Commit 19226dd6 authored by Georg Fette's avatar Georg Fette
Browse files

- finished the Archetype2Model transformer

- fixed several AQL2Cypher-Query tests
parent 90ac20cf
......@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class Concept {
......@@ -29,7 +28,7 @@ public class Concept {
public List<String> termCodes;
@JsonSerialize
// @JsonIgnore
private List<ConceptField> fields;
public String parent;
......@@ -38,18 +37,38 @@ public class Concept {
private Concept() {
}
public Concept(String name, Model model) {
private Concept(Concept aParent, Model aModel, String name, boolean isArray) {
this.name = name;
this.model = model;
this.fields = new ArrayList<ConceptField>();
this.isArray = isArray;
if (aParent != null) {
this.parentConcept = aParent;
this.parent = aParent.name;
}
this.model = aModel;
model.addConcept(this);
}
public Concept(Concept aConc, boolean isArray) {
this.name = aConc.name;
this.model = aConc.model;
this.parent = aConc.parent;
this.isArray = isArray;
model.addConcept(this);
public Concept(Concept aParent, String name, boolean isArray) {
this(aParent, aParent.model, name, isArray);
}
public Concept(Concept aParent, String name) {
this(aParent, aParent.model, name, false);
}
public Concept(String name, Model aModel) {
this(null, aModel, name, false);
}
public Concept copy(boolean isArray) {
Concept newConcept = new Concept(this.parentConcept, this.model, this.name, isArray);
for (ConceptField aField : fields) {
ConceptField conceptField = new ConceptField(aField, newConcept);
newConcept.fields.add(conceptField);
}
newConcept.isArray = isArray;
return newConcept;
}
public ConceptField addField(String fieldName, List<String> fieldTypes, boolean isArrayFlag) {
......@@ -77,7 +96,6 @@ public class Concept {
throw new RuntimeException("field '" + aName + "' does not exist");
}
// @JsonIgnore
public List<ConceptField> getFields() {
if (isArray()) {
throw new RuntimeException("array fields do not have fields");
......@@ -131,6 +149,7 @@ public class Concept {
}
}
@JsonIgnore
public Concept getNonListConcept() {
return model.getConcept(name, false);
}
......
package de.uniwue.model;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
......@@ -17,6 +18,17 @@ public class ConceptField {
public String description;
public ConceptField() {
}
public ConceptField(ConceptField aField, Concept aParentConcept) {
this.parent = aParentConcept;
this.name = aField.name;
this.possibleTypes = new ArrayList<String>(aField.possibleTypes);
this.isArray = aField.isArray;
this.description = aField.description;
}
@JsonIgnore
public Concept getDataType() {
if (possibleTypes.size() == 1) {
......
......@@ -36,10 +36,10 @@ public class FHIRModelInitializer extends Model {
NUMBER.parentConcept = ANY;
DOUBLE.parentConcept = NUMBER;
INTEGER.parentConcept = NUMBER;
LIST_OF_NUMBER = new Concept(NUMBER, true);
LIST_OF_DOUBLE = new Concept(DOUBLE, true);
LIST_OF_NUMBER = NUMBER.copy(true);
LIST_OF_DOUBLE = DOUBLE.copy(true);
LIST_OF_DOUBLE.parentConcept = LIST_OF_NUMBER;
LIST_OF_INTEGER = new Concept(INTEGER, true);
LIST_OF_INTEGER = INTEGER.copy(true);
LIST_OF_INTEGER.parentConcept = LIST_OF_NUMBER;
PERIOD = getConcept("Period");
QUANTITY = getConcept("Quantity");
......
......@@ -94,15 +94,15 @@ public class Model {
}
protected void initialize() {
for (Concept aConc : concepts) {
for (Concept aConc : getConcepts()) {
aConc.model = this;
conceptMap.put(aConc.name, aConc);
arrayConceptMap.put(aConc.name, new Concept(aConc, true));
arrayConceptMap.put(aConc.name, aConc.copy(true));
}
if (!containsConcept("Element")) {
new Concept("Element", this);
}
for (Concept aConc : concepts) {
for (Concept aConc : getConcepts()) {
aConc.initialize();
}
for (Concept aConc : arrayConceptMap.values()) {
......@@ -138,15 +138,15 @@ public class Model {
public Concept getConcept(String aName, boolean isArrayConceptDesired) {
Concept result;
if (!isArrayConceptDesired) {
result = conceptMap.get(aName);
if (isArrayConceptDesired) {
result = arrayConceptMap.get(aName);
if (result == null) {
throw new RuntimeException("Concept '" + aName + "' does not exist");
throw new RuntimeException("Concept 'List<" + aName + ">' does not exist");
}
} else {
result = arrayConceptMap.get(aName);
result = conceptMap.get(aName);
if (result == null) {
throw new RuntimeException("Concept 'List<" + aName + ">' does not exist");
throw new RuntimeException("Concept '" + aName + "' does not exist");
}
}
return result;
......
......@@ -60,7 +60,6 @@ public class Archetype2ModelConverter {
for (ConceptField aField : concept.getFields()) {
existingFields.add(aField.name);
}
rmTypeName = rmTypeName.replaceAll("<.*>", "");
Concept rmType = model.getConcept(rmTypeName, false);
for (ConceptField anRMField : rmType.getFields()) {
if (!existingFields.contains(anRMField.name)) {
......@@ -99,8 +98,7 @@ public class Archetype2ModelConverter {
Set<String> containedPrimitiveTypes = new HashSet<String>();
Set<String> nonPrimitiveTypes = new HashSet<String>();
for (CObject aChildObj : anAttr.getChildren()) {
String childRmTypeName = aChildObj.getRmTypeName();
childRmTypeName = childRmTypeName.replaceAll("<.*>", "");
String childRmTypeName = getRmTypeName(aChildObj);
if (primitiveTypes.contains(childRmTypeName)) {
containedPrimitiveTypes.add(childRmTypeName);
} else {
......@@ -114,13 +112,33 @@ public class Archetype2ModelConverter {
return containedPrimitiveTypes;
}
private void processObject(Concept concept, CObject anObj) throws ParseException, Exception {
private Set<String> getFieldTypes(CAttribute anAttr) {
Set<String> types = new HashSet<String>();
for (CObject aChildObj : anAttr.getChildren()) {
String childRmTypeName = getRmTypeName(aChildObj);
types.add(childRmTypeName);
}
return types;
}
private String getRmTypeName(CObject anObj) {
String rmTypeName = anObj.getRmTypeName();
rmTypeName = rmTypeName.replaceAll("<.*>", "");
return rmTypeName;
}
private void processObject(CObject anObj) throws ParseException, Exception {
if (anObj instanceof ArchetypeInternalRef) {
ArchetypeInternalRef ref = (ArchetypeInternalRef) anObj;
String targetPath = ref.getTargetPath();
anObj = parse.getPathNodeMap().get(targetPath);
}
if ((anObj instanceof CComplexObject) || (anObj instanceof CCodePhrase)) {
String name = parse.getArchetypeId().getValue() + anObj.path();
name = name.replaceAll("/", ".").replaceAll("\\.$", "");
String rmTypeName = getRmTypeName(anObj);
Concept parent = model.getConcept(rmTypeName);
Concept concept = new Concept(parent, name, false);
if (anObj instanceof CComplexObject) {
CComplexObject complexObj = (CComplexObject) anObj;
List<CAttribute> attributes = complexObj.getAttributes();
......@@ -128,7 +146,7 @@ public class Archetype2ModelConverter {
processAttributeOfComplexObject(concept, anAttr);
}
}
enrichSnapshotWithMissingFields(concept, anObj.getRmTypeName());
enrichSnapshotWithMissingFields(concept, getRmTypeName(anObj));
} else if (anObj instanceof ArchetypeSlot) {
// processArchetypesSlot(concept, (ArchetypeSlot) anObj);
}
......@@ -136,21 +154,47 @@ public class Archetype2ModelConverter {
private void processAttributeOfComplexObject(Concept concept, CAttribute anAttr)
throws ParseException, Exception {
Set<String> primitiveTypeFields = getPrimitiveTypeFields(anAttr);
if (primitiveTypeFields.size() > 0) {
for (CObject aChildObj : anAttr.getChildren()) {
String rmAttributeName = anAttr.getRmAttributeName();
boolean isArrayFlag = isArray(aChildObj);
ConceptField newValueElem = concept.addField(rmAttributeName,
new ArrayList<String>(primitiveTypeFields), isArrayFlag);
for (CObject aChildObj : anAttr.getChildren()) {
String rmAttributeName = anAttr.getRmAttributeName();
boolean isArrayFlag = isArray(aChildObj);
String nodeID = aChildObj.getNodeId();
String name = rmAttributeName;
Set<String> fieldTypes;
if (nodeID != null) {
name += "[" + nodeID + "]";
fieldTypes = new HashSet<String>();
fieldTypes.add(concept.name + "." + name);
} else {
fieldTypes = getFieldTypes(anAttr);
}
} else {
for (CObject aChildObj : anAttr.getChildren()) {
processObject(concept, aChildObj);
String cleanedOntName = getCleanedOntName(aChildObj);
// concept.name = cleanedOntName;
ConceptField newValueElem = concept.addField(name, new ArrayList<String>(fieldTypes),
isArrayFlag);
if (nodeID == null) {
// the field contains only one of multiple possible primitives
break;
} else {
processObject(aChildObj);
}
}
// Set<String> primitiveTypeFields = getPrimitiveTypeFields(anAttr);
// if (primitiveTypeFields.size() > 0) {
// for (CObject aChildObj : anAttr.getChildren()) {
// String rmAttributeName = anAttr.getRmAttributeName();
// boolean isArrayFlag = isArray(aChildObj);
// ConceptField newValueElem = concept.addField(rmAttributeName,
// new ArrayList<String>(primitiveTypeFields), isArrayFlag);
// }
// } else {
// for (CObject aChildObj : anAttr.getChildren()) {
// String rmAttributeName = anAttr.getRmAttributeName();
// boolean isArrayFlag = isArray(aChildObj);
// ConceptField newValueElem = concept.addField(rmAttributeName,
// new ArrayList<String>(primitiveTypeFields), isArrayFlag);
// processObject(aChildObj);
// String cleanedOntName = getCleanedOntName(aChildObj);
// // concept.name = cleanedOntName;
// }
// }
}
/*
......@@ -167,19 +211,14 @@ public class Archetype2ModelConverter {
throw new RuntimeException("original language code has to be given");
}
CComplexObject def = parse.getDefinition();
String rmTypeName = def.getRmTypeName();
String rmTypeName = getRmTypeName(def);
if (!rmTypeName.matches(
"CLUSTER|ELEMENT|EVENT|HISTORY|INTERVAL_EVENT|ITEM_LIST|ITEM_SINGLE|ITEM_STRUCTURE|ITEM_TABLE|ITEM_TREE|ITEM|"
+ "ACTION|ACTIVITY|ADMIN_ENTRY|CARE_ENTRY|COMPOSITION|CONTENT_ITEM|EHR|ENTRY|EVALUATION|EVENT_CONTEXT|INSTRUCTION|ISM_TRANSITION|OBSERVATION|SECTION|"
+ "ACTOR|ADDRESS|AGENT|CAPABILITY|CONTACT|GROUP|ORGANISATION|PARTY_IDENTITY|PARTY_RELATIONSHIP|PARTY|PERSON|ROLE|VERSIONED_PARTY")) {
throw new RuntimeException("derivation of other archetypes not yet implemented");
}
Concept parent = model.getConcept(rmTypeName);
Concept concept = new Concept(parent, false);
String name = parse.getArchetypeId().getValue();
concept.name = name;
processObject(concept, def);
processObject(def);
}
// private void processArchetypesSlot(ConceptField parent, ArchetypeSlot archSlot)
......
......@@ -32,10 +32,10 @@ public class OpenEHRModelInitializer extends Model {
NUMBER.parentConcept = ANY;
DOUBLE.parentConcept = NUMBER;
INTEGER.parentConcept = DOUBLE;
LIST_OF_NUMBER = new Concept(NUMBER, true);
LIST_OF_DOUBLE = new Concept(DOUBLE, true);
LIST_OF_NUMBER = NUMBER.copy(true);
LIST_OF_DOUBLE = DOUBLE.copy(true);
LIST_OF_DOUBLE.parentConcept = LIST_OF_NUMBER;
LIST_OF_INTEGER = new Concept(INTEGER, true);
LIST_OF_INTEGER = INTEGER.copy(true);
LIST_OF_INTEGER.parentConcept = LIST_OF_NUMBER;
STRING = getConcept("string");
......
......@@ -380,6 +380,9 @@ public class QueryOperator extends Expression {
if ((aliasParent.type == OperatorType.FILTER) && (aliasParent.alias != null)) {
result.addAll(aliasParent.getChildConcepts());
}
if ((aliasParent.type == OperatorType.DEMOTE)) {
result.addAll(aliasParent.getChildConcepts());
}
}
return result;
}
......
......@@ -23,7 +23,8 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
public static String system = "Cypher";
private String[] aliasNames = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K" };
private String[] aliasNames = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P" };
private int aliasIndex;
......@@ -37,10 +38,11 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
// TODO: fill
@SuppressWarnings("unchecked")
private Set<OperatorType> infixOps = new HashSet<OperatorType>(
Arrays.asList(new OperatorType[] { OperatorType.MORE, OperatorType.LESS, OperatorType.AND,
OperatorType.EQUALS, OperatorType.AFTER, OperatorType.POWER, OperatorType.ADD,
OperatorType.MULTIPLY, OperatorType.DIVIDE, OperatorType.SUBTRACT }));
private Set<OperatorType> infixOps = new HashSet<OperatorType>(Arrays.asList(new OperatorType[] {
OperatorType.MORE_OR_EQUAL, OperatorType.MORE, OperatorType.LESS_OR_EQUAL, OperatorType.LESS,
OperatorType.AND, OperatorType.EQUALS, OperatorType.AFTER,
OperatorType.POWER, OperatorType.ADD, OperatorType.MULTIPLY, OperatorType.DIVIDE,
OperatorType.SUBTRACT, OperatorType.MATCHES_AQL }));
@SuppressWarnings("unchecked")
private Set<OperatorType> prefixOps = new HashSet<OperatorType>(Arrays.asList(new OperatorType[] {
......@@ -206,6 +208,26 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
return result;
}
private String writeList(QueryOperator anOp) {
List<String> elemStrings = new ArrayList<String>();
for (Expression anExp : anOp.getParameters()) {
String writeExpression = writeExpression(anExp);
elemStrings.add(writeExpression);
}
String result = "[" + StringUtilsUniWue.concat(elemStrings, ", ") + "]";
return result;
}
private String writeOr(QueryOperator anOp) {
List<String> elemStrings = new ArrayList<String>();
for (Expression anExp : anOp.getParameters()) {
String writeExpression = writeExpression(anExp);
elemStrings.add(writeExpression);
}
String result = "(" + StringUtilsUniWue.concat(elemStrings, " OR ") + ")";
return result;
}
private String writeOperator(QueryOperator anOp) {
String result;
if ((anOp.type == OperatorType.FILTER) || (anOp.type == OperatorType.EXISTS)) {
......@@ -230,6 +252,10 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
}
} else if (anOp.type == OperatorType.DEMOTE) {
result = "";
} else if (anOp.type == OperatorType.LIST) {
result = writeList(anOp);
} else if (anOp.type == OperatorType.OR) {
result = writeOr(anOp);
} else if (anOp.type == OperatorType.ITERATE) {
result = writeExpression(anOp.getParameters().get(0));
} else if (anOp.type == OperatorType.FIELD) {
......@@ -486,6 +512,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
addOpType("AND", OperatorType.AND);
addOpType("OR", OperatorType.OR);
addOpType("NOT", OperatorType.NOT);
addOpType("count", OperatorType.COUNT);
addOpType("avg", OperatorType.AVG);
......@@ -506,6 +533,9 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
addOpType("during", OperatorType.DURING);
addOpType("in", OperatorType.MATCHES_AQL);
addOpType("", OperatorType.LIST);
addOpType(">", OperatorType.AFTER);
addOpType("ends", OperatorType.END);
addOpType("=", OperatorType.EQUALS);
......
......@@ -472,6 +472,7 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
if (singleNodePredicateComparableName != null) {
if (singleNodePredicateComparableName.matches("openEHR-EHR-.*")) {
fieldOp = insertOp(OperatorType.FIELD);
fieldOp.addParameter(text);
QueryOperator filter = insertOp(OperatorType.FILTER);
String newAliasName = getNewAliasName();
fieldOp.alias = newAliasName;
......
......@@ -19,15 +19,15 @@ public class Test_AQL_2_Cypher {
public static void main(String[] args) throws IOException, QueryParseException {
Test_AQL_2_Cypher test = new Test_AQL_2_Cypher();
test.debugTest();
// test.testAQL_2_AQL();
// test.debugTest();
test.testAQL_2_Cypher();
}
public void debugTest() throws QueryParseException, IOException {
initialize();
QueryManager queryManager = new QueryManager();
for (MultiQuery aMultiQuery : queryManager.queries) {
if (aMultiQuery.name.equals("query_AQL_2_Cypher_longPaths1")) {
if (aMultiQuery.name.equals("query_AQL_2_Cypher_not2")) {
processQuery(aMultiQuery);
}
}
......@@ -57,6 +57,7 @@ public class Test_AQL_2_Cypher {
}
private void processQuery(MultiQuery aMultiQuery) throws QueryParseException {
System.out.println("Processing query '" + aMultiQuery + "'");
String originalQuery = aMultiQuery.system2QueryString.get(aqlLangManager.getSystem());
QueryOperator query = aqlLangManager.parse(originalQuery);
String graphString = query.toString();
......@@ -73,7 +74,7 @@ public class Test_AQL_2_Cypher {
}
@Test
public void testAQL_2_AQL() throws IOException, QueryParseException {
public void testAQL_2_Cypher() throws IOException, QueryParseException {
initialize();
QueryManager queryManager = getQueryManager("working_AQL_2_Cypher");
for (MultiQuery aMultiQuery : queryManager.queries) {
......
*AQL
SELECT e/ehr_id/value
FROM EHR e
CONTAINS COMPOSITION a[openEHR-EHR-COMPOSITION.encounter.v1]
CONTAINS ADMIN_ENTRY b[openEHR-EHR-ADMIN_ENTRY.admission.v0]
WHERE NOT EXISTS a/content[openEHR-EHR-ADMIN_ENTRY.discharge_summary.v0] OR NOT e/ehr_status/subject/external_ref/namespace = 'CEC'
*Graph
QUERY(
FILTER(
ITERATE('EHR') as e,
EXISTS(
CONTAINS_TYPE(
ALIAS_REF('e'),
'COMPOSITION',
'openEHR-EHR-COMPOSITION.encounter.v1'
) as a,
AND(
EXISTS(CONTAINS_TYPE(
ALIAS_REF('a'),
'ADMIN_ENTRY',
'openEHR-EHR-ADMIN_ENTRY.admission.v0'
) as b),
OR(
NOT(EXISTS(FILTER(
FIELD(
ALIAS_REF('a'),
'content'
) as C,
IS(
ALIAS_REF('C'),
'openEHR-EHR-ADMIN_ENTRY.discharge_summary.v0'
)
))),
NOT(EQUALS(
FIELD(
FIELD(
FIELD(
FIELD(
ALIAS_REF('e'),
'ehr_status'
),
'subject'
),
'external_ref'
),
'namespace'
),
'CEC'
))
)
)
)
),
RETURN(FIELD(
FIELD(
ALIAS_REF('e'),
'ehr_id'
),
'value'
))
)
*comment
the cypher query is not ready yet.
*Cypher
MATCH
(A:EHR)-[*]->(B:COMPOSITION), (B)-[*]->(C:ADMIN_ENTRY)
OPTIONAL MATCH
(B)-[*]->(C:ADMIN_ENTRY)
WHERE
B.archetype_node_id = 'openEHR-EHR-COMPOSITION.encounter.v1' AND
C.archetype_node_id = 'openEHR-EHR-ADMIN_ENTRY.admission.v0' AND
NOT EXISTS()
RETURN
A
......@@ -3,53 +3,41 @@ SELECT e/ehr_id/value
FROM EHR e
CONTAINS COMPOSITION a[openEHR-EHR-COMPOSITION.encounter.v1]
CONTAINS ADMIN_ENTRY b[openEHR-EHR-ADMIN_ENTRY.admission.v0]
WHERE NOT EXISTS a/content[openEHR-EHR-ADMIN_ENTRY.discharge_summary.v0] OR NOT e/ehr_status/subject/external_ref/namespace = 'CEC'
WHERE NOT e/ehr_status/subject/external_ref/namespace = 'CEC'
*Graph
QUERY(
FILTER(
ITERATE('EHR') as e,
EXISTS(
CONTAINS_TYPE(
ALIAS_REF('e'),
'COMPOSITION',
'openEHR-EHR-COMPOSITION.encounter.v1'
) as a,
AND(
AND(
EXISTS(
CONTAINS_TYPE(
ALIAS_REF('e'),
'COMPOSITION',
'openEHR-EHR-COMPOSITION.encounter.v1'
) as a,
EXISTS(CONTAINS_TYPE(
ALIAS_REF('a'),
'ADMIN-ENTRY',
'ADMIN_ENTRY',
'openEHR-EHR-ADMIN_ENTRY.admission.v0'
) as b),
OR(
NOT(EXISTS(FILTER(
FIELD(
ALIAS_REF('a'),
'content'
) as C,
IS(
ALIAS_REF('C'),
'openEHR-EHR-ADMIN_ENTRY.discharge_summary.v0'
)
))),
NOT(EQUALS(