diff --git a/hl7templates/goc-tests/.gitignore b/hl7templates/goc-tests/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..42639b2b7fdcf3a806bc33c2f4fb5e221c3aa2f0 --- /dev/null +++ b/hl7templates/goc-tests/.gitignore @@ -0,0 +1 @@ +lab/ \ No newline at end of file diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/ValidatorGenerator.java b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/ValidatorGenerator.java index 89f64b1c0027aa43dbcedcde35273109811c646e..4be62eace0b0dae7cc1727ab018a71ce3dc1f41c 100644 --- a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/ValidatorGenerator.java +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/ValidatorGenerator.java @@ -2,11 +2,21 @@ package net.ihe.gazelle.goctests.application; import net.ihe.gazelle.goctests.application.exceptions.ValidatorGenerationException; import net.ihe.gazelle.goctests.application.models.GeneratedValidator; +import net.ihe.gazelle.goctests.interlay.GenerationConfiguration; import java.net.URL; public interface ValidatorGenerator { + + /** + * Generate Model Based Validator with {@link GenerationConfiguration} parameter + * @param generationConfiguration object holding all generation configuration + * @return GeneratedValidator, the model definition of the validator + * @throws ValidatorGenerationException + */ + GeneratedValidator generateValidator(GenerationConfiguration generationConfiguration) throws ValidatorGenerationException; + /** * Generate Model Based Validator with String parameters * @param bbr The path to the BBR file (XML) @@ -31,4 +41,6 @@ public interface ValidatorGenerator { */ GeneratedValidator generateValidator(URL bbrURL) throws ValidatorGenerationException; + + } diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/specifications/SpecificationType.java b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/specifications/SpecificationType.java index d4062e70acb90ca18980b62f9357f88d0336ee45..2591f1ab815b0ae4ad12b89caa82fabde40ce33b 100644 --- a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/specifications/SpecificationType.java +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/application/specifications/SpecificationType.java @@ -12,7 +12,7 @@ public enum SpecificationType { DATATYPE("datatype"), FIXEDVAL("fixed value"), CLOSED("closed"), - CHOICE("chocie"); + CHOICE("choice"); private String value; diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/GenerationConfiguration.java b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/GenerationConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..0b63402ea050675ca4367616af5fa86bdad19d3a --- /dev/null +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/GenerationConfiguration.java @@ -0,0 +1,115 @@ +package net.ihe.gazelle.goctests.interlay; + +import java.net.URL; + +public class GenerationConfiguration { + + private URL bbrUrl; + + private String outputFolder; + + private String mvn; + + private Boolean ignoreTemplateIdRequirements = Boolean.FALSE; + + private Boolean ignoreCdaBasicRequirements = Boolean.FALSE; + + private Boolean ignoreChoicesPredicates = Boolean.FALSE; + + private String serviceName; + + private String versionLabel; + + private String hl7Conf; + + + public GenerationConfiguration(URL bbrUrl, String outputFolder, String mvn) { + this.bbrUrl = bbrUrl; + this.outputFolder = outputFolder; + this.mvn = mvn; + } + + public GenerationConfiguration(URL bbrUrl, String outputFolder, String mvn, Boolean ignoreTemplateIdRequirements, + Boolean ignoreCdaBasicRequirements, Boolean ignoreChoicesPredicates, String serviceName, String hl7Conf) { + this.bbrUrl = bbrUrl; + this.outputFolder = outputFolder; + this.mvn = mvn; + this.ignoreTemplateIdRequirements = ignoreTemplateIdRequirements; + this.ignoreCdaBasicRequirements = ignoreCdaBasicRequirements; + this.ignoreChoicesPredicates = ignoreChoicesPredicates; + this.serviceName = serviceName; + this.hl7Conf = hl7Conf; + } + + public URL getBbrUrl() { + return bbrUrl; + } + + public void setBbrUrl(URL bbrUrl) { + this.bbrUrl = bbrUrl; + } + + public String getOutputFolder() { + return outputFolder; + } + + public void setOutputFolder(String outputFolder) { + this.outputFolder = outputFolder; + } + + public String getMvn() { + return mvn; + } + + public void setMvn(String mvn) { + this.mvn = mvn; + } + + public Boolean isIgnoreTemplateIdRequirements() { + return ignoreTemplateIdRequirements; + } + + public void setIgnoreTemplateIdRequirements(Boolean ignoreTemplateIdRequirements) { + this.ignoreTemplateIdRequirements = ignoreTemplateIdRequirements; + } + + public Boolean isIgnoreCdaBasicRequirements() { + return ignoreCdaBasicRequirements; + } + + public void setIgnoreCdaBasicRequirements(Boolean ignoreCdaBasicRequirements) { + this.ignoreCdaBasicRequirements = ignoreCdaBasicRequirements; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Boolean isIgnoreChoicesPredicates() { + return ignoreChoicesPredicates; + } + + public void setIgnoreChoicesPredicates(Boolean ignoreChoicesPredicates) { + this.ignoreChoicesPredicates = ignoreChoicesPredicates; + } + + public String getVersionLabel() { + return versionLabel; + } + + public void setVersionLabel(String versionLabel) { + this.versionLabel = versionLabel; + } + + public String getHl7Conf() { + return hl7Conf; + } + + public void setHl7Conf(String hl7Conf) { + this.hl7Conf = hl7Conf; + } +} diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/ValidatorGeneratorImpl.java b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/ValidatorGeneratorImpl.java index 56571131e95d79e634d72c0a3f82d9b980d4c1b8..d785646258f14cc903fb10e5dc025022711e4019 100644 --- a/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/ValidatorGeneratorImpl.java +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/java/net/ihe/gazelle/goctests/interlay/ValidatorGeneratorImpl.java @@ -20,14 +20,25 @@ public class ValidatorGeneratorImpl implements ValidatorGenerator { @Override - public GeneratedValidator generateValidator(URL bbrUrl, String outputFolder, String mvn) throws ValidatorGenerationException { + public GeneratedValidator generateValidator(GenerationConfiguration generationConfiguration) throws ValidatorGenerationException { System.out.println("Start generation for test"); + String outputFolder = generationConfiguration.getOutputFolder(); + URL bbrUrl = generationConfiguration.getBbrUrl(); + String mvn = generationConfiguration.getMvn(); + + Boolean ignoreTemplateIdRequirements = generationConfiguration.isIgnoreTemplateIdRequirements(); + Boolean ignoreCdaBasicRequirements = generationConfiguration.isIgnoreCdaBasicRequirements(); + Boolean ignoreChoicesPredicates = generationConfiguration.isIgnoreChoicesPredicates(); + String serviceName = generationConfiguration.getServiceName(); + String versionLabel = generationConfiguration.getVersionLabel(); + String hl7Conf = generationConfiguration.getHl7Conf(); //Run GOC GOCExecutor gocExecutor = new GOCExecutor(outputFolder); - ValidatorConfiguration validatorConfiguration = gocExecutor.execute(new StreamBBRResource(bbrUrl),mvn); + ValidatorConfiguration validatorConfiguration = gocExecutor.execute(new StreamBBRResource(bbrUrl),mvn, + versionLabel, ignoreTemplateIdRequirements, ignoreCdaBasicRequirements, serviceName, ignoreChoicesPredicates, hl7Conf); StringBuilder logPath = new StringBuilder(outputFolder) .append("/").append(GeneratedValidator.ROOT_LOG_DIRECTORY) @@ -53,6 +64,12 @@ public class ValidatorGeneratorImpl implements ValidatorGenerator { } return validator; + } + + @Override + public GeneratedValidator generateValidator(URL bbrUrl, String outputFolder, String mvn) throws ValidatorGenerationException { + GenerationConfiguration generationConfiguration = new GenerationConfiguration(bbrUrl, outputFolder, mvn); + return this.generateValidator(generationConfiguration); } diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/cda_choice.xml b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/cda_choice.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c3a6095a90fc73cf9a8f9bd5c839de35c53c227 --- /dev/null +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/cda_choice.xml @@ -0,0 +1,73 @@ +<?xml version="1.0"?> +<ClinicalDocument xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sdtc="urn:hl7-org:sdtc" xsi:schemaLocation="http://www.w3schools.com/RedsDevils ./xsd/CDA.xsd"> + <!-- START HEADER: REQUIRED ELEMENTS FOR XSD VALIDATION --> + <typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/> + <id root="1.2.3.4.5.1.7.5.10567878.0"/> + <code code="34133-9" codeSystem="2.16.840.1.113883.6.1" displayName="Summarization of Episode Note"/> + <effectiveTime value="20201201100749-0500"/> + <confidentialityCode code="N" codeSystem="2.16.840.1.113883.5.25"/> + <recordTarget> + <patientRole nullFlavor="UNK"> + <id root="1.2.3.4.5.1.7" extension="19173"/> + </patientRole> + </recordTarget> + <author nullFlavor="UNK" > + <time value="20220101100749-0500"/> + <assignedAuthor> + <id root="2.2.2.2.2.2.2"/> + </assignedAuthor> + </author> + <custodian> + <assignedCustodian> + <representedCustodianOrganization> + <id root="2.2.2.2.2.2.2"/> + </representedCustodianOrganization> + </assignedCustodian> + </custodian> + <componentOf> + <encompassingEncounter> + <effectiveTime value="20201201"/> + </encompassingEncounter> + </componentOf> + <!-- END OF HEADER --> + + <!-- START OF TEST ELEMENTS --> + <component> + <structuredBody> + <component> + <section> + <templateId root="1.1.1.1.1.1.1.1"/> + <id root="1.2.3.5.6"/> + <code code="29545-1" codeSystem="2.11.111.1.111111.1.1" codeSystemName="LOINC"/> + <title>CDA For Test</title> + <entry> + <substanceAdministration classCode="SBADM" moodCode="EVN"> + <realmCode/> + <!-- Test Choice CONF:0008 NEED TO BE True 2_3 --> + + + <!-- Test CONF:0005 "1_1" "IVL_TS" "value" ==> TRUE--> + <effectiveTime value="10122020" xsi:type="IVL_TS" ></effectiveTime> + + <!-- Test CONF:0006 "0_1" not"PIVL_TS" operator="A" ==> FALSE--> + <effectiveTime operator="A" xsi:type="TS" ></effectiveTime> + + <!-- Test CONF:0006 "1_1" TRUE--> + <effectiveTime xsi:type="EIVL_TS" > + <low value="10102020"/> + <high value="10122021"/> + </effectiveTime> + +<!-- <consumable typeCode="AUT"/>--> + </substanceAdministration> + + + + </entry> + </section> + </component> + </structuredBody> + </component> + <!-- END OF TEST ELEMENTS --> + +</ClinicalDocument> \ No newline at end of file diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/decor_choice.xml b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/decor_choice.xml new file mode 100644 index 0000000000000000000000000000000000000000..06f14dba7216363acf8b1c6c1984fedf52339dd0 --- /dev/null +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/decor_choice.xml @@ -0,0 +1,68 @@ +<decor> + + <project id="2.16.840.1.113883.2.4.3.11.60.22" prefix="choice-" defaultLanguage="en-US"> + </project> + + <rules> + <template id="1.1.1.1.1.1.1.1" name="TestCardinality" displayName="Test Cardinality Template" effectiveDate="2022-01-01T00:00:00" statusCode="active" versionLabel="1.0"> + <context id="**"></context> + <element name="cda:section" id="2.16.840.1.113883.3.1937.99.3.9.5334"> + + <element name="cda:templateId" datatype="II" minimumMultiplicity="1" maximumMultiplicity="1" isMandatory="true"> + <item label="CONF:0001"></item> + <attribute name="root" value="1.1.1.1.1.1.1.1" datatype="uid"></attribute> + </element> + <element name="cda:code" datatype="CE" minimumMultiplicity="1" maximumMultiplicity="1" isMandatory="true" id="2.16.840.1.113883.3.1937.99.3.9.5338"> + <desc language="en-US">SHALL contain exactly one [1..1] code (CONF:0002).</desc> + <item label="CONF:0002"></item> + <vocabulary code="29545-1" codeSystem="2.11.111.1.111111.1.1"></vocabulary> + </element> + <element name="cda:title" datatype="ST" minimumMultiplicity="1" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.5339"> + <desc language="en-US">SHALL contain exactly one [1..1] title (CONF:0003).</desc> + <item label="CONF:0003"></item> + </element> + + <element name="cda:entry" minimumMultiplicity="1" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.5341"> + <element name="cda:substanceAdministration" minimumMultiplicity="1" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.5347"> + <element name="cda:realmCode" minimumMultiplicity="1" maximumMultiplicity="1"> + <item label="CONF:0004"></item> + </element> + <!-- Test Choice: NEED TO BE True 2_3 --> + <choice minimumMultiplicity="2" maximumMultiplicity="3"> + + <!-- Test element: NEED TO BE True 1_1 --> + <element name="cda:effectiveTime[(@value or @nullFlavor)]" datatype="IVL_TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="C" id="2.16.840.1.113883.3.1937.99.3.9.5850"> + <attribute name="value" datatype="ts" isOptional="true" id="2.16.840.1.113883.3.1937.99.3.9.5851"></attribute> + <item label="CONF:0005"></item> + </element> + + <!-- Test element: NEED TO BE FALSE (dataType not "PIVL_TS") --> + <element name="cda:effectiveTime[(@operator='A')]" datatype="PIVL_TS" minimumMultiplicity="0" maximumMultiplicity="1" conformance="C" id="2.16.840.1.113883.3.1937.99.3.9.222"> + <item label="CONF:0006"></item> + </element> + + <!-- Test element: NEED TO BE True 1_1 --> + <element name="cda:effectiveTime" datatype="EIVL_TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="C" id="2.16.840.1.113883.3.1937.99.3.9.222"> + <element name="cda:low" datatype="TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.223"> + </element> + <element name="cda:high" datatype="TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.224"> + </element> + <item label="CONF:0007"></item> + + </element> + + <!-- Test element: NEED TO BE True 0_1 (typeCode not "CSM")--> + <element name="hl7:consumable[not(@typeCode='CSM')]" conformance="R" id="2.16.840.1.113883.3.1937.777.11.9.651" minimumMultiplicity="0" maximumMultiplicity="1"> + </element> + + <item label="CONF:0008"></item> + </choice> + <attribute name="classCode"/> + <attribute name="moodCode" /> + + </element> + </element> + </element> + </template> + </rules> +</decor> \ No newline at end of file diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/expected_choice.xml b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/expected_choice.xml new file mode 100644 index 0000000000000000000000000000000000000000..f47bf79581151e7a91a6fc860b4dbb4d54fd53bb --- /dev/null +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/choice/expected_choice.xml @@ -0,0 +1,289 @@ + +<detailedResult> + <DocumentValidXSD> + <XSDMessage> + <Severity>error</Severity> + <Message>cvc-elt.4.3: Type 'TS' is not validly derived from the type definition, 'SXCM_TS', of element 'effectiveTime'.</Message> + <columnNumber>72</columnNumber> + <lineNumber>53</lineNumber> + </XSDMessage> + <XSDMessage> + <Severity>error</Severity> + <Message>cvc-complex-type.3.2.2: Attribute 'operator' is not allowed to appear in element 'effectiveTime'.</Message> + <columnNumber>72</columnNumber> + <lineNumber>53</lineNumber> + </XSDMessage> + <XSDMessage> + <Severity>error</Severity> + <Message>cvc-complex-type.2.4.a: Invalid content was found starting with element 'low'. One of '{"urn:hl7-org:v3":event, "urn:hl7-org:v3":offset}' is expected.</Message> + <columnNumber>56</columnNumber> + <lineNumber>57</lineNumber> + </XSDMessage> + <XSDMessage> + <Severity>error</Severity> + <Message>cvc-complex-type.2.4.b: The content of element 'substanceAdministration' is not complete. One of '{"urn:hl7-org:v3":effectiveTime, "urn:hl7-org:v3":priorityCode, "urn:hl7-org:v3":repeatNumber, "urn:hl7-org:v3":routeCode, "urn:hl7-org:v3":approachSiteCode, "urn:hl7-org:v3":doseQuantity, "urn:hl7-org:v3":rateQuantity, "urn:hl7-org:v3":maxDoseQuantity, "urn:hl7-org:v3":administrationUnitCode, "urn:hl7-org:v3":subject, "urn:hl7-org:v3":specimen, "urn:hl7-org:v3":consumable}' is expected.</Message> + <columnNumber>51</columnNumber> + <lineNumber>62</lineNumber> + </XSDMessage> + <Result>FAILED</Result> + <nbOfErrors>4</nbOfErrors> + <nbOfWarnings>0</nbOfWarnings> + </DocumentValidXSD> + <DocumentWellFormed> + <Result>PASSED</Result> + </DocumentWellFormed> + <MDAValidation> + <Warning> + <Test>NullFlavorChecker</Test> + <Location>/ClinicalDocument/recordTarget/patientRole</Location> + <Description>In /ClinicalDocument/recordTarget/patientRole nullFlavor is defined but the element still defines attributes and sub-elements</Description> + <Identifiant>NullFlavorChecker</Identifiant> + <Type>Null Flavor Check</Type> + </Warning> + <Warning> + <Test>NullFlavorChecker</Test> + <Location>/ClinicalDocument/author</Location> + <Description>In /ClinicalDocument/author nullFlavor is defined but the element still defines attributes and sub-elements</Description> + <Identifiant>NullFlavorChecker</Identifiant> + <Type>Null Flavor Check</Type> + </Warning> + <Note> + <Test>test_IDs</Test> + <Location>/ClinicalDocument</Location> + <Description>Success: Found all IDs referenced</Description> + </Note> + <Note> + <Test>choice001</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:templateId[@root='1.1.1.1.1.1.1.1'], the attribute root SHALL be present</Description> + <Identifiant>choice-TestCardinality-choice001</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0001"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice002</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'], the element(s) hl7:templateId[@root='1.1.1.1.1.1.1.1'] SHALL not have nullFlavor (mandatory) (Item : CONF:0001)</Description> + <Identifiant>choice-TestCardinality-choice002</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0001"/> + <Type>Mandatory</Type> + </Note> + <Note> + <Test>choice003</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'] SHALL contain at most ONE hl7:templateId[@root='1.1.1.1.1.1.1.1'] (Item : CONF:0001)</Description> + <Identifiant>choice-TestCardinality-choice003</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0001"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice004</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'] SHALL contain at least ONE hl7:templateId[@root='1.1.1.1.1.1.1.1'] (Item : CONF:0001)</Description> + <Identifiant>choice-TestCardinality-choice004</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0001"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice005</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:code, the attribute code SHALL be present</Description> + <Identifiant>choice-TestCardinality-choice005</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0002"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice006</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:code, the attribute code SHALL have the value '29545-1' if present</Description> + <Identifiant>choice-TestCardinality-choice006</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0002"/> + <Type>Fixed value</Type> + </Note> + <Note> + <Test>choice007</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:code, the attribute codeSystem SHALL have the value '2.11.111.1.111111.1.1' if present</Description> + <Identifiant>choice-TestCardinality-choice007</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0002"/> + <Type>Fixed value</Type> + </Note> + <Note> + <Test>choice008</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'], the element(s) hl7:code SHALL not have nullFlavor (mandatory) (Item : CONF:0002)</Description> + <Identifiant>choice-TestCardinality-choice008</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0002"/> + <Type>Mandatory</Type> + </Note> + <Note> + <Test>choice009</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'] SHALL contain at least ONE hl7:code (Item : CONF:0002)</Description> + <Identifiant>choice-TestCardinality-choice009</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0002"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice010</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'] SHALL contain at least ONE hl7:title (Item : CONF:0003)</Description> + <Identifiant>choice-TestCardinality-choice010</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0003"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice011</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, the element defined by /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration/hl7:effectiveTime shall verify this requirement : (@value or @nullFlavor) (Item : CONF:0005)</Description> + <Identifiant>choice-TestCardinality-choice011</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0005;CONF:0008"/> + <Type>Context</Type> + </Note> + <Note> + <Test>choice012</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at most ONE hl7:effectiveTime (Item : CONF:0005)</Description> + <Identifiant>choice-TestCardinality-choice012</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0005;CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice013</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at least ONE hl7:effectiveTime (Item : CONF:0005)</Description> + <Identifiant>choice-TestCardinality-choice013</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0005;CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice014</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, the element defined by /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration/hl7:effectiveTime shall verify this requirement : (@operator='A') (Item : CONF:0006)</Description> + <Identifiant>choice-TestCardinality-choice014</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0006;CONF:0008"/> + <Type>Context</Type> + </Note> + <Note> + <Test>choice015</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at most ONE hl7:effectiveTime (Item : CONF:0006)</Description> + <Identifiant>choice-TestCardinality-choice015</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0006;CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice016</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at most ONE hl7:effectiveTime (Item : CONF:0007)</Description> + <Identifiant>choice-TestCardinality-choice016</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0007;CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Error> + <Test>choice017</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at least ONE hl7:effectiveTime (Item : CONF:0007)</Description> + <Identifiant>choice-TestCardinality-choice017</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0007;CONF:0008"/> + <Type>Cardinality</Type> + </Error> + <Note> + <Test>choice018</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, the element defined by /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration/hl7:consumable shall verify this requirement : not(@typeCode='CSM')</Description> + <Identifiant>choice-TestCardinality-choice018</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0008"/> + <Type>Context</Type> + </Note> + <Warning> + <Test>choice019</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHOULD contain at least ONE hl7:consumable</Description> + <Identifiant>choice-TestCardinality-choice019</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0008"/> + <Type>Cardinality</Type> + </Warning> + <Note> + <Test>choice020</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry, the number of elements of type 'effectiveTime', 'effectiveTime', 'effectiveTime', 'consumable' SHALL be lower or equal to 3 (Item : CONF:0008)</Description> + <Identifiant>choice-TestCardinality-choice020</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice021</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, in /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry, the number of elements of type 'effectiveTime', 'effectiveTime', 'effectiveTime', 'consumable' SHALL be bigger or equal to 2 (Item : CONF:0008)</Description> + <Identifiant>choice-TestCardinality-choice021</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0008"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice022</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at most ONE hl7:realmCode (Item : CONF:0004)</Description> + <Identifiant>choice-TestCardinality-choice022</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0004"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice023</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry/hl7:substanceAdministration SHALL contain at least ONE hl7:realmCode (Item : CONF:0004)</Description> + <Identifiant>choice-TestCardinality-choice023</Identifiant> + <assertion idScheme="choice" assertionId="CONF:0004"/> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice024</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1']/hl7:entry SHALL contain at least ONE hl7:substanceAdministration</Description> + <Identifiant>choice-TestCardinality-choice024</Identifiant> + <Type>Cardinality</Type> + </Note> + <Note> + <Test>choice025</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>In Test Cardinality Template, /hl7:section[hl7:templateId/@root='1.1.1.1.1.1.1.1'] SHALL contain at least ONE hl7:entry</Description> + <Identifiant>choice-TestCardinality-choice025</Identifiant> + <Type>Cardinality</Type> + </Note> + <Error> + <Test>structure</Test> + <Location>All the document</Location> + <Description>The tool is not able to find urn:hl7-org:v3:ClinicalDocument element as the root of the validated document.</Description> + </Error> + <Note> + <Test>test_IDs</Test> + <Location>/ClinicalDocument</Location> + <Description>Success: Found all IDs referenced</Description> + </Note> + <Warning> + <Test>rmim052</Test> + <Location>/ClinicalDocument/component/structuredBody/component[0]/section</Location> + <Description>Section.text SHALL be specified, as it is a required element (RMIM-052)</Description> + <Identifiant>cdabasic-SectionSpec-rmim052</Identifiant> + <assertion idScheme="RMIM" assertionId="RMIM-052"/> + <Type>Mandatory</Type> + </Warning> + <Error> + <Test>structure</Test> + <Location>All the document</Location> + <Description>The tool is not able to find urn:hl7-org:v3:ClinicalDocument element as the root of the validated document.</Description> + </Error> + <Note> + <Test>test_IDs</Test> + <Location>/ClinicalDocument</Location> + <Description>Success: Found all IDs referenced</Description> + </Note> + <Result>FAILED</Result> + </MDAValidation> + <ValidationResultsOverview> + <ValidationDate>2022, 06 13</ValidationDate> + <ValidationTime>05:11:10</ValidationTime> + <ValidationServiceName>Gazelle CDA Validation : choice</ValidationServiceName> + <ValidationTestResult>FAILED</ValidationTestResult> + </ValidationResultsOverview> +</detailedResult> diff --git a/hl7templates/goc-tests/goc-tests-runner/src/main/resources/specifications.properties b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/specifications.properties index 169b3a216acd0c4e5daf1ef41ebec69173894da8..defdd8744b8d85aa649655b72fa7c5b272ab8d13 100644 --- a/hl7templates/goc-tests/goc-tests-runner/src/main/resources/specifications.properties +++ b/hl7templates/goc-tests/goc-tests-runner/src/main/resources/specifications.properties @@ -24,4 +24,8 @@ datatype.expected=datatype/expected_datatype.xml context.bbr=context/decor_context.xml context.cda=context/cda_context.xml -context.expected=context/expected_context.xml \ No newline at end of file +context.expected=context/expected_context.xml + +choice.bbr=choice/decor_choice.xml +choice.cda=choice/cda_choice.xml +choice.expected=choice/expected_choice.xml \ No newline at end of file diff --git a/hl7templates/goc-tests/goc-tests-runner/src/test/java/net/ihe/gazelle/goctests/SystemTests.java b/hl7templates/goc-tests/goc-tests-runner/src/test/java/net/ihe/gazelle/goctests/SystemTests.java index b08e9c764d22adc7bdccd969b499966ca7fbe2ed..93a2ce53a8f9b3e51ae07fa4bac76f64bfb7d263 100644 --- a/hl7templates/goc-tests/goc-tests-runner/src/test/java/net/ihe/gazelle/goctests/SystemTests.java +++ b/hl7templates/goc-tests/goc-tests-runner/src/test/java/net/ihe/gazelle/goctests/SystemTests.java @@ -92,6 +92,14 @@ public class SystemTests { runTest(); } + @Ignore + @Test + public void choiceTest() throws ReportGenerationException, TestRunnerException, SpecificationException, + EnvironementException, ResultTransformationException { + this.specificationType = SpecificationType.CHOICE; + runTest(); + + } private void runTest() throws ReportGenerationException, TestRunnerException, diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/AssertAnalyzer.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/AssertAnalyzer.java index b21f6f18972d76e4c9f86ed3c62beea182747852..bfe5439e46911827229990a4f3870ef29de0fc14 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/AssertAnalyzer.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/AssertAnalyzer.java @@ -6,6 +6,7 @@ import gnu.trove.map.hash.THashMap; import net.ihe.gazelle.goc.common.utils.XPATHOCLGroup; import net.ihe.gazelle.goc.common.utils.XPATHOCLRule; import net.ihe.gazelle.goc.common.utils.XSITypeOCL; +import net.ihe.gazelle.tempmodel.decor.dt.utils.DTUtils; import org.apache.commons.lang.StringUtils; import net.ihe.gazelle.goc.uml.utils.OwnedRuleUtil; @@ -50,6 +51,11 @@ public class AssertAnalyzer extends AssertProcessorImpl { protected List<OwnedRule> listGeneratedOwnedRule; + protected Boolean generateDTDistinguisher = Boolean.FALSE; + + + + @SuppressWarnings("unchecked") @Override public void process(Assert t, Object... objects) { @@ -59,7 +65,11 @@ public class AssertAnalyzer extends AssertProcessorImpl { if (objects.length>1) { this.listGeneratedOwnedRule = (List<OwnedRule>) objects[1]; } - if (!GenerationProperties.ignoreAssertionGeneration && verifyThatAssertIsProcessable(this.currentAssert)){ + if(objects.length>2){ + this.generateDTDistinguisher = (Boolean) objects[2]; + } + + if (!GenerationProperties.ignoreAssertionGeneration && verifyThatAssertIsProcessable(this.currentAssert)){; super.process(t, objects); } } @@ -288,6 +298,13 @@ public class AssertAnalyzer extends AssertProcessorImpl { ImportElementHandler.handleAddingElement("CommonOperationsStatic"); } } + if(this.generateDTDistinguisher && currentAssert.getParentObject() instanceof RuleDefinition){ + RuleDefinition parentRD = (RuleDefinition) currentAssert.getParentObject(); + OCLGenerator generator = new OCLGenerator(); + res = generator.appendDTDistinguisher(parentRD, res); + + } + return res; } @@ -422,9 +439,16 @@ public class AssertAnalyzer extends AssertProcessorImpl { XSITypeOCL xsiTypeOCL = (XSITypeOCL)xpathoclRule; String not = xsiTypeOCL.isNegativeOperation()?"not(":""; String closingNot = not.equals("not(")?")":""; - String formattedType = xsiTypeOCL.getType().replace("_",""); - subRule = prefix+"->forAll("+not+"oclIsKindOf("+formattedType+")" + String dt = DTUtils.getUMLDatatype(xsiTypeOCL.getType()); + + if(dt==null){ + return null; + } + //String formattedType = xsiTypeOCL.getType().replace("_",""); + subRule = prefix+"->forAll("+not+"oclIsKindOf("+dt+")" +closingNot+")"+stringOperation; + ImportElementHandler.handleAddingElement(dt); + } else{ subRule = prefix+"->forAll(aa | CommonOperationsStatic::validateByXPATHV2(aa, '" diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/ChoiceDefinitionAnalyzer.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/ChoiceDefinitionAnalyzer.java index aa90417b31b749c4ce26f0386c1ff07e0e84bfed..6cb360a82d27c849994c22a83c3630caa5cc8d08 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/ChoiceDefinitionAnalyzer.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/ChoiceDefinitionAnalyzer.java @@ -6,7 +6,6 @@ import java.util.regex.Pattern; import gnu.trove.map.hash.THashMap; import net.ihe.gazelle.goc.uml.utils.OwnedRuleUtil; -import net.ihe.gazelle.goc.uml.utils.PackagedElementUtil; import net.ihe.gazelle.goc.xmm.OwnedRule; import net.ihe.gazelle.goc.xmm.OwnedRuleKind; import net.ihe.gazelle.goc.xmm.OwnedRuleType; diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/HL7TemplatesConverter.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/HL7TemplatesConverter.java index 0b3c057f264357b2d62ce75d84d0651e8aefa62a..7f33f5da993cad0ed4fa02f24d472bafd8cb1c96 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/HL7TemplatesConverter.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/HL7TemplatesConverter.java @@ -1,6 +1,7 @@ package net.ihe.gazelle.tempgen.action; +import net.ihe.gazelle.goc.template.definer.model.Taml; import net.ihe.gazelle.goc.uml.utils.XMIUtil; import net.ihe.gazelle.goc.xmi.XMI; import net.ihe.gazelle.goc.xmi.XMIMarshaller; @@ -21,6 +22,8 @@ import javax.xml.bind.JAXBException; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -83,12 +86,6 @@ public class HL7TemplatesConverter { log.warn("Converting Decor to XMI"); // - if(ignoreChoicesPredicates){ - log.info("///////////////////////////////////// Ignored all Predicates Choices ///////////////////////////////////////// "); - } - else{ - log.info("///////////////////////////////////// The choices predicates was processing ///////////////////////////////"); - } XMI xmi = convertFlattenedDecorToXMI(decor, ignoreTemplateIdRequirements,ignoreChoicesPredicates); ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMIMarshaller.printXMI(xmi, baos); @@ -143,29 +140,42 @@ public class HL7TemplatesConverter { //The entrypoint to convert the decor to OCL! (new DecorAnalyzer()).process(decor, xmi, Boolean.valueOf(ignoreTemplateIdRequirements),ignoreChoicesPredicates); //Skip incorrect OCL + //cleanTAML(xmi); clearXMI(xmi); return xmi; } + private void clearXMI(XMI xmi){ - for(PackagedElement packagedElement:xmi.getModel().getPackagedElement()){ - for(int ownedRule=0;ownedRule<packagedElement.getOwnedRule().size();ownedRule++) { - if(cleanOCL(packagedElement.getOwnedRule().get(ownedRule))==null) { - packagedElement.getOwnedRule().remove(packagedElement.getOwnedRule().get(ownedRule)); - TamlHandler.removeTAML(packagedElement.getOwnedRule().get(ownedRule)); + ArrayList<String> removedOrIds = new ArrayList<>(); + for(Iterator<PackagedElement> itpe = xmi.getModel().getPackagedElement().listIterator(); itpe.hasNext();){ + PackagedElement currentPe = itpe.next(); + for(Iterator<OwnedRule> itor = currentPe.getOwnedRule().listIterator(); itor.hasNext();){ + OwnedRule currentOr = itor.next(); + if(!isOclClean(currentOr)){ + log.info("Removing wrong OCL: {}",currentOr.getId()); + //TamlHandler.removeTAML(currentOr); + removedOrIds.add(currentOr.getId()); + itor.remove(); } } - + } + for(Iterator<Taml> ittaml = xmi.getTaml().listIterator(); ittaml.hasNext();){ + Taml currentTaml = ittaml.next(); + if(removedOrIds.contains(currentTaml.getBaseConstraint())){ + ittaml.remove(); + } } } - private OwnedRule cleanOCL(OwnedRule ownedRule){ + private boolean isOclClean(OwnedRule ownedRule){ String mat= ownedRule.getSpecification().getBody(); String matr= "\\)[A-Za-z]+"; Pattern pattern = Pattern.compile(matr); Matcher matcher = pattern.matcher(ownedRule.getSpecification().getBody()); if(!matcher.find()){ - return ownedRule; + return true; } - return null; + return false; } + } diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/OCLGenerator.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/OCLGenerator.java index fb7841a7eafd0891eb903c6e4cfa806c4f61c402..6d548ee11e501a65c72dcff99ed62fda52fe12ee 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/OCLGenerator.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/OCLGenerator.java @@ -13,6 +13,7 @@ import net.ihe.gazelle.tempmodel.org.decor.art.model.RuleDefinition; import net.ihe.gazelle.tempmodel.org.decor.art.model.TemplateDefinition; import net.ihe.gazelle.tempmodel.org.decor.art.utils.*; import org.apache.commons.lang.StringUtils; +import org.eclipse.emf.ecore.EDataType; import java.util.ArrayList; import java.util.List; @@ -435,4 +436,28 @@ public class OCLGenerator { } return addNullFlavorChecks(rules); } + + + public String appendDTDistinguisher(RuleDefinition ruleDefinition, String constraint){ + if(constraint == null || ruleDefinition == null){ + return constraint; + } + String rdName = RuleDefinitionUtil.getRealNameOfRuleDefinition(ruleDefinition); + StringBuilder selectionRule = new StringBuilder(rdName); + if(ruleDefinition.getDatatype() == null){ + return constraint; + } + String datatype = ruleDefinition.getDatatype().getLocalPart(); + if(datatype == null){ + return constraint; + } + ImportElementHandler.handleAddingElement(datatype); + String datatypeForOCL = datatype.replace("_",""); + selectionRule.append("->select(aa | CommonOperationsStatic::compareExactType(aa, '") + .append(datatypeForOCL) + .append("'))"); + ImportElementHandler.handleAddingElement("CommonOperationsStatic"); + return constraint.replace(rdName, selectionRule); + + } } diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/RuleDefinitionAnalyzer.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/RuleDefinitionAnalyzer.java index 973c24dedd1f22bd015ba829e0f535f237336c5f..b3a26ed6cb74e9fe22f036f71e4a01ac0a771c8e 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/RuleDefinitionAnalyzer.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/action/RuleDefinitionAnalyzer.java @@ -15,6 +15,7 @@ import net.ihe.gazelle.tempmodel.dpath.utils.DPathExtractor; import net.ihe.gazelle.tempmodel.org.decor.art.behavior.HasItem; import net.ihe.gazelle.tempmodel.org.decor.art.model.*; import net.ihe.gazelle.tempmodel.org.decor.art.utils.*; +import org.eclipse.uml2.uml.DataType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +45,9 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { private List<OwnedRule> listGeneratedOwnedRule = new ArrayList<>(); + private Boolean generateDTDistinguisher = Boolean.FALSE; + + private boolean containsError = false; protected static void updateListDistinguisherFollower(RuleDefinition ruleDefinition, Pair<String, String> pairDisting) { @@ -141,6 +145,10 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { } this.currentPackagedElement = (PackagedElement) objects[0]; this.selectedRuleDefinition = ruleDefinition; + Object parentRule = this.selectedRuleDefinition.getParentObject(); + if(parentRule instanceof ChoiceDefinition){ + this.generateDTDistinguisher = (RuleDefinitionDistinguisherUtil.elementsShouldBeDistinguisedWithDT((ChoiceDefinition) parentRule)); + } if (objects.length > 1) { this.ignoreTemplateIdRequirements = (Boolean) objects[1]; } @@ -162,6 +170,9 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { return; } updateDistinguisherFollowerIfNeeded(); + + // Add a method that adds and 'AND' constraint based on datatype to the processing + super.process(this.selectedRuleDefinition, objects); // -- still not done @@ -261,7 +272,7 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { public void process_asserts(List<Assert> decorAsserts) { if (decorAsserts != null) { for (Assert assert1 : decorAsserts) { - (new AssertAnalyzer()).process(assert1, this.currentPackagedElement, this.listGeneratedOwnedRule); + (new AssertAnalyzer()).process(assert1, this.currentPackagedElement, this.listGeneratedOwnedRule,this.generateDTDistinguisher); } } } @@ -418,13 +429,13 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { @Override public void processMinimumMultiplicity(Integer minimumMultiplicity) { // TODO: 23/12/2021 Highly need to be reviewed - if (this.ignoreMinCardinality()) { - // this is the case where the RuleDefinition is included in a choice - return; - } +// if (this.ignoreMinCardinality()) { +// // this is the case where the RuleDefinition is included in a choice +// return; +// } if (checkIfConstraintCanBeGeneratedForMinimumMultiplicity(minimumMultiplicity, this.selectedRuleDefinition)) { if (!(this.selectedRuleDefinition.getParentObject() instanceof TemplateDefinition)) { - fulfillOwnedRuleForConstraintGenerator((new RDMinimumMultiplicityAnalyzer()), this.currentPackagedElement, OwnedRuleKind.CARDINALITY, + fulfillOwnedRuleForConstraintGenerator((new RDMinimumMultiplicityAnalyzer(this.generateDTDistinguisher)), this.currentPackagedElement, OwnedRuleKind.CARDINALITY, (minimumMultiplicity.intValue() == 0 && selectedRuleDefinition.getConformance().equals(ConformanceType.R))? OwnedRuleType.WARNING: OwnedRuleType.ERROR); } else { @@ -458,7 +469,7 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { boolean isPossibleToHaveConstraint = maximumMultiplicity.intValue() < elementMaxMultiplicity; if (isPossibleToHaveConstraint || (selectedRuleDefinition.getParentObject() instanceof RuleDefinition && ((RuleDefinition) selectedRuleDefinition.getParentObject()).getParentObject() instanceof ChoiceDefinition )) { - fulfillOwnedRuleForConstraintGenerator((new RDMaximumMultiplicityAnalyzer()), this.currentPackagedElement, OwnedRuleKind.CARDINALITY); + fulfillOwnedRuleForConstraintGenerator((new RDMaximumMultiplicityAnalyzer(this.generateDTDistinguisher)), this.currentPackagedElement, OwnedRuleKind.CARDINALITY); } } @@ -491,6 +502,10 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { if (datatype == null) { return; } + if(Boolean.TRUE.equals(this.generateDTDistinguisher)){ + ImportElementHandler.handleAddingElement(DTUtils.getUMLDatatype(datatype.getLocalPart())); + return; + } String dt = datatype.getLocalPart(); String typeRD = RuleDefinitionUtil.getUMLTypeName(selectedRuleDefinition); if (dt != null) { @@ -526,6 +541,9 @@ public class RuleDefinitionAnalyzer extends RuleDefinitionProcessorImpl { if (constraintGenerator == null) { return; } +// if(this.generateDTDistinguisher && constraintGenerator instanceof RDDatatypeAnalyzer){ +// return; +// } OwnedRule ownedRule = OwnedRuleUtil.initOwnedRule(); ownedRule.setConstrainedElement(pe.getId()); String specification = constraintGenerator.generateOCLConstraint(this.selectedRuleDefinition); diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/flatten/action/RuleDefinitionFlattenProc.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/flatten/action/RuleDefinitionFlattenProc.java index cd1216604beccaedb455c4db40047444fbb18cce..0017411996e4bd713005d46c1b9e6d2fb73a4dd2 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/flatten/action/RuleDefinitionFlattenProc.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/flatten/action/RuleDefinitionFlattenProc.java @@ -8,10 +8,7 @@ import net.ihe.gazelle.tempmodel.dpath.model.DElement; import net.ihe.gazelle.tempmodel.dpath.model.DParent; import net.ihe.gazelle.tempmodel.dpath.utils.DPathExtractor; import net.ihe.gazelle.tempmodel.org.decor.art.model.*; -import net.ihe.gazelle.tempmodel.org.decor.art.utils.RuleDefinitionUtil; -import net.ihe.gazelle.tempmodel.org.decor.art.utils.RulesUtil; -import net.ihe.gazelle.tempmodel.org.decor.art.utils.TemplateDefinitionUtil; -import net.ihe.gazelle.tempmodel.org.decor.art.utils.VocabularyUtil; +import net.ihe.gazelle.tempmodel.org.decor.art.utils.*; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -111,9 +108,9 @@ public class RuleDefinitionFlattenProc extends RuleDefinitionProcessorImpl { @Override public void processName(String nameParam) { - if(currentRuleDefinition.getParentObject() instanceof ChoiceDefinition){ - return; - } +// if(currentRuleDefinition.getParentObject() instanceof ChoiceDefinition){ +// return; +// } String name = nameParam; if (name == null) { return; @@ -132,7 +129,22 @@ public class RuleDefinitionFlattenProc extends RuleDefinitionProcessorImpl { DParent userDParent = DPathExtractor.extractDElementFromDPath(name); if (userDParent != null) { this.currentRdNameAsXpath.setProcessed(true); - flattenDecorNameForDParent(userDParent); + //flattenDecorNameForDParent(userDParent) + Assert customAssert = new Assert(); + String assertFromName = AssertUtil.extractAssertFromName(this.currentRuleDefinition.getName()); + customAssert.setTest(assertFromName); + if(assertFromName!=null){ + this.currentRuleDefinition.getLetOrAssertOrReport().add(customAssert); + this.currentRuleDefinition.setName(RuleDefinitionUtil.getRealNameOfRuleDefinition(currentRuleDefinition)); + this.currentRdNameAsXpath.setProcessed(true); + } + else{ + this.currentRdNameAsXpath.setProcessed(false); + ProblemHandler.handleRuleDefinitionError(currentRuleDefinition, + "The name specified cannot be processed by the tool : " + name, + FlattenAnalyzerEnum.RD_FLATTEN_PROCESS.getValue()); + } + } else { this.currentRdNameAsXpath.setProcessed(false); ProblemHandler.handleRuleDefinitionError(currentRuleDefinition, @@ -140,12 +152,14 @@ public class RuleDefinitionFlattenProc extends RuleDefinitionProcessorImpl { FlattenAnalyzerEnum.RD_FLATTEN_PROCESS.getValue()); } } - } else { - this.currentRdNameAsXpath.setProcessed(false); - ProblemHandler.handleRuleDefinitionError(currentRuleDefinition, - "The name specified cannot be processed by the tool : " + name, - FlattenAnalyzerEnum.RD_FLATTEN_PROCESS.getValue()); } +// else { +// Assert customAssert = new Assert(); +// customAssert.setTest(AssertUtil.extractAssertFromName(this.currentRuleDefinition.getName())); +// this.currentRuleDefinition.getLetOrAssertOrReport().add(customAssert); +// this.currentRuleDefinition.setName(RuleDefinitionUtil.getRealNameOfRuleDefinition(currentRuleDefinition)); +// this.currentRdNameAsXpath.setProcessed(false); +// } } /** diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMaximumMultiplicityAnalyzer.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMaximumMultiplicityAnalyzer.java index 109226d35a5389aa20574912835c09ea71e04d84..467d6888cb1121a182d3bec709c6fe394068fb9a 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMaximumMultiplicityAnalyzer.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMaximumMultiplicityAnalyzer.java @@ -17,7 +17,17 @@ import net.ihe.gazelle.tempmodel.org.decor.art.utils.RuleDefinitionUtil; public class RDMaximumMultiplicityAnalyzer implements ConstraintGenerator{ static final int MAX_INTEGER = 1000000000; - + + private final Boolean generateDTDistinguisher; + + public RDMaximumMultiplicityAnalyzer(Boolean generateDTDistinguisher) { + this.generateDTDistinguisher = generateDTDistinguisher; + } + + public RDMaximumMultiplicityAnalyzer() { + this.generateDTDistinguisher = Boolean.FALSE; + } + @Override public String generateOCLConstraint(RuleDefinition ruleDefinition) { Integer maximumMultiplicity = null; @@ -30,7 +40,8 @@ public class RDMaximumMultiplicityAnalyzer implements ConstraintGenerator{ maximumMultiplicity = Integer.valueOf(maximumMultiplicityString); } } - String contextRule = (new OCLGenerator()).generateRuleToParentFromPath(ruleDefinition); + OCLGenerator generator = new OCLGenerator(); + String contextRule = generator.generateRuleToParentFromPath(ruleDefinition); String res = ""; if (contextRule.equals("self")){ res = contextRule + "." + RuleDefinitionUtil.getRealNameOfRuleDefinition(ruleDefinition) @@ -49,6 +60,9 @@ public class RDMaximumMultiplicityAnalyzer implements ConstraintGenerator{ + "->size()<" + + (maximumMultiplicity.intValue() +1) + ")"; } } + if(generateDTDistinguisher == Boolean.TRUE){ + return generator.appendDTDistinguisher(ruleDefinition, res); + } return res; } diff --git a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMinimumMultiplicityAnalyzer.java b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMinimumMultiplicityAnalyzer.java index 81db57b94f1e651ea954909ae8c5abb47a4ef873..056b87aeffa895f04a4a54f72be616f9ddb1ecb6 100644 --- a/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMinimumMultiplicityAnalyzer.java +++ b/hl7templates/hl7templates-generator-jar/src/main/java/net/ihe/gazelle/tempgen/rules/analyzer/RDMinimumMultiplicityAnalyzer.java @@ -15,6 +15,16 @@ import net.ihe.gazelle.tempmodel.org.decor.art.utils.RuleDefinitionUtil; */ public class RDMinimumMultiplicityAnalyzer implements ConstraintGenerator { + private final Boolean generateDTDistinguisher; + + public RDMinimumMultiplicityAnalyzer(Boolean generateDTDistinguisher) { + this.generateDTDistinguisher = generateDTDistinguisher; + } + + public RDMinimumMultiplicityAnalyzer(){ + this.generateDTDistinguisher = Boolean.FALSE; + } + @Override public String generateOCLConstraint(RuleDefinition ruleDefinition) { OCLGenerator generator = new OCLGenerator(); @@ -26,6 +36,9 @@ public class RDMinimumMultiplicityAnalyzer implements ConstraintGenerator { } else { constraint.append(generator.getMinimumMultiplicityRuleForRD(constraint.toString(), ruleDefinition)); } + if(this.generateDTDistinguisher == Boolean.TRUE){ + return generator.appendDTDistinguisher(ruleDefinition, constraint.toString()); + } return constraint.toString(); } diff --git a/hl7templates/hl7templates-generator-jar/src/test/resources/processors/decor_name.xml b/hl7templates/hl7templates-generator-jar/src/test/resources/processors/decor_name.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4c2c62561a8a46dcda8e668997386d5246191be --- /dev/null +++ b/hl7templates/hl7templates-generator-jar/src/test/resources/processors/decor_name.xml @@ -0,0 +1,195 @@ +<?xml-model href="http://art-decor.org/ADAR/rv/DECOR.xsd" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?> +<decor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epsos="urn:epSOS:ps:ps:2010" xsi:noNamespaceSchemaLocation="http://art-decor.org/ADAR/rv/DECOR.xsd" repository="true" epsos:dummy-1="urn:epSOS:ps:ps:2010" xsi:dummy-2="http://www.w3.org/2001/XMLSchema-instance" versionDate="2015-06-09T11:03:41" versionLabel="" compilationDate="2015-06-09T11:03:41" language="en-US" deeplinkprefix="http://decor.nictiz.nl/art-decor/" deeplinkprefixservices="http://decor.nictiz.nl/decor/services/"> + <project> + </project> + <rules> + <template id="2.16.840.1.113883.10.20.22.4.16" name="MedicationActivity" displayName="Medication Activity" effectiveDate="2013-01-31T00:00:00" statusCode="draft" versionLabel="1.1"> + <desc language="en-US">A medication activity describes substance administrations that have actually occurred (e.g. pills ingested or injections given) or are intended to occur (e.g. "take 2 tablets twice a day for the next 10 days"). Medication activities in "INT" mood are reflections of what a clinician intends a patient to be taking. Medication activities in "EVN" mood reflect actual + use. Medication timing is complex. This template requires that there be a substanceAdministration/effectiveTime valued with a time interval, representing the start and stop dates. Additional effectiveTime elements are optional, and can be used to represent frequency and other aspects of more detailed dosing regimens.</desc> + <classification type="cdaentrylevel"></classification> + <context id="**"></context> + <element name="cda:substanceAdministration" id="2.16.840.1.113883.3.1937.99.3.9.211"> + <desc language="en-US">Medication Activity SHOULD include doseQuantity OR rateQuantity</desc> + <attribute name="classCode" value="SBADM" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.212"> + <item label="conf-7496"></item> + </attribute> + <attribute name="moodCode" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.213"> + <item label="conf-7497"></item> + <vocabulary valueSet="2.16.840.1.113883.11.20.9.18"></vocabulary> + </attribute> + <element name="cda:templateId" datatype="II" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" isMandatory="true" id="2.16.840.1.113883.3.1937.99.3.9.214"> + <desc language="en-US">SHALL contain exactly one [1..1] templateId (CONF:7499) such that it</desc> + <item label="conf-7499"></item> + <attribute name="root" value="2.16.840.1.113883.10.20.22.4.16" datatype="uid" id="2.16.840.1.113883.3.1937.99.3.9.215"> + <item label="conf-10504"></item> + </attribute> + </element> + <element name="cda:id" datatype="II" minimumMultiplicity="1" maximumMultiplicity="*" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.216"> + <desc language="en-US">SHALL contain at least one [1..*] id (CONF:7500).</desc> + <item label="conf-7500"></item> + </element> + <element name="cda:code" datatype="CD" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.217"> + <desc language="en-US">MAY contain zero or one [0..1] code (CONF:7506).</desc> + <item label="conf-7506"></item> + </element> + <element name="cda:text" datatype="ED" minimumMultiplicity="0" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.218"> + <desc language="en-US">SHOULD contain zero or one [0..1] text (CONF:7501).</desc> + <item label="conf-7501"></item> + <element name="cda:reference" minimumMultiplicity="0" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.219"> + <desc language="en-US">The text, if present, SHOULD contain zero or one [0..1] reference (CONF:15977).<p></p>This reference/@value SHALL begin with a '#' and SHALL point to its corresponding narrative (using the approach defined in CDA Release 2, section 4.3.5.1)</desc> + <item label="conf-15977"></item> + <attribute name="value" isOptional="true" id="2.16.840.1.113883.3.1937.99.3.9.220"> + <item label="conf-15978"></item> + </attribute> + <assert role="error" test="not(@value) or starts-with(@value, '#')">This reference/@value SHALL begin with a '#' and SHALL point to its corresponding narrative (using the approach defined in CDA Release 2, section 4.3.5.1)</assert> + </element> + </element> + <element name="cda:statusCode" datatype="CS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.221"> + <desc language="en-US">SHALL contain exactly one [1..1] statusCode (CONF:7507).</desc> + <item label="conf-7507"></item> + </element> +<!-- <choice minimumMultiplicity="1" maximumMultiplicity="1">--> +<!-- <desc language="en-US">This effectiveTime SHALL contain either a low or a @value but not both (CONF:26528).<br clear="none" />--> +<!-- </desc>--> +<!-- <item label="conf-26528"></item>--> +<!-- <element name="cda:effectiveTime" datatype="TS" minimumMultiplicity="0" maximumMultiplicity="1" conformance="C" id="2.16.840.1.113883.3.1937.99.3.9.5850">--> +<!-- <desc language="en-US">Note: This effectiveTime represents either the medication duration (i.e., the time the medication was started and stopped) or the single-administration timestamp.<br clear="none" />--> +<!-- </desc>--> +<!-- <item label="conf-26525">--> +<!-- <desc language="en-US">Note: indicates a single-administration timestamp [CONF:26525]<br clear="none" />--> +<!-- </desc>--> +<!-- </item>--> +<!-- <attribute name="value" datatype="ts" isOptional="true" id="2.16.840.1.113883.3.1937.99.3.9.5851"></attribute>--> +<!-- </element>--> +<!-- <element name="cda:effectiveTime[not(@operator='A')]" datatype="IVL_TS" minimumMultiplicity="0" maximumMultiplicity="1" conformance="C" id="2.16.840.1.113883.3.1937.99.3.9.222">--> +<!-- <desc language="en-US">SHALL contain exactly one [1..1] effectiveTime (CONF:7508) such that it</desc>--> +<!-- <item label="conf-7508"></item>--> +<!-- <element name="cda:low" datatype="TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.223">--> +<!-- <desc language="en-US">SHALL contain exactly one [1..1] low (CONF:26526).<br clear="none" />Note: indicates when medication started<br clear="none" />--> +<!-- </desc>--> +<!-- <item label="conf-26526"></item>--> +<!-- </element>--> +<!-- <element name="cda:high" datatype="TS" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.224">--> +<!-- <desc language="en-US">SHALL contain exactly one [1..1] high (CONF:26527).<br clear="none" />Note: indicates when medication stopped<br clear="none" />--> +<!-- </desc>--> +<!-- <item label="conf-26527"></item>--> +<!-- </element>--> +<!-- </element>--> +<!-- </choice>--> + <element name="cda:effectiveTime[@operator='A']" datatype="SXCM_TS" minimumMultiplicity="0" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.225"> + <desc language="en-US">SHOULD contain zero or one [0..1] effectiveTime (CONF:7513) such that it<p></p> SHALL contain exactly one [1..1] @xsi:type=â€PIVL_TS†or “EIVL_TSâ€</desc> + <item label="conf-7513"></item> + <attribute name="operator" value="A" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.226"> + <item label="conf-9106"></item> + </attribute> + <assert role="error" test="count(preceding-sibling::cda:effectiveTime) = 1 and .[@operator='A'][@xsi:type='PIVL_TS' or @xsi:type='EIVL_TS']">SHOULD contain zero or one [0..1] effectiveTime (CONF:7513) such that it</assert> + </element> + <element name="cda:repeatNumber" datatype="IVL_INT" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.227"> + <desc language="en-US">MAY contain zero or one [0..1] repeatNumber (CONF:7555).<p></p>In "INT" (intent) mood, the repeatNumber defines the number of allowed administrations. For example, a repeatNumber of "3" means that the substance can be administered up to 3 times. In "EVN" (event) mood, the repeatNumber is the number of occurrences. For example, a repeatNumber of "3" in a + substance administration event means that the current administration is the 3rd in a series.</desc> + <item label="conf-7555"></item> + </element> + <element name="cda:routeCode" datatype="CE" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.228"> + <desc language="en-US">MAY contain zero or one [0..1] routeCode, which SHALL be selected from ValueSet Medication Route FDA 2.16.840.1.113883.3.88.12.3221.8.7 DYNAMIC (CONF:7514).</desc> + <item label="conf-7514"></item> + <vocabulary valueSet="2.16.840.1.113883.3.88.12.3221.8.7"></vocabulary> + </element> + <element name="cda:approachSiteCode" datatype="CD" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.229"> + <desc language="en-US">MAY contain zero or one [0..1] approachSiteCode, where the code SHALL be selected from ValueSet Body Site 2.16.840.1.113883.3.88.12.3221.8.9 DYNAMIC (CONF:7515).</desc> + <item label="conf-7515"></item> + <vocabulary valueSet="2.16.840.1.113883.3.88.12.3221.8.9"></vocabulary> + </element> + <choice minimumMultiplicity="0"> + <desc language="nl-NL">Medication Activity SHOULD include doseQuantity OR rateQuantity</desc> + <element name="cda:doseQuantity" datatype="IVL_PQ" minimumMultiplicity="0" maximumMultiplicity="1" conformance="R" id="2.16.840.1.113883.3.1937.99.3.9.230"> + <desc language="en-US">SHOULD contain zero or one [0..1] doseQuantity (CONF:7516).<p></p>Pre-coordinated consumable: If the consumable code is a pre-coordinated unit dose (e.g. "metoprolol 25mg tablet") then doseQuantity is a unitless number that indicates the number of products given per administration (e.g. "2", meaning 2 x "metoprolol 25mg tablet").<p></p>Not pre-coordinated + consumable: If the consumable code is not pre-coordinated (e.g. is simply "metoprolol"), then doseQuantity must represent a physical quantity with @unit, e.g. "25" and "mg", specifying the amount of product given per administration.</desc> + <item label="conf-7516"></item> + <attribute name="unit" datatype="cs" isOptional="true" id="2.16.840.1.113883.3.1937.99.3.9.231"> + <item label="conf-7526"></item> + <vocabulary valueSet="2.16.840.1.113883.1.11.12839"></vocabulary> + </attribute> + </element> + <element name="cda:rateQuantity" datatype="IVL_PQ" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.232"> + <desc language="en-US">MAY contain zero or one [0..1] rateQuantity (CONF:7517).</desc> + <item label="conf-7517"></item> + <attribute name="unit" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.233"> + <item label="conf-7525"></item> + <vocabulary valueSet="2.16.840.1.113883.1.11.12839"></vocabulary> + </attribute> + </element> + </choice> + <element name="cda:maxDoseQuantity" datatype="RTO_PQ_PQ" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.234"> + <desc language="en-US">MAY contain zero or one [0..1] maxDoseQuantity (CONF:7518).</desc> + <item label="conf-7518"></item> + </element> + <element name="cda:administrationUnitCode" datatype="CE" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.235"> + <desc language="en-US"><span style="font-family: Arial, Helvetica, Geneva, sans-serif; font-size: 12px;">MAY contain zero or one [0..1] administrationUnitCode, which SHALL be selected from ValueSet AdministrationUnitDoseForm 2.16.840.1.113762.1.4.1021.30 DYNAMIC (CONF:7519).</span><br clear="none" /> + </desc> + <item label="conf-7519"></item> + <vocabulary valueSet="2.16.840.1.113762.1.4.1021.30" flexibility="dynamic"></vocabulary> + </element> + <element name="cda:consumable" contains="2.16.840.1.113883.10.20.22.4.23" flexibility="2013-01-31T00:00:00" minimumMultiplicity="1" maximumMultiplicity="1" conformance="R" isMandatory="false" id="2.16.840.1.113883.3.1937.99.3.9.236"> + <item label="conf-7520"></item> + </element> + <element name="cda:performer" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.237"> + <desc language="en-US">MAY contain zero or one [0..1] performer (CONF:7522).</desc> + <item label="conf-7522"></item> + </element> + <element name="cda:participant" contains="2.16.840.1.113883.10.20.22.4.24" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.238"> + <item label="conf-7523"></item> + <attribute name="typeCode" value="CSM" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.239"> + <item label="conf-7524"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.19" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.240"> + <item label="conf-7536"></item> + <attribute name="typeCode" value="RSON" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.241"> + <item label="conf-7537"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.20" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.242"> + <item label="conf-7539"></item> + <attribute name="typeCode" value="SUBJ" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.243"> + <item label="conf-7540"></item> + </attribute> + <attribute name="inversionInd" value="true" datatype="bl" id="2.16.840.1.113883.3.1937.99.3.9.244"> + <item label="conf-7542"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.17" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.245"> + <item label="conf-7543"></item> + <attribute name="typeCode" value="REFR" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.246"> + <item label="conf-7547"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.18" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.247"> + <item label="conf-7549"></item> + <attribute name="typeCode" value="REFR" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.248"> + <item label="conf-7553"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.9" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.249"> + <item label="conf-7552"></item> + <attribute name="typeCode" value="CAUS" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.250"> + <item label="conf-7544"></item> + </attribute> + </element> + <element name="cda:entryRelationship" contains="2.16.840.1.113883.10.20.22.4.147" flexibility="2015-08-13T00:00:00" minimumMultiplicity="0" maximumMultiplicity="1" id="2.16.840.1.113883.3.1937.99.3.9.5846"> + <attribute name="typeCode" value="COMP" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.5847"> + <item label="conf-32908"> + <desc language="en-US">SHALL contain exactly one [1..1] @typeCode="COMP" Has component (CodeSystem: HL7ActRelationshipType urn:oid:2.16.840.1.113883.5.1002) (CONF:32908).<br clear="none" /> + </desc> + </item> + </attribute> + </element> + <element name="cda:precondition" contains="2.16.840.1.113883.10.20.22.4.25" flexibility="2013-01-31T00:00:00" minimumMultiplicity="0" maximumMultiplicity="*" id="2.16.840.1.113883.3.1937.99.3.9.5848"> + <item label="conf-7546"></item> + <attribute name="typeCode" value="PRCN" datatype="cs" id="2.16.840.1.113883.3.1937.99.3.9.5849"> + <item label="conf-7550"></item> + </attribute> + </element> + </element> + </template> + </rules> +</decor> \ No newline at end of file diff --git a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/AssertUtil.java b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/AssertUtil.java index 3746ae407d91da80b08cb53417aa0f50a9797fdb..1dfe7b0712f32f9a9e329828945e3269dbf0bd5c 100644 --- a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/AssertUtil.java +++ b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/AssertUtil.java @@ -120,6 +120,7 @@ public final class AssertUtil { String[] splitInnerXPATH = innerXPATH.split(" "); XPATHOCLGroup group = new XPATHOCLGroup(); for(int j=0;j<splitInnerXPATH.length;j+=2){ + splitInnerXPATH[j] = splitInnerXPATH[j].replaceAll("\\(?\\)?",""); XPATHOCLRule rule; String operationString = j!=splitInnerXPATH.length-1?splitInnerXPATH[j+1]:""; if(splitInnerXPATH[j].contains("@xsi:type")){ diff --git a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionDistinguisherUtil.java b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionDistinguisherUtil.java index caec88c0af48ad234f69baef2d035779c71fb71e..0b64f697efeb18bd67d545402c8d276baaa4afc3 100644 --- a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionDistinguisherUtil.java +++ b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionDistinguisherUtil.java @@ -10,10 +10,8 @@ import net.ihe.gazelle.tempmodel.org.decor.art.model.TemplateDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import javax.xml.namespace.QName; +import java.util.*; import java.util.Map.Entry; /** @@ -123,4 +121,14 @@ public class RuleDefinitionDistinguisherUtil { return null; } + public static Boolean elementsShouldBeDistinguisedWithDT(ChoiceDefinition choiceDefinition){ + Set<String> names = new HashSet<>(); + int count = 0; + for(RuleDefinition rd : ChoiceDefinitionUtil.getElements(choiceDefinition)){ + names.add(RuleDefinitionUtil.getRealNameOfRuleDefinition(rd)); + count++; + } + return Boolean.valueOf(names.size() != count); + } + } diff --git a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionProblemUtil.java b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionProblemUtil.java index 23ed8127da0dfb326302f14c9cbbefd823c1012d..8ac4639165bdc379c8b0bf8facb43ccbb5f72da5 100644 --- a/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionProblemUtil.java +++ b/hl7templates/hl7templates-model-jar/src/main/java/net/ihe/gazelle/tempmodel/org/decor/art/utils/RuleDefinitionProblemUtil.java @@ -9,9 +9,12 @@ import net.ihe.gazelle.tempmodel.org.decor.art.model.TemplateDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.xml.namespace.QName; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; /** * @author Abderrazek Boufahja @@ -89,19 +92,31 @@ public class RuleDefinitionProblemUtil { if (parent instanceof TemplateDefinition) { List<RuleDefinition> lrd = TemplateDefinitionUtil.getElementsByName((TemplateDefinition) parent, RuleDefinitionUtil.getRealNameOfRuleDefinition(ruleDefinition)); - return lrd.size() == 1; + Set<QName> datatypes = new HashSet<>(); + for(RuleDefinition rd : lrd){ + datatypes.add(rd.getDatatype()); + } + return lrd.size() == datatypes.size(); } else if (parent instanceof RuleDefinition) { RuleDefinition parentRD = (RuleDefinition) parent; List<RuleDefinition> lrd = RuleDefinitionUtil.getElementsByName(parentRD, RuleDefinitionUtil.getRealNameOfRuleDefinition(ruleDefinition)); - return lrd.size() == 1; + Set<QName> datatypes = new HashSet<>(); + for(RuleDefinition rd : lrd){ + datatypes.add(rd.getDatatype()); + } + return lrd.size() == datatypes.size(); } else if (parent instanceof ChoiceDefinition) { ChoiceDefinition choiceDefinition = (ChoiceDefinition) parent; if (choiceDefinition.getParentObject() instanceof RuleDefinition) { RuleDefinition parentOfChoice = (RuleDefinition) choiceDefinition.getParentObject(); List<RuleDefinition> lrd = RuleDefinitionUtil.getElementsByName(parentOfChoice, RuleDefinitionUtil.getRealNameOfRuleDefinition(ruleDefinition)); - return lrd.size() == 1; + Set<QName> datatypes = new HashSet<>(); + for(RuleDefinition rd : lrd){ + datatypes.add(rd.getDatatype()); + } + return lrd.size() == datatypes.size(); } } return false; diff --git a/hl7templates/hl7templates-packager-jar/pom.xml b/hl7templates/hl7templates-packager-jar/pom.xml index e5023e7d8280acd7c30dd0df79e97727152ca29e..551d29c005647a2fb8eafcea0cd5187eda71fe35 100644 --- a/hl7templates/hl7templates-packager-jar/pom.xml +++ b/hl7templates/hl7templates-packager-jar/pom.xml @@ -193,12 +193,12 @@ <dependency> <groupId>net.ihe.gazelle.model</groupId> <artifactId>cda-model</artifactId> - <version>3.0.0</version> + <version>3.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>net.ihe.gazelle.model</groupId> <artifactId>cdaepsos-model</artifactId> - <version>3.0.0</version> + <version>3.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/GOCExecutor.java b/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/GOCExecutor.java index a8b89d23ee7cd3203a303d3588094d0a3f259d09..ca02c2b4608cafd0d00e0d1adfba4cb69325418b 100644 --- a/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/GOCExecutor.java +++ b/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/GOCExecutor.java @@ -21,14 +21,12 @@ public class GOCExecutor { private String hl7Resources; - private String hl7Conf; private static final SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss"); - public GOCExecutor(String outputFile, String hl7Resources, String hl7Conf) { + public GOCExecutor(String outputFile, String hl7Resources) { this.outputFile = outputFile; this.hl7Resources = hl7Resources; - this.hl7Conf = hl7Conf; } public GOCExecutor(String outputFile){ @@ -36,12 +34,12 @@ public class GOCExecutor { } public ValidatorConfiguration execute(BBRResource bbrResource, String mvnExecPath){ - return execute(bbrResource,mvnExecPath,null,true,false,null,false); + return execute(bbrResource,mvnExecPath,null,true,false,null,false,null); } public ValidatorConfiguration execute(BBRResource bbrResource,String mvnExecPath, String versionLabel, Boolean ignoreTemplateIdRequirements, - Boolean ignoreCdaBasicRequirements, String serviceName,Boolean ignoreChoicesPredicates) { + Boolean ignoreCdaBasicRequirements, String serviceName,Boolean ignoreChoicesPredicates, String hl7Conf) { try{ addSubDirectoryToOutput("/validator"); @@ -61,9 +59,9 @@ public class GOCExecutor { this.hl7Resources = this.hl7Resources==null? getWorkspaceRoot()+"/hl7templates-resources":this.hl7Resources; - this.hl7Conf = this.hl7Conf == null ? "cdabasic":this.hl7Conf; + String HL7ConfFolder = (hl7Conf == null) ? "cdabasic":hl7Conf; - EnvironementConfiguration.setSystemVariables("HL7TEMP_CDACONFFOLDERNAME",hl7Conf, + EnvironementConfiguration.setSystemVariables("HL7TEMP_CDACONFFOLDERNAME",HL7ConfFolder, "HL7TEMP_RESOURCES_PATH",this.hl7Resources,"JAVA_EXEC",System.getProperty("java.home")+"/bin/java"); EnvironementConfiguration.configure(); diff --git a/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/HL7Templates2GOC.java b/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/HL7Templates2GOC.java index 19290a789a079d99a85a2a4624dbe64b7d737511..5c744d9bb1c7c51d467b6bb6ccea661279cabaeb 100644 --- a/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/HL7Templates2GOC.java +++ b/hl7templates/hl7templates-packager-jar/src/main/java/net/ihe/gazelle/lib/hl7templatespackager/peripherals/HL7Templates2GOC.java @@ -201,9 +201,9 @@ public class HL7Templates2GOC implements GOCEntry { try { parser.parseArgument(args); - GOCExecutor gocExecutor = new GOCExecutor(outputFile, HL7TEMP_RESOURCES_PATH,HL7TEMP_CDACONFFOLDERNAME); + GOCExecutor gocExecutor = new GOCExecutor(outputFile, HL7TEMP_RESOURCES_PATH); gocExecutor.execute(new PathBBRResource(bbr),mvnExecPath,versionLabel, - ignoreTemplateIdRequirements,ignoreCdaBasicRequirements, serviceName,ignoreChoicesPredicates); + ignoreTemplateIdRequirements,ignoreCdaBasicRequirements, serviceName,ignoreChoicesPredicates, HL7TEMP_CDACONFFOLDERNAME); } catch (CmdLineException e) { System.err.println("Exception in the execution of command line");