Merge pull request #544 from hapifhir/gg-202106-validator-paths
Gg 202106 validator paths
This commit is contained in:
commit
e022acb569
|
@ -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,10 +267,7 @@ 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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 ---------------------------------------------------------
|
||||
|
||||
|
@ -779,10 +800,14 @@ 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(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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -3,19 +3,19 @@ package org.hl7.fhir.r5.elementmodel;
|
|||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
|
@ -26,7 +26,7 @@ package org.hl7.fhir.r5.elementmodel;
|
|||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
@ -72,32 +72,33 @@ import com.google.gson.JsonPrimitive;
|
|||
|
||||
public class JsonParser extends ParserBase {
|
||||
|
||||
private JsonCreator json;
|
||||
private Map<JsonElement, LocationData> map;
|
||||
private boolean allowComments;
|
||||
private JsonCreator json;
|
||||
private Map<JsonElement, LocationData> map;
|
||||
private boolean allowComments;
|
||||
|
||||
private ProfileUtilities profileUtilities;
|
||||
|
||||
public JsonParser(IWorkerContext context, ProfileUtilities utilities) {
|
||||
super(context);
|
||||
|
||||
|
||||
this.profileUtilities = utilities;
|
||||
}
|
||||
|
||||
|
||||
public JsonParser(IWorkerContext context) {
|
||||
super(context);
|
||||
|
||||
|
||||
this.profileUtilities = new ProfileUtilities(this.context, null, null, new FHIRPathEngine(context));
|
||||
}
|
||||
|
||||
public Element parse(String source, String type) throws Exception {
|
||||
JsonObject obj = (JsonObject) new com.google.gson.JsonParser().parse(source);
|
||||
public Element parse(String source, String type) throws Exception {
|
||||
JsonObject obj = (JsonObject) new com.google.gson.JsonParser().parse(source);
|
||||
String path = "/"+type;
|
||||
StructureDefinition sd = getDefinition(-1, -1, type);
|
||||
if (sd == null)
|
||||
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);
|
||||
|
@ -106,138 +107,140 @@ public class JsonParser extends ParserBase {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Element parse(InputStream stream) throws IOException, FHIRException {
|
||||
// if we're parsing at this point, then we're going to use the custom parser
|
||||
map = new IdentityHashMap<JsonElement, LocationData>();
|
||||
String source = TextFile.streamToString(stream);
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
JsonObject obj = null;
|
||||
@Override
|
||||
public Element parse(InputStream stream) throws IOException, FHIRException {
|
||||
// if we're parsing at this point, then we're going to use the custom parser
|
||||
map = new IdentityHashMap<JsonElement, LocationData>();
|
||||
String source = TextFile.streamToString(stream);
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
JsonObject obj = null;
|
||||
try {
|
||||
obj = JsonTrackingParser.parse(source, map, false, allowComments);
|
||||
obj = JsonTrackingParser.parse(source, map, false, allowComments);
|
||||
} catch (Exception e) {
|
||||
logError(-1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
||||
return null;
|
||||
logError(-1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
||||
return null;
|
||||
}
|
||||
assert (map.containsKey(obj));
|
||||
return parse(obj);
|
||||
} else {
|
||||
JsonObject obj = JsonTrackingParser.parse(source, null); // (JsonObject) new com.google.gson.JsonParser().parse(source);
|
||||
// assert (map.containsKey(obj));
|
||||
return parse(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public Element parse(JsonObject object, Map<JsonElement, LocationData> map) throws FHIRException {
|
||||
this.map = map;
|
||||
return parse(object);
|
||||
}
|
||||
|
||||
public Element parse(JsonObject object) throws FHIRException {
|
||||
JsonElement rt = object.get("resourceType");
|
||||
if (rt == null) {
|
||||
logError(line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
||||
return null;
|
||||
} else {
|
||||
String name = rt.getAsString();
|
||||
String path = name;
|
||||
|
||||
StructureDefinition sd = getDefinition(line(object), col(object), name);
|
||||
if (sd == null)
|
||||
return null;
|
||||
|
||||
Element result = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
|
||||
checkObject(object, path);
|
||||
result.markLocation(line(object), col(object));
|
||||
result.setType(name);
|
||||
parseChildren(path, object, result, true);
|
||||
result.numberChildren();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkObject(JsonObject object, String path) throws FHIRFormatError {
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
boolean found = false;
|
||||
for (Entry<String, JsonElement> e : object.entrySet()) {
|
||||
// if (!e.getKey().equals("fhir_comments")) {
|
||||
found = true;
|
||||
break;
|
||||
// }
|
||||
}
|
||||
if (!found)
|
||||
logError(line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseChildren(String path, JsonObject object, Element element, boolean hasResourceType) throws FHIRException {
|
||||
reapComments(object, element);
|
||||
List<Property> properties = element.getProperty().getChildProperties(element.getName(), null);
|
||||
Set<String> processed = new HashSet<String>();
|
||||
if (hasResourceType)
|
||||
processed.add("resourceType");
|
||||
|
||||
// note that we do not trouble ourselves to maintain the wire format order here - we don't even know what it was anyway
|
||||
// first pass: process the properties
|
||||
for (Property property : properties) {
|
||||
parseChildItem(path, object, element, processed, property);
|
||||
}
|
||||
|
||||
// second pass: check for things not processed
|
||||
if (policy != ValidationPolicy.NONE) {
|
||||
for (Entry<String, JsonElement> e : object.entrySet()) {
|
||||
if (!processed.contains(e.getKey())) {
|
||||
logError(line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) {
|
||||
if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) {
|
||||
for (TypeRefComponent type : property.getDefinition().getType()) {
|
||||
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
|
||||
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) {
|
||||
parseChildComplex(path, object, context, processed, property, eName);
|
||||
break;
|
||||
} else if (isPrimitive(type.getWorkingCode()) && (object.has(eName) || object.has("_"+eName))) {
|
||||
parseChildPrimitive(object, context, processed, property, path, eName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (property.isPrimitive(property.getType(null))) {
|
||||
parseChildPrimitive(object, context, processed, property, path, property.getName());
|
||||
} else if (object.has(property.getName())) {
|
||||
parseChildComplex(path, object, context, processed, property, property.getName());
|
||||
assert (map.containsKey(obj));
|
||||
return parse(obj);
|
||||
} else {
|
||||
JsonObject obj = JsonTrackingParser.parse(source, null); // (JsonObject) new com.google.gson.JsonParser().parse(source);
|
||||
// assert (map.containsKey(obj));
|
||||
return parse(obj);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
JsonElement e = object.get(name);
|
||||
if (property.isList() && (e instanceof JsonArray)) {
|
||||
JsonArray arr = (JsonArray) e;
|
||||
if (arr.size() == 0) {
|
||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
|
||||
}
|
||||
int c = 0;
|
||||
for (JsonElement am : arr) {
|
||||
parseChildComplexInstance(npath+"["+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);
|
||||
}
|
||||
}
|
||||
public Element parse(JsonObject object, Map<JsonElement, LocationData> map) throws FHIRException {
|
||||
this.map = map;
|
||||
return parse(object);
|
||||
}
|
||||
|
||||
private String describeType(JsonElement e) {
|
||||
if (e.isJsonArray())
|
||||
return "an Array";
|
||||
if (e.isJsonObject())
|
||||
public Element parse(JsonObject object) throws FHIRException {
|
||||
JsonElement rt = object.get("resourceType");
|
||||
if (rt == null) {
|
||||
logError(line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
||||
return null;
|
||||
} else {
|
||||
String name = rt.getAsString();
|
||||
String path = name;
|
||||
|
||||
StructureDefinition sd = getDefinition(line(object), col(object), name);
|
||||
if (sd == null)
|
||||
return null;
|
||||
|
||||
Element result = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkObject(JsonObject object, String path) throws FHIRFormatError {
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
boolean found = false;
|
||||
for (Entry<String, JsonElement> e : object.entrySet()) {
|
||||
// if (!e.getKey().equals("fhir_comments")) {
|
||||
found = true;
|
||||
break;
|
||||
// }
|
||||
}
|
||||
if (!found)
|
||||
logError(line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseChildren(String path, JsonObject object, Element element, boolean hasResourceType) throws FHIRException {
|
||||
reapComments(object, element);
|
||||
List<Property> properties = element.getProperty().getChildProperties(element.getName(), null);
|
||||
Set<String> processed = new HashSet<String>();
|
||||
if (hasResourceType)
|
||||
processed.add("resourceType");
|
||||
|
||||
// note that we do not trouble ourselves to maintain the wire format order here - we don't even know what it was anyway
|
||||
// first pass: process the properties
|
||||
for (Property property : properties) {
|
||||
parseChildItem(path, object, element, processed, property);
|
||||
}
|
||||
|
||||
// second pass: check for things not processed
|
||||
if (policy != ValidationPolicy.NONE) {
|
||||
for (Entry<String, JsonElement> e : object.entrySet()) {
|
||||
if (!processed.contains(e.getKey())) {
|
||||
logError(line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) {
|
||||
if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) {
|
||||
for (TypeRefComponent type : property.getDefinition().getType()) {
|
||||
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
|
||||
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) {
|
||||
parseChildComplex(path, object, context, processed, property, eName);
|
||||
break;
|
||||
} else if (isPrimitive(type.getWorkingCode()) && (object.has(eName) || object.has("_"+eName))) {
|
||||
parseChildPrimitive(object, context, processed, property, path, eName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (property.isPrimitive(property.getType(null))) {
|
||||
parseChildPrimitive(object, context, processed, property, path, property.getName());
|
||||
} else if (object.has(property.getName())) {
|
||||
parseChildComplex(path, object, context, processed, property, property.getName());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (arr.size() == 0) {
|
||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
|
||||
}
|
||||
int c = 0;
|
||||
for (JsonElement am : arr) {
|
||||
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, fpath, object, element, property, name, e);
|
||||
}
|
||||
}
|
||||
|
||||
private String describeType(JsonElement e) {
|
||||
if (e.isJsonArray())
|
||||
return "an Array";
|
||||
if (e.isJsonObject())
|
||||
return "an Object";
|
||||
if (e.isJsonPrimitive())
|
||||
return "a primitive property";
|
||||
|
@ -246,24 +249,25 @@ public class JsonParser extends ParserBase {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void parseChildComplexInstance(String npath, 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));
|
||||
checkObject(child, npath);
|
||||
element.getChildren().add(n);
|
||||
if (property.isResource())
|
||||
parseResource(npath, child, n, property);
|
||||
else
|
||||
parseChildren(npath, child, n, false);
|
||||
} else
|
||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR);
|
||||
}
|
||||
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())
|
||||
parseResource(npath, child, n, property);
|
||||
else
|
||||
parseChildren(npath, child, n, false);
|
||||
} else
|
||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR);
|
||||
}
|
||||
|
||||
private String describe(JsonElement e) {
|
||||
if (e instanceof JsonArray) {
|
||||
return "an array";
|
||||
}
|
||||
private String describe(JsonElement e) {
|
||||
if (e instanceof JsonArray) {
|
||||
return "an array";
|
||||
}
|
||||
if (e instanceof JsonObject) {
|
||||
return "an object";
|
||||
}
|
||||
|
@ -274,20 +278,21 @@ 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();
|
||||
processed.add(name);
|
||||
processed.add("_"+name);
|
||||
JsonElement main = object.has(name) ? object.get(name) : null;
|
||||
JsonElement fork = object.has("_"+name) ? object.get("_"+name) : null;
|
||||
if (main != null || fork != null) {
|
||||
if (property.isList()) {
|
||||
boolean ok = true;
|
||||
if (!(main == null || main instanceof JsonArray)) {
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
|
||||
ok = false;
|
||||
}
|
||||
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;
|
||||
JsonElement fork = object.has("_"+name) ? object.get("_"+name) : null;
|
||||
if (main != null || fork != null) {
|
||||
if (property.isList()) {
|
||||
boolean ok = true;
|
||||
if (!(main == null || main instanceof JsonArray)) {
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
|
||||
ok = false;
|
||||
}
|
||||
if (!(fork == null || fork instanceof JsonArray)) {
|
||||
logError(line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
|
||||
logError(line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
|
||||
ok = false;
|
||||
}
|
||||
if (ok) {
|
||||
|
@ -296,158 +301,158 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parseChildPrimitiveInstance(element, property, name, npath, fpath, main, fork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JsonElement arrI(JsonArray arr, int i) {
|
||||
return arr == null || i >= arr.size() || arr.get(i) instanceof JsonNull ? null : arr.get(i);
|
||||
}
|
||||
private JsonElement arrI(JsonArray arr, int i) {
|
||||
return arr == null || i >= arr.size() || arr.get(i) instanceof JsonNull ? null : arr.get(i);
|
||||
}
|
||||
|
||||
private int arrC(JsonArray arr) {
|
||||
return arr == null ? 0 : arr.size();
|
||||
}
|
||||
private int arrC(JsonArray arr) {
|
||||
return arr == null ? 0 : arr.size();
|
||||
}
|
||||
|
||||
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath,
|
||||
JsonElement main, JsonElement fork) throws FHIRException {
|
||||
if (main != null && !(main instanceof JsonPrimitive))
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(
|
||||
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);
|
||||
else if (fork != null && !(fork instanceof JsonObject))
|
||||
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));
|
||||
element.getChildren().add(n);
|
||||
if (main != null) {
|
||||
JsonPrimitive p = (JsonPrimitive) main;
|
||||
if (p.isNumber() && p.getAsNumber() instanceof JsonTrackingParser.PresentedBigDecimal) {
|
||||
String rawValue = ((JsonTrackingParser.PresentedBigDecimal) p.getAsNumber()).getPresentation();
|
||||
n.setValue(rawValue);
|
||||
} else {
|
||||
n.setValue(p.getAsString());
|
||||
else if (fork != null && !(fork instanceof JsonObject))
|
||||
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;
|
||||
if (p.isNumber() && p.getAsNumber() instanceof JsonTrackingParser.PresentedBigDecimal) {
|
||||
String rawValue = ((JsonTrackingParser.PresentedBigDecimal) p.getAsNumber()).getPresentation();
|
||||
n.setValue(rawValue);
|
||||
} else {
|
||||
n.setValue(p.getAsString());
|
||||
}
|
||||
if (!n.getProperty().isChoice() && n.getType().equals("xhtml")) {
|
||||
try {
|
||||
n.setXhtml(new XhtmlParser().setValidatorMode(policy == ValidationPolicy.EVERYTHING).parse(n.getValue(), null).getDocumentElement());
|
||||
} catch (Exception e) {
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR);
|
||||
}
|
||||
if (!n.getProperty().isChoice() && n.getType().equals("xhtml")) {
|
||||
try {
|
||||
n.setXhtml(new XhtmlParser().setValidatorMode(policy == ValidationPolicy.EVERYTHING).parse(n.getValue(), null).getDocumentElement());
|
||||
} catch (Exception e) {
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
// now we cross-check the primitive format against the stated type
|
||||
if (Utilities.existsInList(n.getType(), "boolean")) {
|
||||
if (!p.isBoolean())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR);
|
||||
} else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) {
|
||||
if (!p.isNumber())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
|
||||
} else if (!p.isString())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
if (fork != null) {
|
||||
JsonObject child = (JsonObject) fork;
|
||||
checkObject(child, npath);
|
||||
parseChildren(npath, child, n, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
// now we cross-check the primitive format against the stated type
|
||||
if (Utilities.existsInList(n.getType(), "boolean")) {
|
||||
if (!p.isBoolean())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR);
|
||||
} else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) {
|
||||
if (!p.isNumber())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
|
||||
} else if (!p.isString())
|
||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
if (fork != null) {
|
||||
JsonObject child = (JsonObject) fork;
|
||||
checkObject(child, npath);
|
||||
parseChildren(npath, child, n, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException {
|
||||
JsonElement rt = res.get("resourceType");
|
||||
if (rt == null) {
|
||||
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
||||
} else {
|
||||
String name = rt.getAsString();
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs()));
|
||||
if (sd == null) {
|
||||
private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException {
|
||||
JsonElement rt = res.get("resourceType");
|
||||
if (rt == null) {
|
||||
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
||||
} else {
|
||||
String name = rt.getAsString();
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs()));
|
||||
if (sd == null) {
|
||||
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL);
|
||||
} else {
|
||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||
parent.setType(name);
|
||||
parseChildren(npath, res, parent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||
parent.setType(name);
|
||||
parseChildren(npath, res, parent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reapComments(JsonObject object, Element context) {
|
||||
if (object.has("fhir_comments")) {
|
||||
JsonArray arr = object.getAsJsonArray("fhir_comments");
|
||||
for (JsonElement e : arr) {
|
||||
context.getComments().add(e.getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
private void reapComments(JsonObject object, Element context) {
|
||||
if (object.has("fhir_comments")) {
|
||||
JsonArray arr = object.getAsJsonArray("fhir_comments");
|
||||
for (JsonElement e : arr) {
|
||||
context.getComments().add(e.getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int line(JsonElement e) {
|
||||
if (map == null|| !map.containsKey(e))
|
||||
return -1;
|
||||
else
|
||||
return map.get(e).getLine();
|
||||
}
|
||||
private int line(JsonElement e) {
|
||||
if (map == null|| !map.containsKey(e))
|
||||
return -1;
|
||||
else
|
||||
return map.get(e).getLine();
|
||||
}
|
||||
|
||||
private int col(JsonElement e) {
|
||||
if (map == null|| !map.containsKey(e))
|
||||
return -1;
|
||||
else
|
||||
return map.get(e).getCol();
|
||||
}
|
||||
private int col(JsonElement e) {
|
||||
if (map == null|| !map.containsKey(e))
|
||||
return -1;
|
||||
else
|
||||
return map.get(e).getCol();
|
||||
}
|
||||
|
||||
|
||||
protected void prop(String name, String value, String link) throws IOException {
|
||||
protected void prop(String name, String value, String link) throws IOException {
|
||||
json.link(link);
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.value(value);
|
||||
}
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.value(value);
|
||||
}
|
||||
|
||||
protected void open(String name, String link) throws IOException {
|
||||
json.link(link);
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.beginObject();
|
||||
}
|
||||
|
||||
protected void close() throws IOException {
|
||||
json.endObject();
|
||||
}
|
||||
|
||||
protected void openArray(String name, String link) throws IOException {
|
||||
protected void open(String name, String link) throws IOException {
|
||||
json.link(link);
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.beginArray();
|
||||
}
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.beginObject();
|
||||
}
|
||||
|
||||
protected void closeArray() throws IOException {
|
||||
json.endArray();
|
||||
}
|
||||
protected void close() throws IOException {
|
||||
json.endObject();
|
||||
}
|
||||
|
||||
protected void openArray(String name, String link) throws IOException {
|
||||
json.link(link);
|
||||
if (name != null)
|
||||
json.name(name);
|
||||
json.beginArray();
|
||||
}
|
||||
|
||||
protected void closeArray() throws IOException {
|
||||
json.endArray();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void compose(Element e, OutputStream stream, OutputStyle style, String identity) throws FHIRException, IOException {
|
||||
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
|
||||
if (style == OutputStyle.CANONICAL)
|
||||
json = new JsonCreatorCanonical(osw);
|
||||
else
|
||||
json = new JsonCreatorGson(osw);
|
||||
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
|
||||
json.beginObject();
|
||||
prop("resourceType", e.getType(), null);
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : e.getChildren()) {
|
||||
compose(e.getName(), e, done, child);
|
||||
}
|
||||
json.endObject();
|
||||
json.finish();
|
||||
osw.flush();
|
||||
}
|
||||
@Override
|
||||
public void compose(Element e, OutputStream stream, OutputStyle style, String identity) throws FHIRException, IOException {
|
||||
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
|
||||
if (style == OutputStyle.CANONICAL)
|
||||
json = new JsonCreatorCanonical(osw);
|
||||
else
|
||||
json = new JsonCreatorGson(osw);
|
||||
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
|
||||
json.beginObject();
|
||||
prop("resourceType", e.getType(), null);
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : e.getChildren()) {
|
||||
compose(e.getName(), e, done, child);
|
||||
}
|
||||
json.endObject();
|
||||
json.finish();
|
||||
osw.flush();
|
||||
}
|
||||
|
||||
public void compose(Element e, JsonCreator json) throws Exception {
|
||||
this.json = json;
|
||||
|
@ -462,104 +467,104 @@ public class JsonParser extends ParserBase {
|
|||
json.finish();
|
||||
}
|
||||
|
||||
private void compose(String path, Element e, Set<String> done, Element child) throws IOException {
|
||||
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
|
||||
if (!isList) {// for specials, ignore the cardinality of the stated type
|
||||
compose(path, child);
|
||||
} else if (!done.contains(child.getName())) {
|
||||
done.add(child.getName());
|
||||
List<Element> list = e.getChildrenByName(child.getName());
|
||||
composeList(path, list);
|
||||
}
|
||||
}
|
||||
private void compose(String path, Element e, Set<String> done, Element child) throws IOException {
|
||||
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
|
||||
if (!isList) {// for specials, ignore the cardinality of the stated type
|
||||
compose(path, child);
|
||||
} else if (!done.contains(child.getName())) {
|
||||
done.add(child.getName());
|
||||
List<Element> list = e.getChildrenByName(child.getName());
|
||||
composeList(path, list);
|
||||
}
|
||||
}
|
||||
|
||||
private void composeList(String path, List<Element> list) throws IOException {
|
||||
// there will be at least one element
|
||||
String name = list.get(0).getName();
|
||||
boolean complex = true;
|
||||
if (list.get(0).isPrimitive()) {
|
||||
boolean prim = false;
|
||||
complex = false;
|
||||
for (Element item : list) {
|
||||
if (item.hasValue())
|
||||
prim = true;
|
||||
if (item.hasChildren())
|
||||
complex = true;
|
||||
}
|
||||
if (prim) {
|
||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
for (Element item : list) {
|
||||
if (item.hasValue())
|
||||
primitiveValue(null, item);
|
||||
else
|
||||
json.nullValue();
|
||||
}
|
||||
closeArray();
|
||||
}
|
||||
name = "_"+name;
|
||||
}
|
||||
if (complex) {
|
||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
for (Element item : list) {
|
||||
if (item.hasChildren()) {
|
||||
open(null,null);
|
||||
if (item.getProperty().isResource()) {
|
||||
prop("resourceType", item.getType(), linkResolver == null ? null : linkResolver.resolveType(item.getType()));
|
||||
}
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : item.getChildren()) {
|
||||
compose(path+"."+name+"[]", item, done, child);
|
||||
}
|
||||
close();
|
||||
} else
|
||||
json.nullValue();
|
||||
}
|
||||
closeArray();
|
||||
}
|
||||
}
|
||||
private void composeList(String path, List<Element> list) throws IOException {
|
||||
// there will be at least one element
|
||||
String name = list.get(0).getName();
|
||||
boolean complex = true;
|
||||
if (list.get(0).isPrimitive()) {
|
||||
boolean prim = false;
|
||||
complex = false;
|
||||
for (Element item : list) {
|
||||
if (item.hasValue())
|
||||
prim = true;
|
||||
if (item.hasChildren())
|
||||
complex = true;
|
||||
}
|
||||
if (prim) {
|
||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
for (Element item : list) {
|
||||
if (item.hasValue())
|
||||
primitiveValue(null, item);
|
||||
else
|
||||
json.nullValue();
|
||||
}
|
||||
closeArray();
|
||||
}
|
||||
name = "_"+name;
|
||||
}
|
||||
if (complex) {
|
||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||
for (Element item : list) {
|
||||
if (item.hasChildren()) {
|
||||
open(null,null);
|
||||
if (item.getProperty().isResource()) {
|
||||
prop("resourceType", item.getType(), linkResolver == null ? null : linkResolver.resolveType(item.getType()));
|
||||
}
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : item.getChildren()) {
|
||||
compose(path+"."+name+"[]", item, done, child);
|
||||
}
|
||||
close();
|
||||
} else
|
||||
json.nullValue();
|
||||
}
|
||||
closeArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void primitiveValue(String name, Element item) throws IOException {
|
||||
if (name != null) {
|
||||
if (linkResolver != null)
|
||||
json.link(linkResolver.resolveProperty(item.getProperty()));
|
||||
json.name(name);
|
||||
}
|
||||
String type = item.getType();
|
||||
if (Utilities.existsInList(type, "boolean"))
|
||||
json.value(item.getValue().trim().equals("true") ? new Boolean(true) : new Boolean(false));
|
||||
else if (Utilities.existsInList(type, "integer", "unsignedInt", "positiveInt"))
|
||||
json.value(new Integer(item.getValue()));
|
||||
else if (Utilities.existsInList(type, "decimal"))
|
||||
try {
|
||||
json.value(new BigDecimal(item.getValue()));
|
||||
} catch (Exception e) {
|
||||
throw new NumberFormatException(context.formatMessage(I18nConstants.ERROR_WRITING_NUMBER__TO_JSON, item.getValue()));
|
||||
}
|
||||
else
|
||||
json.value(item.getValue());
|
||||
}
|
||||
private void primitiveValue(String name, Element item) throws IOException {
|
||||
if (name != null) {
|
||||
if (linkResolver != null)
|
||||
json.link(linkResolver.resolveProperty(item.getProperty()));
|
||||
json.name(name);
|
||||
}
|
||||
String type = item.getType();
|
||||
if (Utilities.existsInList(type, "boolean"))
|
||||
json.value(item.getValue().trim().equals("true") ? new Boolean(true) : new Boolean(false));
|
||||
else if (Utilities.existsInList(type, "integer", "unsignedInt", "positiveInt"))
|
||||
json.value(new Integer(item.getValue()));
|
||||
else if (Utilities.existsInList(type, "decimal"))
|
||||
try {
|
||||
json.value(new BigDecimal(item.getValue()));
|
||||
} catch (Exception e) {
|
||||
throw new NumberFormatException(context.formatMessage(I18nConstants.ERROR_WRITING_NUMBER__TO_JSON, item.getValue()));
|
||||
}
|
||||
else
|
||||
json.value(item.getValue());
|
||||
}
|
||||
|
||||
private void compose(String path, Element element) throws IOException {
|
||||
String name = element.getName();
|
||||
if (element.isPrimitive() || isPrimitive(element.getType())) {
|
||||
if (element.hasValue())
|
||||
primitiveValue(name, element);
|
||||
name = "_"+name;
|
||||
if (element.getType().equals("xhtml"))
|
||||
json.anchor("end-xhtml");
|
||||
}
|
||||
if (element.hasChildren()) {
|
||||
open(name, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
|
||||
if (element.getProperty().isResource()) {
|
||||
prop("resourceType", element.getType(), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
|
||||
}
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : element.getChildren()) {
|
||||
compose(path+"."+element.getName(), element, done, child);
|
||||
}
|
||||
close();
|
||||
}
|
||||
}
|
||||
private void compose(String path, Element element) throws IOException {
|
||||
String name = element.getName();
|
||||
if (element.isPrimitive() || isPrimitive(element.getType())) {
|
||||
if (element.hasValue())
|
||||
primitiveValue(name, element);
|
||||
name = "_"+name;
|
||||
if (element.getType().equals("xhtml"))
|
||||
json.anchor("end-xhtml");
|
||||
}
|
||||
if (element.hasChildren()) {
|
||||
open(name, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
|
||||
if (element.getProperty().isResource()) {
|
||||
prop("resourceType", element.getType(), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
|
||||
}
|
||||
Set<String> done = new HashSet<String>();
|
||||
for (Element child : element.getChildren()) {
|
||||
compose(path+"."+element.getName(), element, done, child);
|
||||
}
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAllowComments() {
|
||||
return allowComments;
|
||||
|
@ -570,5 +575,5 @@ public class JsonParser extends ParserBase {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -228,9 +228,13 @@ public class Property {
|
|||
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE);
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
return !"1".equals(definition.getMax());
|
||||
}
|
||||
public boolean isList() {
|
||||
return !"1".equals(definition.getMax());
|
||||
}
|
||||
|
||||
public boolean isBaseList() {
|
||||
return !"1".equals(definition.getBase().getMax());
|
||||
}
|
||||
|
||||
public String getScopedPropertyName() {
|
||||
return definition.getBase().getPath();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true);
|
||||
}
|
||||
return 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);
|
||||
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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -70,9 +70,12 @@ public class ChildIterator {
|
|||
String nb = cursor == 0 ? "--" : parent.getChildren().get(cursor - 1).getName();
|
||||
String na = cursor >= parent.getChildren().size() - 1 ? "--" : parent.getChildren().get(cursor + 1).getName();
|
||||
if (name().equals(nb) || name().equals(na)) {
|
||||
return lastCount;
|
||||
} else
|
||||
return -1;
|
||||
return lastCount;
|
||||
} else if (element().isBaseList()) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean next() {
|
||||
|
|
|
@ -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<>();
|
||||
|
|
Loading…
Reference in New Issue