Tester now suports chained parameters
This commit is contained in:
parent
41f160ed67
commit
84af486d51
|
@ -23,8 +23,18 @@ package ca.uhn.fhir.rest.annotation;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
public @interface OptionalParam {
|
||||
String name();
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -23,8 +23,18 @@ package ca.uhn.fhir.rest.annotation;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
public @interface RequiredParam {
|
||||
String name();
|
||||
|
||||
/**
|
||||
* For resource reference parameters ({@link ReferenceParam}) this parameter may be
|
||||
* used to indicate the resource type(s) which may be referenced by this param
|
||||
*/
|
||||
Class<? extends IResource>[] targetTypes() default {};
|
||||
|
||||
}
|
||||
|
|
|
@ -187,6 +187,7 @@ public class ParameterUtil {
|
|||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((RequiredParam) nextAnnotation).name());
|
||||
parameter.setRequired(true);
|
||||
parameter.setDeclaredTypes(((RequiredParam) nextAnnotation).targetTypes());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
@ -194,6 +195,7 @@ public class ParameterUtil {
|
|||
SearchParameter parameter = new SearchParameter();
|
||||
parameter.setName(((OptionalParam) nextAnnotation).name());
|
||||
parameter.setRequired(false);
|
||||
parameter.setDeclaredTypes(((OptionalParam) nextAnnotation).targetTypes());
|
||||
parameter.setType(parameterType, innerCollectionType, outerCollectionType);
|
||||
extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
|
|
|
@ -25,13 +25,13 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
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.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
|
@ -45,6 +45,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
*/
|
||||
public class SearchParameter extends BaseQueryParameter {
|
||||
|
||||
private Class<? extends IResource>[] myDeclaredTypes;
|
||||
private String myDescription;
|
||||
private String myName;
|
||||
private IParamBinder myParamBinder;
|
||||
|
@ -60,14 +61,6 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
this.myRequired = theRequired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder retVal = new ToStringBuilder(this);
|
||||
retVal.append("name", myName);
|
||||
retVal.append("required", myRequired);
|
||||
return retVal.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -85,6 +78,10 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public Class<? extends IResource>[] getDeclaredTypes() {
|
||||
return myDeclaredTypes;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
@ -128,6 +125,10 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
return myParamBinder.parse(theString);
|
||||
}
|
||||
|
||||
public void setDeclaredTypes(Class<? extends IResource>[] theTypes) {
|
||||
myDeclaredTypes=theTypes;
|
||||
}
|
||||
|
||||
public void setDescription(String theDescription) {
|
||||
myDescription = theDescription;
|
||||
}
|
||||
|
@ -189,4 +190,12 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder retVal = new ToStringBuilder(this);
|
||||
retVal.append("name", myName);
|
||||
retVal.append("required", myRequired);
|
||||
return retVal.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,15 +32,18 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
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.RestQuery;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceOperation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceSearchParam;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulConformanceModeEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -164,10 +167,12 @@ public class ServerConformanceProvider {
|
|||
for (SearchParameter nextParameter : searchParameters) {
|
||||
|
||||
String nextParamName = nextParameter.getName();
|
||||
String chain = null;
|
||||
|
||||
// String chain = null;
|
||||
String nextParamUnchainedName = nextParamName;
|
||||
if (nextParamName.contains(".")) {
|
||||
chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
// chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamUnchainedName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
}
|
||||
|
||||
String nextParamDescription = nextParameter.getDescription();
|
||||
|
@ -176,7 +181,7 @@ public class ServerConformanceProvider {
|
|||
* If the parameter has no description, default to the one from the resource
|
||||
*/
|
||||
if (StringUtils.isBlank(nextParamDescription)) {
|
||||
RuntimeSearchParam paramDef = def.getSearchParam(nextParamName);
|
||||
RuntimeSearchParam paramDef = def.getSearchParam(nextParamUnchainedName);
|
||||
if (paramDef != null) {
|
||||
nextParamDescription = paramDef.getDescription();
|
||||
}
|
||||
|
@ -191,11 +196,20 @@ public class ServerConformanceProvider {
|
|||
}
|
||||
|
||||
param.setName(nextParamName);
|
||||
if (StringUtils.isNotBlank(chain)) {
|
||||
param.addChain(chain);
|
||||
}
|
||||
// if (StringUtils.isNotBlank(chain)) {
|
||||
// param.addChain(chain);
|
||||
// }
|
||||
param.setDocumentation(nextParamDescription);
|
||||
param.setType(nextParameter.getParamType());
|
||||
for (Class<? extends IResource> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -680,7 +680,7 @@
|
|||
<p>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
<code>http://fhir.example.com/Observation?value-quantity=%lt;=123.2||mg</code>
|
||||
<code>http://fhir.example.com/Observation?value-quantity=<=123.2||mg</code>
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
|
|
@ -23,8 +23,13 @@ import org.junit.Test;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceSearchParam;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
@ -111,6 +116,28 @@ public class ReferenceParameterTest {
|
|||
assertEquals("2name", p.getName().get(2).getFamilyFirstRep().getValue());
|
||||
}
|
||||
}
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ReferenceParameterTest.class);
|
||||
@Test
|
||||
public void testParamTypesInConformanceStatement() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata?_pretty=true");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Conformance conf = ourCtx.newXmlParser().parseResource(Conformance.class,responseContent);
|
||||
|
||||
RestResource res = conf.getRestFirstRep().getResourceFirstRep();
|
||||
assertEquals("Patient", res.getType().getValue());
|
||||
|
||||
RestResourceSearchParam param = res.getSearchParamFirstRep();
|
||||
assertEquals(Patient.SP_PROVIDER, param.getName().getValue());
|
||||
|
||||
assertEquals(1, param.getTarget().size());
|
||||
assertEquals(ResourceTypeEnum.ORGANIZATION, param.getTarget().get(0).getValueAsEnum());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
|
@ -147,7 +174,7 @@ public class ReferenceParameterTest {
|
|||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Search
|
||||
public List<Patient> findPatient(@RequiredParam(name = Patient.SP_PROVIDER) ReferenceParam theParam) {
|
||||
public List<Patient> findPatient(@OptionalParam(name = Patient.SP_PROVIDER, targetTypes= {Organization.class}) ReferenceParam theParam) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient p = new Patient();
|
||||
|
|
|
@ -121,7 +121,7 @@ public class ServerConformanceProviderTest {
|
|||
assertEquals("DiagnosticReport", res.getType().getValueAsString());
|
||||
|
||||
RestQuery p0 = rest.getQueryFirstRep();
|
||||
assertEquals("subject", p0.getParameterFirstRep().getName().getValue());
|
||||
assertEquals("subject.identifier", p0.getParameterFirstRep().getName().getValue());
|
||||
|
||||
assertEquals(1,res.getSearchInclude().size());
|
||||
assertEquals("DiagnosticReport.result", res.getSearchIncludeFirstRep().getValue());
|
||||
|
|
|
@ -749,7 +749,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
private void validateResourceTypeAndThrowIllegalArgumentException(IdDt theId) {
|
||||
if (theId.hasResourceType() && !theId.getResourceType().equals(myResourceName)) {
|
||||
throw new IllegalArgumentException("Incorrect resource type (" + theId.getResourceType()+ ") for this DAO, wanted: " + myResourceName);
|
||||
throw new IllegalArgumentException("Incorrect resource type (" + theId.getResourceType() + ") for this DAO, wanted: " + myResourceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -916,7 +916,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
}
|
||||
};
|
||||
|
||||
ourLog.info("Processed search for {} on {} in {}ms", new Object[] {myResourceName, theParams, w.getMillisAndRestart()});
|
||||
ourLog.info("Processed search for {} on {} in {}ms", new Object[] { myResourceName, theParams, w.getMillisAndRestart() });
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -968,8 +968,12 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
for (IQueryParameterType next : nextValue) {
|
||||
String value = next.getValueAsQueryToken();
|
||||
IdDt valueId = new IdDt(value);
|
||||
try {
|
||||
long valueLong = translateForcedIdToPid(valueId);
|
||||
joinPids.add(valueLong);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// This isn't an error, just means no result found
|
||||
}
|
||||
}
|
||||
if (joinPids.isEmpty()) {
|
||||
continue;
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
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.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceSearchParam;
|
||||
import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
|
||||
|
@ -16,9 +24,11 @@ public class JpaConformanceProvider extends ServerConformanceProvider {
|
|||
private String myImplementationDescription;
|
||||
private IFhirSystemDao mySystemDao;
|
||||
private volatile Conformance myCachedValue;
|
||||
private RestfulServer myRestfulServer;
|
||||
|
||||
public JpaConformanceProvider(RestfulServer theRestfulServer, IFhirSystemDao theSystemDao) {
|
||||
super(theRestfulServer);
|
||||
myRestfulServer = theRestfulServer;
|
||||
mySystemDao = theSystemDao;
|
||||
super.setCache(false);
|
||||
|
||||
|
@ -41,13 +51,31 @@ public class JpaConformanceProvider extends ServerConformanceProvider {
|
|||
|
||||
Map<String, Long> counts = mySystemDao.getResourceCounts();
|
||||
|
||||
FhirContext ctx = myRestfulServer.getFhirContext();
|
||||
|
||||
retVal = super.getServerConformance();
|
||||
for (Rest nextRest : retVal.getRest()) {
|
||||
for (RestResource nextResource : nextRest.getResource()) {
|
||||
|
||||
// Add resource counts
|
||||
Long count = counts.get(nextResource.getType().getValueAsString());
|
||||
if (count != null) {
|
||||
nextResource.addUndeclaredExtension(false, ExtensionConstants.CONF_RESOURCE_COUNT, new DecimalDt(count));
|
||||
}
|
||||
|
||||
// Add chained params
|
||||
for (RestResourceSearchParam nextParam : nextResource.getSearchParam()) {
|
||||
if (nextParam.getType().getValueAsEnum() == SearchParamTypeEnum.REFERENCE) {
|
||||
List<BoundCodeDt<ResourceTypeEnum>> targets = nextParam.getTarget();
|
||||
for (BoundCodeDt<ResourceTypeEnum> next : targets) {
|
||||
RuntimeResourceDefinition def = ctx.getResourceDefinition(next.getValue());
|
||||
for (RuntimeSearchParam nextChainedParam : def.getSearchParams()) {
|
||||
nextParam.addChain(nextChainedParam.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,17 @@ public class FhirResourceDaoTest {
|
|||
assertEquals(o1id.toUnqualifiedVersionless(), p1.getManagingOrganization().getReference().toUnqualifiedVersionless());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchForUnknownAlphanumericId() {
|
||||
{
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add("_id", new StringParam("testSearchForUnknownAlphanumericId"));
|
||||
IBundleProvider retrieved = ourPatientDao.search(map);
|
||||
assertEquals(0, retrieved.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchTokenParam() {
|
||||
Patient patient = new Patient();
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<dependent-module archiveName="hapi-fhir-jpaserver-base-0.5-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-jpaserver-base/hapi-fhir-jpaserver-base">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module archiveName="hapi-fhir-base-0.5-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-testpage-overlay?includes=**/**&excludes=META-INF/MANIFEST.MF">
|
||||
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-tester-overlay?includes=**/**&excludes=META-INF/MANIFEST.MF">
|
||||
<dependency-type>consumes</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&excludes=META-INF/MANIFEST.MF">
|
||||
|
|
|
@ -64,9 +64,13 @@
|
|||
<th:block th:each="chain : ${param.chain}">
|
||||
chain.push('<th:block th:text="${chain}"/>');
|
||||
</th:block>
|
||||
var target = new Array();
|
||||
<th:block th:each="target : ${param.target}">
|
||||
target.push('<th:block th:text="${target}"/>');
|
||||
</th:block>
|
||||
var rowNum = <th:block th:text="${paramIterStat.index}"/>;
|
||||
var containerRowNum = <th:block th:text="${queryIterStat.index}"/> + '-' + rowNum;
|
||||
addSearchControls(type, name, chain, containerRowNum, rowNum);
|
||||
addSearchControls(conformance, type, name, chain, target, containerRowNum, rowNum);
|
||||
</script>
|
||||
<br clear="all"/>
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,7 @@ function addSearchParamRow() {
|
|||
$("#search-param-rows").append(rowDiv);
|
||||
|
||||
plusBtn.click(function() {
|
||||
plusBtn.hide();
|
||||
addSearchParamRow();
|
||||
});
|
||||
|
||||
|
@ -46,8 +47,8 @@ function addSearchParamRow() {
|
|||
});
|
||||
});
|
||||
select.select2();
|
||||
handleSearchParamTypeChange(select, params, nextRow);
|
||||
select.change(function(){ handleSearchParamTypeChange(select, params, nextRow); });
|
||||
handleSearchParamTypeChange(select, params, nextRow, nextRow);
|
||||
select.change(function(){ handleSearchParamTypeChange(select, params, nextRow, nextRow); });
|
||||
}
|
||||
|
||||
function updateSearchDateQualifier(qualifierBtn, qualifierInput, qualifier) {
|
||||
|
@ -59,19 +60,9 @@ function updateSearchDateQualifier(qualifierBtn, qualifierInput, qualifier) {
|
|||
}
|
||||
}
|
||||
|
||||
function addSearchControls(theSearchParamType, theSearchParamName, theSearchParamChain, theContainerRowNum, theRowNum) {
|
||||
|
||||
if (theSearchParamChain && theSearchParamChain.length > 0) {
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.qualifier', type: 'hidden', value: '.' + theSearchParamChain[0] })
|
||||
);
|
||||
}
|
||||
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.name', type: 'hidden', value: theSearchParamName }),
|
||||
$('<input />', { id: 'param.' + theRowNum + '.type', type: 'hidden', value: theSearchParamType })
|
||||
);
|
||||
function addSearchControls(theConformance, theSearchParamType, theSearchParamName, theSearchParamChain, theSearchParamTarget, theContainerRowNum, theRowNum) {
|
||||
|
||||
var addNameAndType = true;
|
||||
if (theSearchParamType == 'token') {
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<div />', { 'class': 'col-sm-3' }).append(
|
||||
|
@ -122,7 +113,24 @@ function addSearchControls(theSearchParamType, theSearchParamName, theSearchPara
|
|||
$('<input />', { id: 'param.' + theRowNum + '.0', placeholder: placeholderText, type: 'text', 'class': 'form-control' })
|
||||
)
|
||||
);
|
||||
} else if (theSearchParamType == 'number' || theSearchParamType == 'reference') {
|
||||
} else if (theSearchParamType == 'number') {
|
||||
var placeholderText = 'Number';
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.0', placeholder: placeholderText, type: 'hidden' })
|
||||
);
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<div />', { 'class': 'col-sm-3' }).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.1', placeholder: placeholderText, type: 'text', 'class': 'form-control' })
|
||||
)
|
||||
);
|
||||
} else if (theSearchParamType == 'date') {
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, true);
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, false);
|
||||
} else if (theSearchParamType == 'reference' && theSearchParamChain.length == 0) {
|
||||
/*
|
||||
* This is a reference parameter with no chain options, so just display a simple
|
||||
* text box for the ID of the referenced resource
|
||||
*/
|
||||
var placeholderText = 'value';
|
||||
if (theSearchParamType == 'number') {
|
||||
placeholderText = 'Number';
|
||||
|
@ -137,9 +145,71 @@ function addSearchControls(theSearchParamType, theSearchParamName, theSearchPara
|
|||
$('<input />', { id: 'param.' + theRowNum + '.1', placeholder: placeholderText, type: 'text', 'class': 'form-control' })
|
||||
)
|
||||
);
|
||||
} else if (theSearchParamType == 'date') {
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, true);
|
||||
addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum, false);
|
||||
} else if (theSearchParamType == 'reference' && theSearchParamChain.length > 0) {
|
||||
/*
|
||||
* This is a reference parameter with possible chain options, so we need
|
||||
* to display a secondary combobox to let the user choose which chained
|
||||
* parameter they are filling out
|
||||
*/
|
||||
var select = $('<select/>', {/*style:'margin-left:30px;'*/});
|
||||
|
||||
var newContainerRowNum = theContainerRowNum + "-0";
|
||||
var newContainer = $('<div />', { id: 'search-param-rowopts-' + newContainerRowNum })
|
||||
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<br clear="all" />'),
|
||||
$('<div />', { 'class': 'col-sm-1' }),
|
||||
$('<div />', { 'class': 'col-sm-1' }).append(
|
||||
$('<i class="glyphicon glyphicon-link" style="margin-left: 20px; margin-top: 10px;"/>')
|
||||
),
|
||||
$('<div />', { 'class': 'col-sm-4' }).append(
|
||||
select
|
||||
),
|
||||
newContainer
|
||||
);
|
||||
|
||||
// select.append(
|
||||
// $('<option />', { value: '' }).text('Resource ID')
|
||||
// );
|
||||
|
||||
var params = new Array();
|
||||
for (var chainIdx = 0; chainIdx < theSearchParamChain.length; chainIdx++) {
|
||||
var nextChain = theSearchParamChain[chainIdx];
|
||||
var found = false;
|
||||
for (var resIdx = 0; resIdx < theConformance.rest[0].resource.length && !found; resIdx++) {
|
||||
var nextRes = theConformance.rest[0].resource[resIdx];
|
||||
if (!(nextRes.searchParam)) {
|
||||
continue;
|
||||
}
|
||||
for (var paramIdx = 0; paramIdx < nextRes.searchParam.length && !found; paramIdx++) {
|
||||
var nextParam = nextRes.searchParam[paramIdx];
|
||||
if (nextParam.name == nextChain) {
|
||||
if (theSearchParamTarget.length == 0 || theSearchParamTarget.indexOf(nextRes.type) != -1) {
|
||||
var nextName = nextParam.name + '_' + i;
|
||||
nextParam = jQuery.extend({}, nextParam); // clone it so we can add the chain to the name
|
||||
nextParam.name = theSearchParamName + '.' + nextParam.name;
|
||||
params[nextName] = nextParam;
|
||||
select.append(
|
||||
$('<option />', { value: nextName }).text(nextParam.name + ' - ' + nextParam.documentation)
|
||||
);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select.select2();
|
||||
handleSearchParamTypeChange(select, params, newContainerRowNum, theRowNum);
|
||||
select.change(function(){ handleSearchParamTypeChange(select, params, newContainerRowNum, theRowNum); });
|
||||
addNameAndType = false;
|
||||
}
|
||||
|
||||
if (addNameAndType) {
|
||||
$('#search-param-rowopts-' + theContainerRowNum).append(
|
||||
$('<input />', { id: 'param.' + theRowNum + '.name', type: 'hidden', value: theSearchParamName }),
|
||||
$('<input />', { id: 'param.' + theRowNum + '.type', type: 'hidden', value: theSearchParamType })
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -202,20 +272,20 @@ function addSearchControlDate(theSearchParamName, theContainerRowNum, theRowNum,
|
|||
);
|
||||
}
|
||||
|
||||
function handleSearchParamTypeChange(select, params, rowNum) {
|
||||
function handleSearchParamTypeChange(select, params, theContainerRowNum, theParamRowNum) {
|
||||
var oldVal = select.prevVal;
|
||||
var newVal = select.val();
|
||||
if (oldVal == newVal) {
|
||||
return;
|
||||
}
|
||||
$('#search-param-rowopts-' + rowNum).empty();
|
||||
$('#search-param-rowopts-' + theContainerRowNum).empty();
|
||||
var searchParam = params[newVal];
|
||||
/*
|
||||
$('#search-param-rowopts-' + rowNum).append(
|
||||
$('<input />', { name: 'param.' + rowNum + '.type', type: 'hidden', value: searchParam.type })
|
||||
);
|
||||
*/
|
||||
addSearchControls(searchParam.type, searchParam.name, searchParam.chain, rowNum, rowNum);
|
||||
addSearchControls(conformance, searchParam.type, searchParam.name, searchParam.chain, searchParam.target, theContainerRowNum, theParamRowNum);
|
||||
|
||||
select.prevVal = newVal;
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ public class TinderJpaRestServerMojo extends AbstractMojo {
|
|||
|
||||
TinderJpaRestServerMojo mojo = new TinderJpaRestServerMojo();
|
||||
mojo.packageBase = "ca.uhn.test";
|
||||
mojo.baseResourceNames = java.util.Collections.singletonList("patient");
|
||||
mojo.baseResourceNames = java.util.Collections.singletonList("observation");
|
||||
mojo.targetDirectory = new File("target/gen");
|
||||
mojo.execute();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package ca.uhn.fhir.tinder.model;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.emory.mathcs.backport.java.util.Collections;
|
||||
|
||||
public abstract class BaseRootType extends BaseElement {
|
||||
|
||||
private String myId;
|
||||
|
@ -22,7 +24,7 @@ public abstract class BaseRootType extends BaseElement {
|
|||
if (mySearchParameters == null) {
|
||||
mySearchParameters = new ArrayList<SearchParameter>();
|
||||
}
|
||||
return mySearchParameters;
|
||||
return java.util.Collections.unmodifiableList(mySearchParameters);
|
||||
}
|
||||
|
||||
public List<SearchParameter> getSearchParametersWithoutComposite() {
|
||||
|
@ -57,5 +59,9 @@ public abstract class BaseRootType extends BaseElement {
|
|||
}
|
||||
return retVal;
|
||||
}
|
||||
public void addSearchParameter(SearchParameter theParam) {
|
||||
getSearchParameters();
|
||||
mySearchParameters.add(theParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.tinder.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
|
@ -11,49 +12,19 @@ public class SearchParameter {
|
|||
private String myDescription;
|
||||
private String myName;
|
||||
private String myPath;
|
||||
private List<String> myTargetTypes;
|
||||
private String myType;
|
||||
|
||||
public SearchParameter() {
|
||||
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return StringUtils.defaultString(myDescription);
|
||||
}
|
||||
|
||||
public String getConstantName() {
|
||||
return "SP_" + myName.toUpperCase().replace("_[X]", "_X").replace("-[X]", "_X").replace('-', '_').replace("!", "");
|
||||
}
|
||||
|
||||
public List<Include> getPaths() {
|
||||
ArrayList<Include> retVal = new ArrayList<Include>();
|
||||
for (String next : getPath().split("\\s*\\|\\s*")) {
|
||||
retVal.add(new Include(next));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static class Include
|
||||
{
|
||||
private String myPath;
|
||||
|
||||
public Include(String thePath) {
|
||||
myPath=thePath;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
// String retVal = StringUtils.defaultString(myPath);
|
||||
// retVal = retVal.substring(retVal.indexOf('.')+1);
|
||||
return myPath;
|
||||
}
|
||||
|
||||
public String getIncludeName() {
|
||||
String retVal = myPath;
|
||||
retVal = retVal.substring(retVal.indexOf('.')+1);
|
||||
retVal = retVal.toUpperCase().replace('.', '_').replace("[X]", "");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return StringUtils.defaultString(myDescription);
|
||||
}
|
||||
|
||||
public String getFluentConstantName() {
|
||||
|
@ -64,10 +35,6 @@ public class SearchParameter {
|
|||
return myName.toUpperCase().replace("_[X]", "_X").replace("-[X]", "_X").replace('-', '_').replace("!", "");
|
||||
}
|
||||
|
||||
public String getTypeCapitalized() {
|
||||
return WordUtils.capitalize(myType);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
@ -80,10 +47,29 @@ public class SearchParameter {
|
|||
return StringUtils.defaultString(myPath);
|
||||
}
|
||||
|
||||
public List<Include> getPaths() {
|
||||
ArrayList<Include> retVal = new ArrayList<Include>();
|
||||
for (String next : getPath().split("\\s*\\|\\s*")) {
|
||||
retVal.add(new Include(next));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public List<String> getTargetTypes() {
|
||||
if (myTargetTypes==null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return myTargetTypes;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return StringUtils.defaultString(myType);
|
||||
}
|
||||
|
||||
public String getTypeCapitalized() {
|
||||
return WordUtils.capitalize(myType);
|
||||
}
|
||||
|
||||
public void setDescription(String theDescription) {
|
||||
myDescription = theDescription;
|
||||
}
|
||||
|
@ -96,8 +82,35 @@ public class SearchParameter {
|
|||
myPath = thePath;
|
||||
}
|
||||
|
||||
public void setTargetTypes(List<String> theTargetTypes) {
|
||||
myTargetTypes = theTargetTypes;
|
||||
}
|
||||
|
||||
public void setType(String theType) {
|
||||
myType = theType;
|
||||
}
|
||||
|
||||
public static class Include
|
||||
{
|
||||
private String myPath;
|
||||
|
||||
public Include(String thePath) {
|
||||
myPath=thePath;
|
||||
}
|
||||
|
||||
public String getIncludeName() {
|
||||
String retVal = myPath;
|
||||
retVal = retVal.substring(retVal.indexOf('.')+1);
|
||||
retVal = retVal.toUpperCase().replace('.', '_').replace("[X]", "");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
// String retVal = StringUtils.defaultString(myPath);
|
||||
// retVal = retVal.substring(retVal.indexOf('.')+1);
|
||||
return myPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package ca.uhn.fhir.tinder.parser;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -75,6 +77,7 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
// Map<String,String> blockFullNameToShortName = new
|
||||
// HashMap<String,String>();
|
||||
|
||||
Map<String, List<String>> pathToResourceTypes = new HashMap<String, List<String>>();
|
||||
for (int i = 2; i < rows.getLength(); i++) {
|
||||
Element nextRow = (Element) rows.item(i);
|
||||
String name = cellValue(nextRow, 0);
|
||||
|
@ -112,11 +115,30 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
scanForSimpleSetters(elem);
|
||||
}
|
||||
|
||||
pathToResourceTypes.put(name, elem.getType());
|
||||
}
|
||||
|
||||
for (SearchParameter nextParam : resource.getSearchParameters()) {
|
||||
if (nextParam.getType().equals("reference")) {
|
||||
String path = nextParam.getPath();
|
||||
List<String> targetTypes = pathToResourceTypes.get(path);
|
||||
if (targetTypes != null) {
|
||||
targetTypes = new ArrayList<String>(targetTypes);
|
||||
for (Iterator<String> iter = targetTypes.iterator();iter.hasNext();) {
|
||||
String next = iter.next();
|
||||
if (next.equals("Any") || next.endsWith("Dt")) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
nextParam.setTargetTypes(targetTypes);
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
ourLog.info("Parsed {} spreadsheet structures", getResources().size());
|
||||
|
||||
}
|
||||
|
@ -166,7 +188,7 @@ public abstract class BaseStructureSpreadsheetParser extends BaseStructureParser
|
|||
sp.setPath(cellValue(nextRow, colPath));
|
||||
|
||||
if (StringUtils.isNotBlank(sp.getName()) && !sp.getName().startsWith("!")) {
|
||||
theResource.getSearchParameters().add(sp);
|
||||
theResource.addSearchParameter(sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ public class ProfileParser extends BaseStructureParser {
|
|||
|
||||
param.setType(nextParam.getType().getValue());
|
||||
param.setDescription(nextParam.getDocumentation().getValue());
|
||||
retVal.getSearchParameters().add(param);
|
||||
retVal.addSearchParameter(param);
|
||||
}
|
||||
|
||||
addResource(retVal);
|
||||
|
|
|
@ -32,20 +32,26 @@ public class ${className}ResourceProvider extends JpaResourceProvider<${classNam
|
|||
#foreach ( $param in $searchParamsWithoutComposite ) #{if}(true) #{end}
|
||||
|
||||
@Description(shortDefinition="${param.description}")
|
||||
@OptionalParam(name="${param.name}")
|
||||
#if (${param.type} == 'string' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
StringParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'token' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
IdentifierListParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'date' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
DateRangeParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'quantity' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
QuantityDt the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'number' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
QuantityDt the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'reference' )
|
||||
@OptionalParam(name="${param.name}", targetTypes={ #{foreach}($nextType in ${param.targetTypes}) ${nextType}.class #{if}($foreach.hasNext), #{end} #{end} } )
|
||||
ReferenceParam the${param.nameCapitalized},
|
||||
#elseif (${param.type} == 'composite' )
|
||||
@OptionalParam(name="${param.name}")
|
||||
ReferenceParam the${param.nameCapitalized},
|
||||
#end
|
||||
#end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<dependent-module archiveName="hapi-fhir-base-0.4.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
|
||||
<dependent-module archiveName="hapi-fhir-base-0.5-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<property name="context-root" value="restful-server-example"/>
|
||||
|
|
Loading…
Reference in New Issue