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);//用户自定义Typeif(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() });}}@Overridepublic Type[] getComponents() {return data;}@Overridepublic 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*/
@DoNotCacheStructure
public 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-2msh.getMsh3_SendingApplication().getHd1_NamespaceID().setValue("01");msh.getMsh5_ReceivingApplication().getHd1_NamespaceID().setValue("PMI");msh.getDateTimeOfMessage().getTimeOfAnEvent().setValue(nowDate);// MSH-7msh.getMsh10_MessageControlID().setValue(nowDate + new Random().nextInt(100));// MSH-10msh.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);//设置用户自定义Typeqbp.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 blocke.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);}}

java解析HL7协议报文工具(v24版)相关推荐

  1. springboot接收HL7协议报文 HAPI(SpringBoot版本)

    1.maven依赖 <dependency><groupId>ca.uhn.hapi</groupId><artifactId>hapi-base< ...

  2. J8583CN解析ISO8583协议报文注意点

    最近在做POS接入涉及到如何正确解析ISO8583协议的问题,遇到了一些很讨厌的问题今天将他们总结一 下写在博客中,供大家参考. 1.  对于小白首先要了解什么是ISO8583协议,请参考该文章htt ...

  3. java解析JT808协议

    JT808协议扫盲 1 数据类型 2 消息结构 3 消息头 解析 1 消息体实体类 2 字节数组到消息体实体类的转换 21 消息转换器 22 用到的工具类 221 BCD操作工具类 222 位操作工具 ...

  4. java解析soap返回报文_java解析soap响应报文

    本文从 SOAP 报文的编写.在 C#语言中 定义远程响应端的参数设置,以发送报文请求.解析接收的 SOAP 报文从而提 取所需的业务数据等方面,对该系统的设计和实现...... java通过报文交换 ...

  5. Java解析JT808协议示例

    原文地址:https://blog.csdn.net/hylexus/article/details/54987786 JT808协议扫盲 1 数据类型 2 消息结构 3 消息头 解析 1 消息体实体 ...

  6. java解析bt协议详解_BT(带中心Tracker)通信协议的分析

    BT通信协议举例分析 现在的很多BT下载都采用了DHT网络,这样进行BT下载就不需要中心服务器了.本文针对的是需要中心服务器的BT下载. 小弟我最近正在研究BT通信协议,网上的资料很全,但是不是那事详 ...

  7. Java解析HL7消息进阶(解析自定义HL7消息)

    上一篇文章博主笼统的讲了HL7解析,以及解析完成的Message结构,详情移步

  8. 「智慧医疗」1分钟学会解析HL7协议数据

    一.什么是HL7? 标准化的卫生信息传输协议,是医疗领域不同应用之间电子传输的协议.HL7汇集了不同厂商用来设计应用软件之间接口的标准格式,它将允许各个医疗机构在异构系统之间,进行数据交互.HL7 建 ...

  9. Java解析excel的通用方法--基础版

    提出问题: 通过销售地图项目和目前的评分系统的项目都需要用到解析excel,并且每次因为excel中列名的不同和对应的实体类的不同,每一次都需要重新写一个解析excel的方法,代码之长很复杂也很麻烦写 ...

  10. java解析 电力协议_DLT645解析JAVA JAVA解析DLT645电表通信协议 - 下载 - 搜珍网

    压缩包 : d49c1cc60d68dfaef4a4b19567ae9131.zip 列表 ProtocolAnalysls-master/ ProtocolAnalysls-master/.giti ...

最新文章

  1. C# WinForm开发系列 - DataGrid
  2. TypeScript入门-枚举
  3. 初三学生多会筹备计算机中考考试,2020年的初中生注意,中考将会发生这几大变化,最好提前准备...
  4. java知识回顾_Java – 2012年回顾和未来预测
  5. 数据挖掘应用实战-一文教你如何全面分析股市数据特征
  6. 深度搜索剪枝——数的划分
  7. python2.7虚拟环境
  8. springboot 多数据源_SpringBoot整合多数据源的巨坑一
  9. Spring中使用集成MongoDB Client启动时报错:rc: 48
  10. 作为电磁波的 Wi-Fi 信号
  11. VScode+远程服务器docker+C/C++ 代码挑战配置
  12. Mac安装MySQL详细教程
  13. Ubuntu18.04下小米、TPLink、腾达USB无线网卡跳坑记录
  14. 软件工程第二次自考总结(2020年8月)
  15. Centos7下新硬盘的挂载操作
  16. cmd看excel有多少个子表_excel表格拆分成多个表格方法工具
  17. Mendix开发不卡壳之 Scheduler Event定时任务使用
  18. 1.2 储存卡牌信息———自制卡牌游戏之旅
  19. 【洛谷】3960:列队【Splay】
  20. 【厚积薄发系列】Python项目总结2—Python的闭包

热门文章

  1. vue.jsv-html,关于vue.js v-bind 的一些理解和思考,vue.jsv-bind
  2. java物流实时跟踪
  3. 软件工程第2次作业 | 结对项目-最长单词链
  4. C/C++每日一问--判断素数
  5. 使用GO实现尚硅谷家庭记账系统
  6. 记一次在vue项目上使用七牛文件上传的坑
  7. hdu 6069 区间筛
  8. 初识Cura3D打印开源项目
  9. 2022ICPC预选赛 A Yet Another Remainder(数学)(构造)
  10. 办理icp许可证对经营范围还有要求吗