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

io.github.linuxforhealth.hl7.message.util.SegmentExtractorUtil Maven / Gradle / Ivy

/*
 * (C) Copyright IBM Corp. 2020, 2021
 *
 * SPDX-License-Identifier: Apache-2.0
 */
package io.github.linuxforhealth.hl7.message.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import ca.uhn.hl7v2.model.Structure;
import io.github.linuxforhealth.hl7.message.HL7Segment;
import io.github.linuxforhealth.hl7.parsing.HL7DataExtractor;
import io.github.linuxforhealth.hl7.parsing.result.ParsingResult;

public class SegmentExtractorUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(SegmentExtractorUtil.class);

    private SegmentExtractorUtil() {
    }

    /**
     * Returns list of segments and additional segments without group constraint.
     *
     * @param segment Segment to be extracted
     * @param additionalSegments Additional segments to be tracked
     * @param dataExtractor HL7 Data extractor to use
     * @return List of {@link SegmentGroup}
     */
    public static List extractSegmentNonGroups(String segment,
            List additionalSegments, HL7DataExtractor dataExtractor) {
        

        List returnValues = new ArrayList<>();

        List segments = getStructures(segment, dataExtractor);

        if (segments != null && !segments.isEmpty()) {
            Map> additionalSegmentValues = extractAdditionalSegmentValueNonGroup(
                    additionalSegments, dataExtractor);
            returnValues.add(new SegmentGroup(segments, additionalSegmentValues));
        }

        return returnValues;
    }

    /**
     * Returns list of segments from all the repetitions of the group with a group name included in
     * groupId
     * 
     * @param primaryGroup Group the segment is to be extracted from
     * @param primarySegment Segment to be extracted
     * @param additionalSegments Additional segments to be tracked
     * @param dataExtractor HL7 Data extractor to use
     * @param parentGroup Parent group
     * 
     * @return List of {@link SegmentGroup}
     */
    public static List extractSegmentGroups(List primaryGroup,
            String primarySegment, List additionalSegments, HL7DataExtractor dataExtractor,
            List parentGroup) {
        Preconditions.checkArgument(primaryGroup != null,
                "Groups list for segment to be extracted cannot be null");
        Preconditions.checkArgument(StringUtils.isNotBlank(primarySegment),
                "primarySegment  cannot be null or blank.");
        

        if (parentGroup == null || parentGroup.isEmpty()) {
            List parentSegments = getChildStructures(primaryGroup, dataExtractor);
            return generateSegmentGroup(primarySegment, primaryGroup, additionalSegments, dataExtractor,
                    parentSegments, primaryGroup);
        } else { // if parentGroup is not null then fetch parent group.

            List parentSegments = getChildStructures(parentGroup, dataExtractor);

            return generateSegmentGroup(primarySegment, primaryGroup, additionalSegments, dataExtractor,
                    parentSegments, parentGroup);
        }
    }

    private static List generateSegmentGroup(String primarySegment,
            List primaryGroup, List additionalSegments,
            HL7DataExtractor dataExtractor, List parentSegments,
            List parentGroupUsedForParentSegment) {
        List returnValues = new ArrayList<>();
        List relativePrimaryGroups = null;

        relativePrimaryGroups = new ArrayList<>(primaryGroup);
        relativePrimaryGroups.removeAll(parentGroupUsedForParentSegment);

        for (Structure parent : parentSegments) {

            List primarySegments = getChildStructures(parent, relativePrimaryGroups, primarySegment,
                    dataExtractor);

            for (Structure primary : primarySegments) {
                // Extract additional structures
                Map> additionalSegmentValues = extractAdditionalSegmentValue(primary,
                        primaryGroup, additionalSegments, dataExtractor);

                String groupId = generateGroupId(parent, parentGroupUsedForParentSegment);
                if (primarySegments != null && !primarySegments.isEmpty()) {
                    returnValues
                            .add(new SegmentGroup(Lists.newArrayList(primary), additionalSegmentValues, groupId));
                }
            }

        }

        return returnValues;
    }

    private static List getChildStructures(Structure s, List groups,
            String segment, HL7DataExtractor dataExtractor) {

        if (StringUtils.isBlank(segment)) {
            return new ArrayList<>();
        } else if (groups == null || groups.isEmpty()) {
            return getStructures(s, segment, dataExtractor);
        } else {
            List parents = getChildStructures(s, groups, dataExtractor);
            List returnValues = new ArrayList<>();
            for (Structure parent : parents) {
                returnValues.addAll(getStructures(parent, segment, dataExtractor));
            }
            return returnValues;
        }

    }

    private static List getChildStructures(List parentGroup,
            HL7DataExtractor dataExtractor) {

        if (parentGroup.isEmpty()) {
            return new ArrayList<>();
        } else if (parentGroup.size() == 1) {
            return getStructures(parentGroup.get(0), dataExtractor);
        } else {
            String parent = parentGroup.get(0);
            List subParents = parentGroup.subList(1, parentGroup.size());
            List segments = getStructures(parent, dataExtractor);
            List results = new ArrayList<>();
            for (Structure s : segments) {
                results.addAll(getChildStructures(s, subParents, dataExtractor));
            }

            return results;
        }

    }

    private static List getChildStructures(Structure parentStruct,
            List parentGroup, HL7DataExtractor dataExtractor) {

        if (parentGroup.isEmpty()) {
            return Lists.newArrayList(parentStruct);
        } else if (parentStruct == null) {
            return new ArrayList<>();
        } else if (parentGroup.size() == 1) {
            return getStructures(parentStruct, parentGroup.get(0), dataExtractor);
        } else {
            String parent = parentGroup.get(0);
            List subParents = parentGroup.subList(1, parentGroup.size());
            List segments = getStructures(parentStruct, parent, dataExtractor);
            List result = new ArrayList<>();
            for (Structure s : segments) {
                result.addAll(getChildStructures(s, subParents, dataExtractor));
            }
            return result;
        }

    }

    private static Map> extractAdditionalSegmentValue(Structure primaryStruct,
            List primaryGroups, List additionalSegments,
            HL7DataExtractor dataExtractor) {
        Map> additionalSegmentValues = new HashMap<>();
        for (HL7Segment seg : additionalSegments) {

            List values = extractEachAdditionalSegment(primaryStruct, primaryGroups, seg, dataExtractor);
            if (values != null && !values.isEmpty()) {
                additionalSegmentValues.put(seg.getSegment(), values);
            }
        }
        return additionalSegmentValues;
    }

    private static List extractEachAdditionalSegment(Structure primaryStruct,
            List primaryGroups, HL7Segment seg, HL7DataExtractor dataExtractor) {

        List values = null;
        List groups = seg.getGroup();

        if (groups.isEmpty()) {
            values = getStructures(seg.getSegment(), dataExtractor);
        } else if (primaryGroups.isEmpty()) {
            // extract without parent
            List parentSegments = getChildStructures(seg.getGroup(), dataExtractor);
            values = new ArrayList<>();
            for (Structure par : parentSegments) {
                values.addAll(getStructures(par, seg.getSegment(), dataExtractor));
            }
        } else if (CollectionUtils.containsAll(primaryGroups, groups)) {
            String commonParentGroup = getCommonParent(groups, primaryGroups);
            Structure commonParent = getParentGroup(primaryStruct, commonParentGroup);

            values = getStructures(commonParent, seg.getSegment(), dataExtractor);
        } else if (getCommonParent(groups, primaryGroups) != null) {

            String commonParentGroup = getCommonParent(groups, primaryGroups);

            Structure commonParent = getParentGroup(primaryStruct, commonParentGroup);
            List relativeGroupsToCommonParent = new ArrayList<>(groups);
            relativeGroupsToCommonParent.removeAll(primaryGroups);

            values = getChildStructures(commonParent, relativeGroupsToCommonParent, seg.getSegment(),
                    dataExtractor);

        } else {
            //extracts data from segment that is in a group outside of the primary group for that specific resource
            List parentSegments = getChildStructures(seg.getGroup(), dataExtractor);
            values = new ArrayList<>();
            for (Structure par : parentSegments) {
                values.addAll(getStructures(par, seg.getSegment(), dataExtractor));
            }
        }
        return values;

    }

    private static String getCommonParent(List groups, List primaryGroups) {
        List common = groups.stream().filter(primaryGroups::contains).collect(Collectors.toList());
        if (!common.isEmpty()) {
            return common.get(common.size() - 1);
        }
        return null;
    }

    private static Map> extractAdditionalSegmentValueNonGroup(
            List additionalSegments, HL7DataExtractor dataExtractor) {
        Map> additionalSegmentValues = new HashMap<>();
        for (HL7Segment seg : additionalSegments) {
            List values = null;
            if (seg.isFromGroup()) {
                throw new IllegalStateException(
                        "Primary segment is not from a group, so additional segements cannot be from relative group.   ");

            } else if (!seg.getGroup().isEmpty()) {
                //extracts data from segment that is in a group outside of the primary group for that specific resource
                List parentSegments = getChildStructures(seg.getGroup(), dataExtractor);
                values = new ArrayList<>();
                for (Structure par : parentSegments) {
                    values.addAll(getStructures(par, seg.getSegment(), dataExtractor));
                }
            } else {
                ParsingResult result = dataExtractor.getAllStructures(seg.getSegment());
                values = result.getValues();
            }
            if (values != null) {
                additionalSegmentValues.put(seg.getSegment(), values);
            }
        }
        return additionalSegmentValues;
    }

    // HL7 segments extraction
    private static List getStructures(String seg, HL7DataExtractor dataExtractor) {
        ParsingResult segments = dataExtractor.getAllStructures(seg);
        if (segments == null || segments.isEmpty()) {
            return new ArrayList<>();
        } else {
            return segments.getValues();
        }

    }

    private static List getStructures(Structure parent, String segment,
            HL7DataExtractor dataExtractor) {
        ParsingResult segments = dataExtractor.getAllStructures(parent, segment);
        if (segments == null || segments.isEmpty()) {
            return new ArrayList<>();
        } else {
            return segments.getValues();
        }

    }

    private static String generateGroupId(Structure struct, List groups) {

        Structure parent = getParentGroup(struct, groups);

        if (parent != null) {
            return parent.getName() + "_" + parent.hashCode();

        } else {
            return null;
        }
    }

    private static Structure getParentGroup(Structure struct, List groups) {
        if (groups == null || groups.isEmpty()) {
            return null;
        }

        List reversedGroups = new ArrayList<>(groups);
        Collections.reverse(reversedGroups);

        Structure parent = struct;
        boolean foundParentGroup = false;
        int numGroups = reversedGroups.size();
        int i = 0;

        while (!foundParentGroup && i < numGroups) {
            parent = getParentGroup(parent, reversedGroups.get(i));
            if (parent != null) {
                foundParentGroup = true;
            }
            i = i + 1;
        }

        if (parent != null) {
            return parent;

        } else {
            return null;
        }
    }

    private static Structure getParentGroup(Structure struct, String group) {
        boolean parentMatchFound = false;
        Structure parent = struct;
        boolean noMoreParent = false;
        while (!parentMatchFound && !noMoreParent) {

            if (parent != null && StringUtils.endsWith(parent.getName(), group)) {
                parentMatchFound = true;
            } else if (parent == null
                    || parent.getName().equalsIgnoreCase(parent.getMessage().getName())) {
                noMoreParent = true;
            } else {
                parent = parent.getParent();
            }

        }

        if (parentMatchFound) {
            return parent;
        } else {
            return null;
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy