Add tests
This commit is contained in:
parent
19863de012
commit
8c10d96416
|
@ -1,8 +1,17 @@
|
|||
package org.hl7.fhir.dstu3.conformance;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution;
|
||||
|
@ -11,15 +20,50 @@ import org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult;
|
|||
import org.hl7.fhir.dstu3.elementmodel.ObjectConverter;
|
||||
import org.hl7.fhir.dstu3.elementmodel.Property;
|
||||
import org.hl7.fhir.dstu3.formats.IParser;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.*;
|
||||
import org.hl7.fhir.dstu3.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.dstu3.formats.XmlParser;
|
||||
import org.hl7.fhir.dstu3.model.Base;
|
||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.Element;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.AggregationMode;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.DiscriminatorType;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBaseComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionExampleComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionMappingComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionSlicingComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.SlicingRules;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.dstu3.model.Enumeration;
|
||||
import org.hl7.fhir.dstu3.model.Enumerations.BindingStrength;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.*;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||
import org.hl7.fhir.dstu3.model.PrimitiveType;
|
||||
import org.hl7.fhir.dstu3.model.Quantity;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionDifferentialComponent;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionMappingComponent;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionSnapshotComponent;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.TypeDerivationRule;
|
||||
import org.hl7.fhir.dstu3.model.Type;
|
||||
import org.hl7.fhir.dstu3.model.UriType;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.dstu3.utils.*;
|
||||
import org.hl7.fhir.dstu3.utils.NarrativeGenerator;
|
||||
import org.hl7.fhir.dstu3.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.dstu3.utils.TranslatingUtilities;
|
||||
import org.hl7.fhir.dstu3.utils.formats.CSVWriter;
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -28,10 +72,15 @@ import org.hl7.fhir.utilities.Utilities;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.*;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xml.SchematronWriter;
|
||||
import org.hl7.fhir.utilities.xml.SchematronWriter.*;
|
||||
import org.hl7.fhir.utilities.xml.SchematronWriter.Rule;
|
||||
import org.hl7.fhir.utilities.xml.SchematronWriter.SchematronType;
|
||||
import org.hl7.fhir.utilities.xml.SchematronWriter.Section;
|
||||
|
||||
/**
|
||||
* This class provides a set of utility operations for working with Profiles.
|
||||
|
@ -208,36 +257,46 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
* @param path The path of the element within the structure to get the children for
|
||||
* @return A List containing the element children (all of them are Elements)
|
||||
*/
|
||||
public static List<ElementDefinition> getChildList(StructureDefinition profile, String path) {
|
||||
public static List<ElementDefinition> getChildList(StructureDefinition profile, String path, String id) {
|
||||
List<ElementDefinition> res = new ArrayList<ElementDefinition>();
|
||||
|
||||
for (ElementDefinition e : profile.getSnapshot().getElement())
|
||||
{
|
||||
String p = e.getPath();
|
||||
|
||||
if (!Utilities.noString(e.getContentReference()) && path.startsWith(p))
|
||||
{
|
||||
if (path.length() > p.length())
|
||||
return getChildList(profile, e.getContentReference()+"."+path.substring(p.length()+1));
|
||||
else
|
||||
return getChildList(profile, e.getContentReference());
|
||||
boolean capturing = id==null;
|
||||
if (id==null && !path.contains("."))
|
||||
capturing = true;
|
||||
|
||||
for (ElementDefinition e : profile.getSnapshot().getElement()) {
|
||||
if (!capturing && id!=null && e.getId().equals(id)) {
|
||||
capturing = true;
|
||||
}
|
||||
else if (p.startsWith(path+".") && !p.equals(path))
|
||||
{
|
||||
|
||||
// If our element is a slice, stop capturing children as soon as we see the next slice
|
||||
if (capturing && e.hasId() && id!= null && !e.getId().equals(id) && e.getPath().equals(path))
|
||||
break;
|
||||
|
||||
if (capturing) {
|
||||
String p = e.getPath();
|
||||
|
||||
if (!Utilities.noString(e.getContentReference()) && path.startsWith(p)) {
|
||||
if (path.length() > p.length())
|
||||
return getChildList(profile, e.getContentReference()+"."+path.substring(p.length()+1), null);
|
||||
else
|
||||
return getChildList(profile, e.getContentReference(), null);
|
||||
|
||||
} else if (p.startsWith(path+".") && !p.equals(path)) {
|
||||
String tail = p.substring(path.length()+1);
|
||||
if (!tail.contains(".")) {
|
||||
res.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public static List<ElementDefinition> getChildList(StructureDefinition structure, ElementDefinition element) {
|
||||
return getChildList(structure, element.getPath());
|
||||
return getChildList(structure, element.getPath(), element.getId());
|
||||
}
|
||||
|
||||
public void updateMaps(StructureDefinition base, StructureDefinition derived) throws DefinitionException {
|
||||
|
@ -319,9 +378,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
System.out.println(" "+ed.getPath()+" : "+typeSummary(ed)+"["+ed.getMin()+".."+ed.getMax()+"]"+sliceSummary(ed)+" id = "+ed.getId());
|
||||
throw new DefinitionException("Snapshot for "+derived.getUrl()+" does not contain differential element with id: " + e.getId());
|
||||
// System.out.println("**BAD Differential element: " + profileName + ":" + e.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String sliceSummary(ElementDefinition ed) {
|
||||
if (!ed.hasSlicing() && !ed.hasSliceName())
|
||||
|
@ -451,7 +510,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
res = outcome;
|
||||
updateFromBase(outcome, currentBase);
|
||||
if (diffMatches.get(0).hasSliceName())
|
||||
outcome.setSliceName(diffMatches.get(0).getSliceName());
|
||||
outcome.setSliceName(diffMatches.get(0).getSliceName());
|
||||
outcome.setSlicing(null);
|
||||
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url);
|
||||
if (outcome.getPath().endsWith("[x]") && outcome.getType().size() == 1 && !outcome.getType().get(0).getCode().equals("*")) // if the base profile allows multiple types, but the profile only allows one, rename it
|
||||
|
@ -485,15 +544,15 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
nbl++;
|
||||
processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, profileName, tgt.getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false);
|
||||
} else {
|
||||
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0));
|
||||
if (dt == null)
|
||||
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") for type "+typeCode(outcome.getType())+" in profile "+profileName+", but can't find type");
|
||||
contextName = dt.getUrl();
|
||||
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start-1, dt.getSnapshot().getElement().size()-1,
|
||||
diffCursor - 1, url, profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false);
|
||||
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0));
|
||||
if (dt == null)
|
||||
throw new DefinitionException(diffMatches.get(0).getPath()+" has children ("+differential.getElement().get(diffCursor).getPath()+") for type "+typeCode(outcome.getType())+" in profile "+profileName+", but can't find type");
|
||||
contextName = dt.getUrl();
|
||||
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start-1, dt.getSnapshot().getElement().size()-1,
|
||||
diffCursor - 1, url, profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ok, the differential slices the item. Let's check our pre-conditions to ensure that this is correct
|
||||
if (!unbounded(currentBase) && !isSlicedToOneOnly(diffMatches.get(0)))
|
||||
|
@ -512,29 +571,29 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true).setSlicing(diffMatches.get(0).getSlicing());
|
||||
start++;
|
||||
} else {
|
||||
// we're just going to accept the differential slicing at face value
|
||||
ElementDefinition outcome = updateURLs(url, currentBase.copy());
|
||||
outcome.setPath(fixedPath(contextPathDst, outcome.getPath()));
|
||||
updateFromBase(outcome, currentBase);
|
||||
// we're just going to accept the differential slicing at face value
|
||||
ElementDefinition outcome = updateURLs(url, currentBase.copy());
|
||||
outcome.setPath(fixedPath(contextPathDst, outcome.getPath()));
|
||||
updateFromBase(outcome, currentBase);
|
||||
|
||||
if (!diffMatches.get(0).hasSlicing())
|
||||
outcome.setSlicing(makeExtensionSlicing());
|
||||
else
|
||||
outcome.setSlicing(diffMatches.get(0).getSlicing().copy());
|
||||
if (!outcome.getPath().startsWith(resultPathBase))
|
||||
throw new DefinitionException("Adding wrong path");
|
||||
result.getElement().add(outcome);
|
||||
if (!diffMatches.get(0).hasSlicing())
|
||||
outcome.setSlicing(makeExtensionSlicing());
|
||||
else
|
||||
outcome.setSlicing(diffMatches.get(0).getSlicing().copy());
|
||||
if (!outcome.getPath().startsWith(resultPathBase))
|
||||
throw new DefinitionException("Adding wrong path");
|
||||
result.getElement().add(outcome);
|
||||
|
||||
// differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice.
|
||||
if (!diffMatches.get(0).hasSliceName()) {
|
||||
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url);
|
||||
// differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice.
|
||||
if (!diffMatches.get(0).hasSliceName()) {
|
||||
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url);
|
||||
if (!outcome.hasContentReference() && !outcome.hasType()) {
|
||||
throw new DefinitionException("not done yet");
|
||||
}
|
||||
throw new DefinitionException("not done yet");
|
||||
}
|
||||
start++;
|
||||
// result.getElement().remove(result.getElement().size()-1);
|
||||
} else
|
||||
checkExtensionDoco(outcome);
|
||||
} else
|
||||
checkExtensionDoco(outcome);
|
||||
}
|
||||
// now, for each entry in the diff matches, we're going to process the base item
|
||||
// our processing scope for base is all the children of the current path
|
||||
|
@ -610,7 +669,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
result.getElement().add(outcome);
|
||||
|
||||
if (!diffMatches.get(0).hasSliceName()) { // it's not real content, just the slice
|
||||
diffpos++;
|
||||
diffpos++;
|
||||
}
|
||||
|
||||
// now, we have two lists, base and diff. we're going to work through base, looking for matches in diff.
|
||||
|
@ -648,6 +707,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
result.getElement().add(outcome);
|
||||
baseCursor++;
|
||||
}
|
||||
//Lloyd - add this for test T15
|
||||
baseCursor--;
|
||||
}
|
||||
}
|
||||
// finally, we process any remaining entries in diff, which are new (and which are only allowed if the base wasn't closed
|
||||
|
@ -717,7 +778,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int i = 0;
|
||||
for (ElementDefinition e : result.getElement()) {
|
||||
i++;
|
||||
|
@ -1733,7 +1794,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(gen.new Piece(corePath+"valueset-resource-aggregation-mode.html", "}", null));
|
||||
}
|
||||
}
|
||||
} else if (t.hasProfile()) { // a profiled type
|
||||
} else if (t.hasProfile() && (!t.getCode().equals("Extension") || t.getProfile().contains(":"))) { // a profiled type
|
||||
String ref;
|
||||
ref = pkp.getLinkForProfile(profile, t.getProfile());
|
||||
if (ref != null) {
|
||||
|
@ -1772,9 +1833,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
case BUNDLED : return "b";
|
||||
case CONTAINED : return "c";
|
||||
case REFERENCED: return "r";
|
||||
default: return "?";
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
|
||||
|
@ -1971,14 +2031,6 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
row.getCells().add(left);
|
||||
Cell gc = gen.new Cell();
|
||||
row.getCells().add(gc);
|
||||
if (element != null && element.getIsModifier())
|
||||
checkForNoChange(element.getIsModifierElement(), gc.addImage(imagePath+"modifier.png", translate("sd.table", "This element is a modifier element"), "?!", null, null));
|
||||
if (element != null && element.getMustSupport())
|
||||
checkForNoChange(element.getMustSupportElement(), gc.addImage(imagePath+"mustsupport.png", translate("sd.table", "This element must be supported"), "S", "white", "red"));
|
||||
if (element != null && element.getIsSummary())
|
||||
checkForNoChange(element.getIsSummaryElement(), gc.addImage(imagePath+"summary.png", translate("sd.table", "This element is included in summaries"), "Σ", null, null));
|
||||
if (element != null && (!element.getConstraint().isEmpty() || !element.getCondition().isEmpty()))
|
||||
gc.addImage(imagePath+"lock.png", translate("sd.table", "This element has or is affected by some invariants"), "I", null, null);
|
||||
|
||||
ExtensionContext extDefn = null;
|
||||
if (ext) {
|
||||
|
@ -2190,20 +2242,6 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null);
|
||||
}
|
||||
|
||||
public static String pathReverse(String... args) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
boolean d = false;
|
||||
for(String arg: args) {
|
||||
if (!d)
|
||||
d = !Utilities.noString(arg);
|
||||
else if (!s.toString().endsWith("/"))
|
||||
s.append("/");
|
||||
s.append(arg);
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
|
||||
private 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) throws IOException {
|
||||
Cell c = gen.new Cell();
|
||||
row.getCells().add(c);
|
||||
|
@ -2233,7 +2271,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (definition != null && definition.hasShort()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
c.addPiece(checkForNoChange(definition.getShortElement(), gen.new Piece(null, gt(definition.getShortElement()), null)));
|
||||
} else if (fallback != null && fallback.hasShort()) {
|
||||
} else if (fallback != null && fallback != null && fallback.hasShort()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
c.addPiece(checkForNoChange(fallback.getShortElement(), gen.new Piece(null, gt(fallback.getShortElement()), null)));
|
||||
}
|
||||
|
@ -2245,7 +2283,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (ed != null) {
|
||||
String p = ed.getUserString("path");
|
||||
if (p != null) {
|
||||
ref = p.startsWith("http:") || igmode ? p : pathReverse(corePath, p);
|
||||
ref = p.startsWith("http:") || igmode ? p : Utilities.pathURL(corePath, p);
|
||||
}
|
||||
}
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL")+": ", null).addStyle("font-weight:bold"));
|
||||
|
@ -2401,7 +2439,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
if (ed != null) {
|
||||
String p = ed.getUserString("path");
|
||||
if (p != null) {
|
||||
ref = p.startsWith("http:") || igmode ? p : pathReverse(corePath, p);
|
||||
ref = p.startsWith("http:") || igmode ? p : Utilities.pathURL(corePath, p);
|
||||
}
|
||||
}
|
||||
c.getPieces().add(gen.new Piece(null, "URL: ", null).addStyle("font-weight:bold"));
|
||||
|
@ -2700,7 +2738,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
if (p.endsWith("[x]") && actual.startsWith(p.substring(0, p.length()-3)) && !(actual.endsWith("[x]")) && !actual.substring(p.length()-3).contains(".")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (path.startsWith(p+".") && snapshot.get(i).hasContentReference()) {
|
||||
actual = base+(snapshot.get(i).getContentReference().substring(1)+"."+path.substring(p.length()+1)).substring(prefixLength);
|
||||
i = 0;
|
||||
|
@ -3585,7 +3623,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
|
||||
private static ElementDefinitionSlicingDiscriminatorComponent makeDiscriminator(DiscriminatorType profile, String str) {
|
||||
public static ElementDefinitionSlicingDiscriminatorComponent makeDiscriminator(DiscriminatorType profile, String str) {
|
||||
return new ElementDefinitionSlicingDiscriminatorComponent().setType(DiscriminatorType.VALUE).setPath(Utilities.noString(str)? "$this" : str);
|
||||
}
|
||||
|
||||
|
@ -3595,6 +3633,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
case PROFILE: return t.getPath()+"/@profile";
|
||||
case TYPE: return t.getPath()+"/@type";
|
||||
case VALUE: return t.getPath();
|
||||
case EXISTS: return t.getPath(); // determination of value vs. exists is based on whether there's only 2 slices - one with minOccurs=1 and other with maxOccur=0
|
||||
default: throw new FHIRException("Unable to represent "+t.getType().toCode()+":"+t.getPath()+" in R2");
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@ public class ValidationSupportChain implements IValidationSupport {
|
|||
* Constructor
|
||||
*/
|
||||
public ValidationSupportChain() {
|
||||
myChain = new ArrayList<IValidationSupport>();
|
||||
myChain = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,12 +10,18 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
import ca.uhn.fhir.validation.*;
|
||||
import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
|
||||
import org.hl7.fhir.dstu3.context.IWorkerContext;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.Condition.ConditionClinicalStatus;
|
||||
import org.hl7.fhir.dstu3.model.Condition.ConditionVerificationStatus;
|
||||
import org.hl7.fhir.dstu3.model.EligibilityResponse.BenefitComponent;
|
||||
import org.hl7.fhir.dstu3.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
@ -166,6 +172,43 @@ public class ResourceValidatorDstu3Test {
|
|||
assertEquals(0, output.getMessages().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidateProfileWithExtension() throws IOException, FHIRException {
|
||||
PrePopulatedValidationSupport valSupport = new PrePopulatedValidationSupport();
|
||||
DefaultProfileValidationSupport defaultSupport = new DefaultProfileValidationSupport();
|
||||
ValidationSupportChain support = new ValidationSupportChain(valSupport, defaultSupport);
|
||||
|
||||
// Prepopulate SDs
|
||||
valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-profile.xml"));
|
||||
valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-ext.xml"));
|
||||
|
||||
FhirValidator val = ourCtx.newValidator();
|
||||
val.registerValidatorModule(new FhirInstanceValidator(support));
|
||||
|
||||
Consent input = ourCtx.newJsonParser().parseResource(Consent.class, IOUtils.toString(ResourceValidatorDstu3Test.class.getResourceAsStream("/dstu3/myconsent-resource.json")));
|
||||
|
||||
ValidationResult output = val.validateWithResult(input);
|
||||
List<SingleValidationMessage> all = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertEquals(0, all.size());
|
||||
assertEquals(0, output.getMessages().size());
|
||||
|
||||
}
|
||||
|
||||
private StructureDefinition loadStructureDefinition(DefaultProfileValidationSupport theDefaultValSupport, String theResName) throws IOException, FHIRException {
|
||||
StructureDefinition derived = ourCtx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(ResourceValidatorDstu3Test.class.getResourceAsStream(theResName)));
|
||||
StructureDefinition base = theDefaultValSupport.fetchStructureDefinition(ourCtx, derived.getBaseDefinition());
|
||||
Validate.notNull(base);
|
||||
|
||||
IWorkerContext worker = new HapiWorkerContext(ourCtx, theDefaultValSupport);
|
||||
List<ValidationMessage> issues = new ArrayList<>();
|
||||
ProfileUtilities profileUtilities = new ProfileUtilities(worker, issues, null);
|
||||
profileUtilities.generateSnapshot(base, derived, "", "");
|
||||
|
||||
return derived;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidateDifferentPropertyButSameStartsWithPath() throws Exception {
|
||||
|
|
|
@ -22,8 +22,13 @@ import ca.uhn.fhir.validation.ResultSeverityEnum;
|
|||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidatorDstu3Test;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.ResourceValidatorDstu3Test;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.conformance.ProfileUtilities;
|
||||
import org.hl7.fhir.r4.context.IWorkerContext;
|
||||
import org.hl7.fhir.r4.hapi.ctx.*;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
|
||||
|
@ -35,6 +40,7 @@ import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
|
|||
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r4.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.rules.TestWatcher;
|
||||
|
@ -845,4 +851,50 @@ public class FhirInstanceValidatorR4Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateProfileWithExtension() throws IOException, FHIRException {
|
||||
PrePopulatedValidationSupport valSupport = new PrePopulatedValidationSupport();
|
||||
DefaultProfileValidationSupport defaultSupport = new DefaultProfileValidationSupport();
|
||||
ValidationSupportChain support = new ValidationSupportChain(valSupport, defaultSupport);
|
||||
|
||||
// Prepopulate SDs
|
||||
valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-profile.xml"));
|
||||
valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-ext.xml"));
|
||||
|
||||
FhirValidator val = ourCtx.newValidator();
|
||||
val.registerValidatorModule(new FhirInstanceValidator(support));
|
||||
|
||||
Consent input = ourCtx.newJsonParser().parseResource(Consent.class, IOUtils.toString(ResourceValidatorDstu3Test.class.getResourceAsStream("/dstu3/myconsent-resource.json")));
|
||||
input.getPolicyRule().addCoding().setSystem("http://hl7.org/fhir/v3/ActCode").setCode("EMRGONLY");
|
||||
|
||||
// Should pass
|
||||
ValidationResult output = val.validateWithResult(input);
|
||||
List<SingleValidationMessage> all = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertEquals(0, all.size());
|
||||
assertEquals(0, output.getMessages().size());
|
||||
|
||||
// Now with the wrong datatype
|
||||
input.getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/PruebaExtension").get(0).setValue(new CodeType("AAA"));
|
||||
|
||||
// Should fail
|
||||
output = val.validateWithResult(input);
|
||||
all = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertThat(all.toString(), containsString("definition allows for the types [string] but found type code"));
|
||||
|
||||
}
|
||||
|
||||
private StructureDefinition loadStructureDefinition(DefaultProfileValidationSupport theDefaultValSupport, String theResName) throws IOException, FHIRException {
|
||||
StructureDefinition derived = ourCtx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(ResourceValidatorDstu3Test.class.getResourceAsStream(theResName)));
|
||||
StructureDefinition base = theDefaultValSupport.fetchStructureDefinition(ourCtx, derived.getBaseDefinition());
|
||||
Validate.notNull(base);
|
||||
|
||||
IWorkerContext worker = new HapiWorkerContext(ourCtx, theDefaultValSupport);
|
||||
List<ValidationMessage> issues = new ArrayList<>();
|
||||
ProfileUtilities profileUtilities = new ProfileUtilities(worker, issues, null);
|
||||
profileUtilities.generateSnapshot(base, derived, "", "");
|
||||
|
||||
return derived;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<StructureDefinition xmlns="http://hl7.org/fhir">
|
||||
<id value="PruebaExtension" />
|
||||
<meta>
|
||||
<lastUpdated value="2017-12-19T16:53:11.296+01:00" />
|
||||
</meta>
|
||||
<url value="http://hl7.org/fhir/StructureDefinition/PruebaExtension" />
|
||||
<name value="PruebaExtension" />
|
||||
<status value="draft" />
|
||||
<date value="2017-12-19T16:51:07.089+01:00" />
|
||||
<fhirVersion value="3.0.1" />
|
||||
<kind value="complex-type" />
|
||||
<abstract value="false" />
|
||||
<contextType value="resource" />
|
||||
<context value="Consent" />
|
||||
<type value="Extension" />
|
||||
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension" />
|
||||
<derivation value="constraint" />
|
||||
<differential>
|
||||
<element id="Extension.url">
|
||||
<path value="Extension.url" />
|
||||
<fixedUri value="http://hl7.org/fhir/StructureDefinition/PruebaExtension" />
|
||||
</element>
|
||||
<element id="Extension.value[x]:valueString">
|
||||
<path value="Extension.valueString" />
|
||||
<sliceName value="valueString" />
|
||||
<min value="1" />
|
||||
<type>
|
||||
<code value="string" />
|
||||
</type>
|
||||
</element>
|
||||
</differential>
|
||||
</StructureDefinition>
|
|
@ -0,0 +1,42 @@
|
|||
<StructureDefinition xmlns="http://hl7.org/fhir">
|
||||
<id value="Consent" />
|
||||
<meta>
|
||||
<lastUpdated value="2017-12-21T17:22:27.087+01:00" />
|
||||
</meta>
|
||||
<url value="http://hl7.org/fhir/StructureDefinition/MyConsent" />
|
||||
<name value="Consent" />
|
||||
<status value="draft" />
|
||||
<date value="2017-12-19T09:08:41.006+01:00" />
|
||||
<description value="prueba
" />
|
||||
<fhirVersion value="3.0.1" />
|
||||
<kind value="resource" />
|
||||
<abstract value="false" />
|
||||
<type value="Consent" />
|
||||
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Consent" />
|
||||
<derivation value="constraint" />
|
||||
<differential>
|
||||
<element id="Consent.extension">
|
||||
<path value="Consent.extension" />
|
||||
<slicing>
|
||||
<discriminator>
|
||||
<type value="value" />
|
||||
<path value="url" />
|
||||
</discriminator>
|
||||
<rules value="open" />
|
||||
</slicing>
|
||||
</element>
|
||||
<element id="Consent.extension:pruebaExtension">
|
||||
<path value="Consent.extension" />
|
||||
<sliceName value="pruebaExtension" />
|
||||
<min value="1" />
|
||||
<type>
|
||||
<code value="Extension" />
|
||||
<profile value="http://hl7.org/fhir/StructureDefinition/PruebaExtension" />
|
||||
</type>
|
||||
</element>
|
||||
<element id="Consent.identifier">
|
||||
<path value="Consent.identifier" />
|
||||
<min value="1" />
|
||||
</element>
|
||||
</differential>
|
||||
</StructureDefinition>
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"resourceType": "Consent",
|
||||
"id": "consent-example-basic",
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <p>\n\tAuthorize Normal access for Treatment\n\t</p><p>\n Patient "P. van de Heuvel" wishes to have all of the PHI collected at the Good Health Psychiatric Hospital \n available for normal treatment use.\n </p>\n </div>"
|
||||
},
|
||||
"status": "active",
|
||||
"patient": {
|
||||
"reference": "Patient/f001",
|
||||
"display": "P. van de Heuvel"
|
||||
},
|
||||
"period": {
|
||||
"start": "1964-01-01",
|
||||
"end": "2016-01-01"
|
||||
},
|
||||
"dateTime": "2016-05-11",
|
||||
"organization": [
|
||||
{
|
||||
"reference": "Organization/Infoway",
|
||||
"display": "Canada Infoway"
|
||||
}
|
||||
],
|
||||
"sourceAttachment": {
|
||||
"title": "The terms of the consent in lawyer speak."
|
||||
},
|
||||
"identifier": [
|
||||
{
|
||||
"use": "usual",
|
||||
"type": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://hl7.org/fhir/v2/0203",
|
||||
"code": "MR"
|
||||
}
|
||||
]
|
||||
},
|
||||
"system": "urn:oid:1.2.36.146.595.217.0.1",
|
||||
"value": "12345",
|
||||
"period": {
|
||||
"start": "2001-05-06"
|
||||
},
|
||||
"assigner": {
|
||||
"display": "Acme Healthcare"
|
||||
}
|
||||
}
|
||||
],
|
||||
"extension":[
|
||||
{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/PruebaExtension",
|
||||
"valueString" : "123456789"
|
||||
}
|
||||
],
|
||||
"policyRule": "http://goodhealth.org/consent/policy/opt-in"
|
||||
}
|
Loading…
Reference in New Issue