Extensions in generated profiles working again

This commit is contained in:
jamesagnew 2014-03-17 15:52:41 -04:00
parent d6e3750657
commit 55524e4e8a
12 changed files with 502 additions and 49 deletions

View File

@ -330,12 +330,12 @@ public abstract class BaseStructureParser {
String base = "/home/t3903uhn/workspace/uhn-fhir-service/"; String base = "/home/t3903uhn/workspace/uhn-fhir-service/";
TinderStructuresMojo m = new TinderStructuresMojo(); TinderStructuresMojo m = new TinderStructuresMojo();
m.setPackageName("ca.uhn.sailfhirmodel"); m.setPackageName("ca.uhn.sailfhirmodel");
m.setResourceProfileFiles(new ArrayList<String>()); // m.setResourceProfileFiles(new ArrayList<String>());
m.getResourceProfileFiles().add(base + "src/main/resources/profile/patient.xml"); // m.getResourceProfileFiles().add(base + "src/main/resources/profile/patient.xml");
m.getResourceProfileFiles().add(base + "src/main/resources/profile/organization.xml"); // m.getResourceProfileFiles().add(base + "src/main/resources/profile/organization.xml");
m.setResourceValueSetFiles(new ArrayList<String>()); // m.setResourceValueSetFiles(new ArrayList<String>());
m.getResourceValueSetFiles().add(base + "src/main/resources/valueset/valueset-cgta-patientidpool.xml"); // m.getResourceValueSetFiles().add(base + "src/main/resources/valueset/valueset-cgta-patientidpool.xml");
m.getResourceValueSetFiles().add(base + "src/main/resources/valueset/valueset-cgta-provideridpool.xml"); // m.getResourceValueSetFiles().add(base + "src/main/resources/valueset/valueset-cgta-provideridpool.xml");
m.setTargetDirectory(base + "target/generated-sources/tinder"); m.setTargetDirectory(base + "target/generated-sources/tinder");
m.setBuildDatatypes(true); m.setBuildDatatypes(true);
m.execute(); m.execute();

View File

@ -0,0 +1,312 @@
package ca.uhn.fhir.tinder;
import static org.apache.commons.lang.StringUtils.capitalize;
import static org.apache.commons.lang.StringUtils.isBlank;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.MojoFailureException;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu.resource.Profile;
import ca.uhn.fhir.model.dstu.resource.Profile.ExtensionDefn;
import ca.uhn.fhir.model.dstu.resource.Profile.Structure;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElement;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinition;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinitionType;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureSearchParam;
import ca.uhn.fhir.model.dstu.valueset.DataTypeEnum;
import ca.uhn.fhir.model.dstu.valueset.SlicingRulesEnum;
import ca.uhn.fhir.tinder.model.AnyChild;
import ca.uhn.fhir.tinder.model.BaseElement;
import ca.uhn.fhir.tinder.model.BaseRootType;
import ca.uhn.fhir.tinder.model.Child;
import ca.uhn.fhir.tinder.model.Extension;
import ca.uhn.fhir.tinder.model.Resource;
import ca.uhn.fhir.tinder.model.ResourceBlock;
import ca.uhn.fhir.tinder.model.SearchParameter;
import ca.uhn.fhir.tinder.model.SimpleChild;
import ca.uhn.fhir.tinder.model.Slicing;
public class CopyOfProfileParser extends BaseStructureParser {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CopyOfProfileParser.class);
private ExtensionDefn findExtension(Profile theProfile, String theCode) {
for (ExtensionDefn next : theProfile.getExtensionDefn()) {
if (theCode.equals(next.getCode().getValue())) {
return next;
}
}
return null;
}
@Override
protected String getFilenameSuffix() {
return "";
}
@Override
protected String getTemplate() {
return "/vm/resource.vm";
}
public void parseBaseResources(List<String> theBaseResourceNames) throws MojoFailureException {
FhirContext fhirContext = new FhirContext(Profile.class);
for (String nextFileName : theBaseResourceNames) {
ourLog.info("Parsing file: {}", nextFileName);
Profile profile;
try {
profile = (Profile) fhirContext.newXmlParser().parseResource(IOUtils.toString(new FileReader(nextFileName)));
} catch (Exception e) {
throw new MojoFailureException("Failed to load or parse file: " + nextFileName, e);
}
try {
parseSingleProfile(profile, "");
} catch (Exception e) {
throw new MojoFailureException("Failed to process file: " + nextFileName, e);
}
}
// for (int i = 0; i < theBaseResourceNames.size(); i++) {
// theBaseResourceNames.set(i,
// theBaseResourceNames.get(i).toLowerCase());
// }
//
// try {
//
// Bundle bundle =
// fhirContext.newXmlParser().parseBundle(IOUtils.toString(getClass().getResourceAsStream("/prof/allprofiles.xml")));
// TreeSet<String> allProfiles = new TreeSet<String>();
// for (BundleEntry nextResource : bundle.getEntries() ) {
// Profile nextProfile = (Profile) nextResource.getResource();
// allProfiles.add(nextProfile.getName().getValue());
// if
// (theBaseResourceNames.contains(nextProfile.getName().getValue().toLowerCase())){
// parseSingleProfile(nextProfile,
// bundle.getLinkBase().getValueNotNull());
// }
// }
//
// ourLog.info("Base profiles found: {}", allProfiles);
//
// } catch (Exception e) {
// throw new MojoFailureException("Failed to load base resources", e);
// }
}
public BaseRootType parseSingleProfile(Profile theProfile, String theUrlTOThisProfile) throws Exception {
BaseRootType retVal = null;
for (Structure nextStructure : theProfile.getStructure()) {
int elemIdx = 0;
boolean extensionsSliced = false;
SlicingRulesEnum extensionsSlicingIsOpen = SlicingRulesEnum.OPEN;
Map<String, BaseElement> elements = new HashMap<String, BaseElement>();
for (StructureElement next : nextStructure.getElement()) {
BaseElement elem;
if (elemIdx == 0) {
retVal = new Resource();
retVal.setProfile(theProfile.getIdentifier().getValue());
if (retVal.getProfile() == null) {
retVal.setProfile(theUrlTOThisProfile);
}
for (StructureSearchParam nextParam : nextStructure.getSearchParam()) {
SearchParameter param = new SearchParameter();
param.setName(nextParam.getName().getValue());
param.setPath(nextParam.getXpath().getValue());
param.setType(nextParam.getType().getValue());
param.setDescription(nextParam.getDocumentation().getValue());
retVal.getSearchParameters().add(param);
}
addResource(retVal);
elem = retVal;
// below StringUtils.isBlank(type) || type.startsWith("=")
} else {
if (next.getDefinition().getType().size() > 0 && next.getDefinition().getType().get(0).getCode().getValue().equals("Extension")) {
if (!next.getSlicing().isEmpty()) {
if (!"url".equals(next.getSlicing().getDiscriminator().getValue())) {
throw new ConfigurationException("Invalid extension slicing discriminator (must be 'url'): " + next.getSlicing().getDiscriminator().getValue());
}
extensionsSliced = true;
if (StringUtils.isNotBlank(next.getSlicing().getRules().getValueAsString())) {
extensionsSlicingIsOpen = next.getSlicing().getRules().getValueAsEnum();
if (extensionsSlicingIsOpen == null) {
throw new ConfigurationException("Invalid extension slicing rules: " + next.getSlicing().getRules().getValueAsString());
}
}
continue;
} else {
if (!extensionsSliced) {
continue;
}
if (next.getDefinition().getType().size() != 1) {
throw new ConfigurationException("Extension definition '" + next.getName().getValue() + "' has multiple type blocks. This is not supported.");
}
String extUrl = next.getDefinition().getType().get(0).getProfile().getValueAsString();
elem = new Extension(next.getName().getValue(), extUrl, "CodeDt");
}
} else {
if (next.getDefinition().getType().isEmpty()) {
elem = new ResourceBlock();
// } else if (type.startsWith("@")) {
// elem = new ResourceBlockCopy();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("*")) {
elem = new AnyChild();
} else {
elem = new SimpleChild();
}
}
}
elem.setName(next.getPath().getValue());
elem.setElementNameAndDeriveParentElementName(next.getPath().getValue());
boolean allResourceReferences = next.getDefinition().getType().size() > 0;
for (StructureElementDefinitionType nextType : next.getDefinition().getType()) {
if (nextType.getCode().getValueAsEnum() != DataTypeEnum.RESOURCEREFERENCE) {
allResourceReferences = false;
}
}
elem.setResourceRef(allResourceReferences);
StructureElementDefinition definition = next.getDefinition();
BaseElement parentElement = elements.get(elem.getElementParentName());
Slicing childIsSliced = parentElement != null ? parentElement.getChildElementNameToSlicing().get(elem.getName()) : null;
if (next.getSlicing().getDiscriminator().getValue() != null) {
Slicing slicing = new Slicing();
slicing.setDiscriminator(next.getSlicing().getDiscriminator().getValue());
if (parentElement.getChildElementNameToSlicing().get(elem.getName()) != null) {
throw new ConfigurationException("Found multiple slicing definitions for path: " + next.getPath().getValue());
}
parentElement.getChildElementNameToSlicing().put(elem.getName(), slicing);
continue;
}
/*
* Profiles come with a number of standard elements which are generally ignored because they are boilerplate, unless the definition is somehow changing their behaviour (e.g. through
* slices)
*/
if (next.getPath().getValue().endsWith(".contained")) {
continue;
}
if (next.getPath().getValue().endsWith(".text")) {
continue;
}
if (next.getPath().getValue().endsWith(".extension")) {
if (childIsSliced != null) {
if (!"url".equals(childIsSliced.getDiscriminator())) {
throw new ConfigurationException("Extensions must be sliced on 'url' discriminator. Found: " + next.getSlicing().getDiscriminator().getValue());
}
if (next.getDefinition().getType().size() != 1 || next.getDefinition().getType().get(0).getCode().getValueAsEnum() != DataTypeEnum.EXTENSION) {
throw new ConfigurationException("Extension slices must have a single type with a code of 'Extension'");
}
String name = next.getName().getValue();
if (StringUtils.isBlank(name)) {
throw new ConfigurationException("Extension slices must have a 'name' defined, none found at path: " + next.getPath());
}
elem.setName(name);
elem.setElementName(name);
String profile = next.getDefinition().getType().get(0).getProfile().getValueAsString();
if (isBlank(profile)) {
throw new ConfigurationException("Extension slice for " + next.getPath().getValue() + " has no profile specified in its type");
}
if (profile.startsWith("#")) {
Profile.ExtensionDefn extension = findExtension(theProfile, profile.substring(1));
if (extension == null) {
throw new ConfigurationException("Unknown local extension reference: " + profile);
}
ourLog.info("Element at path {} is using extension {}", next.getPath(), profile);
definition = extension.getDefinition();
String extensionUrl = theUrlTOThisProfile + profile;
elem.setExtensionUrl(extensionUrl);
} else {
// TODO: implement this
throw new ConfigurationException("Extensions specified outside of the given profile are not yet supported");
}
} else {
continue;
}
}
if (next.getPath().getValue().endsWith(".modifierExtension")) {
continue;
}
for (StructureElementDefinitionType nextType : definition.getType()) {
if (nextType.getCode().getValueAsEnum() == DataTypeEnum.RESOURCEREFERENCE) {
if (nextType.getProfile().getValueAsString().startsWith("http://hl7.org/fhir/profiles/")) {
elem.getType().add(capitalize(nextType.getProfile().getValueAsString().substring("http://hl7.org/fhir/profiles/".length())));
} else {
// TODO: implement this.. we need to be able to
// reference other profiles
throw new ConfigurationException("Profile type not yet supported");
}
} else {
elem.getType().add(capitalize(nextType.getCode().getValue()) + "Dt");
}
}
elem.setBinding(definition.getBinding().getName().getValue());
elem.setShortName(definition.getShort().getValue());
elem.setDefinition(definition.getFormal().getValue());
elem.setRequirement(definition.getRequirements().getValue());
elem.setCardMin(definition.getMin().getValueAsString());
elem.setCardMax(definition.getMax().getValue());
if (elem instanceof Child) {
Child child = (Child) elem;
elements.put(elem.getName(), elem);
if (parentElement == null) {
throw new Exception("Can't find element " + elem.getElementParentName() + " - Valid values are: " + elements.keySet());
}
parentElement.addChild(child);
/*
* Find simple setters
*/
scanForSimpleSetters(child);
} else {
BaseRootType res = (BaseRootType) elem;
elements.put(res.getName(), res);
}
elemIdx++;
}
}
return retVal;
}
public static void main(String[] args) throws Exception {
String str = IOUtils.toString(Profile.class.getResourceAsStream("/tmp.txt"));
str = IOUtils.toString(new FileReader("../hapi-tinder-test/src/test/resources/profile/organization.xml"));
Profile prof = new FhirContext(Profile.class).newXmlParser().parseResource(Profile.class, str);
CopyOfProfileParser pp = new CopyOfProfileParser();
pp.parseSingleProfile(prof, "http://foo");
pp.markResourcesForImports();
pp.writeAll(new File("target/gen/test/resource"), "test");
}
}

View File

@ -4,6 +4,7 @@ import static org.apache.commons.lang.StringUtils.capitalize;
import static org.apache.commons.lang.StringUtils.isBlank; import static org.apache.commons.lang.StringUtils.isBlank;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -24,16 +25,16 @@ import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinition;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinitionType; import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinitionType;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureSearchParam; import ca.uhn.fhir.model.dstu.resource.Profile.StructureSearchParam;
import ca.uhn.fhir.model.dstu.valueset.DataTypeEnum; import ca.uhn.fhir.model.dstu.valueset.DataTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.tinder.model.AnyChild; import ca.uhn.fhir.tinder.model.AnyChild;
import ca.uhn.fhir.tinder.model.BaseElement; import ca.uhn.fhir.tinder.model.BaseElement;
import ca.uhn.fhir.tinder.model.Child;
import ca.uhn.fhir.tinder.model.BaseRootType; import ca.uhn.fhir.tinder.model.BaseRootType;
import ca.uhn.fhir.tinder.model.Child;
import ca.uhn.fhir.tinder.model.Resource; import ca.uhn.fhir.tinder.model.Resource;
import ca.uhn.fhir.tinder.model.ResourceBlock; import ca.uhn.fhir.tinder.model.ResourceBlock;
import ca.uhn.fhir.tinder.model.SearchParameter; import ca.uhn.fhir.tinder.model.SearchParameter;
import ca.uhn.fhir.tinder.model.SimpleChild; import ca.uhn.fhir.tinder.model.SimpleChild;
import ca.uhn.fhir.tinder.model.Slicing; import ca.uhn.fhir.tinder.model.Slicing;
import ca.uhn.fhir.tinder.model.UndeclaredExtensionChild;
public class ProfileParser extends BaseStructureParser { public class ProfileParser extends BaseStructureParser {
@ -58,7 +59,25 @@ public class ProfileParser extends BaseStructureParser {
return "/vm/resource.vm"; return "/vm/resource.vm";
} }
public void parseBaseResources(List<String> theBaseResourceNames) throws MojoFailureException { public void parseSingleProfile(File theProfile, String theHttpUrl) throws MojoFailureException {
String profileString;
try {
profileString = IOUtils.toString(new FileReader(theProfile));
} catch (IOException e) {
throw new MojoFailureException("Failed to load: " + theProfile, e);
}
FhirContext ctx = new FhirContext(Profile.class);
Profile profile = ctx.newXmlParser().parseResource(Profile.class, profileString);
try {
parseSingleProfile(profile, theHttpUrl);
} catch (Exception e) {
throw new MojoFailureException("Failed to parse profile", e);
}
}
public void parseBaseResources(List<String> theBaseResourceNames, String theHttpUrl) throws MojoFailureException {
FhirContext fhirContext = new FhirContext(Profile.class); FhirContext fhirContext = new FhirContext(Profile.class);
for (String nextFileName : theBaseResourceNames) { for (String nextFileName : theBaseResourceNames) {
@ -72,7 +91,7 @@ public class ProfileParser extends BaseStructureParser {
} }
try { try {
parseSingleProfile(profile, ""); parseSingleProfile(profile, theHttpUrl);
} catch (Exception e) { } catch (Exception e) {
throw new MojoFailureException("Failed to process file: " + nextFileName, e); throw new MojoFailureException("Failed to process file: " + nextFileName, e);
} }
@ -133,20 +152,20 @@ public class ProfileParser extends BaseStructureParser {
addResource(retVal); addResource(retVal);
elem = retVal; elem = retVal;
// below StringUtils.isBlank(type) || type.startsWith("=") // below StringUtils.isBlank(type) || type.startsWith("=")
} else if (next.getDefinition().getType().isEmpty()) {
elem = new ResourceBlock();
// } else if (type.startsWith("@")) {
// elem = new ResourceBlockCopy();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("*")) {
elem = new AnyChild();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("Extension")) {
elem = new UndeclaredExtensionChild();
} else { } else {
elem = new SimpleChild(); if (next.getDefinition().getType().isEmpty()) {
} elem = new ResourceBlock();
// } else if (type.startsWith("@")) {
// elem = new ResourceBlockCopy();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("*")) {
elem = new AnyChild();
// } else if (next.getDefinition().getType().get(0).getCode().getValue().equals("Extension")) {
// elem = new UndeclaredExtensionChild();
} else {
elem = new SimpleChild();
}
elem.setName(next.getPath().getValue()); }
elem.setElementNameAndDeriveParentElementName(next.getPath().getValue());
boolean allResourceReferences = next.getDefinition().getType().size() > 0; boolean allResourceReferences = next.getDefinition().getType().size() > 0;
for (StructureElementDefinitionType nextType : next.getDefinition().getType()) { for (StructureElementDefinitionType nextType : next.getDefinition().getType()) {
@ -154,13 +173,12 @@ public class ProfileParser extends BaseStructureParser {
allResourceReferences = false; allResourceReferences = false;
} }
} }
elem.setResourceRef(allResourceReferences);
populateNewElement(next, elem, allResourceReferences);
StructureElementDefinition definition = next.getDefinition(); StructureElementDefinition definition = next.getDefinition();
BaseElement parentElement = elements.get(elem.getElementParentName()); BaseElement parentElement = elements.get(elem.getElementParentName());
Slicing childIsSliced = parentElement != null ? parentElement.getChildElementNameToSlicing().get(elem.getName()) : null;
if (next.getSlicing().getDiscriminator().getValue() != null) { if (next.getSlicing().getDiscriminator().getValue() != null) {
Slicing slicing = new Slicing(); Slicing slicing = new Slicing();
slicing.setDiscriminator(next.getSlicing().getDiscriminator().getValue()); slicing.setDiscriminator(next.getSlicing().getDiscriminator().getValue());
@ -171,6 +189,8 @@ public class ProfileParser extends BaseStructureParser {
continue; continue;
} }
Slicing childIsSliced = parentElement != null ? parentElement.getChildElementNameToSlicing().get(elem.getName()) : null;
/* /*
* Profiles come with a number of standard elements which are generally ignored because they are boilerplate, unless the definition is somehow changing their behaviour (e.g. through * Profiles come with a number of standard elements which are generally ignored because they are boilerplate, unless the definition is somehow changing their behaviour (e.g. through
* slices) * slices)
@ -189,12 +209,17 @@ public class ProfileParser extends BaseStructureParser {
if (next.getDefinition().getType().size() != 1 || next.getDefinition().getType().get(0).getCode().getValueAsEnum() != DataTypeEnum.EXTENSION) { if (next.getDefinition().getType().size() != 1 || next.getDefinition().getType().get(0).getCode().getValueAsEnum() != DataTypeEnum.EXTENSION) {
throw new ConfigurationException("Extension slices must have a single type with a code of 'Extension'"); throw new ConfigurationException("Extension slices must have a single type with a code of 'Extension'");
} }
String name = next.getName().getValue(); String name = next.getName().getValue();
if (StringUtils.isBlank(name)) { if (StringUtils.isBlank(name)) {
throw new ConfigurationException("Extension slices must have a 'name' defined, none found at path: " + next.getPath()); throw new ConfigurationException("Extension slices must have a 'name' defined, none found at path: " + next.getPath());
} }
elem.setName(name); elem.setName(name);
elem.setElementName(name); elem.setElementName(name);
// elem = new Extension();
// populateNewElement(next, elem, allResourceReferences);
String profile = next.getDefinition().getType().get(0).getProfile().getValueAsString(); String profile = next.getDefinition().getType().get(0).getProfile().getValueAsString();
if (isBlank(profile)) { if (isBlank(profile)) {
throw new ConfigurationException("Extension slice for " + next.getPath().getValue() + " has no profile specified in its type"); throw new ConfigurationException("Extension slice for " + next.getPath().getValue() + " has no profile specified in its type");
@ -267,15 +292,27 @@ public class ProfileParser extends BaseStructureParser {
return retVal; return retVal;
} }
private void populateNewElement(StructureElement next, BaseElement elem, boolean allResourceReferences) {
elem.setName(next.getPath().getValue());
elem.setElementNameAndDeriveParentElementName(next.getPath().getValue());
elem.setResourceRef(allResourceReferences);
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
String str = IOUtils.toString(Profile.class.getResourceAsStream("/tmp.txt")); IParser parser = new FhirContext(Profile.class).newXmlParser();
Profile prof = new FhirContext(Profile.class).newXmlParser().parseResource(Profile.class, str);
ProfileParser pp = new ProfileParser(); ProfileParser pp = new ProfileParser();
pp.parseSingleProfile(prof, "http://foo");
pp.markResourcesForImports();
pp.writeAll(new File("target/gen"), "test");
String str = IOUtils.toString(new FileReader("../hapi-tinder-test/src/test/resources/profile/organization.xml"));
Profile prof = parser.parseResource(Profile.class, str);
pp.parseSingleProfile(prof, "http://foo");
str = IOUtils.toString(new FileReader("../hapi-tinder-test/src/test/resources/profile/patient.xml"));
prof = parser.parseResource(Profile.class, str);
pp.parseSingleProfile(prof, "http://foo");
pp.markResourcesForImports();
pp.writeAll(new File("target/gen/test/resource"), "test");
} }
} }

View File

@ -34,14 +34,37 @@ public class TinderStructuresMojo extends AbstractMojo {
private String packageName; private String packageName;
@Parameter(required = false) @Parameter(required = false)
private List<String> resourceProfileFiles; private List<ProfileFileDefinition> resourceProfileFiles;
@Parameter(required = false) @Parameter(required = false)
private List<String> resourceValueSetFiles; private List<ValueSetFileDefinition> resourceValueSetFiles;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder") @Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private String targetDirectory; private String targetDirectory;
public static class ProfileFileDefinition
{
@Parameter(required = true)
private String profileFile;
@Parameter(required = true)
private String profileSourceUrl;
}
public static class ValueSetFileDefinition
{
@Parameter(required = true)
private String valueSetFile;
public String getValueSetFile() {
return valueSetFile;
}
public void setValueSetFile(String theValueSetFile) {
valueSetFile = theValueSetFile;
}
}
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException { public void execute() throws MojoExecutionException, MojoFailureException {
if (StringUtils.isBlank(packageName)) { if (StringUtils.isBlank(packageName)) {
@ -105,7 +128,9 @@ public class TinderStructuresMojo extends AbstractMojo {
if (resourceProfileFiles != null) { if (resourceProfileFiles != null) {
ourLog.info("Loading profiles..."); ourLog.info("Loading profiles...");
ProfileParser pp = new ProfileParser(); ProfileParser pp = new ProfileParser();
pp.parseBaseResources(resourceProfileFiles); for (ProfileFileDefinition next : resourceProfileFiles) {
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl);
}
pp.bindValueSets(vsp); pp.bindValueSets(vsp);
pp.markResourcesForImports(); pp.markResourcesForImports();
@ -134,11 +159,11 @@ public class TinderStructuresMojo extends AbstractMojo {
return packageName; return packageName;
} }
public List<String> getResourceProfileFiles() { public List<ProfileFileDefinition> getResourceProfileFiles() {
return resourceProfileFiles; return resourceProfileFiles;
} }
public List<String> getResourceValueSetFiles() { public List<ValueSetFileDefinition> getResourceValueSetFiles() {
return resourceValueSetFiles; return resourceValueSetFiles;
} }
@ -162,11 +187,11 @@ public class TinderStructuresMojo extends AbstractMojo {
packageName = thePackageName; packageName = thePackageName;
} }
public void setResourceProfileFiles(List<String> theResourceProfileFiles) { public void setResourceProfileFiles(List<ProfileFileDefinition> theResourceProfileFiles) {
resourceProfileFiles = theResourceProfileFiles; resourceProfileFiles = theResourceProfileFiles;
} }
public void setResourceValueSetFiles(List<String> theResourceValueSetFiles) { public void setResourceValueSetFiles(List<ValueSetFileDefinition> theResourceValueSetFiles) {
resourceValueSetFiles = theResourceValueSetFiles; resourceValueSetFiles = theResourceValueSetFiles;
} }

View File

@ -30,12 +30,13 @@ import ca.uhn.fhir.model.dstu.resource.ValueSet.Define;
import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept; import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition;
import ca.uhn.fhir.tinder.model.ValueSetTm; import ca.uhn.fhir.tinder.model.ValueSetTm;
public class ValueSetGenerator { public class ValueSetGenerator {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetGenerator.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetGenerator.class);
private List<String> myResourceValueSetFiles; private List<ValueSetFileDefinition> myResourceValueSetFiles;
private Set<ValueSetTm> myMarkedValueSets = new HashSet<ValueSetTm>(); private Set<ValueSetTm> myMarkedValueSets = new HashSet<ValueSetTm>();
private Map<String, ValueSetTm> myValueSets = new HashMap<String, ValueSetTm>(); private Map<String, ValueSetTm> myValueSets = new HashMap<String, ValueSetTm>();
@ -68,8 +69,8 @@ public class ValueSetGenerator {
} }
if (myResourceValueSetFiles != null) { if (myResourceValueSetFiles != null) {
for (String next : myResourceValueSetFiles) { for (ValueSetFileDefinition next : myResourceValueSetFiles) {
File file = new File(next); File file = new File(next.getValueSetFile());
ourLog.info("Parsing ValueSet file: {}" + file.getName()); ourLog.info("Parsing ValueSet file: {}" + file.getName());
vs = IOUtils.toString(new FileReader(file)); vs = IOUtils.toString(new FileReader(file));
ValueSet nextVs = (ValueSet) newXmlParser.parseResource(vs); ValueSet nextVs = (ValueSet) newXmlParser.parseResource(vs);
@ -138,8 +139,8 @@ public class ValueSetGenerator {
return vs; return vs;
} }
public void setResourceValueSetFiles(List<String> theString) { public void setResourceValueSetFiles(List<ValueSetFileDefinition> theResourceValueSetFiles) {
myResourceValueSetFiles = theString; myResourceValueSetFiles = theResourceValueSetFiles;
} }
public void write(Collection<ValueSetTm> theValueSets, File theOutputDirectory, String thePackageBase) throws IOException { public void write(Collection<ValueSetTm> theValueSets, File theOutputDirectory, String thePackageBase) throws IOException {

View File

@ -8,7 +8,7 @@
@Child(name="${child.elementNameSimplified}", order=${foreach.index}, min=${child.cardMin}, max=${child.cardMaxForChildAnnotation}, type={ @Child(name="${child.elementNameSimplified}", order=${foreach.index}, min=${child.cardMin}, max=${child.cardMaxForChildAnnotation}, type={
#foreach ($nextType in ${child.referenceTypesForMultiple}) #foreach ($nextType in ${child.referenceTypesForMultiple})
#if ( ${child.resourceRef} && ${nextType} != "IResource" ) #if ( ${child.resourceRef} && ${nextType} != "IResource" )
${packageBase}.resource.${nextType}.class, ${nextType}.class,
#else #else
${nextType}.class, ${nextType}.class,
#end #end

View File

@ -41,6 +41,16 @@
<ordered value="false"/> <ordered value="false"/>
<rules value="open"/> <rules value="open"/>
</slicing> </slicing>
<definition>
<short value="Extensions" />
<formal value="Extensions" />
<min value="0" />
<max value="*" />
<type>
<code value="Extension" />
</type>
<isModifier value="false" />
</definition>
</element> </element>
<element> <element>
<path value="Organization.extension" /> <path value="Organization.extension" />

View File

@ -2,6 +2,7 @@
<classpath> <classpath>
<classpathentry kind="src" path="target/generated-sources/tinder"/> <classpathentry kind="src" path="target/generated-sources/tinder"/>
<classpathentry kind="src" path="src/test/resources"/> <classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/> <classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="var" path="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar" sourcepath="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2-sources.jar"/> <classpathentry kind="var" path="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar" sourcepath="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar" sourcepath="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-sources.jar"/> <classpathentry kind="var" path="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar" sourcepath="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-sources.jar"/>
@ -37,5 +38,10 @@
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.17/log4j-1.2.17.jar"/> <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.17/log4j-1.2.17.jar"/>
<classpathentry kind="var" path="M2_REPO/junit/junit/4.11/junit-4.11.jar" sourcepath="M2_REPO/junit/junit/4.11/junit-4.11-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/junit/junit/4.11/junit-4.11-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -21,6 +21,14 @@
<artifactId>hapi-fhir-base</artifactId> <artifactId>hapi-fhir-base</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -75,13 +83,24 @@
</goals> </goals>
<configuration> <configuration>
<package>ca.uhn.test.customstructs</package> <package>ca.uhn.test.customstructs</package>
<profileHttpBase>http://foo</profileHttpBase>
<resourceProfileFiles> <resourceProfileFiles>
<resourceProfileFile>src/test/resources/profile/patient.xml</resourceProfileFile> <resourceProfileFile>
<resourceProfileFile>src/test/resources/profile/organization.xml</resourceProfileFile> <profileFile>${project.basedir}/src/test/resources/profile/patient.xml</profileFile>
<profileSourceUrl>http://foo1</profileSourceUrl>
</resourceProfileFile>
<resourceProfileFile>
<profileFile>${project.basedir}/src/test/resources/profile/organization.xml</profileFile>
<profileSourceUrl>http://foo1</profileSourceUrl>
</resourceProfileFile>
</resourceProfileFiles> </resourceProfileFiles>
<resourceValueSetFiles> <resourceValueSetFiles>
<resourceValueSetFile>src/test/resources/valueset/valueset-cgta-patientidpool.xml</resourceValueSetFile> <resourceValueSetFile>
<resourceValueSetFile>src/test/resources/valueset/valueset-cgta-provideridpool.xml</resourceValueSetFile> <valueSetFile>${project.basedir}/src/test/resources/valueset/valueset-cgta-patientidpool.xml</valueSetFile>
</resourceValueSetFile>
<resourceValueSetFile>
<valueSetFile>${project.basedir}/src/test/resources/valueset/valueset-cgta-provideridpool.xml</valueSetFile>
</resourceValueSetFile>
</resourceValueSetFiles> </resourceValueSetFiles>
</configuration> </configuration>
</execution> </execution>

View File

@ -0,0 +1,32 @@
package test;
import static org.junit.Assert.*;
import java.io.IOException;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.test.customstructs.resource.Organization;
import ca.uhn.test.customstructs.valueset.ConnectingGTAProviderIDNamespacesEnum;
public class TestCustomStructures {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TestCustomStructures.class);
@Test
public void testExtension() throws DataFormatException, IOException {
Organization org = new Organization();
org.addProviderIdPool(ConnectingGTAProviderIDNamespacesEnum.UNIVERSITY_HEALTH_NETWORK_PROVIDER_IDS);
FhirContext ctx = new FhirContext(Organization.class);
String str = ctx.newXmlParser().encodeResourceToString(org);
ourLog.info(str);
assertTrue(str.contains("<extension url=\"http://foo1#providerIdPool\"><valueCode value=\"urn:oid:1.3.6.1.4.1.12201.1\"/></extension>"));
}
}

View File

@ -41,6 +41,16 @@
<ordered value="false"/> <ordered value="false"/>
<rules value="open"/> <rules value="open"/>
</slicing> </slicing>
<definition>
<short value="Extensions" />
<formal value="Extensions" />
<min value="0" />
<max value="*" />
<type>
<code value="Extension" />
</type>
<isModifier value="false" />
</definition>
</element> </element>
<element> <element>
<path value="Organization.extension" /> <path value="Organization.extension" />

View File

@ -23,7 +23,8 @@
<modules> <modules>
<module>hapi-fhir-base</module> <module>hapi-fhir-base</module>
<module>hapi-tinder-plugin</module> <module>hapi-tinder-plugin</module>
<!-- <module>hapi-tinder-test</module> <module>hapi-fhir-structures-dstu</module> --> <module>hapi-tinder-test</module>
<!-- <module>hapi-fhir-structures-dstu</module> -->
</modules> </modules>
<properties> <properties>