various minor fixes for IG publication

This commit is contained in:
Grahame Grieve 2019-07-31 14:44:38 +10:00
parent f5b5737398
commit a234984179
19 changed files with 16795 additions and 30 deletions

View File

@ -582,7 +582,8 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition currentBase = base.getElement().get(baseCursor);
String cpath = fixedPathSource(contextPathSrc, currentBase.getPath(), redirector);
if (debug)
System.out.println(indent+" - "+cpath+": base = "+baseCursor+" to "+baseLimit+", diff = "+diffCursor+" to "+diffLimit+" (slicingDone = "+slicingDone+") (diffpath= "+(differential.getElement().size() > diffCursor ? differential.getElement().get(diffCursor).getPath() : "n/a")+")");
System.out.println(indent+" - "+cpath+": base = "+baseCursor+" ("+descED(base.getElement(),baseCursor)+") to "+baseLimit+" ("+descED(base.getElement(),baseLimit)+"), diff = "+diffCursor+" ("+descED(differential.getElement(),diffCursor)+") to "+diffLimit+" ("+descED(differential.getElement(),diffLimit)+") "+
"(slicingDone = "+slicingDone+") (diffpath= "+(differential.getElement().size() > diffCursor ? differential.getElement().get(diffCursor).getPath() : "n/a")+")");
List<ElementDefinition> diffMatches = getDiffMatches(differential, cpath, diffCursor, diffLimit, profileName); // get a list of matching elements in scope
// in the simple case, source is not sliced.
@ -737,6 +738,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int start = 0;
int nbl = findEndOfElement(base, baseCursor);
int ndc = differential.getElement().indexOf(diffMatches.get(0));
ElementDefinition elementToRemove = null;
// we come here whether they are sliced in the diff, or whether the short cut is used.
if (typeList.get(0).type != null) {
// this is the short cut method, we've just dived in and specified a type slice.
@ -753,6 +755,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ed.getSlicing().setOrdered(false);
diffMatches.add(0, ed);
differential.getElement().add(ndc, ed);
elementToRemove = ed;
} else {
// as of R4, this changed; if there's no slice, there's no constraint on the slice types, only one the type.
// so the element we insert specifies no types (= all types) allowed in the base, not just the listed type.
@ -765,7 +768,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ed.getSlicing().setOrdered(false);
diffMatches.add(0, ed);
differential.getElement().add(ndc, ed);
elementToRemove = ed;
}
}
int ndl = findEndOfElement(differential, ndc);
@ -815,6 +818,11 @@ public class ProfileUtilities extends TranslatingUtilities {
ndl = findEndOfElement(differential, ndc);
processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, redirector, srcSD);
}
if (elementToRemove != null) {
differential.getElement().remove(elementToRemove);
ndl--;
}
// ok, done with that - next in the base list
baseCursor = nbl+1;
diffCursor = ndl+1;
@ -1086,6 +1094,11 @@ public class ProfileUtilities extends TranslatingUtilities {
}
private String descED(List<ElementDefinition> list, int index) {
return index >=0 && index < list.size() ? list.get(index).present() : "X";
}
private boolean baseHasChildren(StructureDefinitionSnapshotComponent base, ElementDefinition ed) {
int index = base.getElement().indexOf(ed);
if (index == -1 || index >= base.getElement().size()-1)
@ -1551,17 +1564,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (int i = start; i <= end; i++) {
String statedPath = context.getElement().get(i).getPath();
if (statedPath.startsWith(path+".")) {
boolean found = false;
// GG - I don't know what this code is doing....
// for (ElementDefinition ed : base) {
// String ep = ed.getPath();
// if (ep.equals(statedPath) || (ep.endsWith("[x]") && statedPath.length() > ep.length() - 2 && statedPath.substring(0, ep.length()-3).equals(ep.substring(0, ep.length()-3)) && !statedPath.substring(ep.length()).contains("."))) {
// found = true;
// break;
// }
// }
if (!found)
return true;
return true;
}
}
return false;
@ -2196,6 +2199,8 @@ public class ProfileUtilities extends TranslatingUtilities {
private static final int AGG_NONE = 0;
private static final int AGG_IND = 1;
private static final int AGG_GR = 2;
private static final boolean TABLE_FORMAT_FOR_FIXED_VALUES = false;
private Cell genTypes(HierarchicalTableGenerator gen, Row r, ElementDefinition e, String profileBaseFileName, StructureDefinition profile, String corePath, String imagePath) {
Cell c = gen.new Cell();
r.getCells().add(c);
@ -2898,7 +2903,13 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (definition.hasPattern()) {
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, translate("sd.table", "Required Pattern")+": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
if (!TABLE_FORMAT_FOR_FIXED_VALUES || definition.getPattern().isPrimitive())
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
else {
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, "TODO", null).addStyle("color: darkgreen")));
genFixedValue(gen, row, definition.getPattern());
}
} else if (definition.hasExample()) {
for (ElementDefinitionExampleComponent ex : definition.getExample()) {
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
@ -2933,6 +2944,44 @@ public class ProfileUtilities extends TranslatingUtilities {
return c;
}
private void genFixedValue(HierarchicalTableGenerator gen, Row erow, Type value) {
for (org.hl7.fhir.r5.model.Property t : value.children()) {
if (t.hasValues()) {
for (Base b : t.getValues()) {
Row row = gen.new Row();
erow.getSubRows().add(row);
Cell c = gen.new Cell();
row.getCells().add(c);
c.addPiece(gen.new Piece(t.getName()));
c = gen.new Cell();
row.getCells().add(c);
c.addPiece(gen.new Piece("P"));
c = gen.new Cell();
row.getCells().add(c);
c.addPiece(gen.new Piece("1..1"));
c = gen.new Cell();
row.getCells().add(c);
c.addPiece(gen.new Piece(b.fhirType()));
if (b.isPrimitive()) {
c = gen.new Cell();
row.getCells().add(c);
c.addPiece(gen.new Piece(b.primitiveValue()));
} else {
c = gen.new Cell();
row.getCells().add(c);
}
}
}
}
}
private String getFixedUrl(StructureDefinition sd) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().equals("Extension.url")) {

View File

@ -578,7 +578,10 @@ public class Element extends Base {
@Override
public boolean isEmpty() {
if (value != null && !"".equals(value)) {
// GG: this used to also test !"".equals(value).
// the condition where "" is empty and there are no children is an error, and so this really only manifested as an issue in corner cases technical testing of the validator / FHIRPath.
// it should not cause any problems in real life.
if (value != null) {
return false;
}
for (Element next : getChildren()) {

View File

@ -7527,6 +7527,10 @@ When pattern[x] is used to constrain a complex object, it means that each proper
setIsModifier(modifier);
setIsSummary(inSummary);
}
}
public String present() {
return hasId() ? getId() : getPath();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="au1"/>
<url value="http://ns.electronichealth.net.au/ci/fhir/4.0/StructureDefinition/practitioner-dh-base-1"/>
<version value="1.0.0"/>
<name value="PractitionerBase"/>
<title value="Base Practitioner"/>
<status value="draft"/>
<experimental value="true"/>
<date value="2019-07-29T13:05:59+10:00"/>
<publisher value="Australian Digital Health Agency"/>
<contact>
<telecom>
<system value="email"/>
<value value="help@digitalhealth.gov.au"/>
</telecom>
</contact>
<description value="The purpose of this profile is to provide a base model for the concept of a practitioner, defining fundamental concepts that form a conforming representation of a practitioner. It is used as a base model from which to further derive models for specific usage scenarios in an Australian context and where it is desirable to provide some constraint to support unique identification of the practitioner.&#xD;&#xA;&#xD;&#xA;#### Must Support&#xA;&#xA;In the context of this profile [Must Support](http://hl7.org/fhir/R4/conformance-rules.html#mustSupport) SHALL be interpreted as follows:&#xA;&#xA;* The system SHALL be able to include the element when authoring a resource where data is available&#xA;&#xA;* The system SHALL be able to store and retrieve the element&#xA;&#xA;* The system SHALL be able to process resources containing the element"/>
<copyright value="Copyright &#xA9; 2019 Australian Digital Health Agency - All rights reserved. This content is licensed under a Creative Commons Attribution 4.0 International License. See https://creativecommons.org/licenses/by/4.0/."/>
<fhirVersion value="4.0.0"/>
<mapping>
<identity value="v2"/>
<uri value="http://hl7.org/v2"/>
<name value="HL7 v2 Mapping"/>
</mapping>
<mapping>
<identity value="rim"/>
<uri value="http://hl7.org/v3"/>
<name value="RIM Mapping"/>
</mapping>
<mapping>
<identity value="servd"/>
<uri value="http://www.omg.org/spec/ServD/1.0/"/>
<name value="ServD"/>
</mapping>
<mapping>
<identity value="w5"/>
<uri value="http://hl7.org/fhir/fivews"/>
<name value="FiveWs Pattern Mapping"/>
</mapping>
<kind value="resource"/>
<abstract value="false"/>
<type value="Practitioner"/>
<baseDefinition value="http://hl7.org.au/fhir/StructureDefinition/au-practitioner"/>
<derivation value="constraint"/>
<differential>
<element id="Practitioner">
<extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status">
<valueCode value="trial-use"/>
</extension>
<path value="Practitioner"/>
<constraint>
<key value="inv-dh-prac-01"/>
<severity value="error"/>
<human value="The practitioner shall at least have an identifier or a name"/>
<expression value="Practitioner.identifier.exists() or Practitioner.name.exists()"/>
</constraint>
</element>
<element id="Practitioner.identifier">
<path value="Practitioner.identifier"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.identifier:employeeNumber">
<path value="Practitioner.identifier"/>
<sliceName value="employeeNumber"/>
<short value="Employee Number"/>
</element>
<element id="Practitioner.identifier:employeeNumber.type">
<path value="Practitioner.identifier.type"/>
<short value="Employee number type"/>
<min value="1"/>
<patternCodeableConcept>
<coding>
<system value="http://terminology.hl7.org/CodeSystem/v2-0203"/>
<code value="EI"/>
</coding>
</patternCodeableConcept>
<binding>
<strength value="required"/>
<valueSet value="http://terminology.hl7.org/ValueSet/v2-0203"/>
</binding>
</element>
<element id="Practitioner.identifier:employeeNumber.system">
<path value="Practitioner.identifier.system"/>
<short value="Namespace for employee number"/>
<min value="1"/>
<example>
<label value="Example 1"/>
<valueUri value="https://territorymedicalcentre.example.com/provider"/>
</example>
<example>
<label value="Example 2"/>
<valueUri value="http://ns.electronichealth.net.au/id/abn-scoped/service-provider-individual/1.0/51824753556"/>
</example>
</element>
<element id="Practitioner.identifier:employeeNumber.value">
<path value="Practitioner.identifier.value"/>
<short value="Employee number"/>
<min value="1"/>
<example>
<label value="Example 1"/>
<valueString value="frankburns27"/>
</example>
</element>
<element id="Practitioner.active">
<path value="Practitioner.active"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.name">
<path value="Practitioner.name"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.telecom">
<path value="Practitioner.telecom"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.address">
<path value="Practitioner.address"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.gender">
<path value="Practitioner.gender"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.birthDate">
<path value="Practitioner.birthDate"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.photo">
<path value="Practitioner.photo"/>
<max value="0"/>
</element>
<element id="Practitioner.qualification">
<path value="Practitioner.qualification"/>
<mustSupport value="true"/>
</element>
<element id="Practitioner.qualification.identifier">
<path value="Practitioner.qualification.identifier"/>
<min value="0"/>
<max value="*"/>
<type>
<code value="Identifier"/>
</type>
<mustSupport value="true"/>
</element>
<element id="Practitioner.qualification.code">
<path value="Practitioner.qualification.code"/>
<min value="1"/>
<max value="1"/>
<type>
<code value="CodeableConcept"/>
</type>
<mustSupport value="true"/>
</element>
<element id="Practitioner.qualification.period">
<path value="Practitioner.qualification.period"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Period"/>
</type>
<mustSupport value="true"/>
</element>
<element id="Practitioner.qualification.issuer">
<path value="Practitioner.qualification.issuer"/>
<min value="0"/>
<max value="1"/>
<type>
<code value="Reference"/>
<targetProfile value="http://ns.electronichealth.net.au/ci/fhir/4.0/StructureDefinition/organization-dh-base-1"/>
</type>
<constraint>
<key value="inv-dh-prac-02"/>
<severity value="error"/>
<human value="This reference shall at least have a reference, an identifier or a display"/>
<expression value="reference.exists() or identifier.exists() or display.exists()"/>
</constraint>
<mustSupport value="true"/>
</element>
<element id="Practitioner.communication">
<path value="Practitioner.communication"/>
<mustSupport value="true"/>
</element>
</differential>
</StructureDefinition>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="au-receivingfacility" />
<url value="http://hl7.org.au/fhir/StructureDefinition/au-receivingfacility" />
<version value="2.0.0" />
<name value="HL7V2ReceivingFacility" />
<title value="HL7 V2 Receiving Facility" />
<status value="active" />
<date value="2019-07-24" />
<publisher value="Health Level Seven Australia (Patient Administration WG)" />
<contact>
<telecom>
<system value="url" />
<value value="http://hl7.org.au" />
<use value="work" />
</telecom>
</contact>
<description value="This extension defines a HL7v2 receiving facility value for HL7v2 routing purposes associated with an endpoint." />
<fhirVersion value="4.0.0" />
<kind value="complex-type" />
<abstract value="false" />
<context>
<type value="element" />
<expression value="Endpoint" />
</context>
<type value="Extension" />
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension" />
<derivation value="constraint" />
<differential>
<element id="Extension"> <!-- 0 -->
<path value="Extension" />
<short value="HL7 V2 receiving facility" />
<definition value="Values for routing HLV2 message payloads associated with an endpoint, suitable for MSH-6" />
</element>
<element id="Extension.extension"> <!-- 1 -->
<path value="Extension.extension" />
<slicing>
<discriminator>
<type value="value" />
<path value="url" />
</discriminator>
<rules value="open" />
</slicing>
</element>
<element id="Extension.extension:namespace-id"> <!-- 2 -->
<path value="Extension.extension" />
<sliceName value="namespace-id" />
<short value="Application Identifier" />
<max value="1" />
</element>
<element id="Extension.extension:namespace-id.url"> <!-- 3 -->
<path value="Extension.extension.url"/>
<type>
<code value="uri"/>
</type>
<fixedUri value="namespace-id"/>
</element>
<element id="Extension.extension:namespace-id.value[x]:valueString"> <!-- 4 -->
<path value="Extension.extension.valueString" />
<sliceName value="valueString" />
<type>
<code value="string" />
</type>
</element>
<element id="Extension.extension:universal-id"> <!-- 5 -->
<path value="Extension.extension" />
<sliceName value="universal-id" />
<short value="Universal Identifier Value" />
<definition value="Identifier values follwing the universal-id-type defined scheme." />
<max value="1" />
</element>
<element id="Extension.extension:universal-id.url"> <!-- 6 -->
<path value="Extension.extension.url"/>
<type>
<code value="uri"/>
</type>
<fixedUri value="universal-id"/>
</element>
<element id="Extension.extension:universal-id.value[x]:valueString"> <!-- 7 -->
<path value="Extension.extension.valueString" />
<sliceName value="valueString" />
<type>
<code value="string" />
</type>
</element>
<element id="Extension.extension:universal-id-type"> <!-- 8 -->
<path value="Extension.extension" />
<sliceName value="universal-id-type" />
<short value="Type Scheme of universal-id" />
<definition value="Provides scheme to use to interpret the universal-id value .e.g. GUID, ISO etc. see HL7 V2 Table 0301 - Universal ID type." />
<max value="1" />
</element>
<element id="Extension.extension:universal-id-type.url"> <!-- 9 -->
<path value="Extension.extension.url"/>
<type>
<code value="uri"/>
</type>
<fixedUri value="universal-id-type"/>
</element>
<element id="Extension.extension:universal-id-type.value[x]:valueString"> <!-- 10 -->
<path value="Extension.extension.valueString" />
<sliceName value="valueString" />
<type>
<code value="string" />
</type>
</element>
<element id="Extension.value[x]"> <!-- 11 -->
<path value="Extension.value[x]" />
<min value="0" />
<max value="0" />
</element>
</differential>
</StructureDefinition>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
{
"resourceType": "StructureDefinition",
"id": "ncdhc-observation-base",
"url": "http://hl7.org.au/fhir/ch/v1/StructureDefinition/ncdhc-observation-base",
"version": "v1.0.0",
"name": "NCDHC Observation Base Profile",
"title": "NCDHC Observation Base",
"status": "draft",
"date": "2019-03-01",
"publisher": "National Children's Digital Health Collaborative (NCDHC)",
"description": "Define a bsae profile for NCDHC Observation",
"purpose": "To define NCDHC base profile",
"fhirVersion": "3.0.1",
"kind": "resource",
"abstract": true,
"type": "Observation",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Observation",
"derivation": "constraint",
"differential": {
"element": [
{
"id": "Observation",
"path": "Observation",
"short": "NCDHC Observation Base Profile",
"constraint": [
{
"key": "ncdhc-obs-1",
"severity": "error",
"human": "If there is no component or related element then either a value[x] or a data absent reason must be present",
"expression": "(component.empty() and related.empty()) implies (dataAbsentReason or value)",
"xpath": "exists(f:component) or exists(f:related) or exists(f:*[starts-with(local-name(.), 'value')]) or exists(f:dataAbsentReason)"
}
]
},
{
"id": "Observation.status",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint",
"valueString": "default: final"
}
],
"path": "Observation.status",
"mustSupport": true
},
{
"id": "Observation.category",
"path": "Observation.category",
"comment": "In addition to the required category valueset, this element allows various categorization schemes based on the owners definition of the category and effectively multiple categories can be used at once. The level of granularity is defined by the category concepts in the value set.\r\n\r\nCWG: Discussion on the Category to match it with Composition.type",
"max": "1",
"mustSupport": true,
"binding": {
"strength": "required",
"description": "Codes for high level observation categories. This is mainly used to associate an Observation instance to a particular Health Interaction (as applicable)",
"valueSetReference": {
"reference": "http://hl7.org.au/fhir/ch/v1/ValueSet/ncdhc-observation-category"
}
}
},
{
"id": "Observation.subject",
"path": "Observation.subject",
"min": 1,
"type": [
{
"code": "Reference",
"targetProfile": ["http://hl7.org.au/fhir/ch/v1/StructureDefinition/ncdhc-patient-baby"]
}
],
"mustSupport": true
},
{
"id": "Observation.effective[x]:effectiveDateTime",
"path": "Observation.effectiveDateTime",
"sliceName": "effectiveDateTime",
"type": [
{
"code": "dateTime"
}
],
"mustSupport": true
},
{
"id": "Observation.performer",
"path": "Observation.performer",
"slicing": {
"discriminator": [
{
"type": "value",
"path": "display"
}
],
"rules": "open"
},
"min": 1,
"type": [
{
"code": "Reference",
"targetProfile": ["http://hl7.org.au/fhir/StructureDefinition/au-practitioner"]
}
]
},
{
"id": "Observation.performer:Examiner",
"path": "Observation.performer",
"sliceName": "Examiner",
"short": "Person who is clinically responsible for the undertaking of the exam",
"min": 1,
"max": "1",
"type": [
{
"code": "Reference",
"targetProfile": ["http://hl7.org.au/fhir/StructureDefinition/au-practitioner"]
}
]
},
{
"id": "Observation.performer:Examiner.display",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable",
"valueBoolean": true
}
],
"path": "Observation.performer.display",
"fixedString": "Examiner"
},
{
"id": "Observation.performer:Organisation",
"path": "Observation.performer",
"sliceName": "Organisation",
"short": "An organisation which captures the relevant details",
"min": 1,
"max": "1",
"type": [
{
"code": "Reference",
"targetProfile": ["http://hl7.org.au/fhir/StructureDefinition/au-organisation"]
}
]
},
{
"id": "Observation.performer:Organisation.display",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable",
"valueBoolean": true
}
],
"path": "Observation.performer.display",
"fixedString": "Organisation"
},
{
"id": "Observation.dataAbsentReason",
"path": "Observation.dataAbsentReason",
"mustSupport": true
}
]
}
}

View File

@ -220,8 +220,8 @@
<rule text="The element definition for value[x] quantity slice should have sliceName = 'Quantity'" fhirpath="fixture('t44-output').snapshot.element.where(id = 'Observation.value[x]:valueQuantity').check(exists(), 'no slice').sliceName = 'valueQuantity'"/>
<rule text="The element definition for value[x].value quantity slice should have sliceName = 'Quantity'" fhirpath="fixture('t44-output').snapshot.element.where(id = 'Observation.value[x]:valueQuantity.value').check(exists(), 'no slice').min = 1"/>
</test>
<test gen="true" id="samply1">
</test>
<test gen="true" id="au1" include="au1a">
</test>
<test gen="true" id="samply1"/>
<test gen="true" id="au1" include="au1a"/>
<test gen="true" id="au2"/>
<test gen="true" id="au3"/>
</snapshot-generation-tests>

View File

@ -43,12 +43,12 @@ public class CodeSystemValidator extends BaseValidator {
private void checkCodesUnique(CodeSystem cs, List<ValidationMessage> errors) {
Set<String> codes = new HashSet<String>();
checkCodes(codes, cs.getConcept(), "CodeSystem["+cs.getId()+"]", errors);
checkCodes(codes, cs.getConcept(), "CodeSystem.where(id = '"+cs.getId()+"')", errors);
}
private void checkCodes(Set<String> codes, List<ConceptDefinitionComponent> list, String path, List<ValidationMessage> errors) {
for (ConceptDefinitionComponent cc : list) {
String npath = path+".concept["+cc.getCode()+"]";
String npath = path+".concept.descendents().where(code = '"+cc.getCode()+"')";
rule(errors, IssueType.BUSINESSRULE, npath, !codes.contains(cc.getCode()), "Duplicate Code "+cc.getCode());
codes.add(cc.getCode());
checkCodes(codes, cc.getConcept(), npath, errors);

View File

@ -43,17 +43,15 @@ public class CodeSystemValidator extends BaseValidator {
private void checkCodesUnique(CodeSystem cs, List<ValidationMessage> errors) {
Set<String> codes = new HashSet<String>();
checkCodes(codes, cs.getConcept(), "CodeSystem["+cs.getId()+"]", errors);
checkCodes(codes, cs.getConcept(), "CodeSystem.where(id = '"+cs.getId()+"')", errors);
}
private void checkCodes(Set<String> codes, List<ConceptDefinitionComponent> list, String path, List<ValidationMessage> errors) {
for (ConceptDefinitionComponent cc : list) {
String npath = path+".concept["+cc.getCode()+"]";
String npath = path+".concept.descendents().where(code = '"+cc.getCode()+"')";
rule(errors, IssueType.BUSINESSRULE, npath, !codes.contains(cc.getCode()), "Duplicate Code "+cc.getCode());
codes.add(cc.getCode());
checkCodes(codes, cc.getConcept(), npath, errors);
}
}
}

View File

@ -196,11 +196,11 @@
"errorCount": 0
},
"primitive-bad.xml": {
"errorCount": 47,
"errorCount": 45,
"warningCount": 2
},
"primitive-bad-empty.xml": {
"errorCount": 3
"errorCount": 2
},
"group-choice-bad1.xml": {
"errorCount": 2,

View File

@ -21,7 +21,7 @@
<type value="profile"/>
<path value="item.resolve()"/>
</discriminator>
<ordered vale="false"/>
<ordered value="false"/>
<rules value="closed"/>
</slicing>
</element>

View File

@ -21,7 +21,7 @@
<type value="profile"/>
<path value="item.resolve()"/>
</discriminator>
<ordered vale="false"/>
<ordered value="false"/>
<rules value="open"/>
</slicing>
</element>

View File

@ -21,7 +21,7 @@
<type value="profile"/>
<path value="item.resolve()"/>
</discriminator>
<ordered vale="true"/>
<ordered value="true"/>
<rules value="open"/>
</slicing>
</element>