Merge pull request #1484 from hapifhir/2023-11-gg-snapshot-extensions
2023 11 gg snapshot extensions
This commit is contained in:
commit
af07fc7fa6
|
@ -842,6 +842,7 @@ public class ProfilePathProcessor {
|
|||
outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource()));
|
||||
profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl());
|
||||
profileUtilities.updateConstraintSources(outcome, getSourceStructureDefinition().getUrl());
|
||||
profileUtilities.checkExtensions(outcome);
|
||||
profileUtilities.updateFromObligationProfiles(outcome);
|
||||
profileUtilities.updateURLs(url, webUrl, outcome);
|
||||
profileUtilities.markDerived(outcome);
|
||||
|
|
|
@ -218,7 +218,14 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
ALL_TYPES // allow any unknow profile
|
||||
}
|
||||
|
||||
private static final List<String> NON_INHERITED_ED_URLS = Arrays.asList(
|
||||
/**
|
||||
* These extensions are stripped in inherited profiles (and may be replaced by
|
||||
*/
|
||||
|
||||
public static final List<String> NON_INHERITED_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/binding-definition",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/no-binding",
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-category",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm",
|
||||
|
@ -229,10 +236,61 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/obligation-profile",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status-reason",
|
||||
ToolingExtensions.EXT_SUMMARY,
|
||||
ToolingExtensions.EXT_SUMMARY/*,
|
||||
ToolingExtensions.EXT_OBLIGATION_CORE,
|
||||
ToolingExtensions.EXT_OBLIGATION_TOOLS);
|
||||
ToolingExtensions.EXT_OBLIGATION_TOOLS*/);
|
||||
|
||||
public static final List<String> DEFAULT_INHERITED_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-optionRestriction",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-referenceProfile",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption",
|
||||
|
||||
"http://hl7.org/fhir/StructureDefinition/mimeType");
|
||||
|
||||
/**
|
||||
* These extensions are ignored when found in differentials
|
||||
*/
|
||||
public static final List<String> NON_OVERRIDING_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-json-name",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/json-empty-behavior",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/json-nullable",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/json-primitive-choice",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/json-property-key",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/type-specifier",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/xml-choice-group",
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace",
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype"
|
||||
);
|
||||
|
||||
/**
|
||||
* When these extensions are found, they override whatever is set on the ancestor element
|
||||
*/
|
||||
public static final List<String> OVERRIDING_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format",
|
||||
ToolingExtensions.EXT_DATE_RULES,
|
||||
"http://hl7.org/fhir/StructureDefinition/designNote",
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits",
|
||||
"http://hl7.org/fhir/StructureDefinition/elementdefinition-question",
|
||||
"http://hl7.org/fhir/StructureDefinition/entryFormat",
|
||||
"http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces",
|
||||
"http://hl7.org/fhir/StructureDefinition/maxSize",
|
||||
"http://hl7.org/fhir/StructureDefinition/minLength",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-signatureRequired",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-supportLink",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-unitValueSet",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-usageMode",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"
|
||||
);
|
||||
|
||||
public IWorkerContext getContext() {
|
||||
return this.context;
|
||||
|
@ -1937,7 +1995,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (Character.isWhitespace(ch)) {
|
||||
// found the end of the processible link:
|
||||
String url = markdown.substring(linkLeft, i);
|
||||
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
|
||||
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames, webUrl)) {
|
||||
b.append(basePath);
|
||||
if (!Utilities.noString(basePath) && !basePath.endsWith("/")) {
|
||||
b.append("/");
|
||||
|
@ -1967,7 +2025,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
// This code is trying to guess which relative references are actually to the
|
||||
// base specification.
|
||||
//
|
||||
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames)) {
|
||||
if (isLikelySourceURLReference(url, resourceNames, baseFilenames, localFilenames, webUrl)) {
|
||||
b.append("](");
|
||||
b.append(basePath);
|
||||
if (!Utilities.noString(basePath) && !basePath.endsWith("/")) {
|
||||
|
@ -2013,7 +2071,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
|
||||
private static boolean isLikelySourceURLReference(String url, List<String> resourceNames, Set<String> baseFilenames, Set<String> localFilenames) {
|
||||
private static boolean isLikelySourceURLReference(String url, List<String> resourceNames, Set<String> baseFilenames, Set<String> localFilenames, String baseUrl) {
|
||||
if (url == null) {
|
||||
return false;
|
||||
}
|
||||
if (baseUrl != null && !baseUrl.startsWith("http://hl7.org/fhir/R")) {
|
||||
if (resourceNames != null) {
|
||||
for (String n : resourceNames) {
|
||||
if (n != null && url.startsWith(n.toLowerCase()+".html")) {
|
||||
|
@ -2038,6 +2100,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
url.startsWith("extensibility.html") ||
|
||||
url.startsWith("terminologies.html") ||
|
||||
|
@ -2306,20 +2369,12 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
dest.getExtension().remove(elist.get(1));
|
||||
}
|
||||
|
||||
for (Extension ext : source.getExtension()) {
|
||||
if (!Utilities.existsInList(ext.getUrl(), NON_INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
for (Extension ext : source.getExtension()) {
|
||||
if (Utilities.existsInList(ext.getUrl(), ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
updateExtensionsFromDefinition(dest, source);
|
||||
|
||||
for (ElementDefinition ed : obligationProfileElements) {
|
||||
for (Extension ext : ed.getExtension()) {
|
||||
if (Utilities.existsInList(ext.getUrl(), ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
dest.getExtension().add(new Extension(ToolingExtensions.EXT_OBLIGATION_CORE, ext.getValue().copy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2638,6 +2693,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
hasBinding = hasBinding || ed.hasBinding();
|
||||
}
|
||||
if (hasBinding) {
|
||||
updateExtensionsFromDefinition(dest.getBinding(), source.getBinding());
|
||||
ElementDefinitionBindingComponent binding = derived.getBinding();
|
||||
for (ElementDefinition ed : obligationProfileElements) {
|
||||
for (Extension ext : ed.getBinding().getExtension()) {
|
||||
|
@ -2726,8 +2782,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
derived.setBinding(null);
|
||||
else
|
||||
derived.getBinding().setUserData(UD_DERIVATION_EQUALS, true);
|
||||
} // else if (base.hasBinding() && doesn't have bindable type )
|
||||
// base
|
||||
} else if (base.hasBinding()) {
|
||||
base.getBinding().getExtension().removeIf(ext -> Utilities.existsInList(ext.getUrl(), ProfileUtilities.NON_INHERITED_ED_URLS));
|
||||
}
|
||||
|
||||
if (derived.hasIsSummaryElement()) {
|
||||
if (!Base.compareDeep(derived.getIsSummaryElement(), base.getIsSummaryElement(), false)) {
|
||||
|
@ -2820,6 +2877,22 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
//updateURLs(url, webUrl, dest);
|
||||
}
|
||||
|
||||
private void updateExtensionsFromDefinition(Element dest, Element source) {
|
||||
dest.getExtension().removeIf(ext -> Utilities.existsInList(ext.getUrl(), NON_INHERITED_ED_URLS) || (Utilities.existsInList(ext.getUrl(), DEFAULT_INHERITED_ED_URLS) && source.hasExtension(ext.getUrl())));
|
||||
|
||||
for (Extension ext : source.getExtension()) {
|
||||
if (!dest.hasExtension(ext.getUrl())) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
} else if (Utilities.existsInList(ext.getUrl(), NON_OVERRIDING_ED_URLS)) {
|
||||
// do nothing
|
||||
} else if (Utilities.existsInList(ext.getUrl(), OVERRIDING_ED_URLS)) {
|
||||
dest.getExtensionByUrl(ext.getUrl()).setValue(ext.getValue());
|
||||
} else {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeAdditionalBinding(ElementDefinitionBindingAdditionalComponent dest, ElementDefinitionBindingAdditionalComponent source) {
|
||||
for (UsageContext t : source.getUsage()) {
|
||||
if (!hasUsage(dest, t)) {
|
||||
|
@ -4565,4 +4638,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
return propertyCache;
|
||||
}
|
||||
|
||||
public void checkExtensions(ElementDefinition outcome) {
|
||||
outcome.getExtension().removeIf(ext -> Utilities.existsInList(ext.getUrl(), ProfileUtilities.NON_INHERITED_ED_URLS));
|
||||
if (outcome.hasBinding()) {
|
||||
outcome.getBinding().getExtension().removeIf(ext -> Utilities.existsInList(ext.getUrl(), ProfileUtilities.NON_INHERITED_ED_URLS));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -435,5 +435,13 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean isAbstractType(String typeName) {
|
||||
StructureDefinition sd = context.fetchTypeDefinition(typeName);
|
||||
if (sd != null) {
|
||||
return sd.getAbstract();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -43,5 +43,6 @@ public class Constants {
|
|||
public final static String VERSION_MM = "5.0";
|
||||
public final static String DATE = "Thu, Mar 23, 2023 19:59+1100";
|
||||
public final static String URI_REGEX = "((http|https):\\/\\/([A-Za-z0-9\\\\\\.\\:\\%\\$\\-]*\\/)*?)?(Account|ActivityDefinition|ActorDefinition|AdministrableProductDefinition|AdverseEvent|AllergyIntolerance|Appointment|AppointmentResponse|ArtifactAssessment|AuditEvent|Basic|Binary|BiologicallyDerivedProduct|BiologicallyDerivedProductDispense|BodyStructure|Bundle|CapabilityStatement|CarePlan|CareTeam|ChargeItem|ChargeItemDefinition|Citation|Claim|ClaimResponse|ClinicalImpression|ClinicalUseDefinition|CodeSystem|Communication|CommunicationRequest|CompartmentDefinition|Composition|ConceptMap|Condition|ConditionDefinition|Consent|Contract|Coverage|CoverageEligibilityRequest|CoverageEligibilityResponse|DetectedIssue|Device|DeviceAssociation|DeviceDefinition|DeviceDispense|DeviceMetric|DeviceRequest|DeviceUsage|DiagnosticReport|DocumentReference|Encounter|EncounterHistory|Endpoint|EnrollmentRequest|EnrollmentResponse|EpisodeOfCare|EventDefinition|Evidence|EvidenceReport|EvidenceVariable|ExampleScenario|ExplanationOfBenefit|FamilyMemberHistory|Flag|FormularyItem|GenomicStudy|Goal|GraphDefinition|Group|GuidanceResponse|HealthcareService|ImagingSelection|ImagingStudy|Immunization|ImmunizationEvaluation|ImmunizationRecommendation|ImplementationGuide|Ingredient|InsurancePlan|InventoryItem|InventoryReport|Invoice|Library|Linkage|List|Location|ManufacturedItemDefinition|Measure|MeasureReport|Medication|MedicationAdministration|MedicationDispense|MedicationKnowledge|MedicationRequest|MedicationStatement|MedicinalProductDefinition|MessageDefinition|MessageHeader|MolecularSequence|NamingSystem|NutritionIntake|NutritionOrder|NutritionProduct|Observation|ObservationDefinition|OperationDefinition|OperationOutcome|Organization|OrganizationAffiliation|PackagedProductDefinition|Parameters|Patient|PaymentNotice|PaymentReconciliation|Permission|Person|PlanDefinition|Practitioner|PractitionerRole|Procedure|Provenance|Questionnaire|QuestionnaireResponse|RegulatedAuthorization|RelatedPerson|RequestOrchestration|Requirements|ResearchStudy|ResearchSubject|RiskAssessment|Schedule|SearchParameter|ServiceRequest|Slot|Specimen|SpecimenDefinition|StructureDefinition|StructureMap|Subscription|SubscriptionStatus|SubscriptionTopic|Substance|SubstanceDefinition|SubstanceNucleicAcid|SubstancePolymer|SubstanceProtein|SubstanceReferenceInformation|SubstanceSourceMaterial|SupplyDelivery|SupplyRequest|Task|TerminologyCapabilities|TestPlan|TestReport|TestScript|Transport|ValueSet|VerificationResult|VisionPrescription)\\/[A-Za-z0-9\\-\\.]{1,64}(\\/_history\\/[A-Za-z0-9\\-\\.]{1,64})?";
|
||||
public static final String NS_FHIR_ROOT = "http://hl7.org/fhir";
|
||||
public static final String NS_CDA_ROOT = "http://hl7.org/cda/stds/core";
|
||||
}
|
|
@ -62,12 +62,20 @@ public class TypeDetails {
|
|||
public static final Set<String> FP_NUMBERS = new HashSet<String>(Arrays.asList(FP_Integer, FP_Decimal));
|
||||
|
||||
public static class ProfiledType {
|
||||
@Override
|
||||
public String toString() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
private String uri;
|
||||
private List<String> profiles; // or, not and
|
||||
private List<ElementDefinitionBindingComponent> bindings;
|
||||
|
||||
public ProfiledType(String n) {
|
||||
uri = ns(n);
|
||||
if (uri.equals("http://hl7.org/fhir/StructureDefinition/CDA")) {
|
||||
System.out.println("!"); // #FIXME
|
||||
}
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
|
|
|
@ -62,6 +62,7 @@ import org.hl7.fhir.r5.model.TypeDetails;
|
|||
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IssueMessage;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathUtilityClasses.FHIRConstant;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathUtilityClasses.ClassTypeInfo;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathUtilityClasses.FunctionDetails;
|
||||
|
@ -119,6 +120,26 @@ import ca.uhn.fhir.util.ElementUtil;
|
|||
*/
|
||||
public class FHIRPathEngine {
|
||||
|
||||
public class IssueMessage {
|
||||
|
||||
private String message;
|
||||
private String id;
|
||||
|
||||
public IssueMessage(String message, String id) {
|
||||
this.message = message;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private enum Equality { Null, True, False }
|
||||
|
||||
private IWorkerContext worker;
|
||||
|
@ -136,7 +157,7 @@ public class FHIRPathEngine {
|
|||
private boolean doNotEnforceAsSingletonRule;
|
||||
private boolean doNotEnforceAsCaseSensitive;
|
||||
private boolean allowDoubleQuotes;
|
||||
private List<String> typeWarnings = new ArrayList<>();
|
||||
private List<IssueMessage> typeWarnings = new ArrayList<>();
|
||||
private boolean emitSQLonFHIRWarning;
|
||||
|
||||
// if the fhir path expressions are allowed to use constants beyond those defined in the specification
|
||||
|
@ -499,7 +520,7 @@ public class FHIRPathEngine {
|
|||
* @throws PathEngineException
|
||||
* @if the path is not valid
|
||||
*/
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, List<String> typeList, ExpressionNode expr, List<String> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, List<String> typeList, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
|
||||
// if context is a path that refers to a type, do that conversion now
|
||||
|
@ -550,7 +571,7 @@ public class FHIRPathEngine {
|
|||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<String> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
|
@ -589,9 +610,9 @@ public class FHIRPathEngine {
|
|||
fmt = fmt + " "+worker.formatMessagePlural(num, I18nConstants.FHIRPATH_LOCATION, location);
|
||||
}
|
||||
if (holder != null) {
|
||||
return new PathEngineException(fmt, holder.getStart(), holder.toString());
|
||||
return new PathEngineException(fmt, constName, holder.getStart(), holder.toString());
|
||||
} else {
|
||||
return new PathEngineException(fmt);
|
||||
return new PathEngineException(fmt, constName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,9 +622,9 @@ public class FHIRPathEngine {
|
|||
fmt = fmt + " "+worker.formatMessage(I18nConstants.FHIRPATH_LOCATION, location);
|
||||
}
|
||||
if (holder != null) {
|
||||
return new PathEngineException(fmt, holder.getStart(), holder.toString());
|
||||
return new PathEngineException(fmt, constName, holder.getStart(), holder.toString());
|
||||
} else {
|
||||
return new PathEngineException(fmt);
|
||||
return new PathEngineException(fmt, constName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,10 +1621,10 @@ public class FHIRPathEngine {
|
|||
// special Logic for SQL-on-FHIR:
|
||||
if (focus.isChoice()) {
|
||||
if (expr.getInner() == null || expr.getInner().getFunction() != Function.OfType) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_CHOICE_NO_TYPE_SPECIFIER, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_CHOICE_NO_TYPE_SPECIFIER, expr.toString()), I18nConstants.FHIRPATH_CHOICE_NO_TYPE_SPECIFIER));
|
||||
}
|
||||
} else if (expr.getInner() != null && expr.getInner().getFunction() == Function.OfType) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER, expr.toString()), I18nConstants.FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1816,10 +1837,10 @@ public class FHIRPathEngine {
|
|||
} else {
|
||||
String tn = convertToString(right);
|
||||
if (!isKnownType(tn)) {
|
||||
throw new PathEngineException("The type "+tn+" is not valid");
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_INVALID_TYPE, tn), I18nConstants.FHIRPATH_INVALID_TYPE);
|
||||
}
|
||||
if (!doNotEnforceAsSingletonRule && left.size() > 1) {
|
||||
throw new PathEngineException("Attempt to use as on more than one item ("+left.size()+", '"+expr.toString()+"')");
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_AS_COLLECTION, left.size(), expr.toString()), I18nConstants.FHIRPATH_AS_COLLECTION);
|
||||
}
|
||||
for (Base nextLeft : left) {
|
||||
if (compareTypeNames(tn, nextLeft.fhirType())) {
|
||||
|
@ -1904,18 +1925,18 @@ public class FHIRPathEngine {
|
|||
|
||||
private void checkCardinalityForComparabilitySame(TypeDetails left, Operation operation, TypeDetails right, ExpressionNode expr) {
|
||||
if (left.isList() && !right.isList()) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT, expr.toString()), I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT));
|
||||
} else if (!left.isList() && right.isList()) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT, expr.toString()), I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCardinalityForSingle(TypeDetails left, Operation operation, TypeDetails right, ExpressionNode expr) {
|
||||
if (left.isList()) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT, expr.toString()), I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT));
|
||||
}
|
||||
if (right.isList()) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT, expr.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT, expr.toString()), I18nConstants.FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1995,7 +2016,7 @@ public class FHIRPathEngine {
|
|||
if (right.hasType(worker, "Quantity")) {
|
||||
result.addType(left.getType());
|
||||
} else {
|
||||
throw new PathEngineException(String.format("Error in date arithmetic: Unable to add type {0} to {1}", right.getType(), left.getType()), expr.getOpStart(), expr.toString());
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_ARITHMETIC_PLUS, right.getType(), left.getType()), I18nConstants.FHIRPATH_ARITHMETIC_PLUS, expr.getOpStart(), expr.toString());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -2012,7 +2033,7 @@ public class FHIRPathEngine {
|
|||
if (right.hasType(worker, "Quantity")) {
|
||||
result.addType(left.getType());
|
||||
} else {
|
||||
throw new PathEngineException(String.format("Error in date arithmetic: Unable to subtract type {0} from {1}", right.getType(), left.getType()));
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_ARITHMETIC_MINUS, right.getType(), left.getType()), I18nConstants.FHIRPATH_ARITHMETIC_MINUS, expr.getOpStart(), expr.toString());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -2654,13 +2675,13 @@ public class FHIRPathEngine {
|
|||
result.add(Calendar.YEAR, value);
|
||||
break;
|
||||
case "a":
|
||||
throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()));
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_ARITHMETIC_QTY, q.getCode()), I18nConstants.FHIRPATH_ARITHMETIC_QTY, holder.getOpStart(), holder.toString());
|
||||
case "months":
|
||||
case "month":
|
||||
result.add(Calendar.MONTH, value);
|
||||
break;
|
||||
case "mo":
|
||||
throw new PathEngineException(String.format("Error in date arithmetic: attempt to add a definite quantity duration time unit %s", q.getCode()), holder.getOpStart(), holder.toString());
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_ARITHMETIC_QTY, q.getCode()), I18nConstants.FHIRPATH_ARITHMETIC_QTY, holder.getOpStart(), holder.toString());
|
||||
case "weeks":
|
||||
case "week":
|
||||
case "wk":
|
||||
|
@ -2692,7 +2713,7 @@ public class FHIRPathEngine {
|
|||
result.add(Calendar.MILLISECOND, value);
|
||||
break;
|
||||
default:
|
||||
throw new PathEngineException(String.format("Error in date arithmetic: unrecognized time unit %s", q.getCode()));
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_ARITHMETIC_UNIT, q.getCode()), I18nConstants.FHIRPATH_ARITHMETIC_UNIT, holder.getOpStart(), holder.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2730,7 +2751,7 @@ public class FHIRPathEngine {
|
|||
p = worker.getUcumService().multiply(pl, pr);
|
||||
result.add(pairToQty(p));
|
||||
} catch (UcumException e) {
|
||||
throw new PathEngineException(e.getMessage(), expr.getOpStart(), expr.toString(), e);
|
||||
throw new PathEngineException(e.getMessage(), null, expr.getOpStart(), expr.toString(), e); // #FIXME
|
||||
}
|
||||
} else {
|
||||
throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "*", left.get(0).fhirType(), right.get(0).fhirType());
|
||||
|
@ -3221,7 +3242,7 @@ public class FHIRPathEngine {
|
|||
}
|
||||
if (exp.getFunction() == Function.First || exp.getFunction() == Function.Last || exp.getFunction() == Function.Tail || exp.getFunction() == Function.Skip || exp.getFunction() == Function.Take) {
|
||||
if (focus.getCollectionStatus() == CollectionStatus.SINGLETON) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_NOT_A_COLLECTION, container.toString()));
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_NOT_A_COLLECTION, container.toString()), I18nConstants.FHIRPATH_NOT_A_COLLECTION));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3287,7 +3308,8 @@ public class FHIRPathEngine {
|
|||
}
|
||||
case As : {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, exp.getParameters().get(0).getName());
|
||||
String tn = checkType(focus, exp);
|
||||
TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, tn);
|
||||
if (td.typesHaveTargets()) {
|
||||
td.addTargets(focus.getTargets());
|
||||
}
|
||||
|
@ -3295,10 +3317,7 @@ public class FHIRPathEngine {
|
|||
}
|
||||
case OfType : {
|
||||
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
|
||||
String tn = exp.getParameters().get(0).getName();
|
||||
if (typeCastIsImpossible(focus, tn)) {
|
||||
typeWarnings.add(worker.formatMessage(I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE, focus.describeMin(), tn, exp.toString()));
|
||||
}
|
||||
String tn = checkType(focus, exp);
|
||||
TypeDetails td = new TypeDetails(CollectionStatus.SINGLETON, tn);
|
||||
if (td.typesHaveTargets()) {
|
||||
td.addTargets(focus.getTargets());
|
||||
|
@ -3618,6 +3637,27 @@ public class FHIRPathEngine {
|
|||
throw new Error("not Implemented yet");
|
||||
}
|
||||
|
||||
private String checkType(TypeDetails focus, ExpressionNode exp) {
|
||||
String tn;
|
||||
if (exp.getParameters().get(0).getInner() != null) {
|
||||
tn = exp.getParameters().get(0).getName()+"."+exp.getParameters().get(0).getInner().getName();
|
||||
} else {
|
||||
tn = "FHIR."+exp.getParameters().get(0).getName();
|
||||
}
|
||||
if (tn.startsWith("System.")) {
|
||||
tn = tn.substring(7);
|
||||
} else if (tn.startsWith("FHIR.")) {
|
||||
tn = Utilities.pathURL(Constants.NS_FHIR_ROOT, "StructureDefinition", tn.substring(5));
|
||||
} else if (tn.startsWith("CDA.")) {
|
||||
tn = Utilities.pathURL(Constants.NS_CDA_ROOT, "StructureDefinition", tn.substring(4));
|
||||
}
|
||||
|
||||
if (typeCastIsImpossible(focus, tn)) {
|
||||
typeWarnings.add(new IssueMessage(worker.formatMessage(I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE, focus.describeMin(), tn, exp.toString()), I18nConstants.FHIRPATH_OFTYPE_IMPOSSIBLE));
|
||||
}
|
||||
return tn;
|
||||
}
|
||||
|
||||
private boolean typeCastIsImpossible(TypeDetails focus, String tn) {
|
||||
return !focus.hasType(tn);
|
||||
}
|
||||
|
@ -4871,10 +4911,10 @@ public class FHIRPathEngine {
|
|||
tn = "FHIR."+expr.getParameters().get(0).getName();
|
||||
}
|
||||
if (!isKnownType(tn)) {
|
||||
throw new PathEngineException("The type "+tn+" is not valid");
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_INVALID_TYPE, tn), I18nConstants.FHIRPATH_INVALID_TYPE); // #FIXME
|
||||
}
|
||||
if (!doNotEnforceAsSingletonRule && focus.size() > 1) {
|
||||
throw new PathEngineException("Attempt to use as() on more than one item ("+focus.size()+")");
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_AS_COLLECTION, focus.size(), expr.toString()), I18nConstants.FHIRPATH_AS_COLLECTION); // #FIXME
|
||||
}
|
||||
|
||||
for (Base b : focus) {
|
||||
|
@ -4914,7 +4954,7 @@ public class FHIRPathEngine {
|
|||
tn = "FHIR."+expr.getParameters().get(0).getName();
|
||||
}
|
||||
if (!isKnownType(tn)) {
|
||||
throw new PathEngineException("The type "+tn+" is not valid");
|
||||
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_INVALID_TYPE, tn), I18nConstants.FHIRPATH_INVALID_TYPE); // #FIXME
|
||||
}
|
||||
|
||||
|
||||
|
@ -5967,7 +6007,7 @@ public class FHIRPathEngine {
|
|||
for (TypeRefComponent t : ed.getType()) {
|
||||
if (t.hasCode() && t.getCodeElement().hasValue()) {
|
||||
String tn = null;
|
||||
if (t.getCode().equals("Element") || t.getCode().equals("BackboneElement")) {
|
||||
if (Utilities.existsInList(t.getCode(), "Element", "BackboneElement", "Base") || cu.isAbstractType(t.getCode())) {
|
||||
tn = sdi.getType()+"#"+ed.getPath();
|
||||
} else {
|
||||
tn = t.getCode();
|
||||
|
|
|
@ -54,10 +54,12 @@ public class OperationOutcomeUtilities {
|
|||
issue.addExpression(message.getLocation());
|
||||
}
|
||||
// pass through line/col if they're present
|
||||
if (message.getLine() >= 0)
|
||||
if (message.getLine() >= 0) {
|
||||
issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_LINE).setValue(new IntegerType(message.getLine()));
|
||||
if (message.getCol() >= 0)
|
||||
}
|
||||
if (message.getCol() >= 0) {
|
||||
issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_COL).setValue(new IntegerType(message.getCol()));
|
||||
}
|
||||
issue.setSeverity(convert(message.getLevel()));
|
||||
CodeableConcept c = new CodeableConcept();
|
||||
c.setText(message.getMessage());
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hl7.fhir.r5.model.TypeDetails;
|
|||
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IssueMessage;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.json.model.JsonArray;
|
||||
import org.hl7.fhir.utilities.json.model.JsonBoolean;
|
||||
|
@ -253,7 +254,7 @@ public class Validator {
|
|||
} else {
|
||||
String expr = expression.asString();
|
||||
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
ExpressionNode node = null;
|
||||
try {
|
||||
|
@ -264,8 +265,8 @@ public class Validator {
|
|||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
if (td != null && node != null) {
|
||||
for (String s : warnings) {
|
||||
warning(path+".path", expression, s);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(path+".path", expression, s.getMessage());
|
||||
}
|
||||
String columnName = null;
|
||||
JsonElement nameJ = column.get("name");
|
||||
|
@ -419,7 +420,7 @@ public class Validator {
|
|||
} else {
|
||||
String expr = expression.asString();
|
||||
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
|
@ -429,8 +430,8 @@ public class Validator {
|
|||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
if (td != null) {
|
||||
for (String s : warnings) {
|
||||
warning(path+".forEach", expression, s);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(path+".forEach", expression, s.getMessage());
|
||||
}
|
||||
}
|
||||
return td;
|
||||
|
@ -444,7 +445,7 @@ public class Validator {
|
|||
} else {
|
||||
String expr = expression.asString();
|
||||
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
ExpressionNode n = fpe.parse(expr);
|
||||
|
@ -454,8 +455,8 @@ public class Validator {
|
|||
error(path, expression, e.getMessage(), IssueType.INVALID);
|
||||
}
|
||||
if (td != null) {
|
||||
for (String s : warnings) {
|
||||
warning(path+".forEachOrNull", expression, s);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(path+".forEachOrNull", expression, s.getMessage());
|
||||
}
|
||||
}
|
||||
return td;
|
||||
|
@ -546,7 +547,7 @@ public class Validator {
|
|||
error(path, where, "No path provided", IssueType.REQUIRED);
|
||||
}
|
||||
List<String> types = new ArrayList<>();
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
types.add(resourceName);
|
||||
TypeDetails td = null;
|
||||
try {
|
||||
|
@ -560,8 +561,8 @@ public class Validator {
|
|||
if (td.getCollectionStatus() != CollectionStatus.SINGLETON || td.getTypes().size() != 1 || !td.hasType("boolean")) {
|
||||
error(path+".path", where.get("path"), "A where path must return a boolean, but the expression "+expr+" returns a "+td.describe(), IssueType.BUSINESSRULE);
|
||||
} else {
|
||||
for (String s : warnings) {
|
||||
warning(path+".path", where.get("path"), s);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(path+".path", where.get("path"), s.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,906 +0,0 @@
|
|||
package org.hl7.fhir.r5.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ProfileUtilitiesTests {
|
||||
|
||||
// /**
|
||||
// * This is simple: we just create an empty differential, generate the snapshot, and then insist it must match the base
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
@Test
|
||||
public void testSimple() throws FHIRException {
|
||||
|
||||
StructureDefinition focus = new StructureDefinition();
|
||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
focus.setUrl(Utilities.makeUuidUrn());
|
||||
focus.setBaseDefinition(base.getUrl());
|
||||
focus.setType("Patient");
|
||||
focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), messages, null).generateSnapshot(base, focus, focus.getUrl(), "http://test.org/test", "Simple Test");
|
||||
|
||||
boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
if (ok) {
|
||||
if (!f.hasBase())
|
||||
ok = false;
|
||||
else if (!b.getPath().equals(f.getPath()))
|
||||
ok = false;
|
||||
else {
|
||||
b.setBase(null);
|
||||
f.setBase(null);
|
||||
b.setRequirements(null);
|
||||
f.setRequirements(null);
|
||||
for (ElementDefinitionConstraintComponent c : b.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent c : f.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
ok = Base.compareDeep(b, f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.assertTrue(ok);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// /**
|
||||
// * This is simple: we just create an empty differential, generate the snapshot, and then insist it must match the base. for a different resource with recursion
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
@Test
|
||||
public void testSimple2() {
|
||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/ValueSet").copy();
|
||||
StructureDefinition focus = base.copy();
|
||||
focus.setUrl(Utilities.makeUuidUrn());
|
||||
focus.setSnapshot(null);
|
||||
focus.setDifferential(null);
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), messages, null).generateSnapshot(base, focus, focus.getUrl(), "http://test.org", "Simple Test");
|
||||
|
||||
boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
if (ok) {
|
||||
ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
for (ElementDefinitionConstraintComponent c : b.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent c : f.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
if (!f.hasBase() || !b.getPath().equals(f.getPath()))
|
||||
ok = false;
|
||||
else {
|
||||
f.setBase(null);
|
||||
b.setBase(null);
|
||||
b.setRequirements(null);
|
||||
f.setRequirements(null);
|
||||
b.setComment(null);
|
||||
f.setComment(null);
|
||||
b.setDefinition(null);
|
||||
f.setDefinition(null);
|
||||
b.setContentReference(null);
|
||||
f.setContentReference(null);
|
||||
ok = Base.compareDeep(b, f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.assertTrue(ok);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change one cardinality.
|
||||
*/
|
||||
@Test
|
||||
void testCardinalityChange() {
|
||||
StructureDefinition focus = new StructureDefinition();
|
||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
focus.setUrl(Utilities.makeUuidUrn());
|
||||
focus.setBaseDefinition(base.getUrl());
|
||||
focus.setType(base.getType());
|
||||
focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
ElementDefinition id = focus.getDifferential().addElement();
|
||||
id.setPath("Patient.identifier");
|
||||
id.setMin(1);
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), messages, null).generateSnapshot(base, focus, focus.getUrl(), "http://test.org", "Simple Test");
|
||||
|
||||
boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
if (ok) {
|
||||
ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
b.setRequirements(null);
|
||||
f.setRequirements(null);
|
||||
for (ElementDefinitionConstraintComponent c : b.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent c : f.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
if (!f.hasBase() || !b.getPath().equals(f.getPath())) {
|
||||
ok = false;
|
||||
}
|
||||
else {
|
||||
if (f.getPath().equals("Patient.identifier")) {
|
||||
ok = f.getMin() == 1;
|
||||
if (ok) {
|
||||
f.setMin(0);
|
||||
}
|
||||
}
|
||||
if (!Base.compareDeep(b, f, true)) {
|
||||
ok = Base.compareDeep(b, f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.assertTrue(ok);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change min value
|
||||
*/
|
||||
@Test
|
||||
void testMinValueChange() {
|
||||
// Given
|
||||
StructureDefinition focus = new StructureDefinition();
|
||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Appointment").copy();
|
||||
focus.setUrl(Utilities.makeUuidUrn());
|
||||
focus.setBaseDefinition(base.getUrl());
|
||||
focus.setType(base.getType());
|
||||
focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
ElementDefinition id = focus.getDifferential().addElement();
|
||||
id.setPath("Appointment.minutesDuration");
|
||||
id.setMinValue(new IntegerType(1));
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
// When
|
||||
new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), messages, null).generateSnapshot(base, focus, focus.getUrl(), "http://test.org", "Simple Test");
|
||||
// Then
|
||||
boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
if (ok) {
|
||||
ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
b.setRequirements(null);
|
||||
f.setRequirements(null);
|
||||
for (ElementDefinitionConstraintComponent c : b.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent c : f.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
if (!f.hasBase() || !b.getPath().equals(f.getPath())) {
|
||||
ok = false;
|
||||
}
|
||||
else {
|
||||
if (f.getPath().equals("Appointment.minutesDuration")) {
|
||||
ok = f.getMinValue() instanceof IntegerType && ((IntegerType) f.getMinValue()).getValue() == 1;
|
||||
if (ok) {
|
||||
// Can't set minValue to null so change base minValue to IntegerType(1)
|
||||
b.setMinValue(new IntegerType(1));
|
||||
}
|
||||
}
|
||||
if (!Base.compareDeep(b, f, true)) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.assertTrue(ok);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change max value
|
||||
*/
|
||||
@Test
|
||||
void testMaxValueChange() {
|
||||
// Given
|
||||
StructureDefinition focus = new StructureDefinition();
|
||||
StructureDefinition base = TestingUtilities.getSharedWorkerContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Appointment").copy();
|
||||
focus.setUrl(Utilities.makeUuidUrn());
|
||||
focus.setBaseDefinition(base.getUrl());
|
||||
focus.setType(base.getType());
|
||||
focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
ElementDefinition id = focus.getDifferential().addElement();
|
||||
id.setPath("Appointment.minutesDuration");
|
||||
id.setMaxValue(new IntegerType(1));
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
// When
|
||||
new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), messages, null).generateSnapshot(base, focus, focus.getUrl(), "http://test.org", "Simple Test");
|
||||
// Then
|
||||
boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
if (ok) {
|
||||
ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
b.setRequirements(null);
|
||||
f.setRequirements(null);
|
||||
for (ElementDefinitionConstraintComponent c : b.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent c : f.getConstraint()) {
|
||||
c.setSource(null);
|
||||
}
|
||||
if (!f.hasBase() || !b.getPath().equals(f.getPath())) {
|
||||
ok = false;
|
||||
}
|
||||
else {
|
||||
if (f.getPath().equals("Appointment.minutesDuration")) {
|
||||
ok = f.getMaxValue() instanceof IntegerType && ((IntegerType) f.getMaxValue()).getValue() == 1;
|
||||
if (ok) {
|
||||
// Can't set maxValue to null so change base maxValue to IntegerType(1)
|
||||
b.setMaxValue(new IntegerType(1));
|
||||
}
|
||||
}
|
||||
if (!Base.compareDeep(b, f, true)) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.assertTrue(ok);
|
||||
}
|
||||
|
||||
//
|
||||
// /**
|
||||
// * check that documentation appending is working
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void testDocumentationAppend() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.setDefinition("... some more doco");
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.identifier")) {
|
||||
// ok = f.getDefinition().length() > b.getDefinition().length();
|
||||
// if (ok) {
|
||||
// f.setDefinition(null);
|
||||
// b.setDefinition(null);
|
||||
// }
|
||||
// }
|
||||
// ok = ok && Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation documentation append failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation documentation append test passed");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * check that narrowing types is working
|
||||
// * this one doesn't rename the path
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void textTypeNarrowing1() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.deceased[x]");
|
||||
// id.addType().setCode("dateTime");
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.deceasedDateTime")) {
|
||||
// ok = f.getType().size() == 1 && f.getType().get(0).getCode().equals("dateTime");
|
||||
// if (ok) {
|
||||
// f.getType().clear();
|
||||
// b.getType().clear();
|
||||
// f.setPath(b.getPath());
|
||||
// }
|
||||
// }
|
||||
// ok = ok && Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation narrow type 1 failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation narrow type 1 test passed");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * check that narrowing types is working
|
||||
// * this one renames the path
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void textTypeNarrowing2() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.deceasedDateTime");
|
||||
// id.addType().setCode("dateTime");
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.deceasedDateTime")) {
|
||||
// ok = f.getType().size() == 1 && f.getType().get(0).getCode().equals("dateTime");
|
||||
// if (ok) {
|
||||
// f.getType().clear();
|
||||
// b.getType().clear();
|
||||
// f.setPath(b.getPath());
|
||||
// }
|
||||
// }
|
||||
// ok = ok && Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation narrow type 2 failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation narrow type 2 test passed");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * check that mapping resolution is working
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void testMapping() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.addMapping().setIdentity("rim").setMap("test");
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size();
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.identifier")) {
|
||||
// ok = f.getMapping().size() > b.getMapping().size();
|
||||
// if (ok) {
|
||||
// f.getMapping().clear();
|
||||
// b.getMapping().clear();
|
||||
// }
|
||||
// }
|
||||
// ok = ok && Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation mapping changes failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation mapping changes test passed");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Walking into a type
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void testTypeWalk() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.setMustSupport(true);
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier.system");
|
||||
// id.setMustSupport(true);
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // the derived should be 8 longer
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 8;
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i <= 9 ? i : i + 8);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.identifier")) {
|
||||
// ok = f.getMustSupport() && !b.getMustSupport();
|
||||
// if (ok) {
|
||||
// f.setMustSupportElement(null);
|
||||
// }
|
||||
// }
|
||||
// ok = Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation simple test failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation simple test passed");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Walking into a type, without explicitly doing so
|
||||
// *
|
||||
// * note: this currently fails.
|
||||
// *
|
||||
// * @param context2
|
||||
// * @
|
||||
// * @throws EOperationOutcome
|
||||
// */
|
||||
// private void testTypeWalk2() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier.system");
|
||||
// id.setMustSupport(true);
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // the derived should be 8 longer
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 8;
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i <= 9 ? i : i + 8);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.identifier")) {
|
||||
// ok = f.getMustSupport() && !b.getMustSupport();
|
||||
// if (ok) {
|
||||
// f.setMustSupportElement(null);
|
||||
// }
|
||||
// }
|
||||
// ok = Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation simple test failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation simple test passed");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * we're going to slice Patient.identifier
|
||||
// */
|
||||
// private void testSlicingSimple() throws EOperationOutcome, Exception {
|
||||
//
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
//
|
||||
// // set the slice up
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.getSlicing().setOrdered(false).setRules(SlicingRules.OPEN).addDiscriminator().setPath("use").setType(DiscriminatorType.VALUE);
|
||||
//
|
||||
// // first slice:
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.setSliceName("name1");
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier.use");
|
||||
// id.setFixed(new CodeType("usual"));
|
||||
//
|
||||
// // second slice:
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier");
|
||||
// id.setSliceName("name2");
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.identifier.use");
|
||||
// id.setFixed(new CodeType("official"));
|
||||
//
|
||||
//
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // 18 different: identifier + 8 inner children * 2
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 18;
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i <= 9 ? i : i + 18);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.identifier")) {
|
||||
// ok = f.hasSlicing();
|
||||
// if (ok)
|
||||
// f.setSlicing(null);
|
||||
// }
|
||||
// ok = Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // now, check that the slices we skipped are correct:
|
||||
// for (int i = 10; i <= 18; i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition d1 = focus.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition d2 = focus.getSnapshot().getElement().get(i+9);
|
||||
// if (d1.getPath().equals("Patient.identifier.use")) {
|
||||
// ok = d1.hasFixed() && d2.hasFixed() && !Base.compareDeep(d1.getFixed(), d2.getFixed(), true);
|
||||
// if (ok) {
|
||||
// d1.setFixed(null);
|
||||
// d2.setFixed(null);
|
||||
// }
|
||||
// }
|
||||
// if (d1.getPath().equals("Patient.identifier")) {
|
||||
// ok = d1.hasSliceName() && d2.hasSliceName() && !Base.compareDeep(d1.getSliceNameElement(), d2.getSliceNameElement(), true);
|
||||
// if (ok) {
|
||||
// d1.setSliceName(null);
|
||||
// d2.setSliceName(null);
|
||||
// }
|
||||
// }
|
||||
// ok = Base.compareDeep(d1, d2, true);
|
||||
// }
|
||||
// }
|
||||
// // for throughness, we could check against identifier too, but this is not done now.
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation slicing failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation slicing passed");
|
||||
//
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * we're going to slice Patient.extension and refer to extension by profile
|
||||
// *
|
||||
// * implicit: whether to rely on implicit extension slicing
|
||||
// */
|
||||
// private void testSlicingExtension(boolean implicit) throws EOperationOutcome, Exception {
|
||||
//
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
//
|
||||
// // set the slice up
|
||||
// ElementDefinition id;
|
||||
// if (!implicit) {
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.getSlicing().setOrdered(false).setRules(SlicingRules.OPEN).addDiscriminator().setPath("url").setType(DiscriminatorType.VALUE);
|
||||
// id.setMax("3");
|
||||
// }
|
||||
// // first slice:
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.setSliceName("name1");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-birthTime");
|
||||
// id.setMin(1);
|
||||
//
|
||||
// // second slice:
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.setSliceName("name2");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName");
|
||||
//
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// ProfileUtilities pu = new ProfileUtilities(context, messages, null);
|
||||
// pu.generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // 2 different: extension slices
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 2;
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i <= 7 ? i : i + 2);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.extension")) {
|
||||
// ok = f.hasSlicing() && (implicit || f.getMax().equals("3"));
|
||||
// if (ok) {
|
||||
// f.setSlicing(null);
|
||||
// f.setMaxElement(b.getMaxElement());
|
||||
// }
|
||||
// }
|
||||
// if (!f.getPath().equals("Patient.extension")) // no compare that because the definitions get overwritten
|
||||
// ok = Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // now, check that the slices we skipped are correct:
|
||||
// if (ok) {
|
||||
// ElementDefinition d1 = focus.getSnapshot().getElement().get(8);
|
||||
// ElementDefinition d2 = focus.getSnapshot().getElement().get(9);
|
||||
// ok = d1.hasType() && d1.getType().get(0).hasProfile() && d2.hasType() && d2.getType().get(0).hasProfile() && !Base.compareDeep(d1.getType(), d2.getType(), true) &&
|
||||
// d1.getMin() == 1 && d2.getMin() == 0 && d1.getMax().equals("1") && d2.getMax().equals("1");
|
||||
// if (ok) {
|
||||
// d1.getType().clear();
|
||||
// d2.getType().clear();
|
||||
// d1.setSliceName("x");
|
||||
// d2.setSliceName("x");
|
||||
// d1.setMin(0);
|
||||
// }
|
||||
// ok = Base.compareDeep(d1, d2, true);
|
||||
// // for throughness, we could check against extension too, but this is not done now.
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation slicing extensions simple ("+(implicit ? "implicit" : "not implicit")+") failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation slicing extensions simple ("+(implicit ? "implicit" : "not implicit")+") passed");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * we're going to slice Patient.extension and refer to extension by profile. one of the extensions is complex, and we're going to walk into
|
||||
// * it and make it must support
|
||||
// *
|
||||
// * implicit: whether to rely on implicit extension slicing
|
||||
// */
|
||||
// private void testSlicingExtensionComplex(boolean implicit) throws EOperationOutcome, Exception {
|
||||
//
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Patient").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
//
|
||||
// // set the slice up
|
||||
// ElementDefinition id;
|
||||
// if (!implicit) {
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.getSlicing().setOrdered(false).setRules(SlicingRules.OPEN).addDiscriminator().setPath("url").setType(DiscriminatorType.VALUE);
|
||||
// }
|
||||
// // first slice - a simple one to get us going:
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.setSliceName("simple");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-birthTime");
|
||||
//
|
||||
// // second slice - the complex one
|
||||
// // we walk into this and fix properties on the inner extensions
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension");
|
||||
// id.setSliceName("complex");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-nationality");
|
||||
// if (!implicit) {
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension.extension");
|
||||
// id.getSlicing().setOrdered(false).setRules(SlicingRules.OPEN).addDiscriminator().setPath("url").setType(DiscriminatorType.VALUE);
|
||||
// }
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension.extension");
|
||||
// id.setSliceName("code");
|
||||
// id.setMustSupport(true);
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-nationality#code");
|
||||
//
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Patient.extension.extension");
|
||||
// id.setSliceName("period");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/patient-nationality#period");
|
||||
// id.setMax("0"); // prohibit this one....
|
||||
//
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // ok, there's going to 1 (simple) + complex: 1 + id + extnesion.slice + extension.code + (4 inside from that) + extension.period + (4 inside from that) + value + url = 16
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 16;
|
||||
//
|
||||
// // custom checks
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(7).getPath().equals("Patient.extension"), "element 7 (base) path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(7).hasSlicing(), "element 7 slicing");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(8).getPath().equals("Patient.extension"), "element 8 (1st slice) path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(8).getSliceName().equals("simple"), "element 8 (1st slice) name");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(8).getType().get(0).getProfile().equals("http://hl7.org/fhir/StructureDefinition/patient-birthTime"), "element 9 (2nd slice) profile name");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(9).getPath().equals("Patient.extension"), "element 9 (2nd slice) path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(9).getSliceName().equals("complex"), "element 8 (1st slice) name");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(9).getType().get(0).getProfile().equals("http://hl7.org/fhir/StructureDefinition/patient-nationality"), "element 9 (2nd slice) profile name");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(10).getPath().equals("Patient.extension.id"), "element 10 (2nd slice).id path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(11).getPath().equals("Patient.extension.extension"), "element 11 (2nd slice).extension path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(12).getPath().equals("Patient.extension.extension"), "element 12 (2nd slice).extension path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(12).getMustSupport(), "element 12 (2nd slice).extension must support");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(13).getPath().equals("Patient.extension.extension.id"), "element 13 (2nd slice).extension.id path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(14).getPath().equals("Patient.extension.extension.extension"), "element 14 (2nd slice).extension.extension path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(15).getPath().equals("Patient.extension.extension.url"), "element 15 (2nd slice).extension.url path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(16).getPath().equals("Patient.extension.extension.valueCodeableConcept"), "element 16 (2nd slice).extension.valueCodeableConcept path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(17).getPath().equals("Patient.extension.extension"), "element 17 (2nd slice).extension path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(17).getMax().equals("0"), "element 17 (2nd slice).extension cardinality");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(18).getPath().equals("Patient.extension.extension.id"), "element 18 (2nd slice).extension.id path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(19).getPath().equals("Patient.extension.extension.extension"), "element 19 (2nd slice).extension.extension path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(20).getPath().equals("Patient.extension.extension.url"), "element 20 (2nd slice).extension.url path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(21).getPath().equals("Patient.extension.extension.valuePeriod"), "element 21 (2nd slice).extension.valuePeriod path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(22).getPath().equals("Patient.extension.url"), "element 22 (2nd slice).url path");
|
||||
// ok = ok && rule(focus.getSnapshot().getElement().get(23).getPath().equals("Patient.extension.value[x]"), "element 23 (2nd slice).url path");
|
||||
//
|
||||
// for (int i = 0; i < base.getSnapshot().getElement().size(); i++) {
|
||||
// if (ok) {
|
||||
// ElementDefinition b = base.getSnapshot().getElement().get(i);
|
||||
// ElementDefinition f = focus.getSnapshot().getElement().get(i <= 7 ? i : i + 16);
|
||||
// if (!f.hasBase() || !b.getPath().equals(f.getBase().getPath()))
|
||||
// ok = false;
|
||||
// else {
|
||||
// f.setBase(null);
|
||||
// if (f.getPath().equals("Patient.extension")) {
|
||||
// ok = f.hasSlicing();
|
||||
// if (ok)
|
||||
// f.setSlicing(null);
|
||||
// }
|
||||
// if (!f.getPath().equals("Patient.extension")) // no compare that because the definitions get overwritten
|
||||
// ok = Base.compareDeep(b, f, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation slicing extensions complex ("+(implicit ? "implicit" : "not implicit")+") failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation slicing extensions complex ("+(implicit ? "implicit" : "not implicit")+") passed");
|
||||
// }
|
||||
//
|
||||
// private void testSlicingTask8742() throws EOperationOutcome, Exception {
|
||||
// StructureDefinition focus = new StructureDefinition();
|
||||
// StructureDefinition base = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/Organization").copy();
|
||||
// focus.setUrl(Utilities.makeUuidUrn());
|
||||
// focus.setBaseDefinition(base.getUrl());
|
||||
// focus.setType(base.getType());
|
||||
// focus.setDerivation(TypeDerivationRule.CONSTRAINT);
|
||||
//
|
||||
// ElementDefinition id = focus.getDifferential().addElement();
|
||||
// id.setPath("Organization.address");
|
||||
// id.setMin(1);
|
||||
// id.setMax("1");
|
||||
// id.setMustSupport(true);
|
||||
//
|
||||
// id = focus.getDifferential().addElement();
|
||||
// id.setPath("Organization.address.extension");
|
||||
// id.setSliceName("USLabCountycodes");
|
||||
// id.getSlicing().setOrdered(false).setRules(SlicingRules.OPEN).addDiscriminator().setPath("url").setType(DiscriminatorType.VALUE);
|
||||
// id.setShort("County/Parish FIPS codes");
|
||||
// id.setDefinition("County/Parish FIPS codes.");
|
||||
// id.setRequirements("County/Parish Code SHALL use FIPS 6-4 ( INCITS 31:2009).");
|
||||
// id.setMin(0);
|
||||
// id.setMax("1");
|
||||
// id.addType().setCode("Extension").setProfile("http://hl7.org/fhir/StructureDefinition/us-core-county");
|
||||
// id.setMustSupport(true);
|
||||
// id.getBinding().setStrength(BindingStrength.REQUIRED).setDescription("FIPS codes for US counties and county equivalent entities.").setValueSet(new Reference().setReference("http://hl7.org/fhir/ValueSet/fips-county"));
|
||||
// List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
//
|
||||
// new ProfileUtilities(context, messages, null).generateSnapshot(base, focus, focus.getUrl(), "Simple Test" );
|
||||
//
|
||||
// // 14 for address with one sliced extension
|
||||
// boolean ok = base.getSnapshot().getElement().size() == focus.getSnapshot().getElement().size() - 13;
|
||||
//
|
||||
// if (!ok) {
|
||||
// compareXml(base, focus);
|
||||
// throw new FHIRException("Snap shot generation test 8742 failed");
|
||||
// } else
|
||||
// System.out.println("Snap shot generation test 8742 passed");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private boolean rule(boolean ok, String message) {
|
||||
// if (!ok)
|
||||
// System.out.println("Test failed: " + message);
|
||||
// return ok;
|
||||
// }
|
||||
//
|
||||
|
||||
}
|
|
@ -39,10 +39,8 @@ public class PathEngineException extends FHIRException {
|
|||
private static final long serialVersionUID = 31969342112856390L;
|
||||
private SourceLocation location;
|
||||
private String expression;
|
||||
private String id;
|
||||
|
||||
public PathEngineException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PathEngineException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
|
@ -60,6 +58,26 @@ public class PathEngineException extends FHIRException {
|
|||
super(message+rep(location, expression));
|
||||
}
|
||||
|
||||
public PathEngineException(String message, String id, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public PathEngineException(String message, String id) {
|
||||
super(message);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public PathEngineException(String message, String id, SourceLocation location, String expression, Throwable cause) {
|
||||
super(message+rep(location, expression), cause);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public PathEngineException(String message, String id, SourceLocation location, String expression) {
|
||||
super(message+rep(location, expression));
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private static String rep(SourceLocation loc, String expr) {
|
||||
if (loc != null) {
|
||||
if (loc.getLine() == 1) {
|
||||
|
@ -94,4 +112,8 @@ public class PathEngineException extends FHIRException {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
|
@ -952,6 +952,7 @@ public class I18nConstants {
|
|||
public static final String FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT = "FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT";
|
||||
public static final String ED_INVARIANT_KEY_ALREADY_USED = "ED_INVARIANT_KEY_ALREADY_USED";
|
||||
public static final String FHIRPATH_OFTYPE_IMPOSSIBLE = "FHIRPATH_OFTYPE_IMPOSSIBLE";
|
||||
public static final String FHIRPATH_AS_IMPOSSIBLE = "FHIRPATH_AS_IMPOSSIBLE";
|
||||
public static final String ED_SEARCH_EXPRESSION_ERROR = "ED_SEARCH_EXPRESSION_ERROR";
|
||||
public static final String SD_EXTENSION_URL_MISMATCH = "SD_EXTENSION_URL_MISMATCH";
|
||||
public static final String MSG_DEPRECATED = "MSG_DEPRECATED";
|
||||
|
@ -1015,6 +1016,12 @@ public class I18nConstants {
|
|||
public static final String UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV = "UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV";
|
||||
public static final String ED_CONTEXT_INVARIANT_EXPRESSION_ERROR = "ED_CONTEXT_INVARIANT_EXPRESSION_ERROR";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_OBS = "VALIDATION_VAL_PROFILE_SIGNPOST_OBS";
|
||||
public static final String FHIRPATH_INVALID_TYPE = "FHIRPATH_INVALID_TYPE";
|
||||
public static final String FHIRPATH_AS_COLLECTION = "FHIRPATH_AS_COLLECTION";
|
||||
public static final String FHIRPATH_ARITHMETIC_QTY = "FHIRPATH_ARITHMETIC_QTY";
|
||||
public static final String FHIRPATH_ARITHMETIC_UNIT = "FHIRPATH_ARITHMETIC_UNIT";
|
||||
public static final String FHIRPATH_ARITHMETIC_PLUS = "FHIRPATH_ARITHMETIC_PLUS";
|
||||
public static final String FHIRPATH_ARITHMETIC_MINUS = "FHIRPATH_ARITHMETIC_MINUS";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1004,7 +1004,8 @@ LIQUID_VARIABLE_ILLEGAL = Liquid Exception: The variable name ''{0}'' cannot be
|
|||
ED_INVARIANT_DIFF_NO_SOURCE = The invariant {0} defined in the differential must have no source, or the source must be the same as the profile
|
||||
FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT = The left side is inherently a collection, and so the expression ''{0}'' may fail or return false if there is more than one item in the content being evaluated
|
||||
FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT = The right side is inherently a collection, and so this expression ''{0}'' may fail or return false if there is more than one item in the content being evaluated
|
||||
FHIRPATH_OFTYPE_IMPOSSIBLE = The type specified in ofType is {1} which is not a possible candidate for the existing types ({0}) in the expression {2}. Check the paths and types to be sure this is what is intended
|
||||
FHIRPATH_OFTYPE_IMPOSSIBLE = The type specified in ofType() is {1} which is not a possible candidate for the existing types ({0}) in the expression {2}. Check the paths and types to be sure this is what is intended
|
||||
FHIRPATH_AS_IMPOSSIBLE = The type specified in as() is {1} which is not a possible candidate for the existing types ({0}) in the expression {2}. Check the paths and types to be sure this is what is intended
|
||||
ED_SEARCH_EXPRESSION_ERROR = Error in search expression ''{0}'': {1}
|
||||
SD_EXTENSION_URL_MISMATCH = The fixed value for the extension URL is {1} which doesn''t match the canonical URL {0}
|
||||
SD_EXTENSION_URL_MISSING = The value of Extension.url is not fixed to the extension URL {0}
|
||||
|
@ -1072,4 +1073,9 @@ CDA_UNKNOWN_TEMPLATE_EXT = The CDA Template {0} / {1} is not known
|
|||
UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV = The types could not be determined from the extension context, so the invariant can't be validated (types = {0})
|
||||
ED_CONTEXT_INVARIANT_EXPRESSION_ERROR = Error in constraint ''{0}'': {1}
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_OBS = Validate Observation against {1} profile because the {2} code {3} was found
|
||||
|
||||
FHIRPATH_INVALID_TYPE = The type {0} is not valid
|
||||
FHIRPATH_AS_COLLECTION = Attempt to use ''as()'' on more than one item (''{0}'', ''{1}'')
|
||||
FHIRPATH_ARITHMETIC_QTY = Error in date arithmetic: attempt to add a definite quantity duration time unit {0}
|
||||
FHIRPATH_ARITHMETIC_UNIT = Error in date arithmetic: unrecognized time unit {0}
|
||||
FHIRPATH_ARITHMETIC_PLUS = Error in date arithmetic: Unable to add type {0} to {1}
|
||||
FHIRPATH_ARITHMETIC_MINUS = Error in date arithmetic: Unable to subtract type {0} to {1}
|
||||
|
|
|
@ -448,7 +448,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
protected boolean ruleInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, String invId, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage).setInvId(invId);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, invId).setInvId(invId);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
protected boolean txRule(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(theMessage);
|
||||
ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(idForMessage(theMessage, message));
|
||||
vm.setRuleDate(ruleDate);
|
||||
if (checkMsgId(theMessage, vm)) {
|
||||
errors.add(vm.setTxLink(txLink));
|
||||
|
@ -481,6 +481,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
return thePass;
|
||||
}
|
||||
|
||||
private String idForMessage(String theMessage, String message) {
|
||||
return theMessage.equals(message) ? null : theMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#ERROR} validation message if the validation fails
|
||||
*
|
||||
|
@ -605,18 +609,33 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
|
||||
}
|
||||
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String id, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, id);
|
||||
}
|
||||
return thePass;
|
||||
|
||||
}
|
||||
|
||||
protected boolean warningInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, String invId, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg).setInvId(invId);
|
||||
String id = idForMessage(msg, nmsg);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, id).setMessageId(id).setInvId(invId);
|
||||
}
|
||||
return thePass;
|
||||
|
||||
}
|
||||
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
return warning(errors, ruleDate, type, stack.line(), stack.col(), stack.getLiteralPath(), thePass, msg, theMessageArguments);
|
||||
return warning(errors, ruleDate, type, stack, null, thePass, msg, theMessageArguments);
|
||||
}
|
||||
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, String id, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
return warning(errors, ruleDate, type, stack.line(), stack.col(), stack.getLiteralPath(), id, thePass, msg, theMessageArguments);
|
||||
}
|
||||
|
||||
protected boolean warningPlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String msg, Object... theMessageArguments) {
|
||||
|
@ -664,7 +683,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
|
|||
protected boolean txWarning(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg);
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(idForMessage(msg, nmsg));
|
||||
vmsg.setRuleDate(ruleDate);
|
||||
if (checkMsgId(msg, vmsg)) {
|
||||
errors.add(vmsg);
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.ExpressionNode.Kind;
|
|||
import org.hl7.fhir.r5.model.ExpressionNode.Operation;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IssueMessage;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
|
@ -77,10 +78,10 @@ public class SearchParameterValidator extends BaseValidator {
|
|||
private boolean checkExpression(List<ValidationMessage> errors, NodeStack stack, String expression, List<String> bases) {
|
||||
boolean ok = true;
|
||||
try {
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
fpe.checkOnTypes(null, null, bases, fpe.parse(expression), warnings);
|
||||
for (String s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, s);
|
||||
for (IssueMessage m : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, m.getId(), false, m.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IssueMessage;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
@ -554,15 +555,20 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
// we got to the root before finding anything typed
|
||||
types.add(elements.get(0).getNamedChildValue("path"));
|
||||
}
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
ValidationContext vc = new ValidationContext(invariant);
|
||||
if (Utilities.existsInList(rootPath, context.getResourceNames())) {
|
||||
fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings);
|
||||
} else {
|
||||
StructureDefinition sd = context.fetchTypeDefinition(rootPath);
|
||||
if (sd != null) {
|
||||
fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings);
|
||||
} else {
|
||||
fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings);
|
||||
}
|
||||
for (String s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, key+": "+s);
|
||||
}
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, s.getId(), false, key+": "+s.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
|
@ -593,11 +599,11 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
hint(errors, "2023-10-31", IssueType.INFORMATIONAL, stack, false, I18nConstants.UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV, listContexts(sd));
|
||||
} else
|
||||
try {
|
||||
List<String> warnings = new ArrayList<>();
|
||||
List<IssueMessage> warnings = new ArrayList<>();
|
||||
ValidationContext vc = new ValidationContext(invariant);
|
||||
fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings);
|
||||
for (String s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, s);
|
||||
for (IssueMessage s : warnings) {
|
||||
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, s.getId(), false, s.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -20,7 +20,7 @@
|
|||
<properties>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.4.15</validator_test_case_version>
|
||||
<validator_test_case_version>1.4.16-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.15.2</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