Add path and message tracking to element model
This commit is contained in:
parent
91de7ec65b
commit
a2c6dd6af1
|
@ -55,6 +55,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.utilities.ElementDecoration;
|
import org.hl7.fhir.utilities.ElementDecoration;
|
||||||
import org.hl7.fhir.utilities.ElementDecoration.DecorationType;
|
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.Utilities;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
|
@ -102,6 +103,8 @@ public class Element extends Base {
|
||||||
private String explicitType; // for xsi:type attribute
|
private String explicitType; // for xsi:type attribute
|
||||||
private Element parentForValidator;
|
private Element parentForValidator;
|
||||||
private boolean hasParentForValidator;
|
private boolean hasParentForValidator;
|
||||||
|
private String path;
|
||||||
|
private List<ValidationMessage> messages;
|
||||||
|
|
||||||
public Element(String name) {
|
public Element(String name) {
|
||||||
super();
|
super();
|
||||||
|
@ -706,6 +709,13 @@ public class Element extends Base {
|
||||||
return property.isList();
|
return property.isList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBaseList() {
|
||||||
|
if (elementProperty != null)
|
||||||
|
return elementProperty.isBaseList();
|
||||||
|
else
|
||||||
|
return property.isBaseList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getTypesForProperty(int hash, String name) throws FHIRException {
|
public String[] getTypesForProperty(int hash, String name) throws FHIRException {
|
||||||
Property p = property.getChildSimpleName(this.name, name);
|
Property p = property.getChildSimpleName(this.name, name);
|
||||||
|
@ -938,6 +948,29 @@ public class Element extends Base {
|
||||||
property = null;
|
property = null;
|
||||||
elementProperty = null;
|
elementProperty = null;
|
||||||
xhtml = 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.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
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.
|
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
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
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
|
endorse or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
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)
|
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
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,32 +72,33 @@ import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
public class JsonParser extends ParserBase {
|
public class JsonParser extends ParserBase {
|
||||||
|
|
||||||
private JsonCreator json;
|
private JsonCreator json;
|
||||||
private Map<JsonElement, LocationData> map;
|
private Map<JsonElement, LocationData> map;
|
||||||
private boolean allowComments;
|
private boolean allowComments;
|
||||||
|
|
||||||
private ProfileUtilities profileUtilities;
|
private ProfileUtilities profileUtilities;
|
||||||
|
|
||||||
public JsonParser(IWorkerContext context, ProfileUtilities utilities) {
|
public JsonParser(IWorkerContext context, ProfileUtilities utilities) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
this.profileUtilities = utilities;
|
this.profileUtilities = utilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonParser(IWorkerContext context) {
|
public JsonParser(IWorkerContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
this.profileUtilities = new ProfileUtilities(this.context, null, null, new FHIRPathEngine(context));
|
this.profileUtilities = new ProfileUtilities(this.context, null, null, new FHIRPathEngine(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Element parse(String source, String type) throws Exception {
|
public Element parse(String source, String type) throws Exception {
|
||||||
JsonObject obj = (JsonObject) new com.google.gson.JsonParser().parse(source);
|
JsonObject obj = (JsonObject) new com.google.gson.JsonParser().parse(source);
|
||||||
String path = "/"+type;
|
String path = "/"+type;
|
||||||
StructureDefinition sd = getDefinition(-1, -1, type);
|
StructureDefinition sd = getDefinition(-1, -1, type);
|
||||||
if (sd == null)
|
if (sd == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Element result = new Element(type, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
|
Element result = new Element(type, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
|
||||||
|
result.setPath(type);
|
||||||
checkObject(obj, path);
|
checkObject(obj, path);
|
||||||
result.setType(type);
|
result.setType(type);
|
||||||
parseChildren(path, obj, result, true);
|
parseChildren(path, obj, result, true);
|
||||||
|
@ -106,138 +107,140 @@ public class JsonParser extends ParserBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Element parse(InputStream stream) throws IOException, FHIRException {
|
public Element parse(InputStream stream) throws IOException, FHIRException {
|
||||||
// if we're parsing at this point, then we're going to use the custom parser
|
// if we're parsing at this point, then we're going to use the custom parser
|
||||||
map = new IdentityHashMap<JsonElement, LocationData>();
|
map = new IdentityHashMap<JsonElement, LocationData>();
|
||||||
String source = TextFile.streamToString(stream);
|
String source = TextFile.streamToString(stream);
|
||||||
if (policy == ValidationPolicy.EVERYTHING) {
|
if (policy == ValidationPolicy.EVERYTHING) {
|
||||||
JsonObject obj = null;
|
JsonObject obj = null;
|
||||||
try {
|
try {
|
||||||
obj = JsonTrackingParser.parse(source, map, false, allowComments);
|
obj = JsonTrackingParser.parse(source, map, false, allowComments);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logError(-1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
logError(-1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
assert (map.containsKey(obj));
|
assert (map.containsKey(obj));
|
||||||
return parse(obj);
|
return parse(obj);
|
||||||
} else {
|
} else {
|
||||||
JsonObject obj = JsonTrackingParser.parse(source, null); // (JsonObject) new com.google.gson.JsonParser().parse(source);
|
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);
|
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseChildComplex(String path, JsonObject object, Element element, Set<String> processed, Property property, String name) throws FHIRException {
|
public Element parse(JsonObject object, Map<JsonElement, LocationData> map) throws FHIRException {
|
||||||
processed.add(name);
|
this.map = map;
|
||||||
String npath = path+"."+property.getName();
|
return parse(object);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String describeType(JsonElement e) {
|
public Element parse(JsonObject object) throws FHIRException {
|
||||||
if (e.isJsonArray())
|
JsonElement rt = object.get("resourceType");
|
||||||
return "an Array";
|
if (rt == null) {
|
||||||
if (e.isJsonObject())
|
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";
|
return "an Object";
|
||||||
if (e.isJsonPrimitive())
|
if (e.isJsonPrimitive())
|
||||||
return "a primitive property";
|
return "a primitive property";
|
||||||
|
@ -246,24 +249,25 @@ public class JsonParser extends ParserBase {
|
||||||
return null;
|
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) {
|
if (e instanceof JsonObject) {
|
||||||
JsonObject child = (JsonObject) e;
|
JsonObject child = (JsonObject) e;
|
||||||
Element n = new Element(name, property).markLocation(line(child), col(child));
|
Element n = new Element(name, property).markLocation(line(child), col(child));
|
||||||
checkObject(child, npath);
|
n.setPath(fpath);
|
||||||
element.getChildren().add(n);
|
checkObject(child, npath);
|
||||||
if (property.isResource())
|
element.getChildren().add(n);
|
||||||
parseResource(npath, child, n, property);
|
if (property.isResource())
|
||||||
else
|
parseResource(npath, child, n, property);
|
||||||
parseChildren(npath, child, n, false);
|
else
|
||||||
} else
|
parseChildren(npath, child, n, false);
|
||||||
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);
|
} 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) {
|
private String describe(JsonElement e) {
|
||||||
if (e instanceof JsonArray) {
|
if (e instanceof JsonArray) {
|
||||||
return "an array";
|
return "an array";
|
||||||
}
|
}
|
||||||
if (e instanceof JsonObject) {
|
if (e instanceof JsonObject) {
|
||||||
return "an object";
|
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 {
|
private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException {
|
||||||
String npath = path+"."+property.getName();
|
String npath = path+"."+property.getName();
|
||||||
processed.add(name);
|
String fpath = element.getPath()+"."+property.getName();
|
||||||
processed.add("_"+name);
|
processed.add(name);
|
||||||
JsonElement main = object.has(name) ? object.get(name) : null;
|
processed.add("_"+name);
|
||||||
JsonElement fork = object.has("_"+name) ? object.get("_"+name) : null;
|
JsonElement main = object.has(name) ? object.get(name) : null;
|
||||||
if (main != null || fork != null) {
|
JsonElement fork = object.has("_"+name) ? object.get("_"+name) : null;
|
||||||
if (property.isList()) {
|
if (main != null || fork != null) {
|
||||||
boolean ok = true;
|
if (property.isList()) {
|
||||||
if (!(main == null || main instanceof JsonArray)) {
|
boolean ok = true;
|
||||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
|
if (!(main == null || main instanceof JsonArray)) {
|
||||||
ok = false;
|
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)) {
|
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;
|
ok = false;
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -296,158 +301,158 @@ public class JsonParser extends ParserBase {
|
||||||
for (int i = 0; i < Math.max(arrC(arr1), arrC(arr2)); i++) {
|
for (int i = 0; i < Math.max(arrC(arr1), arrC(arr2)); i++) {
|
||||||
JsonElement m = arrI(arr1, i);
|
JsonElement m = arrI(arr1, i);
|
||||||
JsonElement f = arrI(arr2, i);
|
JsonElement f = arrI(arr2, i);
|
||||||
parseChildPrimitiveInstance(element, property, name, npath, m, f);
|
parseChildPrimitiveInstance(element, property, name, npath, fpath, m, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
parseChildPrimitiveInstance(element, property, name, npath, main, fork);
|
parseChildPrimitiveInstance(element, property, name, npath, fpath, main, fork);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonElement arrI(JsonArray arr, int i) {
|
private JsonElement arrI(JsonArray arr, int i) {
|
||||||
return arr == null || i >= arr.size() || arr.get(i) instanceof JsonNull ? null : arr.get(i);
|
return arr == null || i >= arr.size() || arr.get(i) instanceof JsonNull ? null : arr.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int arrC(JsonArray arr) {
|
private int arrC(JsonArray arr) {
|
||||||
return arr == null ? 0 : arr.size();
|
return arr == null ? 0 : arr.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath,
|
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException {
|
||||||
JsonElement main, JsonElement fork) throws FHIRException {
|
if (main != null && !(main instanceof JsonPrimitive))
|
||||||
if (main != null && !(main instanceof JsonPrimitive))
|
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(
|
||||||
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);
|
I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR);
|
||||||
else if (fork != null && !(fork instanceof JsonObject))
|
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);
|
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 {
|
else {
|
||||||
Element n = new Element(name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork));
|
Element n = new Element(name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork));
|
||||||
element.getChildren().add(n);
|
n.setPath(fpath);
|
||||||
if (main != null) {
|
element.getChildren().add(n);
|
||||||
JsonPrimitive p = (JsonPrimitive) main;
|
if (main != null) {
|
||||||
if (p.isNumber() && p.getAsNumber() instanceof JsonTrackingParser.PresentedBigDecimal) {
|
JsonPrimitive p = (JsonPrimitive) main;
|
||||||
String rawValue = ((JsonTrackingParser.PresentedBigDecimal) p.getAsNumber()).getPresentation();
|
if (p.isNumber() && p.getAsNumber() instanceof JsonTrackingParser.PresentedBigDecimal) {
|
||||||
n.setValue(rawValue);
|
String rawValue = ((JsonTrackingParser.PresentedBigDecimal) p.getAsNumber()).getPresentation();
|
||||||
} else {
|
n.setValue(rawValue);
|
||||||
n.setValue(p.getAsString());
|
} 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 {
|
if (policy == ValidationPolicy.EVERYTHING) {
|
||||||
n.setXhtml(new XhtmlParser().setValidatorMode(policy == ValidationPolicy.EVERYTHING).parse(n.getValue(), null).getDocumentElement());
|
// now we cross-check the primitive format against the stated type
|
||||||
} catch (Exception e) {
|
if (Utilities.existsInList(n.getType(), "boolean")) {
|
||||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR);
|
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 (policy == ValidationPolicy.EVERYTHING) {
|
if (!p.isNumber())
|
||||||
// now we cross-check the primitive format against the stated type
|
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
|
||||||
if (Utilities.existsInList(n.getType(), "boolean")) {
|
} else if (!p.isString())
|
||||||
if (!p.isBoolean())
|
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
|
||||||
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())
|
if (fork != null) {
|
||||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
|
JsonObject child = (JsonObject) fork;
|
||||||
} else if (!p.isString())
|
checkObject(child, npath);
|
||||||
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
|
parseChildren(npath, child, n, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException {
|
||||||
JsonElement rt = res.get("resourceType");
|
JsonElement rt = res.get("resourceType");
|
||||||
if (rt == null) {
|
if (rt == null) {
|
||||||
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
|
||||||
} else {
|
} else {
|
||||||
String name = rt.getAsString();
|
String name = rt.getAsString();
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs()));
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs()));
|
||||||
if (sd == null) {
|
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);
|
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 {
|
} else {
|
||||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||||
parent.setType(name);
|
parent.setType(name);
|
||||||
parseChildren(npath, res, parent, true);
|
parseChildren(npath, res, parent, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reapComments(JsonObject object, Element context) {
|
private void reapComments(JsonObject object, Element context) {
|
||||||
if (object.has("fhir_comments")) {
|
if (object.has("fhir_comments")) {
|
||||||
JsonArray arr = object.getAsJsonArray("fhir_comments");
|
JsonArray arr = object.getAsJsonArray("fhir_comments");
|
||||||
for (JsonElement e : arr) {
|
for (JsonElement e : arr) {
|
||||||
context.getComments().add(e.getAsString());
|
context.getComments().add(e.getAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int line(JsonElement e) {
|
private int line(JsonElement e) {
|
||||||
if (map == null|| !map.containsKey(e))
|
if (map == null|| !map.containsKey(e))
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return map.get(e).getLine();
|
return map.get(e).getLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int col(JsonElement e) {
|
private int col(JsonElement e) {
|
||||||
if (map == null|| !map.containsKey(e))
|
if (map == null|| !map.containsKey(e))
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return map.get(e).getCol();
|
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);
|
json.link(link);
|
||||||
if (name != null)
|
if (name != null)
|
||||||
json.name(name);
|
json.name(name);
|
||||||
json.value(value);
|
json.value(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void open(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.beginObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void close() throws IOException {
|
|
||||||
json.endObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void openArray(String name, String link) throws IOException {
|
|
||||||
json.link(link);
|
json.link(link);
|
||||||
if (name != null)
|
if (name != null)
|
||||||
json.name(name);
|
json.name(name);
|
||||||
json.beginArray();
|
json.beginObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void closeArray() throws IOException {
|
protected void close() throws IOException {
|
||||||
json.endArray();
|
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
|
@Override
|
||||||
public void compose(Element e, OutputStream stream, OutputStyle style, String identity) throws FHIRException, IOException {
|
public void compose(Element e, OutputStream stream, OutputStyle style, String identity) throws FHIRException, IOException {
|
||||||
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
|
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
|
||||||
if (style == OutputStyle.CANONICAL)
|
if (style == OutputStyle.CANONICAL)
|
||||||
json = new JsonCreatorCanonical(osw);
|
json = new JsonCreatorCanonical(osw);
|
||||||
else
|
else
|
||||||
json = new JsonCreatorGson(osw);
|
json = new JsonCreatorGson(osw);
|
||||||
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
|
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
|
||||||
json.beginObject();
|
json.beginObject();
|
||||||
prop("resourceType", e.getType(), null);
|
prop("resourceType", e.getType(), null);
|
||||||
Set<String> done = new HashSet<String>();
|
Set<String> done = new HashSet<String>();
|
||||||
for (Element child : e.getChildren()) {
|
for (Element child : e.getChildren()) {
|
||||||
compose(e.getName(), e, done, child);
|
compose(e.getName(), e, done, child);
|
||||||
}
|
}
|
||||||
json.endObject();
|
json.endObject();
|
||||||
json.finish();
|
json.finish();
|
||||||
osw.flush();
|
osw.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compose(Element e, JsonCreator json) throws Exception {
|
public void compose(Element e, JsonCreator json) throws Exception {
|
||||||
this.json = json;
|
this.json = json;
|
||||||
|
@ -462,104 +467,104 @@ public class JsonParser extends ParserBase {
|
||||||
json.finish();
|
json.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compose(String path, Element e, Set<String> done, Element child) throws IOException {
|
private void compose(String path, Element e, Set<String> done, Element child) throws IOException {
|
||||||
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
|
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
|
||||||
if (!isList) {// for specials, ignore the cardinality of the stated type
|
if (!isList) {// for specials, ignore the cardinality of the stated type
|
||||||
compose(path, child);
|
compose(path, child);
|
||||||
} else if (!done.contains(child.getName())) {
|
} else if (!done.contains(child.getName())) {
|
||||||
done.add(child.getName());
|
done.add(child.getName());
|
||||||
List<Element> list = e.getChildrenByName(child.getName());
|
List<Element> list = e.getChildrenByName(child.getName());
|
||||||
composeList(path, list);
|
composeList(path, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void composeList(String path, List<Element> list) throws IOException {
|
private void composeList(String path, List<Element> list) throws IOException {
|
||||||
// there will be at least one element
|
// there will be at least one element
|
||||||
String name = list.get(0).getName();
|
String name = list.get(0).getName();
|
||||||
boolean complex = true;
|
boolean complex = true;
|
||||||
if (list.get(0).isPrimitive()) {
|
if (list.get(0).isPrimitive()) {
|
||||||
boolean prim = false;
|
boolean prim = false;
|
||||||
complex = false;
|
complex = false;
|
||||||
for (Element item : list) {
|
for (Element item : list) {
|
||||||
if (item.hasValue())
|
if (item.hasValue())
|
||||||
prim = true;
|
prim = true;
|
||||||
if (item.hasChildren())
|
if (item.hasChildren())
|
||||||
complex = true;
|
complex = true;
|
||||||
}
|
}
|
||||||
if (prim) {
|
if (prim) {
|
||||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||||
for (Element item : list) {
|
for (Element item : list) {
|
||||||
if (item.hasValue())
|
if (item.hasValue())
|
||||||
primitiveValue(null, item);
|
primitiveValue(null, item);
|
||||||
else
|
else
|
||||||
json.nullValue();
|
json.nullValue();
|
||||||
}
|
}
|
||||||
closeArray();
|
closeArray();
|
||||||
}
|
}
|
||||||
name = "_"+name;
|
name = "_"+name;
|
||||||
}
|
}
|
||||||
if (complex) {
|
if (complex) {
|
||||||
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
openArray(name, linkResolver == null ? null : linkResolver.resolveProperty(list.get(0).getProperty()));
|
||||||
for (Element item : list) {
|
for (Element item : list) {
|
||||||
if (item.hasChildren()) {
|
if (item.hasChildren()) {
|
||||||
open(null,null);
|
open(null,null);
|
||||||
if (item.getProperty().isResource()) {
|
if (item.getProperty().isResource()) {
|
||||||
prop("resourceType", item.getType(), linkResolver == null ? null : linkResolver.resolveType(item.getType()));
|
prop("resourceType", item.getType(), linkResolver == null ? null : linkResolver.resolveType(item.getType()));
|
||||||
}
|
}
|
||||||
Set<String> done = new HashSet<String>();
|
Set<String> done = new HashSet<String>();
|
||||||
for (Element child : item.getChildren()) {
|
for (Element child : item.getChildren()) {
|
||||||
compose(path+"."+name+"[]", item, done, child);
|
compose(path+"."+name+"[]", item, done, child);
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
} else
|
} else
|
||||||
json.nullValue();
|
json.nullValue();
|
||||||
}
|
}
|
||||||
closeArray();
|
closeArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void primitiveValue(String name, Element item) throws IOException {
|
private void primitiveValue(String name, Element item) throws IOException {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (linkResolver != null)
|
if (linkResolver != null)
|
||||||
json.link(linkResolver.resolveProperty(item.getProperty()));
|
json.link(linkResolver.resolveProperty(item.getProperty()));
|
||||||
json.name(name);
|
json.name(name);
|
||||||
}
|
}
|
||||||
String type = item.getType();
|
String type = item.getType();
|
||||||
if (Utilities.existsInList(type, "boolean"))
|
if (Utilities.existsInList(type, "boolean"))
|
||||||
json.value(item.getValue().trim().equals("true") ? new Boolean(true) : new Boolean(false));
|
json.value(item.getValue().trim().equals("true") ? new Boolean(true) : new Boolean(false));
|
||||||
else if (Utilities.existsInList(type, "integer", "unsignedInt", "positiveInt"))
|
else if (Utilities.existsInList(type, "integer", "unsignedInt", "positiveInt"))
|
||||||
json.value(new Integer(item.getValue()));
|
json.value(new Integer(item.getValue()));
|
||||||
else if (Utilities.existsInList(type, "decimal"))
|
else if (Utilities.existsInList(type, "decimal"))
|
||||||
try {
|
try {
|
||||||
json.value(new BigDecimal(item.getValue()));
|
json.value(new BigDecimal(item.getValue()));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new NumberFormatException(context.formatMessage(I18nConstants.ERROR_WRITING_NUMBER__TO_JSON, item.getValue()));
|
throw new NumberFormatException(context.formatMessage(I18nConstants.ERROR_WRITING_NUMBER__TO_JSON, item.getValue()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
json.value(item.getValue());
|
json.value(item.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compose(String path, Element element) throws IOException {
|
private void compose(String path, Element element) throws IOException {
|
||||||
String name = element.getName();
|
String name = element.getName();
|
||||||
if (element.isPrimitive() || isPrimitive(element.getType())) {
|
if (element.isPrimitive() || isPrimitive(element.getType())) {
|
||||||
if (element.hasValue())
|
if (element.hasValue())
|
||||||
primitiveValue(name, element);
|
primitiveValue(name, element);
|
||||||
name = "_"+name;
|
name = "_"+name;
|
||||||
if (element.getType().equals("xhtml"))
|
if (element.getType().equals("xhtml"))
|
||||||
json.anchor("end-xhtml");
|
json.anchor("end-xhtml");
|
||||||
}
|
}
|
||||||
if (element.hasChildren()) {
|
if (element.hasChildren()) {
|
||||||
open(name, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
|
open(name, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
|
||||||
if (element.getProperty().isResource()) {
|
if (element.getProperty().isResource()) {
|
||||||
prop("resourceType", element.getType(), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
|
prop("resourceType", element.getType(), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
|
||||||
}
|
}
|
||||||
Set<String> done = new HashSet<String>();
|
Set<String> done = new HashSet<String>();
|
||||||
for (Element child : element.getChildren()) {
|
for (Element child : element.getChildren()) {
|
||||||
compose(path+"."+element.getName(), element, done, child);
|
compose(path+"."+element.getName(), element, done, child);
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowComments() {
|
public boolean isAllowComments() {
|
||||||
return allowComments;
|
return allowComments;
|
||||||
|
@ -570,5 +575,5 @@ public class JsonParser extends ParserBase {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -228,9 +228,13 @@ public class Property {
|
||||||
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE);
|
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isList() {
|
public boolean isList() {
|
||||||
return !"1".equals(definition.getMax());
|
return !"1".equals(definition.getMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBaseList() {
|
||||||
|
return !"1".equals(definition.getBase().getMax());
|
||||||
|
}
|
||||||
|
|
||||||
public String getScopedPropertyName() {
|
public String getScopedPropertyName() {
|
||||||
return definition.getBase().getPath();
|
return definition.getBase().getPath();
|
||||||
|
|
|
@ -203,6 +203,7 @@ public class XmlParser extends ParserBase {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
|
Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
|
||||||
|
result.setPath(element.getLocalName());
|
||||||
checkElement(element, path, result.getProperty());
|
checkElement(element, path, result.getProperty());
|
||||||
result.markLocation(line(element), col(element));
|
result.markLocation(line(element), col(element));
|
||||||
result.setType(element.getLocalName());
|
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 {
|
public Element parse(org.w3c.dom.Element base, String type) throws Exception {
|
||||||
StructureDefinition sd = getDefinition(0, 0, FormatUtilities.FHIR_NS, type);
|
StructureDefinition sd = getDefinition(0, 0, FormatUtilities.FHIR_NS, type);
|
||||||
Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
|
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();
|
String path = "/"+pathPrefix(base.getNamespaceURI())+base.getLocalName();
|
||||||
checkElement(base, path, result.getProperty());
|
checkElement(base, path, result.getProperty());
|
||||||
result.setType(base.getLocalName());
|
result.setType(base.getLocalName());
|
||||||
|
@ -283,13 +285,18 @@ public class XmlParser extends ParserBase {
|
||||||
if (property != null) {
|
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 ("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"))) {
|
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 {
|
} 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 {
|
} else {
|
||||||
element.getChildren().add(
|
Element n = new Element(property.getName(), property, property.getType(), text).markLocation(line, col);
|
||||||
new Element(property.getName(), property, property.getType(), text).markLocation(line, col));
|
n.setPath(element.getPath()+"."+property.getName());
|
||||||
|
element.getChildren().add(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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);
|
av = convertForDateFormatFromExternal(ToolingExtensions.readStringExtension(property.getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat"), av);
|
||||||
if (property.getName().equals("value") && element.isPrimitive())
|
if (property.getName().equals("value") && element.isPrimitive())
|
||||||
element.setValue(av);
|
element.setValue(av);
|
||||||
else
|
else {
|
||||||
element.getChildren().add(new Element(property.getName(), property, property.getType(), av).markLocation(line, col));
|
Element n = new Element(property.getName(), property, property.getType(), av).markLocation(line, col);
|
||||||
|
n.setPath(element.getPath()+"."+property.getName());
|
||||||
|
element.getChildren().add(n);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
if (FormatUtilities.FHIR_NS.equals(node.getNamespaceURI())) {
|
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();
|
Node child = node.getFirstChild();
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
Property property = getElementProp(properties, child.getLocalName(), child.getNamespaceURI());
|
Property property = getElementProp(properties, child.getLocalName(), child.getNamespaceURI());
|
||||||
if (property != null) {
|
if (property != null) {
|
||||||
|
if (property.getName().equals(lastName)) {
|
||||||
|
repeatCount++;
|
||||||
|
} else {
|
||||||
|
lastName = property.getName();
|
||||||
|
repeatCount = 0;
|
||||||
|
}
|
||||||
if (!property.isChoice() && "xhtml".equals(property.getType())) {
|
if (!property.isChoice() && "xhtml".equals(property.getType())) {
|
||||||
XhtmlNode xhtml;
|
XhtmlNode xhtml;
|
||||||
if (property.getDefinition().hasRepresentation(PropertyRepresentation.CDATEXT))
|
if (property.getDefinition().hasRepresentation(PropertyRepresentation.CDATEXT))
|
||||||
xhtml = new CDANarrativeFormat().convert((org.w3c.dom.Element) child);
|
xhtml = new CDANarrativeFormat().convert((org.w3c.dom.Element) child);
|
||||||
else
|
else
|
||||||
xhtml = new XhtmlParser().setValidatorMode(true).parseHtmlNode((org.w3c.dom.Element) child);
|
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 {
|
} else {
|
||||||
String npath = path+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName();
|
String npath = path+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName();
|
||||||
Element n = new Element(child.getLocalName(), property).markLocation(line(child), col(child));
|
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());
|
checkElement((org.w3c.dom.Element) child, npath, n.getProperty());
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
if (property.isChoice()) {
|
if (property.isChoice()) {
|
||||||
|
|
Loading…
Reference in New Issue