Parameter updates

This commit is contained in:
James Agnew 2018-05-10 11:19:28 -04:00
parent f6b1082ba4
commit b3bb5f9052
5 changed files with 135 additions and 70 deletions

View File

@ -17,6 +17,12 @@
<dependencies> <dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli-api</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli-jpaserver</artifactId> <artifactId>hapi-fhir-cli-jpaserver</artifactId>

View File

@ -1,32 +1,32 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>cli</id> <id>cli</id>
<formats> <formats>
<format>zip</format> <format>zip</format>
<format>tar.bz2</format> <format>tar.bz2</format>
</formats> </formats>
<includeBaseDirectory>false</includeBaseDirectory> <includeBaseDirectory>false</includeBaseDirectory>
<fileSets> <fileSets>
<fileSet> <fileSet>
<directory>${project.basedir}/../hapi-fhir-cli/hapi-fhir-cli-app/target/</directory> <directory>${project.basedir}/../hapi-fhir-cli/hapi-fhir-cli-app/target/</directory>
<outputDirectory>/</outputDirectory> <outputDirectory>/</outputDirectory>
<includes> <includes>
<include>hapi-fhir-cli.jar</include> <include>hapi-fhir-cli.jar</include>
</includes> </includes>
</fileSet> </fileSet>
<fileSet> <fileSet>
<directory>${project.basedir}/../hapi-fhir-cli/hapi-fhir-cli-app/src/main/script</directory> <directory>${project.basedir}/../hapi-fhir-cli/hapi-fhir-cli-api/src/main/script</directory>
<outputDirectory>/</outputDirectory> <outputDirectory>/</outputDirectory>
<includes> <includes>
<include>hapi-fhir-cli</include> <include>hapi-fhir-cli</include>
<include>hapi-fhir-cli.cmd</include> <include>hapi-fhir-cli.cmd</include>
</includes> </includes>
<fileMode>0555</fileMode> <fileMode>0555</fileMode>
</fileSet> </fileSet>
</fileSets> </fileSets>
</assembly> </assembly>

View File

@ -1,5 +1,35 @@
package ca.uhn.fhir.rest.server.method; package ca.uhn.fhir.rest.server.method;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.BaseAndListParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.binder.CollectionBinder;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ReflectionUtil;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
/* /*
@ -11,9 +41,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -22,43 +52,20 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* #L% * #L%
*/ */
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.param.binder.CollectionBinder;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ReflectionUtil;
public class OperationParameter implements IParameter { public class OperationParameter implements IParameter {
static final String REQUEST_CONTENTS_USERDATA_KEY = OperationParam.class.getName() + "_PARSED_RESOURCE";
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static final Class<? extends IQueryParameterType>[] COMPOSITE_TYPES = new Class[0]; private static final Class<? extends IQueryParameterType>[] COMPOSITE_TYPES = new Class[0];
static final String REQUEST_CONTENTS_USERDATA_KEY = OperationParam.class.getName() + "_PARSED_RESOURCE";
private boolean myAllowGet;
private final FhirContext myContext; private final FhirContext myContext;
private final String myName;
private final String myOperationName;
private boolean myAllowGet;
private IOperationParamConverter myConverter; private IOperationParamConverter myConverter;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private Class<? extends Collection> myInnerCollectionType; private Class<? extends Collection> myInnerCollectionType;
private int myMax; private int myMax;
private int myMin; private int myMin;
private final String myName;
private final String myOperationName;
private Class<?> myParameterType; private Class<?> myParameterType;
private String myParamType; private String myParamType;
private SearchParameter mySearchParameterBinding; private SearchParameter mySearchParameterBinding;
@ -75,7 +82,7 @@ public class OperationParameter implements IParameter {
myContext = theCtx; myContext = theCtx;
} }
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({"rawtypes", "unchecked"})
private void addValueToList(List<Object> matchingParamValues, Object values) { private void addValueToList(List<Object> matchingParamValues, Object values) {
if (values != null) { if (values != null) {
if (BaseAndListParam.class.isAssignableFrom(myParameterType) && matchingParamValues.size() > 0) { if (BaseAndListParam.class.isAssignableFrom(myParameterType) && matchingParamValues.size() > 0) {
@ -145,10 +152,10 @@ public class OperationParameter implements IParameter {
boolean typeIsConcrete = !myParameterType.isInterface() && !Modifier.isAbstract(myParameterType.getModifiers()); boolean typeIsConcrete = !myParameterType.isInterface() && !Modifier.isAbstract(myParameterType.getModifiers());
//@formatter:off //@formatter:off
boolean isSearchParam = boolean isSearchParam =
IQueryParameterType.class.isAssignableFrom(myParameterType) || IQueryParameterType.class.isAssignableFrom(myParameterType) ||
IQueryParameterOr.class.isAssignableFrom(myParameterType) || IQueryParameterOr.class.isAssignableFrom(myParameterType) ||
IQueryParameterAnd.class.isAssignableFrom(myParameterType); IQueryParameterAnd.class.isAssignableFrom(myParameterType);
//@formatter:off //@formatter:off
/* /*
@ -250,7 +257,7 @@ public class OperationParameter implements IParameter {
Object values = mySearchParameterBinding.parse(myContext, Collections.singletonList(next)); Object values = mySearchParameterBinding.parse(myContext, Collections.singletonList(next));
addValueToList(matchingParamValues, values); addValueToList(matchingParamValues, values);
} }
} }
} else { } else {
@ -274,7 +281,7 @@ public class OperationParameter implements IParameter {
matchingParamValues.add(next); matchingParamValues.add(next);
} }
} else if (ValidationModeEnum.class.equals(myParameterType)) { } else if (ValidationModeEnum.class.equals(myParameterType)) {
if (isNotBlank(paramValues[0])) { if (isNotBlank(paramValues[0])) {
ValidationModeEnum validationMode = ValidationModeEnum.forCode(paramValues[0]); ValidationModeEnum validationMode = ValidationModeEnum.forCode(paramValues[0]);
if (validationMode != null) { if (validationMode != null) {
@ -283,7 +290,7 @@ public class OperationParameter implements IParameter {
throwInvalidMode(paramValues[0]); throwInvalidMode(paramValues[0]);
} }
} }
} else { } else {
for (String nextValue : paramValues) { for (String nextValue : paramValues) {
FhirContext ctx = theRequest.getServer().getFhirContext(); FhirContext ctx = theRequest.getServer().getFhirContext();
@ -356,6 +363,13 @@ public class OperationParameter implements IParameter {
if (myConverter != null) { if (myConverter != null) {
nextValue = myConverter.incomingServer(nextValue); nextValue = myConverter.incomingServer(nextValue);
} }
if (myParameterType.equals(String.class)) {
if (nextValue instanceof IPrimitiveType<?>) {
IPrimitiveType<?> source = (IPrimitiveType<?>) nextValue;
theMatchingParamValues.add(source.getValueAsString());
continue;
}
}
if (!myParameterType.isAssignableFrom(nextValue.getClass())) { if (!myParameterType.isAssignableFrom(nextValue.getClass())) {
Class<? extends IBaseDatatype> sourceType = (Class<? extends IBaseDatatype>) nextValue.getClass(); Class<? extends IBaseDatatype> sourceType = (Class<? extends IBaseDatatype>) nextValue.getClass();
Class<? extends IBaseDatatype> targetType = (Class<? extends IBaseDatatype>) myParameterType; Class<? extends IBaseDatatype> targetType = (Class<? extends IBaseDatatype>) myParameterType;
@ -373,7 +387,7 @@ public class OperationParameter implements IParameter {
} }
throwWrongParamType(nextValue); throwWrongParamType(nextValue);
} }
addValueToList(theMatchingParamValues, nextValue); addValueToList(theMatchingParamValues, nextValue);
} }
} }

View File

@ -338,6 +338,29 @@ public class OperationServerR4Test {
assertEquals("RET1", resp.getParameter().get(0).getName()); assertEquals("RET1", resp.getParameter().get(0).getName());
} }
@Test
public void testOperationOnServerWithRawString() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/$OP_SERVER_WITH_RAW_STRING");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("$OP_SERVER", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test @Test
public void testOperationOnType() throws Exception { public void testOperationOnType() throws Exception {
Parameters p = new Parameters(); Parameters p = new Parameters();
@ -763,6 +786,23 @@ public class OperationServerR4Test {
return retVal; return retVal;
} }
//@formatter:off
@Operation(name="$OP_SERVER_WITH_RAW_STRING")
public Parameters opServer(
@OperationParam(name="PARAM1") String theParam1,
@OperationParam(name="PARAM2") Patient theParam2
) {
//@formatter:on
ourLastMethod = "$OP_SERVER";
ourLastParam1 = new StringType(theParam1);
ourLastParam2 = theParam2;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off //@formatter:off
@Operation(name="$OP_SERVER_LIST_PARAM") @Operation(name="$OP_SERVER_LIST_PARAM")
public Parameters opServerListParam( public Parameters opServerListParam(

View File

@ -127,6 +127,11 @@
Fix a bug in the DSTU2 QuestionnaireResponseValidator which prevented validation Fix a bug in the DSTU2 QuestionnaireResponseValidator which prevented validation
on groups with only one question. Thanks David Gileadi for the pull request! on groups with only one question. Thanks David Gileadi for the pull request!
</action> </action>
<action type="add">
Operation methods on a plain server may now use parameters
of type String (i.e. plain Java strings), and any FHIR primitive
datatype will be automatically coerced into a String.
</action>
</release> </release>
<release version="3.3.0" date="2018-03-29"> <release version="3.3.0" date="2018-03-29">
<action type="add"> <action type="add">