Merge pull request #1674 from hapifhir/2024-07-gg-ndjson-support
2024 07 gg ndjson support
This commit is contained in:
commit
a5118d8bb9
|
@ -592,7 +592,7 @@ public abstract class CanonicalResourceComparer extends ResourceComparer {
|
|||
|
||||
public XhtmlNode renderMetadata(CanonicalResourceComparison<? extends CanonicalResource> comparison, String id, String prefix) throws FHIRException, IOException {
|
||||
// columns: code, display (left|right), properties (left|right)
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false, "c");
|
||||
TableModel model = gen.new TableModel(id, true);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, null, "Name", "Property Name", null, 100));
|
||||
|
|
|
@ -743,7 +743,7 @@ public class CapabilityStatementComparer extends CanonicalResourceComparer {
|
|||
|
||||
// 6 columns: path | left value | left doco | right value | right doco | comments
|
||||
public XhtmlNode renderStatements(CapabilityStatementComparison comparison, String id, String prefix) throws FHIRException, IOException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false, "c");
|
||||
TableModel model = gen.new TableModel(id, true);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, null, "Type", "The type of item", null, 100));
|
||||
|
|
|
@ -520,7 +520,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
|
|||
|
||||
public XhtmlNode renderConcepts(CodeSystemComparison comparison, String id, String prefix) throws FHIRException, IOException {
|
||||
// columns: code, display (left|right), properties (left|right)
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false, "c");
|
||||
TableModel model = gen.new TableModel(id, true);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, null, "Code", "The code for the concept", null, 100));
|
||||
|
|
|
@ -1252,7 +1252,7 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
|
|||
}
|
||||
|
||||
public XhtmlNode renderStructure(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(session.getI18n(), Utilities.path("[tmp]", "compare"), false, true);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(session.getI18n(), Utilities.path("[tmp]", "compare"), false, true, "cmp");
|
||||
TableModel model = gen.initComparisonTable(corePath, id);
|
||||
genElementComp(null /* come back to this later */, null /* come back to this later */, gen, model.getRows(), comp.combined, corePath, prefix, null, true);
|
||||
return gen.generate(model, prefix, 0, null);
|
||||
|
@ -1260,13 +1260,13 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
|
|||
|
||||
public XhtmlNode renderUnion(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {
|
||||
StructureDefinitionRenderer sdr = new StructureDefinitionRenderer(new RenderingContext(utilsLeft.getContext(), null, utilsLeft.getTerminologyServiceOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER).setPkp(this));
|
||||
return sdr.generateTable(new RenderingStatus(), corePath, comp.union, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "u", null);
|
||||
return sdr.generateTable(new RenderingStatus(), corePath, comp.union, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext().withUniqueLocalPrefix("u"), "u", null);
|
||||
}
|
||||
|
||||
|
||||
public XhtmlNode renderIntersection(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {
|
||||
StructureDefinitionRenderer sdr = new StructureDefinitionRenderer(new RenderingContext(utilsLeft.getContext(), null, utilsLeft.getTerminologyServiceOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER).setPkp(this));
|
||||
return sdr.generateTable(new RenderingStatus(), corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "i", null);
|
||||
return sdr.generateTable(new RenderingStatus(), corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext().withUniqueLocalPrefix("i"), "i", null);
|
||||
}
|
||||
|
||||
private void genElementComp(String defPath, String anchorPrefix, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinitionNode> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
|
||||
|
|
|
@ -589,7 +589,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
}
|
||||
|
||||
public XhtmlNode renderCompose(ValueSetComparison csc, String id, String prefix) throws FHIRException, IOException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "comparison"), false);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "comparison"), false, "c");
|
||||
TableModel model = gen.new TableModel(id, true);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, null, "Item", "The type of item being compared", null, 100));
|
||||
|
@ -780,7 +780,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
boolean hasAbstract = findAbstract(csc.getExpansion());
|
||||
boolean hasInactive = findInactive(csc.getExpansion());
|
||||
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "comparison"), false);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "comparison"), false, "c");
|
||||
TableModel model = gen.new TableModel(id, true);
|
||||
model.setAlternating(true);
|
||||
if (hasSystem) {
|
||||
|
|
|
@ -134,6 +134,10 @@ public class JsonParser extends ParserBase {
|
|||
|
||||
@Override
|
||||
public List<ValidatedFragment> parse(InputStream inStream) throws IOException, FHIRException {
|
||||
return parse(inStream, 0);
|
||||
}
|
||||
|
||||
public List<ValidatedFragment> parse(InputStream inStream, int line) throws IOException, FHIRException {
|
||||
// long start = System.currentTimeMillis();
|
||||
byte[] content = TextFile.streamToBytes(inStream);
|
||||
ValidatedFragment focusFragment = new ValidatedFragment(ValidatedFragment.FOCUS_NAME, "json", content, false);
|
||||
|
@ -146,12 +150,12 @@ public class JsonParser extends ParserBase {
|
|||
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
try {
|
||||
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true);
|
||||
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true, line);
|
||||
} catch (Exception e) {
|
||||
logError(focusFragment.getErrors(), ValidationMessage.NO_RULE_DATE, -1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
||||
logError(focusFragment.getErrors(), ValidationMessage.NO_RULE_DATE, -1, -1, null, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
|
||||
}
|
||||
} else {
|
||||
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true);
|
||||
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true, line);
|
||||
}
|
||||
|
||||
if (obj != null) {
|
||||
|
|
|
@ -47,7 +47,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
|||
public class Manager {
|
||||
|
||||
//TODO use EnumMap
|
||||
public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR, SHC, SHL, FML;
|
||||
public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR, SHC, SHL, FML, NDJSON;
|
||||
// SHC = smart health cards, including as text versions of QR codes
|
||||
// SHL = smart health links, also a text version of the QR code
|
||||
|
||||
|
@ -69,6 +69,8 @@ public class Manager {
|
|||
return "shl";
|
||||
case FML:
|
||||
return "fml";
|
||||
case NDJSON:
|
||||
return "ndjson";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -91,6 +93,8 @@ public class Manager {
|
|||
return SHL;
|
||||
case "fml":
|
||||
return FML;
|
||||
case "ndjson":
|
||||
return NDJSON;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -127,6 +131,7 @@ public class Manager {
|
|||
}
|
||||
switch (format) {
|
||||
case JSON : return new JsonParser(context);
|
||||
case NDJSON : return new NDJsonParser(context);
|
||||
case XML : return new XmlParser(context);
|
||||
case TURTLE : return new TurtleParser(context);
|
||||
case VBAR : return new VerticalBarParser(context);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package org.hl7.fhir.r5.elementmodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
/*
|
||||
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
|
||||
list of conditions and the following disclaimer.
|
||||
* 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
|
||||
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.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonCreator;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
||||
|
||||
public class NDJsonParser extends ParserBase {
|
||||
|
||||
public NDJsonParser(IWorkerContext context, ProfileUtilities utilities) {
|
||||
super(context, utilities);
|
||||
}
|
||||
|
||||
public NDJsonParser(IWorkerContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private ValidatedFragment processLine(int lineCount, String line) throws FHIRException, IOException {
|
||||
List<ValidatedFragment> list = new JsonParser(context).parse(new ByteArrayInputStream(line.getBytes(StandardCharsets.UTF_8)), lineCount);
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ValidatedFragment> parse(InputStream inStream) throws IOException, FHIRException {
|
||||
String source = TextFile.streamToString(inStream);
|
||||
int length = source.length();
|
||||
int start = 0;
|
||||
int cursor = start;
|
||||
int lineCount = 0;
|
||||
|
||||
List<ValidatedFragment> res = new ArrayList<>();
|
||||
while (cursor < length) {
|
||||
while (cursor < length && source.charAt(cursor) != '\n') {
|
||||
cursor++;
|
||||
}
|
||||
if (cursor < length) {
|
||||
String line = source.substring(start, cursor);
|
||||
if (line.endsWith("\r")) {
|
||||
line = line.substring(0, line.length()-1);
|
||||
}
|
||||
if (Utilities.noString(line.trim())) {
|
||||
ValidatedFragment vf = new ValidatedFragment(ValidatedFragment.ITEM_NAME, null, null, false);
|
||||
logError(vf.getErrors(), "2024-06-30", lineCount+1, 1, null, IssueType.INFORMATIONAL, context.formatMessage(I18nConstants.NDJSON_EMPTY_LINE_WARNING), IssueSeverity.WARNING);
|
||||
res.add(vf);
|
||||
} else {
|
||||
res.add(processLine(lineCount, line));
|
||||
}
|
||||
start = cursor+1;
|
||||
} else if (cursor > start) {
|
||||
String line = source.substring(start, cursor);
|
||||
if (line.endsWith("\r")) {
|
||||
line = line.substring(0, line.length()-1);
|
||||
}
|
||||
if (Utilities.noString(line.trim())) {
|
||||
ValidatedFragment vf = new ValidatedFragment(ValidatedFragment.ITEM_NAME, null, null, false);
|
||||
logError(vf.getErrors(), "2024-06-30", lineCount+1, 1, null, IssueType.INFORMATIONAL, context.formatMessage(I18nConstants.NDJSON_EMPTY_LINE_WARNING), IssueSeverity.WARNING);
|
||||
res.add(vf);
|
||||
} else {
|
||||
res.add(processLine(lineCount, line));
|
||||
}
|
||||
start = cursor+1;
|
||||
}
|
||||
lineCount++;
|
||||
cursor++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(Element e, OutputStream stream, OutputStyle style, String identity) throws FHIRException, IOException {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ public class ValidatedFragment {
|
|||
@Getter
|
||||
private final boolean isDerivedContent;
|
||||
public final static String FOCUS_NAME = "focus";
|
||||
public final static String ITEM_NAME = "item";
|
||||
|
||||
@Getter
|
||||
private List<ValidationMessage> errors = new ArrayList<>();
|
||||
|
|
|
@ -61,16 +61,15 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
i++;
|
||||
if (i >= start) {
|
||||
if (be.has("fullUrl")) {
|
||||
root.an(context.prefixAnchor(makeInternalBundleLink(be.primitiveValue("fullUrl"))));
|
||||
root.an(context.prefixAnchor(makeInternalBundleLink(b, be.primitiveValue("fullUrl"))));
|
||||
}
|
||||
if (be.has("resource")) {
|
||||
if (be.child("resource").has("id")) {
|
||||
root.an(context.prefixAnchor(be.child("resource").fhirType() + "_" + be.child("resource").primitiveValue("id")));
|
||||
root.an(context.prefixAnchor("hc"+be.child("resource").fhirType() + "_" + be.child("resource").primitiveValue("id")));
|
||||
} else {
|
||||
String id = makeIdFromBundleEntry(be.primitiveValue("fullUrl"));
|
||||
root.an(context.prefixAnchor(be.child("resource").fhirType() + "_" + id));
|
||||
root.an(context.prefixAnchor("hc"+be.child("resource").fhirType() + "_" + id));
|
||||
String id = be.child("resource").has("id") ? be.child("resource").primitiveValue("id") : makeIdFromBundleEntry(be.primitiveValue("fullUrl"));
|
||||
String anchor = be.child("resource").fhirType() + "_" + id;
|
||||
if (id != null && !context.hasAnchor(anchor)) {
|
||||
context.addAnchor(anchor);
|
||||
root.an(context.prefixAnchor(anchor));
|
||||
root.an(context.prefixAnchor("hc"+anchor));
|
||||
}
|
||||
}
|
||||
root.hr();
|
||||
|
@ -237,31 +236,31 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
return !b.getEntry().isEmpty();
|
||||
}
|
||||
|
||||
private List<XhtmlNode> checkInternalLinks(Bundle b, List<XhtmlNode> childNodes) {
|
||||
scanNodesForInternalLinks(b, childNodes);
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private void scanNodesForInternalLinks(Bundle b, List<XhtmlNode> nodes) {
|
||||
for (XhtmlNode n : nodes) {
|
||||
if ("a".equals(n.getName()) && n.hasAttribute("href")) {
|
||||
scanInternalLink(b, n);
|
||||
}
|
||||
scanNodesForInternalLinks(b, n.getChildNodes());
|
||||
}
|
||||
}
|
||||
|
||||
private void scanInternalLink(Bundle b, XhtmlNode n) {
|
||||
boolean fix = false;
|
||||
for (BundleEntryComponent be : b.getEntry()) {
|
||||
if (be.hasFullUrl() && be.getFullUrl().equals(n.getAttribute("href"))) {
|
||||
fix = true;
|
||||
}
|
||||
}
|
||||
if (fix) {
|
||||
n.setAttribute("href", "#"+makeInternalBundleLink(n.getAttribute("href")));
|
||||
}
|
||||
}
|
||||
// private List<XhtmlNode> checkInternalLinks(Bundle b, List<XhtmlNode> childNodes) {
|
||||
// scanNodesForInternalLinks(b, childNodes);
|
||||
// return childNodes;
|
||||
// }
|
||||
//
|
||||
// private void scanNodesForInternalLinks(Bundle b, List<XhtmlNode> nodes) {
|
||||
// for (XhtmlNode n : nodes) {
|
||||
// if ("a".equals(n.getName()) && n.hasAttribute("href")) {
|
||||
// scanInternalLink(b, n);
|
||||
// }
|
||||
// scanNodesForInternalLinks(b, n.getChildNodes());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void scanInternalLink(Bundle b, XhtmlNode n) {
|
||||
// boolean fix = false;
|
||||
// for (BundleEntryComponent be : b.getEntry()) {
|
||||
// if (be.hasFullUrl() && be.getFullUrl().equals(n.getAttribute("href"))) {
|
||||
// fix = true;
|
||||
// }
|
||||
// }
|
||||
// if (fix) {
|
||||
// n.setAttribute("href", "#"+makeInternalBundleLink(b, n.getAttribute("href")));
|
||||
// }
|
||||
// }
|
||||
|
||||
private void renderSearch(XhtmlNode root, ResourceWrapper search) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
|
|
@ -291,7 +291,7 @@ public class ObligationsRenderer extends Renderer {
|
|||
} else {
|
||||
Piece piece = gen.new Piece("table").attr("class", "grid");
|
||||
c.getPieces().add(piece);
|
||||
renderTable(status, res, piece.getChildren(), false, gen.getDefPath(), gen.getAnchorPrefix(), inScopeElements);
|
||||
renderTable(status, res, piece.getChildren(), false, gen.getDefPath(), gen.getUniqueLocalPrefix(), inScopeElements);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
if (doOpts) {
|
||||
x.b().tx(context.formatPhrase(RenderingContext.QUEST_STRUCT));
|
||||
}
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "");
|
||||
TableModel model = gen.new TableModel("qtree="+q.getId(), context.getRules() == GenerationRules.IG_PUBLISHER);
|
||||
model.setAlternating(true);
|
||||
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
|
||||
|
@ -493,7 +493,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
}
|
||||
|
||||
private void renderLogic(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRException, IOException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "");
|
||||
TableModel model = gen.new TableModel("qtree="+q.getId(), true);
|
||||
model.setAlternating(true);
|
||||
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
public void renderTree(RenderingStatus status, XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "");
|
||||
TableModel model = gen.new TableModel("qtree="+qr.getId(), false);
|
||||
model.setAlternating(true);
|
||||
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
|
||||
|
|
|
@ -792,8 +792,21 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
public static String makeInternalBundleLink(String fullUrl) {
|
||||
return fullUrl.replace(":", "-");
|
||||
public static String makeInternalBundleLink(ResourceWrapper bundle, String fullUrl) {
|
||||
// are we in a bundle in a bundle? Then the link is scoped
|
||||
boolean inBundle = false;
|
||||
ResourceWrapper rw = bundle.parent();
|
||||
while (rw != null) {
|
||||
if (rw.fhirType().equals("Bundle")) {
|
||||
inBundle = true;
|
||||
}
|
||||
rw = rw.parent();
|
||||
}
|
||||
if (inBundle) {
|
||||
return bundle.getScopedId()+"/"+fullUrl.replace(":", "-");
|
||||
} else {
|
||||
return fullUrl.replace(":", "-");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canRender(Resource resource) {
|
||||
|
|
|
@ -112,7 +112,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
renderDict(status, sd, sd.getDifferential().getElement(), x.table("dict"), false, GEN_MODE_DIFF, "", r);
|
||||
} else {
|
||||
x.getChildNodes().add(generateTable(status, context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false,
|
||||
context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context, "", r));
|
||||
context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context.withUniqueLocalPrefix(null), "r", r));
|
||||
}
|
||||
status.setExtensions(true);
|
||||
}
|
||||
|
@ -322,6 +322,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
private List<String> keyRows = new ArrayList<>();
|
||||
private Map<String, Map<String, ElementDefinition>> sdMapCache = new HashMap<>();
|
||||
private IMarkdownProcessor hostMd;
|
||||
private Map<String, Integer> anchors = new HashMap<>();
|
||||
|
||||
|
||||
public Map<String, Map<String, ElementDefinition>> getSdMapCache() {
|
||||
|
@ -492,8 +493,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
// return null;
|
||||
}
|
||||
|
||||
public XhtmlNode generateGrid(String defFile, StructureDefinition profile, String imageFolder, boolean inlineGraphics, String profileBaseFileName, String corePath, String imagePath, Set<String> outputTracker) throws IOException, FHIRException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true);
|
||||
public XhtmlNode generateGrid(String defFile, StructureDefinition profile, String imageFolder, boolean inlineGraphics, String profileBaseFileName, String corePath, String imagePath, Set<String> outputTracker) throws IOException, FHIRException {
|
||||
anchors.clear();
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, "g");
|
||||
TableModel model = gen.initGridTable(corePath, profile.getId());
|
||||
List<ElementDefinition> list = profile.getSnapshot().getElement();
|
||||
List<StructureDefinition> profiles = new ArrayList<StructureDefinition>();
|
||||
|
@ -532,10 +534,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
public XhtmlNode generateTable(RenderingStatus status, String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath,
|
||||
boolean logicalModel, boolean allInvariants, Set<String> outputTracker, boolean mustSupport, RenderingContext rc, String anchorPrefix, ResourceWrapper res) throws IOException, FHIRException {
|
||||
assert(diff != snapshot);// check it's ok to get rid of one of these
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defFile, anchorPrefix);
|
||||
anchors.clear();
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defFile, rc.getUniqueLocalPrefix());
|
||||
|
||||
gen.setUniqueLocalPrefix(context.getUniqueLocalPrefix());
|
||||
|
||||
List<ElementDefinition> list;
|
||||
if (diff)
|
||||
list = supplementMissingDiffElements(profile);
|
||||
|
@ -710,9 +711,12 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
// return;
|
||||
|
||||
if (!onlyInformationIsMapping(all, element)) {
|
||||
Row row = gen.new Row();
|
||||
row.setId(element.getPath());
|
||||
row.setAnchor(element.getPath());
|
||||
Row row = gen.new Row();
|
||||
// in deeply sliced things, there can be duplicate paths that are not usefully differentiated by id, and anyway, we want path
|
||||
String anchor = element.getPath();
|
||||
anchor = makeAnchorUnique(anchor);
|
||||
row.setId(anchor);
|
||||
row.setAnchor(anchor);
|
||||
row.setColor(context.getProfileUtilities().getRowColor(element, isConstraintMode));
|
||||
if (element.hasSlicing())
|
||||
row.setLineColor(1);
|
||||
|
@ -830,9 +834,10 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
} else {
|
||||
if (slicingRow != originalRow && !children.isEmpty()) {
|
||||
// we've entered a slice; we're going to create a holder row for the slice children
|
||||
Row hrow = gen.new Row();
|
||||
hrow.setId(element.getPath());
|
||||
hrow.setAnchor(element.getPath());
|
||||
Row hrow = gen.new Row();
|
||||
String anchorE = makeAnchorUnique(element.getPath());
|
||||
hrow.setId(anchorE);
|
||||
hrow.setAnchor(anchorE);
|
||||
hrow.setColor(context.getProfileUtilities().getRowColor(element, isConstraintMode));
|
||||
hrow.setLineColor(1);
|
||||
hrow.setIcon("icon_element.gif", context.formatPhrase(RenderingContext.TEXT_ICON_ELEMENT));
|
||||
|
@ -857,8 +862,10 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
if (typesRow != null && !children.isEmpty()) {
|
||||
// we've entered a typing slice; we're going to create a holder row for the all types children
|
||||
Row hrow = gen.new Row();
|
||||
hrow.setId(element.getPath());
|
||||
hrow.setAnchor(element.getPath());
|
||||
String anchorE = element.getPath();
|
||||
anchorE = makeAnchorUnique(anchorE);
|
||||
hrow.setId(anchorE);
|
||||
hrow.setAnchor(anchorE);
|
||||
hrow.setColor(context.getProfileUtilities().getRowColor(element, isConstraintMode));
|
||||
hrow.setLineColor(1);
|
||||
hrow.setIcon("icon_element.gif", context.formatPhrase(RenderingContext.TEXT_ICON_ELEMENT));
|
||||
|
@ -890,8 +897,10 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
// ok, we're a slice
|
||||
if (slicer == null || !slicer.getId().equals(child.getPath())) {
|
||||
parent = gen.new Row();
|
||||
parent.setId(child.getPath());
|
||||
parent.setAnchor(child.getPath());
|
||||
String anchorE = child.getPath();
|
||||
anchorE = makeAnchorUnique(anchorE);
|
||||
parent.setId(anchorE);
|
||||
parent.setAnchor(anchorE);
|
||||
parent.setColor(context.getProfileUtilities().getRowColor(child, isConstraintMode));
|
||||
parent.setLineColor(1);
|
||||
parent.setIcon("icon_slice.png", context.formatPhrase(RenderingContext.TEXT_ICON_SLICE));
|
||||
|
@ -934,6 +943,17 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
return slicingRow;
|
||||
}
|
||||
|
||||
private String makeAnchorUnique(String anchor) {
|
||||
if (anchors.containsKey(anchor)) {
|
||||
int c = anchors.get(anchor)+1;
|
||||
anchors.put(anchor, c);
|
||||
anchor = anchor+"."+c;
|
||||
} else {
|
||||
anchors.put(anchor, 1);
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
||||
private boolean isTypeSlice(ElementDefinition child) {
|
||||
|
@ -2107,7 +2127,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
if (!onlyInformationIsMapping(all, element)) {
|
||||
Row row = gen.new Row();
|
||||
row.setId(s);
|
||||
row.setAnchor(element.getPath());
|
||||
String anchor = element.getPath();
|
||||
anchor = makeAnchorUnique(anchor);
|
||||
row.setAnchor(anchor);
|
||||
row.setColor(context.getProfileUtilities().getRowColor(element, isConstraintMode));
|
||||
if (element.hasSlicing())
|
||||
row.setLineColor(1);
|
||||
|
@ -3034,8 +3056,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
|
||||
public XhtmlNode generateSpanningTable(StructureDefinition profile, String imageFolder, boolean onlyConstraints, String constraintPrefix, Set<String> outputTracker) throws IOException, FHIRException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, false, true, "", "");
|
||||
public XhtmlNode generateSpanningTable(StructureDefinition profile, String imageFolder, boolean onlyConstraints, String constraintPrefix, Set<String> outputTracker, String anchorPrefix) throws IOException, FHIRException {
|
||||
anchors.clear();
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, false, true, "", anchorPrefix);
|
||||
TableModel model = initSpanningTable(gen, "", false, profile.getId());
|
||||
Set<String> processed = new HashSet<String>();
|
||||
SpanEntry span = buildSpanningTable("(focus)", "", profile, processed, onlyConstraints, constraintPrefix);
|
||||
|
@ -3139,6 +3162,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
public XhtmlNode generateExtensionTable(RenderingStatus status, String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set<String> outputTracker, RenderingContext rc, String defPath, String anchorPrefix, ResourceWrapper res) throws IOException, FHIRException {
|
||||
anchors.clear();
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defPath, anchorPrefix);
|
||||
TableModel model = gen.initNormalTable(corePath, false, true, ed.getId()+(full ? "f" : "n"), true, TableGenerationMode.XHTML);
|
||||
|
||||
|
|
|
@ -1025,7 +1025,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
}
|
||||
x.br();
|
||||
x.tx(s);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "exp");
|
||||
TableModel model = gen.new TableModel("exp.h="+index, context.getRules() == GenerationRules.IG_PUBLISHER);
|
||||
model.setAlternating(true);
|
||||
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_CODE), context.formatPhrase(RenderingContext.VALUE_SET_CODE_ITEM), null, 0));
|
||||
|
|
|
@ -273,6 +273,7 @@ public class RenderingContext extends RenderingI18nContext {
|
|||
private int base64Limit = 1024;
|
||||
private boolean shortPatientForm;
|
||||
private String uniqueLocalPrefix;
|
||||
private Set<String> anchors = new HashSet<>();
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -1004,4 +1005,11 @@ public class RenderingContext extends RenderingI18nContext {
|
|||
return self;
|
||||
}
|
||||
|
||||
public boolean hasAnchor(String anchor) {
|
||||
return anchors.contains(anchor);
|
||||
}
|
||||
|
||||
public void addAnchor(String anchor) {
|
||||
anchors.add(anchor);
|
||||
}
|
||||
}
|
|
@ -569,7 +569,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
}
|
||||
if (cs != null && cs.hasSupplements()) {
|
||||
String msg = context.formatMessage(I18nConstants.CODESYSTEM_CS_NO_SUPPLEMENT, cs.getUrl());
|
||||
return new ValidationResult(IssueSeverity.ERROR, msg, makeIssue(IssueSeverity.ERROR, IssueType.NOTFOUND, path, msg, OpIssueCode.VSProcessing, null));
|
||||
return new ValidationResult(IssueSeverity.ERROR, msg, makeIssue(IssueSeverity.ERROR, IssueType.INVALID, path+".system", msg, OpIssueCode.InvalidData, null));
|
||||
}
|
||||
if (cs!=null && cs.getContent() != CodeSystemContentMode.COMPLETE) {
|
||||
warningMessage = "Resolved system "+system+(cs.hasVersion() ? " (v"+cs.getVersion()+")" : "")+", but the definition ";
|
||||
|
|
|
@ -1091,4 +1091,5 @@ public class I18nConstants {
|
|||
public static final String IG_DEPENDENCY_VERSION_WARNING = "IG_DEPENDENCY_VERSION_WARNING";
|
||||
public static final String IG_DEPENDENCY_EXCEPTION = "IG_DEPENDENCY_EXCEPTION";
|
||||
public static final String IG_DEPENDENCY_PACKAGE_UNKNOWN = "IG_DEPENDENCY_PACKAGE_UNKNOWN";
|
||||
public static final String NDJSON_EMPTY_LINE_WARNING = "NDJSON_EMPTY_LINE_WARNING";
|
||||
}
|
||||
|
|
|
@ -51,12 +51,12 @@ public class JsonLexer {
|
|||
private boolean isUnquoted;
|
||||
private String sourceName;
|
||||
|
||||
public JsonLexer(String source, boolean allowComments, boolean allowUnquotedStrings) throws IOException {
|
||||
public JsonLexer(String source, boolean allowComments, boolean allowUnquotedStrings, int line) throws IOException {
|
||||
this.source = source;
|
||||
this.allowComments = allowComments;
|
||||
this.allowUnquotedStrings = allowUnquotedStrings;
|
||||
cursor = -1;
|
||||
location = new JsonLocationData(1, 1);
|
||||
location = new JsonLocationData(line+1, 1);
|
||||
start();
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,15 @@ import org.hl7.fhir.utilities.json.parser.JsonLexer.TokenType;
|
|||
*/
|
||||
public class JsonParser {
|
||||
|
||||
protected JsonParser() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected JsonParser(int line) {
|
||||
super();
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(InputStream stream) throws IOException, JsonException {
|
||||
return new JsonParser().parseJsonObject(TextFile.streamToString(stream), false, false);
|
||||
}
|
||||
|
@ -107,6 +116,10 @@ public class JsonParser {
|
|||
return new JsonParser().parseJsonObject(source, isJson5, allowDuplicates);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(String source, boolean isJson5, boolean allowDuplicates, int line) throws IOException, JsonException {
|
||||
return new JsonParser(line).parseJsonObject(source, isJson5, allowDuplicates);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
|
||||
public static JsonElement parse(InputStream stream) throws IOException, JsonException {
|
||||
|
@ -221,6 +234,7 @@ public class JsonParser {
|
|||
private boolean itemUnquoted;
|
||||
private boolean valueUnquoted;
|
||||
private String sourceName;
|
||||
private int line = 0;
|
||||
|
||||
private JsonObject parseJsonObject(String source, boolean isJson5, boolean allowDuplicates) throws IOException, JsonException {
|
||||
this.allowDuplicates = allowDuplicates;
|
||||
|
@ -231,7 +245,7 @@ public class JsonParser {
|
|||
}
|
||||
|
||||
private JsonObject parseSource(String source) throws IOException, JsonException {
|
||||
lexer = new JsonLexer(source, allowComments, allowUnquotedStrings);
|
||||
lexer = new JsonLexer(source, allowComments, allowUnquotedStrings, line);
|
||||
lexer.setSourceName(sourceName);
|
||||
JsonObject result = new JsonObject();
|
||||
lexer.takeComments(result);
|
||||
|
@ -249,8 +263,14 @@ public class JsonParser {
|
|||
if (lexer.getType() != TokenType.Close) {
|
||||
parseProperty();
|
||||
readObject("$", result, true);
|
||||
result.setEnd(endProperty != null ? endProperty.copy() : lexer.getLocation().copy());
|
||||
} else {
|
||||
result.setEnd(endProperty != null ? endProperty.copy() : lexer.getLocation().copy());
|
||||
lexer.next();
|
||||
}
|
||||
if (lexer.getType() != TokenType.Eof) {
|
||||
throw lexer.error("Unexpected content at end of JSON: "+lexer.getType().toString());
|
||||
}
|
||||
result.setEnd(endProperty != null ? endProperty.copy() : lexer.getLocation().copy());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -263,7 +283,7 @@ public class JsonParser {
|
|||
}
|
||||
|
||||
private JsonElement parseSourceElement(String source) throws IOException, JsonException {
|
||||
lexer = new JsonLexer(source, allowComments, allowUnquotedStrings);
|
||||
lexer = new JsonLexer(source, allowComments, allowUnquotedStrings, line);
|
||||
switch (lexer.getType()) {
|
||||
case Boolean:
|
||||
JsonBoolean bool = new JsonBoolean(lexer.getValue().equals("true"));
|
||||
|
|
|
@ -618,7 +618,6 @@ public class HierarchicalTableGenerator {
|
|||
private String dest;
|
||||
private boolean makeTargets;
|
||||
private String defPath = "";
|
||||
private String anchorPrefix = "";
|
||||
|
||||
/**
|
||||
* There are circumstances where the table has to present in the absence of a stable supporting infrastructure.
|
||||
|
@ -637,6 +636,12 @@ public class HierarchicalTableGenerator {
|
|||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String uniqueLocalPrefix) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
this.uniqueLocalPrefix = uniqueLocalPrefix;
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
|
@ -646,29 +651,34 @@ public class HierarchicalTableGenerator {
|
|||
checkSetup();
|
||||
}
|
||||
|
||||
public String getDefPath() {
|
||||
return defPath;
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, String uniqueLocalPrefix) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
this.dest = dest;
|
||||
this.inLineGraphics = inlineGraphics;
|
||||
this.makeTargets = true;
|
||||
this.uniqueLocalPrefix = uniqueLocalPrefix;
|
||||
checkSetup();
|
||||
}
|
||||
|
||||
public String getAnchorPrefix() {
|
||||
return anchorPrefix;
|
||||
}
|
||||
|
||||
private void checkSetup() {
|
||||
if (dest == null) {
|
||||
throw new Error("what");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets, String defPath, String anchorPrefix) {
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets, String defPath, String uniqueLocalPrefix) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
this.dest = dest;
|
||||
this.inLineGraphics = inlineGraphics;
|
||||
this.makeTargets = makeTargets;
|
||||
this.defPath = defPath;
|
||||
this.anchorPrefix = anchorPrefix;
|
||||
this.uniqueLocalPrefix = uniqueLocalPrefix;
|
||||
checkSetup();
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets, String uniqueLocalPrefix) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
this.dest = dest;
|
||||
this.inLineGraphics = inlineGraphics;
|
||||
this.makeTargets = makeTargets;
|
||||
this.uniqueLocalPrefix = uniqueLocalPrefix;
|
||||
checkSetup();
|
||||
}
|
||||
|
||||
|
@ -681,6 +691,16 @@ public class HierarchicalTableGenerator {
|
|||
checkSetup();
|
||||
}
|
||||
|
||||
private void checkSetup() {
|
||||
if (dest == null) {
|
||||
throw new Error("what");
|
||||
}
|
||||
}
|
||||
|
||||
public String getDefPath() {
|
||||
return defPath;
|
||||
}
|
||||
|
||||
public TableModel initNormalTable(String prefix, boolean isLogical, boolean alternating, String id, boolean isActive, TableGenerationMode mode) throws IOException {
|
||||
this.mode = mode;
|
||||
|
||||
|
@ -1141,6 +1161,9 @@ public class HierarchicalTableGenerator {
|
|||
}
|
||||
|
||||
public void setUniqueLocalPrefix(String uniqueLocalPrefix) {
|
||||
if (Utilities.noString(uniqueLocalPrefix)) {
|
||||
throw new Error("what?");
|
||||
}
|
||||
this.uniqueLocalPrefix = uniqueLocalPrefix;
|
||||
}
|
||||
|
||||
|
|
|
@ -1119,3 +1119,4 @@ IG_DEPENDENCY_PACKAGE_UNKNOWN = The package {0} could not be found so the versio
|
|||
IG_DEPENDENCY_VERSION_ERROR = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. Use the package {3} instead
|
||||
IG_DEPENDENCY_VERSION_WARNING = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. In general, this version mismatch should be avoided - some tools will try to make this work with variable degrees of success, but others will not even try
|
||||
IG_DEPENDENCY_EXCEPTION = Exception checking package version consistency: {0}
|
||||
NDJSON_EMPTY_LINE_WARNING = The NDJSON source contains an empty line. This may not be accepted by some processors
|
||||
|
|
|
@ -208,6 +208,8 @@ public class IgLoader implements IValidationEngineLoader {
|
|||
res.setFocus(t.getValue());
|
||||
if (t.getKey().endsWith(".json"))
|
||||
res.setCntType(Manager.FhirFormat.JSON);
|
||||
else if (t.getKey().endsWith(".ndjson"))
|
||||
res.setCntType(Manager.FhirFormat.NDJSON);
|
||||
else if (t.getKey().endsWith(".xml"))
|
||||
res.setCntType(Manager.FhirFormat.XML);
|
||||
else if (t.getKey().endsWith(".ttl"))
|
||||
|
|
|
@ -36,7 +36,7 @@ public class ResourceChecker {
|
|||
return null;
|
||||
}
|
||||
if (guessFromExtension) {
|
||||
String ext = Utilities.getFileExtension(filename);
|
||||
String ext = Utilities.getFileExtension(filename).toLowerCase();
|
||||
if (Utilities.existsInList(ext, "xml")) {
|
||||
return FhirFormat.XML;
|
||||
}
|
||||
|
@ -49,6 +49,9 @@ public class ResourceChecker {
|
|||
if (Utilities.existsInList(ext, "jwt", "jws")) {
|
||||
return Manager.FhirFormat.SHC;
|
||||
}
|
||||
if (Utilities.existsInList(ext, "ndjson")) {
|
||||
return Manager.FhirFormat.NDJSON;
|
||||
}
|
||||
if (Utilities.existsInList(ext, "json")) {
|
||||
if (cnt.length > 2048) {
|
||||
return FhirFormat.JSON;
|
||||
|
@ -86,6 +89,14 @@ public class ResourceChecker {
|
|||
System.out.println("Not JSON: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
try {
|
||||
Manager.parse(context, new ByteArrayInputStream(cnt), Manager.FhirFormat.NDJSON);
|
||||
return Manager.FhirFormat.NDJSON;
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
System.out.println("Not NDJSON: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
try {
|
||||
ValidatorUtils.parseXml(cnt);
|
||||
return Manager.FhirFormat.XML;
|
||||
|
|
|
@ -559,7 +559,6 @@ public class StructureMapValidator extends BaseValidator {
|
|||
private boolean validateRule(List<ValidationMessage> errors, Element src, Element group, Element rule, NodeStack stack, VariableSet variables) {
|
||||
String name = rule.getChildValue("name");
|
||||
boolean ok = rule(errors, "2023-03-01", IssueType.INVALID, rule.line(), rule.col(), stack.getLiteralPath(), idIsValid(name), I18nConstants.SM_NAME_INVALID, name);
|
||||
|
||||
RuleInformation ruleInfo = new RuleInformation();
|
||||
// process the sources
|
||||
VariableSet lvars = variables.copy();
|
||||
|
@ -691,7 +690,61 @@ public class StructureMapValidator extends BaseValidator {
|
|||
private boolean validateRuleTarget(List<ValidationMessage> errors, Element src, Element group, Element rule, Element target, NodeStack stack, VariableSet variables, RuleInformation ruleInfo) {
|
||||
String context = target.getChildValue("context");
|
||||
if (context == null) {
|
||||
return true;
|
||||
// this would be something like
|
||||
// RNDSEntry -> create('Composition') as IPSComposition
|
||||
|
||||
boolean ok = true;
|
||||
|
||||
VariableDefn vn = null;
|
||||
String variable = target.getChildValue("variable");
|
||||
if (variable != null) {
|
||||
if (rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), idIsValid(variable), I18nConstants.SM_NAME_INVALID, variable)) {
|
||||
vn = variables.add(variable, "target"); // may overwrite
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
String transform = target.getChildValue("transform");
|
||||
List<Element> params = target.getChildren("parameter");
|
||||
String type = null;
|
||||
switch (transform) {
|
||||
case "create":
|
||||
if (rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), params.size() < 2, I18nConstants.SM_TARGET_TRANSFORM_PARAM_COUNT_RANGE, "create", "0", "1", params.size())) {
|
||||
if (params.size() == 1) {
|
||||
type = params.get(0).getChildValue("value");
|
||||
// type can be a url, a native type, or an alias
|
||||
if (!Utilities.isAbsoluteUrl(type)) {
|
||||
type = resolveType(type, "target", src);
|
||||
if (!Utilities.isAbsoluteUrl(type)) {
|
||||
StructureDefinition sdt = this.context.fetchTypeDefinition(type);
|
||||
if (sdt != null) {
|
||||
type = sdt.getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
warning(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(),type != null, I18nConstants.SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE, "create");
|
||||
} else {
|
||||
// maybe can guess? maybe not ... type =
|
||||
}
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case "uuid" :
|
||||
ok = rule(errors, "2023-05-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), params.size() == 0, I18nConstants.SM_TARGET_TRANSFORM_MISSING_PARAMS, transform) && ok;
|
||||
type = "string";
|
||||
break;
|
||||
default:
|
||||
rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), false, I18nConstants.SM_TARGET_TRANSFORM_NOT_CHECKED, transform);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (vn != null && type != null) {
|
||||
StructureDefinition sdt = this.context.fetchTypeDefinition(type);
|
||||
vn.setType(ruleInfo.getMaxCount(), sdt, sdt.getSnapshot().getElementFirstRep(), null); // may overwrite
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
boolean ok = rule(errors, "2023-03-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), idIsValid(context), I18nConstants.SM_NAME_INVALID, context) &&
|
||||
rule(errors, "2023-03-01", IssueType.UNKNOWN, target.line(), target.col(), stack.getLiteralPath(), variables.hasVariable(context, TARGET), I18nConstants.SM_TARGET_CONTEXT_UNKNOWN, context);
|
||||
|
@ -805,7 +858,7 @@ public class StructureMapValidator extends BaseValidator {
|
|||
case "append" :
|
||||
ok = rule(errors, "2023-05-01", IssueType.INVALID, target.line(), target.col(), stack.getLiteralPath(), params.size() > 0, I18nConstants.SM_TARGET_TRANSFORM_MISSING_PARAMS, transform) && ok;
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
ok = checkParamExistsOrPrimitive(errors, params.get(1).getNamedChild("value", false), "cc", "parameter "+i, target, variables, stack, ok, false);
|
||||
ok = checkParamExistsOrPrimitive(errors, params.get(i).getNamedChild("value", false), "cc", "parameter "+i, target, variables, stack, ok, false);
|
||||
}
|
||||
break;
|
||||
case "uuid" :
|
||||
|
|
|
@ -687,7 +687,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
|
||||
private OperationOutcomeIssueComponent findMatchingIssue(OperationOutcome oo, OperationOutcomeIssueComponent iss) {
|
||||
for (OperationOutcomeIssueComponent t : oo.getIssue()) {
|
||||
if (t.getExpression().get(0).getValue().equals(iss.getExpression().get(0).getValue()) &&
|
||||
if (
|
||||
(t.hasExpression() && iss.hasExpression() && t.getExpression().get(0).getValue().equals(iss.getExpression().get(0).getValue())
|
||||
|| (!t.hasExpression() && !iss.hasExpression())) &&
|
||||
t.getCode() == iss.getCode() && t.getSeverity() == iss.getSeverity() &&
|
||||
(t.hasDiagnostics() ? t.getDiagnostics().equals(iss.getDiagnostics()) : !iss.hasDiagnostics()) &&
|
||||
(t.getExtensionString(ToolingExtensions.EXT_ISSUE_SERVER) != null ? t.getExtensionString(ToolingExtensions.EXT_ISSUE_SERVER).equals(iss.getExtensionString(ToolingExtensions.EXT_ISSUE_SERVER)) : iss.getExtensionString(ToolingExtensions.EXT_ISSUE_SERVER) == null) &&
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -21,7 +21,7 @@
|
|||
<commons_compress_version>1.26.0</commons_compress_version>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.5.12</validator_test_case_version>
|
||||
<validator_test_case_version>1.5.13-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.17.0</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue