package se.cambio.cds.controller.guide; import org.apache.log4j.Logger; import org.openehr.rm.datatypes.basic.DataValue; import org.openehr.rm.datatypes.basic.DvBoolean; import org.openehr.rm.datatypes.quantity.DvOrdinal; import org.openehr.rm.datatypes.quantity.datetime.DvDateTime; import org.openehr.rm.datatypes.text.CodePhrase; import org.openehr.rm.datatypes.text.DvCodedText; import org.openehr.rm.datatypes.text.DvText; import org.openehr.rm.support.terminology.TerminologyService; import se.cambio.cds.gdl.model.ArchetypeBinding; import se.cambio.cds.gdl.model.ElementBinding; import se.cambio.cds.gdl.model.Guide; import se.cambio.cds.gdl.model.Rule; import se.cambio.cds.gdl.model.expression.*; import se.cambio.cds.gdl.parser.DADLSerializer; import se.cambio.cds.gdl.parser.GDLParser; import se.cambio.cds.model.facade.execution.vo.*; import se.cambio.cds.model.instance.ArchetypeReference; import se.cambio.cds.model.instance.ElementInstance; import se.cambio.cds.util.CurrentTimeExpressionDataValue; import se.cambio.cds.util.GeneratedElementInstanceCollection; import se.cambio.openehr.util.exceptions.InternalErrorException; import java.io.InputStream; import java.util.*; public class GuideUtil { public static final DvCodedText NULL_FLAVOUR_CODE_NO_INFO = new DvCodedText( "no information", new CodePhrase(TerminologyService.OPENEHR, "271")); public static void fillElementInstanceCollection( Guide guide, GeneratedElementInstanceCollection elementInstanceCollection){ Map<String, ArchetypeBinding> abs = guide.getDefinition().getArchetypeBindings(); if (abs!=null){ for (ArchetypeBinding archetypeBinding: abs.values()) { ArchetypeReference ar = getGeneratedArchetypeReference(archetypeBinding, guide.getId()); elementInstanceCollection.add(ar); } } } public static GeneratedArchetypeReference getGeneratedArchetypeReference(ArchetypeBinding archetypeBinding, String guideId){ GeneratedArchetypeReference ar = new GeneratedArchetypeReference( archetypeBinding.getDomain(), archetypeBinding.getArchetypeId(), archetypeBinding.getTemplateId()); if (archetypeBinding.getElements()!=null){ for (ElementBinding elementBinding : archetypeBinding.getElements().values()) { String idElement = archetypeBinding.getArchetypeId()+elementBinding.getPath(); GeneratedElementInstance gei = new GeneratedElementInstance( idElement, null, ar, null, NULL_FLAVOUR_CODE_NO_INFO); gei.getRuleReferences().add(new RuleReference(guideId, elementBinding.getId())); } } generatePredicateElements(archetypeBinding, ar, guideId); return ar; } public static void generatePredicateElements(ArchetypeBinding archetypeBinding, ArchetypeReference ar, String guideId){ if (archetypeBinding.getPredicateStatements()!=null){ for (ExpressionItem expressionItem : archetypeBinding.getPredicateStatements()) { if (expressionItem instanceof BinaryExpression){ BinaryExpression be = ((BinaryExpression)expressionItem); ExpressionItem l = be.getLeft(); ExpressionItem r = be.getRight(); if (l instanceof Variable){ String path = ((Variable) l).getPath(); if (r instanceof ConstantExpression){ String idElement = archetypeBinding.getArchetypeId()+ path; ConstantExpression ce = (ConstantExpression)r; DataValue dv = null; if (!"null".equals(ce.getValue())){ dv = getDataValue(ce); } ElementInstance ei = generateElementInstanceForPredicate(ar, be.getOperator(), idElement, dv); if (ei instanceof PredicateGeneratedElementInstance){ String gtCode = getGTCodeForPredicate(archetypeBinding, path, dv); if (gtCode != null) { ((PredicateGeneratedElementInstance) ei).getRuleReferences().add(new RuleReference(guideId, gtCode)); } } }else if (r instanceof ExpressionItem){ String attribute = path.substring(path.lastIndexOf("/value/")+7, path.length()); path = path.substring(0, path.length()-attribute.length()-7); String idElement = archetypeBinding.getArchetypeId()+path; DataValue dv = new CurrentTimeExpressionDataValue(r, attribute); generateElementInstanceForPredicate(ar, be.getOperator(), idElement, dv); //TODO No rule references added (no gt codes) } } }else if (expressionItem instanceof UnaryExpression){ UnaryExpression ue = ((UnaryExpression)expressionItem); OperatorKind op = ue.getOperator(); ExpressionItem o = ue.getOperand(); if (o instanceof Variable){ String idElement = archetypeBinding.getArchetypeId()+((Variable)o).getPath(); DataValue dv = null; generateElementInstanceForPredicate(ar, op, idElement, dv); //TODO No rule references added (no gt codes) } } } } } private static String getGTCodeForPredicate(ArchetypeBinding archetypeBinding, String path, DataValue dv) { DvCodedText dvCodedText = null; if (dv instanceof DvCodedText) { dvCodedText = ((DvCodedText)dv); } else if (dv instanceof DvOrdinal){ dvCodedText = ((DvOrdinal)dv).getSymbol(); } if (dvCodedText != null) { //TODO Will only work if the same code is used in predicate and definition if ("local".equals(dvCodedText.getTerminologyId()) && dvCodedText.getCode().startsWith("gt")){ return dvCodedText.getCode(); } } if (archetypeBinding.getElements() != null) { for (ElementBinding elementBinding : archetypeBinding.getElements().values()) { if (elementBinding.getPath().equals(path)) { return elementBinding.getId(); } } } return null; } private static ElementInstance generateElementInstanceForPredicate(ArchetypeReference ar, OperatorKind op, String idElement, DataValue dv) { return new PredicateGeneratedElementInstanceBuilder() .setId(idElement) .setDataValue(dv) .setArchetypeReference(ar) .setOperatorKind(op) .createPredicateGeneratedElementInstance(); } public static DataValue getDataValue(ConstantExpression e){ if (e instanceof CodedTextConstant){ return ((CodedTextConstant)e).getCodedText(); } else if (e instanceof QuantityConstant){ return ((QuantityConstant)e).getQuantity(); } else if (e instanceof StringConstant){ return new DvText(((StringConstant)e).getString()); } else if (e instanceof OrdinalConstant){ return ((OrdinalConstant)e).getOrdinal(); } else if (e instanceof DateTimeConstant){ return new DvDateTime(e.getValue()); //TODO Use proper BooleanConstant (create) object } else if ("true".equals(e.getValue()) || "false".equals(e.getValue())){ return new DvBoolean(e.getValue()); } else { Logger.getLogger(GuideUtil.class).warn("Unknown data value for constant expression '"+e+"'"); return null; //TODO Proportion, date, time, count, etc } } public static List<RuleReference> getRuleReferences(List<String> firedRules){ List<RuleReference> ruleReferences = new ArrayList<RuleReference>(); if (firedRules!=null){ for (String firedRule : firedRules) { ruleReferences.add(new RuleReference(firedRule)); } } return ruleReferences; } public static String serializeGuide(Guide guide) throws Exception{ StringBuffer sb = new StringBuffer(); DADLSerializer serializer = new DADLSerializer(); for (String line : serializer.toDADL(guide)) { sb.append(line+"\n"); } return sb.toString(); } public static Guide parseGuide(InputStream input) throws Exception{ GDLParser parser = new GDLParser(); return parser.parse(input); } //Get all element paths in the guideline that contains a read statement public static Set<String> getGTCodesInReads(Guide guide) throws InternalErrorException { Set<String> gtCodes = new HashSet<String>(); if (guide.getDefinition()==null || guide.getDefinition().getRules()==null){ return gtCodes; } //Rules for(Rule rule: guide.getDefinition().getRules().values()){ gtCodes.addAll(getGTCodesInReads(rule)); } //Preconditions gtCodes.addAll(getPreconditionGTCodesInReads(guide)); return gtCodes; } public static Set<String> getGTCodesInReads(Rule rule) throws InternalErrorException { Set<String> gtCodes = new HashSet<String>(); if (rule.getWhenStatements()!=null){ for(ExpressionItem expressionItem: rule.getWhenStatements()){ addGTCodesInReads(expressionItem, gtCodes); } } if (rule.getThenStatements()!=null){ for(ExpressionItem expressionItem: rule.getThenStatements()){ addGTCodesInReads(expressionItem, gtCodes); } } return gtCodes; } public static Set<String> getPreconditionGTCodesInReads(Guide guide) throws InternalErrorException { Set<String> gtCodes = new HashSet<String>(); if (guide.getDefinition().getPreConditionExpressions()!=null){ for(ExpressionItem expressionItem: guide.getDefinition().getPreConditionExpressions()){ addGTCodesInReads(expressionItem, gtCodes); } } return gtCodes; } private static void addGTCodesInReads(ExpressionItem expressionItem, Set<String> gtCodes) throws InternalErrorException { if (expressionItem instanceof BinaryExpression){ BinaryExpression binaryExpression = (BinaryExpression) expressionItem; addGTCodesInReads(binaryExpression.getLeft(), gtCodes); addGTCodesInReads(binaryExpression.getRight(), gtCodes); }else if (expressionItem instanceof UnaryExpression){ UnaryExpression unaryExpression = (UnaryExpression)expressionItem; addGTCodesInReads(unaryExpression.getOperand(), gtCodes); }else if (expressionItem instanceof FunctionalExpression){ FunctionalExpression functionalExpression = (FunctionalExpression)expressionItem; for(ExpressionItem expressionItemAux: functionalExpression.getItems()){ addGTCodesInReads(expressionItemAux, gtCodes); } }else if (expressionItem instanceof AssignmentExpression){ AssignmentExpression assignmentExpression = (AssignmentExpression)expressionItem; addGTCodesInReads(assignmentExpression.getAssignment(), gtCodes); }else if (expressionItem instanceof MultipleAssignmentExpression){ MultipleAssignmentExpression multipleAssignmentExpression = (MultipleAssignmentExpression)expressionItem; for(AssignmentExpression assignmentExpression: multipleAssignmentExpression.getAssignmentExpressions()){ addGTCodesInReads(assignmentExpression, gtCodes); } }else if (expressionItem instanceof Variable){ Variable variable = (Variable)expressionItem; gtCodes.add(variable.getCode()); }else if (expressionItem instanceof ConstantExpression){ //Do nothing }else{ throw new InternalErrorException(new Exception("Unkown expression '"+expressionItem.getClass().getName()+"'")); } } //Get all element paths in the guideline that contains a set/create statement public static Set<String> getGTCodesInWrites(Guide guide) throws InternalErrorException { Set<String> gtCodes = new HashSet<String>(); if (guide.getDefinition()==null || guide.getDefinition().getRules()==null){ return gtCodes; } //Rules for(Rule rule: guide.getDefinition().getRules().values()){ gtCodes.addAll(getGTCodesInWrites(rule)); } return gtCodes; } public static Set<String> getGTCodesInWrites(Rule rule) throws InternalErrorException { Set<String> gtCodes = new HashSet<String>(); if (rule.getThenStatements()!=null){ for(ExpressionItem expressionItem: rule.getThenStatements()){ addGTCodesInWrites(expressionItem, gtCodes); } } return gtCodes; } private static void addGTCodesInWrites(ExpressionItem expressionItem, Set<String> gtCodes) throws InternalErrorException { if (expressionItem instanceof CreateInstanceExpression){ MultipleAssignmentExpression multipleAssignmentExpression = ((CreateInstanceExpression)expressionItem).getAssigment(); for(AssignmentExpression assignmentExpression: multipleAssignmentExpression.getAssignmentExpressions()){ addGTCodesInReads(assignmentExpression, gtCodes); } }else if (expressionItem instanceof AssignmentExpression){ gtCodes.add(((AssignmentExpression) expressionItem).getVariable().getCode()); }else{ throw new InternalErrorException(new Exception("Unkown expression '"+expressionItem.getClass().getName()+"'")); } } public static Map<String, String> getGtCodeElementIdMap(Guide guide){ return getGtCodeElementIdMap(guide, null); } public static Map<String, String> getGtCodeElementIdMap(Guide guide, String domainId){ Map<String, String> gtCodeElementIdMap = new HashMap<String, String>(); if (guide.getDefinition()==null || guide.getDefinition().getArchetypeBindings()==null){ return gtCodeElementIdMap; } for(ArchetypeBinding archetypeBinding: guide.getDefinition().getArchetypeBindings().values()){ if (domainId==null || archetypeBinding.getDomain()==null|| domainId.equals(archetypeBinding.getDomain())){ for(ElementBinding elementBinding: archetypeBinding.getElements().values()){ gtCodeElementIdMap.put(elementBinding.getId(), archetypeBinding.getArchetypeId()+elementBinding.getPath()); } } } return gtCodeElementIdMap; } } /* * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 2.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an 'AS IS' basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * * The Initial Developers of the Original Code are Iago Corbal and Rong Chen. * Portions created by the Initial Developer are Copyright (C) 2012-2013 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Software distributed under the License is distributed on an 'AS IS' basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * ***** END LICENSE BLOCK ***** */