diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java
index e22911d7507..e83b42d05db 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java
@@ -51,16 +51,8 @@ public class ReflectionUtil {
}
public static Class> getGenericCollectionTypeOfField(Field next) {
- Class> type;
ParameterizedType collectionType = (ParameterizedType) next.getGenericType();
- Type firstArg = collectionType.getActualTypeArguments()[0];
- if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
- ParameterizedType pt = ((ParameterizedType) firstArg);
- type = (Class>) pt.getRawType();
- } else {
- type = (Class>) firstArg;
- }
- return type;
+ return getGenericCollectionTypeOf(collectionType.getActualTypeArguments()[0]);
}
/**
@@ -84,42 +76,37 @@ public class ReflectionUtil {
}
public static Class> getGenericCollectionTypeOfMethodParameter(Method theMethod, int theParamIndex) {
- Class> type;
Type genericParameterType = theMethod.getGenericParameterTypes()[theParamIndex];
if (Class.class.equals(genericParameterType) || Class.class.equals(genericParameterType.getClass())) {
return null;
}
ParameterizedType collectionType = (ParameterizedType) genericParameterType;
- Type firstArg = collectionType.getActualTypeArguments()[0];
- if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
- ParameterizedType pt = ((ParameterizedType) firstArg);
- type = (Class>) pt.getRawType();
- } else {
- type = (Class>) firstArg;
- }
- return type;
+ return getGenericCollectionTypeOf(collectionType.getActualTypeArguments()[0]);
}
- @SuppressWarnings({ "rawtypes" })
public static Class> getGenericCollectionTypeOfMethodReturnType(Method theMethod) {
- Class> type;
Type genericReturnType = theMethod.getGenericReturnType();
if (!(genericReturnType instanceof ParameterizedType)) {
return null;
}
ParameterizedType collectionType = (ParameterizedType) genericReturnType;
- Type firstArg = collectionType.getActualTypeArguments()[0];
- if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
- ParameterizedType pt = ((ParameterizedType) firstArg);
+ return getGenericCollectionTypeOf(collectionType.getActualTypeArguments()[0]);
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private static Class> getGenericCollectionTypeOf(Type theType) {
+ Class> type;
+ if (ParameterizedType.class.isAssignableFrom(theType.getClass())) {
+ ParameterizedType pt = ((ParameterizedType) theType);
type = (Class>) pt.getRawType();
- } else if (firstArg instanceof TypeVariable>) {
- Type decl = ((TypeVariable) firstArg).getBounds()[0];
+ } else if (theType instanceof TypeVariable>) {
+ Type decl = ((TypeVariable) theType).getBounds()[0];
return (Class>) decl;
- } else if (firstArg instanceof WildcardType) {
- Type decl = ((WildcardType) firstArg).getUpperBounds()[0];
+ } else if (theType instanceof WildcardType) {
+ Type decl = ((WildcardType) theType).getUpperBounds()[0];
return (Class>) decl;
} else {
- type = (Class>) firstArg;
+ type = (Class>) theType;
}
return type;
}
@@ -154,8 +141,7 @@ public class ReflectionUtil {
public static Object newInstanceOfFhirServerType(String theType) {
String errorMessage = "Unable to instantiate server framework. Please make sure that hapi-fhir-server library is on your classpath!";
String wantedType = "ca.uhn.fhir.rest.api.server.IFhirVersionServer";
- Object fhirServerVersion = newInstanceOfType(theType, errorMessage, wantedType);
- return fhirServerVersion;
+ return newInstanceOfType(theType, errorMessage, wantedType);
}
@SuppressWarnings("unchecked")
diff --git a/hapi-fhir-jaxrsserver-example/pom.xml b/hapi-fhir-jaxrsserver-example/pom.xml
index 63d7afa0de9..a91d125f5d5 100644
--- a/hapi-fhir-jaxrsserver-example/pom.xml
+++ b/hapi-fhir-jaxrsserver-example/pom.xml
@@ -1,7 +1,7 @@
4.0.0
-
ca.uhn.hapi.fhir
@@ -83,12 +83,22 @@
ch.qos.logback
logback-classic
-
- ca.uhn.hapi.fhir
- hapi-fhir-test-utilities
- ${project.version}
- test
-
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-test-utilities
+ ${project.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-noarg
+ ${kotlin.version}
+
@@ -118,7 +128,38 @@
true
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/main/java
+
+
+
+
+ test-compile
+ test-compile
+
+
+ ${project.basedir}/src/test/kotlin
+ ${project.basedir}/src/test/java
+
+
+
+
+
+
+ true
+ 1.3.50
+
diff --git a/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganization.kt b/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganization.kt
new file mode 100644
index 00000000000..05d61056891
--- /dev/null
+++ b/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganization.kt
@@ -0,0 +1,14 @@
+package cn.uhn.fhir.jaxrs.server.example
+
+import ca.uhn.fhir.model.api.annotation.ResourceDef
+import org.hl7.fhir.dstu3.model.BaseResource
+import org.hl7.fhir.dstu3.model.Organization
+import org.hl7.fhir.instance.model.api.IIdType
+
+@ResourceDef(name = "Organization")
+open class ExtendedOrganization : Organization() {
+
+ override fun setId(value: IIdType?): BaseResource? {
+ return this
+ }
+}
diff --git a/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResource.kt b/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResource.kt
new file mode 100644
index 00000000000..54ff9db16ba
--- /dev/null
+++ b/hapi-fhir-jaxrsserver-example/src/main/kotlin/cn/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResource.kt
@@ -0,0 +1,35 @@
+package cn.uhn.fhir.jaxrs.server.example
+
+import ca.uhn.fhir.context.FhirContext
+import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider
+import ca.uhn.fhir.model.api.Include
+import ca.uhn.fhir.rest.annotation.IncludeParam
+import ca.uhn.fhir.rest.annotation.OptionalParam
+import ca.uhn.fhir.rest.annotation.Search
+import ca.uhn.fhir.rest.api.Constants
+import ca.uhn.fhir.rest.param.StringParam
+import org.hl7.fhir.instance.model.api.IAnyResource
+import javax.ejb.Stateless
+import javax.ws.rs.Path
+import javax.ws.rs.Produces
+import javax.ws.rs.core.MediaType
+
+@Path("Organization")
+@Stateless
+@Produces(MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML)
+class ExtendedOrganizationResource : BaseResource() {
+ override fun getResourceType(): Class? = ExtendedOrganization::class.java
+
+ @Search
+ fun find(
+ @OptionalParam(name = "_id") theId: StringParam?,
+ @IncludeParam(allow = ["Patient:general-practitioner"]) includes: Collection?
+ ): List {
+ val organization = ExtendedOrganization().also {
+ it.id = "id"
+ }
+ return listOf(organization)
+ }
+}
+
+abstract class BaseResource: AbstractJaxRsResourceProvider(FhirContext.forDstu3())
diff --git a/hapi-fhir-jaxrsserver-example/src/test/kotlin/ca/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResourceTest.kt b/hapi-fhir-jaxrsserver-example/src/test/kotlin/ca/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResourceTest.kt
new file mode 100644
index 00000000000..edff3030942
--- /dev/null
+++ b/hapi-fhir-jaxrsserver-example/src/test/kotlin/ca/uhn/fhir/jaxrs/server/example/ExtendedOrganizationResourceTest.kt
@@ -0,0 +1,69 @@
+package ca.uhn.fhir.jaxrs.server.example
+
+import ca.uhn.fhir.test.utilities.JettyUtil
+import ca.uhn.fhir.util.TestUtil
+import cn.uhn.fhir.jaxrs.server.example.ExtendedOrganizationResource
+import org.apache.commons.lang3.StringUtils
+import org.eclipse.jetty.server.Server
+import org.eclipse.jetty.servlet.ServletContextHandler
+import org.hamcrest.CoreMatchers.`is`
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder
+import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
+import org.junit.AfterClass
+import org.junit.Assert.assertThat
+import org.junit.BeforeClass
+import org.junit.Test
+import javax.ws.rs.core.Response
+
+class ExtendedOrganizationResourceTest {
+
+ @Test
+ fun makeSureSearchDoesNotThrowOnIncludeParam() {
+ val response = ResteasyClientBuilder()
+ .build()
+ .target("http://localhost:$ourPort/Organization?_id=1")
+ .request()
+ .method("GET")
+ assertThat(
+ "This should not explode!",
+ response.status,
+ `is`(Response.Status.OK.statusCode)
+ )
+ }
+
+ companion object {
+ private var ourPort: Int = 0
+ private lateinit var jettyServer: Server
+
+ @JvmStatic
+ @AfterClass
+ @Throws(Exception::class)
+ fun afterClassClearContext() {
+ JettyUtil.closeServer(jettyServer)
+ TestUtil.clearAllStaticFieldsForUnitTest()
+ }
+
+ @JvmStatic
+ @BeforeClass
+ @Throws(Exception::class)
+ fun setUpClass() {
+ val context = ServletContextHandler(ServletContextHandler.SESSIONS).also {
+ it.contextPath = "/"
+ }
+ jettyServer = Server(0).also {
+ it.handler = context
+ }
+ val jerseyServlet = context.addServlet(HttpServletDispatcher::class.java, "/*").also {
+ it.initOrder = 0
+ //@formatter:off
+ it.setInitParameter(
+ "resteasy.resources",
+ StringUtils.join(listOf(ExtendedOrganizationResource::class.java.canonicalName), ",")
+ )
+ //@formatter:on
+ }
+ JettyUtil.startServer(jettyServer)
+ ourPort = JettyUtil.getPortForStartedServer(jettyServer)
+ }
+ }
+}
diff --git a/hapi-kotlin-test/pom.xml b/hapi-kotlin-test/pom.xml
new file mode 100644
index 00000000000..2ecc4d98617
--- /dev/null
+++ b/hapi-kotlin-test/pom.xml
@@ -0,0 +1,176 @@
+
+
+
+ hapi-fhir
+ ca.uhn.hapi.fhir
+ 4.1.0-SNAPSHOT
+
+ 4.0.0
+
+ hapi-kotlin-test
+
+ HAPI FHIR - Kotlin tests
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-jaxrsserver-base
+ ${project.version}
+
+
+
+
+
+
+
+
+
+
+
+
+ ca.uhn.hapi.fhir
+ org.hl7.fhir.dstu3
+ ${fhir_core_version}
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+ 2.0.1
+ provided
+
+
+
+
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty_version}
+
+
+ org.eclipse.jetty
+ jetty-servlet
+ ${jetty_version}
+
+
+ org.jboss.resteasy
+ resteasy-jaxrs
+
+
+ org.jboss.resteasy
+ resteasy-client
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-test-utilities
+ ${project.version}
+ test
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-base
+ ${project.version}
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-server
+ ${project.version}
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-testpage-overlay
+ ${project.version}
+ war
+ provided
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-testpage-overlay
+ ${project.version}
+ classes
+ provided
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-noarg
+ ${kotlin.version}
+
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/main/java
+
+
+
+
+ test-compile
+ test-compile
+
+
+ ${project.basedir}/src/test/kotlin
+ ${project.basedir}/src/test/java
+
+
+
+
+
+
+ no-arg
+ all-open
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+
+ ca.uhn.hapi.fhir.hapi-fhir-base
+
+
+
+
+
+
+
+
+ true
+ 1.3.50
+
+
diff --git a/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/Server.kt b/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/Server.kt
new file mode 100644
index 00000000000..ab030221cf7
--- /dev/null
+++ b/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/Server.kt
@@ -0,0 +1,15 @@
+package ca.uhn.fhir.rest.server
+
+import ca.uhn.fhir.rest.server.resources.ExtendedPatient
+import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider
+import org.hl7.fhir.instance.model.api.IAnyResource
+
+class Server : BaseResource() {
+ override fun getResourceType(): Class? = ExtendedPatient::class.java
+}
+
+abstract class BaseResource: AbstractJaxRsResourceProvider()
+
+fun main() {
+
+}
diff --git a/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/resources/ExtendedPatient.kt b/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/resources/ExtendedPatient.kt
new file mode 100644
index 00000000000..70ab2e347b8
--- /dev/null
+++ b/hapi-kotlin-test/src/main/kotlin/ca/uhn/fhir/rest/server/resources/ExtendedPatient.kt
@@ -0,0 +1,22 @@
+package ca.uhn.fhir.rest.server.resources
+
+import ca.uhn.fhir.model.api.annotation.Child
+import ca.uhn.fhir.model.api.annotation.Extension
+import ca.uhn.fhir.model.api.annotation.ResourceDef
+import org.hl7.fhir.dstu3.model.CodeableConcept
+import org.hl7.fhir.dstu3.model.Patient
+import org.hl7.fhir.instance.model.api.IBaseResource
+
+import java.util.Collections.emptyList
+
+@ResourceDef(name = "Patient")
+class ExtendedPatient : Patient() {
+
+ @Child(name = "status")
+ @Extension(
+ url = "http://some.url",
+ definedLocally = false,
+ isModifier = false
+ )
+ var status: List = emptyList()
+}