Merge remote-tracking branch 'origin/master' into do-20240122-base-engine
This commit is contained in:
commit
b24fb10f54
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1657,7 +1657,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
r.getCells().add(gen.new Cell("", "", "Extension", null, null));
|
||||
r.setIcon("icon_"+m+"extension_complex.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_COMPLEX);
|
||||
|
||||
|
||||
for (ElementDefinition c : children) {
|
||||
ved = getValueFor(ed, c);
|
||||
ElementDefinition ued = getUrlFor(ed, c);
|
||||
|
@ -1697,7 +1697,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
c.addPiece(gen.new Piece("br")).addPiece(gen.new Piece(null, describeExtensionContext(ed), null));
|
||||
r.getCells().add(c);
|
||||
|
||||
|
||||
try {
|
||||
return gen.generate(model, corePath, 0, outputTracker);
|
||||
} catch (org.hl7.fhir.exceptions.FHIRException e) {
|
||||
|
@ -3484,7 +3484,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
TableModel model = initSpanningTable(gen, "", false, profile.getId());
|
||||
Set<String> processed = new HashSet<String>();
|
||||
SpanEntry span = buildSpanningTable("(focus)", "", profile, processed, onlyConstraints, constraintPrefix);
|
||||
|
||||
|
||||
genSpanEntry(gen, model.getRows(), span);
|
||||
return gen.generate(model, "", 0, outputTracker);
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
package org.hl7.fhir.dstu3.utils;
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -3236,7 +3236,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
case INEXACT : return "><";
|
||||
case UNMATCHED : return "-";
|
||||
case DISJOINT : return "!=";
|
||||
case NULL: return null;
|
||||
case NULL: return null;
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
@ -3708,6 +3708,7 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
inject(sd, x, NarrativeStatus.GENERATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean generate(ResourceContext rcontext, ImplementationGuide ig) throws EOperationOutcome, FHIRException, IOException {
|
||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||
x.h2().addText(ig.getName());
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1253,7 +1253,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);
|
||||
TableModel model = gen.initComparisonTable(corePath, id);
|
||||
genElementComp(null /* come back to this later */, gen, model.getRows(), comp.combined, corePath, prefix, null, true);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1268,7 +1268,7 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
|
|||
return sdr.generateTable(corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "i");
|
||||
}
|
||||
|
||||
private void genElementComp(String defPath, HierarchicalTableGenerator gen, List<Row> rows, StructuralMatch<ElementDefinitionNode> combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException {
|
||||
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 {
|
||||
Row originalRow = slicingRow;
|
||||
Row typesRow = null;
|
||||
|
||||
|
@ -1334,19 +1334,19 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
|
|||
nc = sdrRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName, null);
|
||||
}
|
||||
if (combined.hasLeft()) {
|
||||
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0), leftColor);
|
||||
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList<ElementDefinition>()), leftColor);
|
||||
} else {
|
||||
frame(spacers(row, 4, gen), leftColor);
|
||||
}
|
||||
if (combined.hasRight()) {
|
||||
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0), rightColor);
|
||||
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList<ElementDefinition>()), rightColor);
|
||||
} else {
|
||||
frame(spacers(row, 4, gen), rightColor);
|
||||
}
|
||||
row.getCells().add(cellForMessages(gen, combined.getMessages()));
|
||||
|
||||
for (StructuralMatch<ElementDefinitionNode> child : children) {
|
||||
genElementComp(defPath, gen, row.getSubRows(), child, corePath, prefix, originalRow, false);
|
||||
genElementComp(defPath, anchorPrefix, gen, row.getSubRows(), child, corePath, prefix, originalRow, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -611,18 +611,24 @@ public class Element extends Base implements NamedItem {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasPrimitiveValue() {
|
||||
return property.isPrimitiveName(name) || property.IsLogicalAndHasPrimitiveValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrimitiveValue() {
|
||||
//return property.isPrimitiveName(name) || property.IsLogicalAndHasPrimitiveValue(name);
|
||||
return super.hasPrimitiveValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHavePrimitiveValue() {
|
||||
return property.isPrimitiveName(name) || property.IsLogicalAndHasPrimitiveValue(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String primitiveValue() {
|
||||
if (isPrimitive() || value != null)
|
||||
return value;
|
||||
else {
|
||||
if (hasPrimitiveValue() && children != null) {
|
||||
if (canHavePrimitiveValue() && children != null) {
|
||||
for (Element c : children) {
|
||||
if (c.getName().equals("value"))
|
||||
return c.primitiveValue();
|
||||
|
|
|
@ -258,32 +258,70 @@ public abstract class Base implements Serializable, IBase, IElement {
|
|||
}
|
||||
|
||||
// these 3 allow evaluation engines to get access to primitive values
|
||||
|
||||
/**
|
||||
* @return true if the data type is a primitive type and might have a primitive value
|
||||
* (which will be accessed as a string, irrespective of the stated value)
|
||||
*/
|
||||
public boolean isPrimitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the type is boolean, and the primitive value can only be 'true' or 'false'
|
||||
*/
|
||||
public boolean isBooleanPrimitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPrimitiveValue() {
|
||||
return isPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the type is primitive, and there's value (e.g. no Data-Absent-Reason extension etc)
|
||||
*/
|
||||
public boolean hasPrimitiveValue() {
|
||||
return primitiveValue() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the type is primitive, and there could be a value (irrespective of whether it's present e.g. no Data-Absent-Reason extension etc)
|
||||
*/
|
||||
public boolean canHavePrimitiveValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the primitive value if there is one, as a string irrespective of the actual type (e.g. dates converted to their FHIR string representation)
|
||||
* return null if the value is not a primitive or there is no value (might be extensions instead)
|
||||
*/
|
||||
public String primitiveValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the type is date|dateTime|instant, and the primitive value is a date/time of some precision
|
||||
*/
|
||||
public boolean isDateTime() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the date/time value if there is one, or null
|
||||
*/
|
||||
public BaseDateTimeType dateTimeValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the FHIR type name of the instance (not the java class name)
|
||||
*/
|
||||
public abstract String fhirType() ;
|
||||
|
||||
|
||||
/**
|
||||
* Note that this is potentially misleading on ElementDefinition that has a 'type'
|
||||
* property - don't mistakenly use this thinking it's going to look at ElementDefinition.type
|
||||
*
|
||||
* @param name - fhir type name
|
||||
* @return- true if it 'has' this type (including by specialization)
|
||||
*/
|
||||
public boolean hasType(String... name) {
|
||||
String t = fhirType();
|
||||
for (String n : name) {
|
||||
|
|
|
@ -257,6 +257,11 @@ public abstract class PrimitiveType<T> extends DataType implements IPrimitiveTyp
|
|||
public boolean hasPrimitiveValue() {
|
||||
return StringUtils.isNotBlank(getValueAsString());
|
||||
}
|
||||
|
||||
public boolean canHavePrimitiveValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public String fpValue() {
|
||||
return primitiveValue();
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.fhir.ucum.Canonical;
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.conformance.profile.BindingResolution;
|
||||
|
@ -14,6 +15,7 @@ import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
|||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.r5.model.ActorDefinition;
|
||||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
|
@ -40,9 +42,9 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNodeList;
|
|||
|
||||
public class ObligationsRenderer {
|
||||
public static class ObligationDetail {
|
||||
private String code;
|
||||
private List<String> codes = new ArrayList<>();
|
||||
private List<String> elementIds = new ArrayList<>();
|
||||
private String actor;
|
||||
private List<CanonicalType> actors = new ArrayList<>();
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private String filter;
|
||||
|
@ -57,10 +59,11 @@ public class ObligationsRenderer {
|
|||
private int count = 1;
|
||||
|
||||
public ObligationDetail(Extension ext) {
|
||||
this.code = ext.getExtensionString("code");
|
||||
this.actor = ext.getExtensionString("actor");
|
||||
if (this.actor == null) {
|
||||
this.actor = ext.getExtensionString("actorId");
|
||||
for (Extension e: ext.getExtensionsByUrl("code")) {
|
||||
codes.add(e.getValueStringType().toString());
|
||||
}
|
||||
for (Extension e: ext.getExtensionsByUrl("actor")) {
|
||||
actors.add(e.getValueCanonicalType());
|
||||
}
|
||||
this.doco = ext.getExtensionString("documentation");
|
||||
this.docoShort = ext.getExtensionString("shortDoco");
|
||||
|
@ -80,7 +83,7 @@ public class ObligationsRenderer {
|
|||
|
||||
private String getKey() {
|
||||
// Todo: Consider extending this with content from usageContext if purpose isn't sufficiently differentiating
|
||||
return code + Integer.toString(count);
|
||||
return String.join(",", codes) + Integer.toString(count);
|
||||
}
|
||||
|
||||
private void incrementCount() {
|
||||
|
@ -96,8 +99,11 @@ public class ObligationsRenderer {
|
|||
public String getDoco(boolean full) {
|
||||
return full ? doco : docoShort;
|
||||
}
|
||||
public String getCode() {
|
||||
return code;
|
||||
public String getCodes() {
|
||||
return String.join(",", codes);
|
||||
}
|
||||
public List<String> getCodeList() {
|
||||
return new ArrayList<String>(codes);
|
||||
}
|
||||
public boolean unchanged() {
|
||||
if (!isUnchanged)
|
||||
|
@ -105,9 +111,9 @@ public class ObligationsRenderer {
|
|||
if (compare==null)
|
||||
return true;
|
||||
isUnchanged = true;
|
||||
isUnchanged = isUnchanged && ((code==null && compare.code==null) || code.equals(compare.code));
|
||||
isUnchanged = isUnchanged && ((codes.isEmpty() && compare.codes.isEmpty()) || codes.equals(compare.codes));
|
||||
isUnchanged = elementIds.equals(compare.elementIds);
|
||||
isUnchanged = isUnchanged && ((actor==null && compare.actor==null) || actor.equals(compare.actor));
|
||||
isUnchanged = isUnchanged && ((actors.isEmpty() && compare.actors.isEmpty()) || actors.equals(compare.actors));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((filter==null && compare.filter==null) || filter.equals(compare.filter));
|
||||
|
@ -136,12 +142,16 @@ public class ObligationsRenderer {
|
|||
return usage;
|
||||
}
|
||||
|
||||
public boolean hasActor() {
|
||||
return actor != null;
|
||||
public boolean hasActors() {
|
||||
return !actors.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasActor(String id) {
|
||||
return id.equals(actor);
|
||||
for (CanonicalType actor: actors) {
|
||||
if (actor.getValue().equals(id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,24 +286,24 @@ public class ObligationsRenderer {
|
|||
return abr;
|
||||
}
|
||||
|
||||
public String render() throws IOException {
|
||||
public String render(String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
|
||||
if (obligations.isEmpty()) {
|
||||
return "";
|
||||
} else {
|
||||
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
|
||||
tbl.attribute("class", "grid");
|
||||
renderTable(tbl.getChildNodes(), true);
|
||||
renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements);
|
||||
return new XhtmlComposer(false).compose(tbl);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderTable(HierarchicalTableGenerator gen, Cell c) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public void renderTable(HierarchicalTableGenerator gen, Cell c, List<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
|
||||
if (obligations.isEmpty()) {
|
||||
return;
|
||||
} else {
|
||||
Piece piece = gen.new Piece("table").attr("class", "grid");
|
||||
c.getPieces().add(piece);
|
||||
renderTable(piece.getChildren(), false);
|
||||
renderTable(piece.getChildren(), false, gen.getDefPath(), gen.getAnchorPrefix(), inScopeElements);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,10 +323,21 @@ public class ObligationsRenderer {
|
|||
}
|
||||
|
||||
private void renderObligationLI(XhtmlNodeList children, ObligationDetail ob) throws IOException {
|
||||
renderCode(children, ob.getCode());
|
||||
if (ob.hasFilter() || ob.hasUsage()) {
|
||||
renderCodes(children, ob.getCodeList());
|
||||
if (ob.hasFilter() || ob.hasUsage() || !ob.elementIds.isEmpty()) {
|
||||
children.tx(" (");
|
||||
boolean ffirst = !ob.hasFilter();
|
||||
boolean firstEid = true;
|
||||
|
||||
for (String eid: ob.elementIds) {
|
||||
if (firstEid) {
|
||||
children.span().i().tx("Elements: ");
|
||||
firstEid = false;
|
||||
} else
|
||||
children.tx(", ");
|
||||
String trimmedElement = eid.substring(eid.indexOf(".")+ 1);
|
||||
children.tx(trimmedElement);
|
||||
}
|
||||
if (ob.hasFilter()) {
|
||||
children.span(null, ob.getFilterDesc()).code().tx(ob.getFilter());
|
||||
}
|
||||
|
@ -337,20 +358,25 @@ public class ObligationsRenderer {
|
|||
}
|
||||
|
||||
|
||||
public void renderTable(List<XhtmlNode> children, boolean fullDoco) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public void renderTable(List<XhtmlNode> children, boolean fullDoco, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
|
||||
boolean doco = false;
|
||||
boolean usage = false;
|
||||
boolean actor = false;
|
||||
boolean filter = false;
|
||||
boolean elementId = false;
|
||||
for (ObligationDetail binding : obligations) {
|
||||
actor = actor || binding.actor!=null || (binding.compare!=null && binding.compare.actor !=null);
|
||||
actor = actor || !binding.actors.isEmpty() || (binding.compare!=null && !binding.compare.actors.isEmpty());
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || !binding.usage.isEmpty() || (binding.compare!=null && !binding.compare.usage.isEmpty());
|
||||
filter = filter || binding.filter != null || (binding.compare!=null && binding.compare.filter!=null);
|
||||
elementId = elementId || !binding.elementIds.isEmpty() || (binding.compare!=null && !binding.compare.elementIds.isEmpty());
|
||||
}
|
||||
|
||||
List<String> inScopePaths = new ArrayList<>();
|
||||
for (ElementDefinition e: inScopeElements) {
|
||||
inScopePaths.add(e.getPath());
|
||||
}
|
||||
|
||||
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
|
||||
children.add(tr);
|
||||
tr.td().style("font-size: 11px").b().tx(context.formatPhrase(RenderingContext.GENERAL_OBLIG));
|
||||
|
@ -379,43 +405,52 @@ public class ObligationsRenderer {
|
|||
children.add(tr);
|
||||
|
||||
XhtmlNode code = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.code.equals(ob.compare.code))
|
||||
if (ob.compare!=null && ob.getCodes().equals(ob.compare.getCodes()))
|
||||
code.style("font-color: darkgray");
|
||||
renderCode(code.getChildNodes(), ob.code);
|
||||
if (ob.compare!=null && ob.compare.code != null && !ob.code.equals(ob.compare.code)) {
|
||||
renderCodes(code.getChildNodes(), ob.getCodeList());
|
||||
if (ob.compare!=null && !ob.compare.getCodeList().isEmpty() && !ob.getCodes().equals(ob.compare.getCodes())) {
|
||||
code.br();
|
||||
code = code.span(STYLE_UNCHANGED, null);
|
||||
renderCode(code.getChildNodes(), ob.compare.code);
|
||||
renderCodes(code.getChildNodes(), ob.compare.getCodeList());
|
||||
}
|
||||
if (actor) {
|
||||
|
||||
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, ob.actor);
|
||||
ActorDefinition compAd = null;
|
||||
if (ob.compare!=null && ob.compare.actor!=null) {
|
||||
compAd = context.getContext().fetchResource(ActorDefinition.class, ob.compare.actor);
|
||||
XhtmlNode actorId = tr.td().style("font-size: 11px");
|
||||
if (!ob.actors.isEmpty() || ob.compare.actors.isEmpty()) {
|
||||
boolean firstActor = false;
|
||||
for (CanonicalType anActor : ob.actors) {
|
||||
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, anActor.toString());
|
||||
boolean existingActor = ob.compare != null && ob.compare.actors.contains(anActor);
|
||||
|
||||
if (!firstActor) {
|
||||
actorId.br();
|
||||
firstActor = true;
|
||||
}
|
||||
|
||||
if (!existingActor)
|
||||
actorId.style(STYLE_UNCHANGED);
|
||||
|
||||
}
|
||||
|
||||
XhtmlNode actorId = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.actor.equals(ob.compare.actor))
|
||||
actorId.style(STYLE_UNCHANGED);
|
||||
if (ad != null && ad.hasWebPath()) {
|
||||
actorId.ah(ad.getWebPath(), ob.actor).tx(ad.present());
|
||||
} else if (ad != null) {
|
||||
actorId.span(null, ob.actor).tx(ad.present());
|
||||
}
|
||||
|
||||
if (ob.compare!=null && ob.compare.actor!=null && !ob.actor.equals(ob.compare.actor)) {
|
||||
actorId.br();
|
||||
actorId = actorId.span(STYLE_REMOVED, null);
|
||||
if (compAd != null) {
|
||||
if (compAd.hasWebPath()) {
|
||||
actorId.ah(compAd.getWebPath(), ob.compare.actor).tx(compAd.present());
|
||||
} else {
|
||||
actorId.span(null, ob.compare.actor).tx(compAd.present());
|
||||
if (ob.compare != null) {
|
||||
for (CanonicalType compActor : ob.compare.actors) {
|
||||
if (!ob.actors.contains(compActor)) {
|
||||
ActorDefinition compAd = context.getContext().fetchResource(ActorDefinition.class, compActor.toString());
|
||||
if (!firstActor) {
|
||||
actorId.br();
|
||||
firstActor = true;
|
||||
}
|
||||
actorId = actorId.span(STYLE_REMOVED, null);
|
||||
if (compAd.hasWebPath()) {
|
||||
actorId.ah(compAd.getWebPath(), compActor.toString()).tx(compAd.present());
|
||||
} else {
|
||||
actorId.span(null, compActor.toString()).tx(compAd.present());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (elementId) {
|
||||
XhtmlNode elementIds = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.elementIds.equals(ob.compare.elementIds))
|
||||
|
@ -423,10 +458,13 @@ public class ObligationsRenderer {
|
|||
for (String eid : ob.elementIds) {
|
||||
elementIds.sep(", ");
|
||||
ElementDefinition ed = profile.getSnapshot().getElementById(eid);
|
||||
if (ed != null) {
|
||||
elementIds.ah("#"+eid).tx(ed.getName());
|
||||
boolean inScope = inScopePaths.contains(ed.getPath());
|
||||
String name = eid.substring(eid.indexOf(".") + 1);
|
||||
if (ed != null && inScope) {
|
||||
String link = defPath + "#" + anchorPrefix + eid;
|
||||
elementIds.ah(link).tx(name);
|
||||
} else {
|
||||
elementIds.code().tx(eid);
|
||||
elementIds.code().tx(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,10 +529,10 @@ public class ObligationsRenderer {
|
|||
return newS + "<br/><span style=\"" + STYLE_REMOVED + "\">" + oldS + "</span>";
|
||||
}
|
||||
|
||||
private void renderCode(XhtmlNodeList children, String codeExpr) {
|
||||
if (codeExpr != null) {
|
||||
private void renderCodes(XhtmlNodeList children, List<String> codes) {
|
||||
|
||||
if (!codes.isEmpty()) {
|
||||
boolean first = true;
|
||||
String[] codes = codeExpr.split("\\+");
|
||||
for (String code : codes) {
|
||||
if (first) first = false; else children.tx(" & ");
|
||||
int i = code.indexOf(":");
|
||||
|
@ -507,7 +545,7 @@ public class ObligationsRenderer {
|
|||
CodeResolution cr = this.cr.resolveCode("http://hl7.org/fhir/tools/CodeSystem/obligation", code);
|
||||
code = code.replace("will-", "").replace("can-", "");
|
||||
if (cr.getLink() != null) {
|
||||
children.ah(cr.getLink(), cr.getHint()).tx(code);
|
||||
children.ah(cr.getLink(), cr.getHint()).tx(code);
|
||||
} else {
|
||||
children.span(null, cr.getHint()).tx(code);
|
||||
}
|
||||
|
|
|
@ -549,7 +549,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
public XhtmlNode generateTable(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) 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);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defFile, anchorPrefix);
|
||||
|
||||
List<ElementDefinition> list;
|
||||
if (diff)
|
||||
|
@ -815,7 +815,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
genElementObligations(gen, element, columns, row, corePath, profile);
|
||||
break;
|
||||
case SUMMARY:
|
||||
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0);
|
||||
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0, defPath, anchorPrefix, all);
|
||||
break;
|
||||
}
|
||||
if (element.hasSlicing()) {
|
||||
|
@ -1078,7 +1078,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
|
||||
public List<Cell> genElementCells(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath,
|
||||
String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef,
|
||||
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis) throws IOException {
|
||||
boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
|
||||
List<Cell> res = new ArrayList<>();
|
||||
Cell gc = gen.new Cell();
|
||||
row.getCells().add(gc);
|
||||
|
@ -1121,7 +1121,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
if (extDefn == null) {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
res.add(addCell(row, gen.new Cell(null, null, "?gen-e1? "+element.getType().get(0).getProfile(), null, null)));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
|
||||
} else {
|
||||
String name = element.hasSliceName() ? element.getSliceName() : urltail(eurl);
|
||||
nameCell.getPieces().get(0).setText(name);
|
||||
|
@ -1134,7 +1134,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
else // if it's complex, we just call it nothing
|
||||
// genTypes(gen, row, extDefn.getSnapshot().getElement().get(0), profileBaseFileName, profile);
|
||||
res.add(addCell(row, gen.new Cell(null, null, "("+(context.formatPhrase(RenderingContext.STRUC_DEF_COMPLEX))+")", null, null)));
|
||||
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc));
|
||||
res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
|
||||
}
|
||||
} else {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
|
@ -1142,7 +1142,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
res.add(addCell(row, gen.new Cell()));
|
||||
else
|
||||
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
|
||||
}
|
||||
}
|
||||
} else if (element != null) {
|
||||
|
@ -1151,7 +1151,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
|
||||
else
|
||||
res.add(addCell(row, gen.new Cell()));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
|
||||
res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1309,10 +1309,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException {
|
||||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc);
|
||||
}
|
||||
|
||||
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException {
|
||||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, new ArrayList<ElementDefinition>());
|
||||
}
|
||||
|
||||
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List<ElementDefinition> inScopeElements) throws IOException, FHIRException {
|
||||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, inScopeElements);
|
||||
}
|
||||
|
||||
public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List<ElementDefinition> inScopeElements) throws IOException, FHIRException {
|
||||
Cell c = gen.new Cell();
|
||||
row.getCells().add(c);
|
||||
|
||||
|
@ -1691,7 +1695,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
if (!definition.getPath().contains(".") && profile.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
obr.seeObligations(profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS));
|
||||
}
|
||||
obr.renderTable(gen, c);
|
||||
obr.renderTable(gen, c, inScopeElements);
|
||||
|
||||
if (definition.hasMaxLength() && definition.getMaxLength()!=0) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
|
@ -3046,7 +3050,7 @@ 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);
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, false, true, "", "");
|
||||
TableModel model = initSpanningTable(gen, "", false, profile.getId());
|
||||
Set<String> processed = new HashSet<String>();
|
||||
SpanEntry span = buildSpanningTable("(focus)", "", profile, processed, onlyConstraints, constraintPrefix);
|
||||
|
@ -3149,8 +3153,8 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
return first ? null : x;
|
||||
}
|
||||
|
||||
public XhtmlNode generateExtensionTable(String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set<String> outputTracker, RenderingContext rc) throws IOException, FHIRException {
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true);
|
||||
public XhtmlNode generateExtensionTable(String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set<String> outputTracker, RenderingContext rc, String defPath, String anchorPrefix) throws IOException, FHIRException {
|
||||
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);
|
||||
|
||||
boolean deep = false;
|
||||
|
@ -3211,7 +3215,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
r1.getCells().add(gen.new Cell(null, null, describeCardinality(c, null, new UnusedTracker()), null, null));
|
||||
genTypes(gen, r1, ved, defFile, ed, corePath, imagePath, false, false);
|
||||
r1.setIcon("icon_"+m+"extension_simple.png", context.formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_SIMPLE));
|
||||
generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc);
|
||||
generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc, new ArrayList<ElementDefinition>());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -3324,7 +3328,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
if (isProfiledExtension(ec)) {
|
||||
StructureDefinition extDefn = context.getContext().fetchResource(StructureDefinition.class, ec.getType().get(0).getProfile().get(0).getValue());
|
||||
if (extDefn == null) {
|
||||
generateElementInner(t, sd, ec, 1, null, compareElement, null, false);
|
||||
generateElementInner(t, sd, ec, 1, null, compareElement, null, false, "", anchorPrefix, elements);
|
||||
} else {
|
||||
ElementDefinition valueDefn = getExtensionValueDefinition(extDefn);
|
||||
ElementDefinition compareValueDefn = null;
|
||||
|
@ -3332,15 +3336,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
StructureDefinition compareExtDefn = context.getContext().fetchResource(StructureDefinition.class, compareElement.getType().get(0).getProfile().get(0).getValue());
|
||||
compareValueDefn = getExtensionValueDefinition(extDefn);
|
||||
} catch (Exception except) {}
|
||||
generateElementInner(t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false);
|
||||
generateElementInner(t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false, "", anchorPrefix, elements);
|
||||
// generateElementInner(b, extDefn, extDefn.getSnapshot().getElement().get(0), valueDefn == null ? 2 : 3, valueDefn);
|
||||
}
|
||||
} else {
|
||||
while (!dstack.isEmpty() && !isParent(dstack.peek(), ec)) {
|
||||
finish(t, sd, dstack.pop(), mode);
|
||||
finish(t, sd, dstack.pop(), mode, "", anchorPrefix);
|
||||
}
|
||||
dstack.push(ec);
|
||||
generateElementInner(t, sd, ec, mode, null, compareElement, null, false);
|
||||
generateElementInner(t, sd, ec, mode, null, compareElement, null, false, "", anchorPrefix, elements);
|
||||
if (ec.hasSlicing()) {
|
||||
generateSlicing(t, sd, ec, ec.getSlicing(), compareElement, mode, false);
|
||||
}
|
||||
|
@ -3350,12 +3354,12 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
i++;
|
||||
}
|
||||
while (!dstack.isEmpty()) {
|
||||
finish(t, sd, dstack.pop(), mode);
|
||||
finish(t, sd, dstack.pop(), mode, "", anchorPrefix);
|
||||
}
|
||||
finish(t, sd, null, mode);
|
||||
finish(t, sd, null, mode, "", anchorPrefix);
|
||||
}
|
||||
|
||||
private void finish(XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode) throws FHIRException, IOException {
|
||||
private void finish(XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode, String defPath, String anchorPrefix) throws FHIRException, IOException {
|
||||
|
||||
for (Base b : VersionComparisonAnnotation.getDeleted(ed == null ? sd : ed, "element")) {
|
||||
ElementDefinition ec = (ElementDefinition) b;
|
||||
|
@ -3365,7 +3369,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
sp.span("color: grey", null).tx("--");
|
||||
sp.b().tx(". "+title);
|
||||
|
||||
generateElementInner(t, sd, ec, mode, null, null, null, true);
|
||||
generateElementInner(t, sd, ec, mode, null, null, null, true, defPath, anchorPrefix, new ArrayList<ElementDefinition>());
|
||||
if (ec.hasSlicing()) {
|
||||
generateSlicing(t, sd, ec, ec.getSlicing(), null, mode, true);
|
||||
}
|
||||
|
@ -3685,7 +3689,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
return "color:DarkGray;text-decoration:line-through";
|
||||
}
|
||||
|
||||
private void generateElementInner(XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough) throws FHIRException, IOException {
|
||||
private void generateElementInner(XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws FHIRException, IOException {
|
||||
boolean root = !d.getPath().contains(".");
|
||||
boolean slicedExtension = d.hasSliceName() && (d.getPath().endsWith(".extension") || d.getPath().endsWith(".modifierExtension"));
|
||||
// int slicedExtensionMode = (mode == GEN_MODE_KEY) && slicedExtension ? GEN_MODE_SNAP : mode; // see ProfileUtilities.checkExtensionDoco / Task 3970
|
||||
|
@ -3779,7 +3783,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
tableRow(tbl, context.formatPhrase(RenderingContext.STRUC_DEF_COMP_PROF), "http://hl7.org/fhir/extensions/StructureDefinition-structuredefinition-compliesWithProfile.html", strikethrough,
|
||||
renderCanonicalListExt(context.formatPhrase(RenderingContext.STRUC_DEF_PROF_COMP)+" ", sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_COMPLIES_WITH_PROFILE)));
|
||||
}
|
||||
tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(d, root, sd));
|
||||
tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(d, root, sd, defPath, anchorPrefix, inScopeElements));
|
||||
|
||||
if (d.hasExtension(ToolingExtensions.EXT_EXTENSION_STYLE)) {
|
||||
String es = d.getExtensionString(ToolingExtensions.EXT_EXTENSION_STYLE);
|
||||
|
@ -3981,7 +3985,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
private XhtmlNode describeObligations(ElementDefinition d, boolean root, StructureDefinition sdx) throws IOException {
|
||||
private XhtmlNode describeObligations(ElementDefinition d, boolean root, StructureDefinition sdx, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws IOException {
|
||||
XhtmlNode ret = new XhtmlNode(NodeType.Element, "div");
|
||||
ObligationsRenderer obr = new ObligationsRenderer(corePath, sdx, d.getPath(), context, hostMd, this);
|
||||
obr.seeObligations(d.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS));
|
||||
|
@ -4011,7 +4015,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
if (obr.hasObligations()) {
|
||||
XhtmlNode tbl = ret.table("grid");
|
||||
obr.renderTable(tbl.getChildNodes(), true);
|
||||
obr.renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements);
|
||||
if (tbl.isEmpty()) {
|
||||
ret.remove(tbl);
|
||||
}
|
||||
|
|
|
@ -439,33 +439,37 @@ public class TerminologyClientManager {
|
|||
}
|
||||
|
||||
public SourcedValueSet findValueSetOnServer(String canonical) {
|
||||
if (IGNORE_TX_REGISTRY || getMasterClient() == null || !useEcosystem) {
|
||||
if (IGNORE_TX_REGISTRY || getMasterClient() == null) {
|
||||
return null;
|
||||
}
|
||||
String request = Utilities.pathURL(monitorServiceURL, "resolve?fhirVersion="+factory.getVersion()+"&valueSet="+Utilities.URLEncode(canonical));
|
||||
if (usage != null) {
|
||||
request = request + "&usage="+usage;
|
||||
}
|
||||
String server = null;
|
||||
try {
|
||||
JsonObject json = JsonParser.parseObjectFromUrl(request);
|
||||
for (JsonObject item : json.getJsonObjects("authoritative")) {
|
||||
if (server == null) {
|
||||
server = item.asString("url");
|
||||
if (!useEcosystem) {
|
||||
server = getMasterClient().getAddress();
|
||||
} else {
|
||||
if (usage != null) {
|
||||
request = request + "&usage="+usage;
|
||||
}
|
||||
}
|
||||
for (JsonObject item : json.getJsonObjects("candidates")) {
|
||||
if (server == null) {
|
||||
server = item.asString("url");
|
||||
JsonObject json = JsonParser.parseObjectFromUrl(request);
|
||||
for (JsonObject item : json.getJsonObjects("authoritative")) {
|
||||
if (server == null) {
|
||||
server = item.asString("url");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
if (server.contains("://tx.fhir.org")) {
|
||||
try {
|
||||
server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
|
||||
} catch (MalformedURLException e) {
|
||||
for (JsonObject item : json.getJsonObjects("candidates")) {
|
||||
if (server == null) {
|
||||
server = item.asString("url");
|
||||
}
|
||||
}
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
if (server.contains("://tx.fhir.org")) {
|
||||
try {
|
||||
server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
|
||||
} catch (MalformedURLException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
TerminologyClientContext client = serverMap.get(server);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -958,10 +958,12 @@ public class NpmPackage {
|
|||
public String fhirVersion() {
|
||||
if ("hl7.fhir.core".equals(npm.asString("name")))
|
||||
return npm.asString("version");
|
||||
else if (npm.asString("name").startsWith("hl7.fhir.r2.") || npm.asString("name").startsWith("hl7.fhir.r2b.") || npm.asString("name").startsWith("hl7.fhir.r3.") ||
|
||||
npm.asString("name").startsWith("hl7.fhir.r4.") || npm.asString("name").startsWith("hl7.fhir.r4b.") || npm.asString("name").startsWith("hl7.fhir.r5."))
|
||||
else if (
|
||||
Utilities.existsInList(npm.asString("type"), "fhir.core", "fhir.examples") &&
|
||||
Utilities.startsWithInList( npm.asString("name"), "hl7.fhir.r2.", "hl7.fhir.r2b.", "hl7.fhir.r3.",
|
||||
"hl7.fhir.r4.", "hl7.fhir.r4b.", "hl7.fhir.r5.")) {
|
||||
return npm.asString("version");
|
||||
else {
|
||||
} else {
|
||||
JsonObject dep = null;
|
||||
if (npm.hasObject("dependencies")) {
|
||||
dep = npm.getJsonObject("dependencies");
|
||||
|
|
|
@ -120,7 +120,7 @@ public class HierarchicalTableGenerator {
|
|||
public static final int CONTINUE_SLICE = 5;
|
||||
private static final String BACKGROUND_ALT_COLOR = "#F7F7F7";
|
||||
public static boolean ACTIVE_TABLES = false;
|
||||
|
||||
|
||||
public enum TextAlignment {
|
||||
LEFT, CENTER, RIGHT;
|
||||
}
|
||||
|
@ -617,7 +617,9 @@ 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.
|
||||
* and the file paths cannot be guaranteed. For these reasons, you can tell the builder to inline all the graphics
|
||||
|
@ -628,7 +630,7 @@ public class HierarchicalTableGenerator {
|
|||
|
||||
private TableGenerationMode mode;
|
||||
private RenderingI18nContext i18n;
|
||||
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
|
@ -643,6 +645,14 @@ public class HierarchicalTableGenerator {
|
|||
checkSetup();
|
||||
}
|
||||
|
||||
public String getDefPath() {
|
||||
return defPath;
|
||||
}
|
||||
|
||||
public String getAnchorPrefix() {
|
||||
return anchorPrefix;
|
||||
}
|
||||
|
||||
private void checkSetup() {
|
||||
if (dest == null) {
|
||||
throw new Error("what");
|
||||
|
@ -650,6 +660,17 @@ public class HierarchicalTableGenerator {
|
|||
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets, String defPath, String anchorPrefix) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
this.dest = dest;
|
||||
this.inLineGraphics = inlineGraphics;
|
||||
this.makeTargets = makeTargets;
|
||||
this.defPath = defPath;
|
||||
this.anchorPrefix = anchorPrefix;
|
||||
checkSetup();
|
||||
}
|
||||
|
||||
public HierarchicalTableGenerator(RenderingI18nContext i18n, String dest, boolean inlineGraphics, boolean makeTargets) {
|
||||
super();
|
||||
this.i18n = i18n;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -887,6 +887,9 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
}
|
||||
validator.setJurisdiction(jurisdiction);
|
||||
validator.setLogProgress(true);
|
||||
if (policyAdvisor != null) {
|
||||
validator.setPolicyAdvisor(policyAdvisor);
|
||||
}
|
||||
return validator;
|
||||
}
|
||||
|
||||
|
@ -1259,7 +1262,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
|
||||
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
|
||||
IMessagingServices msgServices, List<ValidationMessage> messages) {
|
||||
return new BasePolicyAdvisorForFullValidation().getImpliedProfilesForResource(validator, appContext, stackPath,
|
||||
return new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.CHECK_VALID).getImpliedProfilesForResource(validator, appContext, stackPath,
|
||||
definition, structure, resource, valid, msgServices, messages);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidati
|
|||
private Map<String, NpmPackage> pidMap = new HashMap<>();
|
||||
|
||||
public StandAloneValidatorFetcher(FilesystemPackageCacheManager pcm, IWorkerContext context, IPackageInstaller installer) {
|
||||
super();
|
||||
super(ReferenceValidationPolicy.IGNORE);
|
||||
this.pcm = pcm;
|
||||
this.context = context;
|
||||
this.installer = installer;
|
||||
|
@ -74,7 +74,7 @@ public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidati
|
|||
Object appContext,
|
||||
String path,
|
||||
String url) {
|
||||
return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS;
|
||||
return ReferenceValidationPolicy.IGNORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -568,6 +568,7 @@ public class ValidationService {
|
|||
StandAloneValidatorFetcher fetcher = new StandAloneValidatorFetcher(validationEngine.getPcm(), validationEngine.getContext(), validationEngine);
|
||||
validationEngine.setFetcher(fetcher);
|
||||
validationEngine.getContext().setLocator(fetcher);
|
||||
validationEngine.setPolicyAdvisor(fetcher);
|
||||
}
|
||||
validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
|
||||
validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
|
||||
|
|
|
@ -27,10 +27,17 @@ import org.hl7.fhir.utilities.validation.ValidationMessage;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
||||
public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvisor {
|
||||
|
||||
private ReferenceValidationPolicy refpol = ReferenceValidationPolicy.CHECK_VALID;
|
||||
|
||||
public BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy refpol) {
|
||||
super();
|
||||
this.refpol = refpol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) {
|
||||
return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS;
|
||||
return refpol;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -596,7 +596,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private boolean noBindingMsgSuppressed;
|
||||
private Map<String, Element> fetchCache = new HashMap<>();
|
||||
private HashMap<Element, ResourceValidationTracker> resourceTracker = new HashMap<>();
|
||||
private IValidationPolicyAdvisor policyAdvisor = new BasePolicyAdvisorForFullValidation();
|
||||
private IValidationPolicyAdvisor policyAdvisor = new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.CHECK_VALID);
|
||||
long time = 0;
|
||||
long start = 0;
|
||||
long lastlog = 0;
|
||||
|
@ -1029,7 +1029,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
validateResource(new ValidationContext(appContext, element), errors, element, element, defn, resourceIdRule, stack.resetIds(), null, new ValidationMode(ValidationReason.Validation, ProfileSource.ConfigProfile), false, false);
|
||||
}
|
||||
}
|
||||
if (hintAboutNonMustSupport) {
|
||||
if (hintAboutNonMustSupport && !profiles.isEmpty()) {
|
||||
checkElementUsage(errors, element, stack);
|
||||
}
|
||||
codingObserver.finish(errors, stack);
|
||||
|
@ -1042,10 +1042,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
|
||||
private void checkElementUsage(List<ValidationMessage> errors, Element element, NodeStack stack) {
|
||||
String elementUsage = element.getUserString("elementSupported");
|
||||
hint(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), elementUsage == null || elementUsage.equals("Y"), I18nConstants.MUSTSUPPORT_VAL_MUSTSUPPORT, element.getName(), element.getProperty().getStructure().getVersionedUrl());
|
||||
if (element.getPath()==null
|
||||
|| (element.getName().equals("id") && !element.getPath().substring(0, element.getPath().length()-3).contains("."))
|
||||
|| (element.getName().equals("text") && !element.getPath().substring(0, element.getPath().length()-5).contains(".")))
|
||||
return;
|
||||
String hasFixed = element.getUserString("hasFixed");
|
||||
if (element.getPath().contains(".") && (hasFixed== null || !hasFixed.equals("Y"))) {
|
||||
String elementUsage = element.getUserString("elementSupported");
|
||||
hint(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), elementUsage != null && (elementUsage.equals("Y") || elementUsage.equals("NA")), I18nConstants.MUSTSUPPORT_VAL_MUSTSUPPORT, element.getName(), element.getProperty().getStructure().getVersionedUrl());
|
||||
if (elementUsage==null || !elementUsage.equals("Y"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.hasChildren()) {
|
||||
if (element.hasChildren() && (hasFixed== null || !hasFixed.equals("Y"))) {
|
||||
String prevName = "";
|
||||
int elementCount = 0;
|
||||
for (Element ce : element.getChildren()) {
|
||||
|
@ -6745,13 +6754,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
profile.setUserData("usesMustSupport", usesMustSupport);
|
||||
}
|
||||
if (usesMustSupport.equals("Y")) {
|
||||
String elementSupported = ei.getElement().getUserString("elementSupported");
|
||||
if (elementSupported == null || ei.definition.getMustSupport())
|
||||
if (ei.definition.getMustSupport()) {
|
||||
ei.getElement().setUserData("elementSupported", "Y");
|
||||
}
|
||||
}
|
||||
String elementSupported = ei.getElement().getUserString("elementSupported");
|
||||
String fixedValue = ei.getElement().getUserString("hasFixed");
|
||||
if ((elementSupported == null || !elementSupported.equals("Y")) && ei.definition.getMustSupport()) {
|
||||
if (ei.definition.getMustSupport()) {
|
||||
ei.getElement().setUserData("elementSupported", "Y");
|
||||
}
|
||||
} else if (elementSupported == null && !usesMustSupport.equals("Y"))
|
||||
ei.getElement().setUserData("elementSupported", "NA");
|
||||
if (fixedValue==null && (ei.definition.hasFixed() || ei.definition.hasPattern()))
|
||||
ei.getElement().setUserData("hasFixed", "Y");
|
||||
}
|
||||
|
||||
public boolean checkCardinalities(List<ValidationMessage> errors, StructureDefinition profile, Element element, NodeStack stack,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package org.hl7.fhir.validation.profile;
|
||||
|
||||
package org.hl7.fhir.validation.profile;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
@ -28,138 +28,140 @@ package org.hl7.fhir.validation.profile;
|
|||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
|
||||
public class ProfileValidator extends BaseValidator {
|
||||
|
||||
private boolean checkAggregation = false;
|
||||
private boolean checkMustSupport = false;
|
||||
private boolean allowDoubleQuotesInFHIRPath = false;
|
||||
private FHIRPathEngine fpe;
|
||||
|
||||
public ProfileValidator(IWorkerContext context, XVerExtensionManager xverManager) {
|
||||
super(context, xverManager, false);
|
||||
fpe = new FHIRPathEngine(context);
|
||||
fpe.setAllowDoubleQuotes(allowDoubleQuotesInFHIRPath);
|
||||
}
|
||||
|
||||
public boolean isCheckAggregation() {
|
||||
return checkAggregation;
|
||||
}
|
||||
|
||||
public boolean isCheckMustSupport() {
|
||||
return checkMustSupport;
|
||||
}
|
||||
|
||||
public void setCheckAggregation(boolean checkAggregation) {
|
||||
this.checkAggregation = checkAggregation;
|
||||
}
|
||||
|
||||
public void setCheckMustSupport(boolean checkMustSupport) {
|
||||
this.checkMustSupport = checkMustSupport;
|
||||
}
|
||||
|
||||
public boolean isAllowDoubleQuotesInFHIRPath() {
|
||||
return allowDoubleQuotesInFHIRPath;
|
||||
}
|
||||
|
||||
public void setAllowDoubleQuotesInFHIRPath(boolean allowDoubleQuotesInFHIRPath) {
|
||||
this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath;
|
||||
}
|
||||
|
||||
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean b, String msg) {
|
||||
String rn = path.contains(".") ? path.substring(0, path.indexOf(".")) : path;
|
||||
return super.ruleHtml(errors, NO_RULE_DATE, type, path, b, msg, "<a href=\""+(rn.toLowerCase())+".html\">"+rn+"</a>: "+Utilities.escapeXml(msg));
|
||||
}
|
||||
|
||||
public List<ValidationMessage> validate(StructureDefinition profile, boolean forBuild) {
|
||||
List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
|
||||
|
||||
// must have a FHIR version- GF#3160
|
||||
String s = (profile.getKind() == StructureDefinitionKind.LOGICAL) ? "Logical Models" : "Profiles";
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), s+" SHOULD state the FHIR Version on which they are based");
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), s+" SHOULD state their own version");
|
||||
|
||||
// extensions must be defined
|
||||
for (ElementDefinition ec : profile.getDifferential().getElement())
|
||||
checkExtensions(profile, errors, "differential", ec);
|
||||
rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "missing Snapshot at "+profile.getName()+"."+profile.getName());
|
||||
for (ElementDefinition ec : profile.getSnapshot().getElement())
|
||||
checkExtensions(profile, errors, "snapshot", ec);
|
||||
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "A snapshot is required")) {
|
||||
Hashtable<String, ElementDefinition> snapshotElements = new Hashtable<String, ElementDefinition>();
|
||||
for (ElementDefinition ed : profile.getSnapshot().getElement()) {
|
||||
snapshotElements.put(ed.getId(), ed);
|
||||
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
|
||||
if (forBuild) {
|
||||
if (!inExemptList(inv.getKey())) {
|
||||
// if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId()+"::"+ed.getPath()+"::"+inv.getKey(), inv.hasExpression(), "The invariant has no FHIR Path expression ("+inv.getXpath()+")")) {
|
||||
// try {
|
||||
// fpe.check(null, profile.getType(), ed.getPath(), inv.getExpression()); // , inv.hasXpath() && inv.getXpath().startsWith("@value")
|
||||
// } catch (Exception e) {
|
||||
// // rule(errors, UNKNOWN_DATE_TIME, IssueType.STRUCTURE, profile.getId()+"::"+ed.getPath()+"::"+inv.getId(), false, e.getMessage());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (snapshotElements != null) {
|
||||
for (ElementDefinition diffElement : profile.getDifferential().getElement()) {
|
||||
if (diffElement == null)
|
||||
throw new Error("Diff Element is null - this is not an expected thing");
|
||||
ElementDefinition snapElement = snapshotElements.get(diffElement.getId());
|
||||
if (snapElement!=null) { // Happens with profiles in the main build - should be able to fix once snapshot generation is fixed - Lloyd
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), !checkMustSupport || snapElement.hasMustSupport(), "Elements included in the differential should declare mustSupport");
|
||||
if (checkAggregation) {
|
||||
for (TypeRefComponent type : snapElement.getType()) {
|
||||
if ("http://hl7.org/fhir/Reference".equals(type.getWorkingCode()) || "http://hl7.org/fhir/canonical".equals(type.getWorkingCode())) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), type.hasAggregation(), "Elements with type Reference or canonical should declare aggregation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
// these are special cases
|
||||
private boolean inExemptList(String key) {
|
||||
return key.startsWith("txt-");
|
||||
}
|
||||
|
||||
private boolean checkExtensions(StructureDefinition profile, List<ValidationMessage> errors, String kind, ElementDefinition ec) {
|
||||
if (!ec.getType().isEmpty() && "Extension".equals(ec.getType().get(0).getWorkingCode()) && ec.getType().get(0).hasProfile()) {
|
||||
String url = ec.getType().get(0).getProfile().get(0).getValue();
|
||||
StructureDefinition defn = context.fetchResource(StructureDefinition.class, url);
|
||||
if (defn == null) {
|
||||
defn = getXverExt(profile, errors, url);
|
||||
}
|
||||
return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), defn != null, "Unable to find Extension '"+url+"' referenced at "+profile.getUrl()+" "+kind+" "+ec.getPath()+" ("+ec.getSliceName()+")");
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
|
||||
public class ProfileValidator extends BaseValidator {
|
||||
|
||||
private boolean checkAggregation = false;
|
||||
private boolean checkMustSupport = false;
|
||||
private boolean allowDoubleQuotesInFHIRPath = false;
|
||||
private FHIRPathEngine fpe;
|
||||
|
||||
public ProfileValidator(IWorkerContext context, XVerExtensionManager xverManager) {
|
||||
super(context, xverManager, false);
|
||||
fpe = new FHIRPathEngine(context);
|
||||
fpe.setAllowDoubleQuotes(allowDoubleQuotesInFHIRPath);
|
||||
}
|
||||
|
||||
public boolean isCheckAggregation() {
|
||||
return checkAggregation;
|
||||
}
|
||||
|
||||
public boolean isCheckMustSupport() {
|
||||
return checkMustSupport;
|
||||
}
|
||||
|
||||
public void setCheckAggregation(boolean checkAggregation) {
|
||||
this.checkAggregation = checkAggregation;
|
||||
}
|
||||
|
||||
public void setCheckMustSupport(boolean checkMustSupport) {
|
||||
this.checkMustSupport = checkMustSupport;
|
||||
}
|
||||
|
||||
public boolean isAllowDoubleQuotesInFHIRPath() {
|
||||
return allowDoubleQuotesInFHIRPath;
|
||||
}
|
||||
|
||||
public void setAllowDoubleQuotesInFHIRPath(boolean allowDoubleQuotesInFHIRPath) {
|
||||
this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath;
|
||||
}
|
||||
|
||||
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean b, String msg) {
|
||||
String rn = path.contains(".") ? path.substring(0, path.indexOf(".")) : path;
|
||||
return super.ruleHtml(errors, NO_RULE_DATE, type, path, b, msg, "<a href=\""+(rn.toLowerCase())+".html\">"+rn+"</a>: "+Utilities.escapeXml(msg));
|
||||
}
|
||||
|
||||
public List<ValidationMessage> validate(StructureDefinition profile, boolean forBuild) {
|
||||
List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
|
||||
|
||||
// must have a FHIR version- GF#3160
|
||||
String s = (profile.getKind() == StructureDefinitionKind.LOGICAL) ? "Logical Models" : "Profiles";
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), s+" SHOULD state the FHIR Version on which they are based");
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), s+" SHOULD state their own version");
|
||||
|
||||
// extensions must be defined
|
||||
for (ElementDefinition ec : profile.getDifferential().getElement())
|
||||
checkExtensions(profile, errors, "differential", ec);
|
||||
rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "missing Snapshot at "+profile.getName()+"."+profile.getName());
|
||||
for (ElementDefinition ec : profile.getSnapshot().getElement())
|
||||
checkExtensions(profile, errors, "snapshot", ec);
|
||||
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "A snapshot is required")) {
|
||||
Hashtable<String, ElementDefinition> snapshotElements = new Hashtable<String, ElementDefinition>();
|
||||
for (ElementDefinition ed : profile.getSnapshot().getElement()) {
|
||||
snapshotElements.put(ed.getId(), ed);
|
||||
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
|
||||
if (forBuild) {
|
||||
if (!inExemptList(inv.getKey())) {
|
||||
// if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId()+"::"+ed.getPath()+"::"+inv.getKey(), inv.hasExpression(), "The invariant has no FHIR Path expression ("+inv.getXpath()+")")) {
|
||||
// try {
|
||||
// fpe.check(null, profile.getType(), ed.getPath(), inv.getExpression()); // , inv.hasXpath() && inv.getXpath().startsWith("@value")
|
||||
// } catch (Exception e) {
|
||||
// // rule(errors, UNKNOWN_DATE_TIME, IssueType.STRUCTURE, profile.getId()+"::"+ed.getPath()+"::"+inv.getId(), false, e.getMessage());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (snapshotElements != null) {
|
||||
for (ElementDefinition diffElement : profile.getDifferential().getElement()) {
|
||||
if (diffElement == null)
|
||||
throw new Error("Diff Element is null - this is not an expected thing");
|
||||
ElementDefinition snapElement = snapshotElements.get(diffElement.getId());
|
||||
if (snapElement!=null) { // Happens with profiles in the main build - should be able to fix once snapshot generation is fixed - Lloyd
|
||||
// We don't care about mustSupport for the root element, if the element is just declaring slicing, if there's a pattern or fixed value, or if the element is being prohibited.
|
||||
boolean noMustSupport = !checkMustSupport || !snapElement.getPath().contains(".") || snapElement.hasSlicing() || snapElement.hasPattern() || snapElement.hasFixed() || snapElement.getMax().equals("0") || snapElement.hasMustSupport();
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), noMustSupport, "Elements included in the differential that aren't prohibited and don't have fixed values or patterns should declare mustSupport: " + snapElement.getPath());
|
||||
if (checkAggregation) {
|
||||
for (TypeRefComponent type : snapElement.getType()) {
|
||||
if ("http://hl7.org/fhir/Reference".equals(type.getWorkingCode()) || "http://hl7.org/fhir/canonical".equals(type.getWorkingCode())) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), type.hasAggregation(), "Elements with type Reference or canonical should declare aggregation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
// these are special cases
|
||||
private boolean inExemptList(String key) {
|
||||
return key.startsWith("txt-");
|
||||
}
|
||||
|
||||
private boolean checkExtensions(StructureDefinition profile, List<ValidationMessage> errors, String kind, ElementDefinition ec) {
|
||||
if (!ec.getType().isEmpty() && "Extension".equals(ec.getType().get(0).getWorkingCode()) && ec.getType().get(0).hasProfile()) {
|
||||
String url = ec.getType().get(0).getProfile().get(0).getValue();
|
||||
StructureDefinition defn = context.fetchResource(StructureDefinition.class, url);
|
||||
if (defn == null) {
|
||||
defn = getXverExt(profile, errors, url);
|
||||
}
|
||||
return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), defn != null, "Unable to find Extension '"+url+"' referenced at "+profile.getUrl()+" "+kind+" "+ec.getPath()+" ("+ec.getSliceName()+")");
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -894,7 +894,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
|
||||
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
|
||||
IMessagingServices msgServices, List<ValidationMessage> messages) {
|
||||
return new BasePolicyAdvisorForFullValidation().getImpliedProfilesForResource(validator, appContext, stackPath,
|
||||
return new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.CHECK_VALID).getImpliedProfilesForResource(validator, appContext, stackPath,
|
||||
definition, structure, resource, valid, msgServices, messages);
|
||||
}
|
||||
}
|
|
@ -5,10 +5,13 @@ import java.util.Locale;
|
|||
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.tests.TestConfig;
|
||||
import org.hl7.fhir.utilities.tests.TestConstants;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher;
|
||||
import org.hl7.fhir.validation.instance.BasePolicyAdvisorForFullValidation;
|
||||
|
||||
public class TestUtilities {
|
||||
|
||||
|
@ -64,6 +67,7 @@ public class TestUtilities {
|
|||
TerminologyCache.setCacheErrors(true);
|
||||
}
|
||||
|
||||
validationEngine.setPolicyAdvisor(new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.IGNORE));
|
||||
return validationEngine;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"http://hl7.org/fhir/ValueSet/ucum-vitals-common|4.0.0" : null,
|
||||
"http://loinc.org/vs" : null,
|
||||
"http://hl7.org.au/fhir/ValueSet/au-hl7v2-0203" : null,
|
||||
"http://hl7.org/fhir/ValueSet/name-use|4.0.1" : null,
|
||||
"http://hl7.org/fhir/ValueSet/observation-status|4.0.0" : null,
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -14,14 +14,14 @@
|
|||
HAPI FHIR
|
||||
-->
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>6.3.11-SNAPSHOT</version>
|
||||
<version>6.3.12-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<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.11-SNAPSHOT</validator_test_case_version>
|
||||
<validator_test_case_version>1.5.11</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