java解析HL7协议报文工具
因为项目需要解析HL7协议报文,网上找到的工具都是解析成带位置信息的xml格式或者json格式,然后需要自己根据需要获取的位置来获取信息。而在生成的HL7协议报文的时候也是需要先生成xml或json格式再进行转换。想着希望找到一个直接解析生成类然后直接用的工具。
后来我找到了这个ca.uhn.hapi,能将HL7报文直接解析成相应的类,通过调用:PipeParser.parse(message, hl7str)来解析报文,将数据填充到message类里面,其中message是工具里面的继承Message类的子类,例如:QBP_Q11、RSP_K23等。而生成HL7报文的时候又可以调用message.encode()来生成,不过需要先设置MSH头,调用:
message.getMSH().getFieldSeparator().setValue("|");
message.getMSH().getEncodingCharacters().setValue("^~\\&");
设置完可以调用msh里面的get方法来设置值,例如:
message.getMSH().getMsh11_ProcessingID().getProcessingID().setValue("P");
message.getMSH().getMsh17_CountryCode().setValue("CHN");
maven导入工具包:
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-base</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v24</artifactId>
<version>2.3</version>
</dependency>
后来因为接入的项目用到的协议和ca.uhn.hapi工具里面已经定义好的类所解析的报文结构不一致,所以需要自己去编写工具来自定义解析和生成相应的HL7报文,比如以下报文的RSP_ZP7在工具包里面没有相应的类结构对应(\r为回车):
MSH|^~\\&|PMI||01||20170719143120||RSP^ZP7|YY00000001|P|2.4|\rMSA|AA|YY00000001|[MsgInfo] Method Type: ZP7 -Success Flag: AA -MSG: success QueryPerson return message success.\rQAK||||0|0|0\rQPD|\rIN1|6|0|8\rQRI|15.014454851245674|3|
下面我写了几个工具类来实现方便调用,HL7Helper类主要是设置数据和获取数据,UserDefineComposite类用于自定义数据类型,UserDefineMessage类用于自定义message类型:
HL7Helper类:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.AbstractComposite;
import ca.uhn.hl7v2.model.AbstractPrimitive;
import ca.uhn.hl7v2.model.AbstractSegment;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Type;
import ca.uhn.hl7v2.model.Varies;
import ca.uhn.hl7v2.parser.PipeParser;
/**
* @author SamJoke
*/
public class HL7Helper {
private static Method method = null;
static {
try {
method = AbstractSegment.class.getDeclaredMethod("add", Class.class, boolean.class, int.class, int.class,
Object[].class, String.class);
method.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
/**
* 自定义添加AbstractSegment类的字段类型,然后可以用getFeild方法进行赋值,例子参考:
* testSegmentAddFeildRequest()
*
* @param obj
* AbstractSegment对象
* @param c
* 数据类型
* @param required
* 是否必填
* @param maxReps
* 数组长度
* @param length
* 字节长度
* @param constructorArgs
* 构造器
* @param name
* 字段名
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public static void segmentAddFeild(AbstractSegment obj, Class<? extends Type> c, boolean required, int maxReps,
int length, Object[] constructorArgs, String name)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
method.invoke(obj, c, required, maxReps, length, constructorArgs, name);
}
public static void segmentAddFeild(AbstractSegment obj, Class<? extends Type> c, int maxReps, int length,
Message msg) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
segmentAddFeild(obj, c, false, maxReps, length, new Object[] { msg }, "user define");
}
public static void segmentAddFeild(AbstractSegment obj, Class<? extends Type> c, int length, Message msg)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
segmentAddFeild(obj, c, false, 1, length, new Object[] { msg }, "user define");
}
// public static void segmentAddFeild(AbstractSegment obj, HL7DataType hl7DateType, Message msg)
// throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// segmentAddFeild(obj, hl7DateType.getCls(), false, hl7DateType.getMaxReps(), hl7DateType.getLength(),
// new Object[] { msg }, "user define");
// }
@SuppressWarnings("unchecked")
public static <T> T getField(AbstractSegment obj, int pos, int index, Class<T> cls) throws HL7Exception {
return (T) obj.getField(pos, index);
}
/**
* 将hl7str协议报文转换为指定的Message类(可自定义),例子参考:testSegmentAddFeildResponse()
*
* @param msg
* Message类型,如ADT_A01
*