Consistency around rendering comments in examples in IGs

This commit is contained in:
Grahame Grieve 2022-11-26 22:24:17 -03:00
parent 53fb08ab19
commit 49f798de48
12 changed files with 365 additions and 290 deletions

View File

@ -333,7 +333,7 @@ public class TurtleParser extends ParserBase {
ontology.triple(ontologyId, "owl:versionIRI", ontologyId.replace(FHIR_URI_BASE, FHIR_VERSION_BASE));
Subject subject = section.triple(subjId, "a", "fhir:" + e.getType());
subject.linkedPredicate("fhir:nodeRole", "fhir:treeRoot", linkResolver == null ? null : linkResolver.resolvePage("rdf.html#tree-root"));
subject.linkedPredicate("fhir:nodeRole", "fhir:treeRoot", linkResolver == null ? null : linkResolver.resolvePage("rdf.html#tree-root"), null);
for (Element child : e.getChildren()) {
composeElement(section, subject, child, null);
@ -398,17 +398,17 @@ public class TurtleParser extends ParserBase {
Complex t;
if (element.getSpecial() == SpecialElement.BUNDLE_ENTRY && parent != null && parent.getNamedChildValue("fullUrl") != null) {
String url = "<"+parent.getNamedChildValue("fullUrl")+">";
ctxt.linkedPredicate("fhir:"+en, url, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
ctxt.linkedPredicate("fhir:"+en, url, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()), null);
t = section.subject(url);
} else {
t = ctxt.linkedPredicate("fhir:"+en, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
t = ctxt.linkedPredicate("fhir:"+en, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()), null);
}
if (element.getSpecial() != null)
t.linkedPredicate("a", "fhir:"+element.fhirType(), linkResolver == null ? null : linkResolver.resolveType(element.fhirType()));
t.linkedPredicate("a", "fhir:"+element.fhirType(), linkResolver == null ? null : linkResolver.resolveType(element.fhirType()), null);
if (element.hasValue())
t.linkedPredicate("fhir:value", ttlLiteral(element.getValue(), element.getType()), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
t.linkedPredicate("fhir:value", ttlLiteral(element.getValue(), element.getType()), linkResolver == null ? null : linkResolver.resolveType(element.getType()), null);
if (element.getProperty().isList() && (!element.isResource() || element.getSpecial() == SpecialElement.CONTAINED))
t.linkedPredicate("fhir:index", Integer.toString(element.getIndex()), linkResolver == null ? null : linkResolver.resolvePage("rdf.html#index"));
t.linkedPredicate("fhir:index", Integer.toString(element.getIndex()), linkResolver == null ? null : linkResolver.resolvePage("rdf.html#index"), null);
if ("Coding".equals(element.getType()))
decorateCoding(t, element, section);

View File

@ -54,6 +54,7 @@ import org.hl7.fhir.r5.elementmodel.Element.SpecialElement;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonCreator;
import org.hl7.fhir.r5.formats.JsonCreatorCanonical;
import org.hl7.fhir.r5.formats.JsonCreatorDirect;
import org.hl7.fhir.r5.formats.JsonCreatorGson;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
@ -182,10 +183,10 @@ public class JsonParser extends ParserBase {
}
private void checkComments(JsonElement element, Element b, String path) throws FHIRFormatError {
if (element.hasComments()) {
if (element != null && element.hasComments()) {
if (allowComments) {
for (JsonComment c : element.getComments()) {
b.getFormatCommentsPre().add(c.getContent());
b.getComments().add(c.getContent());
}
} else {
for (JsonComment c : element.getComments()) {
@ -322,7 +323,7 @@ public class JsonParser extends ParserBase {
}
int c = 0;
for (JsonElement am : arr) {
parseChildComplexInstance(npath+"["+c+"]", fpath+"["+c+"]", element, property, name, am);
parseChildComplexInstance(npath+"["+c+"]", fpath+"["+c+"]", element, property, name, am, c == 0 ? arr : null, path);
c++;
}
} else if (property.isJsonKeyArray()) {
@ -394,7 +395,7 @@ public class JsonParser extends ParserBase {
if (propV.isPrimitive(pvl.getType(null))) {
parseChildPrimitiveInstance(n, pvl, pvl.getName(), npathV, fpathV, pv.getValue(), null);
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue());
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue(), null, null);
} else {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
}
@ -407,7 +408,7 @@ public class JsonParser extends ParserBase {
if (property.isList()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(e), name, path), IssueSeverity.ERROR);
}
parseChildComplexInstance(npath, fpath, element, property, name, e);
parseChildComplexInstance(npath, fpath, element, property, name, e, null, null);
}
}
@ -419,7 +420,7 @@ public class JsonParser extends ParserBase {
return b.toString();
}
private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e) throws FHIRException {
private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e, JsonElement commentContext, String commentPath) throws FHIRException {
if (property.hasTypeSpecifier()) {
FHIRPathEngine fpe = new FHIRPathEngine(context);
String type = null;
@ -454,6 +455,7 @@ public class JsonParser extends ParserBase {
JsonObject child = (JsonObject) e;
Element n = new Element(name, property).markLocation(line(child), col(child));
n.setPath(fpath);
checkComments(commentContext, n, commentPath);
checkObject(child, n, npath);
element.getChildren().add(n);
if (property.isResource()) {
@ -465,6 +467,7 @@ public class JsonParser extends ParserBase {
// we create an element marked as a null element so we know something was present
JsonNull child = (JsonNull) e;
Element n = new Element(name, property).markLocation(line(child), col(child));
checkComments(commentContext, n, commentPath);
checkComments(child, n, fpath);
n.setPath(fpath);
element.getChildren().add(n);
@ -675,13 +678,16 @@ public class JsonParser extends ParserBase {
if (e.getPath() == null) {
e.populatePaths(null);
}
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
if (style == OutputStyle.CANONICAL)
if (style == OutputStyle.CANONICAL) {
json = new JsonCreatorCanonical(osw);
else
json = new JsonCreatorGson(osw);
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
} else if (style == OutputStyle.PRETTY) {
json = new JsonCreatorDirect(osw, true, allowComments);
} else {
json = new JsonCreatorDirect(osw, false, allowComments);
}
checkComposeComments(e);
json.beginObject();
prop("resourceType", e.getType(), null);
Set<String> done = new HashSet<String>();
@ -693,12 +699,19 @@ public class JsonParser extends ParserBase {
osw.flush();
}
private void checkComposeComments(Element e) {
for (String s : e.getComments()) {
json.comment(s);
}
}
public void compose(Element e, JsonCreator json) throws Exception {
if (e.getPath() == null) {
e.populatePaths(null);
}
this.json = json;
checkComposeComments(e);
json.beginObject();
prop("resourceType", e.getType(), linkResolver == null ? null : linkResolver.resolveProperty(e.getProperty()));
@ -711,6 +724,7 @@ public class JsonParser extends ParserBase {
}
private void compose(String path, Element e, Set<String> done, Element child) throws IOException {
checkComposeComments(child);
if (wantCompose(path, child)) {
boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList();
if (!isList) {// for specials, ignore the cardinality of the stated type

View File

@ -69,6 +69,8 @@ public class TurtleParser extends ParserBase {
private String base;
private OutputStyle style;
public static String FHIR_URI_BASE = "http://hl7.org/fhir/";
public static String FHIR_VERSION_BASE = "http://build.fhir.org/";
@ -303,18 +305,16 @@ public class TurtleParser extends ParserBase {
return en.substring(0, en.lastIndexOf(".")+1)+elementName;
}
@Override
public void compose(Element e, OutputStream stream, OutputStyle style, String base) throws IOException, FHIRException {
this.base = base;
this.style = style;
Turtle ttl = new Turtle();
compose(e, ttl, base);
ttl.commit(stream, false);
}
public void compose(Element e, Turtle ttl, String base) throws FHIRException {
if (e.getPath() == null) {
e.populatePaths(null);
@ -325,8 +325,12 @@ public class TurtleParser extends ParserBase {
ttl.prefix("owl", "http://www.w3.org/2002/07/owl#");
ttl.prefix("xsd", "http://www.w3.org/2001/XMLSchema#");
Section section = ttl.section("resource");
if (style == OutputStyle.PRETTY) {
for (String s : e.getComments()) {
section.stringComment(s);
}
}
String subjId = genSubjectId(e);
String ontologyId = subjId.replace(">", ".ttl>");
@ -337,7 +341,7 @@ public class TurtleParser extends ParserBase {
ontology.triple(ontologyId, "owl:versionIRI", ontologyId.replace(FHIR_URI_BASE, FHIR_VERSION_BASE));
Subject subject = section.triple(subjId, "a", "fhir:" + e.getType());
subject.linkedPredicate("fhir:nodeRole", "fhir:treeRoot", linkResolver == null ? null : linkResolver.resolvePage("rdf.html#tree-root"));
subject.linkedPredicate("fhir:nodeRole", "fhir:treeRoot", linkResolver == null ? null : linkResolver.resolvePage("rdf.html#tree-root"), null);
for (Element child : e.getChildren()) {
composeElement(section, subject, child, null);
@ -364,13 +368,13 @@ public class TurtleParser extends ParserBase {
protected void decorateReference(Complex t, Element coding) {
String refURI = getReferenceURI(coding.getChildValue("reference"));
if(refURI != null)
t.linkedPredicate("fhir:link", refURI, linkResolver == null ? null : linkResolver.resolvePage("rdf.html#reference"));
t.linkedPredicate("fhir:link", refURI, linkResolver == null ? null : linkResolver.resolvePage("rdf.html#reference"), null);
}
protected void decorateCanonical(Complex t, Element canonical) {
String refURI = getReferenceURI(canonical.primitiveValue());
if(refURI != null)
t.linkedPredicate("fhir:link", refURI, linkResolver == null ? null : linkResolver.resolvePage("rdf.html#reference"));
t.linkedPredicate("fhir:link", refURI, linkResolver == null ? null : linkResolver.resolvePage("rdf.html#reference"), null);
}
private String genSubjectId(Element e) {
@ -397,26 +401,31 @@ public class TurtleParser extends ParserBase {
private void composeElement(Section section, Complex ctxt, Element element, Element parent) throws FHIRException {
// "Extension".equals(element.getType())?
// (element.getProperty().getDefinition().getIsModifier()? "modifierExtension" : "extension") ;
String en = getFormalName(element);
if (!wantCompose(parent == null ? "" : parent.getPath(), element)) {
return;
}
String comment = null;
if (style == OutputStyle.PRETTY) {
comment = String.join(", ", element.getComments());
}
Complex t;
if (element.getSpecial() == SpecialElement.BUNDLE_ENTRY && parent != null && parent.getNamedChildValue("fullUrl") != null) {
String url = "<"+parent.getNamedChildValue("fullUrl")+">";
ctxt.linkedPredicate("fhir:"+en, url, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
ctxt.linkedPredicate("fhir:"+en, url, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()), comment);
t = section.subject(url);
} else {
t = ctxt.linkedPredicate("fhir:"+en, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()));
t = ctxt.linkedPredicate("fhir:"+en, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty()), comment);
}
if (element.getSpecial() != null)
t.linkedPredicate("a", "fhir:"+element.fhirType(), linkResolver == null ? null : linkResolver.resolveType(element.fhirType()));
t.linkedPredicate("a", "fhir:"+element.fhirType(), linkResolver == null ? null : linkResolver.resolveType(element.fhirType()), null);
if (element.hasValue())
t.linkedPredicate("fhir:value", ttlLiteral(element.getValue(), element.getType()), linkResolver == null ? null : linkResolver.resolveType(element.getType()));
t.linkedPredicate("fhir:value", ttlLiteral(element.getValue(), element.getType()), linkResolver == null ? null : linkResolver.resolveType(element.getType()), null);
if (element.getProperty().isList() && (!element.isResource() || element.getSpecial() == SpecialElement.CONTAINED))
t.linkedPredicate("fhir:index", Integer.toString(element.getIndex()), linkResolver == null ? null : linkResolver.resolvePage("rdf.html#index"));
t.linkedPredicate("fhir:index", Integer.toString(element.getIndex()), linkResolver == null ? null : linkResolver.resolvePage("rdf.html#index"), null);
if ("Coding".equals(element.getType()))
decorateCoding(t, element, section);
@ -549,6 +558,12 @@ public class TurtleParser extends ParserBase {
Expression expression = SnomedExpressions.parse(code);
}
public OutputStyle getStyle() {
return style;
}
public void setStyle(OutputStyle style) {
this.style = style;
}
// 128045006|cellulitis (disorder)|:{363698007|finding site|=56459004|foot structure|}

View File

@ -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.
*/
@ -89,9 +89,9 @@ public class XmlParser extends ParserBase {
public XmlParser(IWorkerContext context) {
super(context);
}
private String schemaPath;
public String getSchemaPath() {
return schemaPath;
}
@ -100,7 +100,7 @@ public class XmlParser extends ParserBase {
}
public boolean isAllowXsiLocation() {
return allowXsiLocation;
}
@ -111,69 +111,69 @@ public class XmlParser extends ParserBase {
public List<NamedElement> parse(InputStream stream) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
List<NamedElement> res = new ArrayList<>();
Document doc = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// xxe protection
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
factory.setNamespaceAware(true);
if (policy == ValidationPolicy.EVERYTHING) {
// The SAX interface appears to not work when reporting the correct version/encoding.
// if we can, we'll inspect the header/encoding ourselves
if (stream.markSupported()) {
stream.mark(1024);
version = checkHeader(stream);
stream.reset();
}
// use a slower parser that keeps location data
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer nullTransformer = transformerFactory.newTransformer();
DocumentBuilder docBuilder = factory.newDocumentBuilder();
doc = docBuilder.newDocument();
DOMResult domResult = new DOMResult(doc);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
// xxe protection
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
Document doc = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// xxe protection
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
factory.setNamespaceAware(true);
if (policy == ValidationPolicy.EVERYTHING) {
// The SAX interface appears to not work when reporting the correct version/encoding.
// if we can, we'll inspect the header/encoding ourselves
if (stream.markSupported()) {
stream.mark(1024);
version = checkHeader(stream);
stream.reset();
}
// use a slower parser that keeps location data
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer nullTransformer = transformerFactory.newTransformer();
DocumentBuilder docBuilder = factory.newDocumentBuilder();
doc = docBuilder.newDocument();
DOMResult domResult = new DOMResult(doc);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
// xxe protection
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
SAXParser saxParser = spf.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
// xxe protection
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
XmlLocationAnnotator locationAnnotator = new XmlLocationAnnotator(xmlReader, doc);
InputSource inputSource = new InputSource(stream);
SAXSource saxSource = new SAXSource(locationAnnotator, inputSource);
nullTransformer.transform(saxSource, domResult);
} else {
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(stream);
}
} catch (Exception e) {
if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) {
SAXParser saxParser = spf.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
// xxe protection
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
XmlLocationAnnotator locationAnnotator = new XmlLocationAnnotator(xmlReader, doc);
InputSource inputSource = new InputSource(stream);
SAXSource saxSource = new SAXSource(locationAnnotator, inputSource);
nullTransformer.transform(saxSource, domResult);
} else {
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(stream);
}
} catch (Exception e) {
if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) {
int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0);
int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0);
logError(ValidationMessage.NO_RULE_DATE, line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL);
} else {
} else {
logError(ValidationMessage.NO_RULE_DATE, 0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
}
}
doc = null;
}
if (doc != null) {
Element e = parse(doc);
}
if (doc != null) {
Element e = parse(doc);
if (e != null) {
res.add(new NamedElement(null, e));
}
}
return res;
}
return res;
}
@ -188,21 +188,21 @@ public class XmlParser extends ParserBase {
while (node != null) {
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE)
logError(ValidationMessage.NO_RULE_DATE, line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage(
I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR);
I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR);
node = node.getNextSibling();
}
}
}
private int line(Node node, boolean end) {
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : end ? loc.getEndLine() : loc.getStartLine();
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : end ? loc.getEndLine() : loc.getStartLine();
}
private int col(Node node, boolean end) {
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : end ? loc.getEndColumn() : loc.getStartColumn();
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
return loc == null ? 0 : end ? loc.getEndColumn() : loc.getStartColumn();
}
public Element parse(Document doc) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
@ -210,12 +210,12 @@ public class XmlParser extends ParserBase {
org.w3c.dom.Element element = doc.getDocumentElement();
return parse(element);
}
public Element parse(org.w3c.dom.Element element) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
String ns = element.getNamespaceURI();
String name = element.getLocalName();
String path = "/"+pathPrefix(ns)+name;
StructureDefinition sd = getDefinition(line(element, false), col(element, false), (ns == null ? "noNamespace" : ns), name);
if (sd == null)
return null;
@ -254,7 +254,7 @@ public class XmlParser extends ParserBase {
}
if (!Utilities.noString(element.getTextContent().trim()))
return false;
Node n = element.getFirstChild();
while (n != null) {
if (n.getNodeType() == Node.ELEMENT_NODE)
@ -263,7 +263,7 @@ public class XmlParser extends ParserBase {
}
return true;
}
private void checkElement(org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError {
if (policy == ValidationPolicy.EVERYTHING) {
if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content
@ -291,16 +291,16 @@ public class XmlParser extends ParserBase {
}
private void parseChildren(String path, org.w3c.dom.Element node, Element element) throws FHIRFormatError, FHIRException, IOException, DefinitionException {
// this parsing routine retains the original order in a the XML file, to support validation
reapComments(node, element);
// this parsing routine retains the original order in a the XML file, to support validation
reapComments(node, element);
List<Property> properties = element.getProperty().getChildProperties(element.getName(), XMLUtil.getXsiType(node));
String text = XMLUtil.getDirectText(node).trim();
String text = XMLUtil.getDirectText(node).trim();
int line = line(node, false);
int col = col(node, false);
if (!Utilities.noString(text)) {
Property property = getTextProp(properties);
if (property != null) {
Property property = getTextProp(properties);
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 n = new Element("dataBase64Binary", property, "base64Binary", text).markLocation(line, col);
@ -317,8 +317,8 @@ public class XmlParser extends ParserBase {
element.getChildren().add(n);
}
}
else {
Node n = node.getFirstChild();
else {
Node n = node.getFirstChild();
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE && !Utilities.noString(n.getTextContent().trim())) {
Node nt = n; // try to find the nearest element for a line/col location
@ -337,28 +337,28 @@ public class XmlParser extends ParserBase {
}
n = n.getNextSibling();
}
}
}
}
for (int i = 0; i < node.getAttributes().getLength(); i++) {
Node attr = node.getAttributes().item(i);
String value = attr.getNodeValue();
if (!validAttrValue(value)) {
Node attr = node.getAttributes().item(i);
String value = attr.getNodeValue();
if (!validAttrValue(value)) {
logError(ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR);
}
if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) {
Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI());
if (property != null) {
String av = attr.getNodeValue();
if (ToolingExtensions.hasExtension(property.getDefinition(), ToolingExtensions.EXT_DATE_FORMAT))
av = convertForDateFormatFromExternal(ToolingExtensions.readStringExtension(property.getDefinition(), ToolingExtensions.EXT_DATE_FORMAT), av);
if (property.getName().equals("value") && element.isPrimitive())
element.setValue(av);
else {
Element n = new Element(property.getName(), property, property.getType(), av).markLocation(line, col);
}
if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) {
Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI());
if (property != null) {
String av = attr.getNodeValue();
if (ToolingExtensions.hasExtension(property.getDefinition(), ToolingExtensions.EXT_DATE_FORMAT))
av = convertForDateFormatFromExternal(ToolingExtensions.readStringExtension(property.getDefinition(), ToolingExtensions.EXT_DATE_FORMAT), av);
if (property.getName().equals("value") && element.isPrimitive())
element.setValue(av);
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())) {
@ -371,28 +371,28 @@ public class XmlParser extends ParserBase {
if (!ok) {
logError(ValidationMessage.NO_RULE_DATE, line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
}
}
}
}
}
}
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 {
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 {
XhtmlParser xp = new XhtmlParser();
xhtml = xp.parseHtmlNode((org.w3c.dom.Element) child);
if (policy == ValidationPolicy.EVERYTHING) {
@ -400,56 +400,56 @@ public class XmlParser extends ParserBase {
logError("2022-11-17", line(child, false), col(child, false), path, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR);
}
}
}
Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child, false), col(child, false));
}
Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child, false), col(child, false));
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, false), col(child, false));
if (property.isList()) {
} else {
String npath = path+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName();
Element n = new Element(child.getLocalName(), property).markLocation(line(child, false), col(child, false));
if (property.isList()) {
n.setPath(element.getPath()+"."+property.getName()+"["+repeatCount+"]");
} else {
} else {
n.setPath(element.getPath()+"."+property.getName());
}
checkElement((org.w3c.dom.Element) child, npath, n.getProperty());
boolean ok = true;
if (property.isChoice()) {
if (property.getDefinition().hasRepresentation(PropertyRepresentation.TYPEATTR)) {
String xsiType = ((org.w3c.dom.Element) child).getAttributeNS(FormatUtilities.NS_XSI, "type");
if (Utilities.noString(xsiType)) {
}
checkElement((org.w3c.dom.Element) child, npath, n.getProperty());
boolean ok = true;
if (property.isChoice()) {
if (property.getDefinition().hasRepresentation(PropertyRepresentation.TYPEATTR)) {
String xsiType = ((org.w3c.dom.Element) child).getAttributeNS(FormatUtilities.NS_XSI, "type");
if (Utilities.noString(xsiType)) {
if (ToolingExtensions.hasExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype")) {
xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype");
n.setType(xsiType);
} else {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR);
ok = false;
ok = false;
}
} else {
if (xsiType.contains(":"))
xsiType = xsiType.substring(xsiType.indexOf(":")+1);
n.setType(xsiType);
n.setExplicitType(xsiType);
}
} else
n.setType(n.getType());
}
element.getChildren().add(n);
if (ok) {
if (property.isResource())
} else {
if (xsiType.contains(":"))
xsiType = xsiType.substring(xsiType.indexOf(":")+1);
n.setType(xsiType);
n.setExplicitType(xsiType);
}
} else
n.setType(n.getType());
}
element.getChildren().add(n);
if (ok) {
if (property.isResource())
parseResource(npath, (org.w3c.dom.Element) child, n, property);
else
parseChildren(npath, (org.w3c.dom.Element) child, n);
}
}
} else
else
parseChildren(npath, (org.w3c.dom.Element) child, n);
}
}
} else
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName()), IssueSeverity.ERROR);
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR);
}
child = child.getNextSibling();
}
child = child.getNextSibling();
}
}
@ -471,16 +471,16 @@ public class XmlParser extends ParserBase {
private Property getElementProp(List<Property> properties, String nodeName, String namespace) {
List<Property> propsSortedByLongestFirst = new ArrayList<Property>(properties);
// sort properties according to their name longest first, so .requestOrganizationReference comes first before .request[x]
// and therefore the longer property names get evaluated first
Collections.sort(propsSortedByLongestFirst, new Comparator<Property>() {
@Override
public int compare(Property o1, Property o2) {
return o2.getName().length() - o1.getName().length();
}
});
// first scan, by namespace
List<Property> propsSortedByLongestFirst = new ArrayList<Property>(properties);
// sort properties according to their name longest first, so .requestOrganizationReference comes first before .request[x]
// and therefore the longer property names get evaluated first
Collections.sort(propsSortedByLongestFirst, new Comparator<Property>() {
@Override
public int compare(Property o1, Property o2) {
return o2.getName().length() - o1.getName().length();
}
});
// first scan, by namespace
for (Property p : propsSortedByLongestFirst) {
if (!p.getDefinition().hasRepresentation(PropertyRepresentation.XMLATTR) && !p.getDefinition().hasRepresentation(PropertyRepresentation.XMLTEXT)) {
if (p.getXmlName().equals(nodeName) && p.getXmlNamespace().equals(namespace))
@ -495,8 +495,8 @@ public class XmlParser extends ParserBase {
return p;
}
}
return null;
}
return null;
}
private Property getAttrProp(List<Property> properties, String nodeName, String namespace) {
for (Property p : properties) {
@ -511,27 +511,27 @@ public class XmlParser extends ParserBase {
}
}
}
return null;
return null;
}
private Property getTextProp(List<Property> properties) {
for (Property p : properties)
if (p.getDefinition().hasRepresentation(PropertyRepresentation.XMLTEXT))
return p;
return null;
}
private Property getTextProp(List<Property> properties) {
for (Property p : properties)
if (p.getDefinition().hasRepresentation(PropertyRepresentation.XMLTEXT))
return p;
return null;
}
private String convertForDateFormatFromExternal(String fmt, String av) throws FHIRException {
if ("v3".equals(fmt) || "YYYYMMDDHHMMSS.UUUU[+|-ZZzz]".equals(fmt)) {
try {
DateTimeType d = DateTimeType.parseV3(av);
return d.asStringValue();
} catch (Exception e) {
return av; // not at all clear what to do in this case.
}
}
throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATA_FORMAT_, fmt));
}
private String convertForDateFormatFromExternal(String fmt, String av) throws FHIRException {
if ("v3".equals(fmt) || "YYYYMMDDHHMMSS.UUUU[+|-ZZzz]".equals(fmt)) {
try {
DateTimeType d = DateTimeType.parseV3(av);
return d.asStringValue();
} catch (Exception e) {
return av; // not at all clear what to do in this case.
}
}
throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATA_FORMAT_, fmt));
}
private String convertForDateFormatToExternal(String fmt, String av) throws FHIRException {
if ("v3".equals(fmt)) {
@ -542,7 +542,7 @@ public class XmlParser extends ParserBase {
}
private void parseResource(String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
org.w3c.dom.Element res = XMLUtil.getFirstChild(container);
org.w3c.dom.Element res = XMLUtil.getFirstChild(container);
String name = res.getLocalName();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
if (sd == null)
@ -550,25 +550,25 @@ public class XmlParser extends ParserBase {
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
parent.setType(name);
parseChildren(res.getLocalName(), res, parent);
}
}
private void reapComments(org.w3c.dom.Element element, Element context) {
Node node = element.getPreviousSibling();
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
if (node.getNodeType() == Node.COMMENT_NODE)
context.getComments().add(0, node.getTextContent());
node = node.getPreviousSibling();
}
node = element.getLastChild();
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
node = node.getPreviousSibling();
}
while (node != null) {
if (node.getNodeType() == Node.COMMENT_NODE)
context.getComments().add(node.getTextContent());
node = node.getNextSibling();
}
}
private void reapComments(org.w3c.dom.Element element, Element context) {
Node node = element.getPreviousSibling();
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
if (node.getNodeType() == Node.COMMENT_NODE)
context.getComments().add(0, node.getTextContent());
node = node.getPreviousSibling();
}
node = element.getLastChild();
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
node = node.getPreviousSibling();
}
while (node != null) {
if (node.getNodeType() == Node.COMMENT_NODE)
context.getComments().add(node.getTextContent());
node = node.getNextSibling();
}
}
private boolean isAttr(Property property) {
for (Enumeration<PropertyRepresentation> r : property.getDefinition().getRepresentation()) {
@ -598,17 +598,17 @@ public class XmlParser extends ParserBase {
}
private boolean isText(Property property) {
for (Enumeration<PropertyRepresentation> r : property.getDefinition().getRepresentation()) {
if (r.getValue() == PropertyRepresentation.XMLTEXT) {
return true;
}
}
return false;
for (Enumeration<PropertyRepresentation> r : property.getDefinition().getRepresentation()) {
if (r.getValue() == PropertyRepresentation.XMLTEXT) {
return true;
}
}
return false;
}
@Override
@Override
public void compose(Element e, OutputStream stream, OutputStyle style, String base) throws IOException, FHIRException {
XMLWriter xml = new XMLWriter(stream, "UTF-8");
XMLWriter xml = new XMLWriter(stream, "UTF-8");
xml.setSortAttributes(false);
xml.setPretty(style == OutputStyle.PRETTY);
xml.start();
@ -645,7 +645,7 @@ public class XmlParser extends ParserBase {
addNamespaces(xml, c);
}
}
private boolean hasTypeAttr(Element e) {
if (isTypeAttr(e.getProperty()))
return true;
@ -665,7 +665,7 @@ public class XmlParser extends ParserBase {
xml.attribute("xsi:type",type);
}
}
public void compose(Element e, IXMLWriter xml) throws Exception {
if (e.getPath() == null) {
e.populatePaths(null);
@ -718,16 +718,16 @@ public class XmlParser extends ParserBase {
if (element.hasValue()) {
if (linkResolver != null)
xml.link(linkResolver.resolveType(element.getType()));
xml.attribute("value", element.getValue());
xml.attribute("value", element.getValue());
}
if (linkResolver != null)
xml.link(linkResolver.resolveProperty(element.getProperty()));
if (element.hasChildren()) {
xml.enter(element.getProperty().getXmlNamespace(), elementName);
for (Element child : element.getChildren())
composeElement(xml, child, child.getName(), false);
xml.exit(element.getProperty().getXmlNamespace(),elementName);
} else
if (element.hasChildren()) {
xml.enter(element.getProperty().getXmlNamespace(), elementName);
for (Element child : element.getChildren())
composeElement(xml, child, child.getName(), false);
xml.exit(element.getProperty().getXmlNamespace(),elementName);
} else
xml.element(elementName);
}
} else {
@ -760,7 +760,7 @@ public class XmlParser extends ParserBase {
composeElement(xml, child, child.getName(), false);
}
}
if (!root && element.getSpecial() != null)
if (!root && element.getSpecial() != null)
xml.exit(element.getProperty().getXmlNamespace(),element.getType());
xml.exit(element.getProperty().getXmlNamespace(),elementName);
}
@ -772,7 +772,7 @@ public class XmlParser extends ParserBase {
int i0 = stream.read();
int i1 = stream.read();
int i2 = stream.read();
StringBuilder b = new StringBuilder();
if (i0 == 0xEF && i1 == 0xBB && i2 == 0xBF) {
// ok, it's UTF-8

View File

@ -42,8 +42,8 @@ import java.math.BigDecimal;
*/
public interface JsonCreator {
void setIndent(String string);
void comment(String comment);
void beginObject() throws IOException;
void endObject() throws IOException;

View File

@ -116,7 +116,7 @@ public class JsonCreatorCanonical implements JsonCreator {
public JsonCreatorCanonical(OutputStreamWriter osw) {
stack = new Stack<JsonCreatorCanonical.JsonCanObject>();
jj = new JsonCreatorDirect(osw);
jj = new JsonCreatorDirect(osw, false, false);
name = null;
}
@ -125,13 +125,6 @@ public class JsonCreatorCanonical implements JsonCreator {
name = null;
return res;
}
@Override
public void setIndent(String indent) {
if (!indent.equals(""))
throw new Error("do not use pretty when canonical is set");
jj.setIndent(indent);
}
@Override
public void beginObject() throws IOException {
@ -276,6 +269,12 @@ public class JsonCreatorCanonical implements JsonCreator {
public void anchor(String name) {
// not used
}
@Override
public void comment(String content) {
// canonical JSON ignores comments
}
}

View File

@ -49,18 +49,24 @@ public class JsonCreatorDirect implements JsonCreator {
private Writer writer;
private boolean pretty;
private boolean comments;
private boolean named;
private List<Boolean> valued = new ArrayList<Boolean>();
private int indent;
private List<String> commentList = new ArrayList<>();
public JsonCreatorDirect(Writer writer) {
public JsonCreatorDirect(Writer writer, boolean pretty, boolean comments) {
super();
this.writer = writer;
this.pretty = pretty;
this.comments = pretty && comments;
}
@Override
public void setIndent(String indent) {
this.pretty = !Utilities.noString(indent);
public void comment(String content) {
if (comments) {
commentList.add(content);
}
}
@Override
@ -74,6 +80,21 @@ public class JsonCreatorDirect implements JsonCreator {
valued.add(0, false);
}
private void commitComments() throws IOException {
if (comments) {
for (String s : commentList) {
writer.write("// ");
writer.write(s);
writer.write("\r\n");
for (int i = 0; i < indent; i++) {
writer.write(" ");
}
}
commentList.clear();
}
}
public void stepIn() throws IOException {
if (pretty) {
indent++;
@ -95,6 +116,7 @@ public class JsonCreatorDirect implements JsonCreator {
}
private void checkState() throws IOException {
commitComments();
if (named) {
if (pretty)
writer.write(" : ");

View File

@ -45,11 +45,6 @@ public class JsonCreatorGson implements JsonCreator {
gson = new JsonWriter(osw);
}
@Override
public void setIndent(String indent) {
gson.setIndent(indent);
}
@Override
public void beginObject() throws IOException {
gson.beginObject();
@ -120,5 +115,11 @@ public class JsonCreatorGson implements JsonCreator {
public void anchor(String name) {
// not used
}
@Override
public void comment(String content) {
// gson (dense json) ignores comments
}
}

View File

@ -183,11 +183,13 @@ public abstract class JsonParserBase extends ParserBase implements IParser {
@Override
public void compose(OutputStream stream, Resource resource) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
if (style == OutputStyle.CANONICAL)
if (style == OutputStyle.CANONICAL) {
json = new JsonCreatorCanonical(osw);
else
json = new JsonCreatorDirect(osw); // use this instead of Gson because this preserves decimal formatting
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
} else if (style == OutputStyle.PRETTY) {
json = new JsonCreatorDirect(osw, true, false);
} else {
json = new JsonCreatorDirect(osw, false, false); // use this instead of Gson because this preserves decimal formatting
}
json.beginObject();
composeResource(resource);
json.endObject();
@ -207,11 +209,13 @@ public abstract class JsonParserBase extends ParserBase implements IParser {
@Override
public void compose(OutputStream stream, DataType type, String rootName) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8");
if (style == OutputStyle.CANONICAL)
if (style == OutputStyle.CANONICAL) {
json = new JsonCreatorCanonical(osw);
else
json = new JsonCreatorDirect(osw);// use this instead of Gson because this preserves decimal formatting
json.setIndent(style == OutputStyle.PRETTY ? " " : "");
} else if (style == OutputStyle.PRETTY) {
json = new JsonCreatorDirect(osw, true, false);
} else {
json = new JsonCreatorDirect(osw, false, false); // use this instead of Gson because this preserves decimal formatting
}
json.beginObject();
composeTypeInner(type);
json.endObject();

View File

@ -41,7 +41,7 @@ public class JsonDirectTests {
@Test
public void testEmptyObject() throws FHIRFormatError, FileNotFoundException, IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
JsonCreatorDirect json = new JsonCreatorDirect(new OutputStreamWriter(bs, "UTF-8"));
JsonCreatorDirect json = new JsonCreatorDirect(new OutputStreamWriter(bs, "UTF-8"), false, false);
json.beginObject();
json.name("a");
json.beginObject();

View File

@ -77,10 +77,10 @@ public class Turtle {
return predicate(predicate, new StringType(object));
}
public Complex linkedPredicate(String predicate, String object, String link) {
public Complex linkedPredicate(String predicate, String object, String link, String comment) {
predicateSet.add(predicate);
objectSet.add(object);
return linkedPredicate(predicate, new StringType(object), link);
return linkedPredicate(predicate, new StringType(object), link, comment);
}
public Complex predicate(String predicate, Triple object) {
@ -104,12 +104,13 @@ public class Turtle {
return null;
}
public Complex linkedPredicate(String predicate, Triple object, String link) {
public Complex linkedPredicate(String predicate, Triple object, String link, String comment) {
Predicate p = getPredicate(predicate);
if (p == null) {
p = new Predicate();
p.predicate = predicate;
p.link = link;
p.comment = comment;
predicateSet.add(predicate);
predicates.add(p);
}
@ -126,10 +127,10 @@ public class Turtle {
return c;
}
public Complex linkedPredicate(String predicate, String link) {
public Complex linkedPredicate(String predicate, String link, String comment) {
predicateSet.add(predicate);
Complex c = complex();
linkedPredicate(predicate, c, link);
linkedPredicate(predicate, c, link, comment);
return c;
}
@ -197,6 +198,7 @@ public class Turtle {
}
public class Section {
private List<String> comments = new ArrayList<>();
private String name;
private List<Subject> subjects = new ArrayList<Subject>();
@ -244,6 +246,10 @@ public class Turtle {
return true;
return false;
}
public void stringComment(String cnt) {
comments.add(cnt);
}
}
private List<Section> sections = new ArrayList<Section>();
@ -435,8 +441,14 @@ public class Turtle {
// private String lastComment = "";
private void commitSection(LineOutputStreamWriter writer, Section section) throws IOException {
writer.ln("# - "+section.name+" "+Utilities.padLeft("", '-', 75-section.name.length()));
writer.ln();
writer.ln("# - "+section.name+" "+Utilities.padLeft("", '-', 75-section.name.length()));
writer.ln();
if (!section.comments.isEmpty()) {
for (String s : section.comments) {
writer.ln("# "+s);
}
writer.ln();
}
for (Subject sbj : section.subjects) {
if (Utilities.noString(sbj.id)) {
writer.write("[");
@ -447,6 +459,7 @@ public class Turtle {
int i = 0;
for (Predicate p : sbj.predicates) {
//
writer.write(p.getPredicate());
writer.write(" ");
boolean first = true;
@ -481,12 +494,19 @@ public class Turtle {
private void commitSection(StringBuilder b, Section section) throws Exception {
b.append("# - "+section.name+" "+Utilities.padLeft("", '-', 75-section.name.length())+"\r\n");
b.append("\r\n");
if (!section.comments.isEmpty()) {
for (String s : section.comments) {
b.append("# "+s+"\r\n");
}
b.append("\r\n");
}
for (Subject sbj : section.subjects) {
b.append(Utilities.escapeXml(sbj.id));
b.append(" ");
int i = 0;
for (Predicate p : sbj.predicates) {
// b.append("# test\r\n ");
b.append(p.makelink());
b.append(" ");
boolean first = true;
@ -497,13 +517,13 @@ public class Turtle {
b.append(", ");
if (o instanceof StringType)
b.append(Utilities.escapeXml(((StringType) o).value));
else {
b.append("[");
else {
b.append("[");
if (write((Complex) o, b, 4))
b.append("\r\n ]");
else
b.append("]");
}
b.append("\r\n ]");
else
b.append("]");
}
}
String comment = p.comment == null? "" : " # "+p.comment;
i++;

View File

@ -480,9 +480,9 @@ public class XMLWriter extends OutputStreamWriter implements IXMLWriter {
writePretty();
}
if (levels.inComment())
write("<!-- "+comment+" -- >");
write(" <!-- "+comment+" -- >");
else
write("<!-- "+comment+" -->");
write(" <!-- "+comment+" -->");
if (doPretty && !isPretty())
writePretty();
}