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

com.nedap.archie.adlparser.treewalkers.CComplexObjectParser Maven / Gradle / Ivy

package com.nedap.archie.adlparser.treewalkers;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.nedap.archie.antlr.errors.ANTLRParserErrors;
import com.nedap.archie.adlparser.antlr.AdlParser.*;
import com.nedap.archie.aom.*;
import com.nedap.archie.base.Cardinality;
import com.nedap.archie.base.MultiplicityInterval;
import com.nedap.archie.base.OpenEHRBase;
import com.nedap.archie.rminfo.MetaModels;
import com.nedap.archie.rules.Assertion;
import com.nedap.archie.serializer.odin.AdlOdinToJsonConverter;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Parser for the definition part of an archetype
 *
 * Created by pieter.bos on 15/10/15.
 */
public class CComplexObjectParser extends BaseTreeWalker {

    private final PrimitivesConstraintParser primitivesConstraintParser;
    private final MetaModels metaModels;

    public CComplexObjectParser(ANTLRParserErrors errors, MetaModels metaModels) {
        super(errors);
        primitivesConstraintParser = new PrimitivesConstraintParser(errors);
        this.metaModels = metaModels;
    }

    public RulesSection parseRules(RulesSectionContext context) {
        RulesSection result = new RulesSection();

        result.setContent(context.getText());
        RulesParser rulesParser = new RulesParser(getErrors());
        for(AssertionContext assertion:context.assertion_list().assertion()) {
            result.addRule(rulesParser.parse(assertion));
        }

        return result;
    }

    public CComplexObject parseComplexObject(C_complex_objectContext context) {
        CComplexObject object = new CComplexObject();
        if(context.type_id() != null) {
            object.setRmTypeName(context.type_id().getText());
        }
        if(context.ID_CODE() != null) {
            object.setNodeId(context.ID_CODE().getText());
        } else if (context.ROOT_ID_CODE() != null) {
            object.setNodeId(context.ROOT_ID_CODE().getText());
        }
        //TODO: object.setDeprecated(context.) ?;
        if (context.c_occurrences() != null) {
            object.setOccurrences(parseMultiplicityInterval(context.c_occurrences()));
        }
        for (C_attribute_defContext attribute : context.c_attribute_def()) {
            parseCAttribute(object, attribute);
        }
        return object;
    }

    private void parseCAttribute(CComplexObject parent, C_attribute_defContext attributeDefContext) {

        if (attributeDefContext.c_attribute() != null) {
            CAttribute attribute = new CAttribute();
            C_attributeContext attributeContext = attributeDefContext.c_attribute();
            if(attributeContext.attribute_id() != null) {
                attribute.setRmAttributeName(attributeContext.attribute_id().getText());
            } else {
                attribute.setDifferentialPath(attributeContext.ADL_PATH().getText());

                attribute.setRmAttributeName(getLastAttributeFromPath(attribute.getDifferentialPath()));
            }
            if (attributeContext.c_existence() != null) {
                attribute.setExistence(parseMultiplicityInterval(attributeContext.c_existence()));
            }

            if (attributeContext.c_cardinality() != null) {
                attribute.setCardinality(this.parseCardinalityInterval(attributeContext.c_cardinality()));
            }
            if (attributeContext.c_objects() != null) {
                attribute.setChildren(parseCObjects(attributeContext.c_objects()));
            } else if (attributeContext.CONTAINED_REGEXP() != null) {
                attribute.addChild(primitivesConstraintParser.parseRegex(attributeContext.CONTAINED_REGEXP()));
            }
            parent.addAttribute(attribute);
            if(attribute.getCardinality() != null) {
                //Sort of sensible default. Will be overwritten in ADLParser with the actual value from the RM
                attribute.setMultiple(true);
            }
        } else if (attributeDefContext.c_attribute_tuple() != null) {
            parent.addAttributeTuple(parseAttributeTuple(parent, attributeDefContext.c_attribute_tuple()));
        } else {
            Default_valueContext defaultValueContext = attributeDefContext.default_value();
            if (defaultValueContext != null) {
                if (defaultValueContext.odin_text().included_other_language() != null) {
                    parent.setDefaultValue(parseIncludedLanguageDefaultValue(defaultValueContext.odin_text().included_other_language().getText()));
                } else {
                    parseOdinDefaultValue(parent, defaultValueContext);
                }
            }
        }
    }

    private OpenEHRBase parseIncludedLanguageDefaultValue(String text) {
        String format = text.substring(1, text.indexOf(')'));
        int startIndex = text.indexOf("<#");
        int endIndex = text.lastIndexOf("#>");
        String content = text.substring(startIndex+2, endIndex);

        if(format.equalsIgnoreCase(DefaultValueContainer.JSON)) {
            ObjectMapper defaultValueJsonObjectMapper = getDefaultValueJsonObjectMapper();
            if (defaultValueJsonObjectMapper != null) {
                try {
                    return defaultValueJsonObjectMapper.readValue(
                            content, OpenEHRBase.class
                    );
                } catch (IOException e) {
                    //TODO: find how to add line number/character position information here
                    addError("error parsing json in default value: " + e.getMessage());
                    //and just store it as a DefaultValueContainer
                    return new DefaultValueContainer(content, format);
                    //throw new RuntimeException(e);
                }

            } else {
                return new DefaultValueContainer(format, content);
            }
        } else {
            return new DefaultValueContainer(format, content);
        }
    }

    private void parseOdinDefaultValue(CComplexObject parent, Default_valueContext defaultValueContext) {
        try {
            ObjectMapper defaultValueObjectMapper = getDefaultValueOdinObjectMapper();
            if (defaultValueObjectMapper != null) {
                OpenEHRBase value = defaultValueObjectMapper.readValue(
                        new AdlOdinToJsonConverter().convert(defaultValueContext.odin_text()), OpenEHRBase.class
                );

                parent.setDefaultValue(value);
            } else {
                parent.setDefaultValue(new DefaultValueContainer(DefaultValueContainer.ODIN, defaultValueContext.odin_text().getText()));
            }
        } catch (IOException e) {
            //TODO: find how to add line number/character position information here
            addError("error parsing json in default value: " + e.getMessage());
            //and just store it as a DefaultValueContainer
            parent.setDefaultValue(new DefaultValueContainer(DefaultValueContainer.ODIN, defaultValueContext.odin_text().getText()));
            //throw new RuntimeException(e);
        }
    }

    private ObjectMapper getDefaultValueJsonObjectMapper() {
        if(metaModels == null) {
            return null;
        }
        if(metaModels.getSelectedModel() == null) {
            return null;
        }
        return metaModels.getSelectedModel().getJsonObjectMapper();
    }

    private ObjectMapper getDefaultValueOdinObjectMapper() {
        if(metaModels == null) {
            return null;
        }
        if(metaModels.getSelectedModel() == null) {
            return null;
        }
        return metaModels.getSelectedModel().getOdinInputObjectMapper();

    }

    public static String getFirstAttributeOfPath(String path) {
        return path.substring(0, path.indexOf('/'));
    }

    public static String getPathMinusFirstAttribute(String path) {
        return path.substring(path.indexOf('/'));
    }

    public static String getLastAttributeFromPath(String path) {
       return path.substring(path.lastIndexOf('/')+1);
    }

    private CAttributeTuple parseAttributeTuple(CComplexObject parent, C_attribute_tupleContext attributeTupleContext) {
        List attributeIdList = attributeTupleContext.attribute_id();
        CAttributeTuple tuple = new CAttributeTuple();

        for(Attribute_idContext idContext:attributeIdList) {
            CAttribute attribute = new CAttribute();
            String id = idContext.getText();//TODO? parse odin string value?
            attribute.setRmAttributeName(id);
            tuple.addMember(attribute);
            parent.addAttribute(attribute);
        }
        List tupleContexts = attributeTupleContext.c_object_tuple();
        for(C_object_tupleContext tupleContext:tupleContexts) {
            CPrimitiveTuple primitiveTuple = new CPrimitiveTuple();

            List primitiveObjectContexts = tupleContext.c_object_tuple_items().c_object_tuple_item();
            int i = 0;
            for(C_object_tuple_itemContext tupleObjectContext:primitiveObjectContexts) {
                CPrimitiveObject primitiveObject = null;
                if(tupleObjectContext.c_primitive_object() != null) {
                    primitiveObject = primitivesConstraintParser.parsePrimitiveObject(tupleObjectContext.c_primitive_object());
                } else if (tupleObjectContext.CONTAINED_REGEXP() != null) {
                    primitiveObject = primitivesConstraintParser.parseRegex(tupleObjectContext.CONTAINED_REGEXP());
                }
                tuple.getMembers().get(i).addChild(primitiveObject);
                primitiveTuple.addMember(primitiveObject);
                i++;
            }
            tuple.addTuple(primitiveTuple);
        }

        return tuple;
    }

    private List parseCObjects(C_objectsContext objectsContext) {
        ArrayList result = new ArrayList<>();

        if (objectsContext.c_primitive_object() != null) {
            result.add(primitivesConstraintParser.parsePrimitiveObject(objectsContext.c_primitive_object()));
        } else {
            List nonPrimitiveObjectOrderedContext = objectsContext.c_non_primitive_object_ordered();
            if (nonPrimitiveObjectOrderedContext != null) {

                for (C_non_primitive_object_orderedContext object : nonPrimitiveObjectOrderedContext) {

                    CObject cobject = parseNonPrimitiveObject(object.c_non_primitive_object());
                    Sibling_orderContext siblingOrderContext = object.sibling_order();
                    if(siblingOrderContext != null) {
                        SiblingOrder siblingOrder = new SiblingOrder();
                        if(siblingOrderContext.SYM_AFTER() != null) {
                            siblingOrder.setBefore(false);
                        } else if (siblingOrderContext.SYM_BEFORE() != null) {
                            siblingOrder.setBefore(true);
                        }
                        siblingOrder.setSiblingNodeId(siblingOrderContext.ID_CODE().getText());
                        cobject.setSiblingOrder(siblingOrder);
                    }

                    result.add(cobject);
                }
            }
        }
        return result;
    }

    private CObject parseNonPrimitiveObject(C_non_primitive_objectContext objectContext) {
        /*
          c_complex_object
        | c_archetype_root
        | c_complex_object_proxy
        | archetype_slot
        */
        if (objectContext.c_complex_object() != null) {
            return parseComplexObject(objectContext.c_complex_object());
        } else if (objectContext.c_archetype_root() != null) {
            return parseArchetypeRoot(objectContext.c_archetype_root());

        } else if (objectContext.c_complex_object_proxy() != null) {
            return parseCComplexObjectProxy(objectContext.c_complex_object_proxy());
        } else if (objectContext.archetype_slot() != null) {
            return parseArchetypeSlot(objectContext.archetype_slot());

        }
        return null;
    }

    private CComplexObjectProxy parseCComplexObjectProxy(C_complex_object_proxyContext proxyContext) {

        CComplexObjectProxy proxy = new CComplexObjectProxy();
        proxy.setOccurrences(this.parseMultiplicityInterval(proxyContext.c_occurrences()));
        proxy.setTargetPath(proxyContext.adl_path().getText());
        proxy.setRmTypeName(proxyContext.type_id().getText());
        proxy.setNodeId(proxyContext.ID_CODE().getText());
        return proxy;
    }

    private CArchetypeRoot parseArchetypeRoot(C_archetype_rootContext archetypeRootContext) {
        CArchetypeRoot root = new CArchetypeRoot();

        root.setRmTypeName(archetypeRootContext.type_id().getText());
        root.setNodeId(archetypeRootContext.ID_CODE().getText());
        if(archetypeRootContext.archetype_ref() != null) {
            root.setArchetypeRef(archetypeRootContext.archetype_ref().getText());
        }

        root.setOccurrences(this.parseMultiplicityInterval(archetypeRootContext.c_occurrences()));
        for (C_attribute_defContext attributeContext : archetypeRootContext.c_attribute_def()) {
            parseCAttribute(root, attributeContext);
        }
//((Archetype_slotContext) slotContext).start.getInputStream().getText(slotContext.getSourceInterval())
        return root;
    }

    private ArchetypeSlot parseArchetypeSlot(Archetype_slotContext slotContext) {
        ArchetypeSlot slot = new ArchetypeSlot();

        slot.setNodeId(slotContext.ID_CODE().getText());
        slot.setRmTypeName(slotContext.type_id().getText());
        if(slotContext.SYM_CLOSED() != null) {
            slot.setClosed(true);
        }
        if (slotContext.c_occurrences() != null) {
            slot.setOccurrences(parseMultiplicityInterval(slotContext.c_occurrences()));
        }
        RulesParser assertionParser = new RulesParser(getErrors());
        if (slotContext.c_excludes() != null) {
            for (AssertionContext assertionContext : slotContext.c_excludes().assertion()) {
                slot.getExcludes().add((Assertion) assertionParser.parse(assertionContext));
            }
        }
        if (slotContext.c_includes() != null) {
            for (AssertionContext assertionContext : slotContext.c_includes().assertion()) {
                slot.getIncludes().add((Assertion) assertionParser.parse(assertionContext));
            }
        }
        return slot;
    }


    private Cardinality parseCardinalityInterval(C_cardinalityContext context) {
        Cardinality cardinality = new Cardinality();
        MultiplicityInterval interval = parseMultiplicity(context.cardinality().multiplicity());
        cardinality.setInterval(interval);

        List modContexts = context.cardinality().multiplicity_mod();
        for(Multiplicity_modContext modContext:modContexts) {
            if(modContext.ordering_mod() != null) {
                cardinality.setOrdered(modContext.ordering_mod().SYM_ORDERED() != null);
            } else {
                cardinality.setOrdered(true);//TODO: this should retrieve it from the RM. This now matches the serializer, but both should be fixed!
            }
            if(modContext.unique_mod() != null) {
                cardinality.setUnique(true);
            }

        }
        return cardinality;
    }

    private MultiplicityInterval parseMultiplicityInterval(C_existenceContext existenceContext) {
        MultiplicityInterval interval = new MultiplicityInterval();
        List integers = existenceContext.existence().INTEGER();
        if(integers.size() == 1) {
            interval.setLower(Integer.parseInt(integers.get(0).getText()));
            interval.setUpper(interval.getLower());
        } else if (integers.size() == 2) {
            interval.setLower(Integer.parseInt(integers.get(0).getText()));
            interval.setUpper(Integer.parseInt(integers.get(1).getText()));
        }
        return interval;
    }

    private MultiplicityInterval parseMultiplicityInterval(C_occurrencesContext occurrencesContext) {
        if(occurrencesContext == null) {
            return null;
        }

        return parseMultiplicity(occurrencesContext.multiplicity());
    }

    private MultiplicityInterval parseMultiplicity(MultiplicityContext multiplicity) {
        if(multiplicity == null) {
            return null;
        }
        MultiplicityInterval interval = new MultiplicityInterval();
        List integers = multiplicity.INTEGER();
        if(multiplicity.SYM_INTERVAL_SEP() != null) {
            if(multiplicity.getText().contains("*")) {
                interval.setLower(Integer.parseInt(integers.get(0).getText()));
                interval.setUpperUnbounded(true);
            } else {
                interval.setLower(Integer.parseInt(integers.get(0).getText()));
                interval.setUpper(Integer.parseInt(integers.get(1).getText()));
            }
        } else {
            //one integer or *
            if(multiplicity.getText().contains("*")) {
                interval.setLowerUnbounded(false);
                interval.setLower(0);
                interval.setUpperUnbounded(true);
            } else {
                interval.setLower(Integer.parseInt(integers.get(0).getText()));
                interval.setUpper(interval.getLower());
            }
        }
        interval.fixUnboundedIncluded();
        return interval;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy