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) {
for (ElementDefinition ed : elements) {
if (("#"+ed.getPath()).equals(contentReference)) {
return ed;
}
if (("#"+ed.getId()).equals(contentReference)) {
return ed;
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();
}
}
throw new Error("getElementByName: can't find "+contentReference+"in "+elements.toString());
for (ElementDefinition ed : elements) {
if (("#"+ed.getPath()).equals(contentReference)) {
return new ElementInStructure(source, ed);
}
if (("#"+ed.getId()).equals(contentReference)) {
return new ElementInStructure(source, ed);
}
}
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

@ -31,14 +31,12 @@ package org.hl7.fhir.r5.model;
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

@ -79,4 +79,9 @@ public class MarkDownProcessor {
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
* 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>
*
* so if a feature is defined in 4.0, if (VersionUtilities.isThisOrLater("4.0", version))...
*
* @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>