Fixing extension building

This commit is contained in:
jamesagnew 2014-03-13 10:51:36 -04:00
parent 45c968532d
commit 561f765d00
17 changed files with 412 additions and 251 deletions

View File

@ -4,8 +4,11 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import ca.uhn.fhir.model.primitive.IdDt;
public abstract class BaseElement implements IElement, ISupportsUndeclaredExtensions { public abstract class BaseElement implements IElement, ISupportsUndeclaredExtensions {
private IdDt myId;
private List<UndeclaredExtension> myUndeclaredExtensions; private List<UndeclaredExtension> myUndeclaredExtensions;
private List<UndeclaredExtension> myUndeclaredModifierExtensions; private List<UndeclaredExtension> myUndeclaredModifierExtensions;
@ -21,6 +24,11 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
return Collections.unmodifiableList(retVal); return Collections.unmodifiableList(retVal);
} }
@Override
public IdDt getId() {
return myId;
}
@Override @Override
public List<UndeclaredExtension> getUndeclaredExtensions() { public List<UndeclaredExtension> getUndeclaredExtensions() {
if (myUndeclaredExtensions == null) { if (myUndeclaredExtensions == null) {
@ -59,4 +67,9 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
return true; return true;
} }
@Override
public void setId(IdDt theId) {
myId = theId;
}
} }

View File

@ -1,7 +1,13 @@
package ca.uhn.fhir.model.api; package ca.uhn.fhir.model.api;
import ca.uhn.fhir.model.primitive.IdDt;
public interface IElement { public interface IElement {
boolean isEmpty(); boolean isEmpty();
public void setId(IdDt theId);
public IdDt getId();
} }

View File

@ -0,0 +1,104 @@
package ca.uhn.fhir.rest.client;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.primitive.Base64BinaryDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.client.api.IRestfulClient;
public class ClientCache {
private FhirContext myPrivateContext;
private FhirContext myPublicContext;
private ClientCache(FhirContext theContext) {
myPublicContext = theContext;
myPrivateContext = new FhirContext(CacheEntry.class);
}
/**
* Accepts a restful client instance and decorates it
*/
public <T extends IRestfulClient> T decorateClient(Class<T> theInterface, T theClientToDecorate) {
for (Method nextMethod : theInterface.getMethods()){
}
return theClientToDecorate;
}
@ResourceDef(name="HapiClientCacheEntry", id="hapiclientcacheentry")
private static class CacheEntry {
@Child(order=2, min=0,max=Child.MAX_UNLIMITED,name="arguments")
private List<IDatatype> myArguments;
@Child(order=1, min=0,max=Child.MAX_UNLIMITED,name="argumentTypes")
private List<StringDt> myArgumentTypes;
@Child(order=3, min=1,max=1,name="loaded")
private InstantDt myLoaded;
@Child(order=0, min=1, max=1, name="methodName")
private StringDt myMethodName;
@Child(order=4, min=1,max=1,name="resourceText")
private Base64BinaryDt myResourceText;
public List<IDatatype> getArguments() {
if (myArguments==null) {
myArguments=new ArrayList<IDatatype>();
}
return myArguments;
}
public List<StringDt> getArgumentTypes() {
return myArgumentTypes;
}
public InstantDt getLoaded() {
return myLoaded;
}
public StringDt getMethodName() {
return myMethodName;
}
public Base64BinaryDt getResourceText() {
return myResourceText;
}
public void setArguments(List<IDatatype> theArguments) {
myArguments = theArguments;
}
public void setArgumentTypes(List<StringDt> theArgumentTypes) {
myArgumentTypes = theArgumentTypes;
}
public void setLoaded(InstantDt theLoaded) {
myLoaded = theLoaded;
}
public void setMethodName(StringDt theMethodName) {
myMethodName = theMethodName;
}
public void setResourceText(Base64BinaryDt theResourceText) {
myResourceText = theResourceText;
}
}
}

View File

@ -1,4 +1,5 @@
package ca.uhn.fhir.rest.client; package ca.uhn.fhir.rest.client;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
@ -36,7 +37,7 @@ public class ClientInvocationHandler implements InvocationHandler {
private final HttpClient myClient; private final HttpClient myClient;
private final FhirContext myContext; private final FhirContext myContext;
private final String myUrlBase; private final String myUrlBase;
private final Map<Method, Object> myMethodToReturnValue=new HashMap<Method, Object>(); private final Map<Method, Object> myMethodToReturnValue = new HashMap<Method, Object>();
public ClientInvocationHandler(HttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) { public ClientInvocationHandler(HttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) {
myClient = theClient; myClient = theClient;
@ -48,9 +49,9 @@ public class ClientInvocationHandler implements InvocationHandler {
myMethodToReturnValue.put(theClientType.getMethod("getHttpClient"), theClient); myMethodToReturnValue.put(theClientType.getMethod("getHttpClient"), theClient);
myMethodToReturnValue.put(theClientType.getMethod("getServerBase"), theUrlBase); myMethodToReturnValue.put(theClientType.getMethod("getServerBase"), theUrlBase);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!",e); throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
} catch (SecurityException e) { } catch (SecurityException e) {
throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!",e); throw new ConfigurationException("Failed to find methods on client. This is a HAPI bug!", e);
} }
} }
@ -61,71 +62,72 @@ public class ClientInvocationHandler implements InvocationHandler {
@Override @Override
public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable { public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable {
Object directRetVal = myMethodToReturnValue.get(theMethod); Object directRetVal = myMethodToReturnValue.get(theMethod);
if (directRetVal!=null) { if (directRetVal != null) {
return directRetVal; return directRetVal;
} }
BaseMethodBinding binding = myBindings.get(theMethod); BaseMethodBinding binding = myBindings.get(theMethod);
GetClientInvocation clientInvocation = binding.invokeClient(theArgs); GetClientInvocation clientInvocation = binding.invokeClient(theArgs);
HttpRequestBase httpRequest = clientInvocation.asHttpRequest(myUrlBase); HttpRequestBase httpRequest = clientInvocation.asHttpRequest(myUrlBase);
HttpResponse response = myClient.execute(httpRequest); HttpResponse response = myClient.execute(httpRequest);
try { try {
Reader reader = createReaderFromResponse(response); Reader reader = createReaderFromResponse(response);
if (ourLog.isTraceEnabled()) { if (ourLog.isTraceEnabled()) {
String responseString = IOUtils.toString(reader); String responseString = IOUtils.toString(reader);
ourLog.trace("FHIR response:\n{}\n{}", response, responseString); ourLog.trace("FHIR response:\n{}\n{}", response, responseString);
reader = new StringReader(responseString); reader = new StringReader(responseString);
} }
ContentType ct = ContentType.get(response.getEntity()); ContentType ct = ContentType.get(response.getEntity());
IParser parser; IParser parser;
String mimeType = ct.getMimeType(); String mimeType = ct.getMimeType();
if (Constants.CT_ATOM_XML.equals(mimeType)) { if (Constants.CT_ATOM_XML.equals(mimeType)) {
parser = myContext.newXmlParser(); parser = myContext.newXmlParser();
} else if (Constants.CT_FHIR_XML.equals(mimeType)) { } else if (Constants.CT_FHIR_XML.equals(mimeType)) {
parser = myContext.newXmlParser(); parser = myContext.newXmlParser();
} else { } else {
throw new NonFhirResponseException("Response contains non-FHIR content-type: " + mimeType, mimeType, response.getStatusLine().getStatusCode(), IOUtils.toString(reader)); throw new NonFhirResponseException("Response contains non-FHIR content-type: " + mimeType, mimeType, response.getStatusLine().getStatusCode(), IOUtils.toString(reader));
} }
switch (binding.getReturnType()) { switch (binding.getReturnType()) {
case BUNDLE: { case BUNDLE: {
Bundle bundle = parser.parseBundle(reader); Bundle bundle = parser.parseBundle(reader);
switch (binding.getMethodReturnType()) { switch (binding.getMethodReturnType()) {
case BUNDLE: case BUNDLE:
return bundle; return bundle;
case LIST_OF_RESOURCES: case LIST_OF_RESOURCES:
return bundle.toListOfResources(); return bundle.toListOfResources();
case RESOURCE: case RESOURCE:
List<IResource> list = bundle.toListOfResources(); List<IResource> list = bundle.toListOfResources();
if (list.size() == 0) { if (list.size() == 0) {
return null; return null;
} else if (list.size() == 1) { } else if (list.size() == 1) {
return list.get(0); return list.get(0);
} else { } else {
throw new InvalidResponseException("FHIR server call returned a bundle with multiple resources, but this method is only able to returns one."); throw new InvalidResponseException("FHIR server call returned a bundle with multiple resources, but this method is only able to returns one.");
}
} }
break;
}
case RESOURCE: {
IResource resource = parser.parseResource(reader);
switch (binding.getMethodReturnType()) {
case BUNDLE:
return Bundle.withSingleResource(resource);
case LIST_OF_RESOURCES:
return Collections.singletonList(resource);
case RESOURCE:
return resource;
}
break;
} }
break;
}
case RESOURCE: {
IResource resource = parser.parseResource(reader);
switch (binding.getMethodReturnType()) {
case BUNDLE:
return Bundle.withSingleResource(resource);
case LIST_OF_RESOURCES:
return Collections.singletonList(resource);
case RESOURCE:
return resource;
} }
break;
}
}
throw new IllegalStateException("Should not get here!"); throw new IllegalStateException("Should not get here!");
} finally { } finally {
if (response instanceof CloseableHttpResponse) { if (response instanceof CloseableHttpResponse) {
((CloseableHttpResponse) response).close(); ((CloseableHttpResponse) response).close();

View File

@ -1,7 +1,6 @@
package ca.uhn.fhir.rest.client; package ca.uhn.fhir.rest.client;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ -10,10 +9,8 @@ import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.rest.common.BaseMethodBinding;
public class GetClientInvocation extends BaseClientInvocation { public class GetClientInvocation extends BaseClientInvocation {

View File

@ -1,5 +0,0 @@
package ca.uhn.fhir.rest.client;
class MethodBinding {
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry excluding="**/*.java" kind="src" path="src/test/resources"/> <classpathentry excluding="**/*.java" kind="src" path="src/test/resources"/>
<classpathentry kind="src" path="target/gen"/>
<classpathentry including="**/*.java" kind="src" path="src/main/java"/> <classpathentry including="**/*.java" kind="src" path="src/main/java"/>
<classpathentry excluding="**/*.java" kind="src" path="src/main/resources"/> <classpathentry excluding="**/*.java" kind="src" path="src/main/resources"/>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/> <classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>

View File

@ -3,14 +3,10 @@ package ca.uhn.fhir.tinder;
import static org.apache.commons.lang.StringUtils.capitalize; 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.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException;
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 java.util.TreeMap;
import java.util.TreeSet;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -18,8 +14,6 @@ import org.apache.maven.plugin.MojoFailureException;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.dstu.resource.Profile; 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.ExtensionDefn;
import ca.uhn.fhir.model.dstu.resource.Profile.Structure; import ca.uhn.fhir.model.dstu.resource.Profile.Structure;
@ -28,8 +22,6 @@ 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.DataFormatException;
import ca.uhn.fhir.parser.XmlParser;
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.Child;
@ -43,29 +35,74 @@ public class ProfileParser extends BaseStructureParser {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ProfileParser.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ProfileParser.class);
public static void main(String[] args) throws Exception { private ExtensionDefn findExtension(Profile theProfile, String theCode) {
for (ExtensionDefn next : theProfile.getExtensionDefn()) {
// FhirContext fhirContext = new FhirContext(Profile.class); if (theCode.equals(next.getCode().getValue())) {
// XmlParser parser = fhirContext.newXmlParser(); return next;
// }
// String file = IOUtils.toString(new }
// FileReader("src/test/resources/prof/organization.xml")); return null;
// Profile text = (Profile) parser.parseResource(file);
//
// ValueSetGenerator vsp = new ValueSetGenerator();
// vsp.setDirectory("src/test/resources/vs/");
// vsp.parse();
//
// ProfileParser p = new ProfileParser();
// p.parseSingleProfile(text,
// "http://fhir.connectinggta.ca/static/Profile/organization.xml");
// p.bindValueSets(vsp);
// p.writeAll("target/generated/valuesets/ca/uhn/fhir/model/dstu/resource");
//
// vsp.writeMarkedValueSets("target/generated/valuesets/ca/uhn/fhir/model/dstu/valueset");
} }
public void parseSingleProfile(Profile theProfile, String theUrlTOThisProfile) throws Exception { @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 Resource parseSingleProfile(Profile theProfile, String theUrlTOThisProfile) throws Exception {
Resource retVal = null;
for (Structure nextStructure : theProfile.getStructure()) { for (Structure nextStructure : theProfile.getStructure()) {
int elemIdx = 0; int elemIdx = 0;
@ -74,10 +111,10 @@ public class ProfileParser extends BaseStructureParser {
BaseElement elem; BaseElement elem;
if (elemIdx == 0) { if (elemIdx == 0) {
Resource resource = new Resource(); retVal = new Resource();
resource.setProfile(theProfile.getIdentifier().getValue()); retVal.setProfile(theProfile.getIdentifier().getValue());
if (resource.getProfile() == null) { if (retVal.getProfile() == null) {
resource.setProfile(theUrlTOThisProfile); retVal.setProfile(theUrlTOThisProfile);
} }
for (StructureSearchParam nextParam : nextStructure.getSearchParam()) { for (StructureSearchParam nextParam : nextStructure.getSearchParam()) {
@ -86,11 +123,11 @@ public class ProfileParser extends BaseStructureParser {
param.setPath(nextParam.getXpath().getValue()); param.setPath(nextParam.getXpath().getValue());
param.setType(nextParam.getType().getValue()); param.setType(nextParam.getType().getValue());
param.setDescription(nextParam.getDocumentation().getValue()); param.setDescription(nextParam.getDocumentation().getValue());
resource.getSearchParameters().add(param); retVal.getSearchParameters().add(param);
} }
addResource(resource); addResource(retVal);
elem = resource; elem = retVal;
// below StringUtils.isBlank(type) || type.startsWith("=") // below StringUtils.isBlank(type) || type.startsWith("=")
} else if (next.getDefinition().getType().isEmpty()) { } else if (next.getDefinition().getType().isEmpty()) {
elem = new ResourceBlock(); elem = new ResourceBlock();
@ -98,8 +135,8 @@ public class ProfileParser extends BaseStructureParser {
// elem = new ResourceBlockCopy(); // elem = new ResourceBlockCopy();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("*")) { } else if (next.getDefinition().getType().get(0).getCode().getValue().equals("*")) {
elem = new AnyChild(); elem = new AnyChild();
} else if (next.getDefinition().getType().get(0).getCode().getValue().equals("Extension")) { // } else if (next.getDefinition().getType().get(0).getCode().getValue().equals("Extension")) {
elem = new UndeclaredExtensionChild(); // elem = new UndeclaredExtensionChild();
} else { } else {
elem = new Child(); elem = new Child();
} }
@ -131,9 +168,7 @@ public class ProfileParser extends BaseStructureParser {
} }
/* /*
* Profiles come with a number of standard elements which are * 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
* generally ignored because they are boilerplate, unless the
* definition is somehow changing their behaviour (e.g. through
* slices) * slices)
*/ */
if (next.getPath().getValue().endsWith(".contained")) { if (next.getPath().getValue().endsWith(".contained")) {
@ -224,72 +259,30 @@ public class ProfileParser extends BaseStructureParser {
} }
} }
return retVal;
} }
private ExtensionDefn findExtension(Profile theProfile, String theCode) { public static void main(String[] args) throws Exception {
for (ExtensionDefn next : theProfile.getExtensionDefn()) {
if (theCode.equals(next.getCode().getValue())) {
return next;
}
}
return null;
}
@Override // FhirContext fhirContext = new FhirContext(Profile.class);
protected String getFilenameSuffix() { // XmlParser parser = fhirContext.newXmlParser();
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 { // String file = IOUtils.toString(new
// FileReader("src/test/resources/prof/organization.xml"));
// Profile text = (Profile) parser.parseResource(file);
// //
// Bundle bundle = // ValueSetGenerator vsp = new ValueSetGenerator();
// fhirContext.newXmlParser().parseBundle(IOUtils.toString(getClass().getResourceAsStream("/prof/allprofiles.xml"))); // vsp.setDirectory("src/test/resources/vs/");
// TreeSet<String> allProfiles = new TreeSet<String>(); // vsp.parse();
// 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); // ProfileParser p = new ProfileParser();
// p.parseSingleProfile(text,
// "http://fhir.connectinggta.ca/static/Profile/organization.xml");
// p.bindValueSets(vsp);
// p.writeAll("target/generated/valuesets/ca/uhn/fhir/model/dstu/resource");
// //
// } catch (Exception e) { // vsp.writeMarkedValueSets("target/generated/valuesets/ca/uhn/fhir/model/dstu/valueset");
// throw new MojoFailureException("Failed to load base resources", e);
// }
} }
} }

View File

@ -1,10 +1,6 @@
package ca.uhn.fhir.tinder; package ca.uhn.fhir.tinder;
import static org.apache.commons.lang.StringUtils.defaultString;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -12,10 +8,6 @@ import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException; import org.apache.http.ParseException;
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
@ -26,9 +18,7 @@ import org.apache.maven.plugins.annotations.Parameter;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.app.VelocityEngine;
import ch.qos.logback.core.util.FileUtil;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Conformance; import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest; import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource; import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
@ -36,51 +26,54 @@ import ca.uhn.fhir.model.dstu.resource.Profile;
import ca.uhn.fhir.model.dstu.valueset.RestfulConformanceModeEnum; import ca.uhn.fhir.model.dstu.valueset.RestfulConformanceModeEnum;
import ca.uhn.fhir.rest.client.IRestfulClientFactory; import ca.uhn.fhir.rest.client.IRestfulClientFactory;
import ca.uhn.fhir.rest.client.api.IBasicClient; import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.tinder.model.Extension;
import ca.uhn.fhir.tinder.model.Resource; import ca.uhn.fhir.tinder.model.Resource;
import ca.uhn.fhir.tinder.model.RestResourceTm; import ca.uhn.fhir.tinder.model.RestResourceTm;
import ca.uhn.fhir.tinder.model.SearchParameter;
@Mojo(name = "generate-client", defaultPhase = LifecyclePhase.GENERATE_SOURCES) @Mojo(name = "generate-client", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class TinderClientMojo extends AbstractMojo { public class TinderClientMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderClientMojo.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderClientMojo.class);
@Parameter(alias = "clientClassName", required = true) @Parameter(required = true)
private String myClientClassName; private String serverBaseHref;
@Parameter(alias = "targetDirectory", required = true, defaultValue = "${project.build.directory}/generated-sources/tinder") @Parameter(required = true)
private File myTargetDirectory; private String clientClassName;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private File targetDirectory;
@Parameter(required = true, defaultValue = "false")
private boolean generateSearchForAllParams;
private List<RestResourceTm> myResources = new ArrayList<RestResourceTm>(); private List<RestResourceTm> myResources = new ArrayList<RestResourceTm>();
private String myPackageBase; private String myPackageBase;
private File myDirectoryBase; private File myDirectoryBase;
private String myClientClassSimpleName; private String myClientClassSimpleName;
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException { public void execute() throws MojoExecutionException, MojoFailureException {
determinePaths(); determinePaths();
// //
// try { // try {
// ProfileParser pp = new ProfileParser(); // ProfileParser pp = new ProfileParser();
// Profile prof=(Profile) new FhirContext(Profile.class).newXmlParser().parseResource(IOUtils.toString(new FileReader("src/test/resources/profile.xml"))); // Profile prof=(Profile) new FhirContext(Profile.class).newXmlParser().parseResource(IOUtils.toString(new FileReader("src/test/resources/profile.xml")));
// pp.parseSingleProfile(prof, "http://foo"); // pp.parseSingleProfile(prof, "http://foo");
// File resourceDir = new File(myDirectoryBase, "resource"); // File resourceDir = new File(myDirectoryBase, "resource");
// resourceDir.mkdirs(); // resourceDir.mkdirs();
// pp.writeAll(resourceDir, myPackageBase); // pp.writeAll(resourceDir, myPackageBase);
// } catch (Exception e) { // } catch (Exception e) {
// throw new MojoFailureException("Failed to load resource profile: ",e); // throw new MojoFailureException("Failed to load resource profile: ",e);
// } // }
// if (true) { // if (true) {
// return; // return;
// } // }
FhirContext ctx = new FhirContext(Conformance.class); FhirContext ctx = new FhirContext(Conformance.class);
IRestfulClientFactory cFact = ctx.newRestfulClientFactory(); IRestfulClientFactory cFact = ctx.newRestfulClientFactory();
IBasicClient client = cFact.newClient(IBasicClient.class, "http://fhir.healthintersections.com.au/open"); IBasicClient client = cFact.newClient(IBasicClient.class, serverBaseHref);
Conformance conformance = client.getServerConformanceStatement(); Conformance conformance = client.getServerConformanceStatement();
@ -100,21 +93,27 @@ public class TinderClientMojo extends AbstractMojo {
Profile profile; Profile profile;
try { try {
ourLog.info("Loading Profile: {}", nextResource.getProfile().getResourceUrl()); ourLog.info("Loading Profile: {}", nextResource.getProfile().getResourceUrl());
profile = (Profile)nextResource.getProfile().loadResource(client); profile = (Profile) nextResource.getProfile().loadResource(client);
} catch (IOException e) { } catch (IOException e) {
throw new MojoFailureException("Failed to load resource profile: "+nextResource.getProfile().getReference().getValue(),e); throw new MojoFailureException("Failed to load resource profile: " + nextResource.getProfile().getReference().getValue(), e);
} }
ProfileParser pp = new ProfileParser(); ProfileParser pp = new ProfileParser();
Resource resourceModel;
try { try {
pp.parseSingleProfile(profile, nextResource.getProfile().getResourceUrl()); resourceModel = pp.parseSingleProfile(profile, nextResource.getProfile().getResourceUrl());
File resourceDir = new File(myDirectoryBase, "resource"); File resourceDir = new File(myDirectoryBase, "resource");
resourceDir.mkdirs(); resourceDir.mkdirs();
pp.writeAll(resourceDir, myPackageBase); pp.writeAll(resourceDir, myPackageBase);
} catch (Exception e) { } catch (Exception e) {
throw new MojoFailureException("Failed to load resource profile: "+nextResource.getProfile().getReference().getValue(),e); throw new MojoFailureException("Failed to load resource profile: " + nextResource.getProfile().getReference().getValue(), e);
} }
if (generateSearchForAllParams) {
for (SearchParameter next : resourceModel.getSearchParameters()) {
nextTmResource.getSearchParams().add(next);
}
}
} }
try { try {
@ -127,12 +126,12 @@ public class TinderClientMojo extends AbstractMojo {
private void determinePaths() { private void determinePaths() {
myPackageBase = ""; myPackageBase = "";
myDirectoryBase = myTargetDirectory; myDirectoryBase = targetDirectory;
myClientClassSimpleName = myClientClassName; myClientClassSimpleName = clientClassName;
if (myClientClassName.lastIndexOf('.') > -1) { if (clientClassName.lastIndexOf('.') > -1) {
myPackageBase = myClientClassName.substring(0, myClientClassName.lastIndexOf('.')); myPackageBase = clientClassName.substring(0, clientClassName.lastIndexOf('.'));
myDirectoryBase = new File(myDirectoryBase, myPackageBase.replace(".", File.separatorChar+"")); myDirectoryBase = new File(myDirectoryBase, myPackageBase.replace(".", File.separatorChar + ""));
myClientClassSimpleName = myClientClassName.substring(myClientClassName.lastIndexOf('.')+1); myClientClassSimpleName = clientClassName.substring(clientClassName.lastIndexOf('.') + 1);
} }
myDirectoryBase.mkdirs(); myDirectoryBase.mkdirs();
@ -179,8 +178,9 @@ public class TinderClientMojo extends AbstractMojo {
// Conformance conformance = new FhirContext(Conformance.class).newXmlParser().parseResource(Conformance.class, metadataString); // Conformance conformance = new FhirContext(Conformance.class).newXmlParser().parseResource(Conformance.class, metadataString);
TinderClientMojo mojo = new TinderClientMojo(); TinderClientMojo mojo = new TinderClientMojo();
mojo.myClientClassName = "ca.uhn.test.ClientClass"; mojo.clientClassName = "ca.uhn.test.ClientClass";
mojo.myTargetDirectory = new File("target/gen"); mojo.targetDirectory = new File("target/gen");
mojo.serverBaseHref = "http://fhir.healthintersections.com.au/open";
mojo.execute(); mojo.execute();
} }

View File

@ -19,41 +19,41 @@ public class TinderStructuresMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderStructuresMojo.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderStructuresMojo.class);
@Parameter(alias = "package", required = true) @Parameter(alias = "package", required = true)
private String myPackage; private String packageName;
@Parameter(alias = "targetDirectory", required = true, defaultValue = "${project.build.directory}/generated-sources/tinder") @Parameter(alias = "targetDirectory", required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private String myTargetDirectory; private String targetDirectory;
@Parameter(alias="resourceValueSetFiles", required = false) @Parameter(alias="resourceValueSetFiles", required = false)
private List<String> myResourceValueSetFiles; private List<String> resourceValueSetFiles;
@Parameter(alias = "baseResourceNames", required = true) @Parameter(alias = "baseResourceNames", required = true)
private List<String> myBaseResourceNames; private List<String> baseResourceNames;
@Parameter(alias = "resourceProfileFiles", required = false) @Parameter(alias = "resourceProfileFiles", required = false)
private List<String> myResourceProfileFiles; private List<String> resourceProfileFiles;
@Component @Component
private MavenProject myProject; private MavenProject myProject;
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException { public void execute() throws MojoExecutionException, MojoFailureException {
if (StringUtils.isBlank(myPackage)) { if (StringUtils.isBlank(packageName)) {
throw new MojoFailureException("Package not specified"); throw new MojoFailureException("Package not specified");
} }
if (myPackage.contains("..") || myPackage.endsWith(".")) { if (packageName.contains("..") || packageName.endsWith(".")) {
throw new MojoFailureException("Invalid package specified"); throw new MojoFailureException("Invalid package specified");
} }
ourLog.info("Beginning HAPI-FHIR Tinder Code Generation..."); ourLog.info("Beginning HAPI-FHIR Tinder Code Generation...");
ourLog.info(" * Output Package: " + myPackage); ourLog.info(" * Output Package: " + packageName);
File directoryBase = new File(new File(myTargetDirectory), myPackage.replace('.', File.separatorChar)); File directoryBase = new File(new File(targetDirectory), packageName.replace('.', File.separatorChar));
directoryBase.mkdirs(); directoryBase.mkdirs();
ourLog.info(" * Output Directory: " + directoryBase.getAbsolutePath()); ourLog.info(" * Output Directory: " + directoryBase.getAbsolutePath());
ValueSetGenerator vsp = new ValueSetGenerator(); ValueSetGenerator vsp = new ValueSetGenerator();
vsp.setResourceValueSetFiles(myResourceValueSetFiles); vsp.setResourceValueSetFiles(resourceValueSetFiles);
try { try {
vsp.parse(); vsp.parse();
} catch (Exception e) { } catch (Exception e) {
@ -73,31 +73,31 @@ public class TinderStructuresMojo extends AbstractMojo {
ourLog.info("Loading Resources..."); ourLog.info("Loading Resources...");
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet(); ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
try { try {
rp.setBaseResourceNames(myBaseResourceNames); rp.setBaseResourceNames(baseResourceNames);
rp.parse(); rp.parse();
} catch (Exception e) { } catch (Exception e) {
throw new MojoFailureException("Failed to load resources", e); throw new MojoFailureException("Failed to load resources", e);
} }
rp.bindValueSets(vsp); rp.bindValueSets(vsp);
if (myResourceProfileFiles != null) { if (resourceProfileFiles != null) {
ourLog.info("Loading profiles..."); ourLog.info("Loading profiles...");
ProfileParser pp = new ProfileParser(); ProfileParser pp = new ProfileParser();
pp.parseBaseResources(myResourceProfileFiles); pp.parseBaseResources(resourceProfileFiles);
pp.bindValueSets(vsp); pp.bindValueSets(vsp);
pp.writeAll(new File(directoryBase, "resource"), myPackage); pp.writeAll(new File(directoryBase, "resource"), packageName);
} }
ourLog.info("Writing Resources..."); ourLog.info("Writing Resources...");
rp.writeAll(new File(directoryBase, "resource"), myPackage); rp.writeAll(new File(directoryBase, "resource"), packageName);
ourLog.info("Writing Composite Datatypes..."); ourLog.info("Writing Composite Datatypes...");
dtp.writeAll(new File(directoryBase, "composite"), myPackage); dtp.writeAll(new File(directoryBase, "composite"), packageName);
ourLog.info("Writing ValueSet Enums..."); ourLog.info("Writing ValueSet Enums...");
vsp.writeMarkedValueSets(new File(directoryBase, "valueset"), myPackage); vsp.writeMarkedValueSets(new File(directoryBase, "valueset"), packageName);
myProject.addCompileSourceRoot(myTargetDirectory); myProject.addCompileSourceRoot(targetDirectory);
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {

View File

@ -243,6 +243,15 @@ public abstract class BaseElement {
myExtensionUrl = theExtensionUrl; myExtensionUrl = theExtensionUrl;
} }
public boolean isExtensionModifier() {
return false; // TODO: implemment
}
public boolean isExtensionLocal() {
return false; // TODO: implemment
}
public boolean isHasExtensionUrl() { public boolean isHasExtensionUrl() {
return StringUtils.isNotBlank(myExtensionUrl); return StringUtils.isNotBlank(myExtensionUrl);
} }

View File

@ -1,6 +1,8 @@
package ca.uhn.fhir.tinder.model; package ca.uhn.fhir.tinder.model;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
@ -13,6 +15,7 @@ public class RestResourceTm {
private String myResourceType; private String myResourceType;
private Map<RestfulOperationTypeEnum, RestResourceOperationTm> mySupportedOperations = new HashMap<RestfulOperationTypeEnum, RestResourceOperationTm>(); private Map<RestfulOperationTypeEnum, RestResourceOperationTm> mySupportedOperations = new HashMap<RestfulOperationTypeEnum, RestResourceOperationTm>();
private ArrayList<SearchParameter> mySearchParams;
public RestResourceTm(RestResource theResource) { public RestResourceTm(RestResource theResource) {
myResourceType = theResource.getType().getValue(); myResourceType = theResource.getType().getValue();
@ -51,4 +54,11 @@ public class RestResourceTm {
return myResourceType; return myResourceType;
} }
public List<SearchParameter> getSearchParams() {
if (mySearchParams == null) {
mySearchParams = new ArrayList<SearchParameter>();
}
return mySearchParams;
}
} }

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.tinder.model; package ca.uhn.fhir.tinder.model;
import org.apache.commons.lang.WordUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public class SearchParameter { public class SearchParameter {
@ -21,6 +22,10 @@ public class SearchParameter {
return myName; return myName;
} }
public String getNameCapitalized() {
return WordUtils.capitalize(myName);
}
public String getPath() { public String getPath() {
return StringUtils.defaultString(myPath); return StringUtils.defaultString(myPath);
} }

View File

@ -47,8 +47,23 @@ public interface ${className} extends IMetadataClient {
*/ */
@Read @Read
${resource.resourceType} get${resource.resourceType}ById(@Read.IdParam IdDt theId, @Read.VersionIdParam IdDt theVersionId); ${resource.resourceType} get${resource.resourceType}ById(@Read.IdParam IdDt theId, @Read.VersionIdParam IdDt theVersionId);
#end
#if ( ${resource.hasSearchOperation} )
#foreach ( $param in $resource.searchParams )
/**
* Searches for ${resource.resourceType} resource(s)
#if ( ${resource.readOperation.hasDocumentation} )
* <p>
* Documentation: ${resource.readOperation.documentation}
* </p>
#end
*/
@Search
${resource.resourceType} search${resource.resourceType}By${param.nameCapitalized}(@Required(name=${resource.resourceType}.${param.constantName}) StringDt the${param.nameCapitalized});
#end #end
#end #end
#end
} }

View File

@ -6,9 +6,10 @@ import java.util.*;
import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.annotation.*; import ca.uhn.fhir.model.api.annotation.*;
import ca.uhn.fhir.model.primitive.*; import ca.uhn.fhir.model.primitive.*;
import ca.uhn.fhir.model.dstu.composite.*; //import ca.uhn.fhir.model.dstu.composite.*;
//import ${packageBase}.valueset.*; import ${packageBase}.composite.*;
import ${packageBase}.valueset.*;
/** /**
* HAPI/FHIR <b>${className}</b> Resource * HAPI/FHIR <b>${className}</b> Resource

View File

@ -16,7 +16,7 @@
@Child(name="${child.elementNameSimplified}", type=${child.annotationType}.class, order=${foreach.index}, min=${child.cardMin}, max=${child.cardMaxForChildAnnotation}) @Child(name="${child.elementNameSimplified}", type=${child.annotationType}.class, order=${foreach.index}, min=${child.cardMin}, max=${child.cardMaxForChildAnnotation})
#end #end
#if ( $child.hasExtensionUrl ) #if ( $child.hasExtensionUrl )
@Extension(url = "${child.extensionUrl}") @Extension(url = "${child.extensionUrl}", isModifier=${child.extensionModifier}, definedLocally=${child.extensionLocal})
#end #end
#if (${includeDescriptionAnnotations}) #if (${includeDescriptionAnnotations})
@Description( @Description(

View File

@ -31,22 +31,34 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<executions> <executions>
<execution> <execution>
<id>structs</id>
<goals> <goals>
<goal>generate</goal> <goal>generate-structures</goal>
</goals> </goals>
<configuration>
<package>ca.uhn.tindertest</package>
<baseResourceNames>
<baseResourceName>patient</baseResourceName>
<baseResourceName>valueset</baseResourceName>
<baseResourceName>organization</baseResourceName>
<baseResourceName>device</baseResourceName>
<baseResourceName>location</baseResourceName>
<baseResourceName>practitioner</baseResourceName>
</baseResourceNames>
</configuration>
</execution>
<execution>
<id>client</id>
<goals>
<goal>generate-client</goal>
</goals>
<configuration>
<clientClassName>ca.uhn.hitest.HiTest</clientClassName>
<serverBaseHref>http://fhir.healthintersections.com.au/open</serverBaseHref>
<generateSearchForAllParams>true</generateSearchForAllParams>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration>
<package>ca.uhn.tindertest</package>
<baseResourceNames>
<baseResourceName>patient</baseResourceName>
<baseResourceName>valueset</baseResourceName>
<baseResourceName>organization</baseResourceName>
<baseResourceName>device</baseResourceName>
<baseResourceName>location</baseResourceName>
<baseResourceName>practitioner</baseResourceName>
</baseResourceNames>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>