diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f06afc3b9..2eec9b92e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,9 +1,18 @@ ## Validator Changes -* alter per-1 to handle different precision on start/end +* Significant improvement in performance of validation (10-100 fold for simple resources) +* Add output tracker to trask progress of validation (Validate %R against %P..........20..........40..........60..........80.........|) +* Alter per-1 to handle different precision on start/end * Add support for a -jurisdiction parameter, preparing for jurisdictionally specific constraints in profiles +* Fix bug in snapshot generation where type slices on a mandatory element were all marked as mandatory +* Add warnings when potential matches are found when performing reference resolution in bundles ## Other code changes * extend FHIRPath to support lowBoundary(), highBoundary() and precision() * Fix for inefficiency in StructureMap engine +* Update version of PubPack used by the IGPublisher +* Handle scope on TestScript R4 <-> r5 conversion +* Fix bug converting extension context = Resource (R4 <-> R5 conversion) +* Update VSAC importer for changes to VSAC FHIR authorization +* Fix broken links in profile comparison due to cross version issues \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/StructureDefinition30_40.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/StructureDefinition30_40.java index bbe92498b..dc7719a74 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/StructureDefinition30_40.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/StructureDefinition30_40.java @@ -356,6 +356,6 @@ public class StructureDefinition30_40 { } static public boolean isResource300(String tn) { - return Utilities.existsInList(tn, "Account", "ActivityDefinition", "AllergyIntolerance", "AdverseEvent", "Appointment", "AppointmentResponse", "AuditEvent", "Basic", "Binary", "BodySite", "Bundle", "CapabilityStatement", "CarePlan", "CareTeam", "ChargeItem", "Claim", "ClaimResponse", "ClinicalImpression", "CodeSystem", "Communication", "CommunicationRequest", "CompartmentDefinition", "Composition", "ConceptMap", "Condition", "Consent", "Contract", "Coverage", "DataElement", "DetectedIssue", "Device", "DeviceComponent", "DeviceMetric", "DeviceRequest", "DeviceUseStatement", "DiagnosticReport", "DocumentManifest", "DocumentReference", "EligibilityRequest", "EligibilityResponse", "Encounter", "Endpoint", "EnrollmentRequest", "EnrollmentResponse", "EpisodeOfCare", "ExpansionProfile", "ExplanationOfBenefit", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "GuidanceResponse", "HealthcareService", "ImagingManifest", "ImagingStudy", "Immunization", "ImmunizationRecommendation", "ImplementationGuide", "Library", "Linkage", "List", "Location", "Measure", "MeasureReport", "Media", "Medication", "MedicationAdministration", "MedicationDispense", "MedicationRequest", "MedicationStatement", "MessageDefinition", "MessageHeader", "NamingSystem", "NutritionOrder", "Observation", "OperationDefinition", "OperationOutcome", "Organization", "Parameters", "Patient", "PaymentNotice", "PaymentReconciliation", "Person", "PlanDefinition", "Practitioner", "PractitionerRole", "Procedure", "ProcedureRequest", "ProcessRequest", "ProcessResponse", "Provenance", "Questionnaire", "QuestionnaireResponse", "ReferralRequest", "RelatedPerson", "RequestGroup", "ResearchStudy", "ResearchSubject", "RiskAssessment", "Schedule", "SearchParameter", "Sequence", "ServiceDefinition", "Slot", "Specimen", "StructureDefinition", "StructureMap", "Subscription", "Substance", "SupplyDelivery", "SupplyRequest", "Task", "TestScript", "TestReport", "ValueSet", "VisionPrescription"); + return Utilities.existsInList(tn, "Resource", "DomainResource", "Account", "ActivityDefinition", "AllergyIntolerance", "AdverseEvent", "Appointment", "AppointmentResponse", "AuditEvent", "Basic", "Binary", "BodySite", "Bundle", "CapabilityStatement", "CarePlan", "CareTeam", "ChargeItem", "Claim", "ClaimResponse", "ClinicalImpression", "CodeSystem", "Communication", "CommunicationRequest", "CompartmentDefinition", "Composition", "ConceptMap", "Condition", "Consent", "Contract", "Coverage", "DataElement", "DetectedIssue", "Device", "DeviceComponent", "DeviceMetric", "DeviceRequest", "DeviceUseStatement", "DiagnosticReport", "DocumentManifest", "DocumentReference", "EligibilityRequest", "EligibilityResponse", "Encounter", "Endpoint", "EnrollmentRequest", "EnrollmentResponse", "EpisodeOfCare", "ExpansionProfile", "ExplanationOfBenefit", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "GuidanceResponse", "HealthcareService", "ImagingManifest", "ImagingStudy", "Immunization", "ImmunizationRecommendation", "ImplementationGuide", "Library", "Linkage", "List", "Location", "Measure", "MeasureReport", "Media", "Medication", "MedicationAdministration", "MedicationDispense", "MedicationRequest", "MedicationStatement", "MessageDefinition", "MessageHeader", "NamingSystem", "NutritionOrder", "Observation", "OperationDefinition", "OperationOutcome", "Organization", "Parameters", "Patient", "PaymentNotice", "PaymentReconciliation", "Person", "PlanDefinition", "Practitioner", "PractitionerRole", "Procedure", "ProcedureRequest", "ProcessRequest", "ProcessResponse", "Provenance", "Questionnaire", "QuestionnaireResponse", "ReferralRequest", "RelatedPerson", "RequestGroup", "ResearchStudy", "ResearchSubject", "RiskAssessment", "Schedule", "SearchParameter", "Sequence", "ServiceDefinition", "Slot", "Specimen", "StructureDefinition", "StructureMap", "Subscription", "Substance", "SupplyDelivery", "SupplyRequest", "Task", "TestScript", "TestReport", "ValueSet", "VisionPrescription"); } } \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java index 5e098382e..854340d9b 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/VSACImporter.java @@ -22,16 +22,16 @@ public class VSACImporter extends OIDBasedValueSetImporter { public static void main(String[] args) throws FHIRException, IOException, ParseException, URISyntaxException { VSACImporter self = new VSACImporter(); - self.process(args[0], args[1], args[2], args[3]); + self.process(args[0], args[1], args[2]); } - private void process(String source, String dest, String username, String password) throws FHIRException, IOException, URISyntaxException { + private void process(String source, String dest, String apiKey) throws FHIRException, IOException, URISyntaxException { CSVReader csv = new CSVReader(new FileInputStream(source)); csv.readHeaders(); FHIRToolingClient fhirToolingClient = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir", "fhir/vsac"); - fhirToolingClient.setUsername(username); - fhirToolingClient.setPassword(password); + fhirToolingClient.setUsername("apikey"); + fhirToolingClient.setPassword(apiKey); int i = 0; while (csv.line()) { diff --git a/org.hl7.fhir.convertors/src/test/java/org/hl7/fhir/convertors/conv30_40/Extension30_40Test.java b/org.hl7.fhir.convertors/src/test/java/org/hl7/fhir/convertors/conv30_40/Extension30_40Test.java new file mode 100644 index 000000000..2bd5e6c70 --- /dev/null +++ b/org.hl7.fhir.convertors/src/test/java/org/hl7/fhir/convertors/conv30_40/Extension30_40Test.java @@ -0,0 +1,47 @@ +package org.hl7.fhir.convertors.conv30_40; + +import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40; +import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +public class Extension30_40Test { + + private void convert(String filename) throws FHIRFormatError, IOException { + InputStream r3_input = this.getClass().getResourceAsStream("/"+filename); + + org.hl7.fhir.dstu3.model.StructureDefinition r3_source = (org.hl7.fhir.dstu3.model.StructureDefinition) new org.hl7.fhir.dstu3.formats.JsonParser().parse(r3_input); + org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_30_40.convertResource(r3_source, new BaseAdvisor_30_40(false)); + org.hl7.fhir.dstu3.model.StructureDefinition r3_roundtrip = (StructureDefinition) VersionConvertorFactory_30_40.convertResource(r4, new BaseAdvisor_30_40(false)); + + Assertions.assertTrue(r3_source.getContextType().equals(r3_roundtrip.getContextType()), + "Failed comparing " + r3_source.getContextType() + " and " + r3_roundtrip.getContextType()); + } + + @Test + public void testExtension_r3_res_base() throws IOException { + convert("extension_r3_res_base.json"); + } + + + @Test + public void testExtension_r3_res_path() throws IOException { + convert("extension_r3_res_path.json"); + } + + @Test + public void testExtension_r3_dt_base() throws IOException { + convert("extension_r3_dt_base.json"); + } + + @Test + public void testExtension_r3_dt_path() throws IOException { + convert("extension_r3_dt_path.json"); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_base.json b/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_base.json new file mode 100644 index 000000000..34036a2ef --- /dev/null +++ b/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_base.json @@ -0,0 +1,98 @@ +{ + "resourceType": "StructureDefinition", + "id": "coding-sctdescid", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "fhir" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 1 + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/coding-sctdescid", + "name": "sctdescid", + "status": "draft", + "date": "2015-02-28", + "publisher": "Health Level Seven, Inc. - FHIR Core WG", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/special/committees/FHIR" + } + ] + } + ], + "description": "The SNOMED CT Description ID for the display.", + "fhirVersion": "3.0.2", + "mapping": [ + { + "identity": "v2", + "uri": "http://hl7.org/v2", + "name": "HL7 v2 Mapping" + }, + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + } + ], + "kind": "complex-type", + "abstract": false, + "contextType": "datatype", + "context": [ + "Coding" + ], + "type": "Extension", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Extension", + "path": "Extension", + "short": "SNOMED CT Description ID", + "definition": "The SNOMED CT Description ID for the display.", + "min": 0, + "max": "1", + "mapping": [ + { + "identity": "v2", + "map": "N/A" + }, + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Extension.extension", + "path": "Extension.extension", + "max": "0" + }, + { + "id": "Extension.url", + "path": "Extension.url", + "type": [ + { + "code": "uri" + } + ], + "fixedUri": "http://hl7.org/fhir/StructureDefinition/coding-sctdescid" + }, + { + "id": "Extension.valueId", + "path": "Extension.valueId", + "type": [ + { + "code": "id" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_path.json b/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_path.json new file mode 100644 index 000000000..774edf042 --- /dev/null +++ b/org.hl7.fhir.convertors/src/test/resources/extension_r3_dt_path.json @@ -0,0 +1,106 @@ +{ + "resourceType": "StructureDefinition", + "id": "elementdefinition-equivalence", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "fhir" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 1 + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-equivalence", + "name": "equivalence", + "status": "draft", + "date": "2015-02-28", + "publisher": "Health Level Seven, Inc. - FHIR Core WG", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/special/committees/FHIR" + } + ] + } + ], + "description": "The level of equivalence between the element containing the mapping and the element mapped to.", + "fhirVersion": "3.0.2", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + } + ], + "kind": "complex-type", + "abstract": false, + "contextType": "datatype", + "context": [ + "ElementDefinition.mapping" + ], + "type": "Extension", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Extension", + "path": "Extension", + "short": "equivalent | equal | wider | subsumes | narrower | specializes | inexact | unmatched | disjoint", + "definition": "The level of equivalence between the element containing the mapping and the element mapped to.", + "min": 0, + "max": "1", + "mapping": [ + { + "identity": "rim", + "map": "N/A (MIF territory)" + } + ] + }, + { + "id": "Extension.extension", + "path": "Extension.extension", + "max": "0" + }, + { + "id": "Extension.url", + "path": "Extension.url", + "type": [ + { + "code": "uri" + } + ], + "fixedUri": "http://hl7.org/fhir/StructureDefinition/elementdefinition-equivalence" + }, + { + "id": "Extension.valueCode", + "path": "Extension.valueCode", + "type": [ + { + "code": "code" + } + ], + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "ConceptMapEquivalence" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "required", + "description": "The degree of equivalence between concepts.", + "valueSetReference": { + "reference": "http://hl7.org/fhir/ValueSet/concept-map-equivalence" + } + } + } + ] + } +} \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_base.json b/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_base.json new file mode 100644 index 000000000..915bcddb2 --- /dev/null +++ b/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_base.json @@ -0,0 +1,86 @@ +{ + "resourceType": "StructureDefinition", + "id": "capabilitystatement-supported-system", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "fhir" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 1 + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system", + "name": "supported-system", + "title": "Supported Code System", + "status": "draft", + "date": "2014-04-12", + "publisher": "Health Level Seven, Inc. - [WG Name] WG", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/special/committees/fhir.htm" + } + ] + } + ], + "description": "A code system that is supported by the system that is not defined in a value set resource.", + "fhirVersion": "3.0.2", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + } + ], + "kind": "complex-type", + "abstract": false, + "contextType": "resource", + "context": [ + "Resource" + ], + "type": "Extension", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Extension", + "path": "Extension", + "short": "Code system not defined in a value set", + "definition": "A code system that is supported by the system that is not defined in a value set resource.", + "comment": "Typically, this is a large terminology such as LOINC, SNOMED CT.", + "min": 0, + "max": "*", + "isModifier": false + }, + { + "id": "Extension.extension", + "path": "Extension.extension", + "max": "0" + }, + { + "id": "Extension.url", + "path": "Extension.url", + "type": [ + { + "code": "uri" + } + ], + "fixedUri": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system" + }, + { + "id": "Extension.valueUri", + "path": "Extension.valueUri", + "type": [ + { + "code": "uri" + } + ] + } + ] + } +} diff --git a/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_path.json b/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_path.json new file mode 100644 index 000000000..5cd949a66 --- /dev/null +++ b/org.hl7.fhir.convertors/src/test/resources/extension_r3_res_path.json @@ -0,0 +1,86 @@ +{ + "resourceType": "StructureDefinition", + "id": "capabilitystatement-websocket", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg", + "valueCode": "fhir" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm", + "valueInteger": 1 + } + ], + "url": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-websocket", + "name": "websocket", + "title": "WebSocket", + "status": "draft", + "date": "2014-04-12", + "publisher": "Health Level Seven, Inc. - [WG Name] WG", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://hl7.org/special/committees/fhir.htm" + } + ] + } + ], + "description": "Where the server provides its web socket end-point.", + "fhirVersion": "3.0.2", + "mapping": [ + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + } + ], + "kind": "complex-type", + "abstract": false, + "contextType": "resource", + "context": [ + "CapabilityStatement.rest" + ], + "type": "Extension", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Extension", + "path": "Extension", + "short": "Where server websocket end point is found", + "definition": "Where the server provides its web socket end-point.", + "comment": "Used for web-socket based subscriptions.", + "min": 0, + "max": "1", + "isModifier": false + }, + { + "id": "Extension.extension", + "path": "Extension.extension", + "max": "0" + }, + { + "id": "Extension.url", + "path": "Extension.url", + "type": [ + { + "code": "uri" + } + ], + "fixedUri": "http://hl7.org/fhir/StructureDefinition/capabilitystatement-websocket" + }, + { + "id": "Extension.valueUri", + "path": "Extension.valueUri", + "type": [ + { + "code": "uri" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java index baf9aad14..6a8f164e8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonRenderer.java @@ -196,7 +196,7 @@ public class ComparisonRenderer implements IEvaluationContext { private void renderProfile(String id, ProfileComparison comp) throws IOException { String template = templates.get("Profile"); Map vars = new HashMap<>(); - ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContextLeft(), null, session.getPkp()), new ProfileUtilities(session.getContextRight(), null, session.getPkp())); + ProfileComparer cs = new ProfileComparer(session, new ProfileUtilities(session.getContextLeft(), null, session.getPkpLeft()), new ProfileUtilities(session.getContextRight(), null, session.getPkpRight())); vars.put("left", new StringType(comp.getLeft().present())); vars.put("right", new StringType(comp.getRight().present())); vars.put("leftId", new StringType(comp.getLeft().getId())); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java index 1ce1f8915..5462fd1c2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java @@ -31,15 +31,17 @@ public class ComparisonSession { private int count; private boolean debug; private String title; - private ProfileKnowledgeProvider pkp; + private ProfileKnowledgeProvider pkpLeft; + private ProfileKnowledgeProvider pkpRight; - public ComparisonSession(IWorkerContext contextLeft, IWorkerContext contextRight, String title, ProfileKnowledgeProvider pkp) { + public ComparisonSession(IWorkerContext contextLeft, IWorkerContext contextRight, String title, ProfileKnowledgeProvider pkpLeft, ProfileKnowledgeProvider pkpRight) { super(); this.contextLeft = contextLeft; this.contextRight = contextRight; this.sessiondId = UUID.randomUUID().toString().toLowerCase(); this.title = title; - this.pkp = pkp; + this.pkpLeft = pkpLeft; + this.pkpRight = pkpRight; // debug = true; } @@ -88,7 +90,7 @@ public class ComparisonSession { compares.put(key, csc); return csc; } else if (left instanceof StructureDefinition && right instanceof StructureDefinition) { - ProfileComparer cs = new ProfileComparer(this, new ProfileUtilities(contextLeft, null, pkp), new ProfileUtilities(contextRight, null, pkp)); + ProfileComparer cs = new ProfileComparer(this, new ProfileUtilities(contextLeft, null, pkpLeft), new ProfileUtilities(contextRight, null, pkpRight)); ProfileComparison csc = cs.compare((StructureDefinition) left, (StructureDefinition) right); compares.put(key, csc); return csc; @@ -145,7 +147,11 @@ public class ComparisonSession { return compares; } - public ProfileKnowledgeProvider getPkp() { - return pkp; + public ProfileKnowledgeProvider getPkpLeft() { + return pkpLeft; + } + + public ProfileKnowledgeProvider getPkpRight() { + return pkpRight; } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java index cff5743d7..2ee855c24 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java @@ -983,12 +983,12 @@ public class ProfileComparer extends CanonicalResourceComparer { String leftColor = !combined.hasLeft() ? COLOR_NO_ROW_LEFT : combined.hasErrors() ? COLOR_DIFFERENT : null; String rightColor = !combined.hasRight() ? COLOR_NO_ROW_LEFT : combined.hasErrors() ? COLOR_DIFFERENT : null; if (combined.hasLeft()) { - nc = utilsRight.genElementNameCell(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, false, ext, used , ref, sName, null); + nc = utilsLeft.genElementNameCell(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, false, ext, used , ref, sName, null); } else { nc = utilsRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName, null); } if (combined.hasLeft()) { - frame(utilsRight.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, null), leftColor); + frame(utilsLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, null), leftColor); } else { frame(spacers(row, 4, gen), leftColor); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 5b3852ba9..3f5d3e0a1 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -1435,7 +1435,10 @@ public class ProfileUtilities extends TranslatingUtilities { } ndc = differential.getElement().indexOf(diffMatches.get(i)); 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, e, null, redirector, srcSD); + ElementDefinition typeSliceElement = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, null, redirector, srcSD); + if (typeList.size() > start+1) { + typeSliceElement.setMin(0); + } } if (elementToRemove != null) { differential.getElement().remove(elementToRemove); @@ -5445,9 +5448,10 @@ public class ProfileUtilities extends TranslatingUtilities { private int prefixLength; private String base; private String name; + private String baseName; private Set errors = new HashSet(); - public ElementDefinitionComparer(boolean inExtension, List snapshot, String base, int prefixLength, String name) { + public ElementDefinitionComparer(boolean inExtension, List snapshot, String base, int prefixLength, String name, String baseName) { this.inExtension = inExtension; this.snapshot = snapshot; this.prefixLength = prefixLength; @@ -5456,6 +5460,7 @@ public class ProfileUtilities extends TranslatingUtilities { this.base = urlTail(base); } this.name = name; + this.baseName = baseName; } @Override @@ -5504,9 +5509,9 @@ public class ProfileUtilities extends TranslatingUtilities { } if (mandatory) { if (prefixLength == 0) - errors.add("Differential contains path "+path+" which is not found in the in base "+name); + errors.add("Differential contains path "+path+" which is not found in the in base "+baseName); else - errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the in base "+name); + errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the in base "+ baseName); } return 0; } @@ -5565,7 +5570,7 @@ public class ProfileUtilities extends TranslatingUtilities { processElementsIntoTree(edh, i, diff.getDifferential().getElement()); // now, we sort the siblings throughout the tree - ElementDefinitionComparer cmp = new ElementDefinitionComparer(true, base.getSnapshot().getElement(), "", 0, name); + ElementDefinitionComparer cmp = new ElementDefinitionComparer(true, base.getSnapshot().getElement(), "", 0, name, base.getType()); sortElements(edh, cmp, errors); // now, we serialise them back to a list @@ -5652,27 +5657,27 @@ public class ProfileUtilities extends TranslatingUtilities { if (profile==null) { ccmp = null; // this might happen before everything is loaded. And we don't so much care about sot order in this case } else { - ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), profile.getType(), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), profile.getType(), child.getSelf().getPath().length(), cmp.name, profile.present()); } } else { - ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name); + ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name, cmp.name); } } else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) { StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue()); if (profile==null) ccmp = null; // this might happen before everything is loaded. And we don't so much care about sot order in this case else - ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), resolveType(ed.getType().get(0).getWorkingCode()), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), resolveType(ed.getType().get(0).getWorkingCode()), child.getSelf().getPath().length(), cmp.name, profile.present()); } else if (ed.getType().size() == 1 && !ed.getType().get(0).getWorkingCode().equals("*")) { StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode())); if (profile==null) throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath())); - ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), resolveType(ed.getType().get(0).getWorkingCode()), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), resolveType(ed.getType().get(0).getWorkingCode()), child.getSelf().getPath().length(), cmp.name, profile.present()); } else if (child.getSelf().getType().size() == 1) { StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(child.getSelf().getType().get(0).getWorkingCode())); if (profile==null) throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath())); - ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), child.getSelf().getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), child.getSelf().getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name, profile.present()); } else if (ed.getPath().endsWith("[x]") && !child.getSelf().getPath().endsWith("[x]")) { String edLastNode = ed.getPath().replaceAll("(.*\\.)*(.*)", "$2"); String childLastNode = child.getSelf().getPath().replaceAll("(.*\\.)*(.*)", "$2"); @@ -5682,7 +5687,7 @@ public class ProfileUtilities extends TranslatingUtilities { StructureDefinition sd = context.fetchResource(StructureDefinition.class, sdNs(p)); if (sd == null) throw new Error(context.formatMessage(I18nConstants.UNABLE_TO_FIND_PROFILE__AT_, p, ed.getId())); - ccmp = new ElementDefinitionComparer(false, sd.getSnapshot().getElement(), p, child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, sd.getSnapshot().getElement(), p, child.getSelf().getPath().length(), cmp.name, sd.present()); } else if (child.getSelf().hasType() && child.getSelf().getType().get(0).getWorkingCode().equals("Reference")) { for (TypeRefComponent t: child.getSelf().getType()) { if (!t.getWorkingCode().equals("Reference")) { @@ -5690,7 +5695,7 @@ public class ProfileUtilities extends TranslatingUtilities { } } StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode())); - ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), ed.getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), ed.getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name, profile.present()); } else if (!child.getSelf().hasType() && ed.getType().get(0).getWorkingCode().equals("Reference")) { for (TypeRefComponent t: ed.getType()) { if (!t.getWorkingCode().equals("Reference")) { @@ -5698,13 +5703,13 @@ public class ProfileUtilities extends TranslatingUtilities { } } StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode())); - ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), ed.getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), ed.getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name, profile.present()); } else { // this is allowed if we only profile the extensions StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs("Element")); if (profile==null) throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath())); - ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), "Element", child.getSelf().getPath().length(), cmp.name); + ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), "Element", child.getSelf().getPath().length(), cmp.name, profile.present()); // throw new Error("Not handled yet (sortElements: "+ed.getPath()+":"+typeCode(ed.getType())+")"); } return ccmp; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index 05280ffae..e47a74817 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -701,6 +701,9 @@ public class I18nConstants { public static final String TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_ERROR = "TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_ERROR"; public static final String TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_WARNING = "TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_WARNING"; public static final String TX_SERVER_NO_BATCH_RESPONSE = "TX_SERVER_NO_BATCH_RESPONSE"; + public static final String BUNDLE_POSSSIBLE_MATCHES = "BUNDLE_POSSSIBLE_MATCHES"; + public static final String BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU = "BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU"; + public static final String BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU = "BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU"; } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java index fbb155854..876cbb35a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java @@ -851,6 +851,9 @@ public class NpmPackage { public InputStream loadExampleResource(String type, String id) throws IOException { NpmPackageFolder f = folders.get("example"); + if (f == null) { + f = folders.get("package/example"); + } if (f != null) { JsonArray files = f.index.getAsJsonArray("files"); for (JsonElement e : files) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/tests/BaseTestingUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/tests/BaseTestingUtilities.java index e6a4ddcaa..cf1d67bf5 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/tests/BaseTestingUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/tests/BaseTestingUtilities.java @@ -108,7 +108,7 @@ public class BaseTestingUtilities { } public static String tempFolder(String name) throws IOException { - String path = ToolGlobalSettings.hasTempPath() ? ToolGlobalSettings.getTempPath() : Utilities.path("[tmp]", name); + String path = Utilities.path(ToolGlobalSettings.hasTempPath() ? ToolGlobalSettings.getTempPath() : "[tmp]", name); Utilities.createDirectory(path); return path; } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 8aae0606c..e7d666f10 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -111,7 +111,7 @@ Reference_REF_BadTargetType = Invalid Resource target type. Found {0}, but expec Reference_REF_BadTargetType2 = The type ''{0}'' implied by the reference URL {1} is not a valid Target for this element (must be one of {2}) Reference_REF_CantMatchChoice = Unable to find a match for profile {0} among choices: {1} Reference_REF_CantMatchType = Unable to find a match for profile {0} (by type) among choices: {1} -Reference_REF_CantResolve = Unable to resolve resource ''{0}'' +Reference_REF_CantResolve = Unable to resolve resource with reference ''{0}'' Reference_REF_CantResolveProfile = Unable to resolve the profile reference ''{0}'' Reference_REF_Format1 = Relative URLs must be of the format [ResourceName]/[id], or a search URL is allowed ([type]?parameters. Encountered {0}) Reference_REF_Format2 = Relative URLs must be of the format [ResourceName]/[id]. Encountered {0} @@ -280,7 +280,7 @@ Unable_to_locate_the_profile__in_order_to_validate_against_it = Unable to locate Reference__refers_to_a__not_a_ValueSet = Reference {0} refers to a {1} not a ValueSet Not_done_yet_ValidatorHostServicesconformsToProfile_when_item_is_not_an_element = Not done yet (ValidatorHostServices.conformsToProfile), when item is not an element Not_supported_yet = Not supported yet -Unable_to_resolve_ = Unable to resolve {0} +Unable_to_resolve_ = Unable to resolve the reference {0} Not_done_yet__resolve__locally_2 = Not done yet - resolve {0} locally (2) Not_done_yet_ValidatorHostServicesexecuteFunction = Not done yet (ValidatorHostServices.executeFunction) Not_done_yet_ValidatorHostServicescheckFunction = Not done yet (ValidatorHostServices.checkFunction) @@ -711,3 +711,6 @@ TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_WARNING = Base64 encoded values SHOULD not SD_DERIVATION_KIND_MISMATCH = The structure definition constrains a kind of {0}, but has a different kind ({1}) VALUESET_IMPORT_UNION_INTERSECTION = This value set has a single include with multiple imported value sets. Per issue https://jira.hl7.org/browse/FHIR-25179, there has been confusion in the past whether these value sets are unioned or intersectioned. If this value set is contained in a package published prior to March 31 2022, it will be treated as a union, otherwise it will be treated as an intersection. If want a union, split the value set imports across multiple includes TX_SERVER_NO_BATCH_RESPONSE = The server return null from a batch validation request +BUNDLE_POSSSIBLE_MATCHES = The bundle contains no match for {1} by the rules of Bundle reference resolution, but it has multiple resources that match {0} by resource type and id +BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU = Entry {0} matches the reference {1} by type and id but it does not match the full target URL {2} by Bundle resolution rules +BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU = Entry {0} matches the reference {1} by type and id but it''s fullUrl {2} does not match the full target URL {3} by Bundle resolution rules diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index 82463d169..3bd9c0626 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -950,8 +950,34 @@ public class BaseValidator implements IValidationContextResourceLoader { if (match != null && resourceType != null) rule(errors, IssueType.REQUIRED, -1, -1, path, match.getType().equals(resourceType), I18nConstants.REFERENCE_REF_RESOURCETYPE, ref, match.getType()); - if (match == null) + if (match == null) { warning(errors, IssueType.REQUIRED, -1, -1, path, !ref.startsWith("urn"), I18nConstants.BUNDLE_BUNDLE_NOT_LOCAL, ref); + if (!Utilities.isAbsoluteUrl(ref)) { + String[] p = ref.split("\\/"); + List ml = new ArrayList<>(); + if (p.length >= 2 && Utilities.existsInList(p[0], context.getResourceNames()) && Utilities.isValidId(p[1])) { + for (int i = 0; i < entries.size(); i++) { + Element we = entries.get(i); + Element r = we.getNamedChild(RESOURCE); + if (r != null && p[0].equals(r.fhirType()) && p[1].equals(r.getNamedChildValue("id")) ) { + ml.add(we); + } + } + } + if (ml.size() > 1) { + warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_POSSSIBLE_MATCHES, ref, targetUrl); + } + for (Element e : ml) { + String fu = e.getChildValue(FULL_URL); + int i = entries.indexOf(e); + if (fu == null) { + warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU, i, ref, targetUrl); + } else { + warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU, i, ref, fu, targetUrl); + } + } + } + } return match == null ? null : new IndexedElement(matchIndex, match, entries.get(matchIndex)); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index 16b6876e8..0f77fdea1 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -627,6 +627,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP igLoader.loadIg(getIgs(), getBinaries(), SHCParser.CURRENT_PACKAGE, true); } validator.setJurisdiction(jurisdiction); + validator.setLogProgress(true); return validator; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ComparisonService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ComparisonService.java index 1fcb1b204..f8c763360 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ComparisonService.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ComparisonService.java @@ -60,7 +60,7 @@ public class ComparisonService { public static void compareStructureDefinitions(String dest, ValidationEngine validator, String left, String right, StructureDefinition resLeft, StructureDefinition resRight) throws IOException, FHIRException, EOperationOutcome { System.out.println("Comparing StructureDefinitions " + left + " to " + right); - ComparisonSession session = new ComparisonSession(validator.getContext(), validator.getContext(), "Comparing Profiles", null); + ComparisonSession session = new ComparisonSession(validator.getContext(), validator.getContext(), "Comparing Profiles", null, null); session.compare(resLeft, resRight); System.out.println("Generating output to " + dest + "..."); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 94b009123..f77b61979 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -424,6 +424,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private QuestionnaireMode questionnaireMode; private ValidationOptions baseOptions = new ValidationOptions(); private Map crLookups = new HashMap<>(); + private boolean logProgress; public InstanceValidator(IWorkerContext theContext, IEvaluationContext hostServices, XVerExtensionManager xverManager) { super(theContext, xverManager); @@ -2980,8 +2981,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (refType.equals("contained") || refType.equals("bundled")) { pol = ReferenceValidationPolicy.CHECK_VALID; } else { - if (policyAdvisor == null) pol = ReferenceValidationPolicy.IGNORE; - else pol = policyAdvisor.policyForReference(this, hostContext.getAppContext(), path, ref); + if (policyAdvisor == null) { + pol = ReferenceValidationPolicy.IGNORE; + } else { + pol = policyAdvisor.policyForReference(this, hostContext.getAppContext(), path, ref); + } } if (pol.checkExists()) { @@ -4397,7 +4401,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat // this method is reentrant, but also the right place to tell the user what is going on if it's the root. // if we're not at the root, we don't report progress pctOwned = true; - pct = new PercentageTracker(resource.countDescendents()+1, resource.fhirType(), defn.getUrl()); + pct = new PercentageTracker(resource.countDescendents()+1, resource.fhirType(), defn.getUrl(), logProgress); } if (BUNDLE.equals(element.fhirType())) { if (debug) { @@ -4467,7 +4471,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } stack.resetIds(); if (pctOwned) { - pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sd.getUrl()); + pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sd.getUrl(), logProgress); } startInner(hostContext, errors, resource, element, sd, stack, false, pct); if (pctOwned) { @@ -4490,7 +4494,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } stack.resetIds(); if (pctOwned) { - pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sd.getUrl()); + pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sd.getUrl(), logProgress); } startInner(hostContext, errors, resource, element, sd, stack, false, pct); if (pctOwned) { @@ -6072,4 +6076,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return this; } + public boolean isLogProgress() { + return logProgress; + } + + public void setLogProgress(boolean logProgress) { + this.logProgress = logProgress; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/PercentageTracker.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/PercentageTracker.java index 2d2cddb70..aba2b2880 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/PercentageTracker.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/PercentageTracker.java @@ -7,18 +7,30 @@ public class PercentageTracker { private int total; private int last; private int current; + private boolean log; + private String url; private static int instance; - public PercentageTracker(int total, String fhirType, String url) { + public PercentageTracker(int total, String fhirType, String url, boolean log) { this.total = total; instance++; last = 0; - System.out.print("Validate "+fhirType+" against "+url); + this.log = log; + this.url = url; + if (log) { + System.out.print("Validate "+fhirType+" against "+url); + } } public void done() { - System.out.println("|"); + if (log) { + System.out.println("|"); + } + } + + public String getUrl() { + return url; } public void seeElement(Element e) { @@ -28,10 +40,14 @@ public class PercentageTracker { int pct = total == 0 ? 0: (current*100) / total; if (pct > last + 2) { while (last + 2 < pct) { - System.out.print("."); + if (log) { + System.out.print("."); + } last = last + 2; if (last % 20 == 0) { - System.out.print(""+last); + if (log) { + System.out.print(""+last); + } } } } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java index 75d82d6bf..58ab30094 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java @@ -132,7 +132,7 @@ public class ComparisonTests { CanonicalResource left = load("left"); CanonicalResource right = load("right"); - ComparisonSession session = new ComparisonSession(context, context, "Comparison Tests", null); + ComparisonSession session = new ComparisonSession(context, context, "Comparison Tests", null, null); if (left instanceof CodeSystem && right instanceof CodeSystem) { CodeSystemComparer cs = new CodeSystemComparer(session); diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/loinc.cache b/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/loinc.cache index 5c3f7df3c..f46d63353 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/loinc.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/loinc.cache @@ -1292,3 +1292,43 @@ v: { "system" : "http://loinc.org" } ------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://loinc.org", + "code" : "11502-2" +}, "url": "http://hl7.org/fhir/ValueSet/doc-typecodes--0", "version": "4.0.1", "lang":"null", "useServer":"true", "useClient":"false", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}#### +v: { + "display" : "Laboratory report", + "code" : "11502-2", + "system" : "http://loinc.org" +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://loinc.org", + "code" : "11502-2" +}, "url": "http://hl7.org/fhir/ValueSet/doc-typecodes", "version": "4.0.1", "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"NO_MEMBERSHIP_CHECK", "versionFlexible":"false"}#### +v: { + "display" : "Laboratory report", + "code" : "11502-2", + "system" : "http://loinc.org" +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://loinc.org", + "code" : "11502-2" +}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"true"}#### +v: { + "display" : "Laboratory report", + "code" : "11502-2", + "system" : "http://loinc.org" +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://loinc.org", + "code" : "11502-2" +}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}#### +v: { + "display" : "Laboratory report", + "code" : "11502-2", + "system" : "http://loinc.org" +} +-------------------------------------------------------------------------------------