java解析HL7协议报文工具(v24版)
来源:互联网 发布:影子网络真的很恐怖吗 编辑:程序博客网 时间:2024/05/22 06:43
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 * @param hl7str * HL7协议报文 * @throws HL7Exception */ public static void acceptResponse(Message msg, String hl7str) throws HL7Exception { PipeParser p = new PipeParser(); p.parse(msg, hl7str); } public static String getMsgValue(Message msg, String segName, int... ints) throws HL7Exception { return getMsgValue(msg, 0, segName, ints); } public static String getMsgValue(Message msg, Class<? extends AbstractSegment> segCls, int... ints) throws HL7Exception { return getMsgValue(msg, 0, segCls.getSimpleName(), ints); } /** * * 获取Message里面的数据,例子参考testGetMsgValue() * * @param msg * Message类型 * @param struIndex * AbstractSegment数组位,比如PID有重复多个的话需要自己设置位置,默认传0进去 * @param segName * AbstractSegment名,如PID、MSH等 * @param ints * 具体位置,如new int[]{3,2,3} * @return * @throws HL7Exception */ public static String getMsgValue(Message msg, int struIndex, String segName, int... ints) throws HL7Exception { AbstractSegment stru = (AbstractSegment) msg.get(segName, struIndex); int segPos = 0; int composIndex = 0; if (ints.length <= 0) { segPos = 0; composIndex = 0; } else if (ints.length == 1) { segPos = ints[0]; composIndex = 0; } else { segPos = ints[0]; composIndex = ints[1]; } Type itetype = stru.getField(segPos, composIndex); for (int i = 2; i < ints.length; i++) { if (itetype instanceof AbstractPrimitive) { break; } else if (itetype instanceof AbstractComposite) { AbstractComposite coms = (AbstractComposite) itetype; itetype = coms.getComponent(ints[i]); } } return itetype.encode(); } public static void setMsgValue(Message msg, String segName, String value, int... ints) throws HL7Exception { setMsgValue(msg, 0, segName, value, ints); } public static void setMsgValue(Message msg, Class<? extends AbstractSegment> segCls, String value, int... ints) throws HL7Exception { setMsgValue(msg, 0, segCls.getSimpleName(), value, ints); } public static void setMsgValue(Message msg, Object segCls, String value, int... ints) throws HL7Exception { setMsgValue(msg, 0, segCls.getClass().getSimpleName(), value, ints); } /** * * 设置Message里面的数据,例子参考testSetMsgValue() * * @param msg * Message类型 * @param struIndex * AbstractSegment数组位,比如PID有重复多个的话需要自己设置位置,默认传0进去 * @param segName * AbstractSegment名,如PID、MSH等 * @param value * 设置值 * @param ints * 具体位置,如new * int[]{3,2,3},需要注意这里的位置,要根据上面的segName类的init方法里面Type的排序和类型来确定,是否支持这样的定位(层级),若不支持则会抛异常, * @return * @throws HL7Exception */ public static void setMsgValue(Message msg, int struIndex, String segName, String value, int... ints) throws HL7Exception { AbstractSegment stru = (AbstractSegment) msg.get(segName, struIndex); int segPos = 0; int composIndex = 0; if (ints.length <= 0) { segPos = 0; composIndex = 0; } else if (ints.length == 1) { segPos = ints[0]; composIndex = 0; } else { segPos = ints[0]; composIndex = ints[1]; } Type itetype = stru.getField(segPos, composIndex); //用户自定义Type if(itetype instanceof Varies){ itetype = ((Varies) itetype).getData(); } if (ints.length == 2) { ((AbstractPrimitive) itetype).setValue(value); } for (int i = 2; i < ints.length; i++) { if (itetype instanceof AbstractPrimitive) { ((AbstractPrimitive) itetype).setValue(value); } else if (itetype instanceof AbstractComposite) { AbstractComposite coms = (AbstractComposite) itetype; itetype = coms.getComponent(ints[i]); if (i >= ints.length - 1) { if (itetype instanceof AbstractComposite) { coms = (AbstractComposite) itetype; ((AbstractPrimitive) coms.getComponent(0)).setValue(value); } else { ((AbstractPrimitive) itetype).setValue(value); } } } } }}
UserDefineComposite类:
import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import ca.uhn.hl7v2.model.AbstractComposite;import ca.uhn.hl7v2.model.DataTypeException;import ca.uhn.hl7v2.model.Message;import ca.uhn.hl7v2.model.Type;import ca.uhn.hl7v2.model.v24.datatype.ST;/** * 用户自定义Type,根据传不同的长度和Types来构建 * @author SamJoke */public class UserDefineComposite extends AbstractComposite { /** * */ private static final long serialVersionUID = 1L; private static Class<? extends Type> defalutclass = ST.class; Type[] data = null; public UserDefineComposite(Message message) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { super(message); data = new Type[1]; Constructor<? extends Type> cons = defalutclass.getConstructor(new Class[] { Message.class }); data[0] = (Type) cons.newInstance(new Object[] { getMessage() }); } public UserDefineComposite(Message message, Type... types) { super(message); init(types); } @SuppressWarnings("rawtypes") public UserDefineComposite(Message message, Class... clss) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { super(message); init(clss); } @SuppressWarnings("rawtypes") public UserDefineComposite(Message message, int typeCount) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { super(message); Class[] clss = new Class[typeCount]; data = new Type[typeCount]; Constructor<? extends Type> cons = defalutclass.getConstructor(new Class[] { Message.class }); for (int i = 0; i < clss.length; i++) { data[i] = (Type) cons.newInstance(new Object[] { getMessage() }); } } private void init(Type... types) { data = new Type[types.length]; for (int i = 0; i < types.length; i++) { data[i] = types[i]; } } @SuppressWarnings({ "rawtypes", "unchecked" }) private void init(Class... clss) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { data = new Type[clss.length]; for (int i = 0; i < clss.length; i++) { Constructor<? extends Type> cons = clss[i].getConstructor(new Class[] { Message.class }); data[i] = (Type) cons.newInstance(new Object[] { getMessage() }); } } @Override public Type[] getComponents() { return data; } @Override public Type getComponent(int number) throws DataTypeException { try { return this.data[number]; } catch (ArrayIndexOutOfBoundsException e) { throw new DataTypeException("Element " + number + " doesn't exist (Type " + getClass().getName() + " has only " + this.data.length + " components)"); } }}
UserDefineMessage类:
import ca.uhn.hl7v2.HL7Exception;import ca.uhn.hl7v2.model.AbstractMessage;import ca.uhn.hl7v2.model.DoNotCacheStructure;import ca.uhn.hl7v2.model.Structure;import ca.uhn.hl7v2.parser.DefaultModelClassFactory;import ca.uhn.hl7v2.parser.ModelClassFactory;/** * 用户自定义Message,@DoNotCacheStructure注解为了不进行缓存 * @author SamJoke */@DoNotCacheStructurepublic class UserDefineMessage extends AbstractMessage { private static final long serialVersionUID = 1L; private static ASType[] types; private static ModelClassFactory fat = null; static { try { fat = new DefaultModelClassFactory(); } catch (Exception e) { e.printStackTrace(); } } public UserDefineMessage(ModelClassFactory factory) throws HL7Exception { super(factory); init(types); } public UserDefineMessage(ASType... types) throws HL7Exception { super(fat == null ? new DefaultModelClassFactory() : fat); setASTypes(types); init(types); } private void init(ASType... types) throws HL7Exception { for (int i = 0; i < types.length; i++) { this.add(types[i].c, types[i].required, types[i].repeating); } } public String getVersion() { return "2.4"; } public Structure getAS(String asName, Class<? extends Structure> asCls) { return getTyped(asName, asCls); } @SuppressWarnings("unchecked") public <T extends Structure> T getAS(Class<T> asCls) throws HL7Exception { return (T) get(asCls.getSimpleName()); } public static class ASType { Class<? extends Structure> c; boolean required; boolean repeating; public ASType(Class<? extends Structure> c, boolean required, boolean repeating) { this.c = c; this.required = required; this.repeating = repeating; } } private static void setASTypes(ASType... tys) { types = tys; }}
测试类:
import ca.uhn.hl7v2.HL7Exception;import ca.uhn.hl7v2.model.v24.datatype.CE;import ca.uhn.hl7v2.model.v24.message.QBP_Q11;import ca.uhn.hl7v2.model.v24.segment.DSC;import ca.uhn.hl7v2.model.v24.segment.ERR;import ca.uhn.hl7v2.model.v24.segment.IN1;import ca.uhn.hl7v2.model.v24.segment.MSA;import ca.uhn.hl7v2.model.v24.segment.MSH;import ca.uhn.hl7v2.model.v24.segment.PID;import ca.uhn.hl7v2.model.v24.segment.QAK;import ca.uhn.hl7v2.model.v24.segment.QPD;import ca.uhn.hl7v2.model.v24.segment.QRI;import ca.uhn.hl7v2.model.v24.segment.RCP;/** * @author SamJoke */public class TestHL7 { static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); public void setHeader(MSH msh) throws DataTypeException{ String nowDate = sdf.format(new Date()); msh.getFieldSeparator().setValue("|");// 分隔符 msh.getEncodingCharacters().setValue("^~\\&");// MSH-2 msh.getMsh3_SendingApplication().getHd1_NamespaceID().setValue("01"); msh.getMsh5_ReceivingApplication().getHd1_NamespaceID().setValue("PMI"); msh.getDateTimeOfMessage().getTimeOfAnEvent().setValue(nowDate);// MSH-7 msh.getMsh10_MessageControlID().setValue(nowDate + new Random().nextInt(100));// MSH-10 msh.getMsh11_ProcessingID().getProcessingID().setValue("P"); msh.getMsh12_VersionID().getVersionID().setValue("2.4"); msh.getMsh15_AcceptAcknowledgmentType().setValue("AL"); msh.getMsh16_ApplicationAcknowledgmentType().setValue("AL"); msh.getMsh17_CountryCode().setValue("CHN"); msh.getMsh18_CharacterSet(0).setValue("UNICODE"); } public String getHL7Text() { QBP_Q11 qbp_q11 = new QBP_Q11(); MSH msh = qbp_q11.getMSH(); String msg = null; try { //MSH设置 HL7Helper.setMsgValue(qbp_q11, MSH.class,"QBP", 9,0,0); HL7Helper.setMsgValue(qbp_q11, MSH.class,"ZP7", 9,0,1); setHeader(msh); //QBP设置 QPD qbp = qbp_q11.getQPD(); HL7Helper.setMsgValue(qbp_q11, QPD.class, "ZP7", 1,0,0); HL7Helper.setMsgValue(qbp_q11, QPD.class, "Find Candidates", 1,0,1); HL7Helper.setMsgValue(qbp_q11, QPD.class, "HL7v2.4", 1,0,2); //设置用户自定义Type qbp.getQpd3_UserParametersInsuccessivefields().setData(new UserDefineComposite(qbp_q11, 3)); //新增Type类型为CE的字段 HL7Helper.segmentAddFeild(qbp, CE.class, 250, qbp_q11); HL7Helper.setMsgValue(qbp_q11, QPD.class, "0", 3,0,0); HL7Helper.setMsgValue(qbp_q11, QPD.class, "2558856", 3,0,1); HL7Helper.setMsgValue(qbp_q11, QPD.class, "0", 3,0,2); HL7Helper.segmentAddFeild(qbp, CE.class, 100, qbp_q11); HL7Helper.setMsgValue(qbp_q11, QPD.class, "SamJoke", 5,0,0); HL7Helper.segmentAddFeild(qbp, CE.class, 250, qbp_q11); SimpleDateFormat sdf01 = new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat sdf02 = new SimpleDateFormat("yyyy-MM-dd"); HL7Helper.setMsgValue(qbp_q11, QPD.class, sdf01.format(sdf02.parse("1994-8-30")), 6,0,0); HL7Helper.segmentAddFeild(qbp, CE.class, 1, qbp_q11); HL7Helper.setMsgValue(qbp_q11, QPD.class, "M", 7,0,0); //RCP设置 HL7Helper.setMsgValue(qbp_q11, RCP.class, "I", 1,0,0); HL7Helper.setMsgValue(qbp_q11, RCP.class, "20", 2,0,0); HL7Helper.setMsgValue(qbp_q11, RCP.class, "RD", 2,0,1); HL7Helper.setMsgValue(qbp_q11, RCP.class, "R", 3,0,0); msg = qbp_q11.encode(); } catch (Exception e) { e.printStackTrace(); } return msg; } public void hl7Text2Obj(String responseStr) { try { ASType[] asTypes = new ASType[7]; asTypes[0] = new ASType(MSH.class,true,true); asTypes[1] = new ASType(MSA.class,true,true); asTypes[2] = new ASType(QAK.class,true,true); asTypes[3] = new ASType(QPD.class,true,true); asTypes[4] = new ASType(PID.class,true,true); asTypes[5] = new ASType(IN1.class,false,true); asTypes[6] = new ASType(QRI.class,false,true); UserDefineMessage udm = new UserDefineMessage(asTypes); UserDefineMessage udm1 = new UserDefineMessage(asTypes); UserDefineMessage udm2 = new UserDefineMessage(asTypes); QPD qpd = udm2.getAS(QPD.class); HL7Helper.segmentAddFeild(qpd, CE.class, 250, udm2); // 添加一个长度为1的CE数组 HL7Helper.segmentAddFeild(qpd, CE.class, 250, udm2); // 添加一个长度为2的CE数组 HL7Helper.segmentAddFeild(qpd, CE.class, 2, 250, udm2); // 添加一个长度为1的CE数组 HL7Helper.segmentAddFeild(qpd, CE.class, 250, udm2); HL7Helper.acceptResponse(udm2, responseStr); MSH msh = (MSH) udm2.get("MSH"); System.out.println(msh.encode()); System.out.println(msh.getDateTimeOfMessage().getTs1_TimeOfAnEvent().toString()); QPD qpdt = (QPD) udm2.get("QPD"); System.out.println(qpdt.encode()); System.out.println(qpdt.getQpd1_MessageQueryName().getCe1_Identifier().getValue()); System.out.println(HL7Helper.getMsgValue(udm2, "QRI", 1,0,0)); System.out.println(udm2.encode()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { TestHL7 co = new TestHL7(); System.out.println(co.getHL7Text()); String resStr = "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|"; co.hl7Text2Obj(resStr); }}
阅读全文
1 0
- java解析HL7协议报文工具(v24版)
- HL7协议报文的解析脚本
- 解析HL7协议
- HL7 2.X解析(JAVA版)
- HTTP 协议报文解析
- ISO8583报文工具类(组装和解析报文)
- ISO8583报文工具类(组装和解析报文)
- HL7 2.X解析(C#版)
- IS08583报文协议包的解析和封装java源代码
- IS08583报文协议包的解析和封装java源代码
- IS08583报文协议包的解析和封装java源代码
- IS08583报文协议包的解析和封装java源代码
- hl7测试工具
- HL7工具安装步骤
- 报文解析各协议结构体
- 网络基础 TCP协议(报文解析)
- J8583CN解析ISO8583协议报文注意点
- SSL协议握手过程报文解析
- Schedule
- 1321:棋盘问题
- 【搜狐笔试题】产品包装
- Python 3实现k-邻近算法以及 iris 数据集分类应用
- 正则表达式整理
- java解析HL7协议报文工具(v24版)
- Window下python 2.73安装pip
- Directx9学习(八)初识texture(3)
- haoi2013软件安装解题报告
- Over子句开窗函数
- java笔记(七)ServerSocket跟Socket
- 小试牛刀
- Devexpress:在GridControl中使用BindingList
- 解决Hibernate 注解在属性上 ,多对一,一对一懒加载 当调用one那一方getId 也会查数据库的问题