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

This commit is contained in:
jamesagnew 2015-01-27 21:56:23 -05:00
commit 9bee09efcd
172 changed files with 152864 additions and 152653 deletions

View File

@ -91,6 +91,46 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
return getCodeElement().equals(theCoding.getCodeElement()) && getSystemElement().equals(theCoding.getSystemElement()); return getCodeElement().equals(theCoding.getCodeElement()) && getSystemElement().equals(theCoding.getSystemElement());
} }
/**
* returns true if <code>this</code> Coding matches a search for the coding specified by <code>theSearchParam</code>, according
* to the following:
* <ul>
* <li>[parameter]=[namespace]|[code] matches a code/value in the given system namespace</li>
* <li>[parameter]=[code] matches a code/value irrespective of it's system namespace</li>
* <li>[parameter]=|[code] matches a code/value that has no system namespace</li>
* </ul>
* @param theSearchParam - coding to test <code>this</code> against
* @return true if the coding matches, false otherwise
*/
public boolean matchesToken(BaseCodingDt theSearchParam) {
if (theSearchParam.isSystemPresent()) {
if (theSearchParam.isSystemBlank()) {
// [parameter]=|[code] matches a code/value that has no system namespace
if (isSystemPresent() && !isSystemBlank())
return false;
} else {
// [parameter]=[namespace]|[code] matches a code/value in the given system namespace
if (!isSystemPresent())
return false;
if (!getSystemElement().equals(theSearchParam.getSystemElement()))
return false;
}
} else {
// [parameter]=[code] matches a code/value irrespective of it's system namespace
// (nothing to do for system for this case)
}
return getCodeElement().equals(theSearchParam.getCodeElement());
}
private boolean isSystemPresent() {
return !getSystemElement().isEmpty();
}
private boolean isSystemBlank() {
return isSystemPresent() && getSystemElement().getValueAsString().equals("");
}
/** /**
* Sets the value for <b>code</b> (Symbol in syntax defined by the system) * Sets the value for <b>code</b> (Symbol in syntax defined by the system)
* *
@ -109,4 +149,5 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
*/ */
public abstract BaseCodingDt setSystem(String theUri); public abstract BaseCodingDt setSystem(String theUri);
} }

View File

@ -94,4 +94,15 @@ public class TokenOrListParam extends BaseOrListParam<TokenParam> {
return new TokenParam(); return new TokenParam();
} }
public boolean doesCodingListMatch(List<? extends BaseCodingDt> theCodings) {
List<BaseCodingDt> paramCodings = getListAsCodings();
for (BaseCodingDt coding : theCodings) {
for (BaseCodingDt paramCoding : paramCodings) {
if (coding.matchesToken(paramCoding)) {
return true;
}
}
}
return false;
}
} }

View File

@ -165,7 +165,7 @@ public class RestfulServer extends HttpServlet {
/** /**
* Count length of URL string, but treating unescaped sequences (e.g. ' ') as their unescaped equivalent (%20) * Count length of URL string, but treating unescaped sequences (e.g. ' ') as their unescaped equivalent (%20)
*/ */
private int escapedLength(String theServletPath) { protected int escapedLength(String theServletPath) {
int delta = 0; int delta = 0;
for (int i = 0; i < theServletPath.length(); i++) { for (int i = 0; i < theServletPath.length(); i++) {
char next = theServletPath.charAt(i); char next = theServletPath.charAt(i);
@ -479,13 +479,11 @@ public class RestfulServer extends HttpServlet {
String operation = null; String operation = null;
String compartment = null; String compartment = null;
String requestPath = requestFullPath.substring(escapedLength(servletContextPath) + escapedLength(servletPath)); String requestPath = getRequestPath(requestFullPath, servletContextPath, servletPath);
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') { if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
requestPath = requestPath.substring(1); requestPath = requestPath.substring(1);
} }
fhirServerBase = getServerBaseForRequest(theRequest);
String completeUrl = StringUtils.isNotBlank(theRequest.getQueryString()) ? requestUrl + "?" + theRequest.getQueryString() : requestUrl.toString(); String completeUrl = StringUtils.isNotBlank(theRequest.getQueryString()) ? requestUrl + "?" + theRequest.getQueryString() : requestUrl.toString();
Map<String, String[]> params = new HashMap<String, String[]>(theRequest.getParameterMap()); Map<String, String[]> params = new HashMap<String, String[]>(theRequest.getParameterMap());
@ -534,6 +532,7 @@ public class RestfulServer extends HttpServlet {
operation = Constants.PARAM_HISTORY; operation = Constants.PARAM_HISTORY;
} }
} else if (nextString.startsWith("_")) { } else if (nextString.startsWith("_")) {
//FIXME: this would be untrue for _meta/_delete
if (operation != null) { if (operation != null) {
throw new InvalidRequestException("URL Path contains two operations (part beginning with _): " + requestPath); throw new InvalidRequestException("URL Path contains two operations (part beginning with _): " + requestPath);
} }
@ -1499,4 +1498,16 @@ public class RestfulServer extends HttpServlet {
} }
} }
/**
* Allows users of RestfulServer to override the getRequestPath method to let them build their custom request path
* implementation
*
* @param requestFullPath the full request path
* @param servletContextPath the servelet context path
* @param servletPath the servelet path
* @return created resource path
*/
protected String getRequestPath(String requestFullPath, String servletContextPath, String servletPath) {
return requestFullPath.substring(escapedLength(servletContextPath) + escapedLength(servletPath));
}
} }

View File

@ -2,7 +2,9 @@ package ca.uhn.fhirtest;
import java.util.List; import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -136,7 +138,7 @@ public class TestRestfulServer extends RestfulServer {
throw new ServletException("Missing system property: " + baseUrlProperty); throw new ServletException("Missing system property: " + baseUrlProperty);
} }
} }
setServerAddressStrategy(new HardcodedServerAddressStrategy(baseUrl)); setServerAddressStrategy(new MyHardcodedServerAddressStrategy(baseUrl));
/* /*
* This is a simple paging strategy that keeps the last 10 * This is a simple paging strategy that keeps the last 10
@ -155,4 +157,32 @@ public class TestRestfulServer extends RestfulServer {
} }
/**
* The public server is deployed to http://fhirtest.uhn.ca and the JEE webserver
* where this FHIR server is deployed is actually fronted by an Apache HTTPd instance,
* so we use an address strategy to let the server know how it should address itself.
*/
private static class MyHardcodedServerAddressStrategy extends HardcodedServerAddressStrategy {
public MyHardcodedServerAddressStrategy(String theBaseUrl) {
super(theBaseUrl);
}
@Override
public String determineServerBase(ServletContext theServletContext, HttpServletRequest theRequest) {
/*
* This is a bit of a hack, but we want to support both HTTP and HTTPS seamlessly
* so we have the outer httpd proxy relay requests to the Java container on
* port 28080 for http and 28081 for https.
*/
String retVal = super.determineServerBase(theServletContext, theRequest);
if (theRequest.getRequestURL().indexOf("28081") != -1) {
retVal = retVal.replace("http://", "https://");
}
return retVal;
}
}
} }

View File

@ -0,0 +1,71 @@
package ca.uhn.fhir.model.base.composite;
import static org.junit.Assert.*;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import org.junit.Test;
/**
* Created by Bill de Beaubien on 12/30/2014.
*/
public class BaseCodingDtTest {
private final CodingDt myTokenWithSystem = new CodingDt("http://foo.org", "53");
private final CodingDt myTokenWithEmptySystem = new CodingDt("", "53");
private final CodingDt myTokenWithoutSystem = new CodingDt(null, "53");
// [parameter]=[namespace]|[code] matches a code/value in the given system namespace
@Test
public void whenTokenIncludesSystem_CodingWithSameSystemAndCode_shouldMatch() {
assertTrue(new CodingDt("http://foo.org", "53").matchesToken(myTokenWithSystem));
}
@Test
public void whenTokenIncludesSystem_CodingWithDifferentSystem_shouldNotMatch() {
assertFalse(new CodingDt("http://bar.org", "53").matchesToken(myTokenWithSystem));
}
@Test
public void whenTokenIncludesSystem_CodingWithBlankSystem_shouldNotMatch() {
assertFalse(new CodingDt("", "53").matchesToken(myTokenWithSystem));
}
@Test
public void whenTokenIncludesSystem_CodingWithNoSystem_shouldNotMatch() {
assertFalse(new CodingDt(null, "53").matchesToken(myTokenWithSystem));
}
@Test
public void whenTokenIncludesSystem_CodingWithSameSystemAndDifferentCode_shouldNotMatch() {
assertFalse(new CodingDt("http://foo.org", "11").matchesToken(myTokenWithSystem));
}
@Test
public void whenTokenIncludesSystem_CodingWithSameSystemAndNoCode_shouldNotMatch() {
assertFalse(new CodingDt("http://foo.org", null).matchesToken(myTokenWithSystem));
}
// [parameter]=[code] matches a code/value irrespective of it's system namespace
@Test
public void whenTokenIncludesNoSystem_CodingWithAnySystemAndCode_shouldMatch() {
assertTrue(new CodingDt("http://foo.org", "53").matchesToken(myTokenWithoutSystem));
assertTrue(new CodingDt("http://bar.org", "53").matchesToken(myTokenWithoutSystem));
assertTrue(new CodingDt("", "53").matchesToken(myTokenWithoutSystem));
assertTrue(new CodingDt(null, "53").matchesToken(myTokenWithoutSystem));
}
// [parameter]=|[code] matches a code/value that has no system namespace
@Test
public void whenTokenIncludesEmptySystem_CodeWithNoSystem_shouldMatch() {
assertTrue(new CodingDt(null, "53").matchesToken(myTokenWithEmptySystem));
}
@Test
public void whenTokenIncludesEmptySystem_CodeWithBlankSystem_shouldMatch() {
assertTrue(new CodingDt("", "53").matchesToken(myTokenWithEmptySystem));
}
@Test
public void whenTokenIncludesEmptySystem_CodeWithSystem_shouldNotMatch() {
assertFalse(new CodingDt("http://bar.org", "53").matchesToken(myTokenWithEmptySystem));
}
}

View File

@ -0,0 +1,37 @@
package ca.uhn.fhir.rest.param;
import static org.junit.Assert.*;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TokenOrListParamTest {
@Test
public void whenParamListHasAnyMatchingCodingsForCodingList_doesCodingListMatch_shouldBeTrue() {
TokenOrListParam params = new TokenOrListParam();
params.add("http://foo.org", "53");
params.add("http://bar.org", "52");
List<CodingDt> codings = new ArrayList<CodingDt>();
codings.add(new CodingDt("http://baz.org", "53"));
codings.add(new CodingDt("http://bar.org", "52"));
assertTrue(params.doesCodingListMatch(codings));
}
@Test
public void whenParamListHasNoMatchingCodingsForCodingList_doesCodingListMatch_shouldBeFalse() {
TokenOrListParam params = new TokenOrListParam();
params.add("http://foo.org", "53");
params.add("http://bar.org", "52");
List<CodingDt> codings = new ArrayList<CodingDt>();
codings.add(new CodingDt("http://baz.org", "53"));
codings.add(new CodingDt("http://bar.org", "11"));
assertFalse(params.doesCodingListMatch(codings));
}
}

View File

@ -291,6 +291,16 @@
<![CDATA[<a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/api/annotation/ResourceDef.html">@ResourceDef</a>]]> <![CDATA[<a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/api/annotation/ResourceDef.html">@ResourceDef</a>]]>
JavaDoc for information on how this works. JavaDoc for information on how this works.
</action> </action>
<action type="add" issue="73" dev="wdebeau1">
Add convenience methods to TokenOrListParam to test whether any of a set of tokens match
the given requested list.
</action>
<action type="add" issue="86" dev="harsha89">
Add a protected method to RestfulServer which allows developers to
implement their own method for determining which part of the request
URL is the FHIR request path (useful if you are embedding the RestulServer inside
of another web framework). Thanks to Harsha Kumara for the pull request!
</action>
</release> </release>
<release version="0.7" date="2014-Oct-23"> <release version="0.7" date="2014-Oct-23">
<action type="add" issue="30"> <action type="add" issue="30">