Merge branch 'ja_20190928_rationalize_search_param_extractor' of github.com:jamesagnew/hapi-fhir into ja_20190928_rationalize_search_param_extractor

This commit is contained in:
jamesagnew 2019-10-28 06:02:36 -04:00
commit 43d8798c1b
4 changed files with 131 additions and 84 deletions

View File

@ -25,7 +25,6 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation; import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.ParameterUtil; import ca.uhn.fhir.rest.param.ParameterUtil;
@ -46,18 +45,17 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class OperationMethodBinding extends BaseResourceReturningMethodBinding { public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationMethodBinding.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationMethodBinding.class);
private BundleTypeEnum myBundleType;
private String myDescription;
private final boolean myIdempotent; private final boolean myIdempotent;
private final Integer myIdParamIndex; private final Integer myIdParamIndex;
private final String myName; private final String myName;
private final RestOperationTypeEnum myOtherOperatiopnType; private final RestOperationTypeEnum myOtherOperationType;
private List<ReturnType> myReturnParams;
private final ReturnTypeEnum myReturnType; private final ReturnTypeEnum myReturnType;
private BundleTypeEnum myBundleType;
private String myDescription;
protected OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider, protected OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType, boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType,
OperationParam[] theReturnParams, BundleTypeEnum theBundleType) { BundleTypeEnum theBundleType) {
super(theReturnResourceType, theMethod, theContext, theProvider); super(theReturnResourceType, theMethod, theContext, theProvider);
myBundleType = theBundleType; myBundleType = theBundleType;
@ -77,7 +75,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
if (isBlank(theOperationName)) { if (isBlank(theOperationName)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName() throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName()
+ " but this annotation has no name defined"); + " but this annotation has no name defined");
} }
if (theOperationName.startsWith("$") == false) { if (theOperationName.startsWith("$") == false) {
theOperationName = "$" + theOperationName; theOperationName = "$" + theOperationName;
@ -97,45 +95,28 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
myReturnType = ReturnTypeEnum.RESOURCE; myReturnType = ReturnTypeEnum.RESOURCE;
if (getResourceName() == null) { if (getResourceName() == null) {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_SERVER; myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_SERVER;
} else if (myIdParamIndex == null) { } else if (myIdParamIndex == null) {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_TYPE; myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_TYPE;
} else { } else {
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE; myOtherOperationType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
}
myReturnParams = new ArrayList<>();
if (theReturnParams != null) {
for (OperationParam next : theReturnParams) {
ReturnType type = new ReturnType();
type.setName(next.name());
type.setMin(next.min());
type.setMax(next.max());
if (type.getMax() == OperationParam.MAX_DEFAULT) {
type.setMax(1);
}
if (!next.type().equals(IBase.class)) {
if (next.type().isInterface() || Modifier.isAbstract(next.type().getModifiers())) {
throw new ConfigurationException("Invalid value for @OperationParam.type(): " + next.type().getName());
}
type.setType(theContext.getElementDefinition(next.type()).getName());
}
myReturnParams.add(type);
}
} }
} }
public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider, public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
Operation theAnnotation) { Operation theAnnotation) {
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.returnParameters(), this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.bundleType());
theAnnotation.bundleType());
} }
public String getDescription() { public String getDescription() {
return myDescription; return myDescription;
} }
public void setDescription(String theDescription) {
myDescription = theDescription;
}
/** /**
* Returns the name of the operation, starting with "$" * Returns the name of the operation, starting with "$"
*/ */
@ -150,7 +131,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
@Override @Override
public RestOperationTypeEnum getRestOperationType() { public RestOperationTypeEnum getRestOperationType() {
return myOtherOperatiopnType; return myOtherOperationType;
} }
@Override @Override
@ -181,12 +162,8 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
return myIdempotent; return myIdempotent;
} }
public void setDescription(String theDescription) {
myDescription = theDescription;
}
public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theVersion, String theOperationName, IBaseParameters theInput, public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theVersion, String theOperationName, IBaseParameters theInput,
boolean theUseHttpGet) { boolean theUseHttpGet) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
if (theResourceName != null) { if (theResourceName != null) {
b.append(theResourceName); b.append(theResourceName);
@ -231,7 +208,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
} }
if (!(value instanceof IPrimitiveType)) { if (!(value instanceof IPrimitiveType)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can not invoke operation as HTTP GET when it has parameters with a composite (non priitive) datatype as the value. Found value: " + value.getClass().getName()); "Can not invoke operation as HTTP GET when it has parameters with a composite (non priitive) datatype as the value. Found value: " + value.getClass().getName());
} }
IPrimitiveType<?> primitive = (IPrimitiveType<?>) value; IPrimitiveType<?> primitive = (IPrimitiveType<?>) value;
params.get(nextName).add(primitive.getValueAsString()); params.get(nextName).add(primitive.getValueAsString());
@ -256,46 +233,4 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
} }
public static class ReturnType {
private int myMax;
private int myMin;
private String myName;
/**
* http://hl7-fhir.github.io/valueset-operation-parameter-type.html
*/
private String myType;
public int getMax() {
return myMax;
}
public int getMin() {
return myMin;
}
public String getName() {
return myName;
}
public String getType() {
return myType;
}
public void setMax(int theMax) {
myMax = theMax;
}
public void setMin(int theMin) {
myMin = theMin;
}
public void setName(String theName) {
myName = theName;
}
public void setType(String theType) {
myType = theType;
}
}
} }

View File

@ -40,7 +40,7 @@ public class ValidateMethodBindingDstu2Plus extends OperationMethodBinding {
public ValidateMethodBindingDstu2Plus(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider, public ValidateMethodBindingDstu2Plus(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
Validate theAnnotation) { Validate theAnnotation) {
super(null, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION); super(null, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), BundleTypeEnum.COLLECTION);
List<IParameter> newParams = new ArrayList<IParameter>(); List<IParameter> newParams = new ArrayList<IParameter>();
int idx = 0; int idx = 0;

View File

@ -0,0 +1,98 @@
package ca.uhn.fhir.jpa.searchparam.extractor;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SearchParamFinder {
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamFinder.class);
public static void main(String[] args) {
FhirContext ctx = FhirContext.forR5();
RestSearchParameterTypeEnum wantType = RestSearchParameterTypeEnum.NUMBER;
for (String nextResourceName : ctx.getResourceNames()) {
RuntimeResourceDefinition nextResDef = ctx.getResourceDefinition(nextResourceName);
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
if (nextSp.getParamType() == wantType) {
boolean logged = false;
for (String nextPath : nextSp.getPathsSplit()) {
List<String> pathsPart = new ArrayList<>(Arrays.asList(nextPath.split("\\.")));
BaseRuntimeElementCompositeDefinition def = null;
traverse(ctx, pathsPart, def);
// for (int i = 0; i < pathsPart.length; i++) {
// String nextPart = pathsPart[i];
//
// if (i == 0) {
// def = ctx.getResourceDefinition(nextPart);
// } else {
// BaseRuntimeChildDefinition child = def.getChildByName(nextPart);
// if (child == null) {
// child = def.getChildByName(nextPart + "[x]");
// }
// BaseRuntimeElementDefinition<?> childDef = child.getChildByName(nextPart);
// if (childDef instanceof RuntimePrimitiveDatatypeDefinition) {
// ourLog.info("SearchParam {} : {} : {} has {}", nextResourceName, nextSp.getName(), nextSp.getPath(), childDef.getName());
// logged = true;
// break;
// }
// def = (BaseRuntimeElementCompositeDefinition) childDef;
// }
//
// }
}
if (!logged) {
ourLog.info("SearchParam {} : {} : {}", nextResourceName, nextSp.getName(), nextSp.getPath());
}
}
}
}
}
private static void traverse(FhirContext theContext, List<String> thePathsPart, BaseRuntimeElementCompositeDefinition theDef) {
if (thePathsPart.size() == 0) {
ourLog.info("{} - {}", thePathsPart, theDef.getName());
return;
}
String nextName = thePathsPart.get(0);
if (theDef == null) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(nextName);
traverse(theContext, thePathsPart.subList(1, thePathsPart.size()), def);
} else {
BaseRuntimeChildDefinition child = theDef.getChildByName(nextName);
if (child != null) {
BaseRuntimeElementCompositeDefinition def = (BaseRuntimeElementCompositeDefinition) child.getChildByName(nextName);
traverse(theContext, thePathsPart.subList(1, thePathsPart.size()), def);
}
RuntimeChildChoiceDefinition choiceChild = (RuntimeChildChoiceDefinition) theDef.getChildByName(nextName + "[x]");
if (choiceChild != null){
for (String nextChildName : choiceChild.getValidChildNames()) {
if (nextChildName.startsWith(nextName)) {
BaseRuntimeElementCompositeDefinition def = (BaseRuntimeElementCompositeDefinition) choiceChild.getChildByName(nextChildName);
traverse(theContext, thePathsPart.subList(1, thePathsPart.size()), def);
}
}
}
}
}
}

View File

@ -0,0 +1,14 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] - %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>