Start with sample code in tester UI

This commit is contained in:
jamesagnew 2014-07-11 09:15:38 -04:00
parent 1346802403
commit 0a7f7d0390
14 changed files with 134 additions and 41 deletions

View File

@ -23,10 +23,8 @@ package ca.uhn.fhir.rest.server.provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@ -34,8 +32,6 @@ import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.ExtensionDt;
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;
@ -104,7 +100,7 @@ public class ServerConformanceProvider {
String resourceName = next.getResourceName();
RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
resource.getType().setValue(def.getName());
resource.getProfile().setId(new IdDt(def.getResourceProfile()));
resource.getProfile().setReference(new IdDt(def.getResourceProfile()));
TreeSet<String> includes = new TreeSet<String>();
@ -160,6 +156,9 @@ public class ServerConformanceProvider {
query = rest.addQuery();
query.getDocumentation().setValue(searchMethodBinding.getDescription());
query.addUndeclaredExtension(false, ExtensionConstants.QUERY_RETURN_TYPE, new CodeDt(resourceName));
for (String nextInclude : searchMethodBinding.getIncludes()) {
query.addUndeclaredExtension(false, ExtensionConstants.QUERY_ALLOWED_INCLUDE, new StringDt(nextInclude));
}
}
for (SearchParameter nextParameter : searchParameters) {

View File

@ -36,5 +36,7 @@ public class ExtensionConstants {
public static final String CONF_ADDITIONAL_PARAM_REQUIRED = "http://hl7api.sourceforge.net/hapi-fhir/extensions.xml#additionalParamRequired";
public static final String CONF_RESOURCE_COUNT = "http://hl7api.sourceforge.net/hapi-fhir/res/extdefs.html#resourceCount";
public static final String QUERY_ALLOWED_INCLUDE = "http://hl7api.sourceforge.net/hapi-fhir/res/extdefs.html#allowedInclude";
}

View File

@ -1,10 +1,7 @@
package ca.uhn.fhir.jpa.provider;
import java.util.Collection;
import java.util.Map;
import ca.uhn.fhir.jpa.dao.IDaoListener;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;

View File

@ -12,7 +12,7 @@
<dependent-module archiveName="hapi-fhir-base-0.4-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=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-tester-overlay?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependency-type>consumes</dependency-type>
</dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">

View File

@ -15,7 +15,7 @@
<value>home , UHN/HAPI Server , http://fhirtest.uhn.ca/base</value>
<value>hi , Health Intersections , http://fhir.healthintersections.com.au/open</value>
<value>furore , Spark - Furore Reference Server , http://spark.furore.com/fhir</value>
<value>blaze , Blaze (Orion Health) , https://fhir.orionhealth.com</value>
<value>blaze , Blaze (Orion Health) , https://fhir.orionhealth.com/blaze/fhir</value>
<value>oridashi , Oridashi , http://demo.oridashi.com.au:8190</value>
<value>fhirbase , FHIRPlace (Health Samurai) , http://try-fhirplace.hospital-systems.com/ </value>
</list>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/moment*.*" kind="src" path="src/main/webapp"/>
<classpathentry excluding="**/moment*.*" kind="src" path="target/m2e-wtp/web-resources"/>
<classpathentry excluding="**/*.svg|**/moment*.*" including="js/RestfulTester.js" kind="src" path="src/main/webapp"/>
<classpathentry excluding="**/*.svg|**/moment*.*" kind="src" path="target/m2e-wtp/web-resources"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>

View File

@ -1,13 +1 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="hapi-fhir-tester-overlay">
<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"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
<dependent-module archiveName="hapi-fhir-base-0.4-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="java-output-path" value="/hapi-fhir-tester-overlay/target/classes"/>
<property name="context-root" value="hapi-fhir-testpage-overlay"/>
</wb-module>
</project-modules>
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId"/>

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.to;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -10,6 +11,9 @@ import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import javax.json.Json;
import javax.json.JsonWriter;
import javax.json.stream.JsonGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -134,7 +138,7 @@ public class Controller {
try {
client.delete(def.getImplementingClass(), new IdDt(id));
} catch (Exception e) {
returnsResource = handleClientException(client,e, theModel);
returnsResource = handleClientException(client, e, theModel);
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
@ -146,11 +150,11 @@ public class Controller {
ResultType returnsResource;
returnsResource = ResultType.NONE;
ourLog.warn("Failed to invoke server", e);
if (theClient.getLastResponse() == null) {
theModel.put("errorMsg", "Error: " + e.getMessage());
}
return returnsResource;
}
@ -293,7 +297,7 @@ public class Controller {
@RequestMapping({ "/resource" })
public String actionResource(final ResourceRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
Conformance conformance = addCommonParams(theRequest, theModel);
Conformance conformance = addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
@ -303,6 +307,7 @@ public class Controller {
TreeSet<String> includes = new TreeSet<String>();
List<RestQuery> queries = new ArrayList<Conformance.RestQuery>();
boolean haveSearchParams = false;
List<List<String>> queryIncludes = new ArrayList<List<String>>();
for (Rest nextRest : conformance.getRest()) {
for (RestResource nextRes : nextRest.getResource()) {
if (nextRes.getType().getValue().equals(resourceName)) {
@ -317,11 +322,25 @@ public class Controller {
}
}
for (RestQuery nextQuery : nextRest.getQuery()) {
boolean queryMatchesResource = false;
List<ExtensionDt> returnTypeExt = nextQuery.getUndeclaredExtensionsByUrl(ExtensionConstants.QUERY_RETURN_TYPE);
if (returnTypeExt != null) {
for (ExtensionDt nextExt : returnTypeExt) {
if (resourceName.equals(nextExt.getValueAsPrimitive().getValueAsString())) {
queries.add(nextQuery);
queryMatchesResource = true;
break;
}
}
}
if (queryMatchesResource) {
ArrayList<String> nextQueryIncludes = new ArrayList<String>();
queryIncludes.add(nextQueryIncludes);
List<ExtensionDt> includesExt = nextQuery.getUndeclaredExtensionsByUrl(ExtensionConstants.QUERY_ALLOWED_INCLUDE);
if (includesExt != null) {
for (ExtensionDt nextExt : includesExt) {
nextQueryIncludes.add(nextExt.getValueAsPrimitive().getValueAsString());
}
}
}
@ -330,6 +349,7 @@ public class Controller {
theModel.put("includes", includes);
theModel.put("queries", queries);
theModel.put("haveSearchParams", haveSearchParams);
theModel.put("queryIncludes", queryIncludes);
if (isNotBlank(theRequest.getUpdateId())) {
String updateId = theRequest.getUpdateId();
@ -347,6 +367,12 @@ public class Controller {
public String actionSearch(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
StringWriter clientCodeJsonStringWriter = new StringWriter();
JsonGenerator clientCodeJsonWriter = Json.createGenerator(clientCodeJsonStringWriter);
clientCodeJsonWriter.writeStartObject();
clientCodeJsonWriter.write("action", "search");
clientCodeJsonWriter.write("base", (String)theModel.get("base"));
GenericClient client = theRequest.newClient(myCtx, myConfig);
IUntypedQuery search = client.search();
@ -358,9 +384,12 @@ public class Controller {
theModel.put("errorMsg", e.toString());
return "resource";
}
clientCodeJsonWriter.write("resource", theReq.getParameter("resource"));
} else {
query = search.forAllResources();
clientCodeJsonWriter.writeNull("resource");
}
String outcomeDescription = "Search for Resources";
@ -405,6 +434,11 @@ public class Controller {
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
clientCodeJsonWriter.writeEnd();
clientCodeJsonWriter.close();
String clientCodeJson = clientCodeJsonStringWriter.toString();
theModel.put("clientCodeJson", clientCodeJson);
return "result";
}
@ -696,7 +730,7 @@ public class Controller {
StringBuilder b = new StringBuilder();
b.append("<span class='hlUrlBase'>");
boolean inParams = false;
for (int i = 0; i < str.length(); i++) {
char nextChar = str.charAt(i);
@ -779,7 +813,7 @@ public class Controller {
private Conformance loadAndAddConf(final HomeRequest theRequest, final ModelMap theModel) {
IGenericClient client = myCtx.newRestfulGenericClient(theRequest.getServerBase(myConfig));
Conformance conformance;
try {
conformance = client.conformance();

View File

@ -102,7 +102,7 @@
$('#search-btn').click(function() {
var btn = $(this);
btn.button('loading');
var sd = $('#tab-search').find('input').each(function() {
$('#tab-search').find('input').each(function() {
if (this.id) {
if (this.id.substring(0,4) == 'inc_') {
this.name = '_include';

View File

@ -22,13 +22,31 @@
<!-- *************************************************** -->
<!-- ** Response ** -->
<!-- *************************************************** -->
<div class="well" id="resultWell">
Executed request against FHIR RESTful server in
<th:block th:text="${latencyMs} + 'ms'"/>
</div>
<div th:if="${requestUrl} != null">
<div class="well" id="resultWell">
Executed request against FHIR RESTful server in
<th:block th:text="${latencyMs} + 'ms'"/>
<!--
<div th:if="${clientCodeJson} != null" class="panel panel-default">
<div class="panel-heading">
Client Code -
<small style="color: #888;">
Use the following code snippet to execute this action in your
own client.
</small>
</div>
<div class="panel-body clientCodeBox" id="clientCodeBody">
</div>
<script type="text/javascript" src="js/ClientCodeGeneratorHapi.js"></script>
<script type="text/javascript">
var jsonClientCode = <th:block th:utext="${clientCodeJson}"/>;
generateHapi(jsonClientCode, $('#clientCodeBody'));
</script>
</div>
-->
<div th:if="${requestUrl} != null">
<table class="table table-bordered table-striped requestTable" id="requestTable">
<colgroup>

View File

@ -2,6 +2,7 @@
<html lang="en">
<div th:fragment="queries-list" class="container-fluid">
<div th:each="query,queryIterStat : ${queries}" class="panel panel-default" th:id="'search-div-' + ${queryIterStat.index}" >
<div class="panel-heading">
<div class="pull-right">
<button type="button" th:id="'search-btn-' + ${queryIterStat.index}" class="btn btn-primary btn-block"
@ -16,8 +17,14 @@
var btn = $(this);
btn.button('loading');
var searchDiv = '<th:block th:text="'search-div-' + ${queryIterStat.index}"/>';
var sd = $('#' + searchDiv).find('input').each(function() {
this.name = this.id;
$('#' + searchDiv).find('input').each(function() {
if (this.id) {
if (this.id.substring(0,4) == 'inc_') {
this.name = '_include';
} else {
this.name = this.id;
}
}
});
$("#outerForm").attr("action", "search").submit();
});
@ -33,6 +40,7 @@
<div th:each="param,paramIterStat : ${query.parameter}"
th:id="'search-param-rowopts-' + ${queryIterStat.index} + '-' + ${paramIterStat.index}"
th:class="'row queryParameter ' + (${paramIterStat.odd} ? 'queryParameterOdd')">
<div class="col-sm-6">
<div class="searchParamDescription">
<div>
@ -61,6 +69,21 @@
</script>
<br clear="all"/>
</div>
<div class="row-fluid" th:unless="${queryIncludes[queryIterStat.index].empty}">
<h4>Includes <small>Also load and include referenced resources in results</small></h4>
</div>
<div class="row-fluid" th:unless="${queryIncludes[queryIterStat.index].empty}">
<span th:each="include : ${queryIncludes[queryIterStat.index]}" class="includeCheckContainer">
<span class="includeCheckCheck">
<input type="checkbox" th:value="${include}" th:id="'inc_' + ${include}" />
</span>
<span class="includeCheckName" th:text="${include}"/>
</span>
</div>
</div>
</div>
</div>

View File

@ -15,6 +15,18 @@ body {
overflow-x: hidden;
}
.clientCodeBox
{
font-family: monospace;
font-size: 0.8em;
line-height: 0.85em;
}
.clientCodePreamble {
color: #888;
font-style: italic;
}
label {
font-size: 1.0em;
color: #808080;

View File

@ -0,0 +1,22 @@
function generateHapi(json, container) {
if (json.action == 'search') {
generateHapiSearch(json, container);
}
}
function generateHapiSearch(json, container) {
container.append($('<span />', {'class': 'clientCodePreamble'}).text("FhirContext ctx = new FhirContext();"));
container.append($('<br/>'));
container.append($('<span />', {'class': 'clientCodePreamble'}).text("IGenericClient client = ctx.newRestfulGenericClient(\"" + json.base + "\");"));
container.append($('<br/>'));
var searchLine = 'client.search()';
if (json.resource != null) {
searchLine = searchLine + '.forResource(' + json.resource + '.class)';
} else {
searchLine = searchLine + '.forAllResources()';
}
container.append($('<span />', {'class': 'clientCodeMain'}).text(searchLine));
}

View File

@ -87,8 +87,6 @@ public class OverlayTestApp {
IFhirSystemDao systemDao = appCtx.getBean("mySystemDao", IFhirSystemDao.class);
@SuppressWarnings("rawtypes")
Collection<IFhirResourceDao> resourceDaos = appCtx.getBeansOfType(IFhirResourceDao.class).values();
JpaSystemProvider systemProvider = new JpaSystemProvider(systemDao);
RestfulServer restServer = new RestfulServer();