Merge branch 'master' into bugfix-condition-convert-abatement
This commit is contained in:
commit
ff25ab2eef
|
@ -1 +1,17 @@
|
|||
Validator:
|
||||
|
||||
* Add support for $index on aggregators in FHIRPath
|
||||
* don't fail with an exception if an unknown resource type appears in contained resource
|
||||
* improved validation for some value sets that are based on unknown code systems
|
||||
* add the -verbose parameter, and add additional verbose messages
|
||||
|
||||
Conversion code:
|
||||
|
||||
* Ignoring abatementBoolean when converting from dstu2 to r4
|
||||
|
||||
Other code changes:
|
||||
|
||||
* Fix rendering of slices so type on slicer is not hidden
|
||||
* Fix rendering for most resources - remove empty tables (e.g. text element, that shouldn't render)
|
||||
* Fix NPE rendering code systems with some kinds of properties
|
||||
* Improve rendering of questionnaires (icons, option sets)
|
||||
|
|
|
@ -4044,6 +4044,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
hint = checkAdd(hint, (hasDef && element.hasSliceName() ? ": " : ""));
|
||||
hint = checkAdd(hint, !hasDef ? null : gt(element.getDefinitionElement()));
|
||||
}
|
||||
if (element.hasSlicing()) {
|
||||
sName = "Slices for "+sName;
|
||||
}
|
||||
Cell left = gen.new Cell(null, ref, sName, hint, null);
|
||||
row.getCells().add(left);
|
||||
return left;
|
||||
|
@ -4102,9 +4105,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
} else {
|
||||
res.add(genCardinality(gen, element, row, hasDef, used, null));
|
||||
if (element.hasSlicing())
|
||||
res.add(addCell(row, gen.new Cell(null, corePath+"profiling.html#slicing", "(Slice Definition)", null, null)));
|
||||
else if (hasDef && !"0".equals(element.getMax()) && typesRow == null)
|
||||
if (hasDef && !"0".equals(element.getMax()) && typesRow == null)
|
||||
res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport));
|
||||
else
|
||||
res.add(addCell(row, gen.new Cell()));
|
||||
|
|
|
@ -366,11 +366,13 @@ public class JsonParser extends ParserBase {
|
|||
} else {
|
||||
String name = rt.getAsString();
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs()));
|
||||
if (sd == null)
|
||||
throw new FHIRFormatError(context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name));
|
||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||
parent.setType(name);
|
||||
parseChildren(npath, res, parent, true);
|
||||
if (sd == null) {
|
||||
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL);
|
||||
} else {
|
||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||
parent.setType(name);
|
||||
parseChildren(npath, res, parent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ public class ExpressionNode {
|
|||
if (!name.startsWith("$"))
|
||||
return true;
|
||||
else
|
||||
return Utilities.existsInList(name, "$this", "$total");
|
||||
return Utilities.existsInList(name, "$this", "$total", "$index");
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
|
|
|
@ -701,18 +701,24 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
} 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 xn = new XhtmlNode(NodeType.Element, getHeader());
|
||||
xn.addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
|
||||
tbl.setAttribute("class", "grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.td().tx("-"); // work around problem with empty table rows
|
||||
addColumnHeadings(tr, grandChildren);
|
||||
boolean add = addColumnHeadings(tr, grandChildren);
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("*"); // work around problem with empty table rows
|
||||
addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent);
|
||||
add = addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent) || add;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
x.add(xn);
|
||||
x.add(tbl);
|
||||
}
|
||||
} else if (isExtension(p)) {
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
|
@ -776,6 +782,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
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))
|
||||
|
@ -812,24 +819,32 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void addColumnHeadings(XhtmlNode tr, List<ElementDefinition> grandChildren) {
|
||||
for (ElementDefinition e : grandChildren)
|
||||
private boolean addColumnHeadings(XhtmlNode tr, List<ElementDefinition> grandChildren) {
|
||||
boolean b = false;
|
||||
for (ElementDefinition e : grandChildren) {
|
||||
b = true;
|
||||
tr.td().b().addText(Utilities.capitalize(tail(e.getPath())));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private void addColumnValues(ResourceWrapper res, XhtmlNode tr, List<ElementDefinition> grandChildren, BaseWrapper v, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||
private boolean addColumnValues(ResourceWrapper res, XhtmlNode tr, List<ElementDefinition> grandChildren, BaseWrapper v, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||
boolean b = false;
|
||||
for (ElementDefinition e : grandChildren) {
|
||||
PropertyWrapper p = v.getChildByName(e.getPath().substring(e.getPath().lastIndexOf(".")+1));
|
||||
XhtmlNode td = tr.td();
|
||||
if (p == null || p.getValues().size() == 0 || p.getValues().get(0) == null)
|
||||
if (p == null || p.getValues().size() == 0 || p.getValues().get(0) == null) {
|
||||
b = true;
|
||||
td.tx(" ");
|
||||
else {
|
||||
} else {
|
||||
for (BaseWrapper vv : p.getValues()) {
|
||||
b = true;
|
||||
td.sep(", ");
|
||||
renderLeaf(res, vv, e, td, td, false, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private void filterGrandChildren(List<ElementDefinition> grandChildren, String string, PropertyWrapper prop) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hl7.fhir.r5.model.Coding;
|
|||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Expression;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Questionnaire;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
|
@ -60,7 +61,11 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
|
||||
public boolean renderTree(XhtmlNode x, Questionnaire q) throws UnsupportedEncodingException, IOException {
|
||||
boolean hasFlags = checkForFlags(q.getItem());
|
||||
boolean doOpts = context.getDefinitionsTarget() == null && hasAnyOptions(q.getItem());
|
||||
|
||||
if (doOpts) {
|
||||
x.b().tx("Structure");
|
||||
}
|
||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
|
||||
TableModel model = gen.new TableModel("qtree="+q.getId(), !forResource);
|
||||
model.setAlternating(true);
|
||||
|
@ -83,9 +88,79 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
}
|
||||
XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null);
|
||||
x.getChildNodes().add(xn);
|
||||
if (doOpts) {
|
||||
renderOptions(q, x);
|
||||
}
|
||||
return hasExt;
|
||||
}
|
||||
|
||||
private void renderOptions(Questionnaire q, XhtmlNode x) {
|
||||
if (hasAnyOptions(q.getItem())) {
|
||||
x.hr();
|
||||
x.para().b().tx("Option Sets");
|
||||
renderOptions(q.getItem(), x);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderOptions(List<QuestionnaireItemComponent> items, XhtmlNode x) {
|
||||
for (QuestionnaireItemComponent i : items) {
|
||||
renderItemOptions(x, i);
|
||||
renderOptions(i.getItem(), x);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderItemOptions(XhtmlNode x, QuestionnaireItemComponent i) {
|
||||
if (i.hasAnswerOption()) {
|
||||
boolean useSelect = false;
|
||||
for (QuestionnaireItemAnswerOptionComponent opt : i.getAnswerOption()) {
|
||||
useSelect = useSelect || opt.getInitialSelected();
|
||||
}
|
||||
x.an("opt-item."+i.getLinkId());
|
||||
x.para().b().tx("Answer options for "+i.getLinkId());
|
||||
XhtmlNode ul = x.ul();
|
||||
for (QuestionnaireItemAnswerOptionComponent opt : i.getAnswerOption()) {
|
||||
XhtmlNode li = ul.li();
|
||||
li.style("font-size: 11px");
|
||||
if (useSelect) {
|
||||
if (opt.getInitialSelected()) {
|
||||
li.img("icon-selected.png");
|
||||
} else {
|
||||
li.img("icon-not-selected.png");
|
||||
}
|
||||
}
|
||||
if (opt.getValue().isPrimitive()) {
|
||||
li.tx(opt.getValue().primitiveValue());
|
||||
} else if (opt.getValue() instanceof Coding) {
|
||||
Coding c = (Coding) opt.getValue();
|
||||
String link = context.getWorker().getLinkForUrl(context.getSpecificationLink(), c.getSystem());
|
||||
if (link == null) {
|
||||
li.tx(c.getSystem()+"#"+c.getCode());
|
||||
} else {
|
||||
li.ah(link).tx(describeSystem(c.getSystem()));
|
||||
li.tx(": "+c.getCode());
|
||||
}
|
||||
if (c.hasDisplay()) {
|
||||
li.tx(" (\""+c.getDisplay()+"\")");
|
||||
}
|
||||
} else {
|
||||
li.tx("??");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasAnyOptions(List<QuestionnaireItemComponent> items) {
|
||||
for (QuestionnaireItemComponent i : items) {
|
||||
if (i.hasAnswerOption()) {
|
||||
return true;
|
||||
}
|
||||
if (hasAnyOptions(i.getItem())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkForFlags(List<QuestionnaireItemComponent> items) {
|
||||
for (QuestionnaireItemComponent i : items) {
|
||||
if (checkForFlags(i)) {
|
||||
|
@ -228,7 +303,12 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
if (i.hasAnswerOption()) {
|
||||
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
|
||||
defn.getPieces().add(gen.new Piece(null, "Options: ", null));
|
||||
defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null));
|
||||
if (context.getDefinitionsTarget() == null) {
|
||||
// if we don't have a definitions target, we'll add them below.
|
||||
defn.getPieces().add(gen.new Piece("#opt-item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null));
|
||||
} else {
|
||||
defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null));
|
||||
}
|
||||
}
|
||||
if (i.hasInitial()) {
|
||||
for (QuestionnaireItemInitialComponent v : i.getInitial()) {
|
||||
|
@ -725,7 +805,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
}
|
||||
}
|
||||
} else if (i.hasAnswerOption()) {
|
||||
|
||||
renderItemOptions(select, i);
|
||||
}
|
||||
select.option("a", "??", false);
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
|
|||
if (cs == null) {
|
||||
return null;
|
||||
}
|
||||
ConceptDefinitionComponent cc = CodeSystemUtilities.getCode(cs, code);
|
||||
ConceptDefinitionComponent cc = code == null ? null : CodeSystemUtilities.getCode(cs, code);
|
||||
return cc == null ? null : cc.getDisplay();
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,9 @@ public class CodeSystemUtilities {
|
|||
}
|
||||
|
||||
public static ConceptDefinitionComponent getCode(CodeSystem cs, String code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
for (ConceptDefinitionComponent cc : cs.getConcept()) {
|
||||
ConceptDefinitionComponent cd = getCode(cc, code);
|
||||
if (cd != null) {
|
||||
|
|
|
@ -130,6 +130,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
|
||||
ValidationResult res = null;
|
||||
boolean inExpansion = false;
|
||||
boolean inInclude = false;
|
||||
String system = code.hasSystem() ? code.getSystem() : getValueSetSystemOrNull();
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
if (system == null && !code.hasDisplay()) { // dealing with just a plain code (enum)
|
||||
|
@ -142,6 +143,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
code.setSystem(system);
|
||||
}
|
||||
inExpansion = checkExpansion(code);
|
||||
inInclude = checkInclude(code);
|
||||
CodeSystem cs = context.fetchCodeSystem(system);
|
||||
if (cs == null) {
|
||||
cs = findSpecialCodeSystem(system);
|
||||
|
@ -181,26 +183,58 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
throw new FHIRException("No try the server");
|
||||
}
|
||||
} else {
|
||||
// disabled waiting for discussion
|
||||
throw new FHIRException("No try the server");
|
||||
// inExpansion = checkExpansion(code);
|
||||
inExpansion = checkExpansion(code);
|
||||
inInclude = checkInclude(code);
|
||||
}
|
||||
|
||||
// then, if we have a value set, we check it's in the value set
|
||||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
if ((res==null || res.isOk()) && !codeInValueSet(system, code.getCode())) {
|
||||
if (!inExpansion) {
|
||||
res.setMessage("Not in value set "+valueset.getUrl()).setSeverity(IssueSeverity.ERROR);
|
||||
} else if (warningMessage!=null) {
|
||||
res = new ValidationResult(IssueSeverity.WARNING, context.formatMessage(I18nConstants.CODE_FOUND_IN_EXPANSION_HOWEVER_, warningMessage));
|
||||
} else {
|
||||
res.setMessage("Code found in expansion, however: " + res.getMessage());
|
||||
if ((res==null || res.isOk())) {
|
||||
Boolean ok = codeInValueSet(system, code.getCode());
|
||||
if (ok == null || !ok) {
|
||||
if (res == null) {
|
||||
res = new ValidationResult(null, null);
|
||||
}
|
||||
if (!inExpansion && !inInclude) {
|
||||
res.setMessage("Not in value set "+valueset.getUrl()).setSeverity(IssueSeverity.ERROR);
|
||||
} else if (warningMessage!=null) {
|
||||
res = new ValidationResult(IssueSeverity.WARNING, context.formatMessage(I18nConstants.CODE_FOUND_IN_EXPANSION_HOWEVER_, warningMessage));
|
||||
} else if (inExpansion) {
|
||||
res.setMessage("Code found in expansion, however: " + res.getMessage());
|
||||
} else if (inInclude) {
|
||||
res.setMessage("Code found in include, however: " + res.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private boolean checkInclude(Coding code) {
|
||||
if (valueset == null || code.getSystem() == null || code.getCode() == null) {
|
||||
return false;
|
||||
}
|
||||
for (ConceptSetComponent inc : valueset.getCompose().getExclude()) {
|
||||
if (inc.hasSystem() && inc.getSystem().equals(code.getSystem())) {
|
||||
for (ConceptReferenceComponent cc : inc.getConcept()) {
|
||||
if (cc.hasCode() && cc.getCode().equals(code.getCode())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ConceptSetComponent inc : valueset.getCompose().getInclude()) {
|
||||
if (inc.hasSystem() && inc.getSystem().equals(code.getSystem())) {
|
||||
for (ConceptReferenceComponent cc : inc.getConcept()) {
|
||||
if (cc.hasCode() && cc.getCode().equals(code.getCode())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private CodeSystem findSpecialCodeSystem(String system) {
|
||||
if ("urn:ietf:rfc:3986".equals(system)) {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
|
|
|
@ -873,6 +873,7 @@ public class FHIRPathEngine {
|
|||
private Base thisItem;
|
||||
private List<Base> total;
|
||||
private Map<String, Base> aliases;
|
||||
private int index;
|
||||
|
||||
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Map<String, Base> aliases, Base thisItem) {
|
||||
this.appInfo = appInfo;
|
||||
|
@ -881,6 +882,7 @@ public class FHIRPathEngine {
|
|||
this.rootResource = rootResource;
|
||||
this.aliases = aliases;
|
||||
this.thisItem = thisItem;
|
||||
this.index = 0;
|
||||
}
|
||||
public Base getFocusResource() {
|
||||
return focusResource;
|
||||
|
@ -894,6 +896,14 @@ public class FHIRPathEngine {
|
|||
public List<Base> getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
index++;
|
||||
}
|
||||
public Base getIndex() {
|
||||
return new IntegerType(index);
|
||||
}
|
||||
|
||||
public void addAlias(String name, List<Base> focus) throws FHIRException {
|
||||
if (aliases == null) {
|
||||
aliases = new HashMap<String, Base>();
|
||||
|
@ -908,6 +918,10 @@ public class FHIRPathEngine {
|
|||
public Base getAlias(String name) {
|
||||
return aliases == null ? null : aliases.get(name);
|
||||
}
|
||||
public ExecutionContext setIndex(int i) {
|
||||
index = i;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private class ExecutionTypeContext {
|
||||
|
@ -1334,6 +1348,8 @@ public class FHIRPathEngine {
|
|||
work.add(context.getThisItem());
|
||||
} else if (atEntry && exp.getName().equals("$total")) {
|
||||
work.addAll(context.getTotal());
|
||||
} else if (atEntry && exp.getName().equals("$index")) {
|
||||
work.add(context.getIndex());
|
||||
} else {
|
||||
for (Base item : focus) {
|
||||
List<Base> outcome = execute(context, item, exp, atEntry);
|
||||
|
@ -1439,6 +1455,8 @@ public class FHIRPathEngine {
|
|||
result.update(context.getThisItem());
|
||||
} else if (atEntry && exp.getName().equals("$total")) {
|
||||
result.update(anything(CollectionStatus.UNORDERED));
|
||||
} else if (atEntry && exp.getName().equals("$index")) {
|
||||
result.addType(TypeDetails.FP_Integer);
|
||||
} else if (atEntry && focus == null) {
|
||||
result.update(executeContextType(context, exp.getName(), exp));
|
||||
} else {
|
||||
|
@ -4346,6 +4364,7 @@ public class FHIRPathEngine {
|
|||
for (Base item : focus) {
|
||||
ExecutionContext c = changeThis(context, item);
|
||||
c.total = total;
|
||||
c.next();
|
||||
total = execute(c, pc, exp.getParameters().get(0), true);
|
||||
}
|
||||
return total;
|
||||
|
@ -5117,10 +5136,12 @@ public class FHIRPathEngine {
|
|||
private List<Base> funcSelect(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
|
||||
List<Base> result = new ArrayList<Base>();
|
||||
List<Base> pc = new ArrayList<Base>();
|
||||
int i = 0;
|
||||
for (Base item : focus) {
|
||||
pc.clear();
|
||||
pc.add(item);
|
||||
result.addAll(execute(changeThis(context, item), pc, exp.getParameters().get(0), true));
|
||||
result.addAll(execute(changeThis(context, item).setIndex(i), pc, exp.getParameters().get(0), true));
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ public class OperationOutcomeUtilities {
|
|||
if (message.getSource() != null) {
|
||||
issue.getExtension().add(ToolingExtensions.makeIssueSource(message.getSource()));
|
||||
}
|
||||
issue.setUserData("source.msg", message);
|
||||
return issue;
|
||||
}
|
||||
|
||||
|
|
|
@ -511,6 +511,7 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
|||
private String locationLink;
|
||||
private String txLink;
|
||||
public String sliceHtml;
|
||||
public String[] sliceText;
|
||||
private boolean slicingHint;
|
||||
private boolean signpost;
|
||||
|
||||
|
@ -771,8 +772,9 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
|||
return sliceHtml;
|
||||
}
|
||||
|
||||
public void setSliceHtml(String sliceHtml) {
|
||||
public void setSliceHtml(String sliceHtml, String[] text) {
|
||||
this.sliceHtml = sliceHtml;
|
||||
this.sliceText = text;
|
||||
}
|
||||
|
||||
public String getMessageId() {
|
||||
|
|
|
@ -262,9 +262,9 @@ public class BaseValidator {
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
//FIXME: formatMessage should be done here
|
||||
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html) {
|
||||
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html, String[] text) {
|
||||
if (!thePass) {
|
||||
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html);
|
||||
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
|
|
@ -97,12 +97,12 @@ public class ValidationService {
|
|||
if (cliContext.getOutput() == null) {
|
||||
if (r instanceof Bundle)
|
||||
for (Bundle.BundleEntryComponent e : ((Bundle) r).getEntry())
|
||||
ec = ec + displayOperationOutcome((OperationOutcome) e.getResource(), ((Bundle) r).getEntry().size() > 1) + ec;
|
||||
ec = ec + displayOperationOutcome((OperationOutcome) e.getResource(), ((Bundle) r).getEntry().size() > 1, validator.isCrumbTrails()) + ec;
|
||||
else if (r == null) {
|
||||
ec = ec + 1;
|
||||
System.out.println("No output from validation - nothing to validate");
|
||||
} else {
|
||||
ec = displayOperationOutcome((OperationOutcome) r, false);
|
||||
ec = displayOperationOutcome((OperationOutcome) r, false, validator.isCrumbTrails());
|
||||
}
|
||||
} else {
|
||||
IParser x;
|
||||
|
@ -262,7 +262,7 @@ public class ValidationService {
|
|||
return sessionId;
|
||||
}
|
||||
|
||||
public int displayOperationOutcome(OperationOutcome oo, boolean hasMultiples) {
|
||||
public int displayOperationOutcome(OperationOutcome oo, boolean hasMultiples, boolean crumbs) {
|
||||
int error = 0;
|
||||
int warn = 0;
|
||||
int info = 0;
|
||||
|
@ -286,6 +286,16 @@ public class ValidationService {
|
|||
System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes");
|
||||
for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) {
|
||||
System.out.println(getIssueSummary(issue));
|
||||
if (crumbs) {
|
||||
ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg");
|
||||
if (vm != null) {
|
||||
if (vm.sliceText != null) {
|
||||
for (String s : vm.sliceText) {
|
||||
System.out.println(" slice info: "+s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasMultiples) {
|
||||
System.out.print("---");
|
||||
|
|
|
@ -56,6 +56,7 @@ public class Params {
|
|||
public static final String WANT_INVARIANTS_IN_MESSAGES = "-want-invariants-in-messages";
|
||||
public static final String SECURITY_CHECKS = "-security-checks";
|
||||
public static final String CRUMB_TRAIL = "-crumb-trails";
|
||||
public static final String VERBOSE = "-verbose";
|
||||
public static final String SHOW_TIMES = "-show-times";
|
||||
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
|
||||
|
||||
|
@ -183,6 +184,8 @@ public class Params {
|
|||
cliContext.setSecurityChecks(true);
|
||||
} else if (args[i].equals(CRUMB_TRAIL)) {
|
||||
cliContext.setCrumbTrails(true);
|
||||
} else if (args[i].equals(VERBOSE)) {
|
||||
cliContext.setCrumbTrails(true);
|
||||
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {
|
||||
String bl = args[++i];
|
||||
if ("true".equals(bl)) {
|
||||
|
|
|
@ -2722,7 +2722,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
|
||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false,
|
||||
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)));
|
||||
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
||||
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
||||
}
|
||||
} else {
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() == 1, I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile()));
|
||||
|
@ -2738,7 +2739,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (!isShowMessagesFromReferences()) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
|
||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)));
|
||||
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()),
|
||||
errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd)));
|
||||
}
|
||||
} else {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet()));
|
||||
|
@ -2864,6 +2866,24 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return "<ul>" + b.toString() + "</ul>";
|
||||
}
|
||||
|
||||
private String[] errorSummaryForSlicingAsText(List<ValidationMessage> list) {
|
||||
List<String> res = new ArrayList<String>();
|
||||
for (ValidationMessage vm : list) {
|
||||
if (vm.isSlicingHint()) {
|
||||
if (vm.sliceText != null) {
|
||||
for (String s : vm.sliceText) {
|
||||
res.add(vm.getLocation() + ": " + s);
|
||||
}
|
||||
} else {
|
||||
res.add(vm.getLocation() + ": " + vm.getMessage());
|
||||
}
|
||||
} else if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL) {
|
||||
res.add(vm.getLocation() + ": " + vm.getHtml());
|
||||
}
|
||||
}
|
||||
return res.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private TypeRefComponent getReferenceTypeRef(List<TypeRefComponent> types) {
|
||||
for (TypeRefComponent tr : types) {
|
||||
if ("Reference".equals(tr.getCode())) {
|
||||
|
@ -3619,13 +3639,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
ValidatorHostContext shc = hostContext.forSlicing();
|
||||
boolean pass = evaluateSlicingExpression(shc, element, path, profile, n);
|
||||
if (!pass) {
|
||||
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()));
|
||||
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()), null);
|
||||
for (String url : shc.getSliceRecords().keySet()) {
|
||||
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false,
|
||||
context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, stack.getLiteralPath(), url),
|
||||
context.formatMessage(I18nConstants.PROFILE__DOES_NOT_MATCH_FOR__BECAUSE_OF_THE_FOLLOWING_PROFILE_ISSUES__,
|
||||
url,
|
||||
stack.getLiteralPath(), errorSummaryForSlicingAsHtml(shc.getSliceRecords().get(url))));
|
||||
stack.getLiteralPath(), errorSummaryForSlicingAsHtml(shc.getSliceRecords().get(url))), errorSummaryForSlicingAsText(shc.getSliceRecords().get(url)));
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
|
@ -4830,7 +4850,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.getPath(), false,
|
||||
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_,
|
||||
profile == null ? "" : " defined in the profile " + profile.getUrl()),
|
||||
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo));
|
||||
context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo),
|
||||
errorSummaryForSlicingAsText(ei.sliceInfo));
|
||||
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
|
||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.getPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTSLICE, (profile == null ? "" : " defined in the profile " + profile.getUrl()), errorSummaryForSlicing(ei.sliceInfo));
|
||||
}
|
||||
|
@ -5337,7 +5358,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, Coding c, boolean checkMembership) {
|
||||
if (checkMembership) {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()), c, valueset);
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).checkValueSetOnly(), c, valueset);
|
||||
} else {
|
||||
return context.validateCode(new ValidationOptions(stack.getWorkingLang()).noCheckValueSetMembership(), c, valueset);
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -19,7 +19,7 @@
|
|||
|
||||
<properties>
|
||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||
<validator_test_case_version>1.1.64</validator_test_case_version>
|
||||
<validator_test_case_version>1.1.65-SNAPSHOT</validator_test_case_version>
|
||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
||||
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
||||
|
|
Loading…
Reference in New Issue