com.nedap.archie.adl14.treewalkers.Adl14CComplexObjectParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aom Show documentation
Show all versions of aom Show documentation
An OpenEHR archetype object model implementation, plus parser
package com.nedap.archie.adl14.treewalkers;
import com.google.common.collect.Lists;
import com.nedap.archie.adl14.aom14.CDVOrdinal;
import com.nedap.archie.adl14.aom14.CDVOrdinalItem;
import com.nedap.archie.adl14.aom14.CDVQuantity;
import com.nedap.archie.adl14.aom14.CDVQuantityItem;
import com.nedap.archie.adlparser.antlr.Adl14Parser;
import com.nedap.archie.adlparser.antlr.Adl14Parser.*;
import com.nedap.archie.adlparser.treewalkers.BaseTreeWalker;
import com.nedap.archie.antlr.errors.ANTLRParserErrors;
import com.nedap.archie.aom.*;
import com.nedap.archie.aom.primitives.CInteger;
import com.nedap.archie.aom.primitives.CReal;
import com.nedap.archie.aom.primitives.CString;
import com.nedap.archie.aom.primitives.CTerminologyCode;
import com.nedap.archie.base.Cardinality;
import com.nedap.archie.base.Interval;
import com.nedap.archie.base.MultiplicityInterval;
import com.nedap.archie.base.terminology.TerminologyCode;
import com.nedap.archie.rules.Assertion;
import org.antlr.v4.runtime.tree.TerminalNode;
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 Adl14CComplexObjectParser extends BaseTreeWalker {
private final Adl14PrimitivesConstraintParser primitivesConstraintParser;
private Odin14ValueParser odinParser;
public Adl14CComplexObjectParser(ANTLRParserErrors errors, Odin14ValueParser odinParser) {
super(errors);
primitivesConstraintParser = new Adl14PrimitivesConstraintParser(errors);
this.odinParser = odinParser;
}
public RulesSection parseRules(Rules_sectionContext context) {
RulesSection result = new RulesSection();
result.setContent(context.getText());
Adl14RulesParser rulesParser = new Adl14RulesParser(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.atTypeId() != null) {
object.setNodeId(context.atTypeId().AT_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) {
attribute.setMultiple(true); //this seems to be the only way to set single or multiple without the RM. Maybe existence as well?
}
}
}
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 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.AT_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());
} else if(objectContext.domainSpecificExtension() != null) {
CComplexObject result = new CComplexObject();
String type = objectContext.domainSpecificExtension().type_id().getText();
if(type.equalsIgnoreCase("C_DV_QUANTITY")) {
parseCDVQuantity(objectContext, result);
} else if (type.equalsIgnoreCase("C_DV_ORDINAL")) {
parseCDVOrdinal(objectContext, result);
} else {
throw new IllegalArgumentException("unknown domain specific type: " + type);
}
return result;
} else if (objectContext.c_ordinal() != null) {
C_ordinalContext ordinalContext = objectContext.c_ordinal();
//TODO: ordinal assumed value is not really possible in ADL 2 thanks to tuples
CComplexObject ordinal = new CComplexObject(); //create complex object. We'll generate a node id later!
if(ordinalContainsRealNumber(ordinalContext)) {
ordinal.setRmTypeName("DV_SCALE");
} else {
ordinal.setRmTypeName("DV_ORDINAL");
}
//plus a tuple
CAttributeTuple tuple = new CAttributeTuple();
List members = new ArrayList<>();
members.add(new CAttribute("value"));
members.add(new CAttribute("symbol"));
tuple.setMembers(members);
for (Ordinal_termContext ordinal_termContext : ordinalContext.ordinal_term()) {
CPrimitiveObject, ?> cValue;
if(ordinal_termContext.integer_value() != null) {
long value = Integer.parseInt(ordinal_termContext.integer_value().getText());
CInteger cInteger = new CInteger();
cInteger.addConstraint(new Interval<>(value));
cValue = cInteger;
} else {
double value = Double.parseDouble(ordinal_termContext.real_value().getText());
CReal cReal = new CReal();
cReal.addConstraint(new Interval<>(value));
cValue = cReal;
}
CPrimitiveTuple primitiveTuple = new CPrimitiveTuple();
CTerminologyCode cCode = new CTerminologyCode();
TerminologyCode code = TerminologyCode.createFromString(ordinal_termContext.c_terminology_code().getText());
cCode.addConstraint(code.getCodeString());
primitiveTuple.addMember(cValue);
primitiveTuple.addMember(cCode);
tuple.addTuple(primitiveTuple);
}
ordinal.addAttributeTuple(tuple);
return ordinal;
}
throw new IllegalArgumentException("unknown non-primitive object: " + objectContext.getText());
}
private boolean ordinalContainsRealNumber(C_ordinalContext ordinalContext) {
for (Ordinal_termContext ordinal_termContext : ordinalContext.ordinal_term()) {
if(ordinal_termContext.real_value() != null) {
return true;
}
}
return false;
}
private void parseCDVOrdinal(C_non_primitive_objectContext objectContext, CComplexObject result) {
result.setRmTypeName("DV_ORDINAL");
if(objectContext.domainSpecificExtension().odin_text() != null) {
CDVOrdinal cdvOrdinal = odinParser.convert(objectContext.domainSpecificExtension().odin_text().getText(), CDVOrdinal.class);
if (cdvOrdinal.getList() != null && !cdvOrdinal.getList().isEmpty()) {
CAttributeTuple tuple = new CAttributeTuple();
boolean hasValue = cdvOrdinal.getList().values().stream().anyMatch(i -> i.getValue() != null);
boolean hasSymbol = cdvOrdinal.getList().values().stream().anyMatch(i -> i.getSymbol() != null);
if (hasValue) {
tuple.addMember(new CAttribute("value"));
}
if (hasSymbol) {
tuple.addMember(new CAttribute("symbol"));
}
for (CDVOrdinalItem item : cdvOrdinal.getList().values()) {
CPrimitiveTuple primitiveTuple = new CPrimitiveTuple();
if(item.getValue() != null) {
primitiveTuple.addMember(item.getValueAdl2());
} else if (hasValue) {
CInteger integer = new CInteger();
integer.addConstraint(Interval.upperUnbounded(0L, true));
primitiveTuple.addMember(integer);
}
if (item.getSymbol() != null) {
primitiveTuple.addMember(item.getSymbolAdl2());
} else if (hasSymbol) {
CTerminologyCode code = new CTerminologyCode();
primitiveTuple.addMember(code);//nothing we can do here!
}
tuple.addTuple(primitiveTuple);
}
result.addAttributeTuple(tuple);
}
}
}
private void parseCDVQuantity(C_non_primitive_objectContext objectContext, CComplexObject result) {
result.setRmTypeName("DV_QUANTITY");
if(objectContext.domainSpecificExtension().odin_text() != null) {
CDVQuantity cdvQuantity = odinParser.convert(objectContext.domainSpecificExtension().odin_text().getText(), CDVQuantity.class);
if(cdvQuantity.getProperty() != null) {
CAttribute property = new CAttribute("property");
CTerminologyCode code = new CTerminologyCode();
//will be converted later
code.addConstraint(cdvQuantity.getProperty().toString());
property.addChild(code);
result.addAttribute(property);
}
if (cdvQuantity.getList() != null && !cdvQuantity.getList().isEmpty()) {
if(cdvQuantity.getList().size() == 1) {
CDVQuantityItem item = cdvQuantity.getList().values().iterator().next();
if (item.getMagnitude() != null) {
CAttribute magnitude = new CAttribute("magnitude");
CReal magnitudeAdl2 = item.getMagnitudeAdl2();
magnitude.addChild(magnitudeAdl2);
result.addAttribute(magnitude);
if(cdvQuantity.getAssumedValue() != null && cdvQuantity.getAssumedValue().getMagnitude() != null) {
Double assumedMagnitude = cdvQuantity.getAssumedValue().getMagnitude();
magnitudeAdl2.setAssumedValue(assumedMagnitude);
}
}
if (item.getUnits() != null) {
CAttribute units = new CAttribute("units");
CString unitsAdl2 = item.getUnitsAdl2();
units.addChild(unitsAdl2);
result.addAttribute(units);
if(cdvQuantity.getAssumedValue() != null && cdvQuantity.getAssumedValue().getUnits() != null) {
String assumedUnits = cdvQuantity.getAssumedValue().getUnits();
unitsAdl2.setAssumedValue(assumedUnits);
}
}
if (item.getPrecision() != null) {
CAttribute precision = new CAttribute("precision");
CInteger precisionAdl2 = item.getPrecisionAdl2();
precision.addChild(precisionAdl2);
result.addAttribute(precision);
if(cdvQuantity.getAssumedValue() != null && cdvQuantity.getAssumedValue().getPrecision() != null) {
Long assumedPrecision = cdvQuantity.getAssumedValue().getPrecision();
precisionAdl2.setAssumedValue(assumedPrecision);
}
}
} else {
CAttributeTuple tuple = new CAttributeTuple();
boolean hasMagnitude = cdvQuantity.getList().values().stream().anyMatch(i -> i.getMagnitude() != null);
boolean hasUnits = cdvQuantity.getList().values().stream().anyMatch(i -> i.getUnits() != null);
boolean hasPrecision = cdvQuantity.getList().values().stream().anyMatch(i -> i.getPrecision() != null);
if (hasMagnitude) {
tuple.addMember(new CAttribute("magnitude"));
}
if (hasUnits) {
tuple.addMember(new CAttribute("units"));
}
if (hasPrecision) {
tuple.addMember(new CAttribute("precision"));
}
for (CDVQuantityItem item : cdvQuantity.getList().values()) {
CPrimitiveTuple primitiveTuple = new CPrimitiveTuple();
if (item.getMagnitude() != null) {
primitiveTuple.addMember(item.getMagnitudeAdl2());
} else if (hasMagnitude) {
CReal cReal = new CReal();
cReal.addConstraint(Interval.upperUnbounded(0.0, true));
primitiveTuple.addMember(cReal);
}
if (item.getUnits() != null) {
primitiveTuple.addMember(item.getUnitsAdl2());
} else if (hasUnits) {
primitiveTuple.addMember(new CString("/.*/"));
}
if (item.getPrecision() != null) {
primitiveTuple.addMember(item.getPrecisionAdl2());
} else if (hasPrecision) {
CInteger cInteger = new CInteger();
cInteger.addConstraint(Interval.upperUnbounded(0l, true));
primitiveTuple.addMember(cInteger);
}
tuple.addTuple(primitiveTuple);
}
result.addAttributeTuple(tuple);
}
//TODO: assumed value is possible in ADL 1.4, but not really in ADL 2, unless there is just one option possible. Cannot be solved until
//ADL 2 spec is changed
}
}
}
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());
if(proxyContext.AT_CODE() != null) {
proxy.setNodeId(proxyContext.AT_CODE().getText());
} //else we have to generate a node id :)
return proxy;
}
private CArchetypeRoot parseArchetypeRoot(C_archetype_rootContext archetypeRootContext) {
CArchetypeRoot root = new CArchetypeRoot();
root.setRmTypeName(archetypeRootContext.type_id().getText());
root.setNodeId(archetypeRootContext.AT_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();
C_archetype_slot_headContext headContext = slotContext.c_archetype_slot_head();
if(headContext.c_archetype_slot_id().AT_CODE() != null) {
slot.setNodeId(headContext.c_archetype_slot_id().AT_CODE().getText());
}
slot.setRmTypeName(headContext.c_archetype_slot_id().type_id().getText());
if(headContext.c_archetype_slot_id().SYM_CLOSED() != null) {
slot.setClosed(true);
}
if (headContext.c_occurrences() != null) {
slot.setOccurrences(parseMultiplicityInterval(headContext.c_occurrences()));
}
Adl14RulesParser assertionParser = new Adl14RulesParser(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);//this will be overwritten later from the meta models
}
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());
}
}
return interval;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy