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);    }}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信qq币充错了怎么办 魅蓝e玩游戏卡怎么办 魅蓝5玩游戏卡怎么办 微信qb充错号了怎么办 支付宝qb充错号了怎么办 手机上q币充错了怎么办 q币数值充错了怎么办 微信充值商户电话是假了怎么办 微信冲话费冲错了怎么办 淘宝退款不退邮费怎么办 淘金币买的退款怎么办 淘宝退款不退运费怎么办 拼多多不退运费怎么办 开发商不退团购服务费怎么办 支付宝话费充错了怎么办 电视版本低不支持投屏怎么办 绝地求生刺激战场不支持机型怎么办 手机不支持微信运动怎么办 淘宝虚拟商品买家退货退款怎么办 虚拟品申请啦退货退款怎么办 淘宝充值话费没到账怎么办 淘宝全球购买到假货怎么办 车跑路上没油了怎么办 摩托车跑路上没油了怎么办 话费充了不到帐怎么办 网上代充被骗了怎么办 天猫买东西没积分怎么办 购物时不要天猫积分怎么办 618没有天猫积分怎么办 话费充错了号码怎么办? 微信被骗充话费怎么办 微信话费充多了怎么办 睫毛烫的太卷了怎么办 烫完睫毛太卷了怎么办 烫睫毛太卷了怎么办 用微信充话费充错了怎么办 微信给空号充话费了怎么办 微信充话费充错号码是空号怎么办 淘宝充流量不到账怎么办 微信退货不退款怎么办 京东话费交错号怎么办?