Merge pull request #544 from hapifhir/gg-202106-validator-paths

Gg 202106 validator paths
This commit is contained in:
Grahame Grieve 2021-06-23 22:07:22 +10:00 committed by GitHub
commit e022acb569
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 652 additions and 452 deletions

View File

@ -53,6 +53,7 @@ import org.hl7.fhir.exceptions.NoTerminologyServiceException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory;
import org.hl7.fhir.r5.context.TerminologyCache.CacheToken;
import org.hl7.fhir.r5.model.BooleanType;
@ -159,7 +160,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
private Object lock = new Object(); // used as a lock for the data that follows
protected String version;
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
private String cacheId;
private boolean isTxCaching;
private Set<String> cached = new HashSet<>();
@ -266,9 +267,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
}
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies) {
// nothing yet
}
public void cacheResource(Resource r) throws FHIRException {
cacheResourceFromPackage(r, null);
@ -1317,6 +1315,65 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
}
public PackageVersion getPackageForUrl(String uri) {
if (uri == null) {
return null;
}
uri = ProfileUtilities.sdNs(uri, getOverrideVersionNs());
synchronized (lock) {
String version = null;
if (uri.contains("|")) {
version = uri.substring(uri.lastIndexOf("|")+1);
uri = uri.substring(0, uri.lastIndexOf("|"));
}
if (uri.contains("#")) {
uri = uri.substring(0, uri.indexOf("#"));
}
if (structures.has(uri)) {
return structures.getPackageInfo(uri, version);
}
if (guides.has(uri)) {
return guides.getPackageInfo(uri, version);
}
if (capstmts.has(uri)) {
return capstmts.getPackageInfo(uri, version);
}
if (measures.has(uri)) {
return measures.getPackageInfo(uri, version);
}
if (libraries.has(uri)) {
return libraries.getPackageInfo(uri, version);
}
if (valueSets.has(uri)) {
return valueSets.getPackageInfo(uri, version);
}
if (codeSystems.has(uri)) {
return codeSystems.getPackageInfo(uri, version);
}
if (operations.has(uri)) {
return operations.getPackageInfo(uri, version);
}
if (searchParameters.has(uri)) {
return searchParameters.getPackageInfo(uri, version);
}
if (plans.has(uri)) {
return plans.getPackageInfo(uri, version);
}
if (maps.has(uri)) {
return maps.getPackageInfo(uri, version);
}
if (transforms.has(uri)) {
return transforms.getPackageInfo(uri, version);
}
if (questionnaires.has(uri)) {
return questionnaires.getPackageInfo(uri, version);
}
return null;
}
}
@SuppressWarnings("unchecked")
public <T extends Resource> T fetchResourceWithException(String cls, String uri, CanonicalResource source) throws FHIRException {
if (uri == null) {
@ -1840,6 +1897,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
public String getLinkForUrl(String corePath, String url) {
if (url == null) {
return null;
}
if (codeSystems.has(url)) {
return codeSystems.get(url).getUserString("path");
}

View File

@ -292,6 +292,20 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
return map.containsKey(url) ? map.get(url).getResource() : null;
}
public PackageVersion getPackageInfo(String system, String version) {
if (version == null) {
return map.containsKey(system) ? map.get(system).getPackageInfo() : null;
} else {
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version).getPackageInfo();
String mm = VersionUtilities.getMajMin(version);
if (mm != null && map.containsKey(system+"|"+mm))
return map.get(system+"|"+mm).getPackageInfo();
else
return null;
}
}
public boolean has(String url) {
return map.containsKey(url);
}

View File

@ -170,6 +170,27 @@ public interface IWorkerContext {
}
}
public class PackageDetails extends PackageVersion {
private String name;
private String canonical;
private String web;
public PackageDetails(String id, String version, String name, String canonical, String web) {
super(id, version);
this.name = name;
this.canonical = canonical;
this.web = web;
}
public String getName() {
return name;
}
public String getCanonical() {
return canonical;
}
public String getWeb() {
return web;
}
}
public interface ICanonicalResourceLocator {
void findResource(Object caller, String url); // if it can be found, put it in the context
}
@ -387,7 +408,7 @@ public interface IWorkerContext {
*
* @param packageInfo
*/
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies);
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies);
// -- profile services ---------------------------------------------------------
@ -780,9 +801,13 @@ public interface IWorkerContext {
int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException;
public boolean hasPackage(String id, String ver);
public boolean hasPackage(PackageVersion pack);
public PackageDetails getPackage(PackageVersion pack);
public int getClientRetryCount();
public IWorkerContext setClientRetryCount(int value);
public TimeTracker clock();
public PackageVersion getPackageForUrl(String url);
}

View File

@ -54,6 +54,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory;
import org.hl7.fhir.r5.context.SimpleWorkerContext.PackageResourceLoader;
import org.hl7.fhir.r5.formats.IParser;
@ -810,15 +811,6 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
this.progress = progress;
}
@Override
public boolean hasPackage(String id, String ver) {
return loadedPackages.contains(id+"#"+ver);
}
public boolean hasPackage(String idAndver) {
return loadedPackages.contains(idAndver);
}
public void setClock(TimeTracker tt) {
clock = tt;
}
@ -837,5 +829,34 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
return xverManager;
}
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies) {
// nothing yet
}
@Override
public boolean hasPackage(String id, String ver) {
return loadedPackages.contains(id+"#"+ver);
}
public boolean hasPackage(String idAndver) {
return loadedPackages.contains(idAndver);
}
@Override
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies) {
// TODO Auto-generated method stub
}
@Override
public boolean hasPackage(PackageVersion pack) {
return false;
}
@Override
public PackageDetails getPackage(PackageVersion pack) {
return null;
}
}

View File

@ -55,6 +55,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.utilities.ElementDecoration;
import org.hl7.fhir.utilities.ElementDecoration.DecorationType;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -102,6 +103,8 @@ public class Element extends Base {
private String explicitType; // for xsi:type attribute
private Element parentForValidator;
private boolean hasParentForValidator;
private String path;
private List<ValidationMessage> messages;
public Element(String name) {
super();
@ -706,6 +709,13 @@ public class Element extends Base {
return property.isList();
}
public boolean isBaseList() {
if (elementProperty != null)
return elementProperty.isBaseList();
else
return property.isBaseList();
}
@Override
public String[] getTypesForProperty(int hash, String name) throws FHIRException {
Property p = property.getChildSimpleName(this.name, name);
@ -938,6 +948,29 @@ public class Element extends Base {
property = null;
elementProperty = null;
xhtml = null;
path = null;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public void addMessage(ValidationMessage vm) {
if (messages == null) {
messages = new ArrayList<>();
}
messages.add(vm);
}
public boolean hasMessages() {
return messages != null && !messages.isEmpty();
}
public List<ValidationMessage> getMessages() {
return messages;
}
}

View File

@ -98,6 +98,7 @@ public class JsonParser extends ParserBase {
return null;
Element result = new Element(type, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
result.setPath(type);
checkObject(obj, path);
result.setType(type);
parseChildren(path, obj, result, true);
@ -123,7 +124,7 @@ public class JsonParser extends ParserBase {
return parse(obj);
} else {
JsonObject obj = JsonTrackingParser.parse(source, null); // (JsonObject) new com.google.gson.JsonParser().parse(source);
// assert (map.containsKey(obj));
// assert (map.containsKey(obj));
return parse(obj);
}
}
@ -150,6 +151,7 @@ public class JsonParser extends ParserBase {
checkObject(object, path);
result.markLocation(line(object), col(object));
result.setType(name);
result.setPath(result.fhirType());
parseChildren(path, object, result, true);
result.numberChildren();
return result;
@ -215,6 +217,7 @@ public class JsonParser extends ParserBase {
private void parseChildComplex(String path, JsonObject object, Element element, Set<String> processed, Property property, String name) throws FHIRException {
processed.add(name);
String npath = path+"."+property.getName();
String fpath = element.getPath()+"."+property.getName();
JsonElement e = object.get(name);
if (property.isList() && (e instanceof JsonArray)) {
JsonArray arr = (JsonArray) e;
@ -223,14 +226,14 @@ public class JsonParser extends ParserBase {
}
int c = 0;
for (JsonElement am : arr) {
parseChildComplexInstance(npath+"["+c+"]", object, element, property, name, am);
parseChildComplexInstance(npath+"["+c+"]", fpath+"["+c+"]", object, element, property, name, am);
c++;
}
} else {
if (property.isList()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describeType(e), name, path), IssueSeverity.ERROR);
}
parseChildComplexInstance(npath, object, element, property, name, e);
parseChildComplexInstance(npath, fpath, object, element, property, name, e);
}
}
@ -246,10 +249,11 @@ public class JsonParser extends ParserBase {
return null;
}
private void parseChildComplexInstance(String npath, JsonObject object, Element element, Property property, String name, JsonElement e) throws FHIRException {
private void parseChildComplexInstance(String npath, String fpath, JsonObject object, Element element, Property property, String name, JsonElement e) throws FHIRException {
if (e instanceof JsonObject) {
JsonObject child = (JsonObject) e;
Element n = new Element(name, property).markLocation(line(child), col(child));
n.setPath(fpath);
checkObject(child, npath);
element.getChildren().add(n);
if (property.isResource())
@ -275,6 +279,7 @@ public class JsonParser extends ParserBase {
private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException {
String npath = path+"."+property.getName();
String fpath = element.getPath()+"."+property.getName();
processed.add(name);
processed.add("_"+name);
JsonElement main = object.has(name) ? object.get(name) : null;
@ -296,11 +301,11 @@ public class JsonParser extends ParserBase {
for (int i = 0; i < Math.max(arrC(arr1), arrC(arr2)); i++) {
JsonElement m = arrI(arr1, i);
JsonElement f = arrI(arr2, i);
parseChildPrimitiveInstance(element, property, name, npath, m, f);
parseChildPrimitiveInstance(element, property, name, npath, fpath, m, f);
}
}
} else {
parseChildPrimitiveInstance(element, property, name, npath, main, fork);
parseChildPrimitiveInstance(element, property, name, npath, fpath, main, fork);
}
}
}
@ -313,8 +318,7 @@ public class JsonParser extends ParserBase {
return arr == null ? 0 : arr.size();
}
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath,
JsonElement main, JsonElement fork) throws FHIRException {
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException {
if (main != null && !(main instanceof JsonPrimitive))
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(
I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR);
@ -322,6 +326,7 @@ public class JsonParser extends ParserBase {
logError(line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(fork), name, npath), IssueSeverity.ERROR);
else {
Element n = new Element(name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork));
n.setPath(fpath);
element.getChildren().add(n);
if (main != null) {
JsonPrimitive p = (JsonPrimitive) main;

View File

@ -232,6 +232,10 @@ public class Property {
return !"1".equals(definition.getMax());
}
public boolean isBaseList() {
return !"1".equals(definition.getBase().getMax());
}
public String getScopedPropertyName() {
return definition.getBase().getPath();
}

View File

@ -203,6 +203,7 @@ public class XmlParser extends ParserBase {
return null;
Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
result.setPath(element.getLocalName());
checkElement(element, path, result.getProperty());
result.markLocation(line(element), col(element));
result.setType(element.getLocalName());
@ -262,6 +263,7 @@ public class XmlParser extends ParserBase {
public Element parse(org.w3c.dom.Element base, String type) throws Exception {
StructureDefinition sd = getDefinition(0, 0, FormatUtilities.FHIR_NS, type);
Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
result.setPath(base.getLocalName());
String path = "/"+pathPrefix(base.getNamespaceURI())+base.getLocalName();
checkElement(base, path, result.getProperty());
result.setType(base.getLocalName());
@ -283,13 +285,18 @@ public class XmlParser extends ParserBase {
if (property != null) {
if ("ED.data[x]".equals(property.getDefinition().getId()) || (property.getDefinition()!=null && property.getDefinition().getBase()!=null && "ED.data[x]".equals(property.getDefinition().getBase().getPath()))) {
if ("B64".equals(node.getAttribute("representation"))) {
element.getChildren().add(new Element("dataBase64Binary", property, "base64Binary", text).markLocation(line, col));
Element n = new Element("dataBase64Binary", property, "base64Binary", text).markLocation(line, col);
n.setPath(element.getPath()+"."+property.getName());
element.getChildren().add(n);
} else {
element.getChildren().add(new Element("dataString", property, "string", text).markLocation(line, col));
Element n = new Element("dataString", property, "string", text).markLocation(line, col);
n.setPath(element.getPath()+"."+property.getName());
element.getChildren().add(n);
}
} else {
element.getChildren().add(
new Element(property.getName(), property, property.getType(), text).markLocation(line, col));
Element n = new Element(property.getName(), property, property.getType(), text).markLocation(line, col);
n.setPath(element.getPath()+"."+property.getName());
element.getChildren().add(n);
}
}
else {
@ -325,8 +332,11 @@ public class XmlParser extends ParserBase {
av = convertForDateFormatFromExternal(ToolingExtensions.readStringExtension(property.getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat"), av);
if (property.getName().equals("value") && element.isPrimitive())
element.setValue(av);
else
element.getChildren().add(new Element(property.getName(), property, property.getType(), av).markLocation(line, col));
else {
Element n = new Element(property.getName(), property, property.getType(), av).markLocation(line, col);
n.setPath(element.getPath()+"."+property.getName());
element.getChildren().add(n);
}
} else {
boolean ok = false;
if (FormatUtilities.FHIR_NS.equals(node.getNamespaceURI())) {
@ -342,21 +352,36 @@ public class XmlParser extends ParserBase {
}
}
String lastName = null;
int repeatCount = 0;
Node child = node.getFirstChild();
while (child != null) {
if (child.getNodeType() == Node.ELEMENT_NODE) {
Property property = getElementProp(properties, child.getLocalName(), child.getNamespaceURI());
if (property != null) {
if (property.getName().equals(lastName)) {
repeatCount++;
} else {
lastName = property.getName();
repeatCount = 0;
}
if (!property.isChoice() && "xhtml".equals(property.getType())) {
XhtmlNode xhtml;
if (property.getDefinition().hasRepresentation(PropertyRepresentation.CDATEXT))
xhtml = new CDANarrativeFormat().convert((org.w3c.dom.Element) child);
else
xhtml = new XhtmlParser().setValidatorMode(true).parseHtmlNode((org.w3c.dom.Element) child);
element.getChildren().add(new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child), col(child)));
Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child), col(child));
n.setPath(element.getPath()+"."+property.getName());
element.getChildren().add(n);
} else {
String npath = path+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName();
Element n = new Element(child.getLocalName(), property).markLocation(line(child), col(child));
if (property.isList()) {
n.setPath(element.getPath()+"."+property.getName()+"["+repeatCount+"]");
} else {
n.setPath(element.getPath()+"."+property.getName());
}
checkElement((org.w3c.dom.Element) child, npath, n.getProperty());
boolean ok = true;
if (property.isChoice()) {

View File

@ -132,7 +132,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
li.tx(opt.getValue().primitiveValue());
} else if (opt.getValue() instanceof Coding) {
Coding c = (Coding) opt.getValue();
String link = context.getWorker().getLinkForUrl(context.getSpecificationLink(), c.getSystem());
String link = c.hasSystem() ? context.getWorker().getLinkForUrl(context.getSpecificationLink(), c.getSystem()) : null;
if (link == null) {
li.tx(c.getSystem()+"#"+c.getCode());
} else {

View File

@ -583,6 +583,7 @@ public class I18nConstants {
public static final String VALIDATION_VAL_PROFILE_NOTSLICE = "Validation_VAL_Profile_NotSlice";
public static final String VALIDATION_VAL_PROFILE_NOTYPE = "Validation_VAL_Profile_NoType";
public static final String VALIDATION_VAL_PROFILE_OUTOFORDER = "Validation_VAL_Profile_OutOfOrder";
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_BASE = "VALIDATION_VAL_PROFILE_SIGNPOST_BASE";
public static final String VALIDATION_VAL_PROFILE_SIGNPOST = "VALIDATION_VAL_PROFILE_SIGNPOST";
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = "VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL";
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_META = "VALIDATION_VAL_PROFILE_SIGNPOST_META";

View File

@ -790,8 +790,9 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
return signpost;
}
public void setSignpost(boolean signpost) {
public ValidationMessage setSignpost(boolean signpost) {
this.signpost = signpost;
return this;
}

View File

@ -524,8 +524,9 @@ TYPE_CHECKS_PATTERN_CC_US = The pattern [system {0}, code {1}, display ''{2}'' a
TYPE_CHECKS_FIXED_CC = The pattern [system {0}, code {1}, and display ''{2}''] defined in the profile {3} not found. Issues: {4}
TYPE_CHECKS_FIXED_CC_US = The pattern [system {0}, code {1}, display ''{2}'' and userSelected {5}] defined in the profile {3} not found. Issues: {4}
VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN = Global Profile reference ''{0}'' from IG {1} could not be resolved, so has not been checked
VALIDATION_VAL_PROFILE_SIGNPOST_BASE = Validate resource against profile
VALIDATION_VAL_PROFILE_SIGNPOST = Validate resource against profile {0}
VALIDATION_VAL_PROFILE_SIGNPOST_META = Validate resource against profile {0} - listed in meta
VALIDATION_VAL_PROFILE_SIGNPOST_META = Validate resource against profile {0} (per meta)
VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM = Validate resource against profile {0} - provided as bundle param
VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = Validate resource against profile {0} - a global profile in {1}
ERROR_GENERATING_SNAPSHOT = Error generating Snapshot: {0} (this usually arises from a problem in the differential)
@ -618,7 +619,7 @@ SD_NESTED_MUST_SUPPORT_SNAPSHOT = The element {0} has types/profiles/targets tha
Unable_to_connect_to_terminology_server = Unable to connect to terminology server. Error = {0}
SD_ED_TYPE_PROFILE_UNKNOWN = Unable to resolve profile {0}
SD_ED_TYPE_PROFILE_NOTYPE = Found profile {0}, but unable to determine the type it applies to
SD_ED_TYPE_PROFILE_WRONG = Extension {0} is for type {1}, but the {3} element has type {2}
SD_ED_TYPE_PROFILE_WRONG = Profile {0} is for type {1}, but the {3} element has type {2}
SD_ED_TYPE_PROFILE_WRONG_TARGET = Profile {0} is for type {1}, which is not a {4} (which is required because the {3} element has type {2})
SD_ED_TYPE_NO_TARGET_PROFILE = Type {0} does not allow for target Profiles
TERMINOLOGY_TX_NOSVC_BOUND_REQ = Could not confirm that the codes provided are from the required value set {0} because there is no terminology service

View File

@ -618,7 +618,7 @@ SD_NESTED_MUST_SUPPORT_SNAPSHOT = Het element {0} heeft typen/profielen/targets
Unable_to_connect_to_terminology_server = Kan niet verbinden met terminologieserver. Fout = {0}
SD_ED_TYPE_PROFILE_UNKNOWN = Kan profiel {0} niet vinden
SD_ED_TYPE_PROFILE_NOTYPE = Profiel {0} gevonden, maar kan niet bepalen op welke type deze van toepassing is
SD_ED_TYPE_PROFILE_WRONG = Extensie {0} is voor type {1}, met het {3} element heeft type {2}
SD_ED_TYPE_PROFILE_WRONG = Profiel {0} is voor type {1}, met het {3} element heeft type {2}
SD_ED_TYPE_PROFILE_WRONG_TARGET = Profiel {0} is voor type {1}, wat geen {4} is (welke wordt vereist om het {3} element type {2} heeft)
SD_ED_TYPE_NO_TARGET_PROFILE = Type {0} laat geen target Profielen toe
TERMINOLOGY_TX_NOSVC_BOUND_REQ = Kan niet bevestigen dat de gevonden codes bestaan in de verplichte waardelijst {0} omdat er geen terminologieservice is

View File

@ -284,12 +284,9 @@ public class BaseValidator {
return thePass;
}
protected boolean signpost(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass) {
protected ValidationMessage signpost(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true);
}
return thePass;
return addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true);
}
protected boolean txHint(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {

View File

@ -3270,8 +3270,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rr.setResource(nstack.getElement());
rr.setFocus(nstack.getElement());
rr.setExternal(false);
rr.setStack(nstack.push(nstack.getElement(), -1, nstack.getElement().getProperty().getDefinition(), nstack.getElement().getProperty().getDefinition()));
rr.getStack().qualifyPath(".ofType("+nstack.getElement().fhirType()+")");
rr.setStack(nstack);
// rr.getStack().qualifyPath(".ofType("+nstack.getElement().fhirType()+")");
System.out.println("-->"+nstack.getLiteralPath());
return rr;
}
if (nstack.getElement().getSpecial() == SpecialElement.CONTAINED) {
@ -3951,7 +3952,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// checkSpecials = we're only going to run these tests if we are actually validating this content (as opposed to we looked it up)
private void start(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack) throws FHIRException {
checkLang(resource, stack);
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST, defn.getUrl());
if (crumbTrails) {
element.addMessage(signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST, defn.getUrl()));
}
if (BUNDLE.equals(element.fhirType())) {
resolveBundleReferences(element, new ArrayList<Element>());
@ -3996,7 +3999,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
if (sd != null) {
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_META, sd.getUrl());
if (crumbTrails) {
element.addMessage(signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_META, sd.getUrl()));
}
stack.resetIds();
startInner(hostContext, errors, resource, element, sd, stack, false);
}
@ -4011,7 +4016,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (rt.equals(gl.getType())) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, gl.getProfile());
if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), sd != null, I18nConstants.VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN, gl.getProfile())) {
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL, sd.getUrl(), ig.getUrl());
if (crumbTrails) {
element.addMessage(signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL, sd.getUrl(), ig.getUrl()));
}
stack.resetIds();
startInner(hostContext, errors, resource, element, sd, stack, false);
}
@ -4517,13 +4524,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
type = null;
}
}
NodeStack localStack = stack.push(ei.getElement(), ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
NodeStack localStack = stack.push(ei.getElement(), "*".equals(ei.getDefinition().getBase().getMax()) && ei.count == -1 ? 0 : ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
// if (debug) {
// System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl());
// }
String localStackLiterapPath = localStack.getLiteralPath();
String localStackLiteralPath = localStack.getLiteralPath();
String eiPath = ei.getPath();
assert (eiPath.equals(localStackLiterapPath)) : "ei.path: " + ei.getPath() + " - localStack.getLiteralPath: " + localStackLiterapPath;
if (!eiPath.equals(localStackLiteralPath)) {
assert (eiPath.equals(localStackLiteralPath)) : "ei.path: " + ei.getPath() + " - localStack.getLiteralPath: " + localStackLiteralPath;
}
boolean thisIsCodeableConcept = false;
String thisExtension = null;
boolean checkDisplay = true;

View File

@ -112,7 +112,9 @@ public class BundleValidator extends BaseValidator{
} else {
Element res = entry.getNamedChild(RESOURCE);
NodeStack rstack = estack.push(res, -1, null, null);
signpost(errors, IssueType.INFORMATIONAL, res.line(), res.col(), stack.getLiteralPath(), !validator.isCrumbTrails(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM, defn.getUrl());
if (validator.isCrumbTrails()) {
res.addMessage(signpost(errors, IssueType.INFORMATIONAL, res.line(), res.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM, defn.getUrl()));
}
stack.resetIds();
validator.startInner(hostContext, errors, res, res, defn, rstack, false);
}

View File

@ -247,8 +247,7 @@ public class StructureDefinitionValidator extends BaseValidator {
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd);
if (t == null) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
throw new Error("What to do about this?");
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
} else {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path);
}
@ -260,8 +259,7 @@ public class StructureDefinitionValidator extends BaseValidator {
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd);
if (t == null) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
throw new Error("What to do about this?");
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
} else {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path);
}
@ -317,7 +315,7 @@ public class StructureDefinitionValidator extends BaseValidator {
if (t == null) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
} else if (!VersionUtilities.isR5Ver(context.getVersion())) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()) || "Resource".equals(t), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource");
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()) || "Resource".equals(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource");
} else {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource");
}

View File

@ -71,9 +71,12 @@ public class ChildIterator {
String na = cursor >= parent.getChildren().size() - 1 ? "--" : parent.getChildren().get(cursor + 1).getName();
if (name().equals(nb) || name().equals(na)) {
return lastCount;
} else
} else if (element().isBaseList()) {
return 0;
} else {
return -1;
}
}
public boolean next() {
if (cursor == -1) {

View File

@ -34,7 +34,7 @@ public class NodeStack {
this.context = context;
ids = new HashMap<>();
this.element = element;
literalPath = element.getName();
literalPath = element.getPath();
workingLang = validationLanguage;
if (!element.getName().equals(element.fhirType())) {
logicalPaths = new ArrayList<>();