This commit is contained in:
Lloyd McKenzie 2020-11-09 23:34:13 -07:00
commit 409bcfbecf
43 changed files with 771 additions and 177 deletions

View File

@ -58,6 +58,11 @@ steps:
<id>$(PGP_KEYNAME)</id>
<passphrase>$(PGP_PASSPHRASE)</passphrase>
</server>
<server>
<id>github-releases</id>
<username>markiantorno</username>
<password>$(GIT_PACKAGE_PAT)</password>
</server>
</servers>
<profiles>
<profile>

View File

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

View File

@ -2479,8 +2479,6 @@ public class VersionConvertor_10_40 {
return convertId((org.hl7.fhir.dstu2.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu2.model.InstantType)
return convertInstant((org.hl7.fhir.dstu2.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu2.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu2.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu2.model.OidType)
@ -2493,6 +2491,8 @@ public class VersionConvertor_10_40 {
return convertTime((org.hl7.fhir.dstu2.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu2.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu2.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UriType)
return convertUri((org.hl7.fhir.dstu2.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UuidType)
@ -2569,8 +2569,6 @@ public class VersionConvertor_10_40 {
return convertId((org.hl7.fhir.r4.model.IdType) src);
if (src instanceof org.hl7.fhir.r4.model.InstantType)
return convertInstant((org.hl7.fhir.r4.model.InstantType) src);
if (src instanceof org.hl7.fhir.r4.model.IntegerType)
return convertInteger((org.hl7.fhir.r4.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r4.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.r4.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.r4.model.OidType)
@ -2583,6 +2581,8 @@ public class VersionConvertor_10_40 {
return convertTime((org.hl7.fhir.r4.model.TimeType) src);
if (src instanceof org.hl7.fhir.r4.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r4.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r4.model.IntegerType)
return convertInteger((org.hl7.fhir.r4.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r4.model.UriType)
return convertUri((org.hl7.fhir.r4.model.UriType) src);
if (src instanceof org.hl7.fhir.r4.model.UuidType)

View File

@ -2503,8 +2503,6 @@ public class VersionConvertor_10_50 {
return convertId((org.hl7.fhir.dstu2.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu2.model.InstantType)
return convertInstant((org.hl7.fhir.dstu2.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu2.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu2.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu2.model.OidType)
@ -2517,6 +2515,8 @@ public class VersionConvertor_10_50 {
return convertTime((org.hl7.fhir.dstu2.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu2.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu2.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UriType)
return convertUri((org.hl7.fhir.dstu2.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu2.model.UuidType)
@ -2593,8 +2593,6 @@ public class VersionConvertor_10_50 {
return convertId((org.hl7.fhir.r5.model.IdType) src);
if (src instanceof org.hl7.fhir.r5.model.InstantType)
return convertInstant((org.hl7.fhir.r5.model.InstantType) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.r5.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.r5.model.OidType)
@ -2607,6 +2605,8 @@ public class VersionConvertor_10_50 {
return convertTime((org.hl7.fhir.r5.model.TimeType) src);
if (src instanceof org.hl7.fhir.r5.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r5.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.UriType)
return convertUri((org.hl7.fhir.r5.model.UriType) src);
if (src instanceof org.hl7.fhir.r5.model.UuidType)

View File

@ -2454,8 +2454,6 @@ public class VersionConvertor_14_30 {
return convertId((org.hl7.fhir.dstu2016may.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.InstantType)
return convertInstant((org.hl7.fhir.dstu2016may.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu2016may.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.OidType)
@ -2468,6 +2466,8 @@ public class VersionConvertor_14_30 {
return convertTime((org.hl7.fhir.dstu2016may.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu2016may.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UriType)
return convertUri((org.hl7.fhir.dstu2016may.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UuidType)
@ -2544,8 +2544,6 @@ public class VersionConvertor_14_30 {
return convertId((org.hl7.fhir.dstu3.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu3.model.InstantType)
return convertInstant((org.hl7.fhir.dstu3.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu3.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu3.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu3.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu3.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu3.model.OidType)
@ -2558,6 +2556,8 @@ public class VersionConvertor_14_30 {
return convertTime((org.hl7.fhir.dstu3.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu3.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu3.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu3.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UriType)
return convertUri((org.hl7.fhir.dstu3.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UuidType)

View File

@ -2607,8 +2607,6 @@ public class VersionConvertor_14_40 {
return convertId((org.hl7.fhir.dstu2016may.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.InstantType)
return convertInstant((org.hl7.fhir.dstu2016may.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu2016may.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.OidType)
@ -2621,6 +2619,8 @@ public class VersionConvertor_14_40 {
return convertTime((org.hl7.fhir.dstu2016may.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu2016may.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UriType)
return convertUri((org.hl7.fhir.dstu2016may.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UuidType)
@ -2695,8 +2695,6 @@ public class VersionConvertor_14_40 {
return convertId((org.hl7.fhir.r4.model.IdType) src);
if (src instanceof org.hl7.fhir.r4.model.InstantType)
return convertInstant((org.hl7.fhir.r4.model.InstantType) src);
if (src instanceof org.hl7.fhir.r4.model.IntegerType)
return convertInteger((org.hl7.fhir.r4.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r4.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.r4.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.r4.model.OidType)
@ -2709,6 +2707,8 @@ public class VersionConvertor_14_40 {
return convertTime((org.hl7.fhir.r4.model.TimeType) src);
if (src instanceof org.hl7.fhir.r4.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r4.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r4.model.IntegerType)
return convertInteger((org.hl7.fhir.r4.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r4.model.UriType)
return convertUri((org.hl7.fhir.r4.model.UriType) src);
if (src instanceof org.hl7.fhir.r4.model.UuidType)

View File

@ -2614,8 +2614,6 @@ public class VersionConvertor_14_50 {
return convertId((org.hl7.fhir.dstu2016may.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.InstantType)
return convertInstant((org.hl7.fhir.dstu2016may.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu2016may.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.OidType)
@ -2628,6 +2626,8 @@ public class VersionConvertor_14_50 {
return convertTime((org.hl7.fhir.dstu2016may.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu2016may.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu2016may.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UriType)
return convertUri((org.hl7.fhir.dstu2016may.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu2016may.model.UuidType)
@ -2702,8 +2702,6 @@ public class VersionConvertor_14_50 {
return convertId((org.hl7.fhir.r5.model.IdType) src);
if (src instanceof org.hl7.fhir.r5.model.InstantType)
return convertInstant((org.hl7.fhir.r5.model.InstantType) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.r5.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.r5.model.OidType)
@ -2716,6 +2714,8 @@ public class VersionConvertor_14_50 {
return convertTime((org.hl7.fhir.r5.model.TimeType) src);
if (src instanceof org.hl7.fhir.r5.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r5.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.UriType)
return convertUri((org.hl7.fhir.r5.model.UriType) src);
if (src instanceof org.hl7.fhir.r5.model.UuidType)

View File

@ -3498,20 +3498,20 @@ public class VersionConvertor_30_50 {
return convertId((org.hl7.fhir.dstu3.model.IdType) src);
if (src instanceof org.hl7.fhir.dstu3.model.InstantType)
return convertInstant((org.hl7.fhir.dstu3.model.InstantType) src);
if (src instanceof org.hl7.fhir.dstu3.model.PositiveIntType)
return convertPositiveInt((org.hl7.fhir.dstu3.model.PositiveIntType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu3.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu3.model.IntegerType)
return convertInteger((org.hl7.fhir.dstu3.model.IntegerType) src);
if (src instanceof org.hl7.fhir.dstu3.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.dstu3.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.dstu3.model.OidType)
return convertOid((org.hl7.fhir.dstu3.model.OidType) src);
if (src instanceof org.hl7.fhir.dstu3.model.PositiveIntType)
return convertPositiveInt((org.hl7.fhir.dstu3.model.PositiveIntType) src);
if (src instanceof org.hl7.fhir.dstu3.model.StringType)
return convertString((org.hl7.fhir.dstu3.model.StringType) src);
if (src instanceof org.hl7.fhir.dstu3.model.TimeType)
return convertTime((org.hl7.fhir.dstu3.model.TimeType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.dstu3.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UriType)
return convertUri((org.hl7.fhir.dstu3.model.UriType) src);
if (src instanceof org.hl7.fhir.dstu3.model.UuidType)
@ -3604,22 +3604,22 @@ public class VersionConvertor_30_50 {
return convertId((org.hl7.fhir.r5.model.IdType) src);
if (src instanceof org.hl7.fhir.r5.model.InstantType)
return convertInstant((org.hl7.fhir.r5.model.InstantType) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.PositiveIntType)
return convertPositiveInt((org.hl7.fhir.r5.model.PositiveIntType) src);
if (src instanceof org.hl7.fhir.r5.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r5.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r5.model.Integer64Type)
return convertInteger64((org.hl7.fhir.r5.model.Integer64Type) src);
if (src instanceof org.hl7.fhir.r5.model.IntegerType)
return convertInteger((org.hl7.fhir.r5.model.IntegerType) src);
if (src instanceof org.hl7.fhir.r5.model.MarkdownType)
return convertMarkdown((org.hl7.fhir.r5.model.MarkdownType) src);
if (src instanceof org.hl7.fhir.r5.model.OidType)
return convertOid((org.hl7.fhir.r5.model.OidType) src);
if (src instanceof org.hl7.fhir.r5.model.PositiveIntType)
return convertPositiveInt((org.hl7.fhir.r5.model.PositiveIntType) src);
if (src instanceof org.hl7.fhir.r5.model.StringType)
return convertString((org.hl7.fhir.r5.model.StringType) src);
if (src instanceof org.hl7.fhir.r5.model.TimeType)
return convertTime((org.hl7.fhir.r5.model.TimeType) src);
if (src instanceof org.hl7.fhir.r5.model.UnsignedIntType)
return convertUnsignedInt((org.hl7.fhir.r5.model.UnsignedIntType) src);
if (src instanceof org.hl7.fhir.r5.model.UriType)
return convertUri((org.hl7.fhir.r5.model.UriType) src);
if (src instanceof org.hl7.fhir.r5.model.UuidType)

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -111,6 +111,7 @@ import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
import org.hl7.fhir.r5.utils.formats.CSVWriter;
import org.hl7.fhir.r5.utils.formats.XLSXWriter;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
@ -362,9 +363,28 @@ public class ProfileUtilities extends TranslatingUtilities {
public List<ElementDefinition> getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
if (element.getContentReference()!=null) {
for (ElementDefinition e : profile.getSnapshot().getElement()) {
if (element.getContentReference().equals("#"+e.getId()))
if (element.getContentReference() != null) {
List<ElementDefinition> list = null;
String id = null;
if (element.getContentReference().startsWith("#")) {
// internal reference
id = element.getContentReference().substring(1);
list = profile.getSnapshot().getElement();
} else if (element.getContentReference().contains("#")) {
// external reference
String ref = element.getContentReference();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ref.substring(0, ref.indexOf("#")));
if (sd == null) {
throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'");
}
list = sd.getSnapshot().getElement();
id = ref.substring(ref.indexOf("#")+1);
} else {
throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'");
}
for (ElementDefinition e : list) {
if (id.equals(e.getId()))
return getChildMap(profile, e);
}
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_NAME_REFERENCE__AT_PATH_, element.getContentReference(), element.getPath()));
@ -3155,6 +3175,10 @@ public class ProfileUtilities extends TranslatingUtilities {
c.getPieces().add(checkForNoChange(ved.getBinding(), gen.new Piece(corePath+"terminologies.html#"+ved.getBinding().getStrength().toCode(), egt(ved.getBinding().getStrengthElement()), ved.getBinding().getStrength().getDefinition())));
c.getPieces().add(gen.new Piece(null, ")", null));
}
if (ved.getBinding().hasDescription() && MarkDownProcessor.isSimpleMarkdown(ved.getBinding().getDescription())) {
c.getPieces().add(gen.new Piece(null, ": ", null));
c.addMarkdownNoPara(ved.getBinding().getDescription());
}
}
c.addPiece(gen.new Piece("br")).addPiece(gen.new Piece(null, describeExtensionContext(ed), null));
r.getCells().add(c);
@ -3195,12 +3219,17 @@ public class ProfileUtilities extends TranslatingUtilities {
Cell c = gen.new Cell();
r.getCells().add(c);
if (e.hasContentReference()) {
ElementDefinition ed = getElementByName(profile.getSnapshot().getElement(), e.getContentReference());
ElementInStructure ed = getElementByName(profile.getSnapshot().getElement(), e.getContentReference(), profile);
if (ed == null)
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Unknown reference to %s", e.getContentReference()), null));
else {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "See ", ed.getPath()), null));
c.getPieces().add(gen.new Piece("#"+ed.getPath(), tail(ed.getPath()), ed.getPath()));
if (ed.getSource() == profile) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "See ", ed.getElement().getPath()), null));
c.getPieces().add(gen.new Piece("#"+ed.getElement().getPath(), tail(ed.getElement().getPath()), ed.getElement().getPath()));
} else {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "See ", ed.getElement().getPath()), null));
c.getPieces().add(gen.new Piece(ed.getSource().getUserString("path")+"#"+ed.getElement().getPath(), tail(ed.getElement().getPath())+" ("+ed.getSource().getType()+")", ed.getElement().getPath()));
}
}
return c;
}
@ -3385,16 +3414,46 @@ public class ProfileUtilities extends TranslatingUtilities {
}
private ElementDefinition getElementByName(List<ElementDefinition> elements, String contentReference) {
private class ElementInStructure {
private StructureDefinition source;
private ElementDefinition element;
public ElementInStructure(StructureDefinition source, ElementDefinition ed) {
this.source = source;
this.element = ed;
}
public StructureDefinition getSource() {
return source;
}
public ElementDefinition getElement() {
return element;
}
}
private ElementInStructure getElementByName(List<ElementDefinition> elements, String contentReference, StructureDefinition source) {
if (contentReference.contains("#")) {
String url = contentReference.substring(0, contentReference.indexOf("#"));
contentReference = contentReference.substring(contentReference.indexOf("#"));
if (!url.equals(source.getUrl())) {
source = context.fetchResource(StructureDefinition.class, url);
if (source == null) {
throw new FHIRException("Unable to resolve StructureDefinition "+url+" resolving content reference "+contentReference);
}
elements = source.getSnapshot().getElement();
}
}
for (ElementDefinition ed : elements) {
if (("#"+ed.getPath()).equals(contentReference)) {
return ed;
return new ElementInStructure(source, ed);
}
if (("#"+ed.getId()).equals(contentReference)) {
return ed;
return new ElementInStructure(source, ed);
}
}
throw new Error("getElementByName: can't find "+contentReference+"in "+elements.toString());
throw new Error("getElementByName: can't find "+contentReference+" in "+elements.toString()+" from "+source.getUrl());
// return null;
}
@ -4282,6 +4341,10 @@ public class ProfileUtilities extends TranslatingUtilities {
c.getPieces().add(checkForNoChange(binding, gen.new Piece(corePath+"extension-elementdefinition-minvalueset.html", translate("sd.table", "Min Binding")+": ", "Min Value Set Extension").addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(binding, gen.new Piece(br.url == null ? null : Utilities.isAbsoluteUrl(br.url) || !pkp.prependLinks() ? br.url : corePath+br.url, br.display, null)));
}
if (binding.hasDescription() && MarkDownProcessor.isSimpleMarkdown(binding.getDescription())) {
c.getPieces().add(gen.new Piece(null, ": ", null));
c.addMarkdownNoPara(binding.getDescription());
}
}
for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) {
if (!inv.hasSource() || profile == null || inv.getSource().equals(profile.getUrl()) || allInvariants) {
@ -4300,7 +4363,6 @@ public class ProfileUtilities extends TranslatingUtilities {
// don't show this, this it's important: c.getPieces().add(gen.new Piece(null, "This repeating element has no defined order", null));
}
}
if (definition.hasFixed()) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, translate("sd.table", "Fixed Value")+": ", null).addStyle("font-weight:bold")));
@ -4548,11 +4610,16 @@ public class ProfileUtilities extends TranslatingUtilities {
if (used) {
if (definition.hasContentReference()) {
ElementDefinition ed = getElementByName(profile.getSnapshot().getElement(), definition.getContentReference());
ElementInStructure ed = getElementByName(profile.getSnapshot().getElement(), definition.getContentReference(), profile);
if (ed == null)
c.getPieces().add(gen.new Piece(null, "Unknown reference to "+definition.getContentReference(), null));
else
c.getPieces().add(gen.new Piece("#"+ed.getPath(), "See "+ed.getPath(), null));
else {
if (ed.getSource() == profile) {
c.getPieces().add(gen.new Piece("#"+ed.getElement().getPath(), "See "+ed.getElement().getPath(), null));
} else {
c.getPieces().add(gen.new Piece(ed.getSource().getUserData("path")+"#"+ed.getElement().getPath(), "See "+ed.getSource().getType()+"."+ed.getElement().getPath(), null));
}
}
}
if (definition.getPath().endsWith("url") && definition.hasFixed()) {
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "\""+buildJson(definition.getFixed())+"\"", null).addStyle("color: darkgreen")));
@ -4594,6 +4661,10 @@ public class ProfileUtilities extends TranslatingUtilities {
c.getPieces().add(checkForNoChange(binding, gen.new Piece(null, " (", null)));
c.getPieces().add(checkForNoChange(binding, gen.new Piece(corePath+"terminologies.html#"+binding.getStrength().toCode(), binding.getStrength().toCode(), binding.getStrength().getDefinition()))); c.getPieces().add(gen.new Piece(null, ")", null));
}
if (binding.hasDescription() && MarkDownProcessor.isSimpleMarkdown(binding.getDescription())) {
c.getPieces().add(gen.new Piece(null, ": ", null));
c.addMarkdownNoPara(binding.getDescription());
}
}
for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
@ -5338,12 +5409,12 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!checkFirst || !sd.hasDifferential() || hasMissingIds(sd.getDifferential().getElement())) {
if (!sd.hasDifferential())
sd.setDifferential(new StructureDefinitionDifferentialComponent());
generateIds(sd.getDifferential().getElement(), sd.getUrl());
generateIds(sd.getDifferential().getElement(), sd.getUrl(), sd.getType());
}
if (!checkFirst || !sd.hasSnapshot() || hasMissingIds(sd.getSnapshot().getElement())) {
if (!sd.hasSnapshot())
sd.setSnapshot(new StructureDefinitionSnapshotComponent());
generateIds(sd.getSnapshot().getElement(), sd.getUrl());
generateIds(sd.getSnapshot().getElement(), sd.getUrl(), sd.getType());
}
}
@ -5388,11 +5459,10 @@ public class ProfileUtilities extends TranslatingUtilities {
}
private void generateIds(List<ElementDefinition> list, String name) throws DefinitionException {
private void generateIds(List<ElementDefinition> list, String name, String type) throws DefinitionException {
if (list.isEmpty())
return;
Map<String, String> idMap = new HashMap<String, String>();
Map<String, String> idList = new HashMap<String, String>();
SliceList sliceInfo = new SliceList();
@ -5420,7 +5490,6 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
String bs = b.toString();
idMap.put(ed.hasId() ? ed.getId() : ed.getPath(), bs);
ed.setId(bs);
if (idList.containsKey(bs)) {
if (exception || messages == null) {
@ -5429,11 +5498,9 @@ public class ProfileUtilities extends TranslatingUtilities {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, "Duplicate Element id "+bs, ValidationMessage.IssueSeverity.ERROR));
}
idList.put(bs, ed.getPath());
if (ed.hasContentReference()) {
String s = ed.getContentReference().substring(1);
if (idMap.containsKey(s))
ed.setContentReference("#"+idMap.get(s));
if (ed.hasContentReference() && ed.getContentReference().startsWith("#")) {
String s = ed.getContentReference();
ed.setContentReference("http://hl7.org/fhir/StructureDefinition/"+type+s);
}
}
// second path - fix up any broken path based id references

View File

@ -75,15 +75,15 @@ public class Element extends Base {
CONTAINED, BUNDLE_ENTRY, BUNDLE_OUTCOME, PARAMETER;
public static SpecialElement fromProperty(Property property) {
if (property.getStructure().getIdElement().getIdPart().equals("Parameters"))
if (property.getStructure().getType().equals("Parameters"))
return PARAMETER;
if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("resource"))
if (property.getStructure().getType().equals("Bundle") && property.getName().equals("resource"))
return BUNDLE_ENTRY;
if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("outcome"))
if (property.getStructure().getType().equals("Bundle") && property.getName().equals("outcome"))
return BUNDLE_OUTCOME;
if (property.getName().equals("contained"))
return CONTAINED;
throw new Error("Unknown resource containing a native resource: "+property.getDefinition().getId());
throw new FHIRException("Unknown resource containing a native resource: "+property.getDefinition().getId());
}
}

View File

@ -208,6 +208,9 @@ public class JsonParser extends ParserBase {
JsonElement e = object.get(name);
if (property.isList() && (e instanceof JsonArray)) {
JsonArray arr = (JsonArray) e;
if (arr.size() == 0) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
}
int c = 0;
for (JsonElement am : arr) {
parseChildComplexInstance(npath+"["+c+"]", object, element, property, name, am);

View File

@ -1,44 +1,42 @@
package org.hl7.fhir.r5.model;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
/**
* Primitive type "integer" in FHIR: A signed 32-bit integer
* Primitive type "integer64" in FHIR: A signed 64-bit integer
*/
@DatatypeDef(name = "integer")
@DatatypeDef(name = "integer64")
public class Integer64Type extends PrimitiveType<Long> /* implements IBaseInteger64Datatype */ {
private static final long serialVersionUID = 3L;
@ -76,12 +74,8 @@ public class Integer64Type extends PrimitiveType<Long> /* implements IBaseIntege
* @throws IllegalArgumentException If the value is too large to fit in a signed integer
*/
public Integer64Type(Long theValue) {
if (theValue < java.lang.Long.MIN_VALUE || theValue > java.lang.Long.MAX_VALUE) {
throw new IllegalArgumentException
(theValue + " cannot be cast to int without changing its value.");
}
if(theValue!=null) {
setValue((long)theValue.longValue());
setValue(theValue);
}
}

View File

@ -401,7 +401,7 @@ public class LibraryRenderer extends ResourceRenderer {
p.code().tx(att.getContentType()+lang(att));
}
String prismCode = determinePrismCode(att);
if (prismCode != null) {
if (prismCode != null && !tooBig(txt)) {
x.pre().code().setAttribute("class", "language-"+prismCode).tx(txt);
} else {
x.pre().code().tx(txt);
@ -420,6 +420,10 @@ public class LibraryRenderer extends ResourceRenderer {
}
}
private boolean tooBig(String txt) {
return txt.length() > 16384;
}
private String imgExtension(String contentType) {
if (contentType != null && contentType.startsWith("image/")) {
if (contentType.startsWith("image/png")) {

View File

@ -119,8 +119,13 @@ public class ParametersRenderer extends ResourceRenderer {
if (p.hasValue()) {
render(tr.td(), p.getValue());
} else if (p.hasResource()) {
ResourceRenderer rr = RendererFactory.factory(p.getResource(), context);
rr.render(tr.td(), p.getResource());
Resource r = p.getResource();
td = tr.td();
XhtmlNode para = td.para();
para.tx(r.fhirType()+"/"+r.getId());
para.an(r.fhirType()+"_"+r.getId()).tx(" ");
ResourceRenderer rr = RendererFactory.factory(r, context);
rr.render(td, r);
} else if (p.hasPart()) {
tr.td();
params(tbl, p.getPart(), 1);

View File

@ -651,7 +651,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
child = p.getElementDefinition();
}
if (child != null) {
generateElementByProfile(res, profile, allElements, x, path, showCodeDetails, indent, p, child);
if (!child.getBase().hasPath() || !child.getBase().getPath().startsWith("Resource.")) {
generateElementByProfile(res, profile, allElements, x, path, showCodeDetails, indent, p, child);
}
}
}
}
@ -721,7 +723,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
XhtmlNode para = x.para();
para.b().addText(p.getStructure().present());
para.tx(": ");
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
renderLeaf(res, vv, child, x, para, false, showCodeDetails, displayHints, path, indent);
} else if (ev.hasValues()) {
XhtmlNode bq = x.addTag("blockquote");
bq.para().b().addText(isExtension(p) ? p.getStructure().present() : p.getName());

View File

@ -46,6 +46,7 @@ public class OperationOutcomeUtilities {
public static OperationOutcomeIssueComponent convertToIssue(ValidationMessage message, OperationOutcome op) {
OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
issue.setUserData("source.vm", message);
issue.setCode(convert(message.getType()));
if (message.getLocation() != null) {

View File

@ -104,6 +104,8 @@ public class ProfileUtilitiesTests {
f.setComment(null);
b.setDefinition(null);
f.setDefinition(null);
b.setContentReference(null);
f.setContentReference(null);
ok = Base.compareDeep(b, f, true);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -78,5 +78,10 @@ public class MarkDownProcessor {
html = html.replace("<table>", "<table class=\"grid\">");
return html;
}
public static boolean isSimpleMarkdown(String description) {
return !description.contains("\n");
}
}

View File

@ -3,8 +3,8 @@ package org.hl7.fhir.utilities;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.npm.NpmPackage;
/*
Copyright (c) 2011+, HL7, Inc.
@ -216,13 +216,17 @@ public class VersionUtilities {
}
/**
* return true if the current version equals test, or later
*
* so if a feature is defined in 4.0, if (VersionUtilities.isThisOrLater("4.0", version))...
* return true if the current version equals test, or later,
* so if a feature is defined in 4.0, if (VersionUtilities.isThisOrLater("4.0", version))
* <p>
* This method tries to perform a numeric parse, so that <code>0.9</code> will be considered below <code>0.10</code>
* in accordance with SemVer. If either side contains a non-numeric character in a version string, a simple text
* compare will be done instead.
* </p>
*
* @param test
* @param current
* @return
* @param test The value to compare to
* @param current The value being compared
* @return Is {@literal current} later or equal to {@literal test}? For example, if <code>this = 0.5</code> and <code>current = 0.6</code> this method will return true
*/
public static boolean isThisOrLater(String test, String current) {
String t = getMajMin(test);
@ -230,8 +234,33 @@ public class VersionUtilities {
if (c.compareTo(t) == 0) {
return isMajMinOrLaterPatch(test, current);
}
boolean ok = c.compareTo(t) >= 0;
return ok;
String[] testParts = t.split("\\.");
String[] currentParts = c.split("\\.");
for (int i = 0; i < Math.max(testParts.length, currentParts.length); i++) {
if (i == testParts.length) {
return true;
} else if (i == currentParts.length) {
return false;
}
String testPart = testParts[i];
String currentPart = currentParts[i];
if (testPart.equals(currentPart)) {
continue;
}
return compareVersionPart(testPart, currentPart);
}
return true;
}
private static boolean compareVersionPart(String theTestPart, String theCurrentPart) {
if (StringUtils.isNumeric(theTestPart) && StringUtils.isNumeric(theCurrentPart)) {
return Integer.parseInt(theCurrentPart) - Integer.parseInt(theTestPart) >= 0;
} else {
return theCurrentPart.compareTo(theTestPart) >= 0;
}
}
/**
@ -251,7 +280,7 @@ public class VersionUtilities {
return true;
}
if (pc!=null) {
return pc.compareTo(pt) >= 0;
return compareVersionPart(pt, pc);
}
}
return false;

View File

@ -12,6 +12,7 @@ public class I18nConstants {
public static final String ALL_OBSERVATIONS_SHOULD_HAVE_A_PERFORMER = "All_observations_should_have_a_performer";
public static final String ALL_OBSERVATIONS_SHOULD_HAVE_A_SUBJECT = "All_observations_should_have_a_subject";
public static final String ALL_OK = "ALL_OK";
public static final String ARRAY_CANNOT_BE_EMPTY = "ARRAY_CANNOT_BE_EMPTY";
public static final String ATTEMPT_TO_A_SLICE_AN_ELEMENT_THAT_DOES_NOT_REPEAT__FROM__IN_ = "Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_";
public static final String ATTEMPT_TO_REPLACE_ELEMENT_NAME_FOR_A_NONCHOICE_TYPE = "Attempt_to_replace_element_name_for_a_nonchoice_type";
public static final String ATTEMPT_TO_USE_A_SNAPSHOT_ON_PROFILE__AS__BEFORE_IT_IS_GENERATED = "Attempt_to_use_a_snapshot_on_profile__as__before_it_is_generated";

View File

@ -351,6 +351,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
System.out.println();
System.out.print(" Installing: ");
}
if (npm.name() == null || id == null || !id.equals(npm.name())) {
if (!id.equals("hl7.fhir.r5.core")) {// temporary work around
throw new IOException("Attempt to import a mis-identified package. Expected " + id + ", got " + npm.name());

View File

@ -240,6 +240,7 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
pieces.add(piece);
return this;
}
public Cell addMarkdown(String md) {
try {
Parser parser = Parser.builder().build();
@ -253,6 +254,19 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
return this;
}
public Cell addMarkdownNoPara(String md) {
try {
Parser parser = Parser.builder().build();
Node document = parser.parse(md);
HtmlRenderer renderer = HtmlRenderer.builder().escapeHtml(true).build();
String html = renderer.render(document);
pieces.addAll(htmlToParagraphPieces(html));
} catch (Exception e) {
e.printStackTrace();
}
return this;
}
private List<Piece> htmlToParagraphPieces(String html) {
List<Piece> myPieces = new ArrayList<Piece>();
try {

View File

@ -209,11 +209,12 @@ Validation_BUNDLE_Message = The first entry in a message must be a MessageHeader
Validation_VAL_Content_Unknown = Unrecognised Content {0}
Validation_VAL_NoType = Unknown type {0}
Validation_VAL_Profile_MatchMultiple = Profile {0}, Element matches more than one slice - {1}, {2}
Validation_VAL_Profile_Maximum = {0}: max allowed = {1}, but found {2}
Validation_VAL_Profile_Minimum = {0}: minimum required = {1}, but only found {2}
// for the next 4 messages, the available parameters are: 0: profile url, 1: ed.path, 2: ed.id, 3: ed.sliceName, 4: ed.label, 5: element.path, 6: ed.min and optionally 7: actual count
Validation_VAL_Profile_Maximum = {2}: max allowed = {6}, but found {7} (from {0})
Validation_VAL_Profile_Minimum = {2}: minimum required = {6}, but only found {7} (from {0})
Validation_VAL_Profile_NoCheckMax = {2}: Unable to check max allowed ({1}) due to lack of slicing validation (from {0})
Validation_VAL_Profile_NoCheckMin = {2}: Unable to check minimum required ({1}) due to lack of slicing validation (from {0})
Validation_VAL_Profile_MultipleMatches = Found multiple matching profiles among choices: {0}
Validation_VAL_Profile_NoCheckMax = {0}: Unable to check max allowed ({1}) due to lack of slicing validation
Validation_VAL_Profile_NoCheckMin = {0}'': Unable to check minimum required ({1}) due to lack of slicing validation
Validation_VAL_Profile_NoDefinition = No definition found for resource type ''{0}''
Validation_VAL_Profile_NoMatch = Unable to find matching profile among choices: {0}
Validation_VAL_Profile_NoSnapshot = StructureDefinition has no snapshot - validation is against the snapshot, so it must be provided
@ -617,4 +618,5 @@ SD_ED_TYPE_PROFILE_NOTYPE = Found profile {0}, but unable to determine the type
SD_ED_TYPE_PROFILE_WRONG = Profile {0} is for type {1}, but this element has type {2}
TERMINOLOGY_TX_NOSVC_BOUND_REQ = Could not confirm that the codes provided are from the required value set {0} because there is no terminology service
TERMINOLOGY_TX_NOSVC_BOUND_EXT = Could not confirm that the codes provided are from the extensible value set {0} because there is no terminology service
ARRAY_CANNOT_BE_EMPTY = Array cannot be empty - the property should not be present if it has no values

View File

@ -0,0 +1,48 @@
package org.hl7.fhir.utilities;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class VersionUtilitiesTest {
@Test
public void isThisOrLater_Simple() {
assertTrue(VersionUtilities.isThisOrLater("0.1", "0.2"));
assertFalse(VersionUtilities.isThisOrLater("0.2", "0.1"));
}
@Test
public void isThisOrLater_NeedNumericComparison() {
assertTrue(VersionUtilities.isThisOrLater("0.9", "0.10"));
assertFalse(VersionUtilities.isThisOrLater("0.10", "0.9"));
}
@Test
public void isThisOrLater_DifferentLengths() {
assertTrue(VersionUtilities.isThisOrLater("0.9", "0.9.1"));
assertFalse(VersionUtilities.isThisOrLater("0.9.1", "0.9"));
}
@Test
public void isThisOrLater_NonNumeric() {
assertTrue(VersionUtilities.isThisOrLater("0.A", "0.B"));
assertFalse(VersionUtilities.isThisOrLater("0.B", "0.A"));
}
@Test
public void isMajMinOrLaterPatch_Simple() {
assertTrue(VersionUtilities.isMajMinOrLaterPatch("0.9.0", "0.9.0"));
assertTrue(VersionUtilities.isMajMinOrLaterPatch("0.9.0", "0.9.1"));
assertFalse(VersionUtilities.isThisOrLater("0.9.0", "0.8.1"));
}
@Test
public void isMajMinOrLaterPatch_VersionWithX() {
assertTrue(VersionUtilities.isMajMinOrLaterPatch("0.9.x", "0.9.0"));
assertTrue(VersionUtilities.isMajMinOrLaterPatch("0.9.x", "0.9.1"));
assertFalse(VersionUtilities.isThisOrLater("0.9.x", "0.8.1"));
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.18-SNAPSHOT</version>
<version>5.1.21-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.1.18-SNAPSHOT</version>
<version>5.1.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -29,6 +29,10 @@ import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.convertors.VersionConvertorAdvisor50;
import org.hl7.fhir.convertors.VersionConvertor_10_30;
@ -56,6 +60,7 @@ import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.elementmodel.ParserBase.ValidationPolicy;
import org.hl7.fhir.r5.elementmodel.ObjectConverter;
import org.hl7.fhir.r5.formats.FormatUtilities;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
@ -98,19 +103,23 @@ import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.ToolsVersion;
import org.hl7.fhir.utilities.turtle.Turtle;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
import org.hl7.fhir.validation.BaseValidator.ValidationControl;
import org.hl7.fhir.validation.ValidationEngine.ValidationRecord;
import org.hl7.fhir.validation.cli.model.ScanOutputItem;
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
import org.hl7.fhir.validation.cli.utils.*;
import org.hl7.fhir.validation.instance.InstanceValidator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
@ -187,6 +196,50 @@ POSSIBILITY OF SUCH DAMAGE.
*/
public class ValidationEngine implements IValidatorResourceFetcher, IPackageInstaller {
public class ValidationRecord {
private String location;
private List<ValidationMessage> messages;
int err = 0;
int warn = 0;
int info = 0;
public ValidationRecord(String location, List<ValidationMessage> messages) {
this.location = location;
this.messages = messages;
for (ValidationMessage vm : messages) {
if (vm.getLevel().equals(ValidationMessage.IssueSeverity.FATAL)||vm.getLevel().equals(ValidationMessage.IssueSeverity.ERROR))
err++;
else if (vm.getLevel().equals(ValidationMessage.IssueSeverity.WARNING))
warn++;
else if (!vm.isSignpost()) {
info++;
}
}
}
public String getLocation() {
return location;
}
public List<ValidationMessage> getMessages() {
return messages;
}
public int getErr() {
return err;
}
public int getWarn() {
return warn;
}
public int getInfo() {
return info;
}
}
public class TransformSupportServices implements ITransformerServices {
private List<Base> outputs;
@ -538,7 +591,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
throw new FHIRException("Unable to fetch content from "+src+" ("+errors.toString()+")");
}
FhirFormat fmt = checkIsResource(cnt, src);
FhirFormat fmt = checkFormat(cnt, src);
if (fmt != null) {
Map<String, byte[]> res = new HashMap<String, byte[]>();
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
@ -809,33 +862,99 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
this.noInvariantChecks = value;
}
private FhirFormat checkFormat(byte[] cnt, String filename) {
System.out.println(" ..Detect format for "+filename);
try {
JsonTrackingParser.parseJson(cnt);
return FhirFormat.JSON;
} catch (Exception e) {
if (debug) {
System.out.println("Not JSON: "+e.getMessage());
}
}
try {
parseXml(cnt);
return FhirFormat.XML;
} catch (Exception e) {
if (debug) {
System.out.println("Not XML: "+e.getMessage());
}
}
try {
new Turtle().parse(TextFile.bytesToString(cnt));
return FhirFormat.TURTLE;
} catch (Exception e) {
if (debug) {
System.out.println("Not Turtle: "+e.getMessage());
}
}
try {
new StructureMapUtilities(context, null, null).parse(TextFile.bytesToString(cnt), null);
return FhirFormat.TEXT;
} catch (Exception e) {
if (debug) {
System.out.println("Not Text: "+e.getMessage());
}
}
if (debug)
System.out.println(" .. not a resource: "+filename);
return null;
}
private FhirFormat checkIsResource(byte[] cnt, String filename) {
System.out.println(" ..Detect format for "+filename);
try {
Manager.parse(context, new ByteArrayInputStream(cnt), FhirFormat.JSON);
return FhirFormat.JSON;
} catch (Exception e) {
if (debug) {
System.out.println("Not JSON: "+e.getMessage());
}
}
try {
Manager.parse(context, new ByteArrayInputStream(cnt),FhirFormat.XML);
parseXml(cnt);
return FhirFormat.XML;
} catch (Exception e) {
if (debug) {
System.out.println("Not XML: "+e.getMessage());
}
}
try {
Manager.parse(context, new ByteArrayInputStream(cnt),FhirFormat.TURTLE);
return FhirFormat.TURTLE;
} catch (Exception e) {
if (debug) {
System.out.println("Not Turtle: "+e.getMessage());
}
}
try {
new StructureMapUtilities(context, null, null).parse(TextFile.bytesToString(cnt), null);
return FhirFormat.TEXT;
} catch (Exception e) {
if (debug) {
System.out.println("Not Text: "+e.getMessage());
}
}
if (debug)
System.out.println(" .. not a resource: "+filename);
return null;
}
private Document parseXml(byte[] cnt) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// xxe protection
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(cnt));
}
private FhirFormat checkIsResource(String path) throws IOException {
String ext = Utilities.getFileExtension(path);
if (Utilities.existsInList(ext, "xml"))
@ -1097,7 +1216,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
public OperationOutcome validate(String source, List<String> profiles) throws FHIRException, IOException {
List<String> l = new ArrayList<String>();
l.add(source);
return (OperationOutcome)validate(l, profiles);
return (OperationOutcome)validate(l, profiles, null);
}
public List<ScanOutputItem> validateScan(List<String> sources, Set<String> guides) throws FHIRException, IOException, EOperationOutcome {
@ -1193,7 +1312,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
}
public Resource validate(List<String> sources, List<String> profiles) throws FHIRException, IOException {
public Resource validate(List<String> sources, List<String> profiles, List<ValidationRecord> record) throws FHIRException, IOException {
if (profiles.size() > 0) {
System.out.println(" Profiles: "+profiles);
}
@ -1207,7 +1326,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
System.out.print(" Validate " + ref);
Content cnt = loadContent(ref, "validate", false);
try {
OperationOutcome outcome = validate(ref, cnt.focus, cnt.cntType, profiles);
OperationOutcome outcome = validate(ref, cnt.focus, cnt.cntType, profiles, record);
ToolingExtensions.addStringExtension(outcome, ToolingExtensions.EXT_OO_FILE, ref);
System.out.println(" " + context.clock().milestone());
results.addEntry().setResource(outcome);
@ -1281,7 +1400,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
}
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws FHIRException, IOException, EOperationOutcome, SAXException {
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles, List<ValidationRecord> record) throws FHIRException, IOException, EOperationOutcome, SAXException {
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
if (doNative) {
SchemaValidator.validateSchema(location, cntType, messages);
@ -1291,6 +1410,9 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
if (showTimes) {
System.out.println(location+": "+validator.reportTimes());
}
if (record != null) {
record.add(new ValidationRecord(location, messages));
}
return messagesToOutcome(messages);
}

View File

@ -41,6 +41,8 @@ public class CliContext {
private String map = null;
@JsonProperty("output")
private String output = null;
@JsonProperty("htmlOutput")
private String htmlOutput = null;
@JsonProperty("txServer")
private String txServer = "http://tx.fhir.org";
@JsonProperty("sv")
@ -252,6 +254,17 @@ public class CliContext {
return this;
}
@JsonProperty("htmlOutput")
public String getHtmlOutput() {
return htmlOutput;
}
@JsonProperty("htmlOutput")
public CliContext setHtmlOutput(String htmlOutput) {
this.htmlOutput = htmlOutput;
return this;
}
@JsonProperty("canDoNative")
public boolean getCanDoNative() {
return canDoNative;
@ -472,6 +485,7 @@ public class CliContext {
noExtensibleBindingMessages == that.noExtensibleBindingMessages &&
Objects.equals(map, that.map) &&
Objects.equals(output, that.output) &&
Objects.equals(htmlOutput, that.htmlOutput) &&
Objects.equals(txServer, that.txServer) &&
Objects.equals(sv, that.sv) &&
Objects.equals(txLog, that.txLog) &&
@ -493,7 +507,7 @@ public class CliContext {
@Override
public int hashCode() {
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, map, output, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
}
@Override
@ -510,6 +524,7 @@ public class CliContext {
", noExtensibleBindingMessages=" + noExtensibleBindingMessages +
", map='" + map + '\'' +
", output='" + output + '\'' +
", htmlOutput='" + htmlOutput + '\'' +
", txServer='" + txServer + '\'' +
", sv='" + sv + '\'' +
", txLog='" + txLog + '\'' +

View File

@ -0,0 +1,181 @@
package org.hl7.fhir.validation.cli.services;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.validation.ValidationEngine.ValidationRecord;
import org.hl7.fhir.validation.cli.utils.VersionUtil;
public class HTMLOutputGenerator {
private List<ValidationRecord> records;
public HTMLOutputGenerator(List<ValidationRecord> records) {
super();
this.records = records;
}
public String generate(long time) {
StringBuilder b = new StringBuilder();
b.append(genHeader(time));
int i = 0;
for (ValidationRecord f : records) {
i++;
b.append(genSummaryRow(i, f));
}
b.append("</table>\r\n");
i = 0;
int id = 0;
for (ValidationRecord f : records) {
i++;
b.append(genStart(i, f));
if (f.getMessages().size() > 0) {
b.append(
" <table class=\"grid\">\r\n"+
" <tr>\r\n"+
" <td><b>Path</b></td><td><b>Severity</b></td><td><b>Message</b></td>\r\n"+
" </tr>\r\n");
for (ValidationMessage vm : f.getMessages()) {
id++;
b.append(genDetails(vm, "m"+id));
}
b.append("</table>\r\n");
} else {
b.append("<p>No Issues detected</p>\r\n");
}
}
return b.toString();
}
private String genHeader(long time) {
int err = 0;
int warn = 0;
int info = 0;
for (ValidationRecord f : records) {
err = err + f.getErr();
warn = warn + f.getWarn();
info = info + f.getInfo();
}
return
"<!DOCTYPE HTML>\r\n"+
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\r\n"+
"<head>\r\n"+
" <title>Validation Results</title>\r\n"+
" <link href=\"http://hl7.org/fhir/fhir.css\" rel=\"stylesheet\"/>\r\n"+
" <style>\r\n"+
" span.flip { background-color: #4CAF50; color: white; border: solid 1px #a6d8a8; padding: 2px }\r\n"+
" </style>\r\n"+
" <script>\r\n"+
" function flip(id) {\r\n"+
" var span = document.getElementById('s'+id);\r\n"+
" var div = document.getElementById(id);\r\n"+
" if (document.getElementById('s'+id).innerHTML == 'Show Reasoning') {\r\n"+
" div.style.display = 'block';\r\n"+
" span.innerHTML = 'Hide Reasoning';\r\n"+
" } else {\r\n"+
" div.style.display = 'none';\r\n"+
" span.innerHTML = 'Show Reasoning';\r\n"+
" }\r\n"+
" }\r\n"+
" </script>\r\n"+
"</head>\r\n"+
"<body style=\"margin: 20px; background-color: #ffffff\">\r\n"+
" <h1>Validation Results</h1>\r\n"+
" <p>"+err+" "+Utilities.pluralize("error", err)+", "+warn+" "+Utilities.pluralize("warning", warn)+", "+info+" "+Utilities.pluralize("hint", info)+". Generated "+now()+" by Validator "+VersionUtil.getVersionString()+" ("+time+"ms)</p>\r\n"+
" <table class=\"grid\">\r\n"+
" <tr>\r\n"+
" <td><b>Filename</b></td><td><b>Errors</b></td><td><b>Warnings</b></td><td><b>Hints</b></td>\r\n"+
" </tr>\r\n";
}
private String now() {
return DateFormat.getDateTimeInstance().format(new Date());
}
private String genSummaryRow(int i, ValidationRecord rec) {
String color = colorForLevel(IssueSeverity.ERROR, false);
if (rec.getErr() == 0) {
color = "#EFFFEF";
}
return
" <tr style=\"background-color: "+color+"\">\r\n"+
" <td><a href=\"#;"+i+"\"><b>"+Utilities.escapeXml(rec.getLocation())+"</b></a></td><td><b>"+rec.getErr()+"</b></td><td><b>"+rec.getWarn()+"</b></td><td><b>"+rec.getInfo()+"</b></td>\r\n"+
" </tr>\r\n";
}
private String genStart(int i, ValidationRecord f) {
String xlink = Utilities.isAbsoluteUrl(f.getLocation()) ? f.getLocation() : "file:"+f.getLocation();
return
"<hr/>\r\n"+
"<a name=\"l"+i+"\"> </a>\r\n"+
"<h2><a href=\""+xlink+"\">"+Utilities.escapeXml(f.getLocation())+"</a></h2>\r\n";
}
private String genDetails(ValidationMessage vm, String id) {
String path = vm.getLocation() == null ? "" : vm.getLocation()+ lineCol(vm);
String level = vm.isSlicingHint() ? "Slicing Information" : vm.isSignpost() ? "Process Info" : vm.getLevel().toCode();
String color = colorForLevel(vm.getLevel(), vm.isSignpost());
String mid = vm.getMessageId();
String msg = vm.getHtml();
String msgdetails = vm.isSlicingHint() ? vm.getSliceHtml() : vm.getHtml();
if (vm.isSlicingHint()) {
return
" <tr style=\"background-color: "+color+"\">\r\n"+
" <td><b>"+path+"</b></td><td><b>"+level+"</b></td><td><b>"+msg+"</b> <span id=\"s"+id+"\" class=\"flip\" onclick=\"flip('"+id+"')\">Show Reasoning</span><div id=\""+id+"\" style=\"display: none\"><p>&nbsp;</p>"+msgdetails+"</div></td>\r\n"+
" </tr>\r\n";
} else {
return
" <tr style=\"background-color: "+color+"\">\r\n"+
" <td><b>"+path+"</b></td><td><b>"+level+"</b></td><td title=\""+mid+"\"><b>"+msg+"</b></td>\r\n"+
" </tr>\r\n";
}
}
private String lineCol(ValidationMessage vm) {
return vm.getLine() > 0 ? " (l"+vm.getLine()+"/c"+vm.getCol()+")" : "";
}
private String colorForLevel(IssueSeverity level, boolean signpost) {
if (signpost) {
return "#d6feff";
}
switch (level) {
case ERROR:
return "#ffcccc";
case FATAL:
return "#ff9999";
case WARNING:
return "#ffebcc";
default: // INFORMATION:
return "#ffffe6";
}
}
private String halfColorForLevel(IssueSeverity level, boolean signpost) {
if (signpost) {
return "#e3feff";
}
switch (level) {
case ERROR:
return "#ffeeee";
case FATAL:
return "#ffcccc";
case WARNING:
return "#fff4ee";
default: // INFORMATION:
return "#fffff2";
}
}
}

View File

@ -27,6 +27,7 @@ import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.ValidationEngine.ValidationRecord;
import org.hl7.fhir.validation.cli.model.*;
import org.hl7.fhir.validation.cli.utils.EngineMode;
import org.hl7.fhir.validation.cli.utils.VersionSourceInformation;
@ -69,7 +70,9 @@ public class ValidationService {
}
public static void validateSources(CliContext cliContext, ValidationEngine validator) throws Exception {
Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles());
long start = System.currentTimeMillis();
List<ValidationRecord> records = new ArrayList<>();
Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles(), records);
int ec = 0;
System.out.println("Done. "+validator.getContext().clock().report());
System.out.println();
@ -92,6 +95,11 @@ public class ValidationService {
x.compose(s, r);
s.close();
}
if (cliContext.getHtmlOutput() != null) {
String html = new HTMLOutputGenerator(records).generate(System.currentTimeMillis()-start);
TextFile.stringToFile(html, cliContext.getHtmlOutput());
System.out.println("HTML Summary in "+cliContext.getHtmlOutput());
}
System.exit(ec > 0 ? 1 : 0);
}
@ -288,10 +296,12 @@ public class ValidationService {
System.out.println("Scanning for versions (no -version parameter):");
VersionSourceInformation versions = ValidationService.scanForVersions(cliContext);
for (String s : versions.getReport()) {
System.out.println(" " + s);
if (!s.equals("(nothing found)")) {
System.out.println(" " + s);
}
}
if (versions.isEmpty()) {
System.out.println("-> Using Default version '" + VersionUtilities.CURRENT_VERSION + "'");
System.out.println(" No Version Info found: Using Default version '" + VersionUtilities.CURRENT_VERSION + "'");
return "current";
}
if (versions.size() == 1) {

View File

@ -12,6 +12,7 @@ public class Params {
public static final String VERSION = "-version";
public static final String OUTPUT = "-output";
public static final String HTML_OUTPUT = "-html-output";
public static final String PROXY = "-proxy";
public static final String PROFILE = "-profile";
public static final String BUNDLE = "-bundle";
@ -93,6 +94,11 @@ public class Params {
throw new Error("Specified -output without indicating output file");
else
cliContext.setOutput(args[++i]);
} else if (args[i].equals(HTML_OUTPUT)) {
if (i + 1 == args.length)
throw new Error("Specified -html-output without indicating output file");
else
cliContext.setHtmlOutput(args[++i]);
} else if (args[i].equals(PROXY)) {
i++; // ignore next parameter
} else if (args[i].equals(PROFILE)) {

View File

@ -961,7 +961,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else {
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, codings.size() == fixed.getCoding().size(), I18nConstants.TERMINOLOGY_TX_CODING_COUNT, Integer.toString(fixed.getCoding().size()), Integer.toString(codings.size()))) {
for (int i = 0; i < codings.size(); i++)
checkFixedValue(errors, path + ".coding", codings.get(i), fixed.getCoding().get(i), fixedSource, "coding", focus);
checkFixedValue(errors, path + ".coding", codings.get(i), fixed.getCoding().get(i), fixedSource, "coding", focus, false);
}
}
}
@ -1748,10 +1748,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return b.toString();
}
private void checkFixedValue(List<ValidationMessage> errors, String path, Element focus, org.hl7.fhir.r5.model.Element fixed, String fixedSource, String propName, Element parent) {
checkFixedValue(errors, path, focus, fixed, fixedSource, propName, parent, false);
}
@SuppressWarnings("rawtypes")
private void checkFixedValue(List<ValidationMessage> errors, String path, Element focus, org.hl7.fhir.r5.model.Element fixed, String fixedSource, String propName, Element parent, boolean pattern) {
if ((fixed == null || fixed.isEmpty()) && focus == null) {
@ -1829,7 +1825,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (Extension e : fixed.getExtension()) {
Element ex = getExtensionByUrl(extensions, e.getUrl());
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, ex != null, I18nConstants.EXTENSION_EXT_COUNT_NOTFOUND, e.getUrl())) {
checkFixedValue(errors, path, ex.getNamedChild("extension").getNamedChild("value"), e.getValue(), fixedSource, "extension.value", ex.getNamedChild("extension"));
checkFixedValue(errors, path, ex.getNamedChild("extension").getNamedChild("value"), e.getValue(), fixedSource, "extension.value", ex.getNamedChild("extension"), false);
}
}
}
@ -1842,25 +1838,33 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkFixedValue(errors, path + ".period", focus.getNamedChild("period"), fixed.getPeriod(), fixedSource, "period", focus, pattern);
List<Element> parts = new ArrayList<Element>();
focus.getNamedChildren("family", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() > 0 == fixed.hasFamily(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_FAMILY, (fixed.hasFamily() ? "1" : "0"), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".family", parts.get(i), fixed.getFamilyElement(), fixedSource, "family", focus, pattern);
if (!pattern || fixed.hasFamily()) {
focus.getNamedChildren("family", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() > 0 == fixed.hasFamily(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_FAMILY, (fixed.hasFamily() ? "1" : "0"), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".family", parts.get(i), fixed.getFamilyElement(), fixedSource, "family", focus, pattern);
}
}
focus.getNamedChildren("given", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getGiven().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_GIVEN, Integer.toString(fixed.getGiven().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".given", parts.get(i), fixed.getGiven().get(i), fixedSource, "given", focus, pattern);
if (!pattern || fixed.hasGiven()) {
focus.getNamedChildren("given", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getGiven().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_GIVEN, Integer.toString(fixed.getGiven().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".given", parts.get(i), fixed.getGiven().get(i), fixedSource, "given", focus, pattern);
}
}
focus.getNamedChildren("prefix", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getPrefix().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_PREFIX, Integer.toString(fixed.getPrefix().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".prefix", parts.get(i), fixed.getPrefix().get(i), fixedSource, "prefix", focus, pattern);
if (!pattern || fixed.hasPrefix()) {
focus.getNamedChildren("prefix", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getPrefix().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_PREFIX, Integer.toString(fixed.getPrefix().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".prefix", parts.get(i), fixed.getPrefix().get(i), fixedSource, "prefix", focus, pattern);
}
}
focus.getNamedChildren("suffix", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getSuffix().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_SUFFIX, Integer.toString(fixed.getSuffix().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".suffix", parts.get(i), fixed.getSuffix().get(i), fixedSource, "suffix", focus, pattern);
if (!pattern || fixed.hasSuffix()) {
focus.getNamedChildren("suffix", parts);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, parts.size() == fixed.getSuffix().size(), I18nConstants.FIXED_TYPE_CHECKS_DT_NAME_SUFFIX, Integer.toString(fixed.getSuffix().size()), Integer.toString(parts.size()))) {
for (int i = 0; i < parts.size(); i++)
checkFixedValue(errors, path + ".suffix", parts.get(i), fixed.getSuffix().get(i), fixedSource, "suffix", focus, pattern);
}
}
}
@ -3054,9 +3058,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// work back through the parent list.
// really, there should only be one level for this (contained resources cannot contain
// contained resources), but we'll leave that to some other code to worry about
boolean wasContained = false;
while (stack != null && stack.getElement() != null) {
if (stack.getElement().getProperty().isResource()) {
// ok, we'll try to find the contained reference
if (ref.equals("#") && stack.getElement().getSpecial() != SpecialElement.CONTAINED && wasContained) {
ResolvedReference rr = new ResolvedReference();
rr.setResource(stack.getElement());
rr.setFocus(stack.getElement());
rr.setExternal(false);
rr.setStack(stack.push(stack.getElement(), -1, stack.getElement().getProperty().getDefinition(), stack.getElement().getProperty().getDefinition()));
rr.getStack().qualifyPath(".ofType("+stack.getElement().fhirType()+")");
return rr;
}
if (stack.getElement().getSpecial() == SpecialElement.CONTAINED) {
wasContained = true;
}
IndexedElement res = getContainedById(stack.getElement(), ref.substring(1));
if (res != null) {
ResolvedReference rr = new ResolvedReference();
@ -4069,8 +4086,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// check type invariants
checkInvariants(hostContext, errors, profile, definition, resource, element, stack, false);
if (definition.getFixed() != null)
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getUrl(), definition.getSliceName(), null);
if (definition.getFixed() != null) {
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getUrl(), definition.getSliceName(), null, false);
}
if (definition.getPattern() != null) {
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getPattern(), profile.getUrl(), definition.getSliceName(), null, true);
}
// get the list of direct defined children, including slices
List<ElementDefinition> childDefinitions = profileUtilities.getChildMap(profile, definition);
@ -4136,13 +4157,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl)
throws FHIRException, DefinitionException {
if (debug && ei.definition != null && ei.slice != null) {
System.out.println(Utilities.padLeft("", ' ', stack.depth())+ "Check "+ei.getPath()+" against both "+ei.definition.getId()+" and "+ei.slice.getId());
}
if (ei.definition != null) {
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei,
extensionUrl, ei.definition, false);
if (debug) {
System.out.println(Utilities.padLeft("", ' ', stack.depth())+ "Check "+ei.getPath()+" against defn "+ei.definition.getId());
}
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei, extensionUrl, ei.definition, false);
}
if (ei.slice != null) {
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei,
extensionUrl, ei.slice, true);
if (debug) {
System.out.println(Utilities.padLeft("", ' ', stack.depth())+ "Check "+ei.getPath()+" against slice "+ei.slice.getId());
}
checkChildByDefinition(hostContext, errors, profile, definition, resource, element, actualType, stack, inCodeableConcept, checkDisplayInContext, ei, extensionUrl, ei.slice, true);
}
}
@ -4186,11 +4214,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (checkDefn.getType().size() > 1) {
String prefix = tail(checkDefn.getPath());
assert typesAreAllReference(checkDefn.getType()) || checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR) || prefix.endsWith("[x]") : prefix;
assert typesAreAllReference(checkDefn.getType()) || checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR) || prefix.endsWith("[x]") || isResourceAndTypes(checkDefn) : "Multiple Types allowed, but name is wrong @ "+checkDefn.getPath()+": "+checkDefn.typeSummaryVB();
if (checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR))
if (checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR)) {
type = ei.getElement().getType();
else {
} else if (ei.getElement().isResource()) {
type = ei.getElement().fhirType();
} else {
prefix = prefix.substring(0, prefix.length() - 3);
for (TypeRefComponent t : checkDefn.getType())
if ((prefix + Utilities.capitalize(t.getWorkingCode())).equals(ei.getName())) {
@ -4251,7 +4281,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkPrimitive(hostContext, errors, ei.getPath(), type, checkDefn, ei.getElement(), profile, stack);
} else {
if (checkDefn.hasFixed()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getUrl(), checkDefn.getSliceName(), null);
checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getUrl(), checkDefn.getSliceName(), null, false);
}
if (checkDefn.hasPattern()) {
checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getPattern(), profile.getUrl(), checkDefn.getSliceName(), null, true);
@ -4386,6 +4416,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
private boolean isResourceAndTypes(ElementDefinition ed) {
if (!Utilities.existsInList(ed.getBase().getPath(), "Bundle.entry.resource", "Bundle.entry.response.outcome", "DomainResource.contained", "Parameters.parameter.resource", "Parameters.parameter.part.resource")) {
return false;
}
for (TypeRefComponent tr : ed.getType()) {
if (!isResource(tr.getCode())) {
return false;
}
}
return true;
}
private boolean isResource(String type) {
StructureDefinition sd = context.fetchTypeDefinition(type);
return sd != null && sd.getKind().equals(StructureDefinitionKind.RESOURCE);
@ -4476,18 +4518,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
}
String location = "Profile " + profile.getUrl() + ", Element '" + stack.getLiteralPath() + "." + tail(ed.getPath()) + (ed.hasSliceName() ? "[" + ed.getSliceName() + (ed.hasLabel() ? " (" + ed.getLabel() + ")" : "") + "]" : "") + "'";
if (ed.getMin() > 0) {
if (problematicPaths.contains(ed.getPath()))
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_NOCHECKMIN, location, Integer.toString(ed.getMin()));
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_NOCHECKMIN, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), Integer.toString(ed.getMin()));
else
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_MINIMUM, location, Integer.toString(ed.getMin()), Integer.toString(count));
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_MINIMUM, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), Integer.toString(ed.getMin()), Integer.toString(count));
}
if (ed.hasMax() && !ed.getMax().equals("*")) {
if (problematicPaths.contains(ed.getPath()))
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), I18nConstants.VALIDATION_VAL_PROFILE_NOCHECKMAX, location, ed.getMax());
else
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), I18nConstants.VALIDATION_VAL_PROFILE_MAXIMUM, location, ed.getMax(), Integer.toString(count));
hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count <= Integer.parseInt(ed.getMax()), I18nConstants.VALIDATION_VAL_PROFILE_NOCHECKMAX, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), ed.getMax());
else if (count > Integer.parseInt(ed.getMax())) {
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_MAXIMUM, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), ed.getMax(), Integer.toString(count));
}
}
}
}
@ -4863,7 +4905,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean valueMatchesCriteria(Element value, ElementDefinition criteria, StructureDefinition profile) throws FHIRException {
if (criteria.hasFixed()) {
List<ValidationMessage> msgs = new ArrayList<ValidationMessage>();
checkFixedValue(msgs, "{virtual}", value, criteria.getFixed(), profile.getUrl(), "value", null);
checkFixedValue(msgs, "{virtual}", value, criteria.getFixed(), profile.getUrl(), "value", null, false);
return msgs.size() == 0;
} else if (criteria.hasBinding() && criteria.getBinding().getStrength() == BindingStrength.REQUIRED && criteria.getBinding().hasValueSet()) {
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SLICE_MATCHING__SLICE_MATCHING_BY_VALUE_SET_NOT_DONE));
@ -4983,6 +5025,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if ("(component.empty() and related.empty()) implies (dataAbsentReason or value)".equals(expr))
return "(component.empty() and related.empty()) implies (dataAbsentReason.exists() or value.exists())";
if ("reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids'))".equals(expr)) {
return "(reference = '#') or reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids'))";
}
if ("reference.startsWith('#').not() or (reference.substring(1).trace('url') in %resource.contained.id.trace('ids'))".equals(expr)) {
return "(reference = '#') or reference.startsWith('#').not() or (reference.substring(1).trace('url') in %resource.contained.id.trace('ids'))";
}
if ("".equals(expr))
return "";
return expr;

View File

@ -165,11 +165,25 @@ public class StructureDefinitionValidator extends BaseValidator {
if (t == null) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p);
} else {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), code.equals(t), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code);
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code);
}
}
}
private boolean isInstanceOf(String t, String code) {
StructureDefinition sd = context.fetchTypeDefinition(t);
while (sd != null) {
if (sd.getType().equals(code)) {
return true;
}
sd = sd.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()) : null;
if (sd != null && !sd.getAbstract()) {
sd = null;
}
}
return false;
}
private String determineBaseType(StructureDefinition sd) {
while (sd != null && !sd.hasType() && sd.getDerivation() == TypeDerivationRule.CONSTRAINT) {
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());

View File

@ -187,5 +187,13 @@ public class NodeStack {
return literalPath;
}
public int depth() {
if (parent == null) {
return 0;
} else {
return parent.depth()+1;
}
}
}

View File

@ -90,7 +90,7 @@ public class ValidationEngineTests {
}
if (!org.hl7.fhir.validation.tests.utilities.TestUtilities.silent)
System.out.println("Test102: Validate patient-example.xml in v1.0.2 version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "41.0.2");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2");
ve.setNoInvariantChecks(true);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient102.xml"), null);
if (!TestUtilities.silent)

11
pom.xml
View File

@ -14,12 +14,12 @@
HAPI FHIR.
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.18-SNAPSHOT</version>
<version>5.1.21-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<hapi_fhir_version>5.1.0</hapi_fhir_version>
<validator_test_case_version>1.1.46</validator_test_case_version>
<validator_test_case_version>1.1.48-SNAPSHOT</validator_test_case_version>
<junit_jupiter_version>5.6.2</junit_jupiter_version>
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
<jacoco_version>0.8.5</jacoco_version>
@ -62,6 +62,13 @@
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>github-releases</id>
<url>https://maven.pkg.github.com/FHIR/fhir-test-cases/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>