From 551ffb43b4a715aa1b4457ea076cc8bfcff612bd Mon Sep 17 00:00:00 2001 From: James Agnew Date: Mon, 15 Dec 2014 17:41:24 -0500 Subject: [PATCH] More work on DEV operations --- .../java/ca/uhn/fhir/context/FhirContext.java | 2 + hapi-fhir-structures-dev/pom.xml | 8 +- .../dev/ServerConformanceProvider.java | 199 ++++++++--------- .../uhn/fhir/parser/MixedResourcesTest.java | 35 --- .../ca/uhn/fhir/rest/server/BinaryTest.java | 183 ++++++++++++++++ .../server/ServerConformanceProviderTest.java | 203 ++++++++++++++++++ hapi-fhir-structures-dstu/pom.xml | 6 +- hapi-fhir-testpage-overlay/.classpath | 170 --------------- .../main/java/ca/uhn/fhir/to/Controller.java | 14 +- .../ca/uhn/fhir/tinder/ValueSetGenerator.java | 5 +- .../org.eclipse.wst.common.component | 2 +- 11 files changed, 510 insertions(+), 317 deletions(-) delete mode 100644 hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/parser/MixedResourcesTest.java create mode 100644 hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/BinaryTest.java create mode 100644 hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java index 79b204fc342..06ffd467770 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java @@ -112,6 +112,8 @@ public class FhirContext { myVersion = theVersion.getVersionImplementation(); } else if (FhirVersionEnum.DSTU1.isPresentOnClasspath()) { myVersion = FhirVersionEnum.DSTU1.getVersionImplementation(); + } else if (FhirVersionEnum.DEV.isPresentOnClasspath()) { + myVersion = FhirVersionEnum.DEV.getVersionImplementation(); } else { throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructures")); } diff --git a/hapi-fhir-structures-dev/pom.xml b/hapi-fhir-structures-dev/pom.xml index 523d860781d..6898b09c5f0 100644 --- a/hapi-fhir-structures-dev/pom.xml +++ b/hapi-fhir-structures-dev/pom.xml @@ -29,12 +29,14 @@ + junit junit @@ -338,13 +340,13 @@ - ${baseDir}/src/main/resources + ${basedir}/src/main/resources - ${baseDir}/target/generated-sources/tinder + ${basedir}/target/generated-sources/tinder - ${baseDir}/target/generated-resources/tinder + ${basedir}/target/generated-resources/tinder diff --git a/hapi-fhir-structures-dev/src/main/java/ca/uhn/fhir/rest/server/provider/dev/ServerConformanceProvider.java b/hapi-fhir-structures-dev/src/main/java/ca/uhn/fhir/rest/server/provider/dev/ServerConformanceProvider.java index f2e9ae9c740..73e6c93dcf6 100644 --- a/hapi-fhir-structures-dev/src/main/java/ca/uhn/fhir/rest/server/provider/dev/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dev/src/main/java/ca/uhn/fhir/rest/server/provider/dev/ServerConformanceProvider.java @@ -34,13 +34,16 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.dev.resource.Conformance; -import ca.uhn.fhir.model.dev.resource.OperationDefinition; import ca.uhn.fhir.model.dev.resource.Conformance.Rest; import ca.uhn.fhir.model.dev.resource.Conformance.RestOperation; import ca.uhn.fhir.model.dev.resource.Conformance.RestResource; +import ca.uhn.fhir.model.dev.resource.Conformance.RestResourceInteraction; import ca.uhn.fhir.model.dev.resource.Conformance.RestResourceSearchParam; +import ca.uhn.fhir.model.dev.resource.OperationDefinition; import ca.uhn.fhir.model.dev.resource.OperationDefinition.Parameter; import ca.uhn.fhir.model.dev.valueset.RestfulConformanceModeEnum; +import ca.uhn.fhir.model.dev.valueset.SystemRestfulInteractionEnum; +import ca.uhn.fhir.model.dev.valueset.TypeRestfulInteractionEnum; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; import ca.uhn.fhir.model.primitive.BooleanDt; import ca.uhn.fhir.model.primitive.CodeDt; @@ -56,16 +59,15 @@ import ca.uhn.fhir.rest.method.SearchParameter; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.ResourceBinding; import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.util.ExtensionConstants; /** * Server FHIR Provider which serves the conformance statement for a RESTful server implementation * *

- * Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is - * always returned unless {@link #setCache(boolean)} is called with a value of false. This means that if - * you are adding anything to the returned conformance instance on each call you should call - * setCache(false) in your provider constructor. + * Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is always returned unless {@link #setCache(boolean)} is called with a value of + * false. This means that if you are adding anything to the returned conformance instance on each call you should call setCache(false) in your provider constructor. *

*/ public class ServerConformanceProvider { @@ -80,9 +82,8 @@ public class ServerConformanceProvider { } /** - * Gets the value of the "publisher" that will be placed in the generated conformance statement. As this - * is a mandatory element, the value should not be null (although this is not enforced). The value defaults - * to "Not provided" but may be set to null, which will cause this element to be omitted. + * Gets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The + * value defaults to "Not provided" but may be set to null, which will cause this element to be omitted. */ public String getPublisher() { return myPublisher; @@ -103,9 +104,9 @@ public class ServerConformanceProvider { retVal.setPublisher(myPublisher); retVal.setDate(DateTimeDt.withCurrentTime()); - retVal.setFhirVersion("0.80"); // TODO: pull from model + retVal.setFhirVersion("0.4.0"); // TODO: pull from model retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser needs to be modified to actually allow it - + retVal.getImplementation().setDescription(myRestfulServer.getImplementationDescription()); retVal.getSoftware().setName(myRestfulServer.getServerName()); retVal.getSoftware().setVersion(myRestfulServer.getServerVersion()); @@ -115,78 +116,86 @@ public class ServerConformanceProvider { Rest rest = retVal.addRest(); rest.setMode(RestfulConformanceModeEnum.SERVER); -// Set systemOps = new HashSet(); -// -// List bindings = new ArrayList(myRestfulServer.getResourceBindings()); -// Collections.sort(bindings, new Comparator() { -// @Override -// public int compare(ResourceBinding theArg0, ResourceBinding theArg1) { -// return theArg0.getResourceName().compareToIgnoreCase(theArg1.getResourceName()); -// } -// }); -// -// for (ResourceBinding next : bindings) { -// -// Set resourceOps = new HashSet(); -// RestResource resource = rest.addResource(); -// -// String resourceName = next.getResourceName(); -// RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceName); -// resource.getType().setValue(def.getName()); -// resource.getProfile().setReference(new IdDt(def.getResourceProfile())); -// -// TreeSet includes = new TreeSet(); -// -// // Map nameToSearchParam = new HashMap(); -// for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) { -// RestfulOperationTypeEnum resOp = nextMethodBinding.getResourceOperationType(); -// if (resOp != null) { -// if (resourceOps.contains(resOp) == false) { -// resourceOps.add(resOp); -// resource.addOperation().setCode(resOp); -// } -// } -// -// RestfulOperationSystemEnum sysOp = nextMethodBinding.getSystemOperationType(); -// if (sysOp != null) { -// if (systemOps.contains(sysOp) == false) { -// systemOps.add(sysOp); -// rest.addOperation().setCode(sysOp); -// } -// } -// -// if (nextMethodBinding instanceof SearchMethodBinding) { -// handleSearchMethodBinding(rest, resource, resourceName, def, includes, (SearchMethodBinding) nextMethodBinding); -// } else if (nextMethodBinding instanceof DynamicSearchMethodBinding) { -// handleDynamicSearchMethodBinding(resource, def, includes, (DynamicSearchMethodBinding) nextMethodBinding); -// } -// -// Collections.sort(resource.getOperation(), new Comparator() { -// @Override -// public int compare(RestResourceOperation theO1, RestResourceOperation theO2) { -// RestfulOperationTypeEnum o1 = theO1.getCode().getValueAsEnum(); -// RestfulOperationTypeEnum o2 = theO2.getCode().getValueAsEnum(); -// if (o1 == null && o2 == null) { -// return 0; -// } -// if (o1 == null) { -// return 1; -// } -// if (o2 == null) { -// return -1; -// } -// return o1.ordinal() - o2.ordinal(); -// } -// }); -// -// } -// -// for (String nextInclude : includes) { -// resource.addSearchInclude(nextInclude); -// } -// -// } + Set systemOps = new HashSet(); + + List bindings = new ArrayList(myRestfulServer.getResourceBindings()); + Collections.sort(bindings, new Comparator() { + @Override + public int compare(ResourceBinding theArg0, ResourceBinding theArg1) { + return theArg0.getResourceName().compareToIgnoreCase(theArg1.getResourceName()); + } + }); + + for (ResourceBinding next : bindings) { + + Set resourceOps = new HashSet(); + RestResource resource = rest.addResource(); + + String resourceName = next.getResourceName(); + RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceName); + resource.getTypeElement().setValue(def.getName()); + resource.getProfile().setReference(new IdDt(def.getResourceProfile())); + + TreeSet includes = new TreeSet(); + + // Map nameToSearchParam = new HashMap(); + for (BaseMethodBinding nextMethodBinding : next.getMethodBindings()) { + String resOpCode = nextMethodBinding.getResourceOperationType().getCode(); + if (resOpCode != null) { + TypeRestfulInteractionEnum resOp = TypeRestfulInteractionEnum.VALUESET_BINDER.fromCodeString(resOpCode); + if (resOp == null) { + throw new InternalErrorException("Unknown type-restful-interaction: " + resOpCode); + } + if (resourceOps.contains(resOp) == false) { + resourceOps.add(resOp); + resource.addInteraction().setCode(resOp); + } + } + + String sysOpCode = nextMethodBinding.getSystemOperationType().getCode(); + if (sysOpCode != null) { + SystemRestfulInteractionEnum sysOp = SystemRestfulInteractionEnum.VALUESET_BINDER.fromCodeString(sysOpCode); + if (sysOp == null) { + throw new InternalErrorException("Unknown system-restful-interaction: " + sysOpCode); + } + if (systemOps.contains(sysOp) == false) { + systemOps.add(sysOp); + rest.addInteraction().setCode(sysOp); + } + } + + if (nextMethodBinding instanceof SearchMethodBinding) { + handleSearchMethodBinding(rest, resource, resourceName, def, includes, (SearchMethodBinding) nextMethodBinding); + } else if (nextMethodBinding instanceof DynamicSearchMethodBinding) { + handleDynamicSearchMethodBinding(resource, def, includes, (DynamicSearchMethodBinding) nextMethodBinding); + } + + Collections.sort(resource.getInteraction(), new Comparator() { + @Override + public int compare(RestResourceInteraction theO1, RestResourceInteraction theO2) { + TypeRestfulInteractionEnum o1 = theO1.getCodeElement().getValueAsEnum(); + TypeRestfulInteractionEnum o2 = theO2.getCodeElement().getValueAsEnum(); + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } + return o1.ordinal() - o2.ordinal(); + } + }); + + } + + for (String nextInclude : includes) { + resource.addSearchInclude(nextInclude); + } + + } myConformance = retVal; return retVal; @@ -232,7 +241,7 @@ public class ServerConformanceProvider { // param.addChain(chain); // } param.setDocumentation(nextParamDescription); -// param.setType(nextParameter.getParamType()); + // param.setType(nextParameter.getParamType()); } } } @@ -288,25 +297,25 @@ public class ServerConformanceProvider { Parameter param; if (query == null) { -// param = resource.addSearchParam(); + // param = resource.addSearchParam(); } else { param = query.addParameter(); param.addUndeclaredExtension(false, ExtensionConstants.PARAM_IS_REQUIRED, new BooleanDt(nextParameter.isRequired())); } -// param.setName(nextParamName); + // param.setName(nextParamName); // if (StringUtils.isNotBlank(chain)) { // param.addChain(chain); // } -// param.setDocumentation(nextParamDescription); -// param.setType(nextParameter.getParamType()); + // param.setDocumentation(nextParamDescription); + // param.setType(nextParameter.getParamType()); for (Class nextTarget : nextParameter.getDeclaredTypes()) { RuntimeResourceDefinition targetDef = myRestfulServer.getFhirContext().getResourceDefinition(nextTarget); if (targetDef != null) { -// ResourceTypeEnum code = ResourceTypeEnum.VALUESET_BINDER.fromCodeString(targetDef.getName()); -// if (code != null) { -// param.addTarget(code); -// } + // ResourceTypeEnum code = ResourceTypeEnum.VALUESET_BINDER.fromCodeString(targetDef.getName()); + // if (code != null) { + // param.addTarget(code); + // } } } } @@ -314,8 +323,7 @@ public class ServerConformanceProvider { } /** - * Sets the cache property (default is true). If set to true, the same response will be returned for each - * invocation. + * Sets the cache property (default is true). If set to true, the same response will be returned for each invocation. *

* See the class documentation for an important note if you are extending this class *

@@ -325,9 +333,8 @@ public class ServerConformanceProvider { } /** - * Sets the value of the "publisher" that will be placed in the generated conformance statement. As this - * is a mandatory element, the value should not be null (although this is not enforced). The value defaults - * to "Not provided" but may be set to null, which will cause this element to be omitted. + * Sets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The + * value defaults to "Not provided" but may be set to null, which will cause this element to be omitted. */ public void setPublisher(String thePublisher) { myPublisher = thePublisher; diff --git a/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/parser/MixedResourcesTest.java b/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/parser/MixedResourcesTest.java deleted file mode 100644 index 7c69d480123..00000000000 --- a/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/parser/MixedResourcesTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package ca.uhn.fhir.parser; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.model.dstu.resource.Appointment; -import ca.uhn.fhir.model.primitive.DateTimeDt; - - -public class MixedResourcesTest { - - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MixedResourcesTest.class); - @Test - public void testMixedResources() { - - // dstu - Appointment a1 = new Appointment(); - a1.getSchedule().addEvent().setStart(new DateTimeDt("2001-01-02T12:00:00")); - - ca.uhn.fhir.model.dev.resource.Appointment a2 = new ca.uhn.fhir.model.dev.resource.Appointment(); - a2.getStartElement().setValueAsString("2001-01-02T12:00:00"); - - IParser parser = new FhirContext().newXmlParser(); - String string = parser.encodeResourceToString(a1); - ourLog.info(string); - assertEquals("", string); - - string = parser.encodeResourceToString(a2); - ourLog.info(string); - assertEquals("", string); - - } -} diff --git a/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/BinaryTest.java b/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/BinaryTest.java new file mode 100644 index 00000000000..8d53a9a31d4 --- /dev/null +++ b/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/BinaryTest.java @@ -0,0 +1,183 @@ +package ca.uhn.fhir.rest.server; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.dstu.resource.Binary; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.util.PortUtil; + +/** + * Created by dsotnikov on 2/25/2014. + */ +public class BinaryTest { + + private static CloseableHttpClient ourClient; + private static FhirContext ourCtx = new FhirContext(); + private static Binary ourLast; + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BinaryTest.class); + + private static int ourPort; + + private static Server ourServer; + + @Before + public void before() { + ourLast=null; + } + + @Test + public void testRead() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo"); + HttpResponse status = ourClient.execute(httpGet); + byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals("foo", status.getFirstHeader("content-type").getValue()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent); + + } + + + @Test + public void testCreate() throws Exception { + HttpPost http = new HttpPost("http://localhost:" + ourPort + "/Binary"); + http.setEntity(new ByteArrayEntity(new byte[] {1,2,3,4}, ContentType.create("foo/bar", "UTF-8"))); + + HttpResponse status = ourClient.execute(http); + assertEquals(201, status.getStatusLine().getStatusCode()); + + assertEquals("foo/bar; charset=UTF-8", ourLast.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, ourLast.getContent()); + + } + + public void testCreateWrongType() throws Exception { + Binary res = new Binary(); + res.setContent(new byte[] { 1, 2, 3, 4 }); + res.setContentType("text/plain"); + String stringContent = ourCtx.newJsonParser().encodeResourceToString(res); + + HttpPost http = new HttpPost("http://localhost:" + ourPort + "/Binary"); + http.setEntity(new StringEntity(stringContent, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"))); + + HttpResponse status = ourClient.execute(http); + assertEquals(201, status.getStatusLine().getStatusCode()); + + assertEquals("text/plain", ourLast.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, ourLast.getContent()); + + } + + @Test + public void testSearch() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary?"); + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_ATOM_XML + "; charset=UTF-8", status.getFirstHeader("content-type").getValue()); + + ourLog.info(responseContent); + + Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent); + Binary bin = (Binary) bundle.getEntries().get(0).getResource(); + + assertEquals("text/plain", bin.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, bin.getContent()); + } + @AfterClass + public static void afterClass() throws Exception { + ourServer.stop(); + } + + @BeforeClass + public static void beforeClass() throws Exception { + ourPort = PortUtil.findFreePort(); + ourServer = new Server(ourPort); + + ResourceProvider patientProvider = new ResourceProvider(); + + ServletHandler proxyHandler = new ServletHandler(); + RestfulServer servlet = new RestfulServer(); + servlet.setResourceProviders(patientProvider); + ServletHolder servletHolder = new ServletHolder(servlet); + proxyHandler.addServletWithMapping(servletHolder, "/*"); + ourServer.setHandler(proxyHandler); + ourServer.start(); + + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setConnectionManager(connectionManager); + ourClient = builder.build(); + + } + + /** + * Created by dsotnikov on 2/25/2014. + */ + public static class ResourceProvider implements IResourceProvider { + + @Create + public MethodOutcome create(@ResourceParam Binary theBinary) { + ourLast = theBinary; + return new MethodOutcome(new IdDt("1")); + } + + @Override + public Class getResourceType() { + return Binary.class; + } + + @Read + public Binary read(@IdParam IdDt theId) { + Binary retVal = new Binary(); + retVal.setId("1"); + retVal.setContent(new byte[] { 1, 2, 3, 4 }); + retVal.setContentType(theId.getIdPart()); + return retVal; + } + + + + @Search + public List search() { + Binary retVal = new Binary(); + retVal.setId("1"); + retVal.setContent(new byte[] { 1, 2, 3, 4 }); + retVal.setContentType("text/plain"); + return Collections.singletonList(retVal); + } + +} + +} diff --git a/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java b/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java new file mode 100644 index 00000000000..973e2d44fd4 --- /dev/null +++ b/hapi-fhir-structures-dev/src/test/java/ca/uhn/fhir/rest/server/ServerConformanceProviderTest.java @@ -0,0 +1,203 @@ +package ca.uhn.fhir.rest.server; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.dev.composite.IdentifierDt; +import ca.uhn.fhir.model.dev.resource.Conformance; +import ca.uhn.fhir.model.dev.resource.Conformance.Rest; +import ca.uhn.fhir.model.dev.resource.Conformance.RestResource; +import ca.uhn.fhir.model.dev.resource.DiagnosticReport; +import ca.uhn.fhir.model.dev.resource.OperationDefinition; +import ca.uhn.fhir.model.dev.resource.Patient; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.rest.annotation.IncludeParam; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RequiredParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.method.BaseMethodBinding; +import ca.uhn.fhir.rest.method.SearchMethodBinding; +import ca.uhn.fhir.rest.method.SearchParameter; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; +import ca.uhn.fhir.rest.server.provider.dev.ServerConformanceProvider; + +public class ServerConformanceProviderTest { + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerConformanceProviderTest.class); + private FhirContext myCtx = new FhirContext(); + + @Test + public void testSearchParameterDocumentation() throws Exception { + + RestfulServer rs = new RestfulServer(); + rs.setProviders(new SearchProvider()); + + ServerConformanceProvider sc = new ServerConformanceProvider(rs); + rs.setServerConformanceProvider(sc); + + rs.init(null); + + boolean found=false; + Collection resourceBindings = rs.getResourceBindings(); + for (ResourceBinding resourceBinding : resourceBindings) { + if (resourceBinding.getResourceName().equals("Patient")) { + List> methodBindings = resourceBinding.getMethodBindings(); + SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0); + SearchParameter param = (SearchParameter) binding.getParameters().iterator().next(); + assertEquals("The patient's identifier (MRN or other card number)", param.getDescription()); + found=true; + } + } + assertTrue(found); + Conformance conformance = sc.getServerConformance(); + + String conf = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance); + ourLog.info(conf); + + assertThat(conf, containsString("")); + assertThat(conf, containsString("")); + + } + + + @Test + public void testValidateGeneratedStatement() throws Exception { + + RestfulServer rs = new RestfulServer(); + rs.setProviders(new MultiOptionalProvider()); + + ServerConformanceProvider sc = new ServerConformanceProvider(rs); + rs.setServerConformanceProvider(sc); + + rs.init(null); + + Conformance conformance = sc.getServerConformance(); + + myCtx.newValidator().validate(conformance); + } + + + + @Test + public void testMultiOptionalDocumentation() throws Exception { + + RestfulServer rs = new RestfulServer(); + rs.setProviders(new MultiOptionalProvider()); + + ServerConformanceProvider sc = new ServerConformanceProvider(rs); + rs.setServerConformanceProvider(sc); + + rs.init(null); + + boolean found=false; + Collection resourceBindings = rs.getResourceBindings(); + for (ResourceBinding resourceBinding : resourceBindings) { + if (resourceBinding.getResourceName().equals("Patient")) { + List> methodBindings = resourceBinding.getMethodBindings(); + SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0); + SearchParameter param = (SearchParameter) binding.getParameters().iterator().next(); + assertEquals("The patient's identifier", param.getDescription()); + found=true; + } + } + assertTrue(found); + Conformance conformance = sc.getServerConformance(); + String conf = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance); + ourLog.info(conf); + + assertThat(conf, containsString("")); + assertThat(conf, containsString("")); + assertThat(conf, containsString("")); + } + + @Test + public void testProviderWithRequiredAndOptional() throws Exception { + + RestfulServer rs = new RestfulServer(); + rs.setProviders(new ProviderWithRequiredAndOptional()); + + ServerConformanceProvider sc = new ServerConformanceProvider(rs); + rs.setServerConformanceProvider(sc); + + rs.init(null); + + Conformance conformance = sc.getServerConformance(); + String conf = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance); + ourLog.info(conf); + + Rest rest = conformance.getRestFirstRep(); + RestResource res = rest.getResourceFirstRep(); + assertEquals("DiagnosticReport", res.getType()); + + OperationDefinition p0 = (OperationDefinition) rest.getOperationFirstRep().getDefinition().getResource(); + assertEquals("subject.identifier", p0.getParameterFirstRep().getName()); + + assertEquals(1,res.getSearchInclude().size()); + assertEquals("DiagnosticReport.result", res.getSearchIncludeFirstRep().getValue()); + } + + + /** + * Created by dsotnikov on 2/25/2014. + */ + @SuppressWarnings("unused") + public static class SearchProvider { + + @Search(type = Patient.class) + public Patient findPatient( + @Description(shortDefinition = "The patient's identifier (MRN or other card number)") + @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) { + return null; + } + + } + + + /** + * Created by dsotnikov on 2/25/2014. + */ + @SuppressWarnings("unused") + public static class MultiOptionalProvider { + + @Search(type = Patient.class) + public Patient findPatient( + @Description(shortDefinition = "The patient's identifier") + @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier, + @Description(shortDefinition = "The patient's name") + @OptionalParam(name=Patient.SP_NAME) StringDt theName) { + return null; + } + + } + + + public static class ProviderWithRequiredAndOptional { + + @Description(shortDefinition="This is a search for stuff!") + @Search + public List findDiagnosticReportsByPatient ( + @RequiredParam(name=DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId, + @OptionalParam(name=DiagnosticReport.SP_NAME) TokenOrListParam theNames, + @OptionalParam(name=DiagnosticReport.SP_DATE) DateRangeParam theDateRange, + @IncludeParam(allow= {"DiagnosticReport.result"}) Set theIncludes + ) throws Exception { + return null; + } + + + } + + +} diff --git a/hapi-fhir-structures-dstu/pom.xml b/hapi-fhir-structures-dstu/pom.xml index 609667bb495..cfb53a19aef 100644 --- a/hapi-fhir-structures-dstu/pom.xml +++ b/hapi-fhir-structures-dstu/pom.xml @@ -305,13 +305,13 @@ - ${baseDir}/src/main/resources + ${basedir}/src/main/resources - ${baseDir}/target/generated-sources/tinder + ${basedir}/target/generated-sources/tinder - ${baseDir}/target/generated-resources/tinder + ${basedir}/target/generated-resources/tinder diff --git a/hapi-fhir-testpage-overlay/.classpath b/hapi-fhir-testpage-overlay/.classpath index 5f121c3e99b..9dc486f04e2 100644 --- a/hapi-fhir-testpage-overlay/.classpath +++ b/hapi-fhir-testpage-overlay/.classpath @@ -14,178 +14,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java index 1cb52eaf2c8..6a0d0c8a38e 100644 --- a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java +++ b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java @@ -131,6 +131,7 @@ public class Controller { return "result"; } + @SuppressWarnings("unchecked") @RequestMapping(value = { "/delete" }) public String actionDelete(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { addCommonParams(theRequest, theModel); @@ -157,7 +158,7 @@ public class Controller { long start = System.currentTimeMillis(); try { - client.delete(def.getImplementingClass(), new IdDt(id)); + client.delete((Class) def.getImplementingClass(), new IdDt(id)); } catch (Exception e) { returnsResource = handleClientException(client, e, theModel); } @@ -191,7 +192,7 @@ public class Controller { return "resource"; } - resType = def.getImplementingClass(); + resType = (Class) def.getImplementingClass(); String id = theReq.getParameter("resource-tags-id"); if (isNotBlank(id)) { String vid = theReq.getParameter("resource-tags-vid"); @@ -384,7 +385,7 @@ public class Controller { if (isNotBlank(theRequest.getUpdateId())) { String updateId = theRequest.getUpdateId(); String updateVid = defaultIfEmpty(theRequest.getUpdateVid(), null); - IResource updateResource = client.read(def.getImplementingClass(), new IdDt(resourceName, updateId, updateVid)); + IResource updateResource = (IResource) client.read(def.getImplementingClass(), new IdDt(resourceName, updateId, updateVid)); String updateResourceString = theRequest.newParser(myCtx).setPrettyPrint(true).encodeResourceToString(updateResource); theModel.put("updateResource", updateResourceString); theModel.put("updateResourceId", updateId); @@ -461,6 +462,7 @@ public class Controller { } + @SuppressWarnings("unchecked") @RequestMapping(value = { "/search" }) public String actionSearch(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { addCommonParams(theRequest, theModel); @@ -478,7 +480,7 @@ public class Controller { IQuery query; if (isNotBlank(theReq.getParameter("resource"))) { try { - query = search.forResource(getResourceType(theReq).getImplementingClass()); + query = search.forResource((Class)getResourceType(theReq).getImplementingClass()); } catch (ServletException e) { theModel.put("errorMsg", e.toString()); return "resource"; @@ -658,7 +660,7 @@ public class Controller { Class type = null; // def.getImplementingClass(); if ("history-type".equals(theMethod)) { RuntimeResourceDefinition def = myCtx.getResourceDefinition(theRequest.getResource()); - type = def.getImplementingClass(); + type = (Class) def.getImplementingClass(); } String body = validate ? theReq.getParameter("resource-validate-body") : theReq.getParameter("resource-create-body"); @@ -741,7 +743,7 @@ public class Controller { Class type = null; // def.getImplementingClass(); if ("history-type".equals(theMethod)) { RuntimeResourceDefinition def = myCtx.getResourceDefinition(theRequest.getResource()); - type = def.getImplementingClass(); + type = (Class) def.getImplementingClass(); id = StringUtils.defaultString(theReq.getParameter("resource-history-id")); } diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ValueSetGenerator.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ValueSetGenerator.java index 79b30d312c3..a53decaf0fd 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ValueSetGenerator.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ValueSetGenerator.java @@ -214,9 +214,8 @@ public class ValueSetGenerator { public static void main(String[] args) throws FileNotFoundException, IOException { - // p.setOutputDirectory("../hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/valueset/"); - // p.setOutputDirectory("target/generated/valuesets/ca/uhn/fhir/model/dstu/valueset"); - // p.parse(); + ValueSetGenerator p = new ValueSetGenerator("dev"); + p.parse(); } diff --git a/restful-server-example/.settings/org.eclipse.wst.common.component b/restful-server-example/.settings/org.eclipse.wst.common.component index 38e539885da..576cd601a1b 100644 --- a/restful-server-example/.settings/org.eclipse.wst.common.component +++ b/restful-server-example/.settings/org.eclipse.wst.common.component @@ -9,7 +9,7 @@ uses - + consumes