moved i18StringConstants class -> fhir.utilities

Extracted error messages of ProfileUtilities
This commit is contained in:
patrick-werner 2020-03-05 15:03:03 +01:00
parent d8262c056c
commit 54bcac00ed
5 changed files with 328 additions and 150 deletions

View File

@ -9,9 +9,9 @@ package org.hl7.fhir.r5.conformance;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -20,6 +20,10 @@ package org.hl7.fhir.r5.conformance;
* #L%
*/
import static org.hl7.fhir.utilities.I18nConstants.formatMessage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@ -31,6 +35,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
@ -95,6 +100,7 @@ import org.hl7.fhir.r5.utils.TranslatingUtilities;
import org.hl7.fhir.r5.utils.formats.CSVWriter;
import org.hl7.fhir.r5.utils.formats.XLSXWriter;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.I18nConstants;
import org.hl7.fhir.utilities.TerminologyServiceOptions;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
@ -266,6 +272,7 @@ public class ProfileUtilities extends TranslatingUtilities {
private boolean newSlicingProcessing;
private String defWebRoot;
private boolean autoFixSliceNames;
private ResourceBundle i18nMessages;
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp) {
super();
@ -274,6 +281,11 @@ public class ProfileUtilities extends TranslatingUtilities {
this.pkp = pkp;
}
public ProfileUtilities(IWorkerContext theContext, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, ResourceBundle i18Nmessages) {
this(theContext, messages, pkp);
this.i18nMessages = i18Nmessages;
}
private class UnusedTracker {
private boolean used;
}
@ -298,19 +310,20 @@ public class ProfileUtilities extends TranslatingUtilities {
}
public interface ProfileKnowledgeProvider {
public class BindingResolution {
class BindingResolution {
public String display;
public String url;
}
public boolean isDatatype(String typeSimple);
public boolean isResource(String typeSimple);
public boolean hasLinkFor(String typeSimple);
public String getLinkFor(String corePath, String typeSimple);
public BindingResolution resolveBinding(StructureDefinition def, ElementDefinitionBindingComponent binding, String path) throws FHIRException;
public BindingResolution resolveBinding(StructureDefinition def, String url, String path) throws FHIRException;
public String getLinkForProfile(StructureDefinition profile, String url);
public boolean prependLinks();
public String getLinkForUrl(String corePath, String s);
boolean isDatatype(String typeSimple);
boolean isResource(String typeSimple);
boolean hasLinkFor(String typeSimple);
String getLinkFor(String corePath, String typeSimple);
BindingResolution resolveBinding(StructureDefinition def,
ElementDefinitionBindingComponent binding, String path) throws FHIRException;
BindingResolution resolveBinding(StructureDefinition def, String url, String path) throws FHIRException;
String getLinkForProfile(StructureDefinition profile, String url);
boolean prependLinks();
String getLinkForUrl(String corePath, String s);
}
@ -321,7 +334,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (element.getContentReference().equals("#"+e.getId()))
return getChildMap(profile, e);
}
throw new DefinitionException("Unable to resolve name reference "+element.getContentReference()+" at path "+element.getPath());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_RESOLVE_NAME_REFERENCE__AT_PATH_, element.getContentReference(), element.getPath()));
} else {
List<ElementDefinition> res = new ArrayList<ElementDefinition>();
@ -343,7 +356,7 @@ public class ProfileUtilities extends TranslatingUtilities {
public List<ElementDefinition> getSliceList(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
if (!element.hasSlicing())
throw new Error("getSliceList should only be called when the element has slicing");
throw new Error(formatMessage(i18nMessages, I18nConstants.GETSLICELIST_SHOULD_ONLY_BE_CALLED_WHEN_THE_ELEMENT_HAS_SLICING));
List<ElementDefinition> res = new ArrayList<ElementDefinition>();
List<ElementDefinition> elements = profile.getSnapshot().getElement();
@ -382,9 +395,9 @@ public class ProfileUtilities extends TranslatingUtilities {
List<ElementDefinition> list = diff ? profile.getDifferential().getElement() : profile.getSnapshot().getElement();
for (ElementDefinition e : list) {
if (e == null)
throw new Error("element = null: "+profile.getUrl());
throw new Error(formatMessage(i18nMessages, I18nConstants.ELEMENT__NULL_, profile.getUrl()));
if (e.getId() == null)
throw new Error("element id = null: "+e.toString()+" on "+profile.getUrl());
throw new Error(formatMessage(i18nMessages, I18nConstants.ELEMENT_ID__NULL__ON_, e.toString(), profile.getUrl()));
if (!capturing && id!=null && e.getId().equals(id)) {
capturing = true;
@ -425,9 +438,9 @@ public class ProfileUtilities extends TranslatingUtilities {
public void updateMaps(StructureDefinition base, StructureDefinition derived) throws DefinitionException {
if (base == null)
throw new DefinitionException("no base profile provided");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NO_BASE_PROFILE_PROVIDED));
if (derived == null)
throw new DefinitionException("no derived structure provided");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NO_DERIVED_STRUCTURE_PROVIDED));
for (StructureDefinitionMappingComponent baseMap : base.getMapping()) {
boolean found = false;
@ -458,30 +471,30 @@ public class ProfileUtilities extends TranslatingUtilities {
*/
public void generateSnapshot(StructureDefinition base, StructureDefinition derived, String url, String webUrl, String profileName) throws DefinitionException, FHIRException {
if (base == null) {
throw new DefinitionException("no base profile provided");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NO_BASE_PROFILE_PROVIDED));
}
if (derived == null) {
throw new DefinitionException("no derived structure provided");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NO_DERIVED_STRUCTURE_PROVIDED));
}
checkNotGenerating(base, "Base for generating a snapshot for the profile "+derived.getUrl());
checkNotGenerating(derived, "Focus for generating a snapshot");
derived.setUserData("profileutils.snapshot.generating", true);
if (!base.hasType()) {
throw new DefinitionException("Base profile "+base.getUrl()+" has no type");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.BASE_PROFILE__HAS_NO_TYPE, base.getUrl()));
}
if (!derived.hasType()) {
throw new DefinitionException("Derived profile "+derived.getUrl()+" has no type");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.DERIVED_PROFILE__HAS_NO_TYPE, derived.getUrl()));
}
if (!derived.hasDerivation()) {
throw new DefinitionException("Derived profile "+derived.getUrl()+" has no derivation value and so can't be processed");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.DERIVED_PROFILE__HAS_NO_DERIVATION_VALUE_AND_SO_CANT_BE_PROCESSED, derived.getUrl()));
}
if (!base.getType().equals(derived.getType()) && derived.getDerivation() == TypeDerivationRule.CONSTRAINT) {
throw new DefinitionException("Base & Derived profiles have different types ("+base.getUrl()+" = "+base.getType()+" vs "+derived.getUrl()+" = "+derived.getType()+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___, base.getUrl(), base.getType(), derived.getUrl(), derived.getType()));
}
if (snapshotStack.contains(derived.getUrl())) {
throw new DefinitionException("Circular snapshot references detected; cannot generate snapshot (stack = "+snapshotStack.toString()+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.CIRCULAR_SNAPSHOT_REFERENCES_DETECTED_CANNOT_GENERATE_SNAPSHOT_STACK__, snapshotStack.toString()));
}
snapshotStack.add(derived.getUrl());
@ -505,7 +518,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int diffCursor = 0; // we need a diff cursor because we can only look ahead, in the bound scoped by longer paths
if (derived.hasDifferential() && !derived.getDifferential().getElementFirstRep().getPath().contains(".") && !derived.getDifferential().getElementFirstRep().getType().isEmpty())
throw new Error("type on first differential element!");
throw new Error(formatMessage(i18nMessages, I18nConstants.TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT));
for (ElementDefinition e : derived.getDifferential().getElement())
e.clearUserData(GENERATED_IN_SNAPSHOT);
@ -536,7 +549,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
if (!derived.getSnapshot().getElementFirstRep().getType().isEmpty())
throw new Error("type on first snapshot element for "+derived.getSnapshot().getElementFirstRep().getPath()+" in "+derived.getUrl()+" from "+base.getUrl());
throw new Error(formatMessage(i18nMessages, I18nConstants.TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_, derived.getSnapshot().getElementFirstRep().getPath(), derived.getUrl(), base.getUrl()));
updateMaps(base, derived);
if (debug) {
@ -553,7 +566,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int ce = 0;
for (ElementDefinition e : diff.getElement()) {
if (!e.hasUserData("diff-source"))
throw new Error("Unxpected internal condition - no source on diff element");
throw new Error(formatMessage(i18nMessages, I18nConstants.UNXPECTED_INTERNAL_CONDITION__NO_SOURCE_ON_DIFF_ELEMENT));
else {
if (e.hasUserData(DERIVATION_EQUALS))
((Base) e.getUserData("diff-source")).setUserData(DERIVATION_EQUALS, e.getUserData(DERIVATION_EQUALS));
@ -592,7 +605,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
}
// last, check for wrong profiles or target profiles
// last, check for wrong profiles or target profiles
for (ElementDefinition ed : derived.getSnapshot().getElement()) {
for (TypeRefComponent t : ed.getType()) {
for (UriType u : t.getProfile()) {
@ -632,14 +645,14 @@ public class ProfileUtilities extends TranslatingUtilities {
boolean first = true;
for (ElementDefinition ed : elements) {
if (!ed.hasPath()) {
throw new FHIRException("No path on element in differential in "+url);
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.NO_PATH_ON_ELEMENT_IN_DIFFERENTIAL_IN_, url));
}
String p = ed.getPath();
if (p == null) {
throw new FHIRException("No path value on element in differential in "+url);
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.NO_PATH_VALUE_ON_ELEMENT_IN_DIFFERENTIAL_IN_, url));
}
if (!((first && type.equals(p)) || p.startsWith(type+"."))) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": must start with "+type+"."+(first ? " (o be '"+type+"')" : ""));
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__MUST_START_WITH_, p, url, type, (first ? " (o be '"+type+"')" : "")));
}
if (p.contains(".")) {
// Element names (the parts of a path delineated by the '.' character) SHALL NOT contain whitespace (i.e. Unicode characters marked as whitespace)
@ -649,25 +662,25 @@ public class ProfileUtilities extends TranslatingUtilities {
String[] pl = p.split("\\.");
for (String pp : pl) {
if (pp.length() < 1) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": name portion mising ('..')");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NAME_PORTION_MISING_, p, url));
}
if (pp.length() > 64) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": name portion exceeds 64 chars in length");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NAME_PORTION_EXCEEDS_64_CHARS_IN_LENGTH, p, url));
}
for (char ch : pp.toCharArray()) {
if (Character.isWhitespace(ch)) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": no unicode whitespace");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NO_UNICODE_WHITESPACE, p, url));
}
if (Utilities.existsInList(ch, ',', ':', ';', '\'', '"', '/', '|', '?', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '{', '}')) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": illegal character '"+ch+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__ILLEGAL_CHARACTER_, p, url, ch));
}
if (ch < ' ' || ch > 'z') {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": illegal character '"+ch+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__ILLEGAL_CHARACTER_, p, url, ch));
}
}
if (pp.contains("[") || pp.contains("]")) {
if (!pp.endsWith("[x]") || (pp.substring(0, pp.length()-3).contains("[") || (pp.substring(0, pp.length()-3).contains("]")))) {
throw new FHIRException("Illegal path '"+p+"' in differential in "+url+": illegal characters []");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ILLEGAL_PATH__IN_DIFFERENTIAL_IN__ILLEGAL_CHARACTERS_, p, url));
}
}
}
@ -821,7 +834,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (resultPathBase == null)
resultPathBase = outcome.getPath();
else if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path - outcome.getPath() = "+outcome.getPath()+", resultPathBase = "+resultPathBase);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH__OUTCOMEGETPATH___RESULTPATHBASE__, outcome.getPath(), resultPathBase));
result.getElement().add(outcome);
if (hasInnerDiffMatches(differential, cpath, diffCursor, diffLimit, base.getElement(), true)) {
// well, the profile walks into this, so we need to as well
@ -831,17 +844,17 @@ public class ProfileUtilities extends TranslatingUtilities {
baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor+1, baseLimit);
} else {
if (outcome.getType().size() == 0) {
throw new DefinitionException(diffMatches.get(0).getPath()+" has no children ("+differential.getElement().get(diffCursor).getPath()+") and no types in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), profileName));
}
if (outcome.getType().size() > 1) {
for (TypeRefComponent t : outcome.getType()) {
if (!t.getWorkingCode().equals("Reference"))
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") and multiple types ("+typeCode(outcome.getType())+") in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
}
}
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0));
if (dt == null)
throw new DefinitionException("Unknown type "+outcome.getType().get(0)+" at "+diffMatches.get(0).getPath());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
contextName = dt.getUrl();
int start = diffCursor;
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+"."))
@ -861,7 +874,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!sd.hasSnapshot()) {
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
if (sdb == null)
throw new DefinitionException("Unable to find base "+sd.getBaseDefinition()+" for "+sd.getUrl());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), sd.getUrl()));
checkNotGenerating(sdb, "an extension base");
generateSnapshot(sdb, sd, sd.getUrl(), (sdb.hasUserData("path")) ? Utilities.extractBaseUrl(sdb.getUserString("path")) : webUrl, sd.getName());
}
@ -874,7 +887,7 @@ public class ProfileUtilities extends TranslatingUtilities {
src = t;
}
if (src == null)
throw new DefinitionException("Unable to find element "+eid+" in "+p.getValue());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_FIND_ELEMENT__IN_, eid, p.getValue()));
} else
src = sd.getSnapshot().getElement().get(0);
template = src.copy().setPath(currentBase.getPath());
@ -907,7 +920,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (resultPathBase == null)
resultPathBase = outcome.getPath();
else if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
baseCursor++;
diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1;
@ -934,7 +947,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (ed != diffMatches.get(0) && !ed.getPath().endsWith(".extension"))
nonExtension = true;
if (nonExtension)
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") and multiple types ("+typeCode(outcome.getType())+") in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
}
}
}
@ -944,7 +957,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (outcome.hasContentReference()) {
ElementDefinition tgt = getElementById(base.getElement(), outcome.getContentReference());
if (tgt == null)
throw new DefinitionException("Unable to resolve reference to "+outcome.getContentReference());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_RESOLVE_REFERENCE_TO_, outcome.getContentReference()));
replaceFromContentReference(outcome, tgt);
int nbc = base.getElement().indexOf(tgt)+1;
int nbl = nbc;
@ -954,7 +967,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} else {
StructureDefinition dt = outcome.getType().size() == 1 ? getProfileForDataType(outcome.getType().get(0)) : getProfileForDataType("Element");
if (dt == null)
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") for type "+typeCode(outcome.getType())+" in profile "+profileName+", but can't find type");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
contextName = dt.getUrl();
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor - 1, url, getWebUrl(dt, webUrl, indent), profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, new ArrayList<ElementRedirection>(), srcSD);
@ -967,9 +980,9 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndc = differential.getElement().indexOf(diffMatches.get(0));
ElementDefinition elementToRemove = null;
boolean shortCut = !typeList.isEmpty() && typeList.get(0).type != null;
// we come here whether they are sliced in the diff, or whether the short cut is used.
// we come here whether they are sliced in the diff, or whether the short cut is used.
if (shortCut) {
// this is the short cut method, we've just dived in and specified a type slice.
// this is the short cut method, we've just dived in and specified a type slice.
// in R3 (and unpatched R4, as a workaround right now...
if (!FHIRVersion.isR4Plus(context.getVersion()) || !newSlicingProcessing) { // newSlicingProcessing is a work around for editorial loop dependency
// we insert a cloned element with the right types at the start of the diffMatches
@ -985,9 +998,9 @@ public class ProfileUtilities extends TranslatingUtilities {
differential.getElement().add(ndc, ed);
elementToRemove = ed;
} else {
// as of R4, this changed; if there's no slice, there's no constraint on the slice types, only one the type.
// so the element we insert specifies no types (= all types) allowed in the base, not just the listed type.
// see also discussion here: https://chat.fhir.org/#narrow/stream/179177-conformance/topic/Slicing.20a.20non-repeating.20element
// as of R4, this changed; if there's no slice, there's no constraint on the slice types, only one the type.
// so the element we insert specifies no types (= all types) allowed in the base, not just the listed type.
// see also discussion here: https://chat.fhir.org/#narrow/stream/179177-conformance/topic/Slicing.20a.20non-repeating.20element
ElementDefinition ed = new ElementDefinition();
ed.setPath(determineTypeSlicePath(diffMatches.get(0).getPath(), cpath));
ed.setSlicing(new ElementDefinitionSlicingComponent());
@ -1004,18 +1017,18 @@ public class ProfileUtilities extends TranslatingUtilities {
if (diffMatches.get(0).getSlicing().hasOrdered()) {
if (diffMatches.get(0).getSlicing().getOrdered()) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.ordered = true");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGORDERED__TRUE, cpath, url));
}
}
if (diffMatches.get(0).getSlicing().hasDiscriminator()) {
if (diffMatches.get(0).getSlicing().getDiscriminator().size() != 1) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.count() > 1");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORCOUNT__1, cpath, url));
}
if (diffMatches.get(0).getSlicing().getDiscriminatorFirstRep().getType() != DiscriminatorType.TYPE) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.type != 'type'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORTYPE__TYPE, cpath, url));
}
if (!"$this".equals(diffMatches.get(0).getSlicing().getDiscriminatorFirstRep().getPath())) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.path != '$this'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORPATH__THIS, cpath, url));
}
}
// check the slice names too while we're at it...
@ -1028,28 +1041,28 @@ public class ProfileUtilities extends TranslatingUtilities {
if (autoFixSliceNames) {
ts.defn.setSliceName(tn);
} else {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice name must be '"+tn+"' but is '"+ts.defn.getSliceName()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_NAME_MUST_BE__BUT_IS_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.getSliceName()));
}
} if (!ts.defn.hasType()) {
ts.defn.addType().setCode(ts.type);
} else if (ts.defn.getType().size() > 1) {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice for type '"+tn+"' has more than one type '"+ts.defn.typeSummary()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_MORE_THAN_ONE_TYPE_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.typeSummary()));
} else if (!ts.defn.getType().get(0).getCode().equals(ts.type)) {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice for type '"+tn+"' has wrong type '"+ts.defn.typeSummary()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_WRONG_TYPE_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.typeSummary()));
}
}
}
// ok passed the checks.
// ok passed the checks.
// copy the root diff, and then process any children it has
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, null, redirector, srcSD);
if (e==null)
throw new FHIRException("Did not find type root: " + diffMatches.get(0).getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath()));
// now set up slicing on the e (cause it was wiped by what we called.
e.setSlicing(new ElementDefinitionSlicingComponent());
e.getSlicing().addDiscriminator().setType(DiscriminatorType.TYPE).setPath("$this");
e.getSlicing().setRules(SlicingRules.CLOSED); // type slicing is always closed; the differential might call it open, but that just means it's not constraining the slices it doesn't mention
e.getSlicing().setRules(SlicingRules.CLOSED); // type slicing is always closed; the differential might call it open, but that just means it's not constraining the slices it doesn't mention
e.getSlicing().setOrdered(false);
start++;
@ -1060,7 +1073,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// our processing scope for the differential is the item in the list, and all the items before the next one in the list
if (diffMatches.get(i).getMin() > 0) {
if (diffMatches.size() > i+1) {
throw new FHIRException("Invalid slicing : there is more than one type slice at "+diffMatches.get(i).getPath()+", but one of them ("+diffMatches.get(i).getSliceName()+") has min = 1, so the other slices cannot exist");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST, diffMatches.get(i).getPath(), diffMatches.get(i).getSliceName()));
} else {
e.setMin(1);
}
@ -1092,9 +1105,9 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!unbounded(currentBase) && !isSlicedToOneOnly(diffMatches.get(0)))
// you can only slice an element that doesn't repeat if the sum total of your slices is limited to 1
// (but you might do that in order to split up constraints by type)
throw new DefinitionException("Attempt to a slice an element that does not repeat: "+currentBase.getPath()+"/"+currentBase.getPath()+" from "+contextName+" in "+url);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ATTEMPT_TO_A_SLICE_AN_ELEMENT_THAT_DOES_NOT_REPEAT__FROM__IN_, currentBase.getPath(), currentBase.getPath(), contextName, url));
if (!diffMatches.get(0).hasSlicing() && !isExtension(currentBase)) // well, the diff has set up a slice, but hasn't defined it. this is an error
throw new DefinitionException("Differential does not have a slice: "+currentBase.getPath()+"/ (b:"+baseCursor+" of "+ baseLimit+" / "+ diffCursor +"/ "+diffLimit+") in profile "+url);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.DIFFERENTIAL_DOES_NOT_HAVE_A_SLICE__B_OF_____IN_PROFILE_, currentBase.getPath(), baseCursor, baseLimit, diffCursor, diffLimit, url));
// well, if it passed those preconditions then we slice the dest.
int start = 0;
@ -1106,7 +1119,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, null, redirector, srcSD);
if (e==null)
throw new FHIRException("Did not find single slice: " + diffMatches.get(0).getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.DID_NOT_FIND_SINGLE_SLICE_, diffMatches.get(0).getPath()));
e.setSlicing(diffMatches.get(0).getSlicing());
start++;
} else {
@ -1120,7 +1133,7 @@ public class ProfileUtilities extends TranslatingUtilities {
else
outcome.setSlicing(diffMatches.get(0).getSlicing().copy());
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
// differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice.
@ -1128,7 +1141,7 @@ public class ProfileUtilities extends TranslatingUtilities {
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url, srcSD);
removeStatusExtensions(outcome);
if (!outcome.hasContentReference() && !outcome.hasType()) {
throw new DefinitionException("not done yet");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NOT_DONE_YET));
}
start++;
// result.getElement().remove(result.getElement().size()-1);
@ -1177,7 +1190,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (resultPathBase == null)
resultPathBase = outcome.getPath();
else if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
// the profile walks into this, so we need to as well
// did we implicitly step into a new type?
@ -1186,17 +1199,17 @@ public class ProfileUtilities extends TranslatingUtilities {
baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor, baseLimit);
} else {
if (outcome.getType().size() == 0) {
throw new DefinitionException(diffMatches.get(0).getPath()+" has no children ("+differential.getElement().get(diffCursor).getPath()+") and no types in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), profileName));
}
if (outcome.getType().size() > 1) {
for (TypeRefComponent t : outcome.getType()) {
if (!t.getWorkingCode().equals("Reference"))
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") and multiple types ("+typeCode(outcome.getType())+") in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
}
}
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0));
if (dt == null)
throw new DefinitionException("Unknown type "+outcome.getType().get(0)+" at "+diffMatches.get(0).getPath());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
contextName = dt.getUrl();
int start = diffCursor;
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+"."))
@ -1212,7 +1225,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition outcome = updateURLs(url, webUrl, base.getElement().get(baseCursor).copy());
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path in profile " + profileName + ": "+outcome.getPath()+" vs " + resultPathBase);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH_IN_PROFILE___VS_, profileName, outcome.getPath(), resultPathBase));
result.getElement().add(outcome); // so we just copy it in
baseCursor++;
}
@ -1223,9 +1236,9 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndc = differential.getElement().indexOf(diffMatches.get(0));
ElementDefinition elementToRemove = null;
boolean shortCut = (!typeList.isEmpty() && typeList.get(0).type != null) || (diffMatches.get(0).hasSliceName() && !diffMatches.get(0).hasSlicing());
// we come here whether they are sliced in the diff, or whether the short cut is used.
// we come here whether they are sliced in the diff, or whether the short cut is used.
if (shortCut) {
// this is the short cut method, we've just dived in and specified a type slice.
// this is the short cut method, we've just dived in and specified a type slice.
// in R3 (and unpatched R4, as a workaround right now...
if (!FHIRVersion.isR4Plus(context.getVersion()) || !newSlicingProcessing) { // newSlicingProcessing is a work around for editorial loop dependency
// we insert a cloned element with the right types at the start of the diffMatches
@ -1241,9 +1254,9 @@ public class ProfileUtilities extends TranslatingUtilities {
differential.getElement().add(ndc, ed);
elementToRemove = ed;
} else {
// as of R4, this changed; if there's no slice, there's no constraint on the slice types, only one the type.
// so the element we insert specifies no types (= all types) allowed in the base, not just the listed type.
// see also discussion here: https://chat.fhir.org/#narrow/stream/179177-conformance/topic/Slicing.20a.20non-repeating.20element
// as of R4, this changed; if there's no slice, there's no constraint on the slice types, only one the type.
// so the element we insert specifies no types (= all types) allowed in the base, not just the listed type.
// see also discussion here: https://chat.fhir.org/#narrow/stream/179177-conformance/topic/Slicing.20a.20non-repeating.20element
ElementDefinition ed = new ElementDefinition();
ed.setPath(determineTypeSlicePath(diffMatches.get(0).getPath(), cpath));
ed.setSlicing(new ElementDefinitionSlicingComponent());
@ -1260,18 +1273,18 @@ public class ProfileUtilities extends TranslatingUtilities {
if (diffMatches.get(0).getSlicing().hasOrdered()) {
if (diffMatches.get(0).getSlicing().getOrdered()) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.ordered = true");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGORDERED__TRUE, cpath, url));
}
}
if (diffMatches.get(0).getSlicing().hasDiscriminator()) {
if (diffMatches.get(0).getSlicing().getDiscriminator().size() != 1) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.count() > 1");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORCOUNT__1, cpath, url));
}
if (diffMatches.get(0).getSlicing().getDiscriminatorFirstRep().getType() != DiscriminatorType.TYPE) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.type != 'type'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORTYPE__TYPE, cpath, url));
}
if (!"$this".equals(diffMatches.get(0).getSlicing().getDiscriminatorFirstRep().getPath())) {
throw new FHIRException("Error at path "+cpath+" in "+url+": Type slicing with slicing.discriminator.path != '$this'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORPATH__THIS, cpath, url));
}
}
// check the slice names too while we're at it...
@ -1281,27 +1294,27 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!ts.defn.hasSliceName()) {
ts.defn.setSliceName(tn);
} else if (!ts.defn.getSliceName().equals(tn)) {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice name must be '"+tn+"' but is '"+ts.defn.getSliceName()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_NAME_MUST_BE__BUT_IS_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.getSliceName()));
} if (!ts.defn.hasType()) {
ts.defn.addType().setCode(ts.type);
} else if (ts.defn.getType().size() > 1) {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice for type '"+tn+"' has more than one type '"+ts.defn.typeSummary()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_MORE_THAN_ONE_TYPE_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.typeSummary()));
} else if (!ts.defn.getType().get(0).getCode().equals(ts.type)) {
throw new FHIRException("Error at path "+(!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath)+": Slice for type '"+tn+"' has wrong type '"+ts.defn.typeSummary()+"'");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_WRONG_TYPE_, (!Utilities.noString(contextPathSrc) ? contextPathSrc : cpath), tn, ts.defn.typeSummary()));
}
}
}
// ok passed the checks.
// ok passed the checks.
// copy the root diff, and then process any children it has
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, cpath, redirector, srcSD);
if (e==null)
throw new FHIRException("Did not find type root: " + diffMatches.get(0).getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath()));
// now set up slicing on the e (cause it was wiped by what we called.
e.setSlicing(new ElementDefinitionSlicingComponent());
e.getSlicing().addDiscriminator().setType(DiscriminatorType.TYPE).setPath("$this");
e.getSlicing().setRules(SlicingRules.CLOSED); // type slicing is always closed; the differential might call it open, but that just means it's not constraining the slices it doesn't mention
e.getSlicing().setRules(SlicingRules.CLOSED); // type slicing is always closed; the differential might call it open, but that just means it's not constraining the slices it doesn't mention
e.getSlicing().setOrdered(false);
start++;
@ -1314,7 +1327,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// our processing scope for the differential is the item in the list, and all the items before the next one in the list
if (diffMatches.get(i).getMin() > 0) {
if (diffMatches.size() > i+1) {
throw new FHIRException("Invalid slicing : there is more than one type slice at "+diffMatches.get(i).getPath()+", but one of them ("+diffMatches.get(i).getSliceName()+") has min = 1, so the other slices cannot exist");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST, diffMatches.get(i).getPath(), diffMatches.get(i).getSliceName()));
}
fixedType = type;
}
@ -1366,11 +1379,11 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinitionSlicingComponent dSlice = diffMatches.get(0).getSlicing();
ElementDefinitionSlicingComponent bSlice = currentBase.getSlicing();
if (dSlice.hasOrderedElement() && bSlice.hasOrderedElement() && !orderMatches(dSlice.getOrderedElement(), bSlice.getOrderedElement()))
throw new DefinitionException("Slicing rules on differential ("+summarizeSlicing(dSlice)+") do not match those on base ("+summarizeSlicing(bSlice)+") - order @ "+path+" ("+contextName+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___ORDER___, summarizeSlicing(dSlice), summarizeSlicing(bSlice), path, contextName));
if (!discriminatorMatches(dSlice.getDiscriminator(), bSlice.getDiscriminator()))
throw new DefinitionException("Slicing rules on differential ("+summarizeSlicing(dSlice)+") do not match those on base ("+summarizeSlicing(bSlice)+") - disciminator @ "+path+" ("+contextName+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___DISCIMINATOR___, summarizeSlicing(dSlice), summarizeSlicing(bSlice), path, contextName));
if (!currentBase.isChoice() && !ruleMatches(dSlice.getRules(), bSlice.getRules()))
throw new DefinitionException("Slicing rules on differential ("+summarizeSlicing(dSlice)+") do not match those on base ("+summarizeSlicing(bSlice)+") - rule @ "+path+" ("+contextName+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___RULE___, summarizeSlicing(dSlice), summarizeSlicing(bSlice), path, contextName));
}
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
@ -1380,7 +1393,7 @@ public class ProfileUtilities extends TranslatingUtilities {
updateFromDefinition(outcome, diffMatches.get(0), profileName, closed, url, srcSD); // if there's no slice, we don't want to update the unsliced description
removeStatusExtensions(outcome);
} else if (!diffMatches.get(0).hasSliceName())
diffMatches.get(0).setUserData(GENERATED_IN_SNAPSHOT, outcome); // because of updateFromDefinition isn't called
diffMatches.get(0).setUserData(GENERATED_IN_SNAPSHOT, outcome); // because of updateFromDefinition isn't called
result.getElement().add(outcome);
@ -1394,11 +1407,11 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndl = findEndOfElement(differential, ndx);
if (nbl == baseCursor) {
if (base.getElement().get(baseCursor).getType().size() != 1) {
throw new Error("Differential walks into '"+cpath+" (@ "+diffMatches.get(0).toString()+")', but the base does not, and there is not a single fixed type. The type is "+base.getElement().get(baseCursor).typeSummary()+". This is not handled yet");
throw new Error(formatMessage(i18nMessages, I18nConstants.DIFFERENTIAL_WALKS_INTO____BUT_THE_BASE_DOES_NOT_AND_THERE_IS_NOT_A_SINGLE_FIXED_TYPE_THE_TYPE_IS__THIS_IS_NOT_HANDLED_YET, cpath, diffMatches.get(0).toString(), base.getElement().get(baseCursor).typeSummary()));
}
StructureDefinition dt = getProfileForDataType(base.getElement().get(baseCursor).getType().get(0));
if (dt == null) {
throw new DefinitionException("Unknown type "+outcome.getType().get(0)+" at "+diffMatches.get(0).getPath());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
}
contextName = dt.getUrl();
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+"."))
@ -1429,7 +1442,7 @@ public class ProfileUtilities extends TranslatingUtilities {
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
outcome.setSlicing(null);
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
if (diffpos < diffMatches.size() && diffMatches.get(diffpos).hasSliceName() && diffMatches.get(diffpos).getSliceName().equals(outcome.getSliceName())) {
// if there's a diff, we update the outcome with diff
// no? updateFromDefinition(outcome, diffMatches.get(diffpos), profileName, closed, url);
@ -1451,7 +1464,7 @@ public class ProfileUtilities extends TranslatingUtilities {
outcome = updateURLs(url, webUrl, base.getElement().get(baseCursor).copy());
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
baseCursor++;
}
@ -1462,11 +1475,11 @@ public class ProfileUtilities extends TranslatingUtilities {
// finally, we process any remaining entries in diff, which are new (and which are only allowed if the base wasn't closed
boolean checkImplicitTypes = false;
if (closed && diffpos < diffMatches.size()) {
// this is a problem, unless we're on a polymorhpic type and we're going to constrain a slice that actually implicitly exists
// this is a problem, unless we're on a polymorhpic type and we're going to constrain a slice that actually implicitly exists
if (currentBase.getPath().endsWith("[x]")) {
checkImplicitTypes = true;
} else {
throw new DefinitionException("The base snapshot marks a slicing as closed, but the differential tries to extend it in "+profileName+" at "+path+" ("+cpath+")");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.THE_BASE_SNAPSHOT_MARKS_A_SLICING_AS_CLOSED_BUT_THE_DIFFERENTIAL_TRIES_TO_EXTEND_IT_IN__AT__, profileName, path, cpath));
}
}
if (diffpos == diffMatches.size()) {
@ -1477,14 +1490,14 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition diffItem = diffMatches.get(diffpos);
for (ElementDefinition baseItem : baseMatches)
if (baseItem.getSliceName().equals(diffItem.getSliceName()))
throw new DefinitionException("Named items are out of order in the slice");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NAMED_ITEMS_ARE_OUT_OF_ORDER_IN_THE_SLICE));
outcome = updateURLs(url, webUrl, currentBase.copy());
// outcome = updateURLs(url, diffItem.copy());
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
updateFromBase(outcome, currentBase);
outcome.setSlicing(null);
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException("Adding wrong path");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
updateFromDefinition(outcome, diffItem, profileName, trimDifferential, url, srcSD);
removeStatusExtensions(outcome);
@ -1496,7 +1509,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (outcome.getType().size() > 1)
for (TypeRefComponent t : outcome.getType()) {
if (!t.getCode().equals("Reference"))
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") and multiple types ("+typeCode(outcome.getType())+") in profile "+profileName);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
}
TypeRefComponent t = outcome.getType().get(0);
if (t.getCode().equals("BackboneElement")) {
@ -1513,10 +1526,10 @@ public class ProfileUtilities extends TranslatingUtilities {
} else {
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0));
// if (t.getCode().equals("Extension") && t.hasProfile() && !t.getProfile().contains(":")) {
// lloydfix dt =
// lloydfix dt =
// }
if (dt == null)
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") for type "+typeCode(outcome.getType())+" in profile "+profileName+", but can't find type");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants._HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
contextName = dt.getUrl();
int start = diffCursor;
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+"."))
@ -1540,7 +1553,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (ElementDefinition e : result.getElement()) {
i++;
if (e.hasMinElement() && e.getMinElement().getValue()==null)
throw new Error("null min");
throw new Error(formatMessage(i18nMessages, I18nConstants.NULL_MIN));
}
return res;
}
@ -1548,7 +1561,7 @@ public class ProfileUtilities extends TranslatingUtilities {
private void checkNotGenerating(StructureDefinition sd, String role) {
if (sd.hasUserData("profileutils.snapshot.generating")) {
throw new FHIRException("Attempt to use a snapshot on profile '"+sd.getUrl()+"' as "+role+" before it is generated");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ATTEMPT_TO_USE_A_SNAPSHOT_ON_PROFILE__AS__BEFORE_IT_IS_GENERATED, sd.getUrl(), role));
}
}
@ -1573,12 +1586,12 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (isPrimitive(Utilities.uncapitalize(t))) {
fixedType = Utilities.uncapitalize(t);
} else {
throw new FHIRException("Unexpected condition in differential: type-slice.type-list.size() == 10 and implicit slice name does not contain a valid type ('"+t+"'?) at "+diffMatches.get(i).getPath()+"/"+diffMatches.get(i).getSliceName());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNEXPECTED_CONDITION_IN_DIFFERENTIAL_TYPESLICETYPELISTSIZE__10_AND_IMPLICIT_SLICE_NAME_DOES_NOT_CONTAIN_A_VALID_TYPE__AT_, t, diffMatches.get(i).getPath(), diffMatches.get(i).getSliceName()));
}
} else if (diffMatches.get(i).getType().size() == 1) {
fixedType = diffMatches.get(i).getType().get(0).getCode();
} else {
throw new FHIRException("Unexpected condition in differential: type-slice.type-list.size() != 1 at "+diffMatches.get(i).getPath()+"/"+diffMatches.get(i).getSliceName());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNEXPECTED_CONDITION_IN_DIFFERENTIAL_TYPESLICETYPELISTSIZE__1_AT_, diffMatches.get(i).getPath(), diffMatches.get(i).getSliceName()));
}
return fixedType;
}
@ -2147,14 +2160,14 @@ public class ProfileUtilities extends TranslatingUtilities {
for (int j = 0; j < p.length; j++) {
ok = ok && sp.length > j && (p[j].equals(sp[j]) || isSameBase(p[j], sp[j]));
}
// don't need this debug check - everything is ok
// if (ok != (statedPath.equals(path) || (path.endsWith("[x]") && statedPath.length() > path.length() - 2 &&
// statedPath.substring(0, path.length()-3).equals(path.substring(0, path.length()-3)) &&
// don't need this debug check - everything is ok
// if (ok != (statedPath.equals(path) || (path.endsWith("[x]") && statedPath.length() > path.length() - 2 &&
// statedPath.substring(0, path.length()-3).equals(path.substring(0, path.length()-3)) &&
// (statedPath.length() < path.length() || !statedPath.substring(path.length()).contains("."))))) {
// System.out.println("mismatch in paths: "+statedPath +" vs " +path);
// }
if (ok) {
/*
/*
* Commenting this out because it raises warnings when profiling inherited elements. For example,
* Error: unknown element 'Bundle.meta.profile' (or it is out of order) in profile ... (looking for 'Bundle.entry')
* Not sure we have enough information here to do the check properly. Might be better done when we're sorting the profile?
@ -2310,7 +2323,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (derived.hasMinElement()) {
if (!Base.compareDeep(derived.getMinElement(), base.getMinElement(), false)) {
if (derived.getMin() < base.getMin() && !derived.hasSliceName()) // in a slice, minimum cardinality rules do not apply
if (derived.getMin() < base.getMin() && !derived.hasSliceName()) // in a slice, minimum cardinality rules do not apply
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived min ("+Integer.toString(derived.getMin())+") cannot be less than base min ("+Integer.toString(base.getMin())+")", ValidationMessage.IssueSeverity.ERROR));
base.setMinElement(derived.getMinElement().copy());
} else if (trimDifferential)
@ -2453,7 +2466,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (derived.hasIsSummaryElement()) {
if (!Base.compareDeep(derived.getIsSummaryElement(), base.getIsSummaryElement(), false)) {
if (base.hasIsSummary())
throw new Error("Error in profile "+pn+" at "+derived.getPath()+": Base isSummary = "+base.getIsSummaryElement().asStringValue()+", derived isSummary = "+derived.getIsSummaryElement().asStringValue());
throw new Error(formatMessage(i18nMessages, I18nConstants.ERROR_IN_PROFILE__AT__BASE_ISSUMMARY___DERIVED_ISSUMMARY__, pn, derived.getPath(), base.getIsSummaryElement().asStringValue(), derived.getIsSummaryElement().asStringValue()));
base.setIsSummaryElement(derived.getIsSummaryElement().copy());
} else if (trimDifferential)
derived.setIsSummaryElement(null);
@ -2573,7 +2586,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ok = true;
}
if (ok && ts.hasTargetProfile()) {
// check that any derived target has a reference chain back to one of the base target profiles
// check that any derived target has a reference chain back to one of the base target profiles
for (UriType u : ts.getTargetProfile()) {
String url = u.getValue();
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
@ -2592,7 +2605,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
if (!tgtOk) {
if (messages == null) {
throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_, purl, derived.getPath(), url, td.getTargetProfile()));
} else {
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR));
}
@ -2601,7 +2614,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
if (!ok) {
throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl());
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.STRUCTUREDEFINITION__AT__ILLEGAL_CONSTRAINED_TYPE__FROM__IN_, purl, derived.getPath(), t, b.toString(), srcSD.getUrl()));
}
}
@ -3168,7 +3181,7 @@ public class ProfileUtilities extends TranslatingUtilities {
try {
return gen.generate(model, imagePath, 0, outputTracker);
} catch (org.hl7.fhir.exceptions.FHIRException e) {
throw new FHIRException("Error generating table for profile " + profile.getUrl() + ": " + e.getMessage(), e);
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.ERROR_GENERATING_TABLE_FOR_PROFILE__, profile.getUrl(), e.getMessage()), e);
}
}
@ -3178,7 +3191,7 @@ public class ProfileUtilities extends TranslatingUtilities {
while (i < list.size()) {
String[] pathCurrent = list.get(i).getPath().split("\\.");
String[] pathLast = list.get(i-1).getPath().split("\\.");
int firstDiff = 0; // the first entry must be a match
int firstDiff = 0; // the first entry must be a match
while (firstDiff < pathCurrent.length && firstDiff < pathLast.length && pathCurrent[firstDiff].equals(pathLast[firstDiff])) {
firstDiff++;
}
@ -3726,7 +3739,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ref = p.startsWith("http:") || igmode ? p : Utilities.pathURL(corePath, p);
}
fixedUrl = getFixedUrl(ed);
if (fixedUrl != null) {// if its null, we guess that it's not a profiled extension?
if (fixedUrl != null) {// if its null, we guess that it's not a profiled extension?
if (fixedUrl.equals(url))
fixedUrl = null;
else {
@ -3993,7 +4006,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (ed.getPath().equals(path))
return ed;
}
throw new FHIRException("Unable to find element "+path);
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_FIND_ELEMENT_, path));
}
@ -4262,7 +4275,7 @@ public class ProfileUtilities extends TranslatingUtilities {
return sd.getType();
if (Utilities.existsInList(value, "SimpleQuantity", "MoneyQuantity"))
return "Quantity";
throw new Error("Internal error - type not known "+value);
throw new Error(formatMessage(i18nMessages, I18nConstants.INTERNAL_ERROR___TYPE_NOT_KNOWN_, value));
}
@ -4562,7 +4575,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) {
if (ed.hasType() && "Resource".equals(ed.getType().get(0).getWorkingCode()) && child.getSelf().getType().get(0).hasProfile()) {
if (child.getSelf().getType().get(0).getProfile().size() > 1) {
throw new FHIRException("Unhandled situation: resource is profiled to more than one option - cannot sort profile");
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNHANDLED_SITUATION_RESOURCE_IS_PROFILED_TO_MORE_THAN_ONE_OPTION__CANNOT_SORT_PROFILE));
}
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
while (profile != null && profile.getDerivation() == TypeDerivationRule.CONSTRAINT) {
@ -4585,12 +4598,12 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (ed.getType().size() == 1 && !ed.getType().get(0).getWorkingCode().equals("*")) {
StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode()));
if (profile==null)
throw new FHIRException("Unable to resolve profile " + sdNs(ed.getType().get(0).getWorkingCode()) + " in element " + ed.getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath()));
ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), ed.getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name);
} else if (child.getSelf().getType().size() == 1) {
StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(child.getSelf().getType().get(0).getWorkingCode()));
if (profile==null)
throw new FHIRException("Unable to resolve profile " + sdNs(ed.getType().get(0).getWorkingCode()) + " in element " + ed.getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath()));
ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), child.getSelf().getType().get(0).getWorkingCode(), child.getSelf().getPath().length(), cmp.name);
} else if (ed.getPath().endsWith("[x]") && !child.getSelf().getPath().endsWith("[x]")) {
String edLastNode = ed.getPath().replaceAll("(.*\\.)*(.*)", "$2");
@ -4600,12 +4613,12 @@ public class ProfileUtilities extends TranslatingUtilities {
p = Utilities.uncapitalize(p);
StructureDefinition sd = context.fetchResource(StructureDefinition.class, sdNs(p));
if (sd == null)
throw new Error("Unable to find profile '"+p+"' at "+ed.getId());
throw new Error(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_FIND_PROFILE__AT_, p, ed.getId()));
ccmp = new ElementDefinitionComparer(false, sd.getSnapshot().getElement(), p, child.getSelf().getPath().length(), cmp.name);
} else if (child.getSelf().hasType() && child.getSelf().getType().get(0).getWorkingCode().equals("Reference")) {
for (TypeRefComponent t: child.getSelf().getType()) {
if (!t.getWorkingCode().equals("Reference")) {
throw new Error("Can't have children on an element with a polymorphic type - you must slice and constrain the types first (sortElements: "+ed.getPath()+":"+typeCode(ed.getType())+")");
throw new Error(formatMessage(i18nMessages, I18nConstants.CANT_HAVE_CHILDREN_ON_AN_ELEMENT_WITH_A_POLYMORPHIC_TYPE__YOU_MUST_SLICE_AND_CONSTRAIN_THE_TYPES_FIRST_SORTELEMENTS_, ed.getPath(), typeCode(ed.getType())));
}
}
StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode()));
@ -4613,7 +4626,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (!child.getSelf().hasType() && ed.getType().get(0).getWorkingCode().equals("Reference")) {
for (TypeRefComponent t: ed.getType()) {
if (!t.getWorkingCode().equals("Reference")) {
throw new Error("Not handled yet (sortElements: "+ed.getPath()+":"+typeCode(ed.getType())+")");
throw new Error(formatMessage(i18nMessages, I18nConstants.NOT_HANDLED_YET_SORTELEMENTS_, ed.getPath(), typeCode(ed.getType())));
}
}
StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs(ed.getType().get(0).getWorkingCode()));
@ -4622,7 +4635,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// this is allowed if we only profile the extensions
StructureDefinition profile = context.fetchResource(StructureDefinition.class, sdNs("Element"));
if (profile==null)
throw new FHIRException("Unable to resolve profile " + sdNs(ed.getType().get(0).getWorkingCode()) + " in element " + ed.getPath());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_, sdNs(ed.getType().get(0).getWorkingCode()), ed.getPath()));
ccmp = new ElementDefinitionComparer(false, profile.getSnapshot().getElement(), "Element", child.getSelf().getPath().length(), cmp.name);
// throw new Error("Not handled yet (sortElements: "+ed.getPath()+":"+typeCode(ed.getType())+")");
}
@ -4691,9 +4704,9 @@ public class ProfileUtilities extends TranslatingUtilities {
// generate schematrons for the rules in a structure definition
public void generateSchematrons(OutputStream dest, StructureDefinition structure) throws IOException, DefinitionException {
if (structure.getDerivation() != TypeDerivationRule.CONSTRAINT)
throw new DefinitionException("not the right kind of structure to generate schematrons for");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NOT_THE_RIGHT_KIND_OF_STRUCTURE_TO_GENERATE_SCHEMATRONS_FOR));
if (!structure.hasSnapshot())
throw new DefinitionException("needs a snapshot");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NEEDS_A_SNAPSHOT));
StructureDefinition base = context.fetchResource(StructureDefinition.class, structure.getBaseDefinition());
@ -4709,7 +4722,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// generate a CSV representation of the structure definition
public void generateCsvs(OutputStream dest, StructureDefinition structure, boolean asXml) throws IOException, DefinitionException, Exception {
if (!structure.hasSnapshot())
throw new DefinitionException("needs a snapshot");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NEEDS_A_SNAPSHOT));
CSVWriter csv = new CSVWriter(dest, structure, asXml);
@ -4725,7 +4738,7 @@ public class ProfileUtilities extends TranslatingUtilities {
System.out.println("no structure!");
}
if (!structure.hasSnapshot()) {
throw new DefinitionException("needs a snapshot");
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NEEDS_A_SNAPSHOT));
}
XLSXWriter xlsx = new XLSXWriter(dest, structure, asXml, hideMustSupportFalse);
@ -4885,7 +4898,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (ElementDefinition ed : list) {
List<String> paths = new ArrayList<String>();
if (!ed.hasPath())
throw new DefinitionException("No path on element Definition "+Integer.toString(list.indexOf(ed))+" in "+name);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.NO_PATH_ON_ELEMENT_DEFINITION__IN_, Integer.toString(list.indexOf(ed)), name));
sliceInfo.seeElement(ed);
String[] pl = ed.getPath().split("\\.");
for (int i = paths.size(); i < pl.length; i++) // -1 because the last path is in focus
@ -4909,7 +4922,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ed.setId(bs);
if (idList.containsKey(bs)) {
if (exception || messages == null) {
throw new DefinitionException("Same id '"+bs+"'on multiple elements "+idList.get(bs)+"/"+ed.getPath()+" in "+name);
throw new DefinitionException(formatMessage(i18nMessages, I18nConstants.SAME_ID_ON_MULTIPLE_ELEMENTS__IN_, bs, idList.get(bs), ed.getPath(), name));
} else
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, "Duplicate Element id "+bs, ValidationMessage.IssueSeverity.ERROR));
}
@ -5103,7 +5116,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (sd.hasBaseDefinition()) {
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
if (base == null)
throw new FHIRException("Unable to find base definition for logical model: "+sd.getBaseDefinition()+" from "+sd.getUrl());
throw new FHIRException(formatMessage(i18nMessages, I18nConstants.UNABLE_TO_FIND_BASE_DEFINITION_FOR_LOGICAL_MODEL__FROM_, sd.getBaseDefinition(), sd.getUrl()));
copyElements(sd, base.getSnapshot().getElement());
}
copyElements(sd, sd.getDifferential().getElement());
@ -5195,7 +5208,7 @@ public class ProfileUtilities extends TranslatingUtilities {
else if (slicer.getPath().equals("Bundle.entry"))
slicer.getSlicing().addDiscriminator().setType(DiscriminatorType.VALUE).setPath("resource.@profile");
else
throw new Error("No slicing for "+slicer.getPath());
throw new Error("No slicing for "+slicer.getPath());
}
public class SpanEntry {
@ -5314,7 +5327,7 @@ public class ProfileUtilities extends TranslatingUtilities {
ElementDefinition ned = ed;
while (ned != null && ned.getPath().contains(".")) {
ned = findParent(ned, list);
if (ned != null) { // todo: this can happen if we've walked into a resoruce. Not sure what to about that?
if (ned != null) { // todo: this can happen if we've walked into a resoruce. Not sure what to about that?
if ("0".equals(ned.getMax()))
max = 0;
else if (!ned.getMax().equals("1") && !ned.hasSlicing())

View File

@ -1,7 +1,22 @@
package org.hl7.fhir.validation.utils;
package org.hl7.fhir.utilities;
import java.text.MessageFormat;
import java.util.ResourceBundle;
public class I18nConstants {
public static String formatMessage(ResourceBundle resourceBundle, String theMessage, Object... theMessageArguments) {
String message;
if (theMessageArguments != null && theMessageArguments.length > 0) {
message = MessageFormat.format(resourceBundle.getString(theMessage), theMessageArguments);
} else if (resourceBundle.containsKey(theMessage)) {
message = resourceBundle.getString(theMessage);
} else {
message = theMessage;
}
return message;
}
public final static String BUNDLE_BUNDLE_ENTRY_CANONICAL = "Bundle_BUNDLE_Entry_Canonical";
public final static String BUNDLE_BUNDLE_ENTRY_DOCUMENT = "Bundle_BUNDLE_Entry_Document";
public final static String BUNDLE_BUNDLE_ENTRY_IDURLMISMATCH = "Bundle_BUNDLE_Entry_IdUrlMismatch";
@ -268,5 +283,76 @@ public class I18nConstants {
public final static String NOT_DONE_YET_VALIDATORHOSTSERVICESEXECUTEFUNCTION = "Not_done_yet_ValidatorHostServicesexecuteFunction";
public final static String NOT_DONE_YET_VALIDATORHOSTSERVICESCHECKFUNCTION = "Not_done_yet_ValidatorHostServicescheckFunction";
public final static String NOT_DONE_YET_VALIDATORHOSTSERVICESRESOLVEFUNCTION_ = "Not_done_yet_ValidatorHostServicesresolveFunction_";
public final static String UNABLE_TO_FIND_BASE_DEFINITION_FOR_LOGICAL_MODEL__FROM_ = "Unable_to_find_base_definition_for_logical_model__from_";
public final static String SAME_ID_ON_MULTIPLE_ELEMENTS__IN_ = "Same_id_on_multiple_elements__in_";
public final static String NO_PATH_ON_ELEMENT_DEFINITION__IN_ = "No_path_on_element_Definition__in_";
public final static String NEEDS_A_SNAPSHOT = "needs_a_snapshot";
public final static String NOT_THE_RIGHT_KIND_OF_STRUCTURE_TO_GENERATE_SCHEMATRONS_FOR = "not_the_right_kind_of_structure_to_generate_schematrons_for";
public final static String NOT_HANDLED_YET_SORTELEMENTS_ = "Not_handled_yet_sortElements_";
public final static String UNABLE_TO_RESOLVE_PROFILE__IN_ELEMENT_ = "Unable_to_resolve_profile__in_element_";
public final static String CANT_HAVE_CHILDREN_ON_AN_ELEMENT_WITH_A_POLYMORPHIC_TYPE__YOU_MUST_SLICE_AND_CONSTRAIN_THE_TYPES_FIRST_SORTELEMENTS_ = "Cant_have_children_on_an_element_with_a_polymorphic_type__you_must_slice_and_constrain_the_types_first_sortElements_";
public final static String UNABLE_TO_FIND_PROFILE__AT_ = "Unable_to_find_profile__at_";
public final static String UNHANDLED_SITUATION_RESOURCE_IS_PROFILED_TO_MORE_THAN_ONE_OPTION__CANNOT_SORT_PROFILE = "Unhandled_situation_resource_is_profiled_to_more_than_one_option__cannot_sort_profile";
public final static String INTERNAL_RECURSION_DETECTION_FIND_LOOP_PATH_RECURSION____CHECK_PATHS_ARE_VALID_FOR_PATH_ = "Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_";
public final static String INTERNAL_ERROR___TYPE_NOT_KNOWN_ = "Internal_error___type_not_known_";
public final static String UNABLE_TO_FIND_ELEMENT_ = "Unable_to_find_element_";
public final static String ERROR_GENERATING_TABLE_FOR_PROFILE__ = "Error_generating_table_for_profile__";
public final static String STRUCTUREDEFINITION__AT__ILLEGAL_CONSTRAINED_TYPE__FROM__IN_ = "StructureDefinition__at__illegal_constrained_type__from__in_";
public final static String ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_ = "Error_at__The_target_profile__is_not__valid_constraint_on_the_base_";
public final static String ERROR_IN_PROFILE__AT__BASE_ISSUMMARY___DERIVED_ISSUMMARY__ = "Error_in_profile__at__Base_isSummary___derived_isSummary__";
public final static String UNEXPECTED_CONDITION_IN_DIFFERENTIAL_TYPESLICETYPELISTSIZE__1_AT_ = "Unexpected_condition_in_differential_typeslicetypelistsize__1_at_";
public final static String UNEXPECTED_CONDITION_IN_DIFFERENTIAL_TYPESLICETYPELISTSIZE__10_AND_IMPLICIT_SLICE_NAME_DOES_NOT_CONTAIN_A_VALID_TYPE__AT_ = "Unexpected_condition_in_differential_typeslicetypelistsize__10_and_implicit_slice_name_does_not_contain_a_valid_type__at_";
public final static String ATTEMPT_TO_USE_A_SNAPSHOT_ON_PROFILE__AS__BEFORE_IT_IS_GENERATED = "Attempt_to_use_a_snapshot_on_profile__as__before_it_is_generated";
public final static String NULL_MIN = "null_min";
public final static String _HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE = "_has_children__for_type__in_profile__but_cant_find_type";
public final static String _HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_ = "_has_children__and_multiple_types__in_profile_";
public final static String ADDING_WRONG_PATH = "Adding_wrong_path";
public final static String NAMED_ITEMS_ARE_OUT_OF_ORDER_IN_THE_SLICE = "Named_items_are_out_of_order_in_the_slice";
public final static String THE_BASE_SNAPSHOT_MARKS_A_SLICING_AS_CLOSED_BUT_THE_DIFFERENTIAL_TRIES_TO_EXTEND_IT_IN__AT__ = "The_base_snapshot_marks_a_slicing_as_closed_but_the_differential_tries_to_extend_it_in__at__";
public final static String NOT_DONE_YET = "Not_done_yet";
public final static String UNKNOWN_TYPE__AT_ = "Unknown_type__at_";
public final static String DIFFERENTIAL_WALKS_INTO____BUT_THE_BASE_DOES_NOT_AND_THERE_IS_NOT_A_SINGLE_FIXED_TYPE_THE_TYPE_IS__THIS_IS_NOT_HANDLED_YET = "Differential_walks_into____but_the_base_does_not_and_there_is_not_a_single_fixed_type_The_type_is__This_is_not_handled_yet";
public final static String SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___RULE___ = "Slicing_rules_on_differential__do_not_match_those_on_base___rule___";
public final static String SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___DISCIMINATOR___ = "Slicing_rules_on_differential__do_not_match_those_on_base___disciminator___";
public final static String SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___ORDER___ = "Slicing_rules_on_differential__do_not_match_those_on_base___order___";
public final static String INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST = "Invalid_slicing__there_is_more_than_one_type_slice_at__but_one_of_them__has_min__1_so_the_other_slices_cannot_exist";
public final static String DID_NOT_FIND_TYPE_ROOT_ = "Did_not_find_type_root_";
public final static String ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_WRONG_TYPE_ = "Error_at_path__Slice_for_type__has_wrong_type_";
public final static String ERROR_AT_PATH__SLICE_FOR_TYPE__HAS_MORE_THAN_ONE_TYPE_ = "Error_at_path__Slice_for_type__has_more_than_one_type_";
public final static String ERROR_AT_PATH__SLICE_NAME_MUST_BE__BUT_IS_ = "Error_at_path__Slice_name_must_be__but_is_";
public final static String ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORPATH__THIS = "Error_at_path__in__Type_slicing_with_slicingdiscriminatorpath__this";
public final static String ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORTYPE__TYPE = "Error_at_path__in__Type_slicing_with_slicingdiscriminatortype__type";
public final static String ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGDISCRIMINATORCOUNT__1 = "Error_at_path__in__Type_slicing_with_slicingdiscriminatorcount__1";
public final static String ERROR_AT_PATH__IN__TYPE_SLICING_WITH_SLICINGORDERED__TRUE = "Error_at_path__in__Type_slicing_with_slicingordered__true";
public final static String ADDING_WRONG_PATH_IN_PROFILE___VS_ = "Adding_wrong_path_in_profile___vs_";
public final static String _HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_ = "_has_no_children__and_no_types_in_profile_";
public final static String DID_NOT_FIND_SINGLE_SLICE_ = "Did_not_find_single_slice_";
public final static String DIFFERENTIAL_DOES_NOT_HAVE_A_SLICE__B_OF_____IN_PROFILE_ = "Differential_does_not_have_a_slice__b_of_____in_profile_";
public final static String ATTEMPT_TO_A_SLICE_AN_ELEMENT_THAT_DOES_NOT_REPEAT__FROM__IN_ = "Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_";
public final static String UNABLE_TO_RESOLVE_REFERENCE_TO_ = "Unable_to_resolve_reference_to_";
public final static String UNABLE_TO_FIND_ELEMENT__IN_ = "Unable_to_find_element__in_";
public final static String UNABLE_TO_FIND_BASE__FOR_ = "Unable_to_find_base__for_";
public final static String ADDING_WRONG_PATH__OUTCOMEGETPATH___RESULTPATHBASE__ = "Adding_wrong_path__outcomegetPath___resultPathBase__";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__ILLEGAL_CHARACTERS_ = "Illegal_path__in_differential_in__illegal_characters_";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__ILLEGAL_CHARACTER_ = "Illegal_path__in_differential_in__illegal_character_";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NO_UNICODE_WHITESPACE = "Illegal_path__in_differential_in__no_unicode_whitespace";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NAME_PORTION_EXCEEDS_64_CHARS_IN_LENGTH = "Illegal_path__in_differential_in__name_portion_exceeds_64_chars_in_length";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NAME_PORTION_MISING_ = "Illegal_path__in_differential_in__name_portion_mising_";
public final static String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__MUST_START_WITH_ = "Illegal_path__in_differential_in__must_start_with_";
public final static String NO_PATH_VALUE_ON_ELEMENT_IN_DIFFERENTIAL_IN_ = "No_path_value_on_element_in_differential_in_";
public final static String NO_PATH_ON_ELEMENT_IN_DIFFERENTIAL_IN_ = "No_path_on_element_in_differential_in_";
public final static String UNXPECTED_INTERNAL_CONDITION__NO_SOURCE_ON_DIFF_ELEMENT = "Unxpected_internal_condition__no_source_on_diff_element";
public final static String TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_ = "type_on_first_snapshot_element_for__in__from_";
public final static String TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT = "type_on_first_differential_element";
public final static String CIRCULAR_SNAPSHOT_REFERENCES_DETECTED_CANNOT_GENERATE_SNAPSHOT_STACK__ = "Circular_snapshot_references_detected_cannot_generate_snapshot_stack__";
public final static String BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___ = "Base__Derived_profiles_have_different_types____vs___";
public final static String DERIVED_PROFILE__HAS_NO_DERIVATION_VALUE_AND_SO_CANT_BE_PROCESSED = "Derived_profile__has_no_derivation_value_and_so_cant_be_processed";
public final static String DERIVED_PROFILE__HAS_NO_TYPE = "Derived_profile__has_no_type";
public final static String BASE_PROFILE__HAS_NO_TYPE = "Base_profile__has_no_type";
public final static String NO_DERIVED_STRUCTURE_PROVIDED = "no_derived_structure_provided";
public final static String NO_BASE_PROFILE_PROVIDED = "no_base_profile_provided";
public final static String ELEMENT_ID__NULL__ON_ = "element_id__null__on_";
public final static String ELEMENT__NULL_ = "element__null_";
public final static String GETSLICELIST_SHOULD_ONLY_BE_CALLED_WHEN_THE_ELEMENT_HAS_SLICING = "getSliceList_should_only_be_called_when_the_element_has_slicing";
public final static String UNABLE_TO_RESOLVE_NAME_REFERENCE__AT_PATH_ = "Unable_to_resolve_name_reference__at_path_";
}

View File

@ -64,16 +64,16 @@ public class BaseValidator {
protected Source source;
protected IWorkerContext context;
private ResourceBundle messages;
private ResourceBundle i18Nmessages;
public BaseValidator(IWorkerContext context){
this.context = context;
messages = ResourceBundle.getBundle("Messages", context.getLocale() );
i18Nmessages = ResourceBundle.getBundle("Messages", context.getLocale() );
}
public void setContext(IWorkerContext context) {
this.context = context;
messages = ResourceBundle.getBundle("Messages", context.getLocale() );
i18Nmessages = ResourceBundle.getBundle("Messages", context.getLocale() );
}
/**
@ -146,11 +146,11 @@ public class BaseValidator {
protected String formatMessage(String theMessage, Object... theMessageArguments) {
String message = "";
if (messages.containsKey(theMessage)) {
if (i18Nmessages.containsKey(theMessage)) {
if (theMessageArguments != null && theMessageArguments.length > 0) {
message = MessageFormat.format(messages.getString(theMessage), theMessageArguments);
} else if (messages.containsKey(theMessage)) {
message = messages.getString(theMessage);
message = MessageFormat.format(i18Nmessages.getString(theMessage), theMessageArguments);
} else if (i18Nmessages.containsKey(theMessage)) {
message = i18Nmessages.getString(theMessage);
}
} else {
message = theMessage;
@ -564,4 +564,8 @@ public class BaseValidator {
}
return thePass;
}
public ResourceBundle getI18Nmessages() {
return i18Nmessages;
}
}

View File

@ -126,6 +126,7 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.IResourceValidator;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.I18nConstants;
import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator.QStack;
import org.hl7.fhir.validation.XVerExtensionManager;
@ -141,7 +142,6 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.validation.instance.utils.*;
import org.hl7.fhir.validation.utils.I18nConstants;
import org.w3c.dom.Document;
import com.google.gson.Gson;
@ -375,7 +375,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
super(theContext);
this.context = theContext;
this.externalHostServices = hostServices;
this.profileUtilities = new ProfileUtilities(theContext, null, null);
this.profileUtilities = new ProfileUtilities(theContext, null, null, getI18Nmessages());
fpe = new FHIRPathEngine(context);
validatorServices = new ValidatorHostServices();
fpe.setHostServices(validatorServices);

View File

@ -265,3 +265,78 @@ Not_done_yet__resolve__locally_2 = Not done yet - resolve {0} locally (2)
Not_done_yet_ValidatorHostServicesexecuteFunction = Not done yet (ValidatorHostServices.executeFunction)
Not_done_yet_ValidatorHostServicescheckFunction = Not done yet (ValidatorHostServices.checkFunction)
Not_done_yet_ValidatorHostServicesresolveFunction_ = Not done yet (ValidatorHostServices.resolveFunction): {0}
Unable_to_find_base_definition_for_logical_model__from_ = Unable to find base definition for logical model: {0} from {1}
Same_id_on_multiple_elements__in_ = Same id '{0}'on multiple elements {1}/{2} in {3}
No_path_on_element_Definition__in_ = No path on element Definition {0} in {1}
needs_a_snapshot = needs a snapshot
not_the_right_kind_of_structure_to_generate_schematrons_for = not the right kind of structure to generate schematrons for
Not_handled_yet_sortElements_ = Not handled yet (sortElements: {0}:{1})
Unable_to_resolve_profile__in_element_ = Unable to resolve profile {0} in element {1}
Cant_have_children_on_an_element_with_a_polymorphic_type__you_must_slice_and_constrain_the_types_first_sortElements_ = Can't have children on an element with a polymorphic type - you must slice and constrain the types first (sortElements: {0}:{1})
Unable_to_find_profile__at_ = Unable to find profile '{0}' at {1}
Unhandled_situation_resource_is_profiled_to_more_than_one_option__cannot_sort_profile = Unhandled situation: resource is profiled to more than one option - cannot sort profile
Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_ = Internal recursion detection: find() loop path recursion > {0} - check paths are valid (for path {1}/{2})
Internal_error___type_not_known_ = Internal error - type not known {0}
Unable_to_find_element_ = Unable to find element {0}
Error_generating_table_for_profile__ = Error generating table for profile {0}: {1}
StructureDefinition__at__illegal_constrained_type__from__in_ = StructureDefinition {0} at {1}: illegal constrained type {2} from {3} in {4}
Error_at__The_target_profile__is_not__valid_constraint_on_the_base_ = Error at {0}#{1}: The target profile {2} is not valid constraint on the base ({3})
Error_in_profile__at__Base_isSummary___derived_isSummary__ = Error in profile {0} at {1}: Base isSummary = {2}, derived isSummary = {3}
StructureDefinition__at__illegal_attempt_to_change_a_binding_from__to_ = StructureDefinition {0} at {1}: illegal attempt to change a binding from {2} to {3}
Unexpected_condition_in_differential_typeslicetypelistsize__1_at_ = Unexpected condition in differential: type-slice.type-list.size() != 1 at {0}/{1}
Unexpected_condition_in_differential_typeslicetypelistsize__10_and_implicit_slice_name_does_not_contain_a_valid_type__at_ = Unexpected condition in differential: type-slice.type-list.size() == 10 and implicit slice name does not contain a valid type ('{0}'?) at {1}/{2}
Attempt_to_use_a_snapshot_on_profile__as__before_it_is_generated = Attempt to use a snapshot on profile '{0}' as {1} before it is generated
null_min = null min
_has_children__for_type__in_profile__but_cant_find_type = {0} has children ({1}) for type {2} in profile {3}, but can't find type
_has_children__and_multiple_types__in_profile_ = {0} has children ({1}) and multiple types ({2}) in profile {3}
Adding_wrong_path = Adding wrong path
Named_items_are_out_of_order_in_the_slice = Named items are out of order in the slice
The_base_snapshot_marks_a_slicing_as_closed_but_the_differential_tries_to_extend_it_in__at__ = The base snapshot marks a slicing as closed, but the differential tries to extend it in {0} at {1} ({2})
Not_done_yet = Not done yet
Unknown_type__at_ = Unknown type {0} at {1}
Differential_walks_into____but_the_base_does_not_and_there_is_not_a_single_fixed_type_The_type_is__This_is_not_handled_yet = Differential walks into '{0} (@ {1})', but the base does not, and there is not a single fixed type. The type is {2}. This is not handled yet
Slicing_rules_on_differential__do_not_match_those_on_base___rule___ = Slicing rules on differential ({0}) do not match those on base ({1}) - rule @ {2} ({3})
Slicing_rules_on_differential__do_not_match_those_on_base___disciminator___ = Slicing rules on differential ({0}) do not match those on base ({1}) - disciminator @ {2} ({3})
Slicing_rules_on_differential__do_not_match_those_on_base___order___ = Slicing rules on differential ({0}) do not match those on base ({1}) - order @ {2} ({3})
not_done_yet__slicing__types__ = not done yet - slicing / types @ {0}
Invalid_slicing__there_is_more_than_one_type_slice_at__but_one_of_them__has_min__1_so_the_other_slices_cannot_exist = Invalid slicing : there is more than one type slice at {0}, but one of them ({1}) has min = 1, so the other slices cannot exist
Did_not_find_type_root_ = Did not find type root: {0}
Error_at_path__Slice_for_type__has_wrong_type_ = Error at path {0}: Slice for type '{1}' has wrong type '{2}'
Error_at_path__Slice_for_type__has_more_than_one_type_ = Error at path {0}: Slice for type '{1}' has more than one type '{2}'
Error_at_path__Slice_name_must_be__but_is_ = Error at path {0}: Slice name must be '{1}' but is '{2}'
Error_at_path__in__Type_slicing_with_slicingdiscriminatorpath__this = Error at path {0} in {1}: Type slicing with slicing.discriminator.path != '$this'
Error_at_path__in__Type_slicing_with_slicingdiscriminatortype__type = Error at path {0} in {1}: Type slicing with slicing.discriminator.type != 'type'
Error_at_path__in__Type_slicing_with_slicingdiscriminatorcount__1 = Error at path {0} in {1}: Type slicing with slicing.discriminator.count() > 1
Error_at_path__in__Type_slicing_with_slicingordered__true = Error at path {0} in {1}: Type slicing with slicing.ordered = true
Adding_wrong_path_in_profile___vs_ = Adding wrong path in profile {0}: {1} vs {2}
_has_no_children__and_no_types_in_profile_ = {0} has no children ({1}) and no types in profile {2}
not_done_yet = not done yet
Did_not_find_single_slice_ = Did not find single slice: {0}
Differential_does_not_have_a_slice__b_of_____in_profile_ = Differential does not have a slice: {0}/ (b:{1} of {2} / {3}/ {4}) in profile {5}
Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_ = Attempt to a slice an element that does not repeat: {0}/{1} from {2} in {3}
Unable_to_resolve_reference_to_ = Unable to resolve reference to {0}
Unable_to_find_element__in_ = Unable to find element {0} in {1}
Unable_to_find_base__for_ = Unable to find base {0} for {1}
Adding_wrong_path__outcomegetPath___resultPathBase__ = Adding wrong path - outcome.getPath() = {0}, resultPathBase = {1}
Illegal_path__in_differential_in__illegal_characters_ = Illegal path '{0}' in differential in {1}: illegal characters []
Illegal_path__in_differential_in__illegal_character_ = Illegal path '{0}' in differential in {1}: illegal character '{2}'
Illegal_path__in_differential_in__no_unicode_whitespace = Illegal path '{0}' in differential in {1}: no unicode whitespace
Illegal_path__in_differential_in__name_portion_exceeds_64_chars_in_length = Illegal path '{0}' in differential in {1}: name portion exceeds 64 chars in length
Illegal_path__in_differential_in__name_portion_mising_ = Illegal path '{0}' in differential in {1}: name portion mising ('..')
Illegal_path__in_differential_in__must_start_with_ = Illegal path '{0}' in differential in {1}: must start with {2}.{3}
No_path_value_on_element_in_differential_in_ = No path value on element in differential in {0}
No_path_on_element_in_differential_in_ = No path on element in differential in {0}
Unxpected_internal_condition__no_source_on_diff_element = Unxpected internal condition - no source on diff element
type_on_first_snapshot_element_for__in__from_ = type on first snapshot element for {0} in {1} from {2}
type_on_first_differential_element = type on first differential element!
Circular_snapshot_references_detected_cannot_generate_snapshot_stack__ = Circular snapshot references detected; cannot generate snapshot (stack = {0})
Base__Derived_profiles_have_different_types____vs___ = Base & Derived profiles have different types ({0} = {1} vs {2} = {3})
Derived_profile__has_no_derivation_value_and_so_cant_be_processed = Derived profile {0} has no derivation value and so can't be processed
Derived_profile__has_no_type = Derived profile {0} has no type
Base_profile__has_no_type = Base profile {0} has no type
no_derived_structure_provided = no derived structure provided
no_base_profile_provided = no base profile provided
element_id__null__on_ = element id = null: {0} on {1}
element__null_ = element = null: {0}
getSliceList_should_only_be_called_when_the_element_has_slicing = getSliceList should only be called when the element has slicing
Unable_to_resolve_name_reference__at_path_ = Unable to resolve name reference {0} at path {1}