Merge remote-tracking branch 'origin/master' into do-20230315-pathbuilder

This commit is contained in:
dotasek 2023-03-22 12:09:56 -04:00
commit 8ce7cd8323
49 changed files with 369 additions and 103 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -2350,7 +2350,7 @@ public class ImplementationGuide40_50 {
tgt.addParameter(convertImplementationGuideDefinitionParameterComponent(t));
} else {
org.hl7.fhir.r4.model.Extension e = new org.hl7.fhir.r4.model.Extension(EXT_IG_DEFINITION_PARAMETER);
org.hl7.fhir.r4.model.Extension eCode = new org.hl7.fhir.r4.model.Extension("code", new org.hl7.fhir.r4.model.StringType(t.getCode().getCode()));
org.hl7.fhir.r4.model.Extension eCode = new org.hl7.fhir.r4.model.Extension("code", new org.hl7.fhir.r4.model.CodeType(t.getCode().getCode()));
org.hl7.fhir.r4.model.Extension eValue = new org.hl7.fhir.r4.model.Extension("value", new org.hl7.fhir.r4.model.StringType(t.getValue()));
e.addExtension(eCode);
e.addExtension(eValue);

View File

@ -2344,7 +2344,7 @@ public class ImplementationGuide43_50 {
tgt.addParameter(convertImplementationGuideDefinitionParameterComponent(t));
else {
org.hl7.fhir.r4b.model.Extension e = new org.hl7.fhir.r4b.model.Extension(EXT_IG_DEFINITION_PARAMETER);
org.hl7.fhir.r4b.model.Extension eCode = new org.hl7.fhir.r4b.model.Extension("code", new org.hl7.fhir.r4b.model.StringType(t.getCode().getCode()));
org.hl7.fhir.r4b.model.Extension eCode = new org.hl7.fhir.r4b.model.Extension("code", new org.hl7.fhir.r4b.model.CodeType(t.getCode().getCode()));
org.hl7.fhir.r4b.model.Extension eValue = new org.hl7.fhir.r4b.model.Extension("value", new org.hl7.fhir.r4b.model.StringType(t.getValue()));
e.addExtension(eCode);
e.addExtension(eValue);

View File

@ -24,6 +24,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
import com.google.gson.JsonSyntaxException;
@ -40,6 +41,7 @@ public abstract class BaseLoaderR5 implements IContextResourceLoader {
@Getter @Setter protected boolean killPrimitives;
@Getter protected List<String> types = new ArrayList<>();
protected ILoaderKnowledgeProviderR5 lkp;
private boolean loadProfiles = true;
public BaseLoaderR5(List<String> types, ILoaderKnowledgeProviderR5 lkp) {
super();
@ -169,6 +171,12 @@ public abstract class BaseLoaderR5 implements IContextResourceLoader {
String url = URL_BASE+versionString()+"/StructureDefinition/"+code;
ToolingExtensions.setUrlExtension(tr, ToolingExtensions.EXT_FHIR_TYPE, url);
}
for (CanonicalType c : tr.getProfile()) {
c.setValue(patchUrl(c.getValue(), "StructureDefinition"));
}
for (CanonicalType c : tr.getTargetProfile()) {
c.setValue(patchUrl(c.getValue(), "StructureDefinition"));
}
}
if (ed.hasBinding()) {
ed.getBinding().setValueSet(patchUrl(ed.getBinding().getValueSet(), "ValueSet"));
@ -178,4 +186,20 @@ public abstract class BaseLoaderR5 implements IContextResourceLoader {
}
}
public IContextResourceLoader setLoadProfiles(boolean value) {
loadProfiles = value;
return this;
}
public boolean wantLoad(NpmPackage pi, PackageResourceInformation pri) {
if (pri.getResourceType().equals("StructureDefinition")) {
if (loadProfiles) {
return true;
} else {
return pi.isCore() && Utilities.tail(pri.getUrl()).equals(pri.getStatedType());
}
} else {
return true;
}
}
}

View File

@ -127,7 +127,7 @@ public class R4ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader
if (killPrimitives) {
throw new FHIRException("Cannot kill primitives when using deferred loading");
}
if (r5 instanceof StructureDefinition && VersionUtilities.isR4BVer(version)) {
if (r5 instanceof StructureDefinition && VersionUtilities.isR4Ver(version)) {
r5 = new StructureDefinitionHacker(version).fixSD((StructureDefinition) r5);
}
if (patchUrls) {

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -149,7 +149,7 @@ public class TestingUtilities extends BaseTestingUtilities {
public static String checkXMLIsSame(String f1, String f2) throws Exception {
String result = compareXml(f1, f2);
if (result != null && SHOW_DIFF) {
if (result != null && SHOW_DIFF && System.getenv("ProgramFiles") != null) {
String diff = Utilities.path(System.getenv("ProgramFiles"), "WinMerge", "WinMergeU.exe");
if (new File(diff).exists()) {
List<String> command = new ArrayList<String>();

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1154,7 +1154,7 @@ public boolean prependLinks() {
@Override
public String getLinkForUrl(String corePath, String s) {
throw new NotImplementedError();
return null;
}

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r5.conformance;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Resource;
@ -22,8 +23,25 @@ public class StructureDefinitionHacker {
}
public Resource fixSD(StructureDefinition sd) {
if (VersionUtilities.isR4Ver(version) && "http://hl7.org/fhir/StructureDefinition/example-composition".equals(sd.getUrl())) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
fixDocSecURL(ed);
} for (ElementDefinition ed : sd.getDifferential().getElement()) {
fixDocSecURL(ed);
}
}
return sd;
}
private void fixDocSecURL(ElementDefinition ed) {
for (TypeRefComponent tr : ed.getType()) {
for (CanonicalType c : tr.getProfile()) {
if ("http://hl7.org/fhir/StructureDefinition/document-section-library".equals(c.getValue())) {
c.setValue("http://hl7.org/fhir/StructureDefinition/example-section-library");
}
}
}
}
}

View File

@ -661,10 +661,7 @@ public class ProfileUtilities extends TranslatingUtilities {
System.out.println(" "+ed.getId()+" = "+ed.getPath()+" : "+typeSummaryWithProfile(ed)+"["+ed.getMin()+".."+ed.getMax()+"]"+sliceSummary(ed)+" "+constraintSummary(ed));
}
}
if (exception)
throw new DefinitionException(msg);
else
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR));
handleError(url, msg);
}
// hack around a problem in R4 definitions (somewhere?)
for (ElementDefinition ed : derived.getSnapshot().getElement()) {
@ -712,14 +709,20 @@ public class ProfileUtilities extends TranslatingUtilities {
if (ed.getPath().equals("Bundle.entry.response.outcome")) {
wt = "OperationOutcome";
}
if (!sd.getType().equals(wt)) {
boolean ok = isCompatibleType(wt, sd);
String tt = sd.getType();
boolean elementProfile = u.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT);
if (elementProfile) {
ElementDefinition edt = sd.getSnapshot().getElementById(u.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT));
if (edt == null) {
handleError(url, "The profile "+u.getValue()+" has type "+sd.getType()+" which is not consistent with the stated type "+wt);
} else {
tt = edt.typeSummary();
}
}
if (!tt.equals(wt)) {
boolean ok = !elementProfile && isCompatibleType(wt, sd);
if (!ok) {
String smsg = "The profile "+u.getValue()+" has type "+sd.getType()+" which is not consistent with the stated type "+wt;
if (exception)
throw new DefinitionException(smsg);
else
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+ed.getId(), smsg, IssueSeverity.ERROR));
handleError(url, "The profile "+u.getValue()+" has type "+sd.getType()+" which is not consistent with the stated type "+wt);
}
}
}
@ -738,6 +741,13 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
private void handleError(String url, String msg) {
if (exception)
throw new DefinitionException(msg);
else
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR));
}
@ -1973,7 +1983,8 @@ public class ProfileUtilities extends TranslatingUtilities {
base.getAlias().addAll(e.getAlias());
base.getMapping().clear();
base.getMapping().addAll(e.getMapping());
} else if (source.getType().size() == 1 && source.getTypeFirstRep().hasProfile()) {
} else if (source.getType().size() == 1 && source.getTypeFirstRep().hasProfile() && !source.getTypeFirstRep().getProfile().get(0).hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT)) {
// todo: should we change down the profile_element if there's one?
String type = source.getTypeFirstRep().getWorkingCode();
if ("Extension".equals(type)) {
System.out.println("Can't find Extension definition for "+source.getTypeFirstRep().getProfile().get(0).asStringValue()+" but trying to go on");
@ -2270,13 +2281,13 @@ public class ProfileUtilities extends TranslatingUtilities {
t.setUserData(UD_DERIVATION_EQUALS, true);
}
List<ElementDefinitionMappingComponent> list = new ArrayList<>();
list.addAll(base.getMapping());
base.getMapping().clear();
addMappings(base.getMapping(), list);
if (derived.hasMapping()) {
List<ElementDefinitionMappingComponent> list = new ArrayList<>();
list.addAll(base.getMapping());
base.getMapping().clear();
addMappings(base.getMapping(), list);
addMappings(base.getMapping(), derived.getMapping());
}
}
for (ElementDefinitionMappingComponent m : base.getMapping()) {
if (m.hasMap()) {
m.setMap(m.getMap().trim());

View File

@ -793,7 +793,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (pIn == null) {
throw new Error(formatMessage(I18nConstants.NO_PARAMETERS_PROVIDED_TO_EXPANDVS));
}
if (vs.getUrl().equals("http://hl7.org/fhir/ValueSet/all-time-units") || vs.getUrl().equals("http://hl7.org/fhir/ValueSet/all-distance-units")) {
return new ValueSetExpansionOutcome("This value set is not expanded correctly at this time (will be fixed in a future version)", TerminologyServiceErrorClass.VALUESET_UNSUPPORTED);
}
Parameters p = pIn.copy();
if (vs.hasExpansion()) {
@ -1213,7 +1216,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (isTxCaching && cacheId != null && vs.getUrl() != null && cached.contains(vs.getUrl()+"|"+vs.getVersion())) {
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+vs.getVersion() : "")));
} else if (options.getVsAsUrl()){
pin.addParameter().setName("url").setValue(new StringType(vs.getUrl()));
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()));
} else {
pin.addParameter().setName("valueSet").setResource(vs);
if (vs.getUrl() != null) {
@ -2412,4 +2415,4 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// TODO Auto-generated method stub
return new PEBuilder(this, elementProps, fixedProps);
}
}
}

View File

@ -77,6 +77,7 @@ import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.TranslationServices;
import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationOptions;
@ -338,6 +339,23 @@ public interface IWorkerContext {
* @return
*/
String patchUrl(String url, String resourceType);
/**
* set this to false (default is true) if you don't want profiles loaded
* @param value
* @return
*/
IContextResourceLoader setLoadProfiles(boolean value);
/**
* Called during the loading process - the loader can decide which resources to load.
* At this point, only the .index.json is being read
*
* @param pi
* @param pri
* @return
*/
boolean wantLoad(NpmPackage pi, PackageResourceInformation pri);
}
/**

View File

@ -492,7 +492,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
types = Utilities.strings("StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem", "Measures" );
}
for (PackageResourceInformation pri : pi.listIndexedResources(types)) {
if (!pri.getFilename().contains("ig-r4")) {
if (!pri.getFilename().contains("ig-r4") && (loader == null || loader.wantLoad(pi, pri))) {
try {
registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageInformation(pi));
t++;

View File

@ -394,7 +394,7 @@ public class FmlParser extends ParserBase {
if (rule.getChildrenByName("source").size() != 1 || !rule.getChildrenByName("source").get(0).hasChild("element"))
throw lexer.error("Complex rules must have an explicit name");
if (rule.getChildrenByName("source").get(0).hasChild("type"))
rule.makeElement("name").setValue(rule.getChildrenByName("source").get(0).getNamedChildValue("element") + rule.getChildrenByName("source").get(0).getNamedChildValue("type"));
rule.makeElement("name").setValue(rule.getChildrenByName("source").get(0).getNamedChildValue("element") + Utilities.capitalize(rule.getChildrenByName("source").get(0).getNamedChildValue("type")));
else
rule.makeElement("name").setValue(rule.getChildrenByName("source").get(0).getNamedChildValue("element"));
}

View File

@ -1245,6 +1245,20 @@ public class StructureDefinition extends CanonicalResource {
return null;
}
public ElementDefinition getElementById(String id) {
if (id == null) {
return null;
}
for (ElementDefinition ed : getElement()) {
if (id.equals(ed.getId())) {
return ed;
}
}
return null;
}
// end addition
}

View File

@ -72,7 +72,11 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
TableModel model = gen.new TableModel("qtree="+q.getId(), context.getRules() == GenerationRules.IG_PUBLISHER);
model.setAlternating(true);
model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png");
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0));
@ -446,7 +450,11 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
TableModel model = gen.new TableModel("qtree="+q.getId(), true);
model.setAlternating(true);
model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png");
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Description & Constraints"), translate("sd.hint", "Additional information about the item"), null, 0));

View File

@ -15,6 +15,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
@ -63,7 +64,11 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
TableModel model = gen.new TableModel("qtree="+qr.getId(), false);
model.setAlternating(true);
model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png");
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0));
@ -86,7 +91,11 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true);
TableModel model = gen.new TableModel("qtree="+q.getId(), true);
model.setAlternating(true);
model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png");
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0));

View File

@ -3,10 +3,12 @@ package org.hl7.fhir.r5.renderers;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
import org.hl7.fhir.r5.utils.TranslatingUtilities;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -76,7 +78,7 @@ public class Renderer extends TranslatingUtilities {
public void genStandardsStatus(XhtmlNode td, StandardsStatus ss) {
if (ss != null) {
td.tx(" ");
XhtmlNode a = td.ah("versions.html#std-process", "Standards Status = "+ss.toDisplay());
XhtmlNode a = td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "versions.html#std-process"), "Standards Status = "+ss.toDisplay());
a.style("padding-left: 3px; padding-right: 3px; border: 1px grey solid; font-weight: bold; color: black; background-color: "+ss.getColor());
a.tx(ss.getAbbrev());
}

View File

@ -516,11 +516,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
}
}
public TableModel initCustomTable(HierarchicalTableGenerator gen, String prefix, boolean isLogical, boolean alternating, String id, boolean isActive, List<Column> columns) {
public TableModel initCustomTable(HierarchicalTableGenerator gen, String prefix, boolean isLogical, boolean alternating, String id, boolean isActive, List<Column> columns) throws IOException {
TableModel model = gen.new TableModel(id, isActive);
model.setAlternating(alternating);
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
}
model.setDocoRef(Utilities.pathURL("https://build.fhir.org/ig/FHIR/ig-guidance", "readingIgs.html#table-views"));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Name"), translate("sd.hint", "The logical name of the element"), null, 0));
for (Column col : columns) {
@ -2586,10 +2590,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
}
private TableModel initSpanningTable(HierarchicalTableGenerator gen, String prefix, boolean isLogical, String id) {
private TableModel initSpanningTable(HierarchicalTableGenerator gen, String prefix, boolean isLogical, String id) throws IOException {
TableModel model = gen.new TableModel(id, true);
model.setDocoImg(prefix+"help16.png");
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
}
model.setDocoRef(Utilities.pathURL(prefix, "formats.html#table")); // todo: change to graph definition
model.getTitles().add(gen.new Title(null, model.getDocoRef(), "Property", "A profiled resource", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), "Card.", "Minimum and Maximum # of times the the element can appear in the instance", null, 0));

View File

@ -461,7 +461,7 @@ public class StructureMapRenderer extends TerminologyRenderer {
if (n.equals(s) || n.equals("\"" + s + "\""))
return true;
if (source.get(0).hasType()) {
s = source.get(0).getElement() + "-" + source.get(0).getType();
s = source.get(0).getElement() + Utilities.capitalize(source.get(0).getType());
return n.equals(s) || n.equals("\"" + s + "\"");
}
return false;

View File

@ -13,6 +13,7 @@ import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
public class TestPackageLoader implements IContextResourceLoader {
@ -62,4 +63,14 @@ public class TestPackageLoader implements IContextResourceLoader {
return url;
}
@Override
public IContextResourceLoader setLoadProfiles(boolean value) {
return this;
}
@Override
public boolean wantLoad(NpmPackage pi, PackageResourceInformation pri) {
return true;
}
}

View File

@ -1000,7 +1000,7 @@ public class StructureMapUtilities {
if (rule.getSource().size() != 1 || !rule.getSourceFirstRep().hasElement() && exceptionsForChecks )
throw lexer.error("Complex rules must have an explicit name");
if (rule.getSourceFirstRep().hasType())
rule.setName(rule.getSourceFirstRep().getElement() + "-" + rule.getSourceFirstRep().getType());
rule.setName(rule.getSourceFirstRep().getElement() + Utilities.capitalize(rule.getSourceFirstRep().getType()));
else
rule.setName(rule.getSourceFirstRep().getElement());
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -115,15 +115,28 @@ public class FTPClient {
resetTimers();
logger.debug("Initial Working directory: " + clientImpl.printWorkingDirectory());
clientImpl.setFileType(FTP.BINARY_FILE_TYPE);
clientImpl.enterLocalPassiveMode();
logger.debug("Setting initial working directory: " + clientImpl.printWorkingDirectory());
clientImpl.changeWorkingDirectory(path);
throwExceptionForNegativeCompletion("FTP server could not establish default working directory", true);
logger.debug("Set initial working directory.");
logger.debug("Resolving remote resolved path.");
resolvedPath = clientImpl.printWorkingDirectory();
logger.debug("Resolved working directory: " + resolvedPath);
logger.debug("Resolved remote resolved path: " + resolvedPath);
}
public void setBufferSize(int bufferSize) {
clientImpl.setBufferSize(bufferSize);
}
public int getBufferSize() {
return clientImpl.getBufferSize();
}
private void resetTimers() {
@ -208,7 +221,6 @@ public class FTPClient {
String resolvedPath = resolveRemotePath(path);
logger.debug("Uploading file to remote path: " + resolvedPath);
attemptUpload(source, resolvedPath);
FTPReplyCodeAndString reply = getFTPReplyCodeAndString();
@ -239,8 +251,6 @@ public class FTPClient {
private void attemptUpload(String source, String resolvedPath) throws IOException {
final long startTime = System.nanoTime();
FileInputStream localStream = new FileInputStream(source);
clientImpl.setFileType(FTP.BINARY_FILE_TYPE);
clientImpl.enterLocalPassiveMode();
clientImpl.storeFile(resolvedPath, localStream);
localStream.close();
this.storeFileTimeNanos += System.nanoTime() - startTime;

View File

@ -905,6 +905,15 @@ public class Utilities {
return false;
}
public static boolean containsInList(String value, String... array) {
if (value == null)
return false;
for (String s : array)
if (value.contains(s))
return true;
return false;
}
public static boolean existsInList(String value, String... array) {
if (value == null)
return false;
@ -1491,10 +1500,13 @@ public class Utilities {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
boolean isDirectory = false;
if (zipEntry.getName().endsWith("/") || zipEntry.getName().endsWith("\\")) {
String n = makeOSSafe(zipEntry.getName());
if (n.endsWith(File.separator)) {
isDirectory = true;
}
Path newPath = zipSlipProtect(zipEntry, target);
Path newPath = zipSlipProtect(n, target);
if (isDirectory) {
Files.createDirectories(newPath);
} else {
@ -1511,19 +1523,23 @@ public class Utilities {
}
}
public static Path zipSlipProtect(ZipEntry zipEntry, Path targetDir)
public static String makeOSSafe(String name) {
return name.replace("\\", File.separator).replace("/", File.separator);
}
public static Path zipSlipProtect(String zipName, Path targetDir)
throws IOException {
// test zip slip vulnerability
// Path targetDirResolved = targetDir.resolve("../../" + zipEntry.getName());
Path targetDirResolved = targetDir.resolve(zipEntry.getName());
Path targetDirResolved = targetDir.resolve(zipName);
// make sure normalized file still has targetDir as its prefix
// else throws exception
Path normalizePath = targetDirResolved.normalize();
if (!normalizePath.startsWith(targetDir)) {
throw new IOException("Bad zip entry: " + zipEntry.getName());
throw new IOException("Bad zip entry: " + zipName);
}
return normalizePath;
@ -1868,7 +1884,7 @@ public class Utilities {
if (ignoreList == null || !ignoreList.contains(f.getAbsolutePath())) {
if (f.isDirectory()) {
addAllFiles(res, root, f, ignoreList);
} else {
} else if (!f.getName().equals(".DS_Store")) {
res.add(getRelativePath(root, f.getAbsolutePath()));
}
}
@ -1932,7 +1948,7 @@ public class Utilities {
public static String tail(String url) {
int i = url.length()-1;
while (i >= 0 && isTokenChar(url.charAt(i))) {
while (i >= 0 && (isTokenChar(url.charAt(i)) || isDigit(url.charAt(i))) ) {
i--;
}
if (i < 0) {

View File

@ -668,6 +668,8 @@ public class I18nConstants {
public static final String MEASURE_SHAREABLE_MISSING_HL7 = "MEASURE_SHAREABLE_MISSING_HL7";
public static final String MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = "MEASURE_SHAREABLE_EXTRA_MISSING_HL7";
public static final String MEASURE_SHAREABLE_EXTRA_MISSING = "MEASURE_SHAREABLE_EXTRA_MISSING";
public static final String VALUESET_EXAMPLE_SYSTEM_ERROR = "VALUESET_EXAMPLE_SYSTEM_ERROR";
public static final String VALUESET_EXAMPLE_SYSTEM_HINT = "VALUESET_EXAMPLE_SYSTEM_HINT";
public static final String VALUESET_UNC_SYSTEM_WARNING = "VALUESET_UNC_SYSTEM_WARNING";
public static final String VALUESET_UNC_SYSTEM_WARNING_VER = "VALUESET_UNC_SYSTEM_WARNING_VER";
public static final String VALUESET_IMPORT_UNION_INTERSECTION = "VALUESET_IMPORT_UNION_INTERSECTION";

View File

@ -66,6 +66,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
@ -82,9 +83,9 @@ import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.TranslatingUtilities;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableGenerationMode;
public class HierarchicalTableGenerator extends TranslatingUtilities {
@ -634,13 +635,17 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
checkSetup();
}
public TableModel initNormalTable(String prefix, boolean isLogical, boolean alternating, String id, boolean isActive, TableGenerationMode mode) {
public TableModel initNormalTable(String prefix, boolean isLogical, boolean alternating, String id, boolean isActive, TableGenerationMode mode) throws IOException {
this.mode = mode;
TableModel model = new TableModel(id, isActive);
model.setAlternating(alternating);
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
if (mode == TableGenerationMode.XML) {
model.setDocoImg(help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
}
model.setDocoRef(Utilities.pathURL("https://build.fhir.org/ig/FHIR/ig-guidance", "readingIgs.html#table-views"));
model.getTitles().add(new Title(null, model.getDocoRef(), translate("sd.head", "Name"), translate("sd.hint", "The logical name of the element"), null, 0));
model.getTitles().add(new Title(null, model.getDocoRef(), translate("sd.head", "Flags"), translate("sd.hint", "Information about the use of the element"), null, 0));
@ -653,11 +658,15 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
return model;
}
public TableModel initComparisonTable(String prefix, String id) {
public TableModel initComparisonTable(String prefix, String id) throws IOException {
TableModel model = new TableModel(id, true);
model.setAlternating(true);
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
if (mode == TableGenerationMode.XML) {
model.setDocoImg(help16AsData()); // #FIXME
} else {
model.setDocoImg(Utilities.pathURL(prefix, "help16.png"));
}
model.setDocoRef(Utilities.pathURL(prefix, "formats.html#table"));
model.getTitles().add(new Title(null, model.getDocoRef(), translate("sd.head", "Name"), translate("sd.hint", "The logical name of the element"), null, 0));
model.getTitles().add(new Title(null, model.getDocoRef(), translate("sd.head", "L Flags"), translate("sd.hint", "Information about the use of the element - Left Structure"), null, 0).setStyle("border-left: 1px grey solid"));
@ -913,7 +922,16 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
return corePrefix+filename;
}
public static String help16AsData() throws IOException {
ClassLoader classLoader = HierarchicalTableGenerator.class.getClassLoader();
InputStream help = classLoader.getResourceAsStream("help16.png");
StringBuilder b = new StringBuilder();
b.append("data:image/png;base64,");
byte[] bytes = TextFile.streamToBytes(help);
b.append(new String(Base64.encodeBase64(bytes)));
return b.toString();
}
private void checkModel(TableModel model) throws FHIRException {
check(!model.getTitles().isEmpty(), "Must have titles");
int tc = 0;

View File

@ -187,7 +187,11 @@ public class XhtmlGenerator {
out.write(" ");
if (adorner != null) {
XhtmlGeneratorAdornerState attrState = adorner.getAttributeMarkup(this, newstate, node, node.getAttributes().item(i).getNodeName(), node.getAttributes().item(i).getTextContent());
out.write(node.getAttributes().item(i).getNodeName()+"=\"<span class=\"xmlattrvalue\">"+attrState.getPrefix()+escapeHtml(Utilities.escapeXml(node.getAttributes().item(i).getTextContent()), level)+attrState.getSuffix()+"</span>\"");
if (attrState.getAltText() != null) {
out.write(node.getAttributes().item(i).getNodeName()+"=\"<span class=\"xmlattrvalue\">"+attrState.getPrefix()+escapeHtml(Utilities.escapeXml(attrState.getAltText()), level)+attrState.getSuffix()+"</span>\"");
} else {
out.write(node.getAttributes().item(i).getNodeName()+"=\"<span class=\"xmlattrvalue\">"+attrState.getPrefix()+escapeHtml(Utilities.escapeXml(node.getAttributes().item(i).getTextContent()), level)+attrState.getSuffix()+"</span>\"");
}
} else
out.write(node.getAttributes().item(i).getNodeName()+"=\"<span class=\"xmlattrvalue\">"+escapeHtml(Utilities.escapeXml(node.getAttributes().item(i).getTextContent()), level)+"</span>\"");
}

View File

@ -41,6 +41,7 @@ public interface XhtmlGeneratorAdorner {
private String suffix;
private String supressionMessage;
private String path;
private String altText;
public XhtmlGeneratorAdornerState(String path, String prefix, String suffix) {
super();
@ -49,6 +50,15 @@ public interface XhtmlGeneratorAdorner {
this.suffix = suffix;
}
public XhtmlGeneratorAdornerState(String path, String prefix, String suffix, String altText) {
super();
this.path = path;
this.prefix = prefix;
this.suffix = suffix;
this.altText = altText;
}
public XhtmlGeneratorAdornerState(String path, String supressionMessage) {
super();
this.path = path;
@ -70,6 +80,11 @@ public interface XhtmlGeneratorAdorner {
public String getPath() {
return path;
}
public String getAltText() {
return altText;
}
}
XhtmlGeneratorAdornerState getState(XhtmlGenerator ref, XhtmlGeneratorAdornerState state, Element node) throws Exception;

View File

@ -558,6 +558,8 @@ SEARCHPARAMETER_EXP_WRONG = The expression ''{2}'' is not compatible with the ex
VALUESET_NO_SYSTEM_WARNING = No System specified, so Concepts and Filters can't be checked
VALUESET_INCLUDE_INVALID_CONCEPT_CODE = The code {1} is not valid in the system {0}
VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = The code {2} is not valid in the system {0} version {1}
VALUESET_EXAMPLE_SYSTEM_HINT = Example System ''{0}'' specified, so Concepts and Filters can''t be checked
VALUESET_EXAMPLE_SYSTEM_ERROR = Example System ''{0}'' specified, which is illegal. Concepts and Filters can''t be checked
VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
VALUESET_UNC_SYSTEM_WARNING_VER = Unknown System/Version ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
Extension_PROF_Type = The Profile ''{0}'' definition allows for the type {1} but found type {2}
@ -855,7 +857,7 @@ SM_NO_LIST_RULE_ID_NEEDED = A list ruleId should not be provided since this is a
SM_LIST_RULE_ID_ONLY_WHEN_SHARE = A ruleId should only be provided when the rule mode is ''share''
SM_RULE_SOURCE_UNASSIGNED = The source statement doesn''t assign a variable to the source - check that this is what is intended
SM_TARGET_PATH_MULTIPLE_MATCHES = The target path {0}.{1} refers to the path {2} which is could be a reference to multiple elements ({3}). No further checking can be performed
SM_SOURCE_TYPE_INVALID = The type {0} is not valid in this source context {1}. The possible types are [{2}]
SM_SOURCE_TYPE_INVALID = The type {0} is not valid in the source context {1}. The possible types are [{2}]
SM_TARGET_TRANSFORM_PARAM_COUNT_RANGE = Transform {0} takes {1}-{2} parameter(s) but {3} were found
SM_TARGET_TRANSFORM_PARAM_COUNT_SINGLE = Transform {0} takes {1} parameter(s) but {2} were found
SM_TARGET_TRANSFORM_NOT_CHECKED = Transform {0} not checked dyet

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

View File

@ -30,8 +30,11 @@ public class FTPClientTest implements ResourceLoaderTests {
public static final String DUMMY_FILE_TO_DELETE = "dummyFileToDelete";
public static final String DUMMY_FILE_TO_UPLOAD = "dummyFileToUpload";
public static final String DUMMY_FILE_TO_UPLOAD_2 = "dummyFileToUpload2";
public static final int FAKE_FTP_PORT = 8022;
public static final String DUMMY_FILE_CONTENT = "Dummy file content\nMore content\n";
public static final String DUMMY_FILE_CONTENT_2 = "Dummy file content 2\nMore content\n";
public static final String LOCALHOST = "localhost";
@ -48,26 +51,31 @@ public class FTPClientTest implements ResourceLoaderTests {
Path dummyFileToUploadPath;
Path dummyFileToUploadPath2;
Path dummyUploadedFilePath;
Path dummyUploadedFilePath2;
String dummyFileContent;
String dummyFileContent2;
@BeforeEach
public void setup() throws IOException {
setupDummyFileToUpload();
setupDummyFilesToUpload();
setupFakeFtpDirectory();
setupFakeFtpServer();
}
private void setupDummyFileToUpload() throws IOException {
dummyFileContent = createDummyFileContent();
private void setupDummyFilesToUpload() throws IOException {
dummyFileContent = DUMMY_FILE_CONTENT;
dummyFileContent2 = DUMMY_FILE_CONTENT;
dummyFileToUploadPath = Files.createTempFile("dummyFtpFileToUpload", "dummy");
Files.write(dummyFileToUploadPath, DUMMY_FILE_CONTENT.getBytes(StandardCharsets.UTF_8));
}
private String createDummyFileContent() {
return DUMMY_FILE_CONTENT;
dummyFileToUploadPath2 = Files.createTempFile("dummyFtpFileToUpload2", "dummy");
Files.write(dummyFileToUploadPath2, DUMMY_FILE_CONTENT_2.getBytes(StandardCharsets.UTF_8));
}
public void setupFakeFtpServer() throws IOException {
@ -101,6 +109,7 @@ public class FTPClientTest implements ResourceLoaderTests {
dummyFileToDeletePath = Files.createFile(relativePath2.resolve(DUMMY_FILE_TO_DELETE));
dummyUploadedFilePath = relativePath2.resolve(DUMMY_FILE_TO_UPLOAD);
dummyUploadedFilePath2 = relativePath2.resolve(DUMMY_FILE_TO_UPLOAD_2);
}
@AfterEach
@ -141,6 +150,7 @@ public class FTPClientTest implements ResourceLoaderTests {
private FTPClient connectToFTPClient() throws IOException {
FTPClient client = new FTPClient(LOCALHOST, FAKE_FTP_PORT, RELATIVE_PATH_1, DUMMY_USER, DUMMY_PASSWORD);
client.setBufferSize(16000);
client.connect();
assertAllMillisFieldsAreZero(client);
@ -175,21 +185,43 @@ public class FTPClientTest implements ResourceLoaderTests {
client.upload(dummyFileToUploadPath.toFile().getAbsolutePath(), RELATIVE_PATH_2 + "/" + DUMMY_FILE_TO_UPLOAD);
assertUploadedFileCorrect(uploadFilePath);
assertUploadedFileCorrect(uploadFilePath, DUMMY_FILE_CONTENT);
assertTrue(client.getDeleteFileTimeNanos() == 0);
assertTrue(client.getStoreFileTimeNanos() > 0);
assertTrue(client.getCreateRemotePathIfNotExistsNanos() == 0);
}
private void assertUploadedFileCorrect(String uploadedFilePath) throws IOException {
@Test
public void testMultiUpload() throws IOException {
FTPClient client = connectToFTPClient();
String uploadFilePath = dummyUploadedFilePath.toFile().getAbsolutePath();
assertFalse(fakeFtpServer.getFileSystem().exists(uploadFilePath));
String uploadFilePath2 = dummyUploadedFilePath2.toFile().getAbsolutePath();
assertFalse(fakeFtpServer.getFileSystem().exists(uploadFilePath));
client.upload(dummyFileToUploadPath.toFile().getAbsolutePath(), RELATIVE_PATH_2 + "/" + DUMMY_FILE_TO_UPLOAD);
client.upload(dummyFileToUploadPath2.toFile().getAbsolutePath(), RELATIVE_PATH_2 + "/" + DUMMY_FILE_TO_UPLOAD_2);
assertUploadedFileCorrect(uploadFilePath, DUMMY_FILE_CONTENT);
assertUploadedFileCorrect(uploadFilePath2, DUMMY_FILE_CONTENT_2);
assertTrue(client.getDeleteFileTimeNanos() == 0);
assertTrue(client.getStoreFileTimeNanos() > 0);
assertTrue(client.getCreateRemotePathIfNotExistsNanos() == 0);
}
private void assertUploadedFileCorrect(String uploadedFilePath, String expectedFileContent) throws IOException {
assertTrue(fakeFtpServer.getFileSystem().exists(uploadedFilePath));
FileEntry fileEntry = (FileEntry)fakeFtpServer.getFileSystem().getEntry(uploadedFilePath);
assertNotNull(fileEntry);
InputStream inputStream = fileEntry.createInputStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
String actualContent = new String(bytes, StandardCharsets.UTF_8);
assertEquals(DUMMY_FILE_CONTENT,actualContent);
assertEquals(expectedFileContent,actualContent);
}
@Test
@ -237,7 +269,7 @@ public class FTPClientTest implements ResourceLoaderTests {
assertTrue(fakeFtpServer.getFileSystem().exists(newPath1.toFile().getAbsolutePath()));
assertTrue(fakeFtpServer.getFileSystem().exists(newPath2.toFile().getAbsolutePath()));
assertUploadedFileCorrect(uploadFilePath.toFile().getAbsolutePath());
assertUploadedFileCorrect(uploadFilePath.toFile().getAbsolutePath(), DUMMY_FILE_CONTENT);
assertTrue(client.getDeleteFileTimeNanos() == 0);
assertTrue(client.getStoreFileTimeNanos() > 0);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -155,6 +155,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
protected List<ValidationMessage> messagesToRemove = new ArrayList<>();
private ValidationLevel level = ValidationLevel.HINTS;
protected Coding jurisdiction;
protected boolean allowExamples;
public BaseValidator(IWorkerContext context, XVerExtensionManager xverManager) {
super();
@ -1231,4 +1232,17 @@ public class BaseValidator implements IValidationContextResourceLoader {
String url = cr.getChildValue("url");
return url != null && url.contains("hl7");
}
public boolean isAllowExamples() {
return this.allowExamples;
}
public void setAllowExamples(boolean value) {
this.allowExamples = value;
}
protected boolean isExampleUrl(String url) {
return Utilities.containsInList(url, "example.org", "acme.com", "acme.org");
}
}

View File

@ -65,8 +65,10 @@ public class CodeSystemValidator extends BaseValidator {
private void checkCodes(Set<String> codes, List<ConceptDefinitionComponent> list, String path, List<ValidationMessage> errors) {
for (ConceptDefinitionComponent cc : list) {
String npath = path+".concept.descendents().where(code = '"+cc.getCode()+"')";
rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, npath, !codes.contains(cc.getCode()), "Duplicate Code "+cc.getCode());
String npath = path+".concept.where(code = '"+cc.getCode()+"')";
if (codes.contains(cc.getCode())) {
rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, npath, false, "Duplicate Code "+cc.getCode());
}
codes.add(cc.getCode());
checkCodes(codes, cc.getConcept(), npath, errors);
}

View File

@ -471,7 +471,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private IValidationProfileUsageTracker tracker;
private ValidatorHostServices validatorServices;
private boolean assumeValidRestReferences;
private boolean allowExamples;
private boolean securityChecks;
private ProfileUtilities profileUtilities;
private boolean crumbTrails;
@ -586,14 +585,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.assumeValidRestReferences = value;
}
public boolean isAllowExamples() {
return this.allowExamples;
}
public void setAllowExamples(boolean value) {
this.allowExamples = value;
}
public boolean isAllowComments() {
return allowComments;
}
@ -2646,7 +2637,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (fetcher != null && !type.equals("uuid")) {
boolean found;
try {
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) ||
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) /* || (url.startsWith("http://hl7.org/fhir/tools")) */ ||
SpecialExtensions.isKnownExtension(url) || isXverUrl(url);
if (!found) {
found = fetcher.resolveURL(this, hostContext, path, url, type);
@ -5043,7 +5034,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (element.getType().equals("StructureMap")) {
return new StructureMapValidator(context, timeTracker, fpe, xverManager,profileUtilities, jurisdiction).validateStructureMap(errors, element, stack);
} else if (element.getType().equals("ValueSet")) {
return new ValueSetValidator(context, timeTracker, this, xverManager, jurisdiction).validateValueSet(errors, element, stack);
return new ValueSetValidator(context, timeTracker, this, xverManager, jurisdiction, allowExamples).validateValueSet(errors, element, stack);
} else {
return true;
}

View File

@ -199,6 +199,11 @@ public class StructureMapValidator extends BaseValidator {
return sd.getUrl().equals(other.sd.getUrl()) && ed.getPath().equals(other.ed.getPath()) && Utilities.stringsEqual(type, other.type);
}
@Override
public String toString() {
return summary();
}
}
public class VariableSet {
@ -623,11 +628,17 @@ public class StructureMapValidator extends BaseValidator {
} else {
ok = false;
}
// check condition
// check check
}
// check condition
// check check
} else {
String variable = source.getChildValue("variable");
if (variable != null) {
variables.add(variable, v.getMode()); // may overwrite
}
}
}
}
return ok;
}
@ -873,20 +884,34 @@ public class StructureMapValidator extends BaseValidator {
// under some special conditions, we can infer what the type will be:
// * there's a nominated default variable
// * that variable has as single type
// * there's a create with no param
// * there's a create/copy with no param
// * there's a single dependent rule with name = StructureMapUtilities.DEF_GROUP_NAME
// * there's a default type group for the type of the source type
// * there's a default type group for the type of the source type
// otherwise, we can't know the target type.
if (ruleInfo.getDefVariable() != null && Utilities.existsInList(transform, "create", "copy") && params.isEmpty()) {
VariableDefn v = variables.getVariable(ruleInfo.getDefVariable(), SOURCE);
if (v != null && v.getEd() != null && (v.getEd().getType().size() == 1 || v.getType() != null)) {
List<Element> dependents = rule.getChildrenByName("dependent");
String type = v.getType() != null ? getTypeFromDefn(v.getEd(), v.getType()) : v.getEd().getTypeFirstRep().getWorkingCode();
if (dependents.size() == 1 && StructureMapUtilities.DEF_GROUP_NAME.equals(dependents.get(0).getChildValue("name"))) {
String type = v.getType() != null ? getTypeFromDefn(v.getEd(), v.getType()) : v.getEd().getTypeFirstRep().getWorkingCode();
// now, we look for a default group.
// todo: look in this source
// now look through the inputs
for (StructureMap map : imports) {
for (StructureMapGroupComponent grp : map.getGroup()) {
if (grp.getTypeMode() != StructureMapGroupTypeMode.NULL && grp.getInput().size() == 2) {
String grpType = getTypeForGroupInput(map, grp, grp.getInput().get(0));
if (sameTypes(type, grpType)) {
String tgtType = getTypeForGroupInput(map, grp, grp.getInput().get(1));
if (tgtType != null) {
return tgtType;
}
}
}
}
}
} else if (dependents.size() == 0) {
for (StructureMap map : imports) {
for (StructureMapGroupComponent grp : map.getGroup()) {
if (grp.getTypeMode() == StructureMapGroupTypeMode.TYPEANDTYPES && grp.getInput().size() == 2) {
@ -900,6 +925,7 @@ public class StructureMapValidator extends BaseValidator {
}
}
}
}
}
}

View File

@ -43,13 +43,13 @@ public class ValueSetValidator extends BaseValidator {
private InstanceValidator parent;
public ValueSetValidator(IWorkerContext context, TimeTracker timeTracker, InstanceValidator parent, XVerExtensionManager xverManager, Coding jurisdiction) {
public ValueSetValidator(IWorkerContext context, TimeTracker timeTracker, InstanceValidator parent, XVerExtensionManager xverManager, Coding jurisdiction, boolean allowExamples) {
super(context, xverManager);
source = Source.InstanceValidator;
this.timeTracker = timeTracker;
this.parent = parent;
this.jurisdiction = jurisdiction;
this.allowExamples = allowExamples;
}
public boolean validateValueSet(List<ValidationMessage> errors, Element vs, NodeStack stack) {
@ -190,7 +190,15 @@ public class ValueSetValidator extends BaseValidator {
if (version == null) {
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null), null);
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage());
if (isExampleUrl(system)) {
if (isAllowExamples()) {
hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_HINT, system);
} else {
rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_ERROR, system);
}
} else {
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage());
}
return false;
} else {
boolean ok = vv.isOk();

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

View File

@ -14,12 +14,12 @@
HAPI FHIR
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.6.113-SNAPSHOT</version>
<version>5.6.115-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<hapi_fhir_version>6.2.1</hapi_fhir_version>
<validator_test_case_version>1.2.21</validator_test_case_version>
<validator_test_case_version>1.2.23</validator_test_case_version>
<junit_jupiter_version>5.7.1</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
<maven_surefire_version>3.0.0-M5</maven_surefire_version>