Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core into main_convertor_files
This commit is contained in:
commit
a4a6f852bd
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -152,8 +152,32 @@ public class VersionConvertor_30_50 {
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.r5.model.CodeType convertStringToCode(org.hl7.fhir.dstu3.model.StringType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.r5.model.CodeType tgt = new org.hl7.fhir.r5.model.CodeType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.dstu3.model.StringType convertCodeToString(org.hl7.fhir.r5.model.CodeType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.dstu3.model.StringType tgt = new org.hl7.fhir.dstu3.model.StringType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.dstu3.model.CodeType convertStringToCode(org.hl7.fhir.r5.model.StringType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.dstu3.model.CodeType tgt = new org.hl7.fhir.dstu3.model.CodeType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.r5.model.StringType convertCodeToString(org.hl7.fhir.dstu3.model.CodeType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.r5.model.StringType tgt = new org.hl7.fhir.r5.model.StringType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
public static org.hl7.fhir.r5.model.DateType convertDate(org.hl7.fhir.dstu3.model.DateType src) throws FHIRException {
|
public static org.hl7.fhir.r5.model.DateType convertDate(org.hl7.fhir.dstu3.model.DateType src) throws FHIRException {
|
||||||
org.hl7.fhir.r5.model.DateType tgt = new org.hl7.fhir.r5.model.DateType(src.getValueAsString());
|
org.hl7.fhir.r5.model.DateType tgt = new org.hl7.fhir.r5.model.DateType(src.getValueAsString());
|
||||||
copyElement(src, tgt);
|
copyElement(src, tgt);
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
@ -290,6 +314,18 @@ public class VersionConvertor_30_50 {
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.r5.model.MarkdownType convertStringToMarkdown(org.hl7.fhir.dstu3.model.StringType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.r5.model.MarkdownType tgt = new org.hl7.fhir.r5.model.MarkdownType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.dstu3.model.StringType convertMarkdownToString(org.hl7.fhir.r5.model.MarkdownType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.dstu3.model.StringType tgt = new org.hl7.fhir.dstu3.model.StringType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
public static org.hl7.fhir.r5.model.TimeType convertTime(org.hl7.fhir.dstu3.model.TimeType src) throws FHIRException {
|
public static org.hl7.fhir.r5.model.TimeType convertTime(org.hl7.fhir.dstu3.model.TimeType src) throws FHIRException {
|
||||||
org.hl7.fhir.r5.model.TimeType tgt = new org.hl7.fhir.r5.model.TimeType(src.getValue());
|
org.hl7.fhir.r5.model.TimeType tgt = new org.hl7.fhir.r5.model.TimeType(src.getValue());
|
||||||
copyElement(src, tgt);
|
copyElement(src, tgt);
|
||||||
|
@ -326,6 +362,18 @@ public class VersionConvertor_30_50 {
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.r5.model.UriType convertCodeToUri(org.hl7.fhir.dstu3.model.CodeType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.r5.model.UriType tgt = new org.hl7.fhir.r5.model.UriType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.hl7.fhir.dstu3.model.CodeType convertUriToCode(org.hl7.fhir.r5.model.UriType src) throws FHIRException {
|
||||||
|
org.hl7.fhir.dstu3.model.CodeType tgt = new org.hl7.fhir.dstu3.model.CodeType(src.getValue());
|
||||||
|
copyElement(src, tgt);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
|
|
||||||
public static org.hl7.fhir.r5.model.UuidType convertUuid(org.hl7.fhir.dstu3.model.UuidType src) throws FHIRException {
|
public static org.hl7.fhir.r5.model.UuidType convertUuid(org.hl7.fhir.dstu3.model.UuidType src) throws FHIRException {
|
||||||
org.hl7.fhir.r5.model.UuidType tgt = new org.hl7.fhir.r5.model.UuidType(src.getValue());
|
org.hl7.fhir.r5.model.UuidType tgt = new org.hl7.fhir.r5.model.UuidType(src.getValue());
|
||||||
copyElement(src, tgt);
|
copyElement(src, tgt);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class OperationDefinition30_50 {
|
||||||
if (src.hasCodeElement())
|
if (src.hasCodeElement())
|
||||||
tgt.setCodeElement((org.hl7.fhir.r5.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement()));
|
tgt.setCodeElement((org.hl7.fhir.r5.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement()));
|
||||||
if (src.hasCommentElement())
|
if (src.hasCommentElement())
|
||||||
tgt.setCommentElement((org.hl7.fhir.r5.model.MarkdownType) VersionConvertor_30_50.convertType(src.getCommentElement()));
|
tgt.setCommentElement(VersionConvertor_30_50.convertStringToMarkdown(src.getCommentElement()));
|
||||||
if (src.hasBase())
|
if (src.hasBase())
|
||||||
tgt.setBaseElement(VersionConvertor_30_50.convertReferenceToCanonical(src.getBase()));
|
tgt.setBaseElement(VersionConvertor_30_50.convertReferenceToCanonical(src.getBase()));
|
||||||
if (src.hasResource()) {
|
if (src.hasResource()) {
|
||||||
|
@ -109,7 +109,7 @@ public class OperationDefinition30_50 {
|
||||||
if (src.hasCodeElement())
|
if (src.hasCodeElement())
|
||||||
tgt.setCodeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement()));
|
tgt.setCodeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getCodeElement()));
|
||||||
if (src.hasCommentElement())
|
if (src.hasCommentElement())
|
||||||
tgt.setCommentElement((org.hl7.fhir.dstu3.model.StringType) VersionConvertor_30_50.convertType(src.getCommentElement()));
|
tgt.setCommentElement(VersionConvertor_30_50.convertMarkdownToString(src.getCommentElement()));
|
||||||
if (src.hasBase())
|
if (src.hasBase())
|
||||||
tgt.setBase(VersionConvertor_30_50.convertCanonicalToReference(src.getBaseElement()));
|
tgt.setBase(VersionConvertor_30_50.convertCanonicalToReference(src.getBaseElement()));
|
||||||
if (src.hasResource()) {
|
if (src.hasResource()) {
|
||||||
|
|
|
@ -175,8 +175,9 @@ public class StructureDefinition30_50 {
|
||||||
if (src.hasAbstractElement())
|
if (src.hasAbstractElement())
|
||||||
tgt.setAbstractElement((org.hl7.fhir.dstu3.model.BooleanType) VersionConvertor_30_50.convertType(src.getAbstractElement()));
|
tgt.setAbstractElement((org.hl7.fhir.dstu3.model.BooleanType) VersionConvertor_30_50.convertType(src.getAbstractElement()));
|
||||||
for (org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionContextComponent t : src.getContext()) {
|
for (org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionContextComponent t : src.getContext()) {
|
||||||
if (!tgt.hasContextType())
|
if (!tgt.hasContextType()) {
|
||||||
tgt.setTypeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getTypeElement()));
|
tgt.setTypeElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertUriToCode(src.getTypeElement()));
|
||||||
|
}
|
||||||
tgt.addContext("Element".equals(t.getExpression()) ? "*" : t.getExpression());
|
tgt.addContext("Element".equals(t.getExpression()) ? "*" : t.getExpression());
|
||||||
}
|
}
|
||||||
if (src.hasContextInvariant()) {
|
if (src.hasContextInvariant()) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class ValueSet30_50 {
|
||||||
if (src.hasOp())
|
if (src.hasOp())
|
||||||
tgt.setOp(convertFilterOperator2(src.getOp()));
|
tgt.setOp(convertFilterOperator2(src.getOp()));
|
||||||
if (src.hasValueElement())
|
if (src.hasValueElement())
|
||||||
tgt.setValueElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertType(src.getValueElement()));
|
tgt.setValueElement((org.hl7.fhir.dstu3.model.CodeType) VersionConvertor_30_50.convertStringToCode(src.getValueElement()));
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ public class ValueSet30_50 {
|
||||||
if (src.hasOp())
|
if (src.hasOp())
|
||||||
tgt.setOp(VersionConvertor_30_50.convertFilterOperator(src.getOp()));
|
tgt.setOp(VersionConvertor_30_50.convertFilterOperator(src.getOp()));
|
||||||
if (src.hasValueElement())
|
if (src.hasValueElement())
|
||||||
tgt.setValueElement((org.hl7.fhir.r5.model.StringType) VersionConvertor_30_50.convertType(src.getValueElement()));
|
tgt.setValueElement((org.hl7.fhir.r5.model.StringType) VersionConvertor_30_50.convertCodeToString(src.getValueElement()));
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
* <code>null</code> if none
|
* <code>null</code> if none
|
||||||
*/
|
*/
|
||||||
public Coding getSecurity(String theSystem, String theCode) {
|
public Coding getSecurity(String theSystem, String theCode) {
|
||||||
for (Coding next : getTag()) {
|
for (Coding next : getSecurity()) {
|
||||||
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ public class Meta extends Type implements IBaseMetaType {
|
||||||
* <code>null</code> if none
|
* <code>null</code> if none
|
||||||
*/
|
*/
|
||||||
public Coding getSecurity(String theSystem, String theCode) {
|
public Coding getSecurity(String theSystem, String theCode) {
|
||||||
for (Coding next : getTag()) {
|
for (Coding next : getSecurity()) {
|
||||||
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.hl7.fhir.dstu2.test;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu2.model.Coding;
|
||||||
|
import org.hl7.fhir.dstu2.model.Meta;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class MetaTest {
|
||||||
|
public static String TEST_SYSTEM = "TEST_SYSTEM";
|
||||||
|
public static String TEST_CODE = "TEST_CODE";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaSecurity() {
|
||||||
|
Meta meta = new Meta();
|
||||||
|
Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE);
|
||||||
|
assertTrue(meta.hasSecurity());
|
||||||
|
assertNotNull(meta.getSecurity());
|
||||||
|
assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(1, meta.getSecurity().size());
|
||||||
|
assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -421,7 +421,7 @@ public class Meta extends Type implements IBaseMetaType {
|
||||||
* <code>null</code> if none
|
* <code>null</code> if none
|
||||||
*/
|
*/
|
||||||
public Coding getSecurity(String theSystem, String theCode) {
|
public Coding getSecurity(String theSystem, String theCode) {
|
||||||
for (Coding next : getTag()) {
|
for (Coding next : getSecurity()) {
|
||||||
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.hl7.fhir.dstu3.test;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.Coding;
|
||||||
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class MetaTest {
|
||||||
|
public static String TEST_SYSTEM = "TEST_SYSTEM";
|
||||||
|
public static String TEST_CODE = "TEST_CODE";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaSecurity() {
|
||||||
|
Meta meta = new Meta();
|
||||||
|
Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE);
|
||||||
|
assertTrue(meta.hasSecurity());
|
||||||
|
assertNotNull(meta.getSecurity());
|
||||||
|
assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(1, meta.getSecurity().size());
|
||||||
|
assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ public class Meta extends Type implements IBaseMetaType {
|
||||||
* <code>null</code> if none
|
* <code>null</code> if none
|
||||||
*/
|
*/
|
||||||
public Coding getSecurity(String theSystem, String theCode) {
|
public Coding getSecurity(String theSystem, String theCode) {
|
||||||
for (Coding next : getTag()) {
|
for (Coding next : getSecurity()) {
|
||||||
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.hl7.fhir.r4.test;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
|
import org.hl7.fhir.r4.model.Meta;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class MetaTest {
|
||||||
|
public static String TEST_SYSTEM = "TEST_SYSTEM";
|
||||||
|
public static String TEST_CODE = "TEST_CODE";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaSecurity() {
|
||||||
|
Meta meta = new Meta();
|
||||||
|
Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE);
|
||||||
|
assertTrue(meta.hasSecurity());
|
||||||
|
assertNotNull(meta.getSecurity());
|
||||||
|
assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(1, meta.getSecurity().size());
|
||||||
|
assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (derived == null) {
|
if (derived == null) {
|
||||||
throw new DefinitionException("no derived structure provided");
|
throw new DefinitionException("no derived structure provided");
|
||||||
}
|
}
|
||||||
|
checkNotGenerating(base, "Base for generating a snapshot for the profile "+derived.getUrl());
|
||||||
|
checkNotGenerating(derived, "Focus for generating a snapshot");
|
||||||
|
derived.setUserData("profileutils.snapshot.generating", true);
|
||||||
|
|
||||||
if (!base.hasType()) {
|
if (!base.hasType()) {
|
||||||
throw new DefinitionException("Base profile "+base.getUrl()+" has no type");
|
throw new DefinitionException("Base profile "+base.getUrl()+" has no type");
|
||||||
|
@ -622,6 +625,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
derived.setSnapshot(null);
|
derived.setSnapshot(null);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
derived.clearUserData("profileutils.snapshot.generating");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDifferential(List<ElementDefinition> elements, String type, String url) {
|
private void checkDifferential(List<ElementDefinition> elements, String type, String url) {
|
||||||
|
@ -853,10 +857,12 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue());
|
||||||
if (sd != null) {
|
if (sd != null) {
|
||||||
|
checkNotGenerating(sd, "an extension definition");
|
||||||
if (!sd.hasSnapshot()) {
|
if (!sd.hasSnapshot()) {
|
||||||
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||||
if (sdb == null)
|
if (sdb == null)
|
||||||
throw new DefinitionException("Unable to find base "+sd.getBaseDefinition()+" for "+sd.getUrl());
|
throw new DefinitionException("Unable to find base "+sd.getBaseDefinition()+" for "+sd.getUrl());
|
||||||
|
checkNotGenerating(sdb, "an extension base");
|
||||||
generateSnapshot(sdb, sd, sd.getUrl(), (sdb.hasUserData("path")) ? Utilities.extractBaseUrl(sdb.getUserString("path")) : webUrl, sd.getName());
|
generateSnapshot(sdb, sd, sd.getUrl(), (sdb.hasUserData("path")) ? Utilities.extractBaseUrl(sdb.getUserString("path")) : webUrl, sd.getName());
|
||||||
}
|
}
|
||||||
ElementDefinition src;
|
ElementDefinition src;
|
||||||
|
@ -905,7 +911,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
result.getElement().add(outcome);
|
result.getElement().add(outcome);
|
||||||
baseCursor++;
|
baseCursor++;
|
||||||
diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1;
|
diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1;
|
||||||
if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it
|
if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || isBaseResource(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it
|
||||||
if (pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".") && !baseWalksInto(base.getElement(), baseCursor)) {
|
if (pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".") && !baseWalksInto(base.getElement(), baseCursor)) {
|
||||||
if (outcome.getType().size() > 1) {
|
if (outcome.getType().size() > 1) {
|
||||||
if (outcome.getPath().endsWith("[x]") && !diffMatches.get(0).getPath().endsWith("[x]")) {
|
if (outcome.getPath().endsWith("[x]") && !diffMatches.get(0).getPath().endsWith("[x]")) {
|
||||||
|
@ -1424,7 +1430,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
outcome.setSlicing(null);
|
outcome.setSlicing(null);
|
||||||
if (!outcome.getPath().startsWith(resultPathBase))
|
if (!outcome.getPath().startsWith(resultPathBase))
|
||||||
throw new DefinitionException("Adding wrong path");
|
throw new DefinitionException("Adding wrong path");
|
||||||
if (diffpos < diffMatches.size() && diffMatches.get(diffpos).getSliceName().equals(outcome.getSliceName())) {
|
if (diffpos < diffMatches.size() && diffMatches.get(diffpos).hasSliceName() && diffMatches.get(diffpos).getSliceName().equals(outcome.getSliceName())) {
|
||||||
// if there's a diff, we update the outcome with diff
|
// if there's a diff, we update the outcome with diff
|
||||||
// no? updateFromDefinition(outcome, diffMatches.get(diffpos), profileName, closed, url);
|
// no? updateFromDefinition(outcome, diffMatches.get(diffpos), profileName, closed, url);
|
||||||
//then process any children
|
//then process any children
|
||||||
|
@ -1540,6 +1546,24 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void checkNotGenerating(StructureDefinition sd, String role) {
|
||||||
|
if (sd.hasUserData("profileutils.snapshot.generating")) {
|
||||||
|
throw new FHIRException("Attempt to use a snapshot on profile '"+sd.getUrl()+"' as "+role+" before it is generated");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBaseResource(List<TypeRefComponent> types) {
|
||||||
|
if (types.isEmpty())
|
||||||
|
return false;
|
||||||
|
for (TypeRefComponent type : types) {
|
||||||
|
String t = type.getWorkingCode();
|
||||||
|
if ("Resource".equals(t))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String determineFixedType(List<ElementDefinition> diffMatches, String fixedType, int i) {
|
public String determineFixedType(List<ElementDefinition> diffMatches, String fixedType, int i) {
|
||||||
if (diffMatches.get(i).getType().size() == 0 && diffMatches.get(i).hasSliceName()) {
|
if (diffMatches.get(i).getType().size() == 0 && diffMatches.get(i).hasSliceName()) {
|
||||||
String n = tail(diffMatches.get(i).getPath()).replace("[x]", "");
|
String n = tail(diffMatches.get(i).getPath()).replace("[x]", "");
|
||||||
|
@ -2441,62 +2465,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
|
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
|
||||||
if (base.hasType()) {
|
if (base.hasType()) {
|
||||||
for (TypeRefComponent ts : derived.getType()) {
|
for (TypeRefComponent ts : derived.getType()) {
|
||||||
boolean ok = false;
|
checkTypeDerivation(purl, srcSD, base, derived, ts);
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
|
||||||
String t = ts.getWorkingCode();
|
|
||||||
for (TypeRefComponent td : base.getType()) {;
|
|
||||||
String tt = td.getWorkingCode();
|
|
||||||
b.append(tt);
|
|
||||||
if (td.hasCode() && (tt.equals(t))) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
StructureDefinition sdt = context.fetchTypeDefinition(tt);
|
|
||||||
if (sdt != null && sdt.getAbstract()) {
|
|
||||||
StructureDefinition sdb = context.fetchTypeDefinition(t);
|
|
||||||
while (sdb != null && !ok) {
|
|
||||||
ok = sdb.getType().equals(sdt.getUrl());
|
|
||||||
sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// work around for old badly generated SDs
|
|
||||||
if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (ok && ts.hasTargetProfile()) {
|
|
||||||
// check that any derived target has a reference chain back to one of the base target profiles
|
|
||||||
for (UriType u : ts.getTargetProfile()) {
|
|
||||||
String url = u.getValue();
|
|
||||||
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
|
|
||||||
while (url != null && !tgtOk) {
|
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
|
||||||
if (sd == null) {
|
|
||||||
if (messages != null) {
|
|
||||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
|
||||||
}
|
|
||||||
url = null;
|
|
||||||
tgtOk = true; // suppress error message
|
|
||||||
} else {
|
|
||||||
url = sd.getBaseDefinition();
|
|
||||||
tgtOk = td.hasTargetProfile(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tgtOk) {
|
|
||||||
if (messages == null) {
|
|
||||||
throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")");
|
|
||||||
} else {
|
|
||||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.getType().clear();
|
base.getType().clear();
|
||||||
|
@ -2576,6 +2545,66 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkTypeDerivation(String purl, StructureDefinition srcSD, ElementDefinition base, ElementDefinition derived, TypeRefComponent ts) {
|
||||||
|
boolean ok = false;
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
String t = ts.getWorkingCode();
|
||||||
|
for (TypeRefComponent td : base.getType()) {;
|
||||||
|
String tt = td.getWorkingCode();
|
||||||
|
b.append(tt);
|
||||||
|
if (td.hasCode() && (tt.equals(t))) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
StructureDefinition sdt = context.fetchTypeDefinition(tt);
|
||||||
|
if (sdt != null && sdt.getAbstract()) {
|
||||||
|
StructureDefinition sdb = context.fetchTypeDefinition(t);
|
||||||
|
while (sdb != null && !ok) {
|
||||||
|
ok = sdb.getType().equals(sdt.getType());
|
||||||
|
sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// work around for old badly generated SDs
|
||||||
|
if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (ok && ts.hasTargetProfile()) {
|
||||||
|
// check that any derived target has a reference chain back to one of the base target profiles
|
||||||
|
for (UriType u : ts.getTargetProfile()) {
|
||||||
|
String url = u.getValue();
|
||||||
|
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
|
||||||
|
while (url != null && !tgtOk) {
|
||||||
|
StructureDefinition sd = context.fetchRawProfile(url);
|
||||||
|
if (sd == null) {
|
||||||
|
if (messages != null) {
|
||||||
|
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
||||||
|
}
|
||||||
|
url = null;
|
||||||
|
tgtOk = true; // suppress error message
|
||||||
|
} else {
|
||||||
|
url = sd.getBaseDefinition();
|
||||||
|
tgtOk = td.hasTargetProfile(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tgtOk) {
|
||||||
|
if (messages == null) {
|
||||||
|
throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")");
|
||||||
|
} else {
|
||||||
|
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void checkTypeOk(ElementDefinition dest, String ft) {
|
public void checkTypeOk(ElementDefinition dest, String ft) {
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
|
@ -4354,13 +4383,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
@Override
|
@Override
|
||||||
public int compare(ElementDefinitionHolder o1, ElementDefinitionHolder o2) {
|
public int compare(ElementDefinitionHolder o1, ElementDefinitionHolder o2) {
|
||||||
if (o1.getBaseIndex() == 0)
|
if (o1.getBaseIndex() == 0)
|
||||||
o1.setBaseIndex(find(o1.getSelf().getPath()));
|
o1.setBaseIndex(find(o1.getSelf().getPath(), true));
|
||||||
if (o2.getBaseIndex() == 0)
|
if (o2.getBaseIndex() == 0)
|
||||||
o2.setBaseIndex(find(o2.getSelf().getPath()));
|
o2.setBaseIndex(find(o2.getSelf().getPath(), true));
|
||||||
return o1.getBaseIndex() - o2.getBaseIndex();
|
return o1.getBaseIndex() - o2.getBaseIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int find(String path) {
|
private int find(String path, boolean mandatory) {
|
||||||
String op = path;
|
String op = path;
|
||||||
int lc = 0;
|
int lc = 0;
|
||||||
String actual = base+path.substring(prefixLength);
|
String actual = base+path.substring(prefixLength);
|
||||||
|
@ -4392,10 +4421,12 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
throw new Error("Internal recursion detection: find() loop path recursion > "+MAX_RECURSION_LIMIT+" - check paths are valid (for path "+path+"/"+op+")");
|
throw new Error("Internal recursion detection: find() loop path recursion > "+MAX_RECURSION_LIMIT+" - check paths are valid (for path "+path+"/"+op+")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prefixLength == 0)
|
if (mandatory) {
|
||||||
errors.add("Differential contains path "+path+" which is not found in the base");
|
if (prefixLength == 0)
|
||||||
else
|
errors.add("Differential contains path "+path+" which is not found in the base");
|
||||||
errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the base");
|
else
|
||||||
|
errors.add("Differential contains path "+path+" which is actually "+actual+", which is not found in the base");
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4508,7 +4539,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private void sortElements(ElementDefinitionHolder edh, ElementDefinitionComparer cmp, List<String> errors) throws FHIRException {
|
private void sortElements(ElementDefinitionHolder edh, ElementDefinitionComparer cmp, List<String> errors) throws FHIRException {
|
||||||
if (edh.getChildren().size() == 1)
|
if (edh.getChildren().size() == 1)
|
||||||
// special case - sort needsto allocate base numbers, but there'll be no sort if there's only 1 child. So in that case, we just go ahead and allocated base number directly
|
// special case - sort needsto allocate base numbers, but there'll be no sort if there's only 1 child. So in that case, we just go ahead and allocated base number directly
|
||||||
edh.getChildren().get(0).baseIndex = cmp.find(edh.getChildren().get(0).getSelf().getPath());
|
edh.getChildren().get(0).baseIndex = cmp.find(edh.getChildren().get(0).getSelf().getPath(), false);
|
||||||
else
|
else
|
||||||
Collections.sort(edh.getChildren(), cmp);
|
Collections.sort(edh.getChildren(), cmp);
|
||||||
cmp.checkForErrors(errors);
|
cmp.checkForErrors(errors);
|
||||||
|
@ -4516,8 +4547,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
for (ElementDefinitionHolder child : edh.getChildren()) {
|
for (ElementDefinitionHolder child : edh.getChildren()) {
|
||||||
if (child.getChildren().size() > 0) {
|
if (child.getChildren().size() > 0) {
|
||||||
ElementDefinitionComparer ccmp = getComparer(cmp, child);
|
ElementDefinitionComparer ccmp = getComparer(cmp, child);
|
||||||
if (ccmp != null)
|
if (ccmp != null) {
|
||||||
sortElements(child, ccmp, errors);
|
sortElements(child, ccmp, errors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4528,7 +4560,22 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
ElementDefinition ed = cmp.snapshot.get(child.getBaseIndex());
|
ElementDefinition ed = cmp.snapshot.get(child.getBaseIndex());
|
||||||
ElementDefinitionComparer ccmp;
|
ElementDefinitionComparer ccmp;
|
||||||
if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) {
|
if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) {
|
||||||
ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name);
|
if (ed.hasType() && "Resource".equals(ed.getType().get(0).getWorkingCode()) && child.getSelf().getType().get(0).hasProfile()) {
|
||||||
|
if (child.getSelf().getType().get(0).getProfile().size() > 1) {
|
||||||
|
throw new FHIRException("Unhandled situation: resource is profiled to more than one option - cannot sort profile");
|
||||||
|
}
|
||||||
|
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
||||||
|
while (profile != null && profile.getDerivation() == TypeDerivationRule.CONSTRAINT) {
|
||||||
|
profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition());
|
||||||
|
}
|
||||||
|
if (profile==null) {
|
||||||
|
ccmp = null; // this might happen before everything is loaded. And we don't so much care about sot order in this case
|
||||||
|
} else {
|
||||||
|
ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), profile.getType(), child.getSelf().getPath().length(), cmp.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name);
|
||||||
|
}
|
||||||
} else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) {
|
} else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) {
|
||||||
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
||||||
if (profile==null)
|
if (profile==null)
|
||||||
|
@ -5264,14 +5311,18 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private String getCardinality(ElementDefinition ed, List<ElementDefinition> list) {
|
private String getCardinality(ElementDefinition ed, List<ElementDefinition> list) {
|
||||||
int min = ed.getMin();
|
int min = ed.getMin();
|
||||||
int max = !ed.hasMax() || ed.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(ed.getMax());
|
int max = !ed.hasMax() || ed.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(ed.getMax());
|
||||||
while (ed != null && ed.getPath().contains(".")) {
|
ElementDefinition ned = ed;
|
||||||
ed = findParent(ed, list);
|
while (ned != null && ned.getPath().contains(".")) {
|
||||||
if (ed.getMax().equals("0"))
|
ned = findParent(ned, list);
|
||||||
max = 0;
|
if (ned != null) { // todo: this can happen if we've walked into a resoruce. Not sure what to about that?
|
||||||
else if (!ed.getMax().equals("1") && !ed.hasSlicing())
|
if ("0".equals(ned.getMax()))
|
||||||
max = Integer.MAX_VALUE;
|
max = 0;
|
||||||
if (ed.getMin() == 0)
|
else if (!ned.getMax().equals("1") && !ned.hasSlicing())
|
||||||
min = 0;
|
max = Integer.MAX_VALUE;
|
||||||
|
if (ned.getMin() == 0) {
|
||||||
|
min = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Integer.toString(min)+".."+(max == Integer.MAX_VALUE ? "*" : Integer.toString(max));
|
return Integer.toString(min)+".."+(max == Integer.MAX_VALUE ? "*" : Integer.toString(max));
|
||||||
}
|
}
|
||||||
|
|
|
@ -539,6 +539,7 @@ public interface IWorkerContext {
|
||||||
public void setOverrideVersionNs(String value);
|
public void setOverrideVersionNs(String value);
|
||||||
|
|
||||||
public StructureDefinition fetchTypeDefinition(String typeName);
|
public StructureDefinition fetchTypeDefinition(String typeName);
|
||||||
|
public StructureDefinition fetchRawProfile(String url);
|
||||||
|
|
||||||
public void setUcumService(UcumService ucumService);
|
public void setUcumService(UcumService ucumService);
|
||||||
|
|
||||||
|
|
|
@ -640,6 +640,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructureDefinition fetchRawProfile(String uri) {
|
||||||
|
StructureDefinition r = super.fetchResource(StructureDefinition.class, uri);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException {
|
public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException {
|
||||||
generateSnapshot(p, false);
|
generateSnapshot(p, false);
|
||||||
|
|
|
@ -671,7 +671,7 @@ public class Meta extends DataType implements IBaseMetaType {
|
||||||
* <code>null</code> if none
|
* <code>null</code> if none
|
||||||
*/
|
*/
|
||||||
public Coding getSecurity(String theSystem, String theCode) {
|
public Coding getSecurity(String theSystem, String theCode) {
|
||||||
for (Coding next : getTag()) {
|
for (Coding next : getSecurity()) {
|
||||||
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1620,6 +1620,8 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
return false;
|
return false;
|
||||||
} else if (e instanceof ElementDefinition) {
|
} else if (e instanceof ElementDefinition) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (e instanceof Base64BinaryType) {
|
||||||
|
return false;
|
||||||
} else if (!(e instanceof Attachment))
|
} else if (!(e instanceof Attachment))
|
||||||
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet");
|
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet");
|
||||||
return false;
|
return false;
|
||||||
|
@ -2515,6 +2517,8 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
if (!x.hasAttribute("xmlns"))
|
if (!x.hasAttribute("xmlns"))
|
||||||
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
if (r.hasLanguage()) {
|
if (r.hasLanguage()) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", r.getLanguage());
|
||||||
x.setAttribute("xml:lang", r.getLanguage());
|
x.setAttribute("xml:lang", r.getLanguage());
|
||||||
}
|
}
|
||||||
if (!r.hasText() || !r.getText().hasDiv() || r.getText().getDiv().getChildNodes().isEmpty()) {
|
if (!r.hasText() || !r.getText().hasDiv() || r.getText().getDiv().getChildNodes().isEmpty()) {
|
||||||
|
@ -2539,6 +2543,13 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
private void inject(Element er, XhtmlNode x, NarrativeStatus status) {
|
private void inject(Element er, XhtmlNode x, NarrativeStatus status) {
|
||||||
if (!x.hasAttribute("xmlns"))
|
if (!x.hasAttribute("xmlns"))
|
||||||
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
|
Element le = XMLUtil.getNamedChild(er, "language");
|
||||||
|
String l = le == null ? null : le.getAttribute("value");
|
||||||
|
if (!Utilities.noString(l)) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", l);
|
||||||
|
x.setAttribute("xml:lang", l);
|
||||||
|
}
|
||||||
Element txt = XMLUtil.getNamedChild(er, "text");
|
Element txt = XMLUtil.getNamedChild(er, "text");
|
||||||
if (txt == null) {
|
if (txt == null) {
|
||||||
txt = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text");
|
txt = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text");
|
||||||
|
@ -2574,6 +2585,12 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
private void inject(org.hl7.fhir.r5.elementmodel.Element er, XhtmlNode x, NarrativeStatus status) throws IOException, FHIRException {
|
private void inject(org.hl7.fhir.r5.elementmodel.Element er, XhtmlNode x, NarrativeStatus status) throws IOException, FHIRException {
|
||||||
if (!x.hasAttribute("xmlns"))
|
if (!x.hasAttribute("xmlns"))
|
||||||
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
||||||
|
String l = er.getChildValue("language");
|
||||||
|
if (!Utilities.noString(l)) {
|
||||||
|
// use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues
|
||||||
|
x.setAttribute("lang", l);
|
||||||
|
x.setAttribute("xml:lang", l);
|
||||||
|
}
|
||||||
org.hl7.fhir.r5.elementmodel.Element txt = er.getNamedChild("text");
|
org.hl7.fhir.r5.elementmodel.Element txt = er.getNamedChild("text");
|
||||||
if (txt == null) {
|
if (txt == null) {
|
||||||
txt = new org.hl7.fhir.r5.elementmodel.Element("text", er.getProperty().getChild(null, "text"));
|
txt = new org.hl7.fhir.r5.elementmodel.Element("text", er.getProperty().getChild(null, "text"));
|
||||||
|
@ -2919,6 +2936,9 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConceptMapRenderInstructions findByTarget(DataType source) {
|
private ConceptMapRenderInstructions findByTarget(DataType source) {
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
String src = source.primitiveValue();
|
String src = source.primitiveValue();
|
||||||
if (src != null)
|
if (src != null)
|
||||||
for (ConceptMapRenderInstructions t : renderingMaps) {
|
for (ConceptMapRenderInstructions t : renderingMaps) {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||||
|
|
||||||
@RunWith(Suite.class)
|
@RunWith(Suite.class)
|
||||||
@SuiteClasses({
|
@SuiteClasses({
|
||||||
|
NpmPackageTests.class,
|
||||||
|
PackageClientTests.class,
|
||||||
SnomedExpressionsTests.class,
|
SnomedExpressionsTests.class,
|
||||||
GraphQLParserTests.class,
|
GraphQLParserTests.class,
|
||||||
TurtleTests.class,
|
TurtleTests.class,
|
||||||
|
@ -21,7 +23,8 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||||
BaseDateTimeTypeTest.class,
|
BaseDateTimeTypeTest.class,
|
||||||
OpenApiGeneratorTest.class,
|
OpenApiGeneratorTest.class,
|
||||||
MetadataResourceManagerTester.class,
|
MetadataResourceManagerTester.class,
|
||||||
NpmPackageTests.class,
|
MetaTest.class,
|
||||||
|
UtilitiesTests.class,
|
||||||
SnapShotGenerationTests.class})
|
SnapShotGenerationTests.class})
|
||||||
|
|
||||||
public class AllR5Tests {
|
public class AllR5Tests {
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class FHIRPathTests {
|
||||||
|
|
||||||
@Parameters(name = "{index}: file {0}")
|
@Parameters(name = "{index}: file {0}")
|
||||||
public static Iterable<Object[]> data() throws ParserConfigurationException, SAXException, IOException {
|
public static Iterable<Object[]> data() throws ParserConfigurationException, SAXException, IOException {
|
||||||
Document dom = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fhirpath", "tests-fhir-r4.xml"));
|
Document dom = XMLUtil.parseToDom(TestingUtilities.loadTestResource("r5", "fhirpath", "tests-fhir-r5.xml"));
|
||||||
|
|
||||||
List<Element> list = new ArrayList<Element>();
|
List<Element> list = new ArrayList<Element>();
|
||||||
List<Element> groups = new ArrayList<Element>();
|
List<Element> groups = new ArrayList<Element>();
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.hl7.fhir.r5.test;
|
||||||
|
|
||||||
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
|
import org.hl7.fhir.r5.model.Meta;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class MetaTest {
|
||||||
|
public static String TEST_SYSTEM = "TEST_SYSTEM";
|
||||||
|
public static String TEST_CODE = "TEST_CODE";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaSecurity() {
|
||||||
|
Meta meta = new Meta();
|
||||||
|
Coding coding = meta.addSecurity().setSystem(TEST_SYSTEM).setCode(TEST_CODE);
|
||||||
|
assertTrue(meta.hasSecurity());
|
||||||
|
assertNotNull(meta.getSecurity());
|
||||||
|
assertNotNull(meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(1, meta.getSecurity().size());
|
||||||
|
assertEquals(meta.getSecurity().get(0), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(meta.getSecurityFirstRep(), meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
assertEquals(coding, meta.getSecurity(TEST_SYSTEM, TEST_CODE));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.hl7.fhir.r5.test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||||
|
import org.hl7.fhir.utilities.cache.PackageCacheManager;
|
||||||
|
import org.hl7.fhir.utilities.cache.ToolsVersion;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PackageCacheTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPath() throws IOException {
|
||||||
|
PackageCacheManager cache = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||||
|
cache.clear();
|
||||||
|
NpmPackage npm = cache.loadPackage("hl7.fhir.pubpack", "0.0.3");
|
||||||
|
npm.loadAllFiles();
|
||||||
|
Assert.assertNotNull(npm);
|
||||||
|
File dir = new File(Utilities.path("[tmp]", "cache"));
|
||||||
|
if (dir.exists()) {
|
||||||
|
Utilities.clearDirectory(dir.getAbsolutePath());
|
||||||
|
} else {
|
||||||
|
Utilities.createDirectory(dir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
npm.save(dir);
|
||||||
|
NpmPackage npm2 = cache.loadPackage("hl7.fhir.pubpack", "file:"+dir.getAbsolutePath());
|
||||||
|
Assert.assertNotNull(npm2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package org.hl7.fhir.r5.test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.cache.PackageClient;
|
||||||
|
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PackageClientTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExists() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://packages.fhir.org");
|
||||||
|
Assert.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1"));
|
||||||
|
Assert.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
|
||||||
|
Assert.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearch() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://packages.fhir.org");
|
||||||
|
List<PackageInfo> matches = client.search("core", null, null, false);
|
||||||
|
for (PackageInfo pi : matches) {
|
||||||
|
System.out.println(pi.toString());
|
||||||
|
}
|
||||||
|
Assert.assertTrue(matches.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchNoMatches() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://packages.fhir.org");
|
||||||
|
List<PackageInfo> matches = client.search("corezxxx", null, null, false);
|
||||||
|
Assert.assertTrue(matches.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersions() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://packages.fhir.org");
|
||||||
|
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3");
|
||||||
|
for (PackageInfo pi : matches) {
|
||||||
|
System.out.println(pi.toString());
|
||||||
|
}
|
||||||
|
Assert.assertTrue(matches.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersionsNone() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://packages.fhir.org");
|
||||||
|
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X");
|
||||||
|
Assert.assertTrue(matches.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExists2() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
Assert.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1"));
|
||||||
|
Assert.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
|
||||||
|
Assert.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearch2() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
List<PackageInfo> matches = client.search("core", null, null, false);
|
||||||
|
for (PackageInfo pi : matches) {
|
||||||
|
System.out.println(pi.toString());
|
||||||
|
}
|
||||||
|
Assert.assertTrue(matches.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchNoMatches2() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
List<PackageInfo> matches = client.search("corezxxx", null, null, false);
|
||||||
|
Assert.assertTrue(matches.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersions2() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3");
|
||||||
|
for (PackageInfo pi : matches) {
|
||||||
|
System.out.println(pi.toString());
|
||||||
|
}
|
||||||
|
Assert.assertTrue(matches.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersions2A() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
List<PackageInfo> matches = client.getVersions("hl7.fhir.us.core");
|
||||||
|
for (PackageInfo pi : matches) {
|
||||||
|
System.out.println(pi.toString());
|
||||||
|
}
|
||||||
|
Assert.assertTrue(matches.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersionsNone2() throws IOException {
|
||||||
|
PackageClient client = new PackageClient("http://test.fhir.org/packages");
|
||||||
|
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X");
|
||||||
|
Assert.assertTrue(matches.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -473,7 +473,9 @@ public class SnapShotGenerationTests {
|
||||||
pu.setNewSlicingProcessing(true);
|
pu.setNewSlicingProcessing(true);
|
||||||
pu.setIds(test.included, false);
|
pu.setIds(test.included, false);
|
||||||
StructureDefinition base = TestingUtilities.context().fetchResource(StructureDefinition.class, test.included.getBaseDefinition());
|
StructureDefinition base = TestingUtilities.context().fetchResource(StructureDefinition.class, test.included.getBaseDefinition());
|
||||||
pu.generateSnapshot(base, test.included, test.included.getUrl(), "http://test.org/profile", test.included.getName());
|
if (base != null) {
|
||||||
|
pu.generateSnapshot(base, test.included, test.included.getUrl(), "http://test.org/profile", test.included.getName());
|
||||||
|
}
|
||||||
if (!TestingUtilities.context().hasResource(StructureDefinition.class, test.included.getUrl()))
|
if (!TestingUtilities.context().hasResource(StructureDefinition.class, test.included.getUrl()))
|
||||||
TestingUtilities.context().cacheResource(test.included);
|
TestingUtilities.context().cacheResource(test.included);
|
||||||
int ec = 0;
|
int ec = 0;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.hl7.fhir.r5.test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
public class UtilitiesTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPath() throws IOException {
|
||||||
|
Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), SystemUtils.IS_OS_WINDOWS ? "c:\\temp\\test.txt" : "/temp/test.txt");
|
||||||
|
Assert.assertEquals(Utilities.path("[user]", "test.txt"), System.getProperty("user.home")+"\\test.txt");
|
||||||
|
Assert.assertEquals(Utilities.path("[JAVA_HOME]", "test.txt"), System.getenv("JAVA_HOME")+"\\test.txt");
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -568,11 +569,20 @@ public class Utilities {
|
||||||
else if (!s.toString().endsWith(File.separator))
|
else if (!s.toString().endsWith(File.separator))
|
||||||
s.append(File.separator);
|
s.append(File.separator);
|
||||||
String a = arg;
|
String a = arg;
|
||||||
if ("[tmp]".equals(a)) {
|
if (s.length() == 0) {
|
||||||
if (hasCTempDir()) {
|
if ("[tmp]".equals(a)) {
|
||||||
a = "c:\\temp";
|
if (hasCTempDir()) {
|
||||||
} else {
|
a = "c:\\temp";
|
||||||
a = System.getProperty("java.io.tmpdir");
|
} else {
|
||||||
|
a = System.getProperty("java.io.tmpdir");
|
||||||
|
}
|
||||||
|
} else if ("[user]".equals(a)) {
|
||||||
|
a = System.getProperty("user.home");
|
||||||
|
} else if (a.startsWith("[") && a.endsWith("]")){
|
||||||
|
String ev = System.getenv(a.replace("[", "").replace("]", ""));
|
||||||
|
if (ev != null) {
|
||||||
|
a = ev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a = a.replace("\\", File.separator);
|
a = a.replace("\\", File.separator);
|
||||||
|
@ -581,11 +591,15 @@ public class Utilities {
|
||||||
a = a.substring(File.separator.length());
|
a = a.substring(File.separator.length());
|
||||||
|
|
||||||
while (a.startsWith(".."+File.separator)) {
|
while (a.startsWith(".."+File.separator)) {
|
||||||
String p = s.toString().substring(0, s.length()-1);
|
if (s.length() == 0) {
|
||||||
if (!p.contains(File.separator)) {
|
s = new StringBuilder(Paths.get(".").toAbsolutePath().normalize().toString());
|
||||||
s = new StringBuilder();
|
|
||||||
} else {
|
} else {
|
||||||
s = new StringBuilder(p.substring(0, p.lastIndexOf(File.separator))+File.separator);
|
String p = s.toString().substring(0, s.length()-1);
|
||||||
|
if (!p.contains(File.separator)) {
|
||||||
|
s = new StringBuilder();
|
||||||
|
} else {
|
||||||
|
s = new StringBuilder(p.substring(0, p.lastIndexOf(File.separator))+File.separator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
a = a.substring(3);
|
a = a.substring(3);
|
||||||
}
|
}
|
||||||
|
@ -599,6 +613,9 @@ public class Utilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasCTempDir() {
|
private static boolean hasCTempDir() {
|
||||||
|
if (!System.getProperty("os.name").toLowerCase().contains("win")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
File tmp = new File("c:\\temp");
|
File tmp = new File("c:\\temp");
|
||||||
return tmp.exists() && tmp.isDirectory();
|
return tmp.exists() && tmp.isDirectory();
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,7 @@ public class NpmPackage {
|
||||||
|
|
||||||
public static void loadFiles(NpmPackage res, String path, File source, String... exemptions) throws FileNotFoundException, IOException {
|
public static void loadFiles(NpmPackage res, String path, File source, String... exemptions) throws FileNotFoundException, IOException {
|
||||||
res.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json")));
|
res.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json")));
|
||||||
|
res.path = path;
|
||||||
|
|
||||||
File dir = new File(path);
|
File dir = new File(path);
|
||||||
for (File f : dir.listFiles()) {
|
for (File f : dir.listFiles()) {
|
||||||
|
@ -622,6 +623,37 @@ public class NpmPackage {
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void save(File directory) throws IOException {
|
||||||
|
File dir = new File(Utilities.path(directory.getAbsolutePath(), name()));
|
||||||
|
if (!dir.exists()) {
|
||||||
|
Utilities.createDirectory(dir.getAbsolutePath());
|
||||||
|
} else {
|
||||||
|
Utilities.clearDirectory(dir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NpmPackageFolder folder : folders.values()) {
|
||||||
|
String n = folder.name;
|
||||||
|
|
||||||
|
File pd = new File(Utilities.path(dir.getAbsolutePath(), n));
|
||||||
|
if (!pd.exists()) {
|
||||||
|
Utilities.createDirectory(pd.getAbsolutePath());
|
||||||
|
}
|
||||||
|
NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder();
|
||||||
|
indexer.start();
|
||||||
|
for (String s : folder.content.keySet()) {
|
||||||
|
byte[] b = folder.content.get(s);
|
||||||
|
indexer.seeFile(s, b);
|
||||||
|
if (!s.equals(".index.json") && !s.equals("package.json")) {
|
||||||
|
TextFile.bytesToFile(b, Utilities.path(dir.getAbsolutePath(), n, s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
byte[] cnt = indexer.build().getBytes(Charset.forName("UTF-8"));
|
||||||
|
TextFile.bytesToFile(cnt, Utilities.path(dir.getAbsolutePath(), n, ".index.json"));
|
||||||
|
}
|
||||||
|
byte[] cnt = TextFile.stringToBytes(new GsonBuilder().setPrettyPrinting().create().toJson(npm), false);
|
||||||
|
TextFile.bytesToFile(cnt, Utilities.path(dir.getAbsolutePath(), "package", "package.json"));
|
||||||
|
}
|
||||||
|
|
||||||
public void save(OutputStream stream) throws IOException {
|
public void save(OutputStream stream) throws IOException {
|
||||||
TarArchiveOutputStream tar;
|
TarArchiveOutputStream tar;
|
||||||
ByteArrayOutputStream OutputStream;
|
ByteArrayOutputStream OutputStream;
|
||||||
|
@ -756,5 +788,35 @@ public class NpmPackage {
|
||||||
Collections.sort(res);
|
Collections.sort(res);
|
||||||
return res ;
|
return res ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearFolder(String folderName) {
|
||||||
|
NpmPackageFolder folder = folders.get(folderName);
|
||||||
|
folder.content.clear();
|
||||||
|
folder.types.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteFolder(String folderName) {
|
||||||
|
folders.remove(folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFile(String folderName, String name, byte[] cnt, String type) {
|
||||||
|
NpmPackageFolder folder = folders.get(folderName);
|
||||||
|
folder.content.put(name, cnt);
|
||||||
|
if (!folder.types.containsKey(type))
|
||||||
|
folder.types.put(type, new ArrayList<>());
|
||||||
|
folder.types.get(type).add(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadAllFiles() throws IOException {
|
||||||
|
for (String folder : folders.keySet()) {
|
||||||
|
NpmPackageFolder pf = folders.get(folder);
|
||||||
|
String p = Utilities.path(path, folder);
|
||||||
|
for (File f : new File(p).listFiles()) {
|
||||||
|
if (!f.isDirectory()) {
|
||||||
|
pf.getContent().put(f.getName(), TextFile.fileToBytes(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,8 +268,10 @@ public class PackageCacheManager {
|
||||||
|
|
||||||
private void clearCache() throws IOException {
|
private void clearCache() throws IOException {
|
||||||
for (File f : new File(cacheFolder).listFiles()) {
|
for (File f : new File(cacheFolder).listFiles()) {
|
||||||
if (f.isDirectory())
|
if (f.isDirectory()) {
|
||||||
|
Utilities.clearDirectory(f.getAbsolutePath());
|
||||||
FileUtils.deleteDirectory(f);
|
FileUtils.deleteDirectory(f);
|
||||||
|
}
|
||||||
else if (!f.getName().equals("packages.ini"))
|
else if (!f.getName().equals("packages.ini"))
|
||||||
FileUtils.forceDelete(f);
|
FileUtils.forceDelete(f);
|
||||||
}
|
}
|
||||||
|
@ -316,6 +318,10 @@ public class PackageCacheManager {
|
||||||
save = checkIniHasMapping("hl7.fhir.core", "http://hl7.org/fhir", ini) || save;
|
save = checkIniHasMapping("hl7.fhir.core", "http://hl7.org/fhir", ini) || save;
|
||||||
save = checkIniHasMapping("hl7.fhir.pubpack", "http://fhir.org/packages/hl7.fhir.pubpack", ini) || save;
|
save = checkIniHasMapping("hl7.fhir.pubpack", "http://fhir.org/packages/hl7.fhir.pubpack", ini) || save;
|
||||||
save = checkIniHasMapping("hl7.fhir.xver-extensions", "http://fhir.org/packages/hl7.fhir.xver-extensions", ini) || save;
|
save = checkIniHasMapping("hl7.fhir.xver-extensions", "http://fhir.org/packages/hl7.fhir.xver-extensions", ini) || save;
|
||||||
|
save = checkIniHasMapping("fhir.base.template", "http://fhir.org/templates/fhir.base.template", ini) || save;
|
||||||
|
save = checkIniHasMapping("hl7.base.template", "http://fhir.org/templates/hl7.base.template", ini) || save;
|
||||||
|
save = checkIniHasMapping("hl7.fhir.template", "http://fhir.org/templates/hl7.fhir.template", ini) || save;
|
||||||
|
save = checkIniHasMapping("ihe.fhir.template", "http://fhir.org/templates/ihe.fhir.template", ini) || save;
|
||||||
|
|
||||||
save = checkIniHasMapping("hl7.fhir.r2.core", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.core.tgz", ini) || save;
|
save = checkIniHasMapping("hl7.fhir.r2.core", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.core.tgz", ini) || save;
|
||||||
save = checkIniHasMapping("hl7.fhir.r2.examples", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.examples.tgz", ini) || save;
|
save = checkIniHasMapping("hl7.fhir.r2.examples", "http://hl7.org/fhir/DSTU2/hl7.fhir.r2.examples.tgz", ini) || save;
|
||||||
|
@ -382,6 +388,9 @@ public class PackageCacheManager {
|
||||||
public void recordMap(String url, String id) throws IOException {
|
public void recordMap(String url, String id) throws IOException {
|
||||||
if (url == null)
|
if (url == null)
|
||||||
return;
|
return;
|
||||||
|
if (url.contains("github.com")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(new File(Utilities.path(cacheFolder, "packages.ini")).exists()))
|
if (!(new File(Utilities.path(cacheFolder, "packages.ini")).exists()))
|
||||||
throw new Error("File "+Utilities.path(cacheFolder, "packages.ini")+" not found #1");
|
throw new Error("File "+Utilities.path(cacheFolder, "packages.ini")+" not found #1");
|
||||||
|
@ -431,7 +440,7 @@ public class PackageCacheManager {
|
||||||
String u = o.get("url").getAsString();
|
String u = o.get("url").getAsString();
|
||||||
if (u.contains("/ImplementationGuide/"))
|
if (u.contains("/ImplementationGuide/"))
|
||||||
u = u.substring(0, u.indexOf("/ImplementationGuide/"));
|
u = u.substring(0, u.indexOf("/ImplementationGuide/"));
|
||||||
builds.add(new BuildRecord(u, o.get("package-id").getAsString(), o.get("repo").getAsString(), readDate(o.get("date").getAsString())));
|
builds.add(new BuildRecord(u, o.get("package-id").getAsString(), getRepo(o.get("repo").getAsString()), readDate(o.get("date").getAsString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(builds, new BuildRecordSorter());
|
Collections.sort(builds, new BuildRecordSorter());
|
||||||
|
@ -443,6 +452,11 @@ public class PackageCacheManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getRepo(String path) {
|
||||||
|
String[] p = path.split("\\/");
|
||||||
|
return p[0]+"/"+p[1];
|
||||||
|
}
|
||||||
|
|
||||||
private Date readDate(String s) throws ParseException {
|
private Date readDate(String s) throws ParseException {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM, yyyy HH:mm:ss Z", new Locale("en", "US"));
|
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM, yyyy HH:mm:ss Z", new Locale("en", "US"));
|
||||||
return sdf.parse(s);
|
return sdf.parse(s);
|
||||||
|
@ -540,6 +554,13 @@ public class PackageCacheManager {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public NpmPackage loadPackageFromCacheOnly(String id, String version) throws IOException {
|
public NpmPackage loadPackageFromCacheOnly(String id, String version) throws IOException {
|
||||||
|
if (Utilities.noString(version)) {
|
||||||
|
throw new FHIRException("Invalid version - ''");
|
||||||
|
}
|
||||||
|
if (version.startsWith("file:")) {
|
||||||
|
return loadPackageFromFile(id, version.substring(5));
|
||||||
|
}
|
||||||
|
|
||||||
for (NpmPackage p : temporaryPackages) {
|
for (NpmPackage p : temporaryPackages) {
|
||||||
if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version)))
|
if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version)))
|
||||||
return p;
|
return p;
|
||||||
|
@ -559,6 +580,7 @@ public class PackageCacheManager {
|
||||||
* Add an already fetched package to the cache
|
* Add an already fetched package to the cache
|
||||||
*/
|
*/
|
||||||
public NpmPackage addPackageToCache(String id, String version, InputStream tgz, String sourceDesc) throws IOException {
|
public NpmPackage addPackageToCache(String id, String version, InputStream tgz, String sourceDesc) throws IOException {
|
||||||
|
checkValidVersionString(version, id);
|
||||||
if (progress ) {
|
if (progress ) {
|
||||||
System.out.println("Installing "+id+"#"+(version == null ? "?" : version)+" to the package cache");
|
System.out.println("Installing "+id+"#"+(version == null ? "?" : version)+" to the package cache");
|
||||||
System.out.print(" Fetching:");
|
System.out.print(" Fetching:");
|
||||||
|
@ -636,11 +658,31 @@ public class PackageCacheManager {
|
||||||
return pck;
|
return pck;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkValidVersionString(String version, String id) {
|
||||||
|
if (Utilities.noString(version)) {
|
||||||
|
throw new FHIRException("Cannot add package "+id+" to the package cache - a version must be provided");
|
||||||
|
}
|
||||||
|
if (version.startsWith("file:")) {
|
||||||
|
throw new FHIRException("Cannot add package "+id+" to the package cache - the version '"+version+"' is illegal in this context");
|
||||||
|
}
|
||||||
|
for (char ch : version.toCharArray()) {
|
||||||
|
if (!Character.isAlphabetic(ch) && !Character.isDigit(ch) && !Utilities.existsInList(ch, '.', '-')) {
|
||||||
|
throw new FHIRException("Cannot add package "+id+" to the package cache - the version '"+version+"' is illegal (ch '"+ch+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NpmPackage loadPackage(String id) throws FHIRException, IOException {
|
public NpmPackage loadPackage(String id) throws FHIRException, IOException {
|
||||||
throw new Error("Not done yet");
|
throw new Error("Not done yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
public NpmPackage loadPackage(String id, String v) throws FHIRException, IOException {
|
public NpmPackage loadPackage(String id, String v) throws FHIRException, IOException {
|
||||||
|
if (Utilities.noString(v)) {
|
||||||
|
throw new FHIRException("Invalid version - ''");
|
||||||
|
}
|
||||||
|
if (v.startsWith("file:")) {
|
||||||
|
return loadPackageFromFile(id, v.substring(5));
|
||||||
|
}
|
||||||
NpmPackage p = loadPackageFromCacheOnly(id, v);
|
NpmPackage p = loadPackageFromCacheOnly(id, v);
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
if ("current".equals(v)) {
|
if ("current".equals(v)) {
|
||||||
|
@ -659,33 +701,42 @@ public class PackageCacheManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = getPackageUrl(id);
|
String url = getPackageUrl(id);
|
||||||
if (url == null)
|
if (url == null) {
|
||||||
throw new FHIRException("Unable to resolve the package '"+id+"'");
|
throw new FHIRException("Unable to resolve the package '"+id+"'");
|
||||||
|
}
|
||||||
|
String aurl = null;
|
||||||
|
try {
|
||||||
if (url.contains(".tgz")) {
|
if (url.contains(".tgz")) {
|
||||||
|
aurl = url;
|
||||||
InputStream stream = fetchFromUrlSpecific(url, true);
|
InputStream stream = fetchFromUrlSpecific(url, true);
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
return addPackageToCache(id, v, stream, url);
|
return addPackageToCache(id, v, stream, url);
|
||||||
throw new FHIRException("Unable to find the package source for '"+id+"' at "+url);
|
throw new FHIRException("Unable to find the package source for '"+id+"' at "+url);
|
||||||
}
|
}
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
|
aurl = Utilities.pathURL(url, "package.tgz");
|
||||||
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(url, "package.tgz"), true);
|
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(url, "package.tgz"), true);
|
||||||
if (stream == null && isBuildLoaded()) {
|
if (stream == null && isBuildLoaded()) {
|
||||||
|
aurl = Utilities.pathURL(buildPath(url), "package.tgz");
|
||||||
stream = fetchFromUrlSpecific(Utilities.pathURL(buildPath(url), "package.tgz"), true);
|
stream = fetchFromUrlSpecific(Utilities.pathURL(buildPath(url), "package.tgz"), true);
|
||||||
}
|
}
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
return addPackageToCache(id, null, stream, url);
|
return addPackageToCache(id, null, stream, url);
|
||||||
throw new FHIRException("Unable to find the package source for '"+id+"' at "+url);
|
throw new FHIRException("Unable to find the package source for '"+id+"' at "+url);
|
||||||
} else if ("current".equals(v) && ciList.containsKey(id)){
|
} else if ("current".equals(v) && ciList.containsKey(id)){
|
||||||
|
aurl = Utilities.pathURL(buildPath(url), "package.tgz");
|
||||||
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "package.tgz"), true);
|
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "package.tgz"), true);
|
||||||
return addPackageToCache(id, v, stream, Utilities.pathURL(ciList.get(id), "package.tgz"));
|
return addPackageToCache(id, v, stream, Utilities.pathURL(ciList.get(id), "package.tgz"));
|
||||||
} else {
|
} else {
|
||||||
String pu = Utilities.pathURL(url, "package-list.json");
|
String pu = Utilities.pathURL(url, "package-list.json");
|
||||||
|
aurl = pu;
|
||||||
JsonObject json;
|
JsonObject json;
|
||||||
try {
|
try {
|
||||||
json = fetchJson(pu);
|
json = fetchJson(pu);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String pv = Utilities.pathURL(url, v, "package.tgz");
|
String pv = Utilities.pathURL(url, v, "package.tgz");
|
||||||
try {
|
try {
|
||||||
|
aurl = pv;
|
||||||
InputStream stream = fetchFromUrlSpecific(pv, true);
|
InputStream stream = fetchFromUrlSpecific(pv, true);
|
||||||
return addPackageToCache(id, v, stream, pv);
|
return addPackageToCache(id, v, stream, pv);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
|
@ -697,6 +748,7 @@ public class PackageCacheManager {
|
||||||
for (JsonElement e : json.getAsJsonArray("list")) {
|
for (JsonElement e : json.getAsJsonArray("list")) {
|
||||||
JsonObject vo = (JsonObject) e;
|
JsonObject vo = (JsonObject) e;
|
||||||
if (v.equals(JSONUtil.str(vo, "version"))) {
|
if (v.equals(JSONUtil.str(vo, "version"))) {
|
||||||
|
aurl = Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz");
|
||||||
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"), true);
|
InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"), true);
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
throw new FHIRException("Unable to find the package source for '"+id+"#"+v+"' at "+Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"));
|
throw new FHIRException("Unable to find the package source for '"+id+"#"+v+"' at "+Utilities.pathURL(JSONUtil.str(vo, "path"), "package.tgz"));
|
||||||
|
@ -712,6 +764,9 @@ public class PackageCacheManager {
|
||||||
// }
|
// }
|
||||||
throw new FHIRException("Unable to resolve version "+v+" for package "+id);
|
throw new FHIRException("Unable to resolve version "+v+" for package "+id);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new FHIRException(e.getMessage()+(aurl == null ? "" : " (url = "+aurl+")"), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -731,6 +786,16 @@ public class PackageCacheManager {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean hasPackage(String id, String version) {
|
public boolean hasPackage(String id, String version) {
|
||||||
|
if (Utilities.noString(version)) {
|
||||||
|
throw new FHIRException("Invalid version - ''");
|
||||||
|
}
|
||||||
|
if (version.startsWith("file:")) {
|
||||||
|
try {
|
||||||
|
return loadPackageFromFile(id, version.substring(5)) != null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (NpmPackage p : temporaryPackages) {
|
for (NpmPackage p : temporaryPackages) {
|
||||||
if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version)))
|
if (p.name().equals(id) && ("current".equals(version) || "dev".equals(version) || p.version().equals(version)))
|
||||||
return true;
|
return true;
|
||||||
|
@ -747,6 +812,21 @@ public class PackageCacheManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private NpmPackage loadPackageFromFile(String id, String folder) throws IOException {
|
||||||
|
File f = new File(Utilities.path(folder, id));
|
||||||
|
if (!f.exists()) {
|
||||||
|
throw new FHIRException("Package '"+id+" not found in folder "+folder);
|
||||||
|
}
|
||||||
|
if (!f.isDirectory()) {
|
||||||
|
throw new FHIRException("File for '"+id+" found in folder "+folder+", not a folder");
|
||||||
|
}
|
||||||
|
File fp = new File(Utilities.path(folder, id, "package", "package.json"));
|
||||||
|
if (!fp.exists()) {
|
||||||
|
throw new FHIRException("Package '"+id+" found in folder "+folder+", but does not contain a package.json file in /package");
|
||||||
|
}
|
||||||
|
return NpmPackage.fromFolder(f.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List which versions of a package are available
|
* List which versions of a package are available
|
||||||
*
|
*
|
||||||
|
|
165
org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java
vendored
Normal file
165
org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageClient.java
vendored
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
package org.hl7.fhir.utilities.cache;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||||
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.hl7.fhir.utilities.cache.PackageClient.PackageInfo;
|
||||||
|
import org.hl7.fhir.utilities.json.JSONUtil;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
public class PackageClient {
|
||||||
|
|
||||||
|
public class PackageInfo {
|
||||||
|
private String id;
|
||||||
|
private String version;
|
||||||
|
private String fhirVersion;
|
||||||
|
private String description;
|
||||||
|
private String url;
|
||||||
|
public PackageInfo(String id, String version, String fhirVersion, String description, String url) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.version = version;
|
||||||
|
this.fhirVersion = fhirVersion;
|
||||||
|
this.description = description;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
public String getFhirVersion() {
|
||||||
|
return fhirVersion;
|
||||||
|
}
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return id+"#"+(version == null ? "??" : version)+(fhirVersion == null ? "": "for FHIR "+fhirVersion)+(url == null ? "" : " @"+url)+(description == null ? "" : " '"+description+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
|
||||||
|
public PackageClient(String address) {
|
||||||
|
super();
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(String id, String ver) throws IOException {
|
||||||
|
List<PackageInfo> vl = getVersions(id);
|
||||||
|
for (PackageInfo pi : vl) {
|
||||||
|
if (ver.equals(pi.getVersion())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream fetch(String id, String ver) throws IOException {
|
||||||
|
return fetchUrl(Utilities.pathURL(address, id, ver));
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream fetch(PackageInfo info) throws IOException {
|
||||||
|
return fetchUrl(Utilities.pathURL(address, info.getId(), info.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream fetchNpm(String id, String ver) throws IOException {
|
||||||
|
return fetchUrl(Utilities.pathURL(address, id, "-", id+"-"+ver+".tgz"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PackageInfo> getVersions(String id) throws IOException {
|
||||||
|
List<PackageInfo> res = new ArrayList<>();
|
||||||
|
JsonObject json;
|
||||||
|
try {
|
||||||
|
json = fetchJson(Utilities.pathURL(address, id));
|
||||||
|
JsonObject versions = json.getAsJsonObject("versions");
|
||||||
|
if (versions != null) {
|
||||||
|
for (String v : sorted(versions.keySet())) {
|
||||||
|
JsonObject obj = versions.getAsJsonObject(v);
|
||||||
|
res.add(new PackageInfo(JSONUtil.str(obj, "name"), JSONUtil.str(obj, "version"), JSONUtil.str(obj, "FhirVersion"), JSONUtil.str(obj, "description"), JSONUtil.str(obj, "url")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> sorted(Set<String> keys) {
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
res.addAll(keys);
|
||||||
|
Collections.sort(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PackageInfo> search(String name, String canonical, String fhirVersion, boolean preRelease) throws IOException {
|
||||||
|
CommaSeparatedStringBuilder params = new CommaSeparatedStringBuilder("&");
|
||||||
|
if (!Utilities.noString(name)) {
|
||||||
|
params.append("name="+name);
|
||||||
|
}
|
||||||
|
if (!Utilities.noString(canonical)) {
|
||||||
|
params.append("canonical="+canonical);
|
||||||
|
}
|
||||||
|
if (!Utilities.noString(fhirVersion)) {
|
||||||
|
params.append("fhirversion="+fhirVersion);
|
||||||
|
}
|
||||||
|
if (preRelease) {
|
||||||
|
params.append("prerelease="+preRelease);
|
||||||
|
}
|
||||||
|
List<PackageInfo> res = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
JsonArray json = fetchJsonArray(Utilities.pathURL(address, "catalog?")+params.toString());
|
||||||
|
for (JsonElement e : json) {
|
||||||
|
JsonObject obj = (JsonObject) e;
|
||||||
|
res.add(new PackageInfo(JSONUtil.str(obj, "Name"), null, JSONUtil.str(obj, "FhirVersion"), JSONUtil.str(obj, "Description"), null));
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e1) {
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getNewPackages(Date lastCalled, List<PackageInfo> updates) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream fetchUrl(String source) throws IOException {
|
||||||
|
URL url = new URL(source);
|
||||||
|
URLConnection c = url.openConnection();
|
||||||
|
return c.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonObject fetchJson(String source) throws IOException {
|
||||||
|
String src = TextFile.streamToString(fetchUrl(source));
|
||||||
|
//System.out.println(src);
|
||||||
|
return (JsonObject) new com.google.gson.JsonParser().parse(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonArray fetchJsonArray(String source) throws IOException {
|
||||||
|
String src = TextFile.streamToString(fetchUrl(source));
|
||||||
|
//System.out.println(src);
|
||||||
|
return (JsonArray) new com.google.gson.JsonParser().parse(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonNull;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
public class JSONUtil {
|
public class JSONUtil {
|
||||||
|
@ -73,7 +74,7 @@ public class JSONUtil {
|
||||||
|
|
||||||
public static String str(JsonObject json, String name) {
|
public static String str(JsonObject json, String name) {
|
||||||
JsonElement e = json.get(name);
|
JsonElement e = json.get(name);
|
||||||
return e == null ? null : e.getAsString();
|
return e == null || e instanceof JsonNull ? null : e.getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String str(JsonObject json, String name1, String name2) {
|
public static String str(JsonObject json, String name1, String name2) {
|
||||||
|
|
|
@ -487,6 +487,8 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
||||||
private String html;
|
private String html;
|
||||||
private String locationLink;
|
private String locationLink;
|
||||||
private String txLink;
|
private String txLink;
|
||||||
|
public String sliceHtml;
|
||||||
|
private boolean slicingHint;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -746,5 +748,22 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
|
||||||
this.html = html;
|
this.html = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSlicingHint() {
|
||||||
|
return slicingHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationMessage setSlicingHint(boolean slicingHint) {
|
||||||
|
this.slicingHint = slicingHint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSliceHtml() {
|
||||||
|
return sliceHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSliceHtml(String sliceHtml) {
|
||||||
|
this.sliceHtml = sliceHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.hl7.fhir.utilities.tests;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
public class UtilitiesTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPath() throws IOException {
|
||||||
|
Assert.assertEquals(Utilities.path("[tmp]", "test.txt"), "c:\\temp\\test.txt");
|
||||||
|
Assert.assertEquals(Utilities.path("[user]", "test.txt"), System.getProperty("user.home")+"\\test.txt");
|
||||||
|
Assert.assertEquals(Utilities.path("[JAVA_HOME]", "test.txt"), System.getenv("JAVA_HOME")+"\\test.txt");
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -145,8 +145,23 @@ public class BaseValidator {
|
||||||
*/
|
*/
|
||||||
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
|
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) {
|
||||||
if (!thePass) {
|
if (!thePass) {
|
||||||
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION);
|
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION);
|
||||||
}
|
}
|
||||||
|
return thePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails. And mark it as a slicing hint for later recovery if appropriate
|
||||||
|
*
|
||||||
|
* @param thePass
|
||||||
|
* Set this parameter to <code>false</code> if the validation does not pass
|
||||||
|
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html) {
|
||||||
|
if (!thePass) {
|
||||||
|
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION).setSlicingHint(true).setSliceHtml(html);
|
||||||
|
}
|
||||||
return thePass;
|
return thePass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +183,7 @@ public class BaseValidator {
|
||||||
protected boolean txHint(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
protected boolean txHint(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||||
if (!thePass) {
|
if (!thePass) {
|
||||||
String message = formatMessage(theMessage, theMessageArguments);
|
String message = formatMessage(theMessage, theMessageArguments);
|
||||||
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine)
|
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine).setTxLink(txLink);
|
||||||
.setTxLink(txLink);
|
|
||||||
}
|
}
|
||||||
return thePass;
|
return thePass;
|
||||||
}
|
}
|
||||||
|
@ -338,9 +352,9 @@ public class BaseValidator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity) {
|
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity) {
|
||||||
Source source = this.source;
|
Source source = this.source;
|
||||||
addValidationMessage(errors, type, line, col, path, msg, theSeverity, source);
|
return addValidationMessage(errors, type, line, col, path, msg, theSeverity, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource) {
|
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource) {
|
||||||
|
|
|
@ -108,6 +108,7 @@ import org.hl7.fhir.r5.model.Range;
|
||||||
import org.hl7.fhir.r5.model.Ratio;
|
import org.hl7.fhir.r5.model.Ratio;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.SampledData;
|
import org.hl7.fhir.r5.model.SampledData;
|
||||||
|
import org.hl7.fhir.r5.model.SearchParameter;
|
||||||
import org.hl7.fhir.r5.model.StringType;
|
import org.hl7.fhir.r5.model.StringType;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition.ExtensionContextType;
|
import org.hl7.fhir.r5.model.StructureDefinition.ExtensionContextType;
|
||||||
|
@ -156,6 +157,9 @@ import ca.uhn.fhir.util.ObjectUtil;
|
||||||
* Thinking of using this in a java program? Don't!
|
* Thinking of using this in a java program? Don't!
|
||||||
* You should use one of the wrappers instead. Either in HAPI, or use ValidationEngine
|
* You should use one of the wrappers instead. Either in HAPI, or use ValidationEngine
|
||||||
*
|
*
|
||||||
|
* Validation todo:
|
||||||
|
* - support @default slices
|
||||||
|
*
|
||||||
* @author Grahame Grieve
|
* @author Grahame Grieve
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -207,6 +211,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
private Element rootResource;
|
private Element rootResource;
|
||||||
private StructureDefinition profile; // the profile that contains the content being validated
|
private StructureDefinition profile; // the profile that contains the content being validated
|
||||||
private boolean checkSpecials = true;
|
private boolean checkSpecials = true;
|
||||||
|
private Map<String, List<ValidationMessage>> sliceRecords;
|
||||||
|
|
||||||
public ValidatorHostContext(Object appContext) {
|
public ValidatorHostContext(Object appContext) {
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
|
@ -242,6 +247,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
res.rootResource = rootResource;
|
res.rootResource = rootResource;
|
||||||
res.container = container;
|
res.container = container;
|
||||||
res.profile = profile;
|
res.profile = profile;
|
||||||
|
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +283,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sliceNotes(String url, List<ValidationMessage> record) {
|
||||||
|
sliceRecords.put(url, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidatorHostContext forSlicing() {
|
||||||
|
ValidatorHostContext res = new ValidatorHostContext(appContext);
|
||||||
|
res.resource = resource;
|
||||||
|
res.rootResource = resource;
|
||||||
|
res.container = resource;
|
||||||
|
res.profile = profile;
|
||||||
|
res.checkSpecials = false;
|
||||||
|
res.sliceRecords = new HashMap<String, List<ValidationMessage>>();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,8 +426,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
} else
|
} else
|
||||||
throw new NotImplementedException("Not done yet (ValidatorHostServices.conformsToProfile), when item is not an element");
|
throw new NotImplementedException("Not done yet (ValidatorHostServices.conformsToProfile), when item is not an element");
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
for (ValidationMessage v : valerrors)
|
List<ValidationMessage> record = new ArrayList<>();
|
||||||
|
for (ValidationMessage v : valerrors) {
|
||||||
ok = ok && !v.getLevel().isError();
|
ok = ok && !v.getLevel().isError();
|
||||||
|
if (v.getLevel().isError() || v.isSlicingHint()) {
|
||||||
|
record.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok && !record.isEmpty()) {
|
||||||
|
ctxt.sliceNotes(url, record);
|
||||||
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1597,9 +1626,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
Set<String> allowedTypes = listExtensionTypes(ex);
|
Set<String> allowedTypes = listExtensionTypes(ex);
|
||||||
String actualType = getExtensionType(element);
|
String actualType = getExtensionType(element);
|
||||||
if (actualType == null)
|
if (actualType == null)
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", allowedTypes.isEmpty(), "The Extension '" + url + "' definition is for a simple extension, so it must contain a value, not extensions");
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowedTypes.isEmpty(), "The Extension '" + url + "' definition is for a simple extension, so it must contain a value, not extensions");
|
||||||
else
|
else
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", allowedTypes.contains(actualType), "The Extension '" + url + "' definition allows for the types "+allowedTypes.toString()+" but found type "+actualType);
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, allowedTypes.contains(actualType), "The Extension '" + url + "' definition allows for the types "+allowedTypes.toString()+" but found type "+actualType);
|
||||||
|
|
||||||
// 3. is the content of the extension valid?
|
// 3. is the content of the extension valid?
|
||||||
validateElement(hostContext, errors, ex, ex.getSnapshot().getElement().get(0), null, null, resource, element, "Extension", stack, false, true, url);
|
validateElement(hostContext, errors, ex, ex.getSnapshot().getElement().get(0), null, null, resource, element, "Extension", stack, false, true, url);
|
||||||
|
@ -1691,7 +1720,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
if (sd.getBaseDefinition() != null) {
|
||||||
|
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||||
|
} else {
|
||||||
|
sd = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1959,7 +1992,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (fetcher != null) {
|
if (fetcher != null) {
|
||||||
boolean found;
|
boolean found;
|
||||||
try {
|
try {
|
||||||
found = (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
|
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
|
@ -2122,6 +2155,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
// for nothing to check
|
// for nothing to check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDefinitionURL(String url) {
|
||||||
|
return Utilities.existsInList(url, "http://hl7.org/fhirpath/System.Boolean", "http://hl7.org/fhirpath/System.String", "http://hl7.org/fhirpath/System.Integer",
|
||||||
|
"http://hl7.org/fhirpath/System.Decimal", "http://hl7.org/fhirpath/System.Date", "http://hl7.org/fhirpath/System.Time", "http://hl7.org/fhirpath/System.DateTime", "http://hl7.org/fhirpath/System.Quantity");
|
||||||
|
}
|
||||||
|
|
||||||
private void checkInnerNames(List<ValidationMessage> errors, Element e, String path, List<XhtmlNode> list) {
|
private void checkInnerNames(List<ValidationMessage> errors, Element e, String path, List<XhtmlNode> list) {
|
||||||
for (XhtmlNode node : list) {
|
for (XhtmlNode node : list) {
|
||||||
if (node.getNodeType() == NodeType.Element) {
|
if (node.getNodeType() == NodeType.Element) {
|
||||||
|
@ -2353,7 +2391,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (!isShowMessagesFromReferences()) {
|
if (!isShowMessagesFromReferences()) {
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile()));
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile()));
|
||||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummary(badProfiles.get(sd)));
|
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+ref+" matching against Profile"+sd.getUrl(), errorSummaryForSlicingAsHtml(badProfiles.get(sd)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size()==1, "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile()));
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size()==1, "Unable to find matching profile for "+ref+" among choices: " + asList(type.getTargetProfile()));
|
||||||
|
@ -2369,7 +2407,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
if (!isShowMessagesFromReferences()) {
|
if (!isShowMessagesFromReferences()) {
|
||||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet()));
|
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet()));
|
||||||
for (StructureDefinition sd : badProfiles.keySet()) {
|
for (StructureDefinition sd : badProfiles.keySet()) {
|
||||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Profile "+sd.getUrl()+" does not match for "+ref+" because of the following errors: "+errorSummary(badProfiles.get(sd)));
|
slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+ref+" matching against Profile"+sd.getUrl(), errorSummaryForSlicingAsHtml(badProfiles.get(sd)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet()));
|
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Found multiple matching profiles for "+ref+" among choices: " + asListByUrl(goodProfiles.keySet()));
|
||||||
|
@ -2404,6 +2442,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
boolean okToRef = !type.hasAggregation() || type.hasAggregation(AggregationMode.REFERENCED);
|
boolean okToRef = !type.hasAggregation() || type.hasAggregation(AggregationMode.REFERENCED);
|
||||||
rule(errors, IssueType.REQUIRED, -1, -1, path, okToRef, "Bundled or contained reference not found within the bundle/resource " + ref);
|
rule(errors, IssueType.REQUIRED, -1, -1, path, okToRef, "Bundled or contained reference not found within the bundle/resource " + ref);
|
||||||
}
|
}
|
||||||
|
if (we == null && ft != null && assumeValidRestReferences) {
|
||||||
|
// if we == null, we inferred ft from the reference. if we are told to treat this as gospel
|
||||||
|
TypeRefComponent type = getReferenceTypeRef(container.getType());
|
||||||
|
Set<String> types = new HashSet<>();
|
||||||
|
for (CanonicalType tp : type.getTargetProfile()) {
|
||||||
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, tp.getValue());
|
||||||
|
if (sd != null) {
|
||||||
|
types.add(sd.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || types.contains(ft), "The type '"+ft+"' implied by the reference URL "+ref+" is not a valid Target for this element (must be one of "+types+")");
|
||||||
|
|
||||||
|
}
|
||||||
if (pol == ReferenceValidationPolicy.CHECK_VALID) {
|
if (pol == ReferenceValidationPolicy.CHECK_VALID) {
|
||||||
// todo....
|
// todo....
|
||||||
}
|
}
|
||||||
|
@ -2434,16 +2485,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String errorSummary(List<ValidationMessage> list) {
|
private String errorSummaryForSlicing(List<ValidationMessage> list) {
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
for (ValidationMessage vm : list) {
|
for (ValidationMessage vm : list) {
|
||||||
if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL) {
|
if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL || vm.isSlicingHint()) {
|
||||||
b.append(vm.getLocation()+": "+vm.getMessage());
|
b.append(vm.getLocation()+": "+vm.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String errorSummaryForSlicingAsHtml(List<ValidationMessage> list) {
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
for (ValidationMessage vm : list) {
|
||||||
|
if (vm.isSlicingHint()) {
|
||||||
|
b.append("<li>"+vm.getLocation()+": "+vm.getSliceHtml()+"</li>");
|
||||||
|
} else if (vm.getLevel() == IssueSeverity.ERROR || vm.getLevel() == IssueSeverity.FATAL ) {
|
||||||
|
b.append("<li>"+vm.getLocation()+": "+vm.getHtml()+"</li>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "<ul>"+b.toString()+"</ul>";
|
||||||
|
}
|
||||||
|
|
||||||
private TypeRefComponent getReferenceTypeRef(List<TypeRefComponent> types) {
|
private TypeRefComponent getReferenceTypeRef(List<TypeRefComponent> types) {
|
||||||
for (TypeRefComponent tr : types) {
|
for (TypeRefComponent tr : types) {
|
||||||
if ("Reference".equals(tr.getCode())) {
|
if ("Reference".equals(tr.getCode())) {
|
||||||
|
@ -3186,7 +3249,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
*/
|
*/
|
||||||
private boolean sliceMatches(ValidatorHostContext hostContext, Element element, String path, ElementDefinition slicer, ElementDefinition ed, StructureDefinition profile, List<ValidationMessage> errors, NodeStack stack) throws DefinitionException, FHIRException {
|
private boolean sliceMatches(ValidatorHostContext hostContext, Element element, String path, ElementDefinition slicer, ElementDefinition ed, StructureDefinition profile, List<ValidationMessage> errors, List<ValidationMessage> sliceInfo, NodeStack stack) throws DefinitionException, FHIRException {
|
||||||
if (!slicer.getSlicing().hasDiscriminator())
|
if (!slicer.getSlicing().hasDiscriminator())
|
||||||
return false; // cannot validate in this case
|
return false; // cannot validate in this case
|
||||||
|
|
||||||
|
@ -3221,19 +3284,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
} else
|
} else
|
||||||
throw new DefinitionException("Discriminator (" + discriminator + ") is based on type, but slice " + ed.getId() + " in "+profile.getUrl()+" has no types");
|
throw new DefinitionException("Discriminator (" + discriminator + ") is based on type, but slice " + ed.getId() + " in "+profile.getUrl()+" has no types");
|
||||||
if (discriminator.isEmpty())
|
if (discriminator.isEmpty())
|
||||||
expression.append(" and this is " + type);
|
expression.append(" and $this is " + type);
|
||||||
else
|
else
|
||||||
expression.append(" and " + discriminator + " is " + type);
|
expression.append(" and " + discriminator + " is " + type);
|
||||||
} else if (s.getType() == DiscriminatorType.PROFILE) {
|
} else if (s.getType() == DiscriminatorType.PROFILE) {
|
||||||
if (criteriaElement.getType().size() == 0) {
|
if (criteriaElement.getType().size() == 0) {
|
||||||
throw new DefinitionException("Profile based discriminators must have a type ("+criteriaElement.getId()+")");
|
throw new DefinitionException("Profile based discriminators must have a type ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")");
|
||||||
}
|
}
|
||||||
if (criteriaElement.getType().size() != 1) {
|
if (criteriaElement.getType().size() != 1) {
|
||||||
throw new DefinitionException("Profile based discriminators must have only one type ("+criteriaElement.getId()+")");
|
throw new DefinitionException("Profile based discriminators must have only one type ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")");
|
||||||
}
|
}
|
||||||
List<CanonicalType> list = discriminator.endsWith(".resolve()") || discriminator.equals("resolve()") ? criteriaElement.getType().get(0).getTargetProfile() : criteriaElement.getType().get(0).getProfile();
|
List<CanonicalType> list = discriminator.endsWith(".resolve()") || discriminator.equals("resolve()") ? criteriaElement.getType().get(0).getTargetProfile() : criteriaElement.getType().get(0).getProfile();
|
||||||
if (list.size() == 0) {
|
if (list.size() == 0) {
|
||||||
throw new DefinitionException("Profile based discriminators must have a type with a profile ("+criteriaElement.getId()+")");
|
throw new DefinitionException("Profile based discriminators must have a type with a profile ("+criteriaElement.getId()+" in profile "+profile.getUrl()+")");
|
||||||
} else if (list.size() > 1) {
|
} else if (list.size() > 1) {
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" or ");
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" or ");
|
||||||
for (CanonicalType c : list) {
|
for (CanonicalType c : list) {
|
||||||
|
@ -3281,7 +3344,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
ed.setUserData("slice.expression.cache", n);
|
ed.setUserData("slice.expression.cache", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return evaluateSlicingExpression(hostContext, element, path, profile, n);
|
ValidatorHostContext shc = hostContext.forSlicing();
|
||||||
|
boolean pass = evaluateSlicingExpression(shc, element, path, profile, n);
|
||||||
|
if (!pass) {
|
||||||
|
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Does not match slice'"+ed.getSliceName(), "discriminator = "+Utilities.escapeXml(n.toString()));
|
||||||
|
for (String url : shc.sliceRecords.keySet()) {
|
||||||
|
slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, "Details for "+stack.getLiteralPath()+" against profile "+url,
|
||||||
|
"Profile "+url+" does not match for "+stack.getLiteralPath()+" because of the following profile issues: "+errorSummaryForSlicingAsHtml(shc.sliceRecords.get(url)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException {
|
public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException {
|
||||||
|
@ -3518,22 +3590,30 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (checkSpecials) {
|
if (checkSpecials) {
|
||||||
// specific known special validations
|
checkSpecials(hostContext, errors, element, stack, checkSpecials);
|
||||||
if (element.getType().equals("Bundle")) {
|
|
||||||
validateBundle(errors, element, stack);
|
|
||||||
} else if (element.getType().equals("Observation")) {
|
|
||||||
validateObservation(errors, element, stack);
|
|
||||||
} else if (element.getType().equals("Questionnaire")) {
|
|
||||||
validateQuestionannaire(errors, element, stack);
|
|
||||||
} else if (element.getType().equals("QuestionnaireResponse")) {
|
|
||||||
validateQuestionannaireResponse(hostContext, errors, element, stack);
|
|
||||||
} else if (element.getType().equals("CodeSystem")) {
|
|
||||||
validateCodeSystem(errors, element, stack);
|
|
||||||
}
|
|
||||||
validateResourceRules(errors, element, stack);
|
validateResourceRules(errors, element, stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkSpecials(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack, boolean checkSpecials) {
|
||||||
|
// specific known special validations
|
||||||
|
if (element.getType().equals("Bundle")) {
|
||||||
|
validateBundle(errors, element, stack, checkSpecials);
|
||||||
|
} else if (element.getType().equals("Observation")) {
|
||||||
|
validateObservation(errors, element, stack);
|
||||||
|
} else if (element.getType().equals("Questionnaire")) {
|
||||||
|
ArrayList<Element> parents = new ArrayList<>();
|
||||||
|
parents.add(element);
|
||||||
|
validateQuestionannaireItem(errors, element, element, stack, parents);
|
||||||
|
} else if (element.getType().equals("QuestionnaireResponse")) {
|
||||||
|
validateQuestionannaireResponse(hostContext, errors, element, stack);
|
||||||
|
} else if (element.getType().equals("CapabilityStatement")) {
|
||||||
|
validateCapabilityStatement(errors, element, stack);
|
||||||
|
} else if (element.getType().equals("CodeSystem")) {
|
||||||
|
validateCodeSystem(errors, element, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ResourceValidationTracker getResourceTracker(Element element) {
|
private ResourceValidationTracker getResourceTracker(Element element) {
|
||||||
ResourceValidationTracker res = resourceTracker.get(element);
|
ResourceValidationTracker res = resourceTracker.get(element);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
|
@ -3543,29 +3623,37 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateQuestionannaire(List<ValidationMessage> errors, Element element, NodeStack stack) {
|
private void validateQuestionannaireItem(List<ValidationMessage> errors, Element element, Element questionnaire, NodeStack stack, List<Element> parents) {
|
||||||
List<Element> list = getItems(element);
|
List<Element> list = getItems(element);
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
Element e = list.get(i);
|
Element e = list.get(i);
|
||||||
NodeStack ns = stack.push(element, i, e.getProperty().getDefinition(), e.getProperty().getDefinition());
|
NodeStack ns = stack.push(e, i, e.getProperty().getDefinition(), e.getProperty().getDefinition());
|
||||||
validateQuestionnaireElement(errors, ns, element, e, new ArrayList<>());
|
validateQuestionnaireElement(errors, ns, questionnaire, e, parents);
|
||||||
|
List<Element> np = new ArrayList<Element>();
|
||||||
|
np.add(e);
|
||||||
|
np.addAll(parents);
|
||||||
|
validateQuestionannaireItem(errors, e, questionnaire, ns, np);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateQuestionnaireElement(List<ValidationMessage> errors, NodeStack ns, Element questionnaire, Element item, List<Element> parents) {
|
private void validateQuestionnaireElement(List<ValidationMessage> errors, NodeStack ns, Element questionnaire, Element item, List<Element> parents) {
|
||||||
// R4+
|
// R4+
|
||||||
if (FHIRVersion.isR4Plus(context.getVersion())) {
|
if (FHIRVersion.isR4Plus(context.getVersion())) {
|
||||||
if (item.hasChild("enableWhen")) {
|
if (item.hasChildren("enableWhen")) {
|
||||||
Element ew = item.getNamedChild("enableWhen");
|
List<Element> ewl = item.getChildren("enableWhen");
|
||||||
String ql = ew.getNamedChildValue("question");
|
for (Element ew : ewl) {
|
||||||
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, ql != null, "Questions with an enableWhen must have a value for the question link")) {
|
// Element ew = item.getNamedChild("enableWhen");
|
||||||
Element tgt = getQuestionById(item, ql);
|
String ql = ew.getNamedChildValue("question");
|
||||||
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt == null, "Questions with an enableWhen cannot refer to an inner question for it's enableWhen condition")) {
|
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, ql != null, "Questions with an enableWhen must have a value for the question link")) {
|
||||||
tgt = getQuestionById(questionnaire, ql);
|
Element tgt = getQuestionById(item, ql);
|
||||||
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != null, "Unable to find "+ql+" target for this question enableWhen")) {
|
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt == null, "Questions with an enableWhen cannot refer to an inner question for it's enableWhen condition")) {
|
||||||
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != item, "Target for this question enableWhen can't reference itself")) {
|
tgt = getQuestionById(questionnaire, ql);
|
||||||
warning(errors, IssueType.BUSINESSRULE, ns.literalPath, isBefore(item, tgt, parents), "The target of this enableWhen rule ("+ql+") comes after the question itself");
|
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != null, "Unable to find target '"+ql+"' for this question enableWhen")) {
|
||||||
|
if (rule(errors, IssueType.BUSINESSRULE, ns.literalPath, tgt != item, "Target for this question enableWhen can't reference itself")) {
|
||||||
|
if (!isBefore(item, tgt, parents)) {
|
||||||
|
warning(errors, IssueType.BUSINESSRULE, ns.literalPath, false, "The target of this enableWhen rule ("+ql+") comes after the question itself");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3576,6 +3664,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
|
|
||||||
private boolean isBefore(Element item, Element tgt, List<Element> parents) {
|
private boolean isBefore(Element item, Element tgt, List<Element> parents) {
|
||||||
// we work up the list, looking for tgt in the children of the parents
|
// we work up the list, looking for tgt in the children of the parents
|
||||||
|
if (parents.contains(tgt)) {
|
||||||
|
// actually, if the target is a parent, that's automatically ok
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for (Element p : parents) {
|
for (Element p : parents) {
|
||||||
int i = findIndex(p, item);
|
int i = findIndex(p, item);
|
||||||
int t = findIndex(p, tgt);
|
int t = findIndex(p, tgt);
|
||||||
|
@ -3599,7 +3691,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
for (Element e : element.getChildren()) {
|
for (Element e : element.getChildren()) {
|
||||||
if (e == descendant)
|
if (e == descendant)
|
||||||
return true;
|
return true;
|
||||||
if (isChild(element, descendant))
|
if (isChild(e, descendant))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -3638,11 +3730,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
Element div = text.getNamedChild("div");
|
Element div = text.getNamedChild("div");
|
||||||
if (lang != null && div != null) {
|
if (lang != null && div != null) {
|
||||||
XhtmlNode xhtml = div.getXhtml();
|
XhtmlNode xhtml = div.getXhtml();
|
||||||
String xl = xhtml.getAttribute("lang");
|
String l = xhtml.getAttribute("lang");
|
||||||
if (xl == null) {
|
String xl = xhtml.getAttribute("xml:lang");
|
||||||
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have a language tag");
|
if (l == null && xl == null) {
|
||||||
} else if (!xl.equals(lang)) {
|
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have an lang or an xml:lang tag (needs both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)");
|
||||||
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has a language ("+xl+"), but they differ ");
|
} else {
|
||||||
|
if (l == null) {
|
||||||
|
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have a lang tag (needs both lang and xml:lang - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)");
|
||||||
|
} else if (!l.equals(lang)) {
|
||||||
|
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has a lang ("+l+"), but they differ ");
|
||||||
|
}
|
||||||
|
if (xl == null) {
|
||||||
|
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language, but the XHTML does not have an xml:lang tag (needs both lang and xml:lang - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues)");
|
||||||
|
} else if (!xl.equals(lang)) {
|
||||||
|
warning(errors, IssueType.BUSINESSRULE, div.line(), div.col(), stack.getLiteralPath(), false, "Resource has a language ("+lang+"), and the XHTML has an xml:lang ("+xl+"), but they differ ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3662,6 +3764,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateCapabilityStatement(List<ValidationMessage> errors, Element cs, NodeStack stack) {
|
||||||
|
int iRest = 0;
|
||||||
|
for (Element rest : cs.getChildrenByName("rest")) {
|
||||||
|
int iResource = 0;
|
||||||
|
for (Element resource : rest.getChildrenByName("resource")) {
|
||||||
|
int iSP = 0;
|
||||||
|
for (Element searchParam : resource.getChildrenByName("searchParam")) {
|
||||||
|
String ref = searchParam.getChildValue("definition");
|
||||||
|
String type = searchParam.getChildValue("type");
|
||||||
|
if (!Utilities.noString(ref)) {
|
||||||
|
SearchParameter sp = context.fetchResource(SearchParameter.class, ref);
|
||||||
|
if (sp != null) {
|
||||||
|
rule(errors, IssueType.INVALID, searchParam.line(), searchParam.col(), stack.literalPath+".rest["+iRest+"].resource["+iResource+"].searchParam["+iSP+"]",
|
||||||
|
sp.getType().toCode().equals(type), "Type mismatch - SearchParameter '"+sp.getUrl()+"' type is "+sp.getType().toCode()+", but type here is "+type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iSP++;
|
||||||
|
}
|
||||||
|
iResource++;
|
||||||
|
}
|
||||||
|
iRest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
private void validateCodeSystem(List<ValidationMessage> errors, Element cs, NodeStack stack) {
|
private void validateCodeSystem(List<ValidationMessage> errors, Element cs, NodeStack stack) {
|
||||||
String url = cs.getNamedChildValue("url");
|
String url = cs.getNamedChildValue("url");
|
||||||
String vsu = cs.getNamedChildValue("valueSet");
|
String vsu = cs.getNamedChildValue("valueSet");
|
||||||
|
@ -4247,7 +4372,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateBundle(List<ValidationMessage> errors, Element bundle, NodeStack stack) {
|
private void validateBundle(List<ValidationMessage> errors, Element bundle, NodeStack stack, boolean checkSpecials) {
|
||||||
List<Element> entries = new ArrayList<Element>();
|
List<Element> entries = new ArrayList<Element>();
|
||||||
bundle.getNamedChildren("entry", entries);
|
bundle.getNamedChildren("entry", entries);
|
||||||
String type = bundle.getNamedChildValue("type");
|
String type = bundle.getNamedChildValue("type");
|
||||||
|
@ -4291,6 +4416,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), false, "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless the resource id ("+id+") also matches");
|
rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), false, "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless the resource id ("+id+") also matches");
|
||||||
rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild("resource").fhirType(), id))), "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless on the canonical server itself");
|
rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry", ":0"), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild("resource").fhirType(), id))), "The canonical URL ("+url+") cannot match the fullUrl ("+fullUrl+") unless on the canonical server itself");
|
||||||
}
|
}
|
||||||
|
// todo: check specials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4617,9 +4743,6 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
|
|
||||||
// time = System.nanoTime();
|
// time = System.nanoTime();
|
||||||
// check type invariants
|
// check type invariants
|
||||||
if (definition.getId().equals("Composition.section:sectionResults")) {
|
|
||||||
System.out.println("!");
|
|
||||||
}
|
|
||||||
checkInvariants(hostContext, errors, profile, definition, resource, element, stack, false);
|
checkInvariants(hostContext, errors, profile, definition, resource, element, stack, false);
|
||||||
if (definition.getFixed() != null)
|
if (definition.getFixed() != null)
|
||||||
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getUrl(), definition.getSliceName(), null);
|
checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getUrl(), definition.getSliceName(), null);
|
||||||
|
@ -4630,16 +4753,14 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
if (childDefinitions.isEmpty()) {
|
if (childDefinitions.isEmpty()) {
|
||||||
if (actualType == null)
|
if (actualType == null)
|
||||||
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
||||||
StructureDefinition dt = null;
|
childDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
||||||
if (isAbsolute(actualType))
|
} else if (definition.getType().size() > 1) {
|
||||||
dt = this.context.fetchResource(StructureDefinition.class, actualType);
|
// this only happens when the profile constrains the abstract children but leaves th choice open.
|
||||||
else
|
if (actualType == null)
|
||||||
dt = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + actualType);
|
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
||||||
if (dt == null)
|
List<ElementDefinition> typeChildDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
||||||
throw new DefinitionException("Unable to resolve actual type " + actualType);
|
// what were going to do is merge them - the type is not allowed to constrain things that the child definitions already do (well, if it does, it'll be ignored)
|
||||||
trackUsage(dt, hostContext, element);
|
mergeChildLists(childDefinitions, typeChildDefinitions, definition.getPath(), actualType);
|
||||||
|
|
||||||
childDefinitions = ProfileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ElementInfo> children = listChildren(element, stack);
|
List<ElementInfo> children = listChildren(element, stack);
|
||||||
|
@ -4654,6 +4775,39 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mergeChildLists(List<ElementDefinition> master, List<ElementDefinition> additional, String masterPath, String typePath) {
|
||||||
|
for (ElementDefinition ed : additional) {
|
||||||
|
boolean inMaster = false;
|
||||||
|
for (ElementDefinition t : master) {
|
||||||
|
String tp = masterPath + ed.getPath().substring(typePath.length());
|
||||||
|
if (t.getPath().equals(tp)) {
|
||||||
|
inMaster = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inMaster) {
|
||||||
|
master.add(ed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: the element definition in context might assign a constrained profile for the type?
|
||||||
|
public List<ElementDefinition> getActualTypeChildren(ValidatorHostContext hostContext, Element element, String actualType) {
|
||||||
|
List<ElementDefinition> childDefinitions;
|
||||||
|
StructureDefinition dt = null;
|
||||||
|
if (isAbsolute(actualType))
|
||||||
|
dt = this.context.fetchResource(StructureDefinition.class, actualType);
|
||||||
|
else
|
||||||
|
dt = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + actualType);
|
||||||
|
if (dt == null)
|
||||||
|
throw new DefinitionException("Unable to resolve actual type " + actualType);
|
||||||
|
trackUsage(dt, hostContext, element);
|
||||||
|
|
||||||
|
childDefinitions = ProfileUtilities.getChildMap(dt, dt.getSnapshot().getElement().get(0));
|
||||||
|
return childDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
public void checkChild(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition,
|
public void checkChild(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition,
|
||||||
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl)
|
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext, ElementInfo ei, String extensionUrl)
|
||||||
throws FHIRException, DefinitionException {
|
throws FHIRException, DefinitionException {
|
||||||
|
@ -5018,7 +5172,10 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
|
|
||||||
// if (process) {
|
// if (process) {
|
||||||
for (ElementInfo ei : children) {
|
for (ElementInfo ei : children) {
|
||||||
unsupportedSlicing = matchSlice(hostContext, errors, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei);
|
if (ei.sliceInfo == null) {
|
||||||
|
ei.sliceInfo = new ArrayList<>();
|
||||||
|
}
|
||||||
|
unsupportedSlicing = matchSlice(hostContext, errors, ei.sliceInfo, profile, stack, slicer, unsupportedSlicing, problematicPaths, sliceOffset, i, ed, childUnsupportedSlicing, ei);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@ -5032,14 +5189,16 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
if (ei.additionalSlice && ei.definition != null) {
|
if (ei.additionalSlice && ei.definition != null) {
|
||||||
if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) ||
|
if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) ||
|
||||||
ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) {
|
ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) {
|
||||||
hint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for the profile " + profile.getUrl()));
|
slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()),
|
||||||
|
"This element does not match any known slice" + (profile == null ? "" : " defined in the profile " + profile.getUrl()+": "+errorSummaryForSlicingAsHtml(ei.sliceInfo)));
|
||||||
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
|
} else if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.CLOSED)) {
|
||||||
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice" + (profile == null ? "" : " for profile " + profile.getUrl() + " and slicing is CLOSED"));
|
rule(errors, IssueType.INVALID, ei.line(), ei.col(), ei.path, false, "This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicing(ei.sliceInfo)),
|
||||||
|
"This element does not match any known slice " + (profile == null ? "" : " defined in the profile " + profile.getUrl() + " and slicing is CLOSED: "+errorSummaryForSlicingAsHtml(ei.sliceInfo)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Don't raise this if we're in an abstract profile, like Resource
|
// Don't raise this if we're in an abstract profile, like Resource
|
||||||
if (!profile.getAbstract())
|
if (!profile.getAbstract())
|
||||||
hint(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "Could not verify slice for profile " + profile.getUrl());
|
rule(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.path, (ei.definition != null), "This element is not allowed by the profile "+profile.getUrl());
|
||||||
}
|
}
|
||||||
// TODO: Should get the order of elements correct when parsing elements that are XML attributes vs. elements
|
// TODO: Should get the order of elements correct when parsing elements that are XML attributes vs. elements
|
||||||
boolean isXmlAttr = false;
|
boolean isXmlAttr = false;
|
||||||
|
@ -5081,7 +5240,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element, onlyNonInherited);
|
checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element, onlyNonInherited);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matchSlice(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, NodeStack stack,
|
public boolean matchSlice(ValidatorHostContext hostContext, List<ValidationMessage> errors, List<ValidationMessage> sliceInfo, StructureDefinition profile, NodeStack stack,
|
||||||
ElementDefinition slicer, boolean unsupportedSlicing, List<String> problematicPaths, int sliceOffset, int i, ElementDefinition ed,
|
ElementDefinition slicer, boolean unsupportedSlicing, List<String> problematicPaths, int sliceOffset, int i, ElementDefinition ed,
|
||||||
boolean childUnsupportedSlicing, ElementInfo ei) {
|
boolean childUnsupportedSlicing, ElementInfo ei) {
|
||||||
boolean match = false;
|
boolean match = false;
|
||||||
|
@ -5090,7 +5249,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
} else {
|
} else {
|
||||||
if (nameMatches(ei.name, tail(ed.getPath())))
|
if (nameMatches(ei.name, tail(ed.getPath())))
|
||||||
try {
|
try {
|
||||||
match = sliceMatches(hostContext, ei.element, ei.path, slicer, ed, profile, errors, stack);
|
match = sliceMatches(hostContext, ei.element, ei.path, slicer, ed, profile, errors, sliceInfo, stack);
|
||||||
if (match) {
|
if (match) {
|
||||||
ei.slice = slicer;
|
ei.slice = slicer;
|
||||||
|
|
||||||
|
@ -5557,6 +5716,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
||||||
|
|
||||||
public class ElementInfo {
|
public class ElementInfo {
|
||||||
|
|
||||||
|
public List<ValidationMessage> sliceInfo;
|
||||||
public int index; // order of definition in overall order. all slices get the index of the slicing definition
|
public int index; // order of definition in overall order. all slices get the index of the slicing definition
|
||||||
public int sliceindex; // order of the definition in the slices (if slice != null)
|
public int sliceindex; // order of the definition in the slices (if slice != null)
|
||||||
public int count;
|
public int count;
|
||||||
|
|
|
@ -241,6 +241,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
private boolean debug;
|
private boolean debug;
|
||||||
private Set<String> loadedIgs = new HashSet<>();
|
private Set<String> loadedIgs = new HashSet<>();
|
||||||
private IValidatorResourceFetcher fetcher;
|
private IValidatorResourceFetcher fetcher;
|
||||||
|
private boolean assumeValidRestReferences;
|
||||||
|
|
||||||
private class AsteriskFilter implements FilenameFilter {
|
private class AsteriskFilter implements FilenameFilter {
|
||||||
String dir;
|
String dir;
|
||||||
|
@ -432,7 +433,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
return fetchFromUrl(src+(v == null ? "" : "|"+v), explore);
|
return fetchFromUrl(src+(v == null ? "" : "|"+v), explore);
|
||||||
}
|
}
|
||||||
|
|
||||||
File f = new File(src);
|
File f = new File(Utilities.path(src));
|
||||||
if (f.exists()) {
|
if (f.exists()) {
|
||||||
if (f.isDirectory() && new File(Utilities.path(src, "package.tgz")).exists())
|
if (f.isDirectory() && new File(Utilities.path(src, "package.tgz")).exists())
|
||||||
return loadPackage(new FileInputStream(Utilities.path(src, "package.tgz")), Utilities.path(src, "package.tgz"));
|
return loadPackage(new FileInputStream(Utilities.path(src, "package.tgz")), Utilities.path(src, "package.tgz"));
|
||||||
|
@ -760,8 +761,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
System.out.print("* load file: "+fn);
|
System.out.print("* load file: "+fn);
|
||||||
}
|
}
|
||||||
System.out.println(" - ignored due to error: "+(e.getMessage() == null ? " (null - NPE)" : e.getMessage()));
|
System.out.println(" - ignored due to error: "+(e.getMessage() == null ? " (null - NPE)" : e.getMessage()));
|
||||||
if (debug)
|
if (debug || ((e.getMessage() != null && e.getMessage().contains("cannot be cast")))) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1270,6 +1272,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
||||||
validator.setNoInvariantChecks(isNoInvariantChecks());
|
validator.setNoInvariantChecks(isNoInvariantChecks());
|
||||||
validator.setValidationLanguage(language);
|
validator.setValidationLanguage(language);
|
||||||
|
validator.setAssumeValidRestReferences(assumeValidRestReferences);
|
||||||
validator.setFetcher(this);
|
validator.setFetcher(this);
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
@ -1689,6 +1692,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
this.fetcher = fetcher;
|
this.fetcher = fetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAssumeValidRestReferences(boolean assumeValidRestReferences) {
|
||||||
|
this.assumeValidRestReferences = assumeValidRestReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,8 @@ public class Validator {
|
||||||
System.out.println(" referenced implementation guides or profiles as errors. (Default is to only raise information messages.)");
|
System.out.println(" referenced implementation guides or profiles as errors. (Default is to only raise information messages.)");
|
||||||
System.out.println("-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not");
|
System.out.println("-hintAboutNonMustSupport: If present, raise hints if the instance contains data elements that are not");
|
||||||
System.out.println(" marked as mustSupport=true. Useful to identify elements included that may be ignored by recipients");
|
System.out.println(" marked as mustSupport=true. Useful to identify elements included that may be ignored by recipients");
|
||||||
|
System.out.println("-assumeValidRestReferences: If present, assume that URLs that reference resources follow the RESTful URI pattern");
|
||||||
|
System.out.println(" and it is safe to infer the type from the URL");
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
System.out.println("The validator also supports the param -proxy=[address]:[port] for if you use a proxy");
|
System.out.println("The validator also supports the param -proxy=[address]:[port] for if you use a proxy");
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
|
@ -414,6 +416,7 @@ public class Validator {
|
||||||
String fhirpath = null;
|
String fhirpath = null;
|
||||||
String snomedCT = "900000000000207008";
|
String snomedCT = "900000000000207008";
|
||||||
boolean doDebug = false;
|
boolean doDebug = false;
|
||||||
|
boolean assumeValidRestReferences = false;
|
||||||
|
|
||||||
// load the parameters - so order doesn't matter
|
// load the parameters - so order doesn't matter
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
@ -447,6 +450,8 @@ public class Validator {
|
||||||
questionnaires.add(args[++i]);
|
questionnaires.add(args[++i]);
|
||||||
} else if (args[i].equals("-native")) {
|
} else if (args[i].equals("-native")) {
|
||||||
doNative = true;
|
doNative = true;
|
||||||
|
} else if (args[i].equals("-assumeValidRestReferences")) {
|
||||||
|
assumeValidRestReferences = true;
|
||||||
} else if (args[i].equals("-debug")) {
|
} else if (args[i].equals("-debug")) {
|
||||||
doDebug = true;
|
doDebug = true;
|
||||||
} else if (args[i].equals("-sct")) {
|
} else if (args[i].equals("-sct")) {
|
||||||
|
@ -577,6 +582,7 @@ public class Validator {
|
||||||
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
|
||||||
validator.setLanguage(lang);
|
validator.setLanguage(lang);
|
||||||
validator.setSnomedExtension(snomedCT);
|
validator.setSnomedExtension(snomedCT);
|
||||||
|
validator.setAssumeValidRestReferences(assumeValidRestReferences);
|
||||||
|
|
||||||
IParser x;
|
IParser x;
|
||||||
if (output != null && output.endsWith(".json"))
|
if (output != null && output.endsWith(".json"))
|
||||||
|
|
|
@ -177,6 +177,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
||||||
} else {
|
} else {
|
||||||
val.setAllowExamples(true);
|
val.setAllowExamples(true);
|
||||||
}
|
}
|
||||||
|
val.setAssumeValidRestReferences(content.has("assumeValidRestReferences") ? content.get("assumeValidRestReferences").getAsBoolean() : false);
|
||||||
if (name.endsWith(".json"))
|
if (name.endsWith(".json"))
|
||||||
val.validate(null, errors, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON);
|
val.validate(null, errors, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON);
|
||||||
else
|
else
|
||||||
|
@ -200,6 +201,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
||||||
v = content.has("version") ? content.get("version").getAsString() : Constants.VERSION;
|
v = content.has("version") ? content.get("version").getAsString() : Constants.VERSION;
|
||||||
StructureDefinition sd = loadProfile(filename, contents, v, messages);
|
StructureDefinition sd = loadProfile(filename, contents, v, messages);
|
||||||
val.getContext().cacheResource(sd);
|
val.getContext().cacheResource(sd);
|
||||||
|
val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false);
|
||||||
List<ValidationMessage> errorsProfile = new ArrayList<ValidationMessage>();
|
List<ValidationMessage> errorsProfile = new ArrayList<ValidationMessage>();
|
||||||
if (name.endsWith(".json"))
|
if (name.endsWith(".json"))
|
||||||
val.validate(null, errorsProfile, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON, asSdList(sd));
|
val.validate(null, errorsProfile, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON, asSdList(sd));
|
||||||
|
|
4
pom.xml
4
pom.xml
|
@ -13,11 +13,11 @@
|
||||||
each other. It is fine to bump the point version of this POM without affecting
|
each other. It is fine to bump the point version of this POM without affecting
|
||||||
HAPI FHIR.
|
HAPI FHIR.
|
||||||
-->
|
-->
|
||||||
<version>4.1.54-SNAPSHOT</version>
|
<version>4.1.63-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hapi_fhir_version>4.1.0</hapi_fhir_version>
|
<hapi_fhir_version>4.1.0</hapi_fhir_version>
|
||||||
<validator_test_case_version>1.0.35-SNAPSHOT</validator_test_case_version>
|
<validator_test_case_version>1.0.42-SNAPSHOT</validator_test_case_version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>org.hl7.fhir.core</artifactId>
|
<artifactId>org.hl7.fhir.core</artifactId>
|
||||||
|
|
14
release.bat
14
release.bat
|
@ -1,7 +1,7 @@
|
||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
set oldver=4.1.53
|
set oldver=4.1.62
|
||||||
set newver=4.1.54
|
set newver=4.1.63
|
||||||
|
|
||||||
echo ..
|
echo ..
|
||||||
echo =====================================================================
|
echo =====================================================================
|
||||||
|
@ -11,7 +11,8 @@ echo ..
|
||||||
|
|
||||||
call mvn versions:set -DnewVersion=%newver%-SNAPSHOT
|
call mvn versions:set -DnewVersion=%newver%-SNAPSHOT
|
||||||
|
|
||||||
call git commit -a -m "Release new version"
|
call git commit -t v%newver% -a -m "Release new version %newver%"
|
||||||
|
|
||||||
call git push origin master
|
call git push origin master
|
||||||
call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\build" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 8
|
call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\build" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 8
|
||||||
call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\fhir-ig-publisher" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 2
|
call "C:\tools\fnr.exe" -dir "C:\work\org.hl7.fhir\fhir-ig-publisher" -fileMask "*.xml" -find "%oldver%-SNAPSHOT" -replace "%newver%-SNAPSHOT" -count 2
|
||||||
|
@ -22,6 +23,9 @@ IF %ERRORLEVEL% NEQ 0 (
|
||||||
GOTO DONE
|
GOTO DONE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
call "C:\tools\versionNotes.exe" -fileName C:\work\org.hl7.fhir\latest-ig-publisher\release-notes-validator.md -version %newver% -fileDest C:\temp\current-release-notes-validator.md -url https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar -maven https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=%newver%-SNAPSHOT&e=jar
|
||||||
|
|
||||||
|
|
||||||
copy org.hl7.fhir.validation.cli\target\org.hl7.fhir.validation.cli-%newver%-SNAPSHOT.jar ..\latest-ig-publisher\org.hl7.fhir.validator.jar
|
copy org.hl7.fhir.validation.cli\target\org.hl7.fhir.validation.cli-%newver%-SNAPSHOT.jar ..\latest-ig-publisher\org.hl7.fhir.validator.jar
|
||||||
cd ..\latest-ig-publisher
|
cd ..\latest-ig-publisher
|
||||||
call git commit -a -m "Release new version %newver%-SNAPSHOT"
|
call git commit -a -m "Release new version %newver%-SNAPSHOT"
|
||||||
|
@ -29,7 +33,9 @@ call git push origin master
|
||||||
cd ..\org.hl7.fhir.core
|
cd ..\org.hl7.fhir.core
|
||||||
|
|
||||||
call python c:\tools\zulip-api\zulip\zulip\send.py --stream committers/notification --subject "java core" -m "New Java Core v%newver%-SNAPSHOT released. New Validator at https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=%newver%-SNAPSHOT&e=jar, and also deployed at https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar" --config-file zuliprc
|
call python c:\tools\zulip-api\zulip\zulip\send.py --stream committers/notification --subject "java core" -m "New Java Core v%newver%-SNAPSHOT released. New Validator at https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=ca.uhn.hapi.fhir&a=org.hl7.fhir.validation.cli&v=%newver%-SNAPSHOT&e=jar, and also deployed at https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar" --config-file zuliprc
|
||||||
call python c:\tools\zulip-api\zulip\zulip\send.py --stream tooling/releases --subject "Validator" -m "New Validator @ https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.validator.jar (v%newver%)" --config-file zuliprc
|
call python c:\tools\zulip-api\zulip\zulip\send.py --stream tooling/releases --subject "Validator" --config-file zuliprc < C:\temp\current-release-notes-validator.md
|
||||||
|
|
||||||
|
del C:\temp\current-release-notes-validator.md
|
||||||
|
|
||||||
:DONE
|
:DONE
|
||||||
echo ===============================================================
|
echo ===============================================================
|
||||||
|
|
Loading…
Reference in New Issue