Skip to content

Commit

Permalink
Merge c3447c3 into cb8492d
Browse files Browse the repository at this point in the history
  • Loading branch information
SRiviere committed Feb 8, 2017
2 parents cb8492d + c3447c3 commit 745820d
Show file tree
Hide file tree
Showing 30 changed files with 768 additions and 52 deletions.
Expand Up @@ -22,6 +22,7 @@

import java.lang.reflect.Constructor;
import java.util.*;
import ca.uhn.fhir.util.UrlUtil;

import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBase;
Expand Down Expand Up @@ -100,9 +101,19 @@ private Constructor<T> getConstructor(Object theArgument) {
/**
* @return Returns null if none
*/
public RuntimeChildDeclaredExtensionDefinition getDeclaredExtension(String theExtensionUrl) {
public RuntimeChildDeclaredExtensionDefinition getDeclaredExtension(String theExtensionUrl, final String serverBaseUrl) {
validateSealed();
return myUrlToExtension.get(theExtensionUrl);
RuntimeChildDeclaredExtensionDefinition definition = myUrlToExtension.get(theExtensionUrl);
if (definition == null && StringUtils.isNotBlank(serverBaseUrl)) {
for (final Map.Entry<String, RuntimeChildDeclaredExtensionDefinition> entry : myUrlToExtension.entrySet()) {
final String key = (!UrlUtil.isValid(entry.getKey()) && StringUtils.isNotBlank(serverBaseUrl)) ? serverBaseUrl + entry.getKey() : entry.getKey();
if (key.equals(theExtensionUrl)) {
definition = entry.getValue();
break;
}
}
}
return definition;
}

public List<RuntimeChildDeclaredExtensionDefinition> getExtensions() {
Expand Down
Expand Up @@ -115,7 +115,7 @@ private void copyChildren(BaseRuntimeElementCompositeDefinition<?> theSourceDef,
}

private void addExtension(BaseRuntimeElementCompositeDefinition<?> theSourceDef, BaseElement theSource, BaseElement theTarget, RuntimeChildDeclaredExtensionDefinition nextExt, String url) {
RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url);
RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url, "");
if (sourceDeclaredExt == null) {

for (ExtensionDt next : theSource.getAllUndeclaredExtensions()) {
Expand Down
13 changes: 13 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java
Expand Up @@ -77,6 +77,7 @@
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.UrlUtil;

public abstract class BaseParser implements IParser {

Expand Down Expand Up @@ -931,6 +932,18 @@ protected boolean shouldEncodeResourceId(IBaseResource theResource) {
return retVal;
}

protected String getExtensionUrl(final String extensionUrl) {
String url = extensionUrl;
if (StringUtils.isNotBlank(extensionUrl) && StringUtils.isNotBlank(myServerBaseUrl)) {
url = !UrlUtil.isValid(extensionUrl) && extensionUrl.startsWith("/") ? myServerBaseUrl + extensionUrl : extensionUrl;
}
return url;
}

protected String getServerBaseUrl() {
return myServerBaseUrl;
}

/**
* Used for DSTU2 only
*/
Expand Down
12 changes: 6 additions & 6 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
Expand Up @@ -1405,9 +1405,9 @@ private void parseExtension(ParserState<?> theState, JsonLikeArray theValues, bo
getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url");
url = null;
} else {
url = jsonElement.getAsString();
url = getExtensionUrl(jsonElement.getAsString());
}
theState.enteringNewElementExtension(null, url, theIsModifier);
theState.enteringNewElementExtension(null, url, theIsModifier, getServerBaseUrl());
for (String next : nextExtObj.keySet()) {
if ("url".equals(next)) {
continue;
Expand Down Expand Up @@ -1758,8 +1758,8 @@ public HeldExtension(RuntimeChildDeclaredExtensionDefinition theDef, IBase theVa
public int compareTo(HeldExtension theArg0) {
String url1 = myDef != null ? myDef.getExtensionUrl() : myUndeclaredExtension.getUrl();
String url2 = theArg0.myDef != null ? theArg0.myDef.getExtensionUrl() : theArg0.myUndeclaredExtension.getUrl();
url1 = defaultString(url1);
url2 = defaultString(url2);
url1 = defaultString(getExtensionUrl(url1));
url2 = defaultString(getExtensionUrl(url2));
return url1.compareTo(url2);
}

Expand All @@ -1771,7 +1771,7 @@ public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource

writeCommentsPreAndPost(myValue, theEventWriter);

JsonParser.write(theEventWriter, "url", myDef.getExtensionUrl());
JsonParser.write(theEventWriter, "url", getExtensionUrl(myDef.getExtensionUrl()));

/*
* This makes sure that even if the extension contains a reference to a contained
Expand All @@ -1797,7 +1797,7 @@ public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource

private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonLikeWriter theEventWriter, IBaseExtension<?, ?> ext) throws IOException {
IBase value = ext.getValue();
String extensionUrl = ext.getUrl();
final String extensionUrl = getExtensionUrl(ext.getUrl());

theEventWriter.beginObject();

Expand Down
18 changes: 9 additions & 9 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
Expand Up @@ -98,8 +98,8 @@ public void enteringNewElement(String theNamespaceUri, String theName) throws Da
myState.enteringNewElement(theNamespaceUri, theName);
}

public void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier) {
myState.enteringNewElementExtension(theElem, theUrlAttr, theIsModifier);
public void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
myState.enteringNewElementExtension(theElem, theUrlAttr, theIsModifier, baseServerUrl);
}

public T getObject() {
Expand Down Expand Up @@ -791,7 +791,7 @@ public void enteringNewElement(String theNamespaceUri, String theLocalPart) thro
* Default implementation just handles undeclared extensions
*/
@SuppressWarnings("unused")
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
if (myPreResourceState != null && getCurrentElement() instanceof ISupportsUndeclaredExtensions) {
ExtensionDt newExtension = new ExtensionDt(theIsModifier);
newExtension.setUrl(theUrlAttr);
Expand Down Expand Up @@ -1483,7 +1483,7 @@ public void enteringNewElement(String theNamespaceUri, String theLocalPart) thro
}

@Override
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
RuntimeChildDeclaredExtensionDefinition declaredExtension = myDefinition.getChildExtensionForUrl(theUrlAttr);
if (declaredExtension != null) {
if (myChildInstance == null) {
Expand All @@ -1493,7 +1493,7 @@ public void enteringNewElementExtension(StartElement theElement, String theUrlAt
BaseState newState = new DeclaredExtensionState(getPreResourceState(), declaredExtension, myChildInstance);
push(newState);
} else {
super.enteringNewElementExtension(theElement, theUrlAttr, theIsModifier);
super.enteringNewElementExtension(theElement, theUrlAttr, theIsModifier, baseServerUrl);
}
}

Expand Down Expand Up @@ -1664,13 +1664,13 @@ public void enteringNewElement(String theNamespace, String theChildName) throws
}

@Override
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
RuntimeChildDeclaredExtensionDefinition declaredExtension = myDefinition.getDeclaredExtension(theUrlAttr);
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
RuntimeChildDeclaredExtensionDefinition declaredExtension = myDefinition.getDeclaredExtension(theUrlAttr, baseServerUrl);
if (declaredExtension != null) {
BaseState newState = new DeclaredExtensionState(getPreResourceState(), declaredExtension, myInstance);
push(newState);
} else {
super.enteringNewElementExtension(theElement, theUrlAttr, theIsModifier);
super.enteringNewElementExtension(theElement, theUrlAttr, theIsModifier, baseServerUrl);
}
}

Expand Down Expand Up @@ -2466,7 +2466,7 @@ public void enteringNewElement(String theNamespaceUri, String theLocalPart) thro
}

@Override
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier) {
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
myDepth++;
}

Expand Down
12 changes: 6 additions & 6 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
Expand Up @@ -213,7 +213,7 @@ private <T> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState)
} else {
url = urlAttr.getValue();
}
parserState.enteringNewElementExtension(elem, url, false);
parserState.enteringNewElementExtension(elem, url, false, getServerBaseUrl());
} else if ("modifierExtension".equals(elem.getName().getLocalPart())) {
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
String url;
Expand All @@ -223,7 +223,7 @@ private <T> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState)
} else {
url = urlAttr.getValue();
}
parserState.enteringNewElementExtension(elem, url, true);
parserState.enteringNewElementExtension(elem, url, true, getServerBaseUrl());
} else {
String elementName = elem.getName().getLocalPart();
parserState.enteringNewElement(namespaceURI, elementName);
Expand Down Expand Up @@ -655,11 +655,11 @@ private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBa

String childName = childNameAndDef.getChildName();
BaseRuntimeElementDefinition<?> childDef = childNameAndDef.getChildDef();
String extensionUrl = nextChild.getExtensionUrl();
String extensionUrl = getExtensionUrl(nextChild.getExtensionUrl());

if (nextValue instanceof IBaseExtension && myContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
// This is called for the Query resource in DSTU1 only
extensionUrl = ((IBaseExtension<?, ?>) nextValue).getUrl();
extensionUrl = getExtensionUrl(((IBaseExtension<?, ?>) nextValue).getUrl());
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theContainedResource, nextChildElem);

} else if (extensionUrl != null && childName.equals("extension") == false) {
Expand All @@ -671,7 +671,7 @@ private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBa
continue;
}
}
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, extension.getUrl(), theContainedResource, nextChildElem);
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, getExtensionUrl(extension.getUrl()), theContainedResource, nextChildElem);
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
// suppress narratives from contained resources
} else {
Expand Down Expand Up @@ -902,7 +902,7 @@ private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWrit
theEventWriter.writeAttribute("id", elementId);
}

String url = next.getUrl();
String url = getExtensionUrl(next.getUrl());
theEventWriter.writeAttribute("url", url);

if (next.getValue() != null) {
Expand Down
Expand Up @@ -482,6 +482,7 @@ public T invokeClient(String theResponseMimeType, Reader theResponseReader, int
throw NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
}
IParser parser = respType.newParser(getFhirContext());
parser.setServerBaseUrl(getUrlBase());
if (myPreferResponseTypes != null) {
parser.setPreferTypes(myPreferResponseTypes);
}
Expand Down
Expand Up @@ -179,7 +179,7 @@ public static <T extends IBaseResource> T loadResourceFromRequest(RequestDetails
}

IParser parser = encoding.newParser(ctx);

parser.setServerBaseUrl(theRequest.getFhirServerBase());
T retVal;
try {
if (theResourceType != null) {
Expand Down
Expand Up @@ -41,8 +41,10 @@
import javax.ws.rs.core.Response;

import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.hapi.rest.server.ServerConformanceProvider;
import org.hl7.fhir.dstu3.model.Conformance;
import org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider;
import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import ca.uhn.fhir.model.dstu2.resource.Conformance;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -83,8 +85,8 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
private RestulfulServerConfiguration serverConfiguration = new RestulfulServerConfiguration();

/** the conformance. It is created once during startup */
private Conformance myDstu3Conformance;
private ca.uhn.fhir.model.dstu2.resource.Conformance myDstu2Conformance;
private CapabilityStatement myDstu3Conformance;
private Conformance myDstu2Conformance;

/**
* Constructor allowing the description, servername and server to be set
Expand Down Expand Up @@ -142,11 +144,12 @@ protected void setUpPostConstruct() {
hardcodedServerAddressStrategy.setValue(getBaseForServer());
serverConfiguration.setServerAddressStrategy(hardcodedServerAddressStrategy);
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
// ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
final ServerCapabilityStatementProvider serverConformanceProvider = new ServerCapabilityStatementProvider((serverConfiguration));
serverConformanceProvider.initializeOperations();
myDstu3Conformance = serverConformanceProvider.getServerConformance(null);
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider serverConformanceProvider = new ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider(serverConfiguration);
ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
serverConformanceProvider.initializeOperations();
myDstu2Conformance = serverConformanceProvider.getServerConformance(null);
}
Expand Down Expand Up @@ -275,9 +278,9 @@ public int addProvider(IResourceProvider theProvider, Class<? extends IResourceP
@Override
public Class<IBaseResource> getResourceType() {
if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
return Class.class.cast(Conformance.class);
return Class.class.cast(CapabilityStatement.class);
} else if (super.getFhirContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
return Class.class.cast(ca.uhn.fhir.model.dstu2.resource.Conformance.class);
return Class.class.cast(Conformance.class);
}
return null;
}
Expand Down
Expand Up @@ -32,6 +32,7 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;

Expand Down Expand Up @@ -125,7 +126,8 @@ public IServerAddressStrategy getServerAddressStrategy() {
* @return the ascii string for the server base
*/
public String getBaseForServer() {
return getUriInfo().getBaseUri().toASCIIString();
final String url = getUriInfo().getBaseUri().toASCIIString();
return StringUtils.isNotBlank(url) && url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
}

/**
Expand Down
Expand Up @@ -286,6 +286,12 @@ public Response findCompartment(@PathParam("id") final String id, @PathParam("co
return execute(theRequest, compartment);
}

@POST
@Path("/$validate")
public Response validate(final String resource) throws IOException {
return customOperation(resource, RequestTypeEnum.POST, null, "$validate", RestOperationTypeEnum.EXTENDED_OPERATION_TYPE);
}

/**
* Execute the method described by the requestBuilder and methodKey
*
Expand Down
@@ -1,7 +1,9 @@
package ca.uhn.fhir.jaxrs.server;

import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

Expand All @@ -24,10 +26,11 @@
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Conformance;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Identifier;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Resource;
Expand Down Expand Up @@ -154,7 +157,7 @@ public void testConditionalCreate() throws Exception {
toCreate.getIdentifier().add(new Identifier().setValue("myIdentifier"));
outcome.setResource(toCreate);

when(mock.create(patientCaptor.capture(), eq("Patient?_format=json&identifier=2"))).thenReturn(outcome);
when(mock.create(patientCaptor.capture(), eq("/Patient?_format=json&identifier=2"))).thenReturn(outcome);
client.setEncoding(EncodingEnum.JSON);

MethodOutcome response = client.create().resource(toCreate).conditional()
Expand All @@ -168,7 +171,7 @@ public void testConditionalCreate() throws Exception {
/** Conformance - Server */
@Test
public void testConformance() {
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
final CapabilityStatement conf = client.fetchConformance().ofType(CapabilityStatement.class).execute();
assertEquals(conf.getRest().get(0).getResource().get(0).getType().toString(), "Patient");
}

Expand Down Expand Up @@ -426,6 +429,21 @@ public void testXFindUnknownPatient() {
assertTrue(e.getMessage().contains("999955541264"));
}
}

@Test
public void testValidate() {
// prepare mock
final OperationOutcome oo = new OperationOutcome();
final Patient patient = new Patient();
patient.addIdentifier((new Identifier().setValue("1")));
//invoke
final Parameters inParams = new Parameters();
inParams.addParameter().setResource(patient);

final MethodOutcome mO = client.validate().resource(patient).execute();
//verify
assertNotNull(mO.getOperationOutcome());
}

@BeforeClass
public static void setUpClass() throws Exception {
Expand Down

0 comments on commit 745820d

Please sign in to comment.