commit
be52ad2e96
|
@ -1,5 +1,7 @@
|
|||
package org.hl7.fhir.convertors.conv40_50.datatypes40_50;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hl7.fhir.convertors.context.ConversionContext40_50;
|
||||
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.special40_50.Extension40_50;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -8,14 +10,22 @@ public class BackboneElement40_50 {
|
|||
public static void copyBackboneElement(org.hl7.fhir.r4.model.BackboneElement src, org.hl7.fhir.r5.model.BackboneElement tgt, String ... extensionUrlsToIgnore) throws FHIRException {
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt, extensionUrlsToIgnore);
|
||||
for (org.hl7.fhir.r4.model.Extension e : src.getModifierExtension()) {
|
||||
tgt.addModifierExtension(Extension40_50.convertExtension(e));
|
||||
if (!isExemptExtension(e.getUrl(), extensionUrlsToIgnore)) {
|
||||
tgt.addModifierExtension(Extension40_50.convertExtension(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isExemptExtension(String url, String[] extensionsToIgnore) {
|
||||
return Arrays.asList(extensionsToIgnore).contains(url);
|
||||
}
|
||||
|
||||
public static void copyBackboneElement(org.hl7.fhir.r5.model.BackboneElement src, org.hl7.fhir.r4.model.BackboneElement tgt, String... extensionUrlsToIgnore) throws FHIRException {
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt, extensionUrlsToIgnore);
|
||||
for (org.hl7.fhir.r5.model.Extension e : src.getModifierExtension()) {
|
||||
tgt.addModifierExtension(Extension40_50.convertExtension(e));
|
||||
if (!isExemptExtension(e.getUrl(), extensionUrlsToIgnore)) {
|
||||
tgt.addModifierExtension(Extension40_50.convertExtension(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,9 @@ public class ConceptMap40_50 {
|
|||
for (org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent t : src.getTarget()) {
|
||||
if (t.getEquivalence() == org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence.UNMATCHED) {
|
||||
tgt.setNoMap(true);
|
||||
if (t.hasComment()) {
|
||||
tgt.addExtension("http://hl7.org/fhir/4.0/StructureDefinition/extension-ConceptMap.group.element.target.comment", ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().convertType(t.getCommentElement()));
|
||||
}
|
||||
} else {
|
||||
tgt.addTarget(convertTargetElementComponent(t, tgtMap));
|
||||
}
|
||||
|
@ -218,13 +221,18 @@ public class ConceptMap40_50 {
|
|||
if (src == null)
|
||||
return null;
|
||||
org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent tgt = new org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent();
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt);
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt, "http://hl7.org/fhir/4.0/StructureDefinition/extension-ConceptMap.group.element.target.comment");
|
||||
if (src.hasCode())
|
||||
tgt.setCodeElement(Code40_50.convertCode(src.getCodeElement()));
|
||||
if (src.hasDisplay())
|
||||
tgt.setDisplayElement(String40_50.convertString(src.getDisplayElement()));
|
||||
if (src.hasNoMap() && src.getNoMap() == true) {
|
||||
tgt.addTarget(new org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent().setEquivalence(org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence.UNMATCHED));
|
||||
org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent t = new org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent();
|
||||
t.setEquivalence(org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence.UNMATCHED);
|
||||
if (src.hasExtension("http://hl7.org/fhir/4.0/StructureDefinition/extension-ConceptMap.group.element.target.comment")) {
|
||||
t.setCommentElement((org.hl7.fhir.r4.model.StringType) ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().convertType(src.getExtensionByUrl("http://hl7.org/fhir/4.0/StructureDefinition/extension-ConceptMap.group.element.target.comment").getValue()));
|
||||
}
|
||||
tgt.addTarget(t);
|
||||
} else {
|
||||
for (org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent t : src.getTarget())
|
||||
tgt.addTarget(convertTargetElementComponent(t, srcMap));
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r4.formats.JsonParser;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
|
||||
|
@ -60,8 +61,18 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
CapabilityStatement cs = fhirToolingClient.getCapabilitiesStatement();
|
||||
JsonParser json = new JsonParser();
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "vsac-capability-statmenet.json")), cs);
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "vsac-capability-statement.json")), cs);
|
||||
|
||||
System.out.println("CodeSystems");
|
||||
CodeSystem css = fhirToolingClient.fetchResource(CodeSystem.class, "CDCNHSN");
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "CodeSystem-CDCNHSN.json")), css);
|
||||
css = fhirToolingClient.fetchResource(CodeSystem.class, "CDCREC");
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "CodeSystem-CDCREC.json")), css);
|
||||
css = fhirToolingClient.fetchResource(CodeSystem.class, "HSLOC");
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "CodeSystem-HSLOC.json")), css);
|
||||
css = fhirToolingClient.fetchResource(CodeSystem.class, "SOP");
|
||||
json.setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "CodeSystem-SOP.json")), css);
|
||||
|
||||
System.out.println("Loading");
|
||||
List<String> oids = new ArrayList<>();
|
||||
while (csv.line()) {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package org.hl7.fhir.convertors.conv40_50;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ConceptMap40_50Test {
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("Test r5 -> r4 ConceptMap conversion.")
|
||||
public void testR5_R4() throws IOException {
|
||||
InputStream r4_input = this.getClass().getResourceAsStream("/cm_nomap.json");
|
||||
|
||||
org.hl7.fhir.r4.model.ConceptMap r4_actual = (org.hl7.fhir.r4.model.ConceptMap) new org.hl7.fhir.r4.formats.JsonParser().parse(r4_input);
|
||||
org.hl7.fhir.r5.model.Resource r5_conv = VersionConvertorFactory_40_50.convertResource(r4_actual);
|
||||
org.hl7.fhir.r4.model.Resource r4_conv = VersionConvertorFactory_40_50.convertResource(r5_conv);
|
||||
|
||||
System.out.println(new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(r4_actual));
|
||||
System.out.println(new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(r4_conv));
|
||||
assertTrue(r4_actual.equalsDeep(r4_conv), "should be the same");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"resourceType": "ConceptMap",
|
||||
"id": "appointment-status-concept-map",
|
||||
"url": "https://hl7.fi/fhir/finnish-scheduling/ConceptMap/appointment-status-concept-map",
|
||||
"title": "FHIR Appointment status codes and Ajanvaraus - Ajanvarauksen tila",
|
||||
"description": "Mapping between the Finnish logical model [*Ajanvaraus - Ajanvarauksen tila*](https://koodistopalvelu.kanta.fi/codeserver/pages/classification-view-page.xhtml?classificationKey=1943) (oid `1.2.246.537.6.881`) and FHIR Appoinment status codes, in both directions.",
|
||||
"status": "draft",
|
||||
"sourceUri": "https://koodistopalvelu.kanta.fi/codeserver/pages/classification-view-page.xhtml?classificationKey=1943",
|
||||
"targetCanonical": "http://hl7.org/fhir/appointmentstatus",
|
||||
"group": [{
|
||||
"source": "https://koodistopalvelu.kanta.fi/codeserver/pages/classification-view-page.xhtml?classificationKey=1943",
|
||||
"target": "http://hl7.org/fhir/appointmentstatus",
|
||||
"element": [{
|
||||
"code": "5",
|
||||
"display": "Siirretty",
|
||||
"target": [{
|
||||
"equivalence": "unmatched",
|
||||
"comment": "There is no status for rescheduled appointments in FHIR. This code SHOULD be mapped to cancelled, if required. Note that this code is deprecated."
|
||||
}]
|
||||
}, {
|
||||
"code" : "3",
|
||||
"display" : "Varattu",
|
||||
"target" : [{
|
||||
"code" : "booked",
|
||||
"display" : "Booked",
|
||||
"equivalence" : "equal"
|
||||
}]
|
||||
}]
|
||||
]}
|
||||
}
|
|
@ -3658,23 +3658,22 @@ public class FHIRPathEngine {
|
|||
|
||||
case LowBoundary:
|
||||
case HighBoundary: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, true);
|
||||
if (paramTypes.size() > 0) {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
|
||||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
|
||||
}
|
||||
if (focus.hasType("decimal")
|
||||
&& (focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime);
|
||||
} else if (focus.hasType("decimal")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
|
||||
if ((focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime);
|
||||
} else if (focus.hasType("decimal") || focus.hasType("integer")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
|
||||
} else {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
|
||||
}
|
||||
}
|
||||
case Precision: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, false);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
|
||||
}
|
||||
|
||||
case Custom: {
|
||||
|
@ -3778,9 +3777,8 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime")
|
||||
&& !focus.hasType("time") && !focus.hasType("Quantity")) {
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr, boolean allowInteger) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time") && !focus.hasType("Quantity") && !(allowInteger && focus.hasType("integer"))) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_CONTINUOUS_ONLY, name, focus.describe());
|
||||
}
|
||||
}
|
||||
|
@ -4223,42 +4221,43 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "lowBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values",
|
||||
"integer");
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values", "integer");
|
||||
}
|
||||
precision = Integer.parseInt(n1.get(0).primitiveValue());
|
||||
}
|
||||
|
||||
|
||||
Base base = focus.get(0);
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
|
||||
|
||||
if (base.hasType("decimal")) {
|
||||
result
|
||||
.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(),
|
||||
"decimal or date");
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private List<Base> funcHighBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||
if (focus.size() == 0) {
|
||||
return makeNull();
|
||||
|
@ -4266,41 +4265,43 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values",
|
||||
"integer");
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values", "integer");
|
||||
}
|
||||
precision = Integer.parseInt(n1.get(0).primitiveValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Base base = focus.get(0);
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
if (base.hasType("decimal")) {
|
||||
result.add(
|
||||
new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(),
|
||||
"decimal or date");
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private List<Base> funcPrecision(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||
if (focus.size() != 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||
|
|
|
@ -3660,23 +3660,22 @@ public class FHIRPathEngine {
|
|||
|
||||
case LowBoundary:
|
||||
case HighBoundary: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, true);
|
||||
if (paramTypes.size() > 0) {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
|
||||
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
|
||||
}
|
||||
if (focus.hasType("decimal")
|
||||
&& (focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime);
|
||||
} else if (focus.hasType("decimal")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
|
||||
if ((focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime);
|
||||
} else if (focus.hasType("decimal") || focus.hasType("integer")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
|
||||
} else {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
|
||||
}
|
||||
}
|
||||
case Precision: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, false);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
|
||||
}
|
||||
|
||||
case Custom: {
|
||||
|
@ -3780,9 +3779,8 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime")
|
||||
&& !focus.hasType("time") && !focus.hasType("Quantity")) {
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr, boolean allowInteger) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time") && !focus.hasType("Quantity") && !(allowInteger && focus.hasType("integer"))) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_CONTINUOUS_ONLY, name, focus.describe());
|
||||
}
|
||||
}
|
||||
|
@ -4233,42 +4231,43 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "lowBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values",
|
||||
"integer");
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values", "integer");
|
||||
}
|
||||
precision = Integer.parseInt(n1.get(0).primitiveValue());
|
||||
}
|
||||
|
||||
|
||||
Base base = focus.get(0);
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
|
||||
|
||||
if (base.hasType("decimal")) {
|
||||
result
|
||||
.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(),
|
||||
"decimal or date");
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private List<Base> funcHighBoundary(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||
if (focus.size() == 0) {
|
||||
return makeNull();
|
||||
|
@ -4276,41 +4275,43 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values",
|
||||
"integer");
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "lowBoundary", "0", "Multiple Values", "integer");
|
||||
}
|
||||
precision = Integer.parseInt(n1.get(0).primitiveValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Base base = focus.get(0);
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
if (base.hasType("decimal")) {
|
||||
result.add(
|
||||
new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result
|
||||
.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(),
|
||||
"decimal or date");
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private List<Base> funcPrecision(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
|
||||
if (focus.size() != 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
package org.hl7.fhir.r5.conformance.profile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.r5.model.Element;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
|
||||
public class MappingAssistant {
|
||||
|
||||
|
||||
public enum MappingMergeModeOption {
|
||||
DUPLICATE, // if there's more than one mapping for the same URI, just keep them all
|
||||
IGNORE, // if there's more than one, keep the first
|
||||
OVERWRITE, // if there's opre than, keep the last
|
||||
APPEND, // if there's more than one, append them with ';'
|
||||
}
|
||||
|
||||
private MappingMergeModeOption mappingMergeMode = MappingMergeModeOption.APPEND;
|
||||
private StructureDefinition base;
|
||||
private StructureDefinition derived;
|
||||
|
||||
private List<StructureDefinitionMappingComponent> masterList= new ArrayList<StructureDefinition.StructureDefinitionMappingComponent>();
|
||||
private Map<String, String> renames = new HashMap<>();
|
||||
private String version;
|
||||
|
||||
public MappingAssistant(MappingMergeModeOption mappingMergeMode, StructureDefinition base, StructureDefinition derived, String version) {
|
||||
this.mappingMergeMode = mappingMergeMode;
|
||||
this.base = base;
|
||||
this.derived = derived;
|
||||
this.version = version;
|
||||
|
||||
// figure out where we're going to be:
|
||||
// mappings declared in derived get priority; we do not change them either
|
||||
for (StructureDefinitionMappingComponent m : derived.getMapping()) {
|
||||
masterList.add(m);
|
||||
if (!isSuppressed(m)) {
|
||||
m.setUserData("private-marked-as-derived", true);
|
||||
}
|
||||
}
|
||||
|
||||
// now, look at the base profile. If mappings in there match one in the derived, then we use that, otherwise, we add it to the list
|
||||
for (StructureDefinitionMappingComponent m : base.getMapping()) {
|
||||
StructureDefinitionMappingComponent md = findMatchInDerived(m);
|
||||
if (md == null) {
|
||||
if (nameExists(m.getIdentity())) {
|
||||
int i = 1;
|
||||
String n = m.getIdentity() + i;
|
||||
while (nameExists(n)) {
|
||||
i++;
|
||||
n = m.getIdentity() + i;
|
||||
}
|
||||
renames.put(m.getIdentity(), n);
|
||||
masterList.add(m.copy().setName(n));
|
||||
} else {
|
||||
masterList.add(m.copy());
|
||||
}
|
||||
} else {
|
||||
if (!md.hasName() && m.hasName()) {
|
||||
md.setName(m.getName());
|
||||
}
|
||||
if (!md.hasUri() && m.hasUri()) {
|
||||
md.setUri(m.getUri());
|
||||
}
|
||||
if (!md.hasComment() && m.hasComment()) {
|
||||
md.setComment(m.getComment());
|
||||
}
|
||||
if (!m.getIdentity().equals(md.getIdentity())) {
|
||||
renames.put(m.getIdentity(), md.getIdentity());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean nameExists(String n) {
|
||||
for (StructureDefinitionMappingComponent md : masterList) {
|
||||
if (n.equals(md.getIdentity())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private StructureDefinitionMappingComponent findMatchInDerived(StructureDefinitionMappingComponent m) {
|
||||
for (StructureDefinitionMappingComponent md : derived.getMapping()) {
|
||||
// if the URIs match, they match, irregardless of anything else
|
||||
if (md.hasUri() && m.hasUri() && md.getUri().equals(m.getUri())) {
|
||||
return md;
|
||||
}
|
||||
// if the codes match
|
||||
if (md.hasIdentity() && m.hasIdentity() && md.getIdentity().equals(m.getIdentity())) {
|
||||
// the names have to match if present
|
||||
if (!md.hasName() || !m.hasName() || md.getName().equals(m.getName())) {
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
|
||||
Set<StructureDefinitionMappingComponent> usedList= new HashSet<StructureDefinition.StructureDefinitionMappingComponent>();
|
||||
for (ElementDefinition ed : derived.getSnapshot().getElement()) {
|
||||
for (ElementDefinitionMappingComponent m : ed.getMapping()) {
|
||||
StructureDefinitionMappingComponent def = findDefinition(m.getIdentity());
|
||||
if (def != null) {
|
||||
usedList.add(def);
|
||||
} else {
|
||||
// not sure what to do?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
derived.getMapping().clear();
|
||||
for (StructureDefinitionMappingComponent t : masterList) {
|
||||
if (usedList.contains(t) || t.hasUserData("private-marked-as-derived")) {
|
||||
derived.getMapping().add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void merge(ElementDefinition base, ElementDefinition derived) {
|
||||
List<ElementDefinitionMappingComponent> list = new ArrayList<>();
|
||||
addMappings(list, base.getMapping(), renames);
|
||||
if (derived.hasMapping()) {
|
||||
addMappings(list, derived.getMapping(), null);
|
||||
}
|
||||
derived.setMapping(list);
|
||||
|
||||
// trim anything
|
||||
for (ElementDefinitionMappingComponent m : base.getMapping()) {
|
||||
if (m.hasMap()) {
|
||||
m.setMap(m.getMap().trim());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addMappings(List<ElementDefinitionMappingComponent> destination, List<ElementDefinitionMappingComponent> source, Map<String, String> renames2) {
|
||||
for (ElementDefinitionMappingComponent s : source) {
|
||||
if (!isSuppressed(s)) {
|
||||
String name = s.getIdentity();
|
||||
if (!isSuppressed(name)) {
|
||||
if (renames2 != null && renames2.containsKey(name)) {
|
||||
name = renames2.get(name);
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
for (ElementDefinitionMappingComponent d : destination) {
|
||||
if (compareMaps(name, s, d)) {
|
||||
found = true;
|
||||
d.setUserData(ProfileUtilities.UD_DERIVATION_EQUALS, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
destination.add(s.setIdentity(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSuppressed(String name) {
|
||||
StructureDefinitionMappingComponent m = findDefinition(name);
|
||||
return m != null && isSuppressed(m);
|
||||
}
|
||||
|
||||
private boolean isSuppressed(Element s) {
|
||||
return ToolingExtensions.readBoolExtension(s, ToolingExtensions.EXT_SUPPRESSED);
|
||||
}
|
||||
|
||||
private StructureDefinitionMappingComponent findDefinition(String name) {
|
||||
for (StructureDefinitionMappingComponent t : masterList) {
|
||||
if (t.getIdentity().equals(name)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean compareMaps(String name, ElementDefinitionMappingComponent s, ElementDefinitionMappingComponent d) {
|
||||
|
||||
if (d.getIdentity().equals(name) && d.getMap().equals(s.getMap())) {
|
||||
return true;
|
||||
}
|
||||
if (VersionUtilities.isR5Plus(version)) {
|
||||
if (d.getIdentity().equals(name)) {
|
||||
switch (mappingMergeMode) {
|
||||
case APPEND:
|
||||
if (!Utilities.splitStrings(d.getMap(), "\\,").contains(s.getMap())) {
|
||||
d.setMap(d.getMap()+","+s.getMap());
|
||||
}
|
||||
return true;
|
||||
case DUPLICATE:
|
||||
return false;
|
||||
case IGNORE:
|
||||
d.setMap(s.getMap());
|
||||
return true;
|
||||
case OVERWRITE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -128,7 +128,7 @@ public class ProfilePathProcessor {
|
|||
}
|
||||
|
||||
|
||||
protected static void processPaths(ProfileUtilities profileUtilities, StructureDefinition base, StructureDefinition derived, String url, String webUrl, StructureDefinition.StructureDefinitionDifferentialComponent differential, StructureDefinition.StructureDefinitionSnapshotComponent baseSnapshot) {
|
||||
protected static void processPaths(ProfileUtilities profileUtilities, StructureDefinition base, StructureDefinition derived, String url, String webUrl, StructureDefinition.StructureDefinitionDifferentialComponent differential, StructureDefinition.StructureDefinitionSnapshotComponent baseSnapshot, MappingAssistant mapHelper) {
|
||||
|
||||
ProfilePathProcessorState cursors = new ProfilePathProcessorState(
|
||||
baseSnapshot,
|
||||
|
@ -152,16 +152,17 @@ public class ProfilePathProcessor {
|
|||
.withRedirector(new ArrayList<ElementRedirection>())
|
||||
.withSourceStructureDefinition(base)
|
||||
.withDerived(derived)
|
||||
.withSlicing(new PathSlicingParams()).processPaths(cursors);
|
||||
.withSlicing(new PathSlicingParams()).processPaths(cursors, mapHelper);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cursors
|
||||
* @param mapHelper
|
||||
* @throws DefinitionException, FHIRException
|
||||
* @throws Exception
|
||||
*/
|
||||
private ElementDefinition processPaths(final ProfilePathProcessorState cursors) throws FHIRException {
|
||||
private ElementDefinition processPaths(final ProfilePathProcessorState cursors, MappingAssistant mapHelper) throws FHIRException {
|
||||
debugProcessPathsEntry(cursors);
|
||||
ElementDefinition res = null;
|
||||
List<TypeSlice> typeList = new ArrayList<>();
|
||||
|
@ -177,13 +178,13 @@ public class ProfilePathProcessor {
|
|||
// in the simple case, source is not sliced.
|
||||
if (!currentBase.hasSlicing() || currentBasePath.equals(getSlicing().getPath()))
|
||||
{
|
||||
ElementDefinition currentRes = processSimplePath(currentBase, currentBasePath, diffMatches, typeList, cursors);
|
||||
ElementDefinition currentRes = processSimplePath(currentBase, currentBasePath, diffMatches, typeList, cursors, mapHelper);
|
||||
if (res == null) {
|
||||
res = currentRes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
processPathWithSlicedBase(currentBase, currentBasePath, diffMatches, typeList, cursors);
|
||||
processPathWithSlicedBase(currentBase, currentBasePath, diffMatches, typeList, cursors, mapHelper);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,26 +239,26 @@ public class ProfilePathProcessor {
|
|||
final String currentBasePath,
|
||||
final List<ElementDefinition> diffMatches,
|
||||
final List<TypeSlice> typeList,
|
||||
final ProfilePathProcessorState cursors) throws FHIRException {
|
||||
final ProfilePathProcessorState cursors, MappingAssistant mapHelper) throws FHIRException {
|
||||
ElementDefinition res = null;
|
||||
|
||||
// the differential doesn't say anything about this item
|
||||
// so we just copy it in
|
||||
if (diffMatches.isEmpty())
|
||||
processSimplePathWithEmptyDiffMatches(currentBase, currentBasePath, diffMatches, cursors);
|
||||
processSimplePathWithEmptyDiffMatches(currentBase, currentBasePath, diffMatches, cursors, mapHelper);
|
||||
// one matching element in the differential
|
||||
else if (oneMatchingElementInDifferential(getSlicing().isDone(), currentBasePath, diffMatches))
|
||||
res = processSimplePathWithOneMatchingElementInDifferential(currentBase, currentBasePath, diffMatches, cursors);
|
||||
res = processSimplePathWithOneMatchingElementInDifferential(currentBase, currentBasePath, diffMatches, cursors, mapHelper);
|
||||
else if (profileUtilities.diffsConstrainTypes(diffMatches, currentBasePath, typeList))
|
||||
processSimplePathWhereDiffsConstrainTypes(currentBasePath, diffMatches, typeList, cursors);
|
||||
processSimplePathWhereDiffsConstrainTypes(currentBasePath, diffMatches, typeList, cursors, mapHelper);
|
||||
else
|
||||
processSimplePathDefault(currentBase, currentBasePath, diffMatches, cursors);
|
||||
processSimplePathDefault(currentBase, currentBasePath, diffMatches, cursors, mapHelper);
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private void processSimplePathDefault(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors) {
|
||||
private void processSimplePathDefault(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, MappingAssistant mapHelper) {
|
||||
// ok, the differential slices the item. Let's check our pre-conditions to ensure that this is correct
|
||||
if (!profileUtilities.unbounded(currentBase) && !profileUtilities.isSlicedToOneOnly(diffMatches.get(0)))
|
||||
// you can only slice an element that doesn't repeat if the sum total of your slices is limited to 1
|
||||
|
@ -280,7 +281,7 @@ public class ProfilePathProcessor {
|
|||
.withBaseLimit(newBaseLimit)
|
||||
.withDiffLimit(newDiffLimit)
|
||||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, 0)).withSlicing(new PathSlicingParams(true, null, null))
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
if (e == null)
|
||||
throw new FHIRException(profileUtilities.getContext().formatMessage(I18nConstants.DID_NOT_FIND_SINGLE_SLICE_, diffMatches.get(0).getPath()));
|
||||
e.setSlicing(diffMatches.get(0).getSlicing());
|
||||
|
@ -322,7 +323,7 @@ public class ProfilePathProcessor {
|
|||
|
||||
// differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice.
|
||||
if (!diffMatches.get(0).hasSliceName()) {
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), isTrimDifferential(), getUrl(),getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0)));
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), isTrimDifferential(), getUrl(),getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0)), mapHelper);
|
||||
profileUtilities.removeStatusExtensions(outcome);
|
||||
if (!outcome.hasContentReference() && !outcome.hasType() && outcome.getPath().contains(".")) {
|
||||
throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.NOT_DONE_YET));
|
||||
|
@ -350,7 +351,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(currentBasePath)
|
||||
.withContextPathTarget(outcome.getPath()).withSlicing(new PathSlicingParams()) /* starting again on the data type, but skip the root */
|
||||
. processPaths(new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
}
|
||||
start++;
|
||||
|
@ -375,7 +376,7 @@ public class ProfilePathProcessor {
|
|||
.withDiffLimit(newDiffLimit)
|
||||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, i))
|
||||
.withSlicing(new PathSlicingParams(true, slicerElement, null))
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
// ok, done with that - next in the base list
|
||||
cursors.baseCursor = newBaseLimit + 1;
|
||||
|
@ -400,7 +401,7 @@ public class ProfilePathProcessor {
|
|||
return Base.compareDeep(s1.getDiscriminator(), s2.getDiscriminator(), false);
|
||||
}
|
||||
|
||||
private void processSimplePathWhereDiffsConstrainTypes(String currentBasePath, List<ElementDefinition> diffMatches, List<TypeSlice> typeList, ProfilePathProcessorState cursors) {
|
||||
private void processSimplePathWhereDiffsConstrainTypes(String currentBasePath, List<ElementDefinition> diffMatches, List<TypeSlice> typeList, ProfilePathProcessorState cursors, MappingAssistant mapHelper) {
|
||||
int start = 0;
|
||||
int newBaseLimit = profileUtilities.findEndOfElement(cursors.base, cursors.baseCursor);
|
||||
int newDiffCursor = getDifferential().getElement().indexOf(diffMatches.get(0));
|
||||
|
@ -498,7 +499,7 @@ public class ProfilePathProcessor {
|
|||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, 0))
|
||||
.withSlicing(new PathSlicingParams(true, null, null))
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
if (elementDefinition == null)
|
||||
throw new FHIRException(profileUtilities.getContext().formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, path));
|
||||
// now set up slicing on the e (cause it was wiped by what we called.
|
||||
|
@ -531,7 +532,7 @@ public class ProfilePathProcessor {
|
|||
.withDiffLimit(newDiffLimit)
|
||||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, i))
|
||||
.withSlicing(new PathSlicingParams(true, elementDefinition, null))
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
.processPaths(new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
if (typeList.size() > start + 1) {
|
||||
typeSliceElement.setMin(0);
|
||||
}
|
||||
|
@ -576,7 +577,7 @@ public class ProfilePathProcessor {
|
|||
cursors.diffCursor = newDiffLimit + 1;
|
||||
}
|
||||
|
||||
private ElementDefinition processSimplePathWithOneMatchingElementInDifferential(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors) {
|
||||
private ElementDefinition processSimplePathWithOneMatchingElementInDifferential(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, MappingAssistant mapHelper) {
|
||||
ElementDefinition res;
|
||||
ElementDefinition template = null;
|
||||
if (diffMatches.get(0).hasType() && "Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode()) && !profileUtilities.isValidType(diffMatches.get(0).getType().get(0), currentBase)) {
|
||||
|
@ -684,7 +685,7 @@ public class ProfilePathProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), isTrimDifferential(), getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0)));
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), isTrimDifferential(), getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0)), mapHelper);
|
||||
profileUtilities.removeStatusExtensions(outcome);
|
||||
// if (outcome.getPath().endsWith("[x]") && outcome.getType().size() == 1 && !outcome.getType().get(0).getCode().equals("*") && !diffMatches.get(0).hasSlicing()) // if the base profile allows multiple types, but the profile only allows one, rename it
|
||||
// outcome.setPath(outcome.getPath().substring(0, outcome.getPath().length()-3)+Utilities.capitalize(outcome.getType().get(0).getCode()));
|
||||
|
@ -746,7 +747,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(target.getElement().getPath())
|
||||
.withContextPathTarget(diffMatches.get(0).getPath()).withRedirector(profileUtilities.redirectorStack(getRedirector(), outcome, currentBasePath))
|
||||
.withSourceStructureDefinition(target.getSource())
|
||||
.withSlicing(new PathSlicingParams()).processPaths(new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase));
|
||||
.withSlicing(new PathSlicingParams()).processPaths(new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
} else {
|
||||
final int newBaseCursor = cursors.base.getElement().indexOf(target.getElement()) + 1;
|
||||
int newBaseLimit = newBaseCursor;
|
||||
|
@ -761,7 +762,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathTarget(diffMatches.get(0).getPath())
|
||||
.withRedirector(profileUtilities.redirectorStack(getRedirector(), outcome, currentBasePath))
|
||||
.withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
} else {
|
||||
StructureDefinition dt = outcome.getType().size() == 1 ? profileUtilities.getProfileForDataType(outcome.getType().get(0), getWebUrl(), getDerived()) : profileUtilities.getProfileForDataType("Element");
|
||||
|
@ -778,7 +779,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(diffMatches.get(0).getPath()).withContextPathTarget(outcome.getPath()).withRedirector(new ArrayList<ElementRedirection>())
|
||||
.withSlicing(new PathSlicingParams()). /* starting again on the data type, but skip the root */
|
||||
processPaths(new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -864,7 +865,7 @@ public class ProfilePathProcessor {
|
|||
}
|
||||
|
||||
|
||||
private void processSimplePathWithEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors) {
|
||||
private void processSimplePathWithEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, MappingAssistant mapHelper) {
|
||||
ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy());
|
||||
outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource()));
|
||||
profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl());
|
||||
|
@ -884,7 +885,7 @@ public class ProfilePathProcessor {
|
|||
// did we implicitly step into a new type?
|
||||
if (baseHasChildren(cursors.base, currentBase)) { // not a new type here
|
||||
|
||||
this.incrementDebugIndent().withSlicing(new PathSlicingParams()). processPaths( new ProfilePathProcessorState(cursors.base, cursors.baseCursor + 1, cursors.diffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
this.incrementDebugIndent().withSlicing(new PathSlicingParams()). processPaths( new ProfilePathProcessorState(cursors.base, cursors.baseCursor + 1, cursors.diffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
cursors.baseCursor = indexOfFirstNonChild(cursors.base, currentBase, cursors.baseCursor + 1, getBaseLimit());
|
||||
}
|
||||
else {
|
||||
|
@ -933,7 +934,7 @@ public class ProfilePathProcessor {
|
|||
.withRedirector(profileUtilities.redirectorStack(getRedirector(), outcome, currentBasePath))
|
||||
.withSourceStructureDefinition(tgt.getSource())
|
||||
.withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start - 1, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
} else {
|
||||
int newBaseCursor = cursors.base.getElement().indexOf(tgt.getElement()) + 1;
|
||||
int newBaseLimit = newBaseCursor;
|
||||
|
@ -948,7 +949,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(tgt.getElement().getPath())
|
||||
.withContextPathTarget(outcome.getPath())
|
||||
.withRedirector(profileUtilities.redirectorStack(getRedirector(), outcome, currentBasePath)).withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, newBaseCursor, start, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
} else {
|
||||
StructureDefinition dt = outcome.getType().size() > 1 ? profileUtilities.getContext().fetchTypeDefinition("Element") : profileUtilities.getProfileForDataType(outcome.getType().get(0), getWebUrl(), getDerived());
|
||||
|
@ -967,7 +968,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathTarget(outcome.getPath())
|
||||
.withSlicing(new PathSlicingParams()).processPaths( /* starting again on the data type, but skip the root */
|
||||
new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
} else {
|
||||
|
||||
this
|
||||
|
@ -979,7 +980,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathTarget( outcome.getPath())
|
||||
.withRedirector(profileUtilities.redirectorStack(getRedirector(), currentBase, currentBasePath)).withSlicing(new PathSlicingParams()).processPaths( /* starting again on the data type, but skip the root */
|
||||
new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -991,7 +992,7 @@ public class ProfilePathProcessor {
|
|||
ElementDefinition currentBase,
|
||||
String currentBasePath,
|
||||
List<ElementDefinition> diffMatches, List<TypeSlice> typeList,
|
||||
final ProfilePathProcessorState cursors
|
||||
final ProfilePathProcessorState cursors, MappingAssistant mapHelper
|
||||
) {
|
||||
// the item is already sliced in the base profile.
|
||||
// here's the rules
|
||||
|
@ -1004,19 +1005,19 @@ public class ProfilePathProcessor {
|
|||
String path = currentBase.getPath();
|
||||
|
||||
if (diffMatches.isEmpty()) {
|
||||
processPathWithSlicedBaseAndEmptyDiffMatches(currentBase, currentBasePath, diffMatches, cursors, path);
|
||||
processPathWithSlicedBaseAndEmptyDiffMatches(currentBase, currentBasePath, diffMatches, cursors, path, mapHelper);
|
||||
}
|
||||
else if (profileUtilities.diffsConstrainTypes(diffMatches, currentBasePath, typeList))
|
||||
{
|
||||
processPathWithSlicedBaseWhereDiffsConstrainTypes(currentBasePath, diffMatches, typeList, cursors);
|
||||
processPathWithSlicedBaseWhereDiffsConstrainTypes(currentBasePath, diffMatches, typeList, cursors, mapHelper);
|
||||
}
|
||||
else
|
||||
{
|
||||
processPathWithSlicedBaseDefault(currentBase, currentBasePath, diffMatches, cursors, path);
|
||||
processPathWithSlicedBaseDefault(currentBase, currentBasePath, diffMatches, cursors, path, mapHelper);
|
||||
}
|
||||
}
|
||||
|
||||
private void processPathWithSlicedBaseDefault(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, String path) {
|
||||
private void processPathWithSlicedBaseDefault(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, String path, MappingAssistant mapHelper) {
|
||||
// first - check that the slicing is ok
|
||||
boolean closed = currentBase.getSlicing().getRules() == ElementDefinition.SlicingRules.CLOSED;
|
||||
int diffpos = 0;
|
||||
|
@ -1037,7 +1038,7 @@ public class ProfilePathProcessor {
|
|||
profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl());
|
||||
if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) {
|
||||
profileUtilities.updateFromSlicing(outcome.getSlicing(), diffMatches.get(0).getSlicing());
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), closed, getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0))); // if there's no slice, we don't want to update the unsliced description
|
||||
profileUtilities.updateFromDefinition(outcome, diffMatches.get(0), getProfileName(), closed, getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffMatches.get(0)), mapHelper); // if there's no slice, we don't want to update the unsliced description
|
||||
profileUtilities.removeStatusExtensions(outcome);
|
||||
} else if (!diffMatches.get(0).hasSliceName()) {
|
||||
diffMatches.get(0).setUserData(profileUtilities.UD_GENERATED_IN_SNAPSHOT, outcome); // because of updateFromDefinition isn't called
|
||||
|
@ -1076,7 +1077,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(currentBasePath).withContextPathTarget(outcome.getPath())
|
||||
.withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(dt.getSnapshot(), 1, newDiffCursor,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
} else {
|
||||
|
||||
this
|
||||
|
@ -1086,7 +1087,7 @@ public class ProfilePathProcessor {
|
|||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, 0))
|
||||
.withRedirector(null).withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor + 1, newDiffCursor,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
// throw new Error("Not done yet");
|
||||
// } else if (currentBase.getType().get(0).getCode().equals("BackboneElement") && diffMatches.size() > 0 && diffMatches.get(0).hasSliceName()) {
|
||||
|
@ -1127,7 +1128,7 @@ public class ProfilePathProcessor {
|
|||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, diffpos))
|
||||
.withTrimDifferential(closed)
|
||||
.withSlicing(new PathSlicingParams(true, null, null)).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
// ok, done with that - now set the cursors for if this is the end
|
||||
cursors.baseCursor = newBaseLimit;
|
||||
cursors.diffCursor = newDiffLimit + 1;
|
||||
|
@ -1175,7 +1176,7 @@ public class ProfilePathProcessor {
|
|||
throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.ADDING_WRONG_PATH));
|
||||
debugCheck(outcome);
|
||||
getResult().getElement().add(outcome);
|
||||
profileUtilities.updateFromDefinition(outcome, diffItem, getProfileName(), isTrimDifferential(), getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffItem));
|
||||
profileUtilities.updateFromDefinition(outcome, diffItem, getProfileName(), isTrimDifferential(), getUrl(), getSourceStructureDefinition(), getDerived(), diffPath(diffItem), mapHelper);
|
||||
profileUtilities.removeStatusExtensions(outcome);
|
||||
// --- LM Added this
|
||||
cursors.diffCursor = getDifferential().getElement().indexOf(diffItem) + 1;
|
||||
|
@ -1204,7 +1205,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathTarget(cursors.base.getElement().get(0).getPath())
|
||||
.withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, baseStart, start - 1,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
} else {
|
||||
StructureDefinition dt = profileUtilities.getProfileForDataType(outcome.getType().get(0), getWebUrl(), getDerived());
|
||||
// if (t.getCode().equals("Extension") && t.hasProfile() && !t.getProfile().contains(":")) {
|
||||
|
@ -1225,7 +1226,7 @@ public class ProfilePathProcessor {
|
|||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, 0))
|
||||
.withContextPathSource(diffMatches.get(0).getPath()).withContextPathTarget(outcome.getPath()).withSlicing(new PathSlicingParams()).processPaths( /* starting again on the data type, but skip the root */
|
||||
new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start - 1,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1243,7 +1244,7 @@ public class ProfilePathProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
private void processPathWithSlicedBaseWhereDiffsConstrainTypes(String currentBasePath, List<ElementDefinition> diffMatches, List<TypeSlice> typeList, ProfilePathProcessorState cursors) {
|
||||
private void processPathWithSlicedBaseWhereDiffsConstrainTypes(String currentBasePath, List<ElementDefinition> diffMatches, List<TypeSlice> typeList, ProfilePathProcessorState cursors, MappingAssistant mapHelper) {
|
||||
int start = 0;
|
||||
int newBaseLimit = profileUtilities.findEndOfElement(cursors.base, cursors.baseCursor);
|
||||
int newDiffCursor = getDifferential().getElement().indexOf(diffMatches.get(0));
|
||||
|
@ -1329,7 +1330,7 @@ public class ProfilePathProcessor {
|
|||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches,0))
|
||||
.withSlicing(new PathSlicingParams(true, null, currentBasePath)).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor, newDiffCursor,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
if (e == null)
|
||||
throw new FHIRException(profileUtilities.getContext().formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath()));
|
||||
// now set up slicing on the e (cause it was wiped by what we called.
|
||||
|
@ -1369,7 +1370,7 @@ public class ProfilePathProcessor {
|
|||
.withDiffLimit(newDiffLimit)
|
||||
.withProfileName(getProfileName() + profileUtilities.pathTail(diffMatches, i))
|
||||
.withSlicing(new PathSlicingParams(true, e, currentBasePath)).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, sStart, newDiffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, sStart, newDiffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
if (elementToRemove != null) {
|
||||
getDifferential().getElement().remove(elementToRemove);
|
||||
|
@ -1395,7 +1396,7 @@ public class ProfilePathProcessor {
|
|||
.withBaseLimit(bs.getEnd())
|
||||
.withDiffLimit(0)
|
||||
.withProfileName(getProfileName() + profileUtilities.tail(bs.getDefn().getPath())).withSlicing(new PathSlicingParams(true, e, currentBasePath)).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, bs.getStart(), 0, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, bs.getStart(), 0, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1405,7 +1406,7 @@ public class ProfilePathProcessor {
|
|||
//throw new Error("not done yet - slicing / types @ "+cpath);
|
||||
}
|
||||
|
||||
private void processPathWithSlicedBaseAndEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, String path) {
|
||||
private void processPathWithSlicedBaseAndEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List<ElementDefinition> diffMatches, ProfilePathProcessorState cursors, String path, MappingAssistant mapHelper) {
|
||||
if (profileUtilities.hasInnerDiffMatches(getDifferential(), path, cursors.diffCursor, getDiffLimit(), cursors.base.getElement(), true)) {
|
||||
// so we just copy it in
|
||||
ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy());
|
||||
|
@ -1425,7 +1426,7 @@ public class ProfilePathProcessor {
|
|||
this
|
||||
.incrementDebugIndent()
|
||||
.withSlicing(new PathSlicingParams()).processPaths(
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor + 1, cursors.diffCursor, cursors.contextName, cursors.resultPathBase));
|
||||
new ProfilePathProcessorState(cursors.base, cursors.baseCursor + 1, cursors.diffCursor, cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
cursors.baseCursor = indexOfFirstNonChild(cursors.base, currentBase, cursors.baseCursor, getBaseLimit());
|
||||
} else {
|
||||
StructureDefinition dt = profileUtilities.getTypeForElement(getDifferential(), cursors.diffCursor, getProfileName(), diffMatches, outcome, getWebUrl(), getDerived());
|
||||
|
@ -1447,7 +1448,7 @@ public class ProfilePathProcessor {
|
|||
.withContextPathSource(currentBasePath)
|
||||
.withContextPathTarget(outcome.getPath()).withSlicing(new PathSlicingParams()).processPaths( /* starting again on the data type, but skip the root */
|
||||
new ProfilePathProcessorState(dt.getSnapshot(), 1 /* starting again on the data type, but skip the root */, start,
|
||||
cursors.contextName, cursors.resultPathBase));
|
||||
cursors.contextName, cursors.resultPathBase), mapHelper);
|
||||
}
|
||||
}
|
||||
cursors.baseCursor++;
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.hl7.fhir.exceptions.DefinitionException;
|
|||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.conformance.ElementRedirection;
|
||||
import org.hl7.fhir.r5.conformance.profile.MappingAssistant.MappingMergeModeOption;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.AllowUnknownProfile;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.ElementDefinitionCounter;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
|
@ -205,13 +206,6 @@ public class ProfileUtilities {
|
|||
|
||||
}
|
||||
|
||||
public enum MappingMergeModeOption {
|
||||
DUPLICATE, // if there's more than one mapping for the same URI, just keep them all
|
||||
IGNORE, // if there's more than one, keep the first
|
||||
OVERWRITE, // if there's opre than, keep the last
|
||||
APPEND, // if there's more than one, append them with ';'
|
||||
}
|
||||
|
||||
public enum AllowUnknownProfile {
|
||||
NONE, // exception if there's any unknown profiles (the default)
|
||||
NON_EXTNEIONS, // don't raise an exception except on Extension (because more is going on there
|
||||
|
@ -640,26 +634,6 @@ public class ProfileUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateMaps(StructureDefinition base, StructureDefinition derived) throws DefinitionException {
|
||||
if (base == null)
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.NO_BASE_PROFILE_PROVIDED));
|
||||
if (derived == null)
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.NO_DERIVED_STRUCTURE_PROVIDED));
|
||||
|
||||
for (StructureDefinitionMappingComponent baseMap : base.getMapping()) {
|
||||
boolean found = false;
|
||||
for (StructureDefinitionMappingComponent derivedMap : derived.getMapping()) {
|
||||
if (derivedMap.getUri() != null && derivedMap.getUri().equals(baseMap.getUri())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
derived.getMapping().add(baseMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a base (snapshot) profile structure, and a differential profile, generate a new snapshot profile
|
||||
*
|
||||
|
@ -752,7 +726,9 @@ public class ProfileUtilities {
|
|||
// debug = true;
|
||||
// }
|
||||
|
||||
ProfilePathProcessor.processPaths(this, base, derived, url, webUrl, diff, baseSnapshot);
|
||||
MappingAssistant mappingDetails = new MappingAssistant(mappingMergeMode, base, derived, context.getVersion());
|
||||
|
||||
ProfilePathProcessor.processPaths(this, base, derived, url, webUrl, diff, baseSnapshot, mappingDetails);
|
||||
|
||||
checkGroupConstraints(derived);
|
||||
if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
|
||||
|
@ -761,7 +737,7 @@ public class ProfileUtilities {
|
|||
if (!e.hasUserData(UD_GENERATED_IN_SNAPSHOT) && e.getPath().contains(".")) {
|
||||
ElementDefinition existing = getElementInCurrentContext(e.getPath(), derived.getSnapshot().getElement());
|
||||
if (existing != null) {
|
||||
updateFromDefinition(existing, e, profileName, false, url, base, derived, "StructureDefinition.differential.element["+i+"]");
|
||||
updateFromDefinition(existing, e, profileName, false, url, base, derived, "StructureDefinition.differential.element["+i+"]", mappingDetails);
|
||||
} else {
|
||||
ElementDefinition outcome = updateURLs(url, webUrl, e.copy());
|
||||
e.setUserData(UD_GENERATED_IN_SNAPSHOT, outcome);
|
||||
|
@ -781,7 +757,7 @@ public class ProfileUtilities {
|
|||
|
||||
if (derived.getKind() != StructureDefinitionKind.LOGICAL && !derived.getSnapshot().getElementFirstRep().getType().isEmpty())
|
||||
throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_, derived.getSnapshot().getElementFirstRep().getPath(), derived.getUrl(), base.getUrl()));
|
||||
updateMaps(base, derived);
|
||||
mappingDetails.update();
|
||||
|
||||
setIds(derived, false);
|
||||
if (debug) {
|
||||
|
@ -2374,7 +2350,7 @@ public class ProfileUtilities {
|
|||
}
|
||||
|
||||
|
||||
protected void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD, StructureDefinition derivedSrc, String path) throws DefinitionException, FHIRException {
|
||||
protected void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD, StructureDefinition derivedSrc, String path, MappingAssistant mappings) throws DefinitionException, FHIRException {
|
||||
source.setUserData(UD_GENERATED_IN_SNAPSHOT, dest);
|
||||
// we start with a clone of the base profile ('dest') and we copy from the profile ('source')
|
||||
// over the top for anything the source has
|
||||
|
@ -2845,18 +2821,7 @@ public class ProfileUtilities {
|
|||
t.setUserData(UD_DERIVATION_EQUALS, true);
|
||||
}
|
||||
|
||||
List<ElementDefinitionMappingComponent> list = new ArrayList<>();
|
||||
list.addAll(base.getMapping());
|
||||
base.getMapping().clear();
|
||||
addMappings(base.getMapping(), list);
|
||||
if (derived.hasMapping()) {
|
||||
addMappings(base.getMapping(), derived.getMapping());
|
||||
}
|
||||
for (ElementDefinitionMappingComponent m : base.getMapping()) {
|
||||
if (m.hasMap()) {
|
||||
m.setMap(m.getMap().trim());
|
||||
}
|
||||
}
|
||||
mappings.merge(derived, base); // note reversal of names to be correct in .merge()
|
||||
|
||||
// todo: constraints are cumulative. there is no replacing
|
||||
for (ElementDefinitionConstraintComponent s : base.getConstraint()) {
|
||||
|
@ -2960,52 +2925,6 @@ public class ProfileUtilities {
|
|||
tgt.getExtension().addAll(src.getExtension());
|
||||
}
|
||||
|
||||
private void addMappings(List<ElementDefinitionMappingComponent> destination, List<ElementDefinitionMappingComponent> source) {
|
||||
for (ElementDefinitionMappingComponent s : source) {
|
||||
boolean found = false;
|
||||
for (ElementDefinitionMappingComponent d : destination) {
|
||||
if (compareMaps(s, d)) {
|
||||
found = true;
|
||||
d.setUserData(UD_DERIVATION_EQUALS, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
destination.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean compareMaps(ElementDefinitionMappingComponent s, ElementDefinitionMappingComponent d) {
|
||||
if (d.getIdentity().equals(s.getIdentity()) && d.getMap().equals(s.getMap())) {
|
||||
return true;
|
||||
}
|
||||
if (VersionUtilities.isR5Plus(context.getVersion())) {
|
||||
if (d.getIdentity().equals(s.getIdentity())) {
|
||||
switch (mappingMergeMode) {
|
||||
case APPEND:
|
||||
if (!Utilities.splitStrings(d.getMap(), "\\,").contains(s.getMap())) {
|
||||
d.setMap(d.getMap()+","+s.getMap());
|
||||
}
|
||||
return true;
|
||||
case DUPLICATE:
|
||||
return false;
|
||||
case IGNORE:
|
||||
d.setMap(s.getMap());
|
||||
return true;
|
||||
case OVERWRITE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTypeDerivation(String purl, StructureDefinition srcSD, ElementDefinition base, ElementDefinition derived, TypeRefComponent ts, String path) {
|
||||
boolean ok = false;
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
|
|
|
@ -3735,20 +3735,20 @@ public class FHIRPathEngine {
|
|||
|
||||
case LowBoundary:
|
||||
case HighBoundary: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, true);
|
||||
if (paramTypes.size() > 0) {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer));
|
||||
}
|
||||
if (focus.hasType("decimal") && (focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
if ((focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime);
|
||||
} else if (focus.hasType("decimal")) {
|
||||
} else if (focus.hasType("decimal") || focus.hasType("integer")) {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal);
|
||||
} else {
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_DateTime);
|
||||
}
|
||||
}
|
||||
case Precision: {
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp);
|
||||
checkContextContinuous(focus, exp.getFunction().toCode(), exp, false);
|
||||
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Integer);
|
||||
}
|
||||
case hasTemplateIdOf: {
|
||||
|
@ -3897,8 +3897,8 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time") && !focus.hasType("Quantity")) {
|
||||
private void checkContextContinuous(TypeDetails focus, String name, ExpressionNode expr, boolean allowInteger) throws PathEngineException {
|
||||
if (!focus.hasNoTypes() && !focus.hasType("decimal") && !focus.hasType("date") && !focus.hasType("dateTime") && !focus.hasType("time") && !focus.hasType("Quantity") && !(allowInteger && focus.hasType("integer"))) {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_CONTINUOUS_ONLY, name, focus.describe());
|
||||
}
|
||||
}
|
||||
|
@ -4295,7 +4295,7 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "lowBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
|
@ -4308,17 +4308,23 @@ public class FHIRPathEngine {
|
|||
List<Base> result = new ArrayList<Base>();
|
||||
|
||||
if (base.hasType("decimal")) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.lowBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.lowBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.lowBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.lowBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
|
@ -4333,7 +4339,7 @@ public class FHIRPathEngine {
|
|||
if (focus.size() > 1) {
|
||||
throw makeExceptionPlural(focus.size(), expr, I18nConstants.FHIRPATH_FOCUS, "highBoundary", focus.size());
|
||||
}
|
||||
int precision = 0;
|
||||
Integer precision = null;
|
||||
if (expr.getParameters().size() > 0) {
|
||||
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
|
||||
if (n1.size() != 1) {
|
||||
|
@ -4346,17 +4352,23 @@ public class FHIRPathEngine {
|
|||
Base base = focus.get(0);
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
if (base.hasType("decimal")) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == 0 ? 8 : precision)));
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("integer")) {
|
||||
if (precision == null || (precision >= 0 && precision < 17)) {
|
||||
result.add(new DecimalType(Utilities.highBoundaryForDecimal(base.primitiveValue(), precision == null ? 8 : precision)));
|
||||
}
|
||||
} else if (base.hasType("date")) {
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 10 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 10 : precision)));
|
||||
} else if (base.hasType("dateTime")) {
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == 0 ? 17 : precision)));
|
||||
result.add(new DateTimeType(Utilities.highBoundaryForDate(base.primitiveValue(), precision == null ? 17 : precision)));
|
||||
} else if (base.hasType("time")) {
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == 0 ? 9 : precision)));
|
||||
result.add(new TimeType(Utilities.highBoundaryForTime(base.primitiveValue(), precision == null ? 9 : precision)));
|
||||
} else if (base.hasType("Quantity")) {
|
||||
String value = getNamedValue(base, "value");
|
||||
Base v = base.copy();
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == 0 ? 8 : precision)));
|
||||
v.setProperty("value", new DecimalType(Utilities.highBoundaryForDecimal(value, precision == null ? 8 : precision)));
|
||||
result.add(v);
|
||||
} else {
|
||||
makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "sqrt", "(focus)", base.fhirType(), "decimal or date");
|
||||
|
|
|
@ -5625,6 +5625,11 @@ public boolean hasTarget() {
|
|||
|
||||
@Block()
|
||||
public static class ElementDefinitionMappingComponent extends Element implements IBaseDatatypeElement {
|
||||
@Override
|
||||
public String toString() {
|
||||
return identity+"=" + map;
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal reference to the definition of a mapping.
|
||||
*/
|
||||
|
|
|
@ -397,6 +397,11 @@ public class StructureDefinition extends CanonicalResource {
|
|||
|
||||
@Block()
|
||||
public static class StructureDefinitionMappingComponent extends BackboneElement implements IBaseBackboneElement {
|
||||
@Override
|
||||
public String toString() {
|
||||
return identity + "=" + uri + " (\""+name+"\")";
|
||||
}
|
||||
|
||||
/**
|
||||
* An Internal id that is used to identify this mapping set when specific mappings are made.
|
||||
*/
|
||||
|
|
|
@ -579,8 +579,8 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
if (!ccm.hasRelationship())
|
||||
tr.td();
|
||||
else {
|
||||
if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
|
||||
String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
|
||||
if (ccm.hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
|
||||
String code = ToolingExtensions.readStringExtension(ccm, ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
|
||||
tr.td().ah(context.prefixLocalHref(eqpath+"#"+code), code).tx(presentEquivalenceCode(code));
|
||||
} else {
|
||||
tr.td().ah(context.prefixLocalHref(eqpath+"#"+ccm.getRelationship().toCode()), ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode()));
|
||||
|
|
|
@ -332,13 +332,14 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
} else if (!round2 && !exemptFromRendering(child)) {
|
||||
if (isExtension(p)) {
|
||||
boolean isExt = isExtension(p);
|
||||
if (isExt) {
|
||||
status.setExtensions(true);
|
||||
}
|
||||
List<ElementDefinition> grandChildren = getChildrenForPath(profile, allElements, path+"."+p.getName());
|
||||
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
||||
if (p.getValues().size() > 0) {
|
||||
if (isSimple(child)) {
|
||||
if (isSimple(child) && !isExt) {
|
||||
XhtmlNode para = x.isPara() ? para = x : x.para();
|
||||
String name = p.getName();
|
||||
if (name.endsWith("[x]"))
|
||||
|
@ -383,22 +384,40 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
x.add(tbl);
|
||||
}
|
||||
} else if (isExtension(p)) {
|
||||
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, p.getUrl());
|
||||
for (ResourceWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
ResourceWrapper vp = v.child("value");
|
||||
List<ResourceWrapper> ev = v.children("extension");
|
||||
if (vp != null) {
|
||||
XhtmlNode para = x.para();
|
||||
para.b().addText(labelforExtension(p.getName()));
|
||||
para.b().addText(labelforExtension(sd, p.getUrl()));
|
||||
para.tx(": ");
|
||||
renderLeaf(status, res, vp, profile, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
} else if (!ev.isEmpty()) {
|
||||
XhtmlNode bq = x.addTag("blockquote");
|
||||
bq.para().b().addText(labelforExtension(p.getName()));
|
||||
XhtmlNode bq = x.addTag("blockquote");
|
||||
bq.para().b().addText(labelforExtension(sd, p.getUrl()));
|
||||
// what happens now depends. If all the children are simple extensions, they'll be rendered as properties
|
||||
boolean allSimple = true;
|
||||
for (ResourceWrapper vv : ev) {
|
||||
StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension");
|
||||
List<ElementDefinition> children = getChildrenForPath(profile, ex.getSnapshot().getElement(), "Extension");
|
||||
generateByProfile(status, res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1);
|
||||
if (!vv.has("value")) {
|
||||
allSimple = false;
|
||||
}
|
||||
}
|
||||
if (allSimple) {
|
||||
XhtmlNode ul = bq.ul();
|
||||
for (ResourceWrapper vv : ev) {
|
||||
XhtmlNode li = ul.li();
|
||||
li.tx(labelForSubExtension(vv.primitiveValue("url"), sd));
|
||||
li.tx(": ");
|
||||
renderLeaf(status, res, vv.child("value"), sd, child, x, li, isExt, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
} else {
|
||||
for (ResourceWrapper vv : ev) {
|
||||
StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension");
|
||||
List<ElementDefinition> children = getChildrenForPath(profile, ex.getSnapshot().getElement(), "Extension");
|
||||
generateByProfile(status, res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,8 +436,11 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
|
||||
private String labelforExtension(String url) {
|
||||
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, url);
|
||||
private String labelForSubExtension(String url, StructureDefinition sd) {
|
||||
return url;
|
||||
}
|
||||
|
||||
private String labelforExtension(StructureDefinition sd, String url) {
|
||||
if (sd == null) {
|
||||
return tail(url);
|
||||
} else {
|
||||
|
@ -467,7 +489,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
public boolean isExtension(NamedResourceWrapperList p) {
|
||||
return p.getName().contains("extension[");
|
||||
return p.getUrl() != null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -571,12 +593,12 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
// 2. Park it
|
||||
NamedResourceWrapperList nl = null;
|
||||
for (NamedResourceWrapperList t : results) {
|
||||
if (t.getName().equals(url)) {
|
||||
if (t.getUrl() != null && t.getUrl().equals(url)) {
|
||||
nl = t;
|
||||
}
|
||||
}
|
||||
if (nl == null) {
|
||||
nl = new NamedResourceWrapperList(url);
|
||||
nl = new NamedResourceWrapperList(p.getName(), url);
|
||||
results.add(nl);
|
||||
}
|
||||
nl.getValues().add(v);
|
||||
|
|
|
@ -578,14 +578,16 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
protected void renderUri(RenderingStatus status, XhtmlNode x, ResourceWrapper uri) throws FHIRFormatError, DefinitionException, IOException {
|
||||
if (!renderPrimitiveWithNoValue(status, x, uri)) {
|
||||
String v = uri.primitiveValue();
|
||||
boolean local = false;
|
||||
|
||||
if (context.getContextUtilities().isResource(v)) {
|
||||
v = "http://hl7.org/fhir/StructureDefinition/"+v;
|
||||
local = true;
|
||||
}
|
||||
if (v.startsWith("mailto:")) {
|
||||
x.ah(v).addText(v.substring(7));
|
||||
} else {
|
||||
ResourceWithReference rr = resolveReference(uri);
|
||||
ResourceWithReference rr = local ? resolveReference(uri.resource(), v, true) : resolveReference(uri);
|
||||
if (rr != null) {
|
||||
if (rr.getResource() == null) {
|
||||
x.ah(context.prefixLocalHref(rr.getWebPath())).addText(rr.getUrlReference());
|
||||
|
|
|
@ -31,16 +31,28 @@ public abstract class ResourceWrapper {
|
|||
|
||||
public static class NamedResourceWrapperList {
|
||||
private String name;
|
||||
private String url; // for extension definitions
|
||||
private List<ResourceWrapper> values = new ArrayList<ResourceWrapper>();
|
||||
|
||||
|
||||
public NamedResourceWrapperList(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public NamedResourceWrapperList(String name, String url) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public List<ResourceWrapper> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
|
|
@ -275,6 +275,7 @@ public class ToolingExtensions {
|
|||
public static final String EXT_VS_CS_SUPPL_NEEDED = "http://hl7.org/fhir/StructureDefinition/valueset-supplement";
|
||||
public static final String EXT_TYPE_PARAMETER = "http://hl7.org/fhir/tools/StructureDefinition/type-parameter";
|
||||
public static final String EXT_ALTERNATE_CANONICAL = "http://hl7.org/fhir/StructureDefinition/alternate-canonical";
|
||||
public static final String EXT_SUPPRESSED = "http://hl7.org/fhir/StructureDefinition/elementdefinition-suppress";
|
||||
|
||||
// specific extension helpers
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hl7.fhir.r5.formats.JsonParser;
|
|||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.r5.model.Narrative;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
|
@ -582,6 +583,9 @@ public class SnapShotGenerationTests {
|
|||
rc.setProfileUtilities(new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), null, new TestPKP()));
|
||||
RendererFactory.factory(output, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), output));
|
||||
}
|
||||
// we just generated it - but we don't care what it is here, just that there's no exceptions (though we need it for the rules)
|
||||
Narrative txt = output.getText();
|
||||
output.setText(null);
|
||||
if (!fail) {
|
||||
test.output = output;
|
||||
TestingUtilities.getSharedWorkerContext().cacheResource(output);
|
||||
|
@ -603,6 +607,7 @@ public class SnapShotGenerationTests {
|
|||
}
|
||||
Assertions.assertTrue(structureDefinitionEquality, "Output does not match expected");
|
||||
}
|
||||
output.setText(txt);
|
||||
}
|
||||
|
||||
private StructureDefinition getSD(String url, SnapShotGenerationTestsContext context) throws DefinitionException, FHIRException, IOException {
|
||||
|
|
|
@ -1695,31 +1695,47 @@ public class Utilities {
|
|||
value = value.substring(0, value.indexOf("e"));
|
||||
}
|
||||
if (isZero(value)) {
|
||||
return applyPrecision("-0.5000000000000000000000000", precision);
|
||||
return applyPrecision("-0.5000000000000000000000000", precision, true);
|
||||
} else if (value.startsWith("-")) {
|
||||
return "-"+highBoundaryForDecimal(value.substring(1), precision)+(e == null ? "" : e);
|
||||
} else {
|
||||
if (value.contains(".")) {
|
||||
return applyPrecision(minusOne(value)+"50000000000000000000000000000", precision)+(e == null ? "" : e);
|
||||
return applyPrecision(minusOne(value)+"50000000000000000000000000000", precision, true)+(e == null ? "" : e);
|
||||
} else {
|
||||
return applyPrecision(minusOne(value)+".50000000000000000000000000000", precision)+(e == null ? "" : e);
|
||||
return applyPrecision(minusOne(value)+".50000000000000000000000000000", precision, true)+(e == null ? "" : e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String applyPrecision(String v, int p) {
|
||||
private static String applyPrecision(String v, int p, boolean down) {
|
||||
String nv = v;
|
||||
int dp = -1;
|
||||
if (nv.contains(".")) {
|
||||
dp = nv.indexOf(".");
|
||||
nv = nv.substring(0, dp)+nv.substring(dp+1);
|
||||
}
|
||||
String s = null;
|
||||
int d = p - getDecimalPrecision(v);
|
||||
if (d == 0) {
|
||||
return v;
|
||||
s = nv;
|
||||
} else if (d > 0) {
|
||||
return v + padLeft("", '0', d);
|
||||
s = nv + padLeft("", '0', d);
|
||||
} else {
|
||||
if (v.charAt(v.length()+d) >= '6') {
|
||||
return v.substring(0, v.length()+d-1)+((char) (v.charAt(v.length()+d)+1));
|
||||
int l = v.length();
|
||||
int ld = l+d;
|
||||
if (dp > -1) {
|
||||
ld--;
|
||||
}
|
||||
if (nv.charAt(ld) >= '5' && !down) {
|
||||
s = nv.substring(0, ld-1)+((char) (nv.charAt(ld-1)+1));
|
||||
} else {
|
||||
return v.substring(0, v.length()+d);
|
||||
s = nv.substring(0, ld);
|
||||
}
|
||||
}
|
||||
if (s.endsWith(".")) {
|
||||
s = s.substring(0, s.length()-1);
|
||||
}
|
||||
return dp == -1 || dp >= s.length() ? s : s.substring(0, dp)+"."+s.substring(dp);
|
||||
}
|
||||
|
||||
private static String minusOne(String value) {
|
||||
|
@ -1831,14 +1847,14 @@ public class Utilities {
|
|||
value = value.substring(0, value.indexOf("e"));
|
||||
}
|
||||
if (isZero(value)) {
|
||||
return applyPrecision("0.50000000000000000000000000000", precision);
|
||||
return applyPrecision("0.50000000000000000000000000000", precision, false);
|
||||
} else if (value.startsWith("-")) {
|
||||
return "-"+lowBoundaryForDecimal(value.substring(1), precision)+(e == null ? "" : e);
|
||||
} else {
|
||||
if (value.contains(".")) {
|
||||
return applyPrecision(value+"50000000000000000000000000000", precision)+(e == null ? "" : e);
|
||||
return applyPrecision(value+"50000000000000000000000000000", precision, false)+(e == null ? "" : e);
|
||||
} else {
|
||||
return applyPrecision(value+".50000000000000000000000000000", precision)+(e == null ? "" : e);
|
||||
return applyPrecision(value+".50000000000000000000000000000", precision, false)+(e == null ? "" : e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ public class NpmPackageIndexBuilder {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error parsing "+name+": "+e.getMessage());
|
||||
// System.out.println("Error parsing "+name+": "+e.getMessage());
|
||||
if (name.contains("openapi")) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1138,4 +1138,6 @@ TYPE_SPECIFIC_CHECKS_DT_XHTML_LITERAL_HREF = Hyperlink scheme ''{3}'' in ''{0}''
|
|||
SM_TARGET_TYPE_UNKNOWN = The type of the target variable is not known: {0}
|
||||
XHTML_XHTML_ATTRIBUTE_XML_SPACE = The attribute 'xml:space' is legal but has a fixed value of 'preserve'. It''s use is discouraged
|
||||
VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS = This resource has more than workgroup extension (http://hl7.org/fhir/StructureDefinition/structuredefinition-wg)
|
||||
|
||||
NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG = Wrong Display Name ''{0}'' for {1}#{2}. There are no valid display names found for language(s) ''{3}''. Default display is ''{4}''
|
||||
NO_VALID_DISPLAY_AT_ALL = Cannot validate display Name ''{0}'' for {1}#{2}: No displays are known
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ class UtilitiesTest {
|
|||
assertEquals("0.95", Utilities.lowBoundaryForDecimal("1.0", 2));
|
||||
assertEquals("-1.05000000", Utilities.lowBoundaryForDecimal("-1.0", 8));
|
||||
assertEquals("1.23", Utilities.lowBoundaryForDecimal("1.234", 2));
|
||||
assertEquals("1.57", Utilities.lowBoundaryForDecimal("1.567", 2));
|
||||
assertEquals("1.56", Utilities.lowBoundaryForDecimal("1.567", 2));
|
||||
|
||||
assertEquals("0.50000000", Utilities.highBoundaryForDecimal("0", 8));
|
||||
assertEquals("1.500000", Utilities.highBoundaryForDecimal("1", 6));
|
||||
|
|
|
@ -497,10 +497,12 @@ public class IgLoader implements IValidationEngineLoader {
|
|||
private Map<String, ByteProvider> fetchByPackage(String src, boolean loadInContext) throws FHIRException, IOException {
|
||||
NpmPackage pi;
|
||||
|
||||
InputStream stream = directProvider.fetchByPackage(src);
|
||||
if (stream != null) {
|
||||
pi = NpmPackage.fromPackage(stream);
|
||||
return loadPackage(pi, loadInContext);
|
||||
if (directProvider != null) {
|
||||
InputStream stream = directProvider.fetchByPackage(src);
|
||||
if (stream != null) {
|
||||
pi = NpmPackage.fromPackage(stream);
|
||||
return loadPackage(pi, loadInContext);
|
||||
}
|
||||
}
|
||||
String id = src;
|
||||
String version = null;
|
||||
|
|
|
@ -277,7 +277,7 @@ public class ValueSetValidator extends BaseValidator {
|
|||
}
|
||||
if (version == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(system);
|
||||
if (cs != null && !CodeSystemUtilities.isExemptFromMultipleVersionChecking(system)) {
|
||||
if (cs != null && !CodeSystemUtilities.isExemptFromMultipleVersionChecking(system) && fetcher != null) {
|
||||
Set<String> possibleVersions = fetcher.fetchCanonicalResourceVersions(null, valContext.getAppContext(), system);
|
||||
warning(errors, NO_RULE_DATE, IssueType.INVALID, stack, possibleVersions.size() <= 1, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_MULTIPLE_POSSIBLE_VERSIONS,
|
||||
system, cs.getVersion(), CommaSeparatedStringBuilder.join(", ", Utilities.sorted(possibleVersions)));
|
||||
|
|
|
@ -163,6 +163,7 @@ public class TxTester {
|
|||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean runSuite(JsonObject suite, ITerminologyClient tx, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
|
||||
System.out.println("Group "+suite.asString("name"));
|
||||
JsonObject outputS = new JsonObject();
|
||||
|
@ -187,6 +188,7 @@ public class TxTester {
|
|||
if (output != null) {
|
||||
output.add(outputT);
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
Parameters profile = loadProfile(test);
|
||||
outputT.add("name", test.asString("name"));
|
||||
if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) {
|
||||
|
@ -219,7 +221,7 @@ public class TxTester {
|
|||
throw new Exception("Unknown Operation "+test.asString("operation"));
|
||||
}
|
||||
|
||||
System.out.println(msg == null ? "Pass" : "Fail");
|
||||
System.out.println((msg == null ? "Pass" : "Fail") + " ("+Utilities.describeDuration(System.currentTimeMillis() - start)+")");
|
||||
if (msg != null) {
|
||||
System.out.println(" "+msg);
|
||||
error = msg;
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -21,7 +21,7 @@
|
|||
<commons_compress_version>1.26.0</commons_compress_version>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.5.19</validator_test_case_version>
|
||||
<validator_test_case_version>1.5.20-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.17.0</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue