mirror of
https://github.com/hapifhir/org.hl7.fhir.core.git
synced 2025-03-05 19:09:11 +00:00
Merge pull request #338 from hapifhir/gg_v518c
Preparing for new release
This commit is contained in:
commit
03fb727894
@ -3742,7 +3742,7 @@ public class VersionConvertor_40_50 {
|
||||
return convertUsageContext((org.hl7.fhir.r4.model.UsageContext) src);
|
||||
if (src instanceof org.hl7.fhir.r4.model.ElementDefinition)
|
||||
return convertElementDefinition((org.hl7.fhir.r4.model.ElementDefinition) src);
|
||||
throw new Error("Unknown type " + src.fhirType());
|
||||
throw new FHIRException("Unknown type " + src.fhirType());
|
||||
}
|
||||
|
||||
public static org.hl7.fhir.r4.model.Type convertType(org.hl7.fhir.r5.model.DataType src) throws FHIRException {
|
||||
@ -3868,7 +3868,7 @@ public class VersionConvertor_40_50 {
|
||||
return convertUsageContext((org.hl7.fhir.r5.model.UsageContext) src);
|
||||
if (src instanceof org.hl7.fhir.r5.model.ElementDefinition)
|
||||
return convertElementDefinition((org.hl7.fhir.r5.model.ElementDefinition) src);
|
||||
throw new Error("Unknown type " + src.fhirType());
|
||||
throw new FHIRException("Unknown type " + src.fhirType());
|
||||
}
|
||||
|
||||
protected static void copyDomainResource(org.hl7.fhir.r4.model.DomainResource src, org.hl7.fhir.r5.model.DomainResource tgt) throws FHIRException {
|
||||
@ -4174,7 +4174,7 @@ public class VersionConvertor_40_50 {
|
||||
return VerificationResult40_50.convertVerificationResult((org.hl7.fhir.r4.model.VerificationResult) src);
|
||||
if (src instanceof org.hl7.fhir.r4.model.VisionPrescription)
|
||||
return VisionPrescription40_50.convertVisionPrescription((org.hl7.fhir.r4.model.VisionPrescription) src);
|
||||
throw new Error("Unknown resource " + src.fhirType());
|
||||
throw new FHIRException("Unknown resource " + src.fhirType());
|
||||
}
|
||||
|
||||
public static org.hl7.fhir.r4.model.Resource convertResource(org.hl7.fhir.r5.model.Resource src) throws FHIRException {
|
||||
@ -4441,7 +4441,7 @@ public class VersionConvertor_40_50 {
|
||||
return VerificationResult40_50.convertVerificationResult((org.hl7.fhir.r5.model.VerificationResult) src);
|
||||
if (src instanceof org.hl7.fhir.r5.model.VisionPrescription)
|
||||
return VisionPrescription40_50.convertVisionPrescription((org.hl7.fhir.r5.model.VisionPrescription) src);
|
||||
throw new Error("Unknown resource " + src.fhirType());
|
||||
throw new FHIRException("Unknown resource " + src.fhirType());
|
||||
}
|
||||
|
||||
protected static org.hl7.fhir.r5.model.CodeType convertResourceEnum(org.hl7.fhir.r4.model.CodeType src) {
|
||||
|
@ -295,8 +295,7 @@ public class BundleRenderer extends ResourceRenderer {
|
||||
try {
|
||||
xn = rr.build(be.getResource());
|
||||
} catch (Exception e) {
|
||||
xn = new XhtmlNode();
|
||||
xn.para().b().tx("Exception generating narrative: "+e.getMessage());
|
||||
xn = makeExceptionXhtml(e, "generating narrative");
|
||||
}
|
||||
}
|
||||
root.blockquote().getChildNodes().addAll(checkInternalLinks(b, xn.getChildNodes()));
|
||||
|
@ -58,6 +58,7 @@ import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||
|
||||
@ -1021,6 +1022,21 @@ public class DataRenderer extends Renderer {
|
||||
}
|
||||
|
||||
|
||||
public XhtmlNode makeExceptionXhtml(Exception e, String function) {
|
||||
XhtmlNode xn;
|
||||
xn = new XhtmlNode(NodeType.Element, "div");
|
||||
xn.para().b().tx("Exception "+function+": "+e.getMessage()).addComment(getStackTrace(e));
|
||||
return xn;
|
||||
}
|
||||
|
||||
private String getStackTrace(Exception e) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("\r\n");
|
||||
for (StackTraceElement t : e.getStackTrace()) {
|
||||
b.append(t.getClassName()+"."+t.getMethodName()+" ("+t.getFileName()+":"+t.getLineNumber());
|
||||
b.append("\r\n");
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
}
|
@ -41,6 +41,7 @@ import org.hl7.fhir.r5.model.InstantType;
|
||||
import org.hl7.fhir.r5.model.Meta;
|
||||
import org.hl7.fhir.r5.model.Narrative;
|
||||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.model.Period;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Property;
|
||||
@ -320,6 +321,12 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
} else {
|
||||
x.addText("??");
|
||||
}
|
||||
} else if (e instanceof org.hl7.fhir.r5.model.Integer64Type) {
|
||||
if (((org.hl7.fhir.r5.model.Integer64Type) e).hasValue()) {
|
||||
x.addText(Long.toString(((org.hl7.fhir.r5.model.Integer64Type) e).getValue()));
|
||||
} else {
|
||||
x.addText("??");
|
||||
}
|
||||
} else if (e instanceof org.hl7.fhir.r5.model.DecimalType) {
|
||||
x.addText(((org.hl7.fhir.r5.model.DecimalType) e).getValue().toString());
|
||||
} else if (e instanceof HumanName) {
|
||||
@ -387,12 +394,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
} else if (e instanceof ElementDefinition) {
|
||||
x.tx("todo-bundle");
|
||||
} else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) {
|
||||
StructureDefinition sd = getContext().getWorker().fetchTypeDefinition(e.fhirType());
|
||||
if (sd == null)
|
||||
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet, and no structure found");
|
||||
else
|
||||
generateByProfile(res, sd, ew, sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep(),
|
||||
getChildrenForPath(sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep().getPath()), x, e.fhirType(), showCodeDetails, indent + 1);
|
||||
throw new NotImplementedException("type "+e.getClass().getName()+" not handled - should not be here");
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,12 +555,28 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
|
||||
private boolean isPrimitive(ElementDefinition e) {
|
||||
//we can tell if e is a primitive because it has types
|
||||
if (e.getType().isEmpty())
|
||||
if (e.getType().isEmpty()) {
|
||||
return false;
|
||||
if (e.getType().size() == 1 && isBase(e.getType().get(0).getWorkingCode()))
|
||||
}
|
||||
if (e.getType().size() == 1 && isBase(e.getType().get(0).getWorkingCode())) {
|
||||
return false;
|
||||
return true;
|
||||
// return !e.getType().isEmpty()
|
||||
}
|
||||
if (e.getType().size() > 1) {
|
||||
return true;
|
||||
}
|
||||
StructureDefinition sd = context.getWorker().fetchTypeDefinition(e.getTypeFirstRep().getCode());
|
||||
if (sd != null) {
|
||||
if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) {
|
||||
return true;
|
||||
}
|
||||
if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) {
|
||||
if (Utilities.existsInList(e.getTypeFirstRep().getCode(), "Extension", "CodeableConcept", "Coding", "Annotation", "Identifier", "HumanName", "SampledData",
|
||||
"Address", "ContactPoint", "ContactDetail", "Timing", "Range", "Quantity", "Ratio", "Period", "Reference")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBase(String code) {
|
||||
@ -646,31 +664,32 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
||||
if (p.getValues().size() > 0) {
|
||||
if (isPrimitive(child)) {
|
||||
XhtmlNode para = x.para();
|
||||
String name = p.getName();
|
||||
if (name.endsWith("[x]"))
|
||||
name = name.substring(0, name.length() - 3);
|
||||
if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) {
|
||||
para.b().addText(name);
|
||||
para.tx(": ");
|
||||
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||
XhtmlNode list = x.ul();
|
||||
for (BaseWrapper v : p.getValues())
|
||||
renderLeaf(res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent);
|
||||
} else {
|
||||
boolean first = true;
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
para.tx(", ");
|
||||
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (canDoTable(path, p, grandChildren)) {
|
||||
XhtmlNode para = x.isPara() ? para = x : x.para();
|
||||
String name = p.getName();
|
||||
if (name.endsWith("[x]"))
|
||||
name = name.substring(0, name.length() - 3);
|
||||
if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) {
|
||||
para.b().addText(name);
|
||||
para.tx(": ");
|
||||
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||
XhtmlNode list = x.ul();
|
||||
for (BaseWrapper v : p.getValues())
|
||||
renderLeaf(res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent);
|
||||
} else {
|
||||
boolean first = true;
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
para.tx(", ");
|
||||
}
|
||||
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (canDoTable(path, p, grandChildren, x)) {
|
||||
x.addTag(getHeader()).addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||
XhtmlNode tbl = x.table( "grid");
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.td().tx("-"); // work around problem with empty table rows
|
||||
addColumnHeadings(tr, grandChildren);
|
||||
@ -737,10 +756,13 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
return res;
|
||||
}
|
||||
|
||||
private boolean canDoTable(String path, PropertyWrapper p, List<ElementDefinition> grandChildren) {
|
||||
private boolean canDoTable(String path, PropertyWrapper p, List<ElementDefinition> grandChildren, XhtmlNode x) {
|
||||
if (isExtension(p)) {
|
||||
return false;
|
||||
}
|
||||
if (x.getName().equals("p")) {
|
||||
return false;
|
||||
}
|
||||
for (ElementDefinition e : grandChildren) {
|
||||
List<PropertyWrapper> values = getValues(path, p, e);
|
||||
if (values.size() > 1 || !isPrimitive(e) || !canCollapse(e))
|
||||
@ -830,15 +852,17 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
getContext().getWorker().cacheResource(ed);
|
||||
}
|
||||
}
|
||||
if (p.getName().equals("modifierExtension") && ed == null)
|
||||
if (p.getName().equals("modifierExtension") && ed == null) {
|
||||
throw new DefinitionException("Unknown modifier extension "+url);
|
||||
}
|
||||
PropertyWrapper pe = map.get(p.getName()+"["+url+"]");
|
||||
if (pe == null) {
|
||||
if (ed == null) {
|
||||
if (url.startsWith("http://hl7.org/fhir") && !url.startsWith("http://hl7.org/fhir/us"))
|
||||
if (url.startsWith("http://hl7.org/fhir") && !url.startsWith("http://hl7.org/fhir/us")) {
|
||||
throw new DefinitionException("unknown extension "+url);
|
||||
}
|
||||
// System.out.println("unknown extension "+url);
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex), ed.getSnapshot().getElementFirstRep());
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex), null);
|
||||
} else {
|
||||
ElementDefinition def = ed.getSnapshot().getElement().get(0);
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", "Extension", def.getDefinition(), def.getMin(), def.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(def.getMax()), ex), ed.getSnapshot().getElementFirstRep());
|
||||
|
@ -795,6 +795,10 @@ public class FHIRPathEngine {
|
||||
return item.primitiveValue();
|
||||
} else if (item instanceof Quantity) {
|
||||
Quantity q = (Quantity) item;
|
||||
if (q.hasUnit() && Utilities.existsInList(q.getUnit(), "year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds")
|
||||
&& (!q.hasSystem() || q.getSystem().equals("http://unitsofmeasure.org"))) {
|
||||
return q.getValue().toPlainString()+" "+q.getUnit();
|
||||
}
|
||||
if (q.getSystem().equals("http://unitsofmeasure.org")) {
|
||||
String u = "'"+q.getCode()+"'";
|
||||
return q.getValue().toPlainString()+" "+u;
|
||||
@ -954,12 +958,14 @@ public class FHIRPathEngine {
|
||||
if (!isString && !lexer.done() && (result.getConstant() instanceof IntegerType || result.getConstant() instanceof DecimalType) && (lexer.isStringConstant() || lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds"))) {
|
||||
// it's a quantity
|
||||
String ucum = null;
|
||||
String unit = null;
|
||||
if (lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds")) {
|
||||
String s = lexer.take();
|
||||
unit = s;
|
||||
if (s.equals("year") || s.equals("years")) {
|
||||
ucum = "a";
|
||||
// this is not the UCUM year
|
||||
} else if (s.equals("month") || s.equals("months")) {
|
||||
ucum = "mo";
|
||||
// this is not the UCUM month
|
||||
} else if (s.equals("week") || s.equals("weeks")) {
|
||||
ucum = "wk";
|
||||
} else if (s.equals("day") || s.equals("days")) {
|
||||
@ -976,7 +982,7 @@ public class FHIRPathEngine {
|
||||
} else {
|
||||
ucum = lexer.readConstant("units");
|
||||
}
|
||||
result.setConstant(new Quantity().setValue(new BigDecimal(result.getConstant().primitiveValue())).setSystem("http://unitsofmeasure.org").setCode(ucum));
|
||||
result.setConstant(new Quantity().setValue(new BigDecimal(result.getConstant().primitiveValue())).setUnit(unit).setSystem(ucum == null ? null : "http://unitsofmeasure.org").setCode(ucum));
|
||||
}
|
||||
result.setEnd(lexer.getCurrentLocation());
|
||||
} else if ("(".equals(lexer.getCurrent())) {
|
||||
@ -1934,18 +1940,50 @@ public class FHIRPathEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean qtyEqual(Quantity left, Quantity right) {
|
||||
private Boolean qtyEqual(Quantity left, Quantity right) {
|
||||
if (!left.hasValue() && !right.hasValue()) {
|
||||
return true;
|
||||
}
|
||||
if (!left.hasValue() || !right.hasValue()) {
|
||||
return null;
|
||||
}
|
||||
if (worker.getUcumService() != null) {
|
||||
DecimalType dl = qtyToCanonical(left);
|
||||
DecimalType dr = qtyToCanonical(right);
|
||||
Pair dl = qtyToCanonicalPair(left);
|
||||
Pair dr = qtyToCanonicalPair(right);
|
||||
if (dl != null && dr != null) {
|
||||
return doEquals(dl, dr);
|
||||
if (dl.getCode().equals(dr.getCode())) {
|
||||
return doEquals(new DecimalType(dl.getValue().asDecimal()), new DecimalType(dr.getValue().asDecimal()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return left.equals(right);
|
||||
if (left.hasCode() || right.hasCode()) {
|
||||
if (!(left.hasCode() && right.hasCode()) || !left.getCode().equals(right.getCode())) {
|
||||
return null;
|
||||
}
|
||||
} else if (!left.hasUnit() || right.hasUnit()) {
|
||||
if (!(left.hasUnit() && right.hasUnit()) || !left.getUnit().equals(right.getUnit())) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return doEquals(new DecimalType(left.getValue()), new DecimalType(right.getValue()));
|
||||
}
|
||||
|
||||
private DecimalType qtyToCanonical(Quantity q) {
|
||||
private Pair qtyToCanonicalPair(Quantity q) {
|
||||
if (!"http://unitsofmeasure.org".equals(q.getSystem())) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Pair p = new Pair(new Decimal(q.getValue().toPlainString()), q.getCode() == null ? "1" : q.getCode());
|
||||
Pair c = worker.getUcumService().getCanonicalForm(p);
|
||||
return c;
|
||||
} catch (UcumException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private DecimalType qtyToCanonicalDecimal(Quantity q) {
|
||||
if (!"http://unitsofmeasure.org".equals(q.getSystem())) {
|
||||
return null;
|
||||
}
|
||||
@ -1975,15 +2013,34 @@ public class FHIRPathEngine {
|
||||
}
|
||||
|
||||
|
||||
private boolean qtyEquivalent(Quantity left, Quantity right) throws PathEngineException {
|
||||
private Boolean qtyEquivalent(Quantity left, Quantity right) throws PathEngineException {
|
||||
if (!left.hasValue() && !right.hasValue()) {
|
||||
return true;
|
||||
}
|
||||
if (!left.hasValue() || !right.hasValue()) {
|
||||
return null;
|
||||
}
|
||||
if (worker.getUcumService() != null) {
|
||||
DecimalType dl = qtyToCanonical(left);
|
||||
DecimalType dr = qtyToCanonical(right);
|
||||
Pair dl = qtyToCanonicalPair(left);
|
||||
Pair dr = qtyToCanonicalPair(right);
|
||||
if (dl != null && dr != null) {
|
||||
return doEquivalent(dl, dr);
|
||||
if (dl.getCode().equals(dr.getCode())) {
|
||||
return doEquivalent(new DecimalType(dl.getValue().asDecimal()), new DecimalType(dr.getValue().asDecimal()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return left.equals(right);
|
||||
if (left.hasCode() || right.hasCode()) {
|
||||
if (!(left.hasCode() && right.hasCode()) || !left.getCode().equals(right.getCode())) {
|
||||
return null;
|
||||
}
|
||||
} else if (!left.hasUnit() || right.hasUnit()) {
|
||||
if (!(left.hasUnit() && right.hasUnit()) || !left.getUnit().equals(right.getUnit())) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return doEquivalent(new DecimalType(left.getValue()), new DecimalType(right.getValue()));
|
||||
}
|
||||
|
||||
|
||||
@ -2072,9 +2129,9 @@ public class FHIRPathEngine {
|
||||
return makeBoolean(false);
|
||||
} else {
|
||||
List<Base> dl = new ArrayList<Base>();
|
||||
dl.add(qtyToCanonical((Quantity) left.get(0)));
|
||||
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
|
||||
List<Base> dr = new ArrayList<Base>();
|
||||
dr.add(qtyToCanonical((Quantity) right.get(0)));
|
||||
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
|
||||
return opLessThan(dl, dr);
|
||||
}
|
||||
}
|
||||
@ -2119,9 +2176,9 @@ public class FHIRPathEngine {
|
||||
return makeBoolean(false);
|
||||
} else {
|
||||
List<Base> dl = new ArrayList<Base>();
|
||||
dl.add(qtyToCanonical((Quantity) left.get(0)));
|
||||
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
|
||||
List<Base> dr = new ArrayList<Base>();
|
||||
dr.add(qtyToCanonical((Quantity) right.get(0)));
|
||||
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
|
||||
return opGreater(dl, dr);
|
||||
}
|
||||
}
|
||||
@ -2169,9 +2226,9 @@ public class FHIRPathEngine {
|
||||
return makeBoolean(false);
|
||||
} else {
|
||||
List<Base> dl = new ArrayList<Base>();
|
||||
dl.add(qtyToCanonical((Quantity) left.get(0)));
|
||||
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
|
||||
List<Base> dr = new ArrayList<Base>();
|
||||
dr.add(qtyToCanonical((Quantity) right.get(0)));
|
||||
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
|
||||
return opLessOrEqual(dl, dr);
|
||||
}
|
||||
}
|
||||
@ -2217,9 +2274,9 @@ public class FHIRPathEngine {
|
||||
return makeBoolean(false);
|
||||
} else {
|
||||
List<Base> dl = new ArrayList<Base>();
|
||||
dl.add(qtyToCanonical((Quantity) left.get(0)));
|
||||
dl.add(qtyToCanonicalDecimal((Quantity) left.get(0)));
|
||||
List<Base> dr = new ArrayList<Base>();
|
||||
dr.add(qtyToCanonical((Quantity) right.get(0)));
|
||||
dr.add(qtyToCanonicalDecimal((Quantity) right.get(0)));
|
||||
return opGreaterOrEqual(dl, dr);
|
||||
}
|
||||
}
|
||||
@ -4857,7 +4914,7 @@ public class FHIRPathEngine {
|
||||
if (s.equals("year") || s.equals("years")) {
|
||||
return Quantity.fromUcum(v, "a");
|
||||
} else if (s.equals("month") || s.equals("months")) {
|
||||
return Quantity.fromUcum(v, "mo");
|
||||
return Quantity.fromUcum(v, "mo_s");
|
||||
} else if (s.equals("week") || s.equals("weeks")) {
|
||||
return Quantity.fromUcum(v, "wk");
|
||||
} else if (s.equals("day") || s.equals("days")) {
|
||||
|
@ -145,7 +145,7 @@ public class FHIRPathTests {
|
||||
public void test(String name, Element test) throws FileNotFoundException, IOException, FHIRException, org.hl7.fhir.exceptions.FHIRException, UcumException {
|
||||
// Setting timezone for this test. Grahame is in UTC+11, Travis is in GMT, and I'm here in Toronto, Canada with
|
||||
// all my time based tests failing locally...
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC+1100"));
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC+1100"));
|
||||
|
||||
fp.setHostServices(new FHIRPathTestEvaluationServices());
|
||||
String input = test.getAttribute("inputfile");
|
||||
@ -178,6 +178,7 @@ public class FHIRPathTests {
|
||||
outcome.clear();
|
||||
outcome.add(new BooleanType(ok));
|
||||
}
|
||||
System.out.println(name);
|
||||
if (fp.hasLog()) {
|
||||
System.out.println(name);
|
||||
System.out.println(fp.takeLog());
|
||||
|
@ -152,7 +152,7 @@ public class NarrativeGenerationTests {
|
||||
x = RendererFactory.factory(source, rc).render(new ElementWrappers.ResourceWrapperMetaElement(rc, e));
|
||||
|
||||
target = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-meta.html"));
|
||||
output = HEADER+new XhtmlComposer(true).compose(x)+FOOTER;
|
||||
output = HEADER+new XhtmlComposer(true, true).compose(x)+FOOTER;
|
||||
TextFile.stringToFile(output, TestingUtilities.tempFile("narrative", test.getId() + "-meta.output.html"));
|
||||
Assertions.assertTrue(output.equals(target), "Output does not match expected (meta)");
|
||||
}
|
||||
|
@ -56,6 +56,12 @@ public class MarkDownProcessor {
|
||||
|
||||
|
||||
public String process(String source, String context) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if ("".equals(source)) {
|
||||
return "";
|
||||
}
|
||||
switch (dialect) {
|
||||
case DARING_FIREBALL : return Processor.process(source);
|
||||
case COMMON_MARK : return processCommonMark(source);
|
||||
|
@ -161,7 +161,7 @@ public class I18nConstants {
|
||||
public static final String FHIRPATH_UNKNOWN_CONSTANT = "FHIRPATH_UNKNOWN_CONSTANT";
|
||||
public static final String FHIRPATH_UNKNOWN_CONTEXT = "FHIRPATH_UNKNOWN_CONTEXT";
|
||||
public static final String FHIRPATH_UNKNOWN_CONTEXT_ELEMENT = "FHIRPATH_UNKNOWN_CONTEXT_ELEMENT";
|
||||
public static final String FHIRPATH_UNKNOWN_NAME = "FHIRPATH_UNWKNOWN_NAME";
|
||||
public static final String FHIRPATH_UNKNOWN_NAME = "FHIRPATH_UNKNOWN_NAME";
|
||||
public static final String FHIRPATH_WRONG_PARAM_TYPE = "FHIRPATH_WRONG_PARAM_TYPE";
|
||||
public static final String FIXED_TYPE_CHECKS_DT_ADDRESS_LINE = "Fixed_Type_Checks_DT_Address_Line";
|
||||
public static final String FIXED_TYPE_CHECKS_DT_NAME_FAMILY = "Fixed_Type_Checks_DT_Name_Family";
|
||||
@ -466,6 +466,7 @@ public class I18nConstants {
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX = "Type_Specific_Checks_DT_Primitive_Regex";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_VALUEEXT = "Type_Specific_Checks_DT_Primitive_ValueExt";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_WS = "Type_Specific_Checks_DT_Primitive_WS";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = "TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_STRING_LENGTH = "Type_Specific_Checks_DT_String_Length";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_STRING_WS = "Type_Specific_Checks_DT_String_WS";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_TIME_VALID = "Type_Specific_Checks_DT_Time_Valid";
|
||||
@ -578,6 +579,7 @@ public class I18nConstants {
|
||||
public static final String XHTML_XHTML_ATTRIBUTE_ILLEGAL = "XHTML_XHTML_Attribute_Illegal";
|
||||
public static final String XHTML_XHTML_DOCTYPE_ILLEGAL = "XHTML_XHTML_DOCTYPE_ILLEGAL";
|
||||
public static final String XHTML_XHTML_ELEMENT_ILLEGAL = "XHTML_XHTML_Element_Illegal";
|
||||
public static final String XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = "XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA";
|
||||
public static final String XHTML_XHTML_NAME_INVALID = "XHTML_XHTML_Name_Invalid";
|
||||
public static final String XHTML_XHTML_NS_INVALID = "XHTML_XHTML_NS_InValid";
|
||||
public static final String XML_ATTR_VALUE_INVALID = "xml_attr_value_invalid";
|
||||
|
@ -41,7 +41,10 @@ import java.util.Map;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseXhtml;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.ChildOrder;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
@ -137,11 +140,53 @@ public class XhtmlNode implements IBaseXhtml {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void validate(List<String> errors, String path, boolean inResource, boolean inPara) {
|
||||
if (nodeType == NodeType.Element || nodeType == NodeType.Document) {
|
||||
path = Utilities.noString(path) ? name : path+"/"+name;
|
||||
if (inResource) {
|
||||
if (!Utilities.existsInList(name, "p", "br", "div", "h1", "h2", "h3", "h4", "h5", "h6", "a", "span", "b", "em", "i", "strong",
|
||||
"small", "big", "tt", "small", "dfn", "q", "var", "abbr", "acronym", "cite", "blockquote", "hr", "address", "bdo", "kbd", "q", "sub", "sup",
|
||||
"ul", "ol", "li", "dl", "dt", "dd", "pre", "table", "caption", "colgroup", "col", "thead", "tr", "tfoot", "tbody", "th", "td",
|
||||
"code", "samp", "img", "map", "area")) {
|
||||
errors.add("Error at "+path+": Found "+name+" in a resource");
|
||||
}
|
||||
for (String an : attributes.keySet()) {
|
||||
boolean ok = an.startsWith("xmlns") || Utilities.existsInList(an,
|
||||
"title", "style", "class", "ID", "lang", "xml:lang", "dir", "accesskey", "tabindex",
|
||||
// tables
|
||||
"span", "width", "align", "valign", "char", "charoff", "abbr", "axis", "headers", "scope", "rowspan", "colspan") ||
|
||||
Utilities.existsInList(name + "." + an, "a.href", "a.name", "img.src", "img.border", "div.xmlns", "blockquote.cite", "q.cite",
|
||||
"a.charset", "a.type", "a.name", "a.href", "a.hreflang", "a.rel", "a.rev", "a.shape", "a.coords", "img.src",
|
||||
"img.alt", "img.longdesc", "img.height", "img.width", "img.usemap", "img.ismap", "map.name", "area.shape",
|
||||
"area.coords", "area.href", "area.nohref", "area.alt", "table.summary", "table.width", "table.border",
|
||||
"table.frame", "table.rules", "table.cellspacing", "table.cellpadding", "pre.space", "td.nowrap"
|
||||
);
|
||||
if (!ok)
|
||||
errors.add("Error at "+path+": Found attribute "+name+"."+an+" in a resource");
|
||||
}
|
||||
}
|
||||
if (inPara && Utilities.existsInList(name, "div", "blockquote", "table", "ol", "ul", "p")) {
|
||||
errors.add("Error at "+path+": Found "+name+" inside an html paragraph");
|
||||
}
|
||||
|
||||
if (childNodes != null) {
|
||||
if ("p".equals(name)) {
|
||||
inPara = true;
|
||||
}
|
||||
for (XhtmlNode child : childNodes) {
|
||||
child.validate(errors, path, inResource, inPara);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public XhtmlNode addTag(String name)
|
||||
{
|
||||
|
||||
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document))
|
||||
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document)) {
|
||||
throw new Error("Wrong node type - node is "+nodeType.toString()+" ('"+getName()+"/"+getContent()+"')");
|
||||
}
|
||||
|
||||
XhtmlNode node = new XhtmlNode(NodeType.Element);
|
||||
node.setName(name);
|
||||
childNodes.add(node);
|
||||
@ -188,7 +233,6 @@ public class XhtmlNode implements IBaseXhtml {
|
||||
childNodes.add(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
public XhtmlNode addText(String content)
|
||||
{
|
||||
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document))
|
||||
@ -747,6 +791,11 @@ public class XhtmlNode implements IBaseXhtml {
|
||||
}
|
||||
|
||||
|
||||
public boolean isPara() {
|
||||
return "p".equals(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -605,3 +605,5 @@ FHIRPATH_NUMERICAL_ONLY = Error evaluating FHIRPath expression: The function {0}
|
||||
FHIRPATH_DECIMAL_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on a decimal but found {1}
|
||||
FHIRPATH_FOCUS_PLURAL = Error evaluating FHIRPath expression: focus for {0} has more than one value
|
||||
REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect, and it should be checked
|
||||
TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable
|
||||
XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'')
|
||||
|
@ -2,7 +2,12 @@ package org.hl7.fhir.validation;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
@ -64,6 +69,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
@ -78,10 +85,28 @@ import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.validation.BaseValidator.ValidationControl;
|
||||
import org.hl7.fhir.validation.instance.utils.IndexedElement;
|
||||
|
||||
public class BaseValidator {
|
||||
|
||||
public class ValidationControl {
|
||||
private boolean allowed;
|
||||
private IssueSeverity level;
|
||||
|
||||
public ValidationControl(boolean allowed, IssueSeverity level) {
|
||||
super();
|
||||
this.allowed = allowed;
|
||||
this.level = level;
|
||||
}
|
||||
public boolean isAllowed() {
|
||||
return allowed;
|
||||
}
|
||||
public IssueSeverity getLevel() {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
protected final String META = "meta";
|
||||
protected final String ENTRY = "entry";
|
||||
protected final String DOCUMENT = "document";
|
||||
@ -98,7 +123,16 @@ public class BaseValidator {
|
||||
protected Source source;
|
||||
protected IWorkerContext context;
|
||||
protected TimeTracker timeTracker = new TimeTracker();
|
||||
|
||||
|
||||
/**
|
||||
* Use to control what validation the validator performs.
|
||||
* Using this, you can turn particular kinds of validation on and off
|
||||
* In addition, you can override the error | warning | hint level and make it a different level
|
||||
*
|
||||
* There is no way to do this using the command line validator; it's a service that is only
|
||||
* offered when the validator is hosted in some other process
|
||||
*/
|
||||
private Map<String, ValidationControl> validationControl = new HashMap<>();
|
||||
|
||||
public BaseValidator(IWorkerContext context){
|
||||
this.context = context;
|
||||
@ -287,7 +321,10 @@ public class BaseValidator {
|
||||
protected boolean txRule(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
errors.add(new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setTxLink(txLink));
|
||||
ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(theMessage);
|
||||
if (checkMsgId(theMessage, vm)) {
|
||||
errors.add(vm.setTxLink(txLink));
|
||||
}
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
@ -415,10 +452,23 @@ public class BaseValidator {
|
||||
|
||||
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource, String id) {
|
||||
ValidationMessage validationMessage = new ValidationMessage(theSource, type, line, col, path, msg, theSeverity).setMessageId(id);
|
||||
errors.add(validationMessage);
|
||||
if (checkMsgId(id, validationMessage)) {
|
||||
errors.add(validationMessage);
|
||||
}
|
||||
return validationMessage;
|
||||
}
|
||||
|
||||
public boolean checkMsgId(String id, ValidationMessage vm) {
|
||||
if (id != null && validationControl.containsKey(id)) {
|
||||
ValidationControl control = validationControl.get(id);
|
||||
if (control.level != null) {
|
||||
vm.setLevel(control.level);
|
||||
}
|
||||
return control.isAllowed();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#WARNING} validation message if the validation fails
|
||||
*
|
||||
@ -429,7 +479,10 @@ public class BaseValidator {
|
||||
protected boolean txWarning(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
errors.add(new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg));
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg);
|
||||
if (checkMsgId(msg, vmsg)) {
|
||||
errors.add(vmsg);
|
||||
}
|
||||
}
|
||||
return thePass;
|
||||
|
||||
@ -567,7 +620,10 @@ public class BaseValidator {
|
||||
}
|
||||
|
||||
protected void addValidationMessage(List<ValidationMessage> errors, IssueType type, String path, String msg, String html, IssueSeverity theSeverity, String id) {
|
||||
errors.add(new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity).setMessageId(id));
|
||||
ValidationMessage vm = new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity);
|
||||
if (checkMsgId(id, vm)) {
|
||||
errors.add(vm.setMessageId(id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -802,5 +858,9 @@ public class BaseValidator {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ValidationControl> getValidationControl() {
|
||||
return validationControl;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -34,6 +34,7 @@ import org.hl7.fhir.r5.utils.*;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.*;
|
||||
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.validation.BaseValidator.ValidationControl;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.utilities.IniFile;
|
||||
@ -309,6 +310,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
|
||||
private List<ImplementationGuide> igs = new ArrayList<>();
|
||||
private boolean showTimes;
|
||||
private List<BundleValidationRule> bundleValidationRules = new ArrayList<>();
|
||||
private Map<String, ValidationControl> validationControl = new HashMap<>();
|
||||
|
||||
private class AsteriskFilter implements FilenameFilter {
|
||||
String dir;
|
||||
@ -1580,6 +1582,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
|
||||
validator.setFetcher(this);
|
||||
validator.getImplementationGuides().addAll(igs);
|
||||
validator.getBundleValidationRules().addAll(bundleValidationRules);
|
||||
validator.getValidationControl().putAll(validationControl );
|
||||
return validator;
|
||||
}
|
||||
|
||||
@ -2391,9 +2394,27 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
|
||||
return pcm.packageExists(id, ver);
|
||||
}
|
||||
|
||||
|
||||
public void loadPackage(String id, String ver) throws IOException, FHIRException {
|
||||
loadIg(id+(ver == null ? "" : "#"+ver), true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Systems that host the ValidationEngine can use this to control what validation the validator performs.
|
||||
*
|
||||
* Using this, you can turn particular kinds of validation on and off. In addition, you can override
|
||||
* the error | warning | hint level and make it a different level.
|
||||
*
|
||||
* Each entry has
|
||||
* * 'allowed': a boolean flag. if this is false, the Validator will not report the error.
|
||||
* * 'level' : set to error, warning, information
|
||||
*
|
||||
* Entries are registered by ID, using the IDs in /org.hl7.fhir.utilities/src/main/resources/Messages.properties
|
||||
*
|
||||
* This feature is not supported by the validator CLI - and won't be. It's for systems hosting
|
||||
* the validation framework in their own implementation context
|
||||
*/
|
||||
public Map<String, ValidationControl> getValidationControl() {
|
||||
return validationControl;
|
||||
}
|
||||
|
||||
}
|
@ -491,17 +491,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
return false;
|
||||
}
|
||||
|
||||
private void bpCheck(List<ValidationMessage> errors, IssueType invalid, int line, int col, String literalPath, boolean test, String message) {
|
||||
private void bpCheck(List<ValidationMessage> errors, IssueType invalid, int line, int col, String literalPath, boolean test, String message, Object... theMessageArguments) {
|
||||
if (bpWarnings != null) {
|
||||
switch (bpWarnings) {
|
||||
case Error:
|
||||
rule(errors, invalid, line, col, literalPath, test, message);
|
||||
rule(errors, invalid, line, col, literalPath, test, message, theMessageArguments);
|
||||
break;
|
||||
case Warning:
|
||||
warning(errors, invalid, line, col, literalPath, test, message);
|
||||
warning(errors, invalid, line, col, literalPath, test, message, theMessageArguments);
|
||||
break;
|
||||
case Hint:
|
||||
hint(errors, invalid, line, col, literalPath, test, message);
|
||||
hint(errors, invalid, line, col, literalPath, test, message, theMessageArguments);
|
||||
break;
|
||||
default: // do nothing
|
||||
break;
|
||||
@ -2070,7 +2070,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
checkInnerNS(errors, e, path, xhtml.getChildNodes());
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, "div".equals(xhtml.getName()), I18nConstants.XHTML_XHTML_NAME_INVALID, ns);
|
||||
// check that no illegal elements and attributes have been used
|
||||
checkInnerNames(errors, e, path, xhtml.getChildNodes());
|
||||
checkInnerNames(errors, e, path, xhtml.getChildNodes(), false);
|
||||
checkUrls(errors, e, path, xhtml.getChildNodes());
|
||||
}
|
||||
}
|
||||
@ -2171,7 +2171,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
"http://hl7.org/fhirpath/System.Decimal", "http://hl7.org/fhirpath/System.Date", "http://hl7.org/fhirpath/System.Time", "http://hl7.org/fhirpath/System.DateTime", "http://hl7.org/fhirpath/System.Quantity");
|
||||
}
|
||||
|
||||
private void checkInnerNames(List<ValidationMessage> errors, Element e, String path, List<XhtmlNode> list) {
|
||||
private void checkInnerNames(List<ValidationMessage> errors, Element e, String path, List<XhtmlNode> list, boolean inPara) {
|
||||
for (XhtmlNode node : list) {
|
||||
if (node.getNodeType() == NodeType.Comment) {
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !node.getContent().startsWith("DOCTYPE"), I18nConstants.XHTML_XHTML_DOCTYPE_ILLEGAL);
|
||||
@ -2181,9 +2181,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
"p", "br", "div", "h1", "h2", "h3", "h4", "h5", "h6", "a", "span", "b", "em", "i", "strong",
|
||||
"small", "big", "tt", "small", "dfn", "q", "var", "abbr", "acronym", "cite", "blockquote", "hr", "address", "bdo", "kbd", "q", "sub", "sup",
|
||||
"ul", "ol", "li", "dl", "dt", "dd", "pre", "table", "caption", "colgroup", "col", "thead", "tr", "tfoot", "tbody", "th", "td",
|
||||
"code", "samp", "img", "map", "area"
|
||||
|
||||
), I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL, node.getName());
|
||||
"code", "samp", "img", "map", "area"), I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL, node.getName());
|
||||
|
||||
for (String an : node.getAttributes().keySet()) {
|
||||
boolean ok = an.startsWith("xmlns") || Utilities.existsInList(an,
|
||||
"title", "style", "class", ID, "lang", "xml:lang", "dir", "accesskey", "tabindex",
|
||||
@ -2195,11 +2194,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
"img.alt", "img.longdesc", "img.height", "img.width", "img.usemap", "img.ismap", "map.name", "area.shape",
|
||||
"area.coords", "area.href", "area.nohref", "area.alt", "table.summary", "table.width", "table.border",
|
||||
"table.frame", "table.rules", "table.cellspacing", "table.cellpadding", "pre.space", "td.nowrap"
|
||||
);
|
||||
if (!ok)
|
||||
);
|
||||
if (!ok) {
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.XHTML_XHTML_ATTRIBUTE_ILLEGAL, an, node.getName());
|
||||
}
|
||||
}
|
||||
checkInnerNames(errors, e, path, node.getChildNodes());
|
||||
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !(inPara && Utilities.existsInList(node.getName(), "div", "blockquote", "table", "ol", "ul", "p")) , I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA, node.getName());
|
||||
|
||||
checkInnerNames(errors, e, path, node.getChildNodes(), inPara || "p".equals(node.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2320,6 +2323,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||
if (system != null || code != null ) {
|
||||
checkCodedElement(theErrors, thePath, element, theProfile, definition, false, false, theStack, code, system, unit);
|
||||
}
|
||||
|
||||
if (code != null && "http://unitsofmeasure.org".equals(system)) {
|
||||
int b = code.indexOf("{");
|
||||
int e = code.indexOf("}");
|
||||
if (b >= 0 && e > 0 && b < e) {
|
||||
bpCheck(theErrors, IssueType.BUSINESSRULE, element.line(), element.col(), thePath, !code.contains("{"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS, code.substring(b, e+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAttachment(List<ValidationMessage> errors, String path, Element element, StructureDefinition theProfile, ElementDefinition definition, boolean theInCodeableConcept, boolean theCheckDisplayInContext, NodeStack theStack) {
|
||||
|
@ -36,6 +36,7 @@ import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.BestPracticeWarningLevel;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
|
||||
@ -204,6 +205,9 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
||||
} else {
|
||||
val.setDebug(false);
|
||||
}
|
||||
if (content.has("best-practice")) {
|
||||
val.setBestPracticeWarningLevel(BestPracticeWarningLevel.valueOf(content.get("best-practice").getAsString()));
|
||||
}
|
||||
if (content.has("examples")) {
|
||||
val.setAllowExamples(content.get("examples").getAsBoolean());
|
||||
} else {
|
||||
@ -367,10 +371,12 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
||||
}
|
||||
if (!TestingUtilities.context(version).isNoTerminologyServer() || !focus.has("tx-dependent")) {
|
||||
Assert.assertEquals("Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("errorCount").getAsInt()) + " errors, but found " + Integer.toString(ec) + ".", java.get("errorCount").getAsInt(), ec);
|
||||
if (java.has("warningCount"))
|
||||
if (java.has("warningCount")) {
|
||||
Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("warningCount").getAsInt()) + " warnings, but found " + Integer.toString(wc) + ".", java.get("warningCount").getAsInt(), wc);
|
||||
if (java.has("infoCount"))
|
||||
}
|
||||
if (java.has("infoCount")) {
|
||||
Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("infoCount").getAsInt()) + " hints, but found " + Integer.toString(hc) + ".", java.get("infoCount").getAsInt(), hc);
|
||||
}
|
||||
}
|
||||
if (java.has("error-locations")) {
|
||||
JsonArray el = java.getAsJsonArray("error-locations");
|
||||
|
Loading…
x
Reference in New Issue
Block a user