Work on #682 - Allow fewtching structure definitions by relative URL

This commit is contained in:
James Agnew 2017-07-12 17:05:43 -04:00
parent 0dacf8d82a
commit 1a6b3ea867
5 changed files with 388 additions and 324 deletions

View File

@ -7,6 +7,7 @@ import java.io.InputStreamReader;
import java.util.*; import java.util.*;
import org.apache.commons.io.Charsets; import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
@ -22,6 +23,10 @@ import ca.uhn.fhir.context.FhirContext;
public class DefaultProfileValidationSupport implements IValidationSupport { public class DefaultProfileValidationSupport implements IValidationSupport {
private static final String URL_PREFIX_VALUE_SET = "http://hl7.org/fhir/ValueSet/";
private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/";
private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class);
private Map<String, CodeSystem> myCodeSystems; private Map<String, CodeSystem> myCodeSystems;
@ -86,51 +91,28 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) { public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
Validate.notBlank(theUri, "theUri must not be null or blank"); Validate.notBlank(theUri, "theUri must not be null or blank");
if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) { if (theClass.equals(StructureDefinition.class)) {
return (T) fetchStructureDefinition(theContext, theUri); return (T) fetchStructureDefinition(theContext, theUri);
} }
if (theUri.startsWith("http://hl7.org/fhir/ValueSet/")) {
if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) {
return (T) fetchValueSet(theContext, theUri); return (T) fetchValueSet(theContext, theUri);
} }
// if (theUri.startsWith("http://hl7.org/fhir/ValueSet/")) {
// Map<String, ValueSet> defaultValueSets = myDefaultValueSets;
// if (defaultValueSets == null) {
// String path = theContext.getVersion().getPathToSchemaDefinitions().replace("/schema", "/valueset") + "/valuesets.xml";
// InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(path);
// if (valuesetText == null) {
// return null;
// }
// InputStreamReader reader;
// try {
// reader = new InputStreamReader(valuesetText, "UTF-8");
// } catch (UnsupportedEncodingException e) {
// // Shouldn't happen!
// throw new InternalErrorException("UTF-8 encoding not supported on this platform", e);
// }
//
// defaultValueSets = new HashMap<String, ValueSet>();
//
// Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
// for (BundleEntryComponent next : bundle.getEntry()) {
// IdType nextId = new IdType(next.getFullUrl());
// if (nextId.isEmpty() || !nextId.getValue().startsWith("http://hl7.org/fhir/ValueSet/")) {
// continue;
// }
// defaultValueSets.put(nextId.toVersionless().getValue(), (ValueSet) next.getResource());
// }
//
// myDefaultValueSets = defaultValueSets;
// }
//
// return (T) defaultValueSets.get(theUri);
// }
return null; return null;
} }
@Override @Override
public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) { public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) {
return provideStructureDefinitionMap(theContext).get(theUrl); String url = theUrl;
if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
// no change
} else if (url.indexOf('/') == -1) {
url = URL_PREFIX_STRUCTURE_DEFINITION + url;
} else if (StringUtils.countMatches(url, '/') == 1) {
url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url;
}
return provideStructureDefinitionMap(theContext).get(url);
} }
ValueSet fetchValueSet(FhirContext theContext, String theSystem) { ValueSet fetchValueSet(FhirContext theContext, String theSystem) {

View File

@ -1,14 +1,14 @@
package org.hl7.fhir.dstu3.hapi.validation; package org.hl7.fhir.dstu3.hapi.validation;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -21,112 +21,154 @@ import ca.uhn.fhir.context.FhirContext;
*/ */
public class PrePopulatedValidationSupport implements IValidationSupport { public class PrePopulatedValidationSupport implements IValidationSupport {
private Map<String, StructureDefinition> myStructureDefinitions; private Map<String, CodeSystem> myCodeSystems;
private Map<String, ValueSet> myValueSets; private Map<String, StructureDefinition> myStructureDefinitions;
private Map<String, CodeSystem> myCodeSystems; private Map<String, ValueSet> myValueSets;
/** /**
* Constructor * Constructor
*/ */
public PrePopulatedValidationSupport() { public PrePopulatedValidationSupport() {
myStructureDefinitions = new HashMap<String,StructureDefinition>(); myStructureDefinitions = new HashMap<String, StructureDefinition>();
myValueSets = new HashMap<String,ValueSet>(); myValueSets = new HashMap<String, ValueSet>();
myCodeSystems = new HashMap<String,CodeSystem>(); myCodeSystems = new HashMap<String, CodeSystem>();
} }
/**
* Constructor
*
* @param theStructureDefinitions
* The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and
* values are the resource itself.
* @param theValueSets
* The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are
* the resource itself.
* @param theCodeSystems
* The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are
* the resource itself.
*/
public PrePopulatedValidationSupport(Map<String, StructureDefinition> theStructureDefinitions, Map<String, ValueSet> theValueSets, Map<String, CodeSystem> theCodeSystems) {
myStructureDefinitions = theStructureDefinitions;
myValueSets = theValueSets;
myCodeSystems = theCodeSystems;
}
/** /**
* Add a new StructureDefinition resource which will be available to the validator. Note that * Add a new CodeSystem resource which will be available to the validator. Note that
* {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this * {@link CodeSystem#getUrl() the URL field) in this resource must contain a value as this
* value will be used as the logical URL. * value will be used as the logical URL.
*/ * <p>
public void addStructureDefinition(StructureDefinition theStructureDefinition) { * Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value"); * it will be stored in three ways:
myStructureDefinitions.put(theStructureDefinition.getUrl(), theStructureDefinition); * <ul>
} * <li>Extension</li>
* <li>StructureDefinition/Extension</li>
* <li>http://hl7.org/StructureDefinition/Extension</li>
* </ul>
* </p>
*/
public void addCodeSystem(CodeSystem theCodeSystem) {
Validate.notBlank(theCodeSystem.getUrl(), "theCodeSystem.getUrl() must not return a value");
addToMap(theCodeSystem, myCodeSystems, theCodeSystem.getUrl());
}
/** /**
* Add a new ValueSet resource which will be available to the validator. Note that * Add a new StructureDefinition resource which will be available to the validator. Note that
* {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this * {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this
* value will be used as the logical URL. * value will be used as the logical URL.
*/ * <p>
public void addValueSet(ValueSet theValueSet) { * Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value"); * it will be stored in three ways:
myValueSets.put(theValueSet.getUrl(), theValueSet); * <ul>
} * <li>Extension</li>
* <li>StructureDefinition/Extension</li>
* <li>http://hl7.org/StructureDefinition/Extension</li>
* </ul>
* </p>
*/
public void addStructureDefinition(StructureDefinition theStructureDefinition) {
Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value");
addToMap(theStructureDefinition, myStructureDefinitions, theStructureDefinition.getUrl());
}
/** private <T extends MetadataResource> void addToMap(T theStructureDefinition, Map<String, T> map, String theUrl) {
* Add a new CodeSystem resource which will be available to the validator. Note that if (isNotBlank(theUrl)) {
* {@link CodeSystem#getUrl() the URL field) in this resource must contain a value as this map.put(theUrl, theStructureDefinition);
* value will be used as the logical URL.
*/
public void addCodeSystem(CodeSystem theCodeSystem) {
Validate.notBlank(theCodeSystem.getUrl(), "theCodeSystem.getUrl() must not return a value");
myCodeSystems.put(theCodeSystem.getUrl(), theCodeSystem);
}
/** int lastSlashIdx = theUrl.lastIndexOf('/');
* Constructor if (lastSlashIdx != -1) {
* map.put(theUrl.substring(lastSlashIdx + 1), theStructureDefinition);
* @param theStructureDefinitions int previousSlashIdx = theUrl.lastIndexOf('/', lastSlashIdx - 1);
* The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and if (previousSlashIdx != -1) {
* values are the resource itself. map.put(theUrl.substring(previousSlashIdx + 1), theStructureDefinition);
* @param theValueSets }
* The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are }
* the resource itself.
* @param theCodeSystems
* The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are
* the resource itself.
*/
public PrePopulatedValidationSupport(Map<String, StructureDefinition> theStructureDefinitions, Map<String, ValueSet> theValueSets, Map<String, CodeSystem> theCodeSystems) {
myStructureDefinitions = theStructureDefinitions;
myValueSets = theValueSets;
myCodeSystems = theCodeSystems;
}
@Override }
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) { }
return null;
}
@Override /**
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) { * Add a new ValueSet resource which will be available to the validator. Note that
return new ArrayList<StructureDefinition>(myStructureDefinitions.values()); * {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this
} * value will be used as the logical URL.
* <p>
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
* it will be stored in three ways:
* <ul>
* <li>Extension</li>
* <li>StructureDefinition/Extension</li>
* <li>http://hl7.org/StructureDefinition/Extension</li>
* </ul>
* </p>
*/
public void addValueSet(ValueSet theValueSet) {
Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value");
addToMap(theValueSet, myValueSets, theValueSet.getUrl());
}
@Override @Override
public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
return myCodeSystems.get(theSystem); return null;
} }
@SuppressWarnings("unchecked") @Override
@Override public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) { return new ArrayList<StructureDefinition>(myStructureDefinitions.values());
if (theClass.equals(StructureDefinition.class)) { }
return (T) myStructureDefinitions.get(theUri);
}
if (theClass.equals(ValueSet.class)) {
return (T) myValueSets.get(theUri);
}
if (theClass.equals(CodeSystem.class)) {
return (T) myCodeSystems.get(theUri);
}
return null;
}
@Override @Override
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) {
return myStructureDefinitions.get(theUrl); return myCodeSystems.get(theSystem);
} }
@Override @SuppressWarnings("unchecked")
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) { @Override
return false; public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
} if (theClass.equals(StructureDefinition.class)) {
return (T) myStructureDefinitions.get(theUri);
}
if (theClass.equals(ValueSet.class)) {
return (T) myValueSets.get(theUri);
}
if (theClass.equals(CodeSystem.class)) {
return (T) myCodeSystems.get(theUri);
}
return null;
}
@Override @Override
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
return null; return myStructureDefinitions.get(theUrl);
} }
@Override
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
return false;
}
@Override
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
return null;
}
} }

View File

@ -0,0 +1,34 @@
package org.hl7.fhir.dstu3.hapi.validation;
import static org.junit.Assert.*;
import org.junit.AfterClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
public class DefaultProfileValidationSupportTest {
private DefaultProfileValidationSupport mySvc = new DefaultProfileValidationSupport();
private static FhirContext ourCtx = FhirContext.forDstu3();
@Test
public void testGetStructureDefinitionsWithRelativeUrls() {
assertNotNull(mySvc.fetchStructureDefinition(ourCtx, "http://hl7.org/fhir/StructureDefinition/Extension"));
assertNotNull(mySvc.fetchStructureDefinition(ourCtx, "StructureDefinition/Extension"));
assertNotNull(mySvc.fetchStructureDefinition(ourCtx, "Extension"));
assertNull(mySvc.fetchStructureDefinition(ourCtx, "http://hl7.org/fhir/StructureDefinition/Extension2"));
assertNull(mySvc.fetchStructureDefinition(ourCtx, "StructureDefinition/Extension2"));
assertNull(mySvc.fetchStructureDefinition(ourCtx, "Extension2"));
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
}

View File

@ -1,4 +1,4 @@
package org.hl7.fhir.dstu3.validation; package org.hl7.fhir.dstu3.hapi.validation;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -7,24 +7,19 @@ import java.util.*;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.hl7.fhir.dstu3.context.IWorkerContext; import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.*;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.utils.StructureMapUtilities; import org.hl7.fhir.dstu3.utils.StructureMapUtilities;
import org.junit.*; import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
public class StructureMapTests2 { public class StructureMapTest {
/**
* path to the files used to test the profile generator.
*/
String resourcePath = null;
/** /**
* The logger object. * The logger object.
*/ */
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StructureMapTests2.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StructureMapTest.class);
/** /**
* The basic fhir context used to parse structure definitions. * The basic fhir context used to parse structure definitions.
@ -36,141 +31,60 @@ public class StructureMapTests2 {
*/ */
IWorkerContext hapiContext; IWorkerContext hapiContext;
/**
* path to the files used to test the profile generator.
*/
String resourcePath = null;
/** /**
* Used to validate definitions as well as add new structure definitions to a registry. * Used to validate definitions as well as add new structure definitions to a registry.
*/ */
PrePopulatedValidationSupport validationSupport; PrePopulatedValidationSupport validationSupport;
/** public StructureMap.StructureMapGroupRuleSourceComponent buildSource(String context, @Nullable String element, @Nullable String variable, @Nullable String type, @Nullable Integer min,
* Sets up the resource paths as well as create the contexts using a defalut validator to start with. @Nullable String max) {
* StructureMap.StructureMapGroupRuleSourceComponent retVal = new StructureMap.StructureMapGroupRuleSourceComponent();
* @throws Exception retVal.setContext(context);
*/ if (element != null)
@Before retVal.setElement(element);
public void setUp() throws Exception { if (variable != null)
// resourcePath = getFileFromURL().getParent(); retVal.setVariable(variable);
if (this.context == null) if (type != null)
this.context = FhirContext.forDstu3(); retVal.setType(type);
if (min != null)
retVal.setMin(min);
if (max != null)
retVal.setMax(max);
return retVal;
} }
/** public List<StructureMap.StructureMapGroupRuleSourceComponent> buildSourceList(StructureMap.StructureMapGroupRuleSourceComponent[] sources) {
* See #682 List<StructureMap.StructureMapGroupRuleSourceComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleSourceComponent>();
*/ retVal.addAll(Arrays.asList(sources));
@Test return retVal;
@Ignore }
public void testMappingTransform() throws Exception {
Map<String, StructureMap> maps = new HashMap<String, StructureMap>(); // Instantiate a hashmap for StructureMaps public StructureMap.StructureMapGroupRuleTargetComponent buildTarget(@Nullable String context, @Nullable String element, @Nullable String variable,
this.validationSupport = new PrePopulatedValidationSupport(); // Create Validation Instance @Nullable StructureMap.StructureMapTransform transform, @Nullable TargetParam[] params) throws Exception {
for (StructureDefinition sd : new DefaultProfileValidationSupport().fetchAllStructureDefinitions(this.context)) { // Read in the default Structure Definitions into a validator that allows custom StructureMap.StructureMapGroupRuleTargetComponent retVal = new StructureMap.StructureMapGroupRuleTargetComponent();
// declared structure definitions. if (context != null)
this.validationSupport.addStructureDefinition(sd); retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (transform != null)
retVal.setTransform(transform);
if (params != null) {
if (params.length > 0)
retVal.setParameter(this.constructParameters(params));
} }
StructureDefinition sd1 = this.createTestStructure(); // Calls a method that constructs a comp
this.validationSupport.addStructureDefinition(sd1); // Add custom structure to validation support.
this.hapiContext = new HapiWorkerContext(this.context, this.validationSupport);// Init the Hapi Work
StructureMap map = this.createTestStructuremap();
maps.put(map.getUrl(), map);
StructureMapUtilities scu = new StructureMapUtilities(hapiContext, maps, null, null);
List<StructureDefinition> result = scu.analyse(null, map).getProfiles();
assertEquals(1, result.size());
ourLog.info(context.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.get(0)));
}
public StructureDefinition createTestStructure() {
StructureDefinition sd = new StructureDefinition();
sd.setId("TestStructure");
sd.setUrl("http://opencimi.org/structuredefinition/TestStructure");
sd.setStatus(Enumerations.PublicationStatus.DRAFT);
sd.setName("TestStructure");
sd.setType("TestStructure");
sd.setSnapshot(this.createTestSnapshot());
sd.setDifferential(this.createTestDiff());
sd.setKind(StructureDefinition.StructureDefinitionKind.LOGICAL);
return sd;
}
public StructureDefinition.StructureDefinitionSnapshotComponent createTestSnapshot() {
StructureDefinition.StructureDefinitionSnapshotComponent retVal = new StructureDefinition.StructureDefinitionSnapshotComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
ed.setMin(1);
ed.setMax("1");
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition.StructureDefinitionDifferentialComponent createTestDiff() {
StructureDefinition.StructureDefinitionDifferentialComponent retVal = new StructureDefinition.StructureDefinitionDifferentialComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
eList.add(ed);
retVal.setElement(eList);
return retVal; return retVal;
} }
public StructureMap createTestStructuremap() throws Exception { public List<StructureMap.StructureMapGroupRuleTargetComponent> buildTargetList(StructureMap.StructureMapGroupRuleTargetComponent[] sources) {
StructureMap retMap = new StructureMap(); List<StructureMap.StructureMapGroupRuleTargetComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleTargetComponent>();
retMap.setUrl("http://opencimi.org/structuremap/testtransform"); retVal.addAll(Arrays.asList(sources));
retMap.setName("TestTransform");
retMap.setStatus(Enumerations.PublicationStatus.DRAFT);
retMap.setStructure(this.createMapStructureList());
retMap.setGroup(this.buildTestGroup());
return retMap;
}
public List<StructureMap.StructureMapStructureComponent> createMapStructureList() {
List<StructureMap.StructureMapStructureComponent> retVal = new ArrayList<StructureMap.StructureMapStructureComponent>();
StructureMap.StructureMapStructureComponent source = new StructureMap.StructureMapStructureComponent();
StructureMap.StructureMapStructureComponent target = new StructureMap.StructureMapStructureComponent();
source.setUrl("http://opencimi.org/structuredefinition/TestStructure");
source.setMode(StructureMap.StructureMapModelMode.SOURCE);
target.setUrl("http://hl7.org/fhir/StructureDefinition/Coding");
target.setMode(StructureMap.StructureMapModelMode.TARGET);
retVal.add(source);
retVal.add(target);
return retVal; return retVal;
} }
@ -225,53 +139,6 @@ public class StructureMapTests2 {
return retVal; return retVal;
} }
public List<StructureMap.StructureMapGroupRuleSourceComponent> buildSourceList(StructureMap.StructureMapGroupRuleSourceComponent[] sources) {
List<StructureMap.StructureMapGroupRuleSourceComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleSourceComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public StructureMap.StructureMapGroupRuleSourceComponent buildSource(String context, @Nullable String element, @Nullable String variable, @Nullable String type, @Nullable Integer min,
@Nullable String max) {
StructureMap.StructureMapGroupRuleSourceComponent retVal = new StructureMap.StructureMapGroupRuleSourceComponent();
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (type != null)
retVal.setType(type);
if (min != null)
retVal.setMin(min);
if (max != null)
retVal.setMax(max);
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetComponent> buildTargetList(StructureMap.StructureMapGroupRuleTargetComponent[] sources) {
List<StructureMap.StructureMapGroupRuleTargetComponent> retVal = new ArrayList<StructureMap.StructureMapGroupRuleTargetComponent>();
retVal.addAll(Arrays.asList(sources));
return retVal;
}
public StructureMap.StructureMapGroupRuleTargetComponent buildTarget(@Nullable String context, @Nullable String element, @Nullable String variable,
@Nullable StructureMap.StructureMapTransform transform, @Nullable TargetParam[] params) throws Exception {
StructureMap.StructureMapGroupRuleTargetComponent retVal = new StructureMap.StructureMapGroupRuleTargetComponent();
if (context != null)
retVal.setContext(context);
if (element != null)
retVal.setElement(element);
if (variable != null)
retVal.setVariable(variable);
if (transform != null)
retVal.setTransform(transform);
if (params != null) {
if (params.length > 0)
retVal.setParameter(this.constructParameters(params));
}
return retVal;
}
public List<StructureMap.StructureMapGroupRuleTargetParameterComponent> constructParameters(TargetParam[] params) throws Exception { public List<StructureMap.StructureMapGroupRuleTargetParameterComponent> constructParameters(TargetParam[] params) throws Exception {
List<StructureMap.StructureMapGroupRuleTargetParameterComponent> parameterComponents = new ArrayList<StructureMap.StructureMapGroupRuleTargetParameterComponent>(); List<StructureMap.StructureMapGroupRuleTargetParameterComponent> parameterComponents = new ArrayList<StructureMap.StructureMapGroupRuleTargetParameterComponent>();
for (TargetParam tp : params) { for (TargetParam tp : params) {
@ -293,29 +160,161 @@ public class StructureMapTests2 {
return parameterComponents; return parameterComponents;
} }
public List<StructureMap.StructureMapStructureComponent> createMapStructureList() {
List<StructureMap.StructureMapStructureComponent> retVal = new ArrayList<StructureMap.StructureMapStructureComponent>();
StructureMap.StructureMapStructureComponent source = new StructureMap.StructureMapStructureComponent();
StructureMap.StructureMapStructureComponent target = new StructureMap.StructureMapStructureComponent();
source.setUrl("http://opencimi.org/structuredefinition/TestStructure");
source.setMode(StructureMap.StructureMapModelMode.SOURCE);
target.setUrl("http://hl7.org/fhir/StructureDefinition/Coding");
target.setMode(StructureMap.StructureMapModelMode.TARGET);
retVal.add(source);
retVal.add(target);
return retVal;
}
public StructureDefinition.StructureDefinitionDifferentialComponent createTestDiff() {
StructureDefinition.StructureDefinitionDifferentialComponent retVal = new StructureDefinition.StructureDefinitionDifferentialComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition.StructureDefinitionSnapshotComponent createTestSnapshot() {
StructureDefinition.StructureDefinitionSnapshotComponent retVal = new StructureDefinition.StructureDefinitionSnapshotComponent();
List<ElementDefinition> eList = new ArrayList<ElementDefinition>();
ElementDefinition ed0 = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed0.setId("TestStructure");
ed0.setSliceName("TestStructure");
ed0.setPath("TestStructure");
// ed0.setBase(base);
ed0.setMin(1);
ed0.setMax("1");
eList.add(ed0);
ElementDefinition ed = new ElementDefinition();
// ElementDefinition.ElementDefinitionBaseComponent base = new ElementDefinition.ElementDefinitionBaseComponent();
// base.setId("http://hl7.org/fhir/StructureDefinition/Element");
ed.setId("system");
ed.setSliceName("system");
ed.setPath("TestStructure.system");
// ed.setBase(base);
ed.setFixed(new UriType().setValue("HTTP://opencimi.org/structuredefinition/TestStructure.html#Debugging"));
// ed.setType(this.createTypeRefList());
ed.setMin(1);
ed.setMax("1");
eList.add(ed);
retVal.setElement(eList);
return retVal;
}
public StructureDefinition createTestStructure() {
StructureDefinition sd = new StructureDefinition();
sd.setId("TestStructure");
sd.setUrl("http://opencimi.org/structuredefinition/TestStructure");
sd.setStatus(Enumerations.PublicationStatus.DRAFT);
sd.setName("TestStructure");
sd.setType("TestStructure");
sd.setSnapshot(this.createTestSnapshot());
sd.setDifferential(this.createTestDiff());
sd.setKind(StructureDefinition.StructureDefinitionKind.LOGICAL);
return sd;
}
public StructureMap createTestStructuremap() throws Exception {
StructureMap retMap = new StructureMap();
retMap.setUrl("http://opencimi.org/structuremap/testtransform");
retMap.setName("TestTransform");
retMap.setStatus(Enumerations.PublicationStatus.DRAFT);
retMap.setStructure(this.createMapStructureList());
retMap.setGroup(this.buildTestGroup());
return retMap;
}
/**
* Sets up the resource paths as well as create the contexts using a defalut validator to start with.
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
if (this.context == null) {
this.context = FhirContext.forDstu3();
}
}
/**
* See #682
*/
@Test
public void testMappingTransform() throws Exception {
Map<String, StructureMap> maps = new HashMap<String, StructureMap>(); // Instantiate a hashmap for StructureMaps
this.validationSupport = new PrePopulatedValidationSupport(); // Create Validation Instance
for (StructureDefinition sd : new DefaultProfileValidationSupport().fetchAllStructureDefinitions(this.context)) { // Read in the default Structure Definitions into a validator that allows custom
// declared structure definitions.
this.validationSupport.addStructureDefinition(sd);
}
StructureDefinition sd1 = this.createTestStructure(); // Calls a method that constructs a comp
this.validationSupport.addStructureDefinition(sd1); // Add custom structure to validation support.
this.hapiContext = new HapiWorkerContext(this.context, this.validationSupport);// Init the Hapi Work
StructureMap map = this.createTestStructuremap();
maps.put(map.getUrl(), map);
StructureMapUtilities scu = new StructureMapUtilities(hapiContext, maps, null, null);
List<StructureDefinition> result = scu.analyse(null, map).getProfiles();
assertEquals(1, result.size());
ourLog.info(context.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.get(0)));
}
public class TargetParam { public class TargetParam {
private String type;
private String value;
public TargetParam(String type, String value) { public TargetParam(String type, String value) {
this.type = type; this.type = type;
this.value = value; this.value = value;
} }
private String type;
private String value;
public String getType() { public String getType() {
return type; return type;
} }
public void setType(String type) {
this.type = type;
}
public String getValue() { public String getValue() {
return value; return value;
} }
public void setType(String type) {
this.type = type;
}
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }

View File

@ -149,6 +149,13 @@
AuthorizationInterceptor did not permit PATCH operations to proceed even AuthorizationInterceptor did not permit PATCH operations to proceed even
if the user had write access for the resource being patched. if the user had write access for the resource being patched.
</action> </action>
<action type="fix" issue="682">
Fix an issue in HapiWorkerContext where structure definitions are
not able to be retrieved if they are referred to by their
relative or logical ID. This affects profile tooling such as
StructureMapUtilities. Thanks to Travis Lukach for reporting and
providing a test case!
</action>
</release> </release>
<release version="2.5" date="2017-06-08"> <release version="2.5" date="2017-06-08">
<action type="fix"> <action type="fix">