All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pronoia.hapi.HapiTestUtil Maven / Gradle / Ivy

There is a newer version: 1.0.2
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.pronoia.hapi;

import java.util.regex.Pattern;

import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.Version;
import ca.uhn.hl7v2.model.GenericMessage;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.parser.CanonicalModelClassFactory;
import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
import ca.uhn.hl7v2.parser.EncodingCharacters;
import ca.uhn.hl7v2.parser.GenericModelClassFactory;
import ca.uhn.hl7v2.parser.ParserConfiguration;
import ca.uhn.hl7v2.util.SegmentFinder;
import ca.uhn.hl7v2.util.Terser;
import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Base class for HAPI Asserts.
 */
public class HapiTestUtil {
    private static final Logger LOG = LoggerFactory.getLogger(HapiTestUtil.class);

    private static EncodingCharacters defaultEncodingCharacters;

    private static DefaultHapiContext defaultHapiContext;
    private static DefaultHapiContext genericHapiContext;
    private static DefaultHapiContext canonicalHapiContext;

    static {
        defaultEncodingCharacters = new EncodingCharacters('|', null);

        defaultHapiContext = new DefaultHapiContext(
            new ParserConfiguration(),
            ValidationContextFactory.noValidation(),
            new DefaultModelClassFactory());

        genericHapiContext = new DefaultHapiContext(
            new ParserConfiguration(),
            ValidationContextFactory.noValidation(),
            new GenericModelClassFactory());
    }

    protected HapiTestUtil() {
    }

    public static EncodingCharacters getDefaultEncodingCharacters() {
        return defaultEncodingCharacters;
    }

    public static void setDefaultEncodingCharacters(EncodingCharacters defaultEncodingCharacters) {
        HapiTestUtil.defaultEncodingCharacters = defaultEncodingCharacters;
    }

    public static void setEncodingCharacters(char fieldDelimiter) {
        HapiTestUtil.defaultEncodingCharacters = new EncodingCharacters(fieldDelimiter, null);
    }

    public static void setEncodingCharacters(char fieldDelimiter, String encodingCharacters) {
        HapiTestUtil.defaultEncodingCharacters = new EncodingCharacters(fieldDelimiter, encodingCharacters);
    }

    public static DefaultHapiContext getDefaultHapiContext() {
        return defaultHapiContext;
    }

    public static void setDefaultHapiContext(DefaultHapiContext defaultHapiContext) {
        HapiTestUtil.defaultHapiContext = defaultHapiContext;
    }

    public static DefaultHapiContext getGenericHapiContext() {
        return genericHapiContext;
    }

    public static void setGenericHapiContext(DefaultHapiContext genericHapiContext) {
        HapiTestUtil.genericHapiContext = genericHapiContext;
    }

    public static DefaultHapiContext getCanonicalHapiContext() {
        return canonicalHapiContext;
    }

    public static void setCanonicalHapiContext(DefaultHapiContext canonicalHapiContext) {
        HapiTestUtil.canonicalHapiContext = canonicalHapiContext;
    }

    public static DefaultHapiContext createHapiContext() {
        return new DefaultHapiContext(
            new ParserConfiguration(),
            ValidationContextFactory.noValidation(),
            new DefaultModelClassFactory());
    }

    public static DefaultHapiContext createCanonicalHapiContext(Class messageClass) {
        return new DefaultHapiContext(
            new ParserConfiguration(),
            ValidationContextFactory.noValidation(),
            messageClass == null ? new CanonicalModelClassFactory() : new CanonicalModelClassFactory(messageClass));
    }

    public static DefaultHapiContext createGenericHapiContext() {
        return new DefaultHapiContext(
            new ParserConfiguration(),
            ValidationContextFactory.noValidation(),
            new GenericModelClassFactory());
    }

    public static Message createMessage(final String er7Data, Class messageClass) {
        if (defaultHapiContext == null) {
            throw new IllegalStateException("Cannot create message using DefaultModelClassFactory - default HapiContext is null");
        }

        try {
            Message message = defaultHapiContext.newMessage(messageClass);

            message.parse(er7Data);

            return message;
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to %s message from %s",
                messageClass, er7Data);
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Message createMessage(final String er7Data, String eventType, String triggerEvent, String version) {
        return createMessage(er7Data, eventType, triggerEvent, Version.versionOf(version));
    }

    public static Message createMessage(final String er7Data, String eventType, String triggerEvent, Version version) {
        if (defaultHapiContext == null) {
            throw new IllegalStateException("Cannot create message using DefaultModelClassFactory - default HapiContext is null");
        }

        try {
            Message message = defaultHapiContext.newMessage(eventType, triggerEvent, version);

            message.parse(er7Data);

            return message;
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to message (event type %s, trigger event %s, version %s) from %s",
                eventType, triggerEvent, version.toString(), er7Data);
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Message createMessage(final String er7Data)  {
        if (defaultHapiContext == null) {
            throw new IllegalStateException("Cannot create message using DefaultModelClassFactory - default HapiContext is null");
        }

        try {
            return defaultHapiContext.getPipeParser().parse(er7Data);
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to message from %s", er7Data);
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static GenericMessage createGenericMessage(final String er7Data) {
        if (genericHapiContext == null) {
            throw new IllegalStateException("Cannot create message using GenericModelClassFactory - Generic HapiContext is null");
        }

        try {
            return (GenericMessage) genericHapiContext.getPipeParser().parse(er7Data);
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to a GenericMessage message from %s", er7Data);
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Message createCanonicalMessage(final String er7Data) {
        if (canonicalHapiContext == null) {
            throw new HapiTestException("Cannot create message using CanonicalModelClassFactory - Canonical HapiContext is null");
        }

        try {
            return canonicalHapiContext.getPipeParser().parse(er7Data);
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to a GenericMessage message from %s", er7Data);
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Terser createTerser(final Message message) {
        return new Terser(message);
    }

    public static Terser createTerser(final String er7Data) {
        return createTerser(createMessage(er7Data));
    }

    public static Terser createGenericTerser(final String er7Data) {
        return createTerser(createGenericMessage(er7Data));
    }

    public static String stripMshTimestamp(String segmentString) {
        final String msh7Pattern = "^(MSH\\|(?:[^|]*\\|){5})[^|]*(.*)$";

        return segmentString.replaceFirst(msh7Pattern, "$1$2");
    }

    public static String[] convertToArrayOfSegmentStrings(final Message message) {
        return convertToArrayOfSegmentStrings(encode(message));
    }

    public static String[] convertToArrayOfSegmentStrings(final String message) {
        return message.split("\r");
    }

    public static Segment getSegment(final String segmentName, final Message message) {
        return getSegment(segmentName, 0, message);
    }

    public static Segment getSegment(final String segmentName, int repetition, final Message message) {
        try {
            return (Segment) message.get(segmentName, repetition);
        } catch (Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to get %s segment repetition %d from %s message",
                segmentName, repetition, message.getClass().getSimpleName());
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Segment findSegment(final String segmentName, final Message message) {
        return findSegment(segmentName, 0, message);
    }

    public static Segment findSegment(final String segmentName, int repetition, final Message message) {
        try {
            return new SegmentFinder(message).findSegment(segmentName, repetition);
        } catch (HL7Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to find %s segment repetition %d in %s message",
                segmentName, repetition, message.getClass().getSimpleName());
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }
    }

    public static Segment findOptionalSegment(final String segmentName, final Message message) {
        return findOptionalSegment(segmentName, 0, message);
    }

    public static Segment findOptionalSegment(final String segmentName, int repetition, final Message message) {
        try {
            return new SegmentFinder(message).findSegment(segmentName, repetition);
        } catch (HL7Exception hl7Ex) {
            LOG.debug("Exception encountered while attempting to find {} segment repetition {} in {} message - returning null",
                segmentName, repetition, message.getClass().getSimpleName());
            return null;
        }
    }

    public static Segment findNonEmptySegment(final String segmentName, final Message message) {
        return findNonEmptySegment(segmentName, 0, message);
    }

    public static Segment findNonEmptySegment(final String segmentName, int repetition, final Message message) {
        SegmentFinder segmentFinder = new SegmentFinder(message);

        Segment segment;
        try {
            do {
                segment = segmentFinder.findSegment(segmentName, repetition);
            } while (segment == null || segment.isEmpty());
        } catch (HL7Exception hl7Ex) {
            final String exceptionMessage = String.format("Exception encountered while attempting to find a non-empty %s segment repetition %d in %s message",
                segmentName, repetition, message.getClass().getSimpleName());
            throw new HapiTestException(exceptionMessage, hl7Ex);
        }

        return segment;
    }

    public static Segment findOptionalNonEmptySegment(final String segmentName, final Message message) {
        return findOptionalNonEmptySegment(segmentName, 0, message);
    }

    public static Segment findOptionalNonEmptySegment(final String segmentName, int repetition, final Message message) {
        SegmentFinder segmentFinder = new SegmentFinder(message);

        Segment segment;
        try {
            do {
                segment = segmentFinder.findSegment(segmentName, repetition);
            } while (segment != null && segment.isEmpty());
        } catch (HL7Exception hl7Ex) {
            LOG.debug("Exception encountered while attempting to find non-empty {} segment repetition {} in {} message - returning null",
                segmentName, repetition, message.getClass().getSimpleName());
            return null;
        }

        return segment;
    }

    public static String extractSegmentName(final String segmentString) {
        return extractSegmentName(segmentString, defaultEncodingCharacters.getFieldSeparator());
    }

    public static String extractSegmentName(final String segmentString, char fieldSeparator) {
        return segmentString.substring(0, segmentString.indexOf(fieldSeparator));
    }

    public static String encode(final Message message) {
        try {
            return message.encode();
        } catch (Exception encodeEx) {
            LOG.warn("Exception encountered encoding message {} using Message.encode() - attempting to encode with generic parser", message.getClass().getName(), encodeEx);
            try {
                return genericHapiContext.getPipeParser().encode(message);
            } catch (HL7Exception genericEncodeEx) {
                throw new HapiTestException("Failed to encode message with generic parser", genericEncodeEx);
            }
        }
    }

    public static String encode(final Segment segment) {
        try {
            return segment.encode();
        } catch (ClassCastException | HL7Exception encodeEx) {
            // TODO:  Remove this workaround once https://github.com/hapifhir/hapi-hl7v2/issues/15 is addressed
            Message message = segment.getMessage();
            String logMessage = String.format("Exception encountered encoding message segment <%s> using the parser <%s> associated with the parent message <%s> - attempting to encode with generic parser",
                segment.getClass(), message.getParser().getClass(), message.getClass());
            if (message instanceof GenericMessage) {
                // TODO:  Try and figure out why this keeps happening
                LOG.debug(logMessage, encodeEx);
            } else {
                LOG.warn(logMessage, encodeEx);
            }

            try {
                return genericHapiContext.getGenericParser().doEncode(segment, defaultEncodingCharacters);
            } catch (HL7Exception genericEncodeEx) {
                String exceptionMessage = String.format("Exception encountered encoding message segment <%s> using the parser <%s> associated with the parent message <%s> - attempting to encode with generic parser",
                    segment.getClass(), genericHapiContext.getGenericParser().getClass(), message.getClass());
                throw new HapiTestException(exceptionMessage, genericEncodeEx);
            }
        }
    }

    public static String encodeSegment(final Message message, String segmentName) {
        return encode(findSegment(segmentName, message));
    }

    public static Pattern compilePatternEscapingPipesAndCarets(String patternString) {
        return compilePatternEscapingPipesAndCarets(patternString, Pattern.DOTALL);
    }

    public static Pattern compilePatternEscapingPipesAndCarets(String patternString, int flags) {
        String escaptedPatternString = patternString.replaceAll("\\|", "\\\\|").replaceAll("\\^", "\\\\^");
        return Pattern.compile(escaptedPatternString, flags);
    }

    public static int indexOfDifference(String expected, String actual) {
        if (expected == actual) {
            return -1;
        }
        if (expected == null || actual == null) {
            return 0;
        }
        int i;
        for (i = 0; i < expected.length() && i < actual.length(); ++i) {
            if (expected.charAt(i) != actual.charAt(i)) {
                break;
            }
        }
        if (i < actual.length() || i < expected.length()) {
            return i;
        }
        return -1;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy