+ * Patch is used to apply a differential to a resource in either
+ * XML or JSON format
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface Patch {
+
+ /**
+ * The return type for this search method. This generally does not need
+ * to be populated for a server implementation, since servers will return
+ * only one resource per class, but generally does need to be populated
+ * for client implementations.
+ */
+ // NB: Read, Search (maybe others) share this annotation, so update the javadocs everywhere
+ Class extends IBaseResource> type() default IBaseResource.class;
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PatchTypeEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PatchTypeEnum.java
new file mode 100644
index 00000000000..24fbbf48107
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/PatchTypeEnum.java
@@ -0,0 +1,43 @@
+package ca.uhn.fhir.rest.api;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import ca.uhn.fhir.rest.annotation.Patch;
+import ca.uhn.fhir.rest.server.Constants;
+
+/**
+ * Parameter type for methods annotated with {@link Patch}
+ */
+public enum PatchTypeEnum {
+
+ JSON_PATCH(Constants.CT_JSON_PATCH), XML_PATCH(Constants.CT_XML_PATCH);
+
+ private final String myContentType;
+
+ PatchTypeEnum(String theContentType) {
+ myContentType = theContentType;
+ }
+
+ public String getContentType() {
+ return myContentType;
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/RestOperationTypeEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/RestOperationTypeEnum.java
index 5e62a58a7e0..e6ccf32768c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/RestOperationTypeEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/RestOperationTypeEnum.java
@@ -130,7 +130,12 @@ public enum RestOperationTypeEnum {
/**
* $meta-delete extended operation
*/
- META_DELETE("$meta-delete"),
+ META_DELETE("$meta-delete"),
+
+ /**
+ * Patch operation
+ */
+ PATCH("patch"),
;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java
index f0a1a32d277..3bfb5bee98c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java
@@ -1,7 +1,5 @@
package ca.uhn.fhir.rest.client;
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
-
/*
* #%L
* HAPI FHIR - Core Library
@@ -22,33 +20,20 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* #L%
*/
-import java.io.ByteArrayInputStream;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
-import org.hl7.fhir.instance.model.api.IBase;
-import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.hl7.fhir.instance.model.api.IPrimitiveType;
+import org.hl7.fhir.instance.model.api.*;
-import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
-import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
-import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
+import ca.uhn.fhir.context.*;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.SummaryEnum;
@@ -67,6 +52,7 @@ import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.util.OperationOutcomeUtil;
+import ca.uhn.fhir.util.XmlUtil;
public abstract class BaseClient implements IRestfulClient {
@@ -105,6 +91,11 @@ public abstract class BaseClient implements IRestfulClient {
if ("true".equals(System.getProperty(HAPI_CLIENT_KEEPRESPONSES))) {
setKeepResponses(true);
}
+
+ if (XmlUtil.isStaxPresent() == false) {
+ myEncoding = EncodingEnum.JSON;
+ }
+
}
protected Map> createExtraParams() {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
index 895e795a5f1..9b39d0df5e7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java
@@ -69,6 +69,7 @@ import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
@@ -107,6 +108,11 @@ import ca.uhn.fhir.rest.gclient.IOperationUntyped;
import ca.uhn.fhir.rest.gclient.IOperationUntypedWithInput;
import ca.uhn.fhir.rest.gclient.IOperationUntypedWithInputAndPartialOutput;
import ca.uhn.fhir.rest.gclient.IParam;
+import ca.uhn.fhir.rest.gclient.IPatch;
+import ca.uhn.fhir.rest.gclient.IPatchExecutable;
+import ca.uhn.fhir.rest.gclient.IPatchTyped;
+import ca.uhn.fhir.rest.gclient.IPatchWithQuery;
+import ca.uhn.fhir.rest.gclient.IPatchWithQueryTyped;
import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.gclient.IRead;
import ca.uhn.fhir.rest.gclient.IReadExecutable;
@@ -519,6 +525,32 @@ public class GenericClient extends BaseClient implements IGenericClient {
return new ArrayList(resp.toListOfResources());
}
+
+
+ @Override
+ public IPatch patch() {
+ return new PatchInternal();
+ }
+
+ @Override
+ public MethodOutcome patch(IdDt theIdDt, IBaseResource theResource) {
+ BaseHttpClientInvocation invocation = MethodUtil.createUpdateInvocation(theResource, null, theIdDt, myContext);
+ if (isKeepResponses()) {
+ myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
+ }
+
+ RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
+ final String resourceName = def.getName();
+
+ OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
+ MethodOutcome resp = invokeClient(myContext, binding, invocation, myLogRequestAndResponse);
+ return resp;
+ }
+
+ @Override
+ public MethodOutcome patch(String theId, IBaseResource theResource) {
+ return update(new IdDt(theId), theResource);
+ }
@Override
public IUpdate update() {
@@ -2287,6 +2319,139 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
}
+
+ private class PatchInternal extends BaseClientExecutable implements IPatch, IPatchTyped, IPatchExecutable, IPatchWithQuery, IPatchWithQueryTyped {
+
+ private CriterionList myCriterionList;
+ private IIdType myId;
+ private PreferReturnEnum myPrefer;
+ private IBaseResource myResource;
+ private String myResourceBody;
+ private String mySearchUrl;
+ private PatchTypeEnum myPatchType;
+ private String myPatchBody;
+
+ @Override
+ public IPatchWithQueryTyped and(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
+ @Override
+ public IPatchWithQuery conditional() {
+ myCriterionList = new CriterionList();
+ return this;
+ }
+
+ @Override
+ public IPatchTyped conditionalByUrl(String theSearchUrl) {
+ mySearchUrl = validateAndEscapeConditionalUrl(theSearchUrl);
+ return this;
+ }
+
+ @Override
+ public MethodOutcome execute() {
+ if (myResource == null) {
+ myResource = parseResourceBody(myResourceBody);
+ }
+
+ // If an explicit encoding is chosen, we will re-serialize to ensure the right encoding
+ if (getParamEncoding() != null) {
+ myResourceBody = null;
+ }
+
+ if (myPatchType == null) {
+ throw new InvalidRequestException("No patch type supplied, cannot invoke server");
+ }
+ if (myPatchBody == null) {
+ throw new InvalidRequestException("No patch body supplied, cannot invoke server");
+ }
+
+
+ if (myId == null) {
+ myId = myResource.getIdElement();
+ }
+
+ if (myId == null || myId.hasIdPart() == false) {
+ throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
+ }
+ BaseHttpClientInvocation invocation = MethodUtil.createPatchInvocation(myContext, myId, myPatchType, myPatchBody);
+
+ addPreferHeader(myPrefer, invocation);
+
+ RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
+ final String resourceName = def.getName();
+
+ OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName, myPrefer);
+
+ Map> params = new HashMap>();
+ return invoke(params, binding, invocation);
+
+ }
+
+ @Override
+ public IPatchExecutable prefer(PreferReturnEnum theReturn) {
+ myPrefer = theReturn;
+ return this;
+ }
+
+ @Override
+ public IPatchTyped resource(IBaseResource theResource) {
+ Validate.notNull(theResource, "Resource can not be null");
+ myResource = theResource;
+ return this;
+ }
+
+ @Override
+ public IPatchTyped resource(String theResourceBody) {
+ Validate.notBlank(theResourceBody, "Body can not be null or blank");
+ myResourceBody = theResourceBody;
+ return this;
+ }
+
+ @Override
+ public IPatchWithQueryTyped where(ICriterion> theCriterion) {
+ myCriterionList.add((ICriterionInternal) theCriterion);
+ return this;
+ }
+
+ @Override
+ public IPatchExecutable withId(IIdType theId) {
+ if (theId == null) {
+ throw new NullPointerException("theId can not be null");
+ }
+ if (theId.hasIdPart() == false) {
+ throw new NullPointerException("theId must not be blank and must contain an ID, found: " + theId.getValue());
+ }
+ myId = theId;
+ return this;
+ }
+
+ @Override
+ public IPatchExecutable withId(String theId) {
+ if (theId == null) {
+ throw new NullPointerException("theId can not be null");
+ }
+ if (isBlank(theId)) {
+ throw new NullPointerException("theId must not be blank and must contain an ID, found: " + theId);
+ }
+ myId = new IdDt(theId);
+ return this;
+ }
+
+ @Override
+ public IPatchTyped patchType(PatchTypeEnum patchType) {
+ myPatchType = patchType;
+ return this;
+ }
+
+ @Override
+ public IPatchTyped patchBody(String patchBody) {
+ myPatchBody = patchBody;
+ return this;
+ }
+
+ }
private class UpdateInternal extends BaseClientExecutable implements IUpdate, IUpdateTyped, IUpdateExecutable, IUpdateWithQuery, IUpdateWithQueryTyped {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
index ac49faf4b8d..7d79af36e3e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/IGenericClient.java
@@ -46,6 +46,7 @@ import ca.uhn.fhir.rest.gclient.IGetTags;
import ca.uhn.fhir.rest.gclient.IHistory;
import ca.uhn.fhir.rest.gclient.IMeta;
import ca.uhn.fhir.rest.gclient.IOperation;
+import ca.uhn.fhir.rest.gclient.IPatch;
import ca.uhn.fhir.rest.gclient.IRead;
import ca.uhn.fhir.rest.gclient.ITransaction;
import ca.uhn.fhir.rest.gclient.IUntypedQuery;
@@ -253,6 +254,35 @@ public interface IGenericClient extends IRestfulClient {
@Override
void registerInterceptor(IClientInterceptor theInterceptor);
+
+ /**
+ * Fluent method for the "patch" operation, which performs a logical patch on a server resource
+ */
+ IPatch patch();
+
+ /**
+ * Implementation of the "instance patch" method.
+ *
+ * @param theId
+ * The ID to update
+ * @param theResource
+ * The new resource body
+ * @return An outcome containing the results and possibly the new version ID
+ */
+ MethodOutcome patch(IdDt theId, IBaseResource theResource);
+
+ /**
+ * Implementation of the "instance update" method.
+ *
+ * @param theId
+ * The ID to update
+ * @param theResource
+ * The new resource body
+ * @return An outcome containing the results and possibly the new version ID
+ */
+ MethodOutcome patch(String theId, IBaseResource theResource);
+
+
/**
* Search for resources matching a given set of criteria. Searching is a very powerful
* feature in FHIR with many features for specifying exactly what should be seaerched for
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java
index 48ac411ea50..f635e236bb6 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java
@@ -30,12 +30,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpOptions;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicNameValuePair;
import org.hl7.fhir.instance.model.api.IBaseBinary;
@@ -188,6 +183,10 @@ public class ApacheHttpClient implements IHttpClient {
switch (myRequestType) {
case DELETE:
return new HttpDelete(url);
+ case PATCH:
+ HttpPatch httpPatch = new HttpPatch(url);
+ httpPatch.setEntity(theEntity);
+ return httpPatch;
case OPTIONS:
return new HttpOptions(url);
case POST:
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatch.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatch.java
new file mode 100644
index 00000000000..7fc26ed0d7f
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatch.java
@@ -0,0 +1,31 @@
+package ca.uhn.fhir.rest.gclient;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+public interface IPatch {
+
+ IPatchTyped resource(IBaseResource theResource);
+
+ IPatchTyped resource(String theResourceBody);
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchExecutable.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchExecutable.java
new file mode 100644
index 00000000000..3fb718598f3
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchExecutable.java
@@ -0,0 +1,37 @@
+package ca.uhn.fhir.rest.gclient;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PreferReturnEnum;
+
+public interface IPatchExecutable extends IClientExecutable{
+
+ /**
+ * Add a Prefer header to the request, which requests that the server include
+ * or suppress the resource body as a part of the result. If a resource is returned by the server
+ * it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}
+ *
+ * @since HAPI 1.1
+ */
+ IPatchExecutable prefer(PreferReturnEnum theReturn);
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchTyped.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchTyped.java
new file mode 100644
index 00000000000..e38522587ac
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchTyped.java
@@ -0,0 +1,61 @@
+package ca.uhn.fhir.rest.gclient;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import org.hl7.fhir.instance.model.api.IIdType;
+
+import ca.uhn.fhir.rest.api.PatchTypeEnum;
+
+public interface IPatchTyped extends IPatchExecutable {
+
+ IPatchExecutable withId(IIdType theId);
+
+ IPatchExecutable withId(String theId);
+
+ /**
+ * Specifies that the update should be performed as a conditional create
+ * against a given search URL.
+ *
+ * @param theSearchUrl The search URL to use. The format of this URL should be of the form [ResourceType]?[Parameters],
+ * for example: Patient?name=Smith&identifier=13.2.4.11.4%7C847366
+ * @since HAPI 0.9 / FHIR DSTU 2
+ */
+ IPatchTyped conditionalByUrl(String theSearchUrl);
+
+ /**
+ * @since HAPI 0.9 / FHIR DSTU 2
+ */
+ IPatchWithQuery conditional();
+
+ /**
+ * Specifies the format of the patch (either XML or JSON)
+ * @param patchType
+ */
+ IPatchTyped patchType(PatchTypeEnum patchType);
+
+ /**
+ * The body of the patch document serialized in either XML or JSON which conforms to
+ * http://jsonpatch.com/ or http://tools.ietf.org/html/rfc5261
+ * @param patchBody
+ */
+ IPatchTyped patchBody(String patchBody);
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQuery.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQuery.java
new file mode 100644
index 00000000000..32b94c5c02c
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQuery.java
@@ -0,0 +1,26 @@
+package ca.uhn.fhir.rest.gclient;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+
+public interface IPatchWithQuery extends IBaseQuery {
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQueryTyped.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQueryTyped.java
new file mode 100644
index 00000000000..cdc639f1dfa
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/IPatchWithQueryTyped.java
@@ -0,0 +1,25 @@
+package ca.uhn.fhir.rest.gclient;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+public interface IPatchWithQueryTyped extends IPatchTyped, IPatchWithQuery {
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
index cb485611393..65b387cd5e6 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseHttpClientInvocationWithContents.java
@@ -211,8 +211,12 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
private String getContentType(EncodingEnum encoding) {
if (myBundle != null || (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1 && ((myContents != null && myContentsIsBundle) || myResources != null))) {
return encoding.getBundleContentType();
- } else {
+ } else if (getContext().getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
+ // application/xml+fhir
return encoding.getResourceContentType();
+ } else {
+ // application/fhir+xml
+ return encoding.getResourceContentTypeNonLegacy();
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
index b4155cede8d..5e540dd1584 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseMethodBinding.java
@@ -46,20 +46,7 @@ import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.parser.IParser;
-import ca.uhn.fhir.rest.annotation.AddTags;
-import ca.uhn.fhir.rest.annotation.Create;
-import ca.uhn.fhir.rest.annotation.Delete;
-import ca.uhn.fhir.rest.annotation.DeleteTags;
-import ca.uhn.fhir.rest.annotation.GetPage;
-import ca.uhn.fhir.rest.annotation.GetTags;
-import ca.uhn.fhir.rest.annotation.History;
-import ca.uhn.fhir.rest.annotation.Metadata;
-import ca.uhn.fhir.rest.annotation.Operation;
-import ca.uhn.fhir.rest.annotation.Read;
-import ca.uhn.fhir.rest.annotation.Search;
-import ca.uhn.fhir.rest.annotation.Transaction;
-import ca.uhn.fhir.rest.annotation.Update;
-import ca.uhn.fhir.rest.annotation.Validate;
+import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
@@ -387,9 +374,10 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
Transaction transaction = theMethod.getAnnotation(Transaction.class);
Operation operation = theMethod.getAnnotation(Operation.class);
GetPage getPage = theMethod.getAnnotation(GetPage.class);
+ Patch patch = theMethod.getAnnotation(Patch.class);
// ** if you add another annotation above, also add it to the next line:
- if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, getTags, addTags, deleteTags, transaction, operation, getPage)) {
+ if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, getTags, addTags, deleteTags, transaction, operation, getPage, patch)) {
return null;
}
@@ -414,7 +402,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @"
+ GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
}
- } else if (MethodOutcome.class.equals(returnTypeFromMethod)) {
+ } else if (MethodOutcome.class.isAssignableFrom(returnTypeFromMethod)) {
// returns a method outcome
} else if (IBundleProvider.class.equals(returnTypeFromMethod)) {
// returns a bundle provider
@@ -448,6 +436,8 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
returnTypeFromAnnotation = history.type();
} else if (delete != null) {
returnTypeFromAnnotation = delete.type();
+ } else if (patch != null) {
+ returnTypeFromAnnotation = patch.type();
} else if (create != null) {
returnTypeFromAnnotation = create.type();
} else if (update != null) {
@@ -513,6 +503,8 @@ public abstract class BaseMethodBinding implements IClientResponseHandler
return new UpdateMethodBinding(theMethod, theContext, theProvider);
} else if (delete != null) {
return new DeleteMethodBinding(theMethod, theContext, theProvider);
+ } else if (patch != null) {
+ return new PatchMethodBinding(theMethod, theContext, theProvider);
} else if (history != null) {
return new HistoryMethodBinding(theMethod, theContext, theProvider);
} else if (validate != null) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
index bcd7c825b7e..e39173ef7fe 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java
@@ -184,8 +184,15 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding theMethodAnnotationType, Class extends IBaseResource> theResourceTypeFromAnnotation) {
+ super(theMethod, theContext, theMethodAnnotationType, theProvider);
+
+ Class extends IBaseResource> resourceType = theResourceTypeFromAnnotation;
+ if (resourceType != IBaseResource.class) {
+ RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType);
+ myResourceName = def.getName();
+ } else {
+ if (theProvider != null && theProvider instanceof IResourceProvider) {
+ RuntimeResourceDefinition def = theContext.getResourceDefinition(((IResourceProvider) theProvider).getResourceType());
+ myResourceName = def.getName();
+ } else {
+ throw new ConfigurationException(
+ "Can not determine resource type for method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getCanonicalName() + " - Did you forget to include the resourceType() value on the @" + Delete.class.getSimpleName() + " method annotation?");
+ }
+ }
+
+ myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
+ if (myIdParameterIndex == null) {
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has no parameter annotated with the @" + IdParam.class.getSimpleName() + " annotation");
+ }
+
+ Integer versionIdParameterIndex = MethodUtil.findVersionIdParameterIndex(theMethod);
+ if (versionIdParameterIndex != null) {
+ throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has a parameter annotated with the @" + VersionIdParam.class.getSimpleName() + " annotation but delete methods may not have this annotation");
+ }
+
+ }
+
+ @Override
+ public String getResourceName() {
+ return myResourceName;
+ }
+
+ protected Integer getIdParameterIndex() {
+ return myIdParameterIndex;
+ }
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
index 1642794a39a..f24326cde6d 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/DeleteMethodBinding.java
@@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.method;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,59 +28,19 @@ import java.util.Set;
import org.hl7.fhir.instance.model.api.IIdType;
-import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.IResource;
-import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Delete;
-import ca.uhn.fhir.rest.annotation.IdParam;
-import ca.uhn.fhir.rest.annotation.VersionIdParam;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
-import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
-
- private String myResourceName;
- private Integer myIdParameterIndex;
+public class DeleteMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceIdButNoResourceBody {
public DeleteMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
- super(theMethod, theContext, Delete.class, theProvider);
-
- Delete deleteAnnotation = theMethod.getAnnotation(Delete.class);
- Class extends IResource> resourceType = deleteAnnotation.type();
- if (resourceType != IResource.class) {
- RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType);
- myResourceName = def.getName();
- } else {
- if (theProvider != null && theProvider instanceof IResourceProvider) {
- RuntimeResourceDefinition def = theContext.getResourceDefinition(((IResourceProvider) theProvider).getResourceType());
- myResourceName = def.getName();
- } else {
- throw new ConfigurationException(
- "Can not determine resource type for method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getCanonicalName() + " - Did you forget to include the resourceType() value on the @" + Delete.class.getSimpleName() + " method annotation?");
- }
- }
-
- myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
- if (myIdParameterIndex == null) {
- throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has no parameter annotated with the @" + IdParam.class.getSimpleName() + " annotation");
- }
-
- Integer versionIdParameterIndex = MethodUtil.findVersionIdParameterIndex(theMethod);
- if (versionIdParameterIndex != null) {
- throw new ConfigurationException("Method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName() + "' has a parameter annotated with the @" + VersionIdParam.class.getSimpleName() + " annotation but delete methods may not have this annotation");
- }
-
- }
-
- @Override
- protected boolean allowVoidReturnType() {
- return true;
+ super(theMethod, theContext, theProvider, Delete.class, theMethod.getAnnotation(Delete.class).type());
}
@Override
@@ -102,13 +62,13 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
}
@Override
- public String getResourceName() {
- return myResourceName;
+ protected boolean allowVoidReturnType() {
+ return true;
}
@Override
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
- IdDt idDt = (IdDt) theArgs[myIdParameterIndex];
+ IIdType idDt = (IIdType) theArgs[getIdParameterIndex()];
if (idDt == null) {
throw new NullPointerException("ID can not be null");
}
@@ -136,7 +96,7 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
- theParams[myIdParameterIndex] = theRequest.getId();
+ theParams[getIdParameterIndex()] = theRequest.getId();
}
@Override
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpDeleteClientInvocation.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpDeleteClientInvocation.java
index e7e869d8976..7cce411bada 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpDeleteClientInvocation.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpDeleteClientInvocation.java
@@ -67,4 +67,10 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
return createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.DELETE);
}
+ @Override
+ protected IHttpRequest createHttpRequest(String theUrl, EncodingEnum theEncoding, RequestTypeEnum theRequestType) {
+ // TODO Auto-generated method stub
+ return super.createHttpRequest(theUrl, theEncoding, theRequestType);
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPatchClientInvocation.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPatchClientInvocation.java
new file mode 100644
index 00000000000..2969fb4d063
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPatchClientInvocation.java
@@ -0,0 +1,84 @@
+package ca.uhn.fhir.rest.method;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import java.util.List;
+import java.util.Map;
+
+import org.hl7.fhir.instance.model.api.IIdType;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.api.RequestTypeEnum;
+import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
+import ca.uhn.fhir.rest.client.api.IHttpClient;
+import ca.uhn.fhir.rest.client.api.IHttpRequest;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+
+public class HttpPatchClientInvocation extends BaseHttpClientInvocation {
+
+ private String myUrlPath;
+ private Map> myParams;
+ private String myContents;
+ private String myContentType;
+
+ public HttpPatchClientInvocation(FhirContext theContext, IIdType theId, String theContentType, String theContents) {
+ super(theContext);
+ myUrlPath = theId.toUnqualifiedVersionless().getValue();
+ myContentType = theContentType;
+ myContents = theContents;
+ }
+//
+// public HttpDeleteClientInvocation(FhirContext theContext, String theSearchUrl) {
+// super(theContext);
+// myUrlPath = theSearchUrl;
+// }
+//
+// public HttpDeleteClientInvocation(FhirContext theContext, String theResourceType, Map> theParams) {
+// super(theContext);
+// myUrlPath = theResourceType;
+// myParams = theParams;
+// }
+
+ @Override
+ public IHttpRequest asHttpRequest(String theUrlBase, Map> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
+ StringBuilder b = new StringBuilder();
+ b.append(theUrlBase);
+ if (!theUrlBase.endsWith("/")) {
+ b.append('/');
+ }
+ b.append(myUrlPath);
+
+ appendExtraParamsWithQuestionMark(myParams, b, b.indexOf("?") == -1);
+ appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
+
+
+
+ return createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.PATCH);
+ }
+
+ @Override
+ protected IHttpRequest createHttpRequest(String theUrl, EncodingEnum theEncoding, RequestTypeEnum theRequestType) {
+ IHttpClient httpClient = getRestfulClientFactory().getHttpClient(new StringBuilder(theUrl), null, null, theRequestType, getHeaders());
+ return httpClient.createByteRequest(getContext(), myContents, myContentType, null);
+ }
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java
index c5f8f2ed557..d52243fdd35 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java
@@ -22,10 +22,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.*;
-import ca.uhn.fhir.rest.api.MethodOutcome;
-import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
-import ca.uhn.fhir.rest.api.SummaryEnum;
-import ca.uhn.fhir.rest.api.ValidationModeEnum;
+import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.method.OperationParameter.IOperationParamConverter;
import ca.uhn.fhir.rest.param.*;
@@ -158,6 +155,12 @@ public class MethodUtil {
retVal.setIfNoneExistString(theIfNoneExistUrl);
return retVal;
}
+
+ public static HttpPatchClientInvocation createPatchInvocation(FhirContext theContext, IIdType theId, PatchTypeEnum thePatchType, String theBody) {
+ return PatchMethodBinding.createPatchInvocation(theContext, theId, thePatchType, theBody);
+ }
+
+ /** End Patch **/
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IBaseResource theResource, String theResourceBody, Map> theMatchParams) {
StringBuilder b = new StringBuilder();
@@ -188,6 +191,7 @@ public class MethodUtil {
return retVal;
}
+
public static HttpPutClientInvocation createUpdateInvocation(FhirContext theContext, IBaseResource theResource, String theResourceBody, String theMatchUrl) {
HttpPutClientInvocation retVal;
if (StringUtils.isBlank(theResourceBody)) {
@@ -364,6 +368,8 @@ public class MethodUtil {
param = new RequestOperationCallbackParameter();
} else if (parameterType.equals(SummaryEnum.class)) {
param = new SummaryEnumParameter();
+ } else if (parameterType.equals(PatchTypeEnum.class)) {
+ param = new PatchTypeParameter();
} else {
for (int i = 0; i < annotations.length && param == null; i++) {
Annotation nextAnnotation = annotations[i];
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchMethodBinding.java
new file mode 100644
index 00000000000..37d9514c2ae
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchMethodBinding.java
@@ -0,0 +1,153 @@
+package ca.uhn.fhir.rest.method;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.hl7.fhir.instance.model.api.IIdType;
+
+import ca.uhn.fhir.context.ConfigurationException;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.IResource;
+import ca.uhn.fhir.rest.annotation.Patch;
+import ca.uhn.fhir.rest.annotation.ResourceParam;
+import ca.uhn.fhir.rest.api.PatchTypeEnum;
+import ca.uhn.fhir.rest.api.RequestTypeEnum;
+import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
+import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
+import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
+import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
+
+/**
+ * Base class for an operation that has a resource type but not a resource body in the
+ * request body
+ *
+ */
+public class PatchMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceIdButNoResourceBody {
+
+ private int myPatchTypeParameterIndex = -1;
+ private int myResourceParamIndex;
+
+ public PatchMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
+ super(theMethod, theContext, theProvider, Patch.class, theMethod.getAnnotation(Patch.class).type());
+
+ for (ListIterator> iter = Arrays.asList(theMethod.getParameterTypes()).listIterator(); iter.hasNext();) {
+ int nextIndex = iter.nextIndex();
+ Class> next = iter.next();
+ if (next.equals(PatchTypeEnum.class)) {
+ myPatchTypeParameterIndex = nextIndex;
+ }
+ for (Annotation nextAnnotation : theMethod.getParameterAnnotations()[nextIndex]) {
+ if (nextAnnotation instanceof ResourceParam) {
+ myResourceParamIndex = nextIndex;
+ }
+ }
+ }
+
+ if (myPatchTypeParameterIndex == -1) {
+ throw new ConfigurationException("Method has no parameter of type " + PatchTypeEnum.class.getName() + " - " + theMethod.toString());
+ }
+ if (myResourceParamIndex == -1) {
+ throw new ConfigurationException("Method has no parameter with @" + ResourceParam.class.getSimpleName() + " annotation - " + theMethod.toString());
+ }
+ }
+
+ @Override
+ public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
+ boolean retVal = super.incomingServerRequestMatchesMethod(theRequest);
+ if (retVal) {
+ PatchTypeParameter.getTypeForRequestOrThrowInvalidRequestException(theRequest);
+ }
+ return retVal;
+ }
+
+ @Override
+ public RestOperationTypeEnum getRestOperationType() {
+ return RestOperationTypeEnum.PATCH;
+ }
+
+ @Override
+ protected Set provideAllowableRequestTypes() {
+ return Collections.singleton(RequestTypeEnum.PATCH);
+ }
+
+ @Override
+ protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {
+ StringBuilder urlExtension = new StringBuilder();
+ urlExtension.append(getContext().getResourceDefinition(theResource).getName());
+
+ return new HttpPostClientInvocation(getContext(), theResource, urlExtension.toString());
+ }
+
+ @Override
+ protected boolean allowVoidReturnType() {
+ return true;
+ }
+
+ @Override
+ public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
+ IIdType idDt = (IIdType) theArgs[getIdParameterIndex()];
+ if (idDt == null) {
+ throw new NullPointerException("ID can not be null");
+ }
+
+ if (idDt.hasResourceType() == false) {
+ idDt = idDt.withResourceType(getResourceName());
+ } else if (getResourceName().equals(idDt.getResourceType()) == false) {
+ throw new InvalidRequestException("ID parameter has the wrong resource type, expected '" + getResourceName() + "', found: " + idDt.getResourceType());
+ }
+
+ PatchTypeEnum patchType = (PatchTypeEnum) theArgs[myPatchTypeParameterIndex];
+ String body = (String) theArgs[myResourceParamIndex];
+
+ HttpPatchClientInvocation retVal = createPatchInvocation(getContext(), idDt, patchType, body);
+
+ for (int idx = 0; idx < theArgs.length; idx++) {
+ IParameter nextParam = getParameters().get(idx);
+ nextParam.translateClientArgumentIntoQueryArgument(getContext(), theArgs[idx], null, null);
+ }
+
+ return retVal;
+ }
+
+ public static HttpPatchClientInvocation createPatchInvocation(FhirContext theContext, IIdType theId, PatchTypeEnum thePatchType, String theBody) {
+ HttpPatchClientInvocation retVal = new HttpPatchClientInvocation(theContext, theId, thePatchType.getContentType(), theBody);
+ return retVal;
+ }
+
+ @Override
+ protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
+ IIdType id = theRequest.getId();
+ id = UpdateMethodBinding.applyETagAsVersion(theRequest, id);
+ theParams[getIdParameterIndex()] = id;
+ }
+
+ @Override
+ protected String getMatchingOperation() {
+ return null;
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchTypeParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchTypeParameter.java
new file mode 100644
index 00000000000..32a46c94d54
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PatchTypeParameter.java
@@ -0,0 +1,72 @@
+package ca.uhn.fhir.rest.method;
+
+import static org.apache.commons.lang3.StringUtils.defaultString;
+
+/*
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2016 University Health Network
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.api.PatchTypeEnum;
+import ca.uhn.fhir.rest.server.Constants;
+import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
+import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
+import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
+
+class PatchTypeParameter implements IParameter {
+ @Override
+ public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
+ // nothing
+ }
+
+ @Override
+ public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding> theMethodBinding) throws InternalErrorException, InvalidRequestException {
+ return getTypeForRequestOrThrowInvalidRequestException(theRequest);
+ }
+
+ @Override
+ public void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType) {
+ // ignore
+ }
+
+ public static PatchTypeEnum getTypeForRequestOrThrowInvalidRequestException(RequestDetails theRequest) {
+ String contentTypeAll = defaultString(theRequest.getHeader(Constants.HEADER_CONTENT_TYPE));
+ String contentType = contentTypeAll;
+ int semiColonIdx = contentType.indexOf(';');
+ if (semiColonIdx != -1) {
+ contentType = contentTypeAll.substring(0, semiColonIdx);
+ }
+ contentType = contentType.trim();
+ if (Constants.CT_JSON_PATCH.equals(contentType)) {
+ return PatchTypeEnum.JSON_PATCH;
+ } else if (Constants.CT_XML_PATCH.equals(contentType)) {
+ return PatchTypeEnum.XML_PATCH;
+ } else {
+ throw new InvalidRequestException("Invalid Content-Type for PATCH operation: " + contentTypeAll);
+ }
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
index 77fd774a3e9..e4624dce4b3 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/ServletRequestParameter.java
@@ -35,6 +35,10 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
class ServletRequestParameter implements IParameter {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletRequestParameter.class);
+ ServletRequestParameter() {
+ super();
+ }
+
@Override
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
/*
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
index d30f57b4554..8140346752e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java
@@ -69,13 +69,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
}
}
- String ifMatchValue = theRequest.getHeader(Constants.HEADER_IF_MATCH);
- if (isNotBlank(ifMatchValue)) {
- ifMatchValue = MethodUtil.parseETagValue(ifMatchValue);
- if (id != null && id.hasVersionIdPart() == false) {
- id = id.withVersion(ifMatchValue);
- }
- }
+ id = applyETagAsVersion(theRequest, id);
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
if (id != null && id.hasVersionIdPart()) {
@@ -94,6 +88,17 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
super.addParametersForServerRequest(theRequest, theParams);
}
+ public static IIdType applyETagAsVersion(RequestDetails theRequest, IIdType id) {
+ String ifMatchValue = theRequest.getHeader(Constants.HEADER_IF_MATCH);
+ if (isNotBlank(ifMatchValue)) {
+ ifMatchValue = MethodUtil.parseETagValue(ifMatchValue);
+ if (id != null && id.hasVersionIdPart() == false) {
+ id = id.withVersion(ifMatchValue);
+ }
+ }
+ return id;
+ }
+
@Override
protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {
IdDt idDt = (IdDt) theArgs[myIdParameterIndex];
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index 22a17a003ab..a7c87d1bb23 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -63,6 +63,8 @@ public class Constants {
public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0";
public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_JSON_NEW + ";q=1.0, " + HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY.replace("1.0", "0.9");
+ public static final String HEADER_ACCEPT_VALUE_XML_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_XML + ";q=0.9";
+ public static final String HEADER_ACCEPT_VALUE_JSON_NON_LEGACY = CT_FHIR_JSON_NEW + ";q=1.0, " + CT_FHIR_JSON + ";q=0.9";
public static final String HEADER_ALLOW = "Allow";
public static final String HEADER_AUTHORIZATION = "Authorization";
public static final String HEADER_AUTHORIZATION_VALPREFIX_BASIC = "Basic ";
@@ -166,6 +168,8 @@ public class Constants {
public static final String TAG_SUBSETTED_SYSTEM = "http://hl7.org/fhir/v3/ObservationValue";
public static final String URL_TOKEN_HISTORY = "_history";
public static final String URL_TOKEN_METADATA = "metadata";
+ public static final String CT_JSON_PATCH = "application/json-patch+json";
+ public static final String CT_XML_PATCH = "application/xml-patch+xml";
static {
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
index b62bc691d42..59b7d6e5b84 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
@@ -29,15 +29,8 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
-import java.util.StringTokenizer;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.Manifest;
@@ -78,14 +71,16 @@ import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
-import ca.uhn.fhir.util.CoverageIgnore;
-import ca.uhn.fhir.util.ReflectionUtil;
-import ca.uhn.fhir.util.UrlPathTokenizer;
-import ca.uhn.fhir.util.UrlUtil;
-import ca.uhn.fhir.util.VersionUtil;
+import ca.uhn.fhir.util.*;
public class RestfulServer extends HttpServlet implements IRestfulServer {
+ /**
+ * All incoming requests will have an attribute added to {@link HttpServletRequest#getAttribute(String)}
+ * with this key. The value will be a Java {@link Date} with the time that request processing began.
+ */
+ public static final String REQUEST_START_TIME = RestfulServer.class.getName() + "REQUEST_START_TIME";
+
/**
* Default setting for {@link #setETagSupport(ETagSupportEnum) ETag Support}: {@link ETagSupportEnum#ENABLED}
*/
@@ -658,6 +653,11 @@ public class RestfulServer extends HttpServlet implements IRestfulServer= 0; i--) {
+ IServerInterceptor next = getInterceptors().get(i);
+ next.processingCompletedNormally(requestDetails);
+ }
+
} catch (NotModifiedException e) {
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
@@ -1163,6 +1163,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer
* This method may however throw a subclass of {@link BaseServerResponseException}, and processing
@@ -292,7 +295,8 @@ public interface IServerInterceptor {
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
- boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
+ boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
+ throws AuthenticationException;
/**
* This method is called after the server implementation method has been called, but before any attempt to stream the
@@ -364,6 +368,18 @@ public interface IServerInterceptor {
*/
BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException;
+ /**
+ * This method is called after all processing is completed for a request, but only if the
+ * request completes normally (i.e. no exception is thrown).
+ *
+ * Note that this individual interceptors will have this method called in the reverse order from the order in
+ * which the interceptors were registered with the server.
+ *
+ * @param theRequestDetails
+ * The request itself
+ */
+ void processingCompletedNormally(ServletRequestDetails theRequestDetails);
+
public static class ActionRequestDetails {
private final FhirContext myContext;
private final IIdType myId;
@@ -400,20 +416,22 @@ public interface IServerInterceptor {
myResource = theResource;
}
- public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
- this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
- }
-
/**
* Constructor
*
- * @param theRequestDetails The request details to wrap
- * @param theId The ID of the resource being created (note that the ID should have the resource type populated)
+ * @param theRequestDetails
+ * The request details to wrap
+ * @param theId
+ * The ID of the resource being created (note that the ID should have the resource type populated)
*/
public ActionRequestDetails(RequestDetails theRequestDetails, IIdType theId) {
this(theRequestDetails, theId.getResourceType(), theId);
}
+ public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
+ this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
+ }
+
public FhirContext getContext() {
return myContext;
}
@@ -454,14 +472,14 @@ public interface IServerInterceptor {
}
/**
- * Returns the same map which was
+ * Returns the same map which was
*/
public Map
");
b.append("\n");
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java
index 98f62579210..55d6cf74e70 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java
@@ -19,26 +19,12 @@ package ca.uhn.fhir.util;
* limitations under the License.
* #L%
*/
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
+import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLEventWriter;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLResolver;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.*;
import org.apache.commons.lang3.StringEscapeUtils;
import org.codehaus.stax2.XMLOutputFactory2;
@@ -47,6 +33,7 @@ import org.codehaus.stax2.io.EscapingWriterFactory;
import com.ctc.wstx.api.WstxInputProperties;
import com.ctc.wstx.stax.WstxOutputFactory;
+import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.util.jar.DependencyLogFactory;
import ca.uhn.fhir.util.jar.IDependencyLog;
@@ -62,6 +49,7 @@ public class XmlUtil {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class);
private static Throwable ourNextException;
private static volatile XMLOutputFactory ourOutputFactory;
+ private static Boolean ourStaxPresent;
private static final Map VALID_ENTITY_NAMES;
private static final ExtendedEntityReplacingXmlResolver XML_RESOLVER = new ExtendedEntityReplacingXmlResolver();
@@ -1528,8 +1516,8 @@ public class XmlUtil {
// ok
}
- XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
-
+ XMLOutputFactory outputFactory = newOutputFactory();
+
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(outputFactory.getClass());
}
@@ -1601,8 +1589,7 @@ public class XmlUtil {
// ok
}
- XMLInputFactory inputFactory;
- inputFactory = XMLInputFactory.newInstance();
+ XMLInputFactory inputFactory = newInputFactory();
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(inputFactory.getClass());
@@ -1645,7 +1632,6 @@ public class XmlUtil {
return ourInputFactory;
}
-
private static XMLOutputFactory getOrCreateOutputFactory() throws FactoryConfigurationError {
if (ourOutputFactory == null) {
ourOutputFactory = createOutputFactory();
@@ -1661,6 +1647,29 @@ public class XmlUtil {
ourHaveLoggedStaxImplementation = true;
}
+
+ static XMLInputFactory newInputFactory() throws FactoryConfigurationError {
+ XMLInputFactory inputFactory;
+ try {
+ inputFactory = XMLInputFactory.newInstance();
+ throwUnitTestExceptionIfConfiguredToDoSo();
+ } catch (Throwable e) {
+ throw new ConfigurationException("Unable to initialize StAX - XML processing is disabled", e);
+ }
+ return inputFactory;
+ }
+
+ static XMLOutputFactory newOutputFactory() throws FactoryConfigurationError {
+ XMLOutputFactory outputFactory;
+ try {
+ outputFactory = XMLOutputFactory.newInstance();
+ throwUnitTestExceptionIfConfiguredToDoSo();
+ } catch (Throwable e) {
+ throw new ConfigurationException("Unable to initialize StAX - XML processing is disabled", e);
+ }
+ return outputFactory;
+ }
+
/**
* FOR UNIT TESTS ONLY - Throw this exception for the next operation
*/
@@ -1691,6 +1700,26 @@ public class XmlUtil {
}
}
+ /**
+ * This method will return true if a StAX XML parsing library is present
+ * on the classpath
+ */
+ public static boolean isStaxPresent() {
+ Boolean retVal = ourStaxPresent;
+ if (retVal == null) {
+ try {
+ newInputFactory();
+ ourStaxPresent = Boolean.TRUE;
+ retVal = Boolean.TRUE;
+ } catch (ConfigurationException e) {
+ ourLog.info("StAX not detected on classpath, XML processing will be disabled");
+ ourStaxPresent = Boolean.FALSE;
+ retVal = Boolean.FALSE;
+ }
+ }
+ return retVal;
+ }
+
public static class MyEscaper implements EscapingWriterFactory {
@Override
diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java
index edd27fee83b..4f882dfd986 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java
+++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java
@@ -180,7 +180,9 @@ public class App {
try {
String[] args = Arrays.asList(theArgs).subList(1, theArgs.length).toArray(new String[theArgs.length - 1]);
parsedOptions = parser.parse(options, args, true);
-
+ if (parsedOptions.getArgList().isEmpty()==false) {
+ throw new ParseException("Unrecognized argument: " + parsedOptions.getArgList().get(0).toString());
+ }
// Actually execute the command
command.run(parsedOptions);
diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml
index 508e0733b33..f84e913f113 100644
--- a/hapi-fhir-jacoco/pom.xml
+++ b/hapi-fhir-jacoco/pom.xml
@@ -232,6 +232,7 @@
hapi-fhir-structures-dstu3/target/jacoco.exechapi-fhir-jpaserver-base/target/jacoco.exechapi-fhir-client-okhttp/target/jacoco.exec
+ hapi-fhir-android/target/jacoco.exec
diff --git a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.java b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.java
index 12e9af1504b..6d4cee89274 100644
--- a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.java
+++ b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.java
@@ -57,7 +57,7 @@ import ca.uhn.fhir.rest.server.IRestfulServer;
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
*/
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
-@Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
+@Consumes({ MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_XML_NEW })
@Interceptors(JaxRsExceptionInterceptor.class)
public abstract class AbstractJaxRsResourceProvider extends AbstractJaxRsProvider
diff --git a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java
index 2605b3c65ef..623bdbb86d3 100644
--- a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java
+++ b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java
@@ -267,7 +267,7 @@ public class GenericJaxRsClientDstu3Test {
client.create().resource(p).execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient", ourRequestUri);
assertEquals("POST", ourRequestMethod);
@@ -277,7 +277,7 @@ public class GenericJaxRsClientDstu3Test {
client.create().resource(p).execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
String body = ourRequestBodyString;
assertThat(body, containsString(""));
assertThat(body, not(containsString("123")));
@@ -302,7 +302,7 @@ public class GenericJaxRsClientDstu3Test {
client.create().resource(p).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient", ourRequestUri);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo", ourRequestFirstHeaders.get(Constants.HEADER_IF_NONE_EXIST).getValue());
@@ -311,7 +311,7 @@ public class GenericJaxRsClientDstu3Test {
client.create().resource(p).conditionalByUrl("Patient?name=http://foo|bar").execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient", ourRequestUri);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=http%3A//foo%7Cbar", ourRequestFirstHeaders.get(Constants.HEADER_IF_NONE_EXIST).getValue());
@@ -320,7 +320,7 @@ public class GenericJaxRsClientDstu3Test {
client.create().resource(p).conditional().where(Patient.NAME.matches().value("foo")).execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient", ourRequestUri);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo", ourRequestFirstHeaders.get(Constants.HEADER_IF_NONE_EXIST).getValue());
@@ -344,7 +344,7 @@ public class GenericJaxRsClientDstu3Test {
client.create(p);
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient", ourRequestUri);
assertEquals("POST", ourRequestMethod);
@@ -839,7 +839,7 @@ public class GenericJaxRsClientDstu3Test {
//@formatter:on
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
assertEquals(1, resp.getParameter().size());
@@ -875,7 +875,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals("POST", ourRequestMethod);
assertEquals("", (ourRequestBodyString));
@@ -896,7 +896,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals("POST", ourRequestMethod);
assertEquals("",
(ourRequestBodyString));
@@ -918,7 +918,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals("POST", ourRequestMethod);
assertEquals(
"",
@@ -1049,7 +1049,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1064,7 +1064,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1079,7 +1079,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1122,7 +1122,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1137,7 +1137,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1152,7 +1152,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123/$SOMEOPERATION", ourRequestUri);
assertEquals(respString, p.encodeResourceToString(resp));
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertEquals(ourRequestBodyString, reqString);
assertEquals("POST", ourRequestMethod);
@@ -1644,7 +1644,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("name=james", ourRequestBodyString);
assertEquals("application/x-www-form-urlencoded", ourRequestContentType);
- assertEquals(Constants.CT_FHIR_JSON, ourRequestFirstHeaders.get("Accept").getValue());
+ assertEquals(Constants.HEADER_ACCEPT_VALUE_JSON_NON_LEGACY, ourRequestFirstHeaders.get("Accept").getValue());
}
@Test
@@ -1843,7 +1843,7 @@ public class GenericJaxRsClientDstu3Test {
assertEquals("http://localhost:" + ourPort + "/fhir/", ourRequestUri);
assertThat(response, containsString("\"Bundle\""));
- assertEquals("application/json+fhir;charset=UTF-8", ourRequestFirstHeaders.get("Content-Type").getValue());
+ assertEquals("application/fhir+json;charset=UTF-8", ourRequestFirstHeaders.get("Content-Type").getValue());
//@formatter:off
response = client.transaction()
@@ -1853,7 +1853,7 @@ public class GenericJaxRsClientDstu3Test {
//@formatter:on
assertEquals("http://localhost:" + ourPort + "/fhir/", ourRequestUri);
- assertEquals("application/xml+fhir;charset=UTF-8", ourRequestFirstHeaders.get("Content-Type").getValue());
+ assertEquals("application/fhir+xml;charset=UTF-8", ourRequestFirstHeaders.get("Content-Type").getValue());
}
@@ -1913,7 +1913,7 @@ public class GenericJaxRsClientDstu3Test {
client.update().resource(p).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("PUT", ourRequestMethod);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo", ourRequestUri);
@@ -1921,7 +1921,7 @@ public class GenericJaxRsClientDstu3Test {
client.update().resource(p).conditionalByUrl("Patient?name=http://foo|bar").execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("PUT", ourRequestMethod);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=http%3A//foo%7Cbar", ourRequestUri);
@@ -1929,7 +1929,7 @@ public class GenericJaxRsClientDstu3Test {
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditionalByUrl("Patient?name=foo").execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("PUT", ourRequestMethod);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo", ourRequestUri);
@@ -1937,7 +1937,7 @@ public class GenericJaxRsClientDstu3Test {
client.update().resource(p).conditional().where(Patient.NAME.matches().value("foo")).and(Patient.ADDRESS.matches().value("AAA|BBB")).execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("PUT", ourRequestMethod);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo&address=AAA%5C%7CBBB", ourRequestUri);
@@ -1945,7 +1945,7 @@ public class GenericJaxRsClientDstu3Test {
client.update().resource(ourCtx.newXmlParser().encodeResourceToString(p)).conditional().where(Patient.NAME.matches().value("foo")).and(Patient.ADDRESS.matches().value("AAA|BBB")).execute();
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("PUT", ourRequestMethod);
assertEquals("http://localhost:" + ourPort + "/fhir/Patient?name=foo&address=AAA%5C%7CBBB", ourRequestUri);
@@ -1968,7 +1968,7 @@ public class GenericJaxRsClientDstu3Test {
client.update(new IdType("Patient/123").getValue(), p);
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123", ourRequestUri);
assertEquals("PUT", ourRequestMethod);
@@ -1976,7 +1976,7 @@ public class GenericJaxRsClientDstu3Test {
client.update("123", p);
assertEquals(1, ourRequestHeaders.get(Constants.HEADER_CONTENT_TYPE).size());
- assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
+ assertEquals(EncodingEnum.XML.getResourceContentTypeNonLegacy() + Constants.HEADER_SUFFIX_CT_UTF_8, ourRequestFirstHeaders.get(Constants.HEADER_CONTENT_TYPE).getValue().replace(";char", "; char"));
assertThat(ourRequestBodyString, containsString(""));
assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123", ourRequestUri);
assertEquals("PUT", ourRequestMethod);
diff --git a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/server/test/TestJaxRsMockPatientRestProviderDstu3.java b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/server/test/TestJaxRsMockPatientRestProviderDstu3.java
index 2e0e1e07031..c36a5a1d6bf 100644
--- a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/server/test/TestJaxRsMockPatientRestProviderDstu3.java
+++ b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/server/test/TestJaxRsMockPatientRestProviderDstu3.java
@@ -48,7 +48,7 @@ import ca.uhn.fhir.rest.server.IPagingProvider;
*/
@Path(TestJaxRsMockPatientRestProviderDstu3.PATH)
@Stateless
-@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
+@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_XML_NEW })
@Interceptors(JaxRsExceptionInterceptor.class)
public class TestJaxRsMockPatientRestProviderDstu3 extends AbstractJaxRsResourceProvider {
diff --git a/hapi-fhir-jpaserver-base/.gitignore b/hapi-fhir-jpaserver-base/.gitignore
index ec1f25fea96..bc3ff7634b3 100644
--- a/hapi-fhir-jpaserver-base/.gitignore
+++ b/hapi-fhir-jpaserver-base/.gitignore
@@ -1,4 +1,5 @@
ca.uhn.fhir.jpa.entity.ResourceTable/
+ca.*/
target/
/bin
nohup.out
diff --git a/hapi-fhir-jpaserver-base/ca.uhn.fhir.jpa.entity.TermConcept/segments_1 b/hapi-fhir-jpaserver-base/ca.uhn.fhir.jpa.entity.TermConcept/segments_1
deleted file mode 100644
index c6a50652363..00000000000
Binary files a/hapi-fhir-jpaserver-base/ca.uhn.fhir.jpa.entity.TermConcept/segments_1 and /dev/null differ
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index f4dafd1a4e7..c9352d8fdcc 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -99,7 +99,18 @@
org.jsciencejscience
-
+
+
+
+ net.riotopsys
+ json_patch
+
+
+ com.github.dnault
+ xml-patch
+ 0.3.0
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir
+ 2.1-SNAPSHOT
+ ../../pom.xml
+
+
+ ca.uhn.hapi.fhir.example
+ hapi-fhir-jpaserver-example-postgres
+ war
+
+ HAPI FHIR JPA Server - Example (Postgres)
+
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-base
+ 2.1-SNAPSHOT
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-jpaserver-base
+ 2.1-SNAPSHOT
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-testpage-overlay
+ 2.1-SNAPSHOT
+ war
+ provided
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-testpage-overlay
+ 2.1-SNAPSHOT
+ classes
+ provided
+
+
+
+
+ ch.qos.logback
+ logback-classic
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
+
+ org.thymeleaf
+ thymeleaf
+
+
+
+
+ org.ebaysf.web
+ cors-filter
+
+
+ servlet-api
+ javax.servlet
+
+
+
+
+
+
+ org.springframework
+ spring-web
+
+
+
+
+ org.apache.commons
+ commons-dbcp2
+
+
+
+
+ org.apache.derby
+ derby
+
+
+ org.apache.derby
+ derbynet
+
+
+ org.apache.derby
+ derbyclient
+
+
+
+
+ org.eclipse.jetty
+ jetty-servlets
+ test
+
+
+ org.eclipse.jetty
+ jetty-servlet
+ test
+
+
+ org.eclipse.jetty
+ jetty-server
+ test
+
+
+ org.eclipse.jetty
+ jetty-util
+ test
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ test
+
+
+ com.phloc
+ phloc-schematron
+
+
+
+ org.postgresql
+ postgresql
+ 9.4.1210.jre7
+
+
+
+
+
+
+
+ hapi-fhir-jpaserver-example
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-maven-plugin
+
+
+ /hapi-fhir-jpaserver-example
+ true
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.6
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+ ${maven.build.timestamp}
+
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-testpage-overlay
+
+
+ src/main/webapp/WEB-INF/web.xml
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+ true
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
+
+ a
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/readme.intellij.txt b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/readme.intellij.txt
new file mode 100644
index 00000000000..049d5d341a5
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/readme.intellij.txt
@@ -0,0 +1,31 @@
+Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ
+
+Install Tomcat.
+
+Make sure you have Tomcat set up in IntelliJ.
+File->Settings->Build, Execution, Deployment->Application Servers
+Click +
+Select "Tomcat Server"
+Enter the path to your tomcat deployment for both Tomcat Home (IntelliJ will fill in base directory for you)
+
+Add a Run Configuration for running hapi-fhir-jpaserver-example under Tomcat
+Run->Edit Configurations
+Click the green +
+Select Tomcat Server, Local
+Change the name to whatever you wish
+Uncheck the "After launch" checkbox
+On the "Deployment" tab, click the green +
+Select "Artifact"
+Select "hapi-fhir-jpaserver-example:war"
+In "Application context" type /hapi
+
+Run the configuration
+You should now have an "Application Servers" in the list of windows at the bottom.
+Click it.
+Select your server, and click the green triangle (or the bug if you want to debug)
+Wait for the console output to stop
+
+Point your browser (or fiddler, or what have you) to
+http://localhost:8080/hapi/base/Patient
+
+You should get an empty bundle back.
\ No newline at end of file
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java
new file mode 100644
index 00000000000..4a19ef39012
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java
@@ -0,0 +1,129 @@
+package ca.uhn.fhir.jpa.demo;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.commons.lang3.time.DateUtils;
+import org.hibernate.jpa.HibernatePersistenceProvider;
+import org.springframework.beans.factory.annotation.Autowire;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
+import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3;
+import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
+import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
+import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
+
+/**
+ * This class isn't used by default by the example, but
+ * you can use it as a config if you want to support DSTU3
+ * instead of DSTU2 in your server.
+ *
+ * See https://github.com/jamesagnew/hapi-fhir/issues/278
+ */
+@Configuration
+@EnableTransactionManagement()
+public class FhirServerConfig extends BaseJavaConfigDstu3 {
+
+ /**
+ * Configure FHIR properties around the the JPA server via this bean
+ */
+ @Bean()
+ public DaoConfig daoConfig() {
+ DaoConfig retVal = new DaoConfig();
+ retVal.setSubscriptionEnabled(true);
+ retVal.setSubscriptionPollDelay(5000);
+ retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
+ retVal.setAllowMultipleDelete(true);
+ return retVal;
+ }
+
+ /**
+ * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a
+ * directory called "jpaserver_derby_files".
+ *
+ * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource.
+ */
+ @Bean(destroyMethod = "close")
+ public DataSource dataSource() {
+ BasicDataSource retVal = new BasicDataSource();
+ retVal.setDriver(new org.postgresql.Driver());
+ retVal.setUrl("jdbc:postgresql://localhost:5432/hapi");
+ retVal.setUsername("hapi");
+ retVal.setPassword("mysecretpassword");
+ return retVal;
+ }
+
+ @Bean()
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ LocalContainerEntityManagerFactoryBean retVal = new LocalContainerEntityManagerFactoryBean();
+ retVal.setPersistenceUnitName("HAPI_PU");
+ retVal.setDataSource(dataSource());
+ retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity");
+ retVal.setPersistenceProvider(new HibernatePersistenceProvider());
+ retVal.setJpaProperties(jpaProperties());
+ return retVal;
+ }
+
+ private Properties jpaProperties() {
+ Properties extraProperties = new Properties();
+ extraProperties.put("hibernate.dialect", org.hibernate.dialect.PostgreSQL94Dialect.class.getName());
+ extraProperties.put("hibernate.format_sql", "true");
+ extraProperties.put("hibernate.show_sql", "false");
+ extraProperties.put("hibernate.hbm2ddl.auto", "update");
+ extraProperties.put("hibernate.jdbc.batch_size", "20");
+ extraProperties.put("hibernate.cache.use_query_cache", "false");
+ extraProperties.put("hibernate.cache.use_second_level_cache", "false");
+ extraProperties.put("hibernate.cache.use_structured_entries", "false");
+ extraProperties.put("hibernate.cache.use_minimal_puts", "false");
+ extraProperties.put("hibernate.search.default.directory_provider", "filesystem");
+ extraProperties.put("hibernate.search.default.indexBase", "target/lucenefiles");
+ extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT");
+// extraProperties.put("hibernate.search.default.worker.execution", "async");
+ return extraProperties;
+ }
+
+ /**
+ * Do some fancy logging to create a nice access log that has details about each incoming request.
+ */
+ public IServerInterceptor loggingInterceptor() {
+ LoggingInterceptor retVal = new LoggingInterceptor();
+ retVal.setLoggerName("fhirtest.access");
+ retVal.setMessageFormat(
+ "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]");
+ retVal.setLogExceptions(true);
+ retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}");
+ return retVal;
+ }
+
+ /**
+ * This interceptor adds some pretty syntax highlighting in responses when a browser is detected
+ */
+ @Bean(autowire = Autowire.BY_TYPE)
+ public IServerInterceptor responseHighlighterInterceptor() {
+ ResponseHighlighterInterceptor retVal = new ResponseHighlighterInterceptor();
+ return retVal;
+ }
+
+ @Bean(autowire = Autowire.BY_TYPE)
+ public IServerInterceptor subscriptionSecurityInterceptor() {
+ SubscriptionsRequireManualActivationInterceptorDstu3 retVal = new SubscriptionsRequireManualActivationInterceptorDstu3();
+ return retVal;
+ }
+
+ @Bean()
+ public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
+ JpaTransactionManager retVal = new JpaTransactionManager();
+ retVal.setEntityManagerFactory(entityManagerFactory);
+ return retVal;
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java
new file mode 100644
index 00000000000..22c9e4d1067
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java
@@ -0,0 +1,51 @@
+package ca.uhn.fhir.jpa.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+import ca.uhn.fhir.context.FhirVersionEnum;
+import ca.uhn.fhir.to.FhirTesterMvcConfig;
+import ca.uhn.fhir.to.TesterConfig;
+
+//@formatter:off
+/**
+ * This spring config file configures the web testing module. It serves two
+ * purposes:
+ * 1. It imports FhirTesterMvcConfig, which is the spring config for the
+ * tester itself
+ * 2. It tells the tester which server(s) to talk to, via the testerConfig()
+ * method below
+ */
+@Configuration
+@Import(FhirTesterMvcConfig.class)
+public class FhirTesterConfig {
+
+ /**
+ * This bean tells the testing webpage which servers it should configure itself
+ * to communicate with. In this example we configure it to talk to the local
+ * server, as well as one public server. If you are creating a project to
+ * deploy somewhere else, you might choose to only put your own server's
+ * address here.
+ *
+ * Note the use of the ${serverBase} variable below. This will be replaced with
+ * the base URL as reported by the server itself. Often for a simple Tomcat
+ * (or other container) installation, this will end up being something
+ * like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are
+ * deploying your server to a place with a fully qualified domain name,
+ * you might want to use that instead of using the variable.
+ */
+ @Bean
+ public TesterConfig testerConfig() {
+ TesterConfig retVal = new TesterConfig();
+ retVal
+ .addServer()
+ .withId("home")
+ .withFhirVersion(FhirVersionEnum.DSTU3)
+ .withBaseUrl("${serverBase}/baseDstu3")
+ .withName("Local Tester");
+ return retVal;
+ }
+
+}
+//@formatter:on
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java
new file mode 100644
index 00000000000..8b51ff4bc54
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java
@@ -0,0 +1,124 @@
+package ca.uhn.fhir.jpa.demo;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+import org.hl7.fhir.dstu3.model.Meta;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
+import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
+import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
+import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
+import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
+import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
+import ca.uhn.fhir.rest.server.ETagSupportEnum;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+import ca.uhn.fhir.rest.server.IResourceProvider;
+import ca.uhn.fhir.rest.server.RestfulServer;
+import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
+
+public class JpaServerDemo extends RestfulServer {
+
+ private static final long serialVersionUID = 1L;
+
+ private WebApplicationContext myAppCtx;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void initialize() throws ServletException {
+ super.initialize();
+
+ /*
+ * We want to support FHIR DSTU3 format. This means that the server
+ * will use the DSTU3 bundle format and other DSTU3 encoding changes.
+ *
+ * If you want to use DSTU1 instead, change the following line, and change the 3 occurrences of dstu2 in web.xml to dstu1
+ */
+ setFhirContext(FhirContext.forDstu3());
+
+ // Get the spring context from the web container (it's declared in web.xml)
+ myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext();
+
+ /*
+ * The BaseJavaConfigDstu3.java class is a spring configuration
+ * file which is automatically generated as a part of hapi-fhir-jpaserver-base and
+ * contains bean definitions for a resource provider for each resource type
+ */
+ List beans = myAppCtx.getBean("myResourceProvidersDstu3", List.class);
+ setResourceProviders(beans);
+
+ /*
+ * The system provider implements non-resource-type methods, such as
+ * transaction, and global history.
+ */
+ setPlainProviders(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class));
+
+ /*
+ * The conformance provider exports the supported resources, search parameters, etc for
+ * this server. The JPA version adds resource counts to the exported statement, so it
+ * is a nice addition.
+ */
+ IFhirSystemDao systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
+ JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class));
+ confProvider.setImplementationDescription("Example Server");
+ setServerConformanceProvider(confProvider);
+
+ /*
+ * Enable ETag Support (this is already the default)
+ */
+ setETagSupport(ETagSupportEnum.ENABLED);
+
+ /*
+ * This server tries to dynamically generate narratives
+ */
+ FhirContext ctx = getFhirContext();
+ ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
+
+ /*
+ * Default to JSON and pretty printing
+ */
+ setDefaultPrettyPrint(true);
+ setDefaultResponseEncoding(EncodingEnum.JSON);
+
+ /*
+ * -- New in HAPI FHIR 1.5 --
+ * This configures the server to page search results to and from
+ * the database, instead of only paging them to memory. This may mean
+ * a performance hit when performing searches that return lots of results,
+ * but makes the server much more scalable.
+ */
+ setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class));
+
+ /*
+ * Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
+ */
+ Collection interceptorBeans = myAppCtx.getBeansOfType(IServerInterceptor.class).values();
+ for (IServerInterceptor interceptor : interceptorBeans) {
+ this.registerInterceptor(interceptor);
+ }
+
+ /*
+ * If you are hosting this server at a specific DNS name, the server will try to
+ * figure out the FHIR base URL based on what the web container tells it, but
+ * this doesn't always work. If you are setting links in your search bundles that
+ * just refer to "localhost", you might want to use a server address strategy:
+ */
+ //setServerAddressStrategy(new HardcodedServerAddressStrategy("http://mydomain.com/fhir/baseDstu2"));
+
+ /*
+ * If you are using DSTU3+, you may want to add a terminology uploader, which allows
+ * uploading of external terminologies such as Snomed CT. Note that this uploader
+ * does not have any security attached (any anonymous user may use it by default)
+ * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
+ * with this feature.
+ */
+ registerProvider(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class));
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/resources/logback.xml b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/resources/logback.xml
new file mode 100644
index 00000000000..ffec8d30c06
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ INFO
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/about.html b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/about.html
new file mode 100644
index 00000000000..d552027e956
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/about.html
@@ -0,0 +1,67 @@
+
+
+
+ About This Server
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/tmpl-footer.html b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/tmpl-footer.html
new file mode 100644
index 00000000000..bf18c498a78
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/templates/tmpl-footer.html
@@ -0,0 +1,16 @@
+
+
+
+ This is the home for the FHIR test server operated by
+ University Health Network. This server
+ (and the testing application you are currently using to access it)
+ is entirely built using
+ HAPI-FHIR,
+ a 100% open-source Java implementation of the
+ FHIR specification.
+
+ Access a
+ different server
+ (use the Server menu at the top of the page to see a list of public FHIR servers)
+
+
+
+
+
+ You are accessing the public FHIR server
+ . This server is hosted elsewhere on the internet
+ but is being accessed using the HAPI client implementation.
+
+
+
+
+
+ This is not a production server!
+
+ Do not store any information here that contains personal health information
+ or any other confidential information. This server will be regularly purged
+ and reloaded with fixed test data.
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/web.xml b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000000..882a7be5652
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,108 @@
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+
+ contextConfigLocation
+
+ ca.uhn.fhir.jpa.demo.FhirServerConfig
+
+
+
+
+
+
+ spring
+ org.springframework.web.servlet.DispatcherServlet
+
+ contextClass
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+ contextConfigLocation
+ ca.uhn.fhir.jpa.demo.FhirTesterConfig
+
+ 2
+
+
+
+ fhirServlet
+ ca.uhn.fhir.jpa.demo.JpaServerDemo
+
+ ImplementationDescription
+ FHIR JPA Server
+
+
+ FhirVersion
+ DSTU2
+
+ 1
+
+
+
+ fhirServlet
+ /baseDstu3/*
+
+
+
+ spring
+ /
+
+
+
+
+
+
+ CORS Filter
+ org.ebaysf.web.cors.CORSFilter
+
+ A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.
+ cors.allowed.origins
+ *
+
+
+ A comma separated list of HTTP verbs, using which a CORS request can be made.
+ cors.allowed.methods
+ GET,POST,PUT,DELETE,OPTIONS
+
+
+ A comma separated list of allowed headers when making a non simple CORS request.
+ cors.allowed.headers
+ X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers
+
+
+ A comma separated list non-standard response headers that will be exposed to XHR2 object.
+ cors.exposed.headers
+ Location,Content-Location
+
+
+ A flag that suggests if CORS is supported with cookies
+ cors.support.credentials
+ true
+
+
+ A flag to control logging
+ cors.logging.enabled
+ true
+
+
+ Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.
+ cors.preflight.maxage
+ 300
+
+
+
+ CORS Filter
+ /*
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/javaee_6.xsd b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/javaee_6.xsd
new file mode 100644
index 00000000000..9fb587749ce
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/javaee_6.xsd
@@ -0,0 +1,2419 @@
+
+
+
+
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the
+ GNU General Public License Version 2 only ("GPL") or the Common
+ Development and Distribution License("CDDL") (collectively, the
+ "License"). You may not use this file except in compliance with
+ the License. You can obtain a copy of the License at
+ https://glassfish.dev.java.net/public/CDDL+GPL.html or
+ glassfish/bootstrap/legal/LICENSE.txt. See the License for the
+ specific language governing permissions and limitations under the
+ License.
+
+ When distributing the software, include this License Header
+ Notice in each file and include the License file at
+ glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
+ particular file as subject to the "Classpath" exception as
+ provided by Sun in the GPL Version 2 section of the License file
+ that accompanied this code. If applicable, add the following
+ below the License Header, with the fields enclosed by brackets []
+ replaced by your own identifying information:
+ "Portions Copyrighted [year] [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the
+ CDDL or only the GPL Version 2, indicate your decision by adding
+ "[Contributor] elects to include this software in this
+ distribution under the [CDDL or GPL Version 2] license." If you
+ don't indicate a single choice of license, a recipient has the
+ option to distribute your version of this file under either the
+ CDDL, the GPL Version 2 or to extend the choice of license to its
+ licensees as provided above. However, if you add GPL Version 2
+ code and therefore, elected the GPL Version 2 license, then the
+ option applies only if the new code is made subject to such
+ option by the copyright holder.
+
+
+
+
+
+
+
+ The following definitions that appear in the common
+ shareable schema(s) of Java EE deployment descriptors should be
+ interpreted with respect to the context they are included:
+
+ Deployment Component may indicate one of the following:
+ java ee application;
+ application client;
+ web application;
+ enterprise bean;
+ resource adapter;
+
+ Deployment File may indicate one of the following:
+ ear file;
+ war file;
+ jar file;
+ rar file;
+
+
+
+
+
+
+
+
+
+
+ This group keeps the usage of the contained description related
+ elements consistent across Java EE deployment descriptors.
+
+ All elements may occur multiple times with different languages,
+ to support localization of the content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This group keeps the usage of the contained JNDI environment
+ reference elements consistent across Java EE deployment descriptors.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This group collects elements that are common to most
+ JNDI resource elements.
+
+
+
+
+
+
+
+
+
+ The JNDI name to be looked up to resolve a resource reference.
+
+
+
+
+
+
+
+
+
+
+
+ This group collects elements that are common to all the
+ JNDI resource elements. It does not include the lookup-name
+ element, that is only applicable to some resource elements.
+
+
+
+
+
+
+
+
+ A product specific name that this resource should be
+ mapped to. The name of this resource, as defined by the
+ resource's name element or defaulted, is a name that is
+ local to the application component using the resource.
+ (It's a name in the JNDI java:comp/env namespace.) Many
+ application servers provide a way to map these local
+ names to names of resources known to the application
+ server. This mapped name is often a global JNDI name,
+ but may be a name of any form.
+
+ Application servers are not required to support any
+ particular form or type of mapped name, nor the ability
+ to use mapped names. The mapped name is
+ product-dependent and often installation-dependent. No
+ use of a mapped name is portable.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Configuration of a DataSource.
+
+
+
+
+
+
+
+
+ Description of this DataSource.
+
+
+
+
+
+
+
+
+ The name element specifies the JNDI name of the
+ data source being defined.
+
+
+
+
+
+
+
+
+ DataSource, XADataSource or ConnectionPoolDataSource
+ implementation class.
+
+
+
+
+
+
+
+
+ Database server name.
+
+
+
+
+
+
+
+
+ Port number where a server is listening for requests.
+
+
+
+
+
+
+
+
+ Name of a database on a server.
+
+
+
+
+
+
+
+ url property is specified
+ along with other standard DataSource properties
+ such as serverName, databaseName
+ and portNumber, the more specific properties will
+ take precedence and url will be ignored.
+
+ ]]>
+
+
+
+
+
+
+
+ User name to use for connection authentication.
+
+
+
+
+
+
+
+
+ Password to use for connection authentication.
+
+
+
+
+
+
+
+
+ JDBC DataSource property. This may be a vendor-specific
+ property or a less commonly used DataSource property.
+
+
+
+
+
+
+
+
+ Sets the maximum time in seconds that this data source
+ will wait while attempting to connect to a database.
+
+
+
+
+
+
+
+
+ Set to false if connections should not participate in
+ transactions.
+
+
+
+
+
+
+
+
+ Isolation level for connections.
+
+
+
+
+
+
+
+
+ Number of connections that should be created when a
+ connection pool is initialized.
+
+
+
+
+
+
+
+
+ Maximum number of connections that should be concurrently
+ allocated for a connection pool.
+
+
+
+
+
+
+
+
+ Minimum number of connections that should be concurrently
+ allocated for a connection pool.
+
+
+
+
+
+
+
+
+ The number of seconds that a physical connection should
+ remain unused in the pool before the connection is
+ closed for a connection pool.
+
+
+
+
+
+
+
+
+ The total number of statements that a connection pool
+ should keep open.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The description type is used by a description element to
+ provide text describing the parent element. The elements
+ that use this type should include any information that the
+ Deployment Component's Deployment File file producer wants
+ to provide to the consumer of the Deployment Component's
+ Deployment File (i.e., to the Deployer). Typically, the
+ tools used by such a Deployment File consumer will display
+ the description when processing the parent element that
+ contains the description.
+
+ The lang attribute defines the language that the
+ description is provided in. The default value is "en" (English).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type defines a dewey decimal that is used
+ to describe versions of documents.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Employee Self Service
+
+
+ The value of the xml:lang attribute is "en" (English) by default.
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EmployeeRecord
+
+ ../products/product.jar#ProductEJB
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The ejb-local-refType is used by ejb-local-ref elements for
+ the declaration of a reference to an enterprise bean's local
+ home or to the local business interface of a 3.0 bean.
+ The declaration consists of:
+
+ - an optional description
+ - the EJB reference name used in the code of the Deployment
+ Component that's referencing the enterprise bean.
+ - the optional expected type of the referenced enterprise bean
+ - the optional expected local interface of the referenced
+ enterprise bean or the local business interface of the
+ referenced enterprise bean.
+ - the optional expected local home interface of the referenced
+ enterprise bean. Not applicable if this ejb-local-ref refers
+ to the local business interface of a 3.0 bean.
+ - optional ejb-link information, used to specify the
+ referenced enterprise bean
+ - optional elements to define injection of the named enterprise
+ bean into a component field or property.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ejb/Payroll
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The ejb-refType is used by ejb-ref elements for the
+ declaration of a reference to an enterprise bean's home or
+ to the remote business interface of a 3.0 bean.
+ The declaration consists of:
+
+ - an optional description
+ - the EJB reference name used in the code of
+ the Deployment Component that's referencing the enterprise
+ bean.
+ - the optional expected type of the referenced enterprise bean
+ - the optional remote interface of the referenced enterprise bean
+ or the remote business interface of the referenced enterprise
+ bean
+ - the optional expected home interface of the referenced
+ enterprise bean. Not applicable if this ejb-ref
+ refers to the remote business interface of a 3.0 bean.
+ - optional ejb-link information, used to specify the
+ referenced enterprise bean
+ - optional elements to define injection of the named enterprise
+ bean into a component field or property
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The ejb-ref-typeType contains the expected type of the
+ referenced enterprise bean.
+
+ The ejb-ref-type designates a value
+ that must be one of the following:
+
+ Entity
+ Session
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type is used to designate an empty
+ element when used.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The env-entryType is used to declare an application's
+ environment entry. The declaration consists of an optional
+ description, the name of the environment entry, a type
+ (optional if the value is injected, otherwise required), and
+ an optional value.
+
+ It also includes optional elements to define injection of
+ the named resource into fields or JavaBeans properties.
+
+ If a value is not specified and injection is requested,
+ no injection will occur and no entry of the specified name
+ will be created. This allows an initial value to be
+ specified in the source code without being incorrectly
+ changed when no override has been specified.
+
+ If a value is not specified and no injection is requested,
+ a value must be supplied during deployment.
+
+ This type is used by env-entry elements.
+
+
+
+
+
+
+
+
+ minAmount
+
+ ]]>
+
+
+
+
+
+
+ java.lang.Integer
+
+ ]]>
+
+
+
+
+
+
+ 100.00
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ java.lang.Boolean
+ java.lang.Class
+ com.example.Color
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The elements that use this type designate the name of a
+ Java class or interface. The name is in the form of a
+ "binary name", as defined in the JLS. This is the form
+ of name used in Class.forName(). Tools that need the
+ canonical name (the name used in source code) will need
+ to convert this binary name to the canonical name.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type defines four different values which can designate
+ boolean values. This includes values yes and no which are
+ not designated by xsd:boolean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The icon type contains small-icon and large-icon elements
+ that specify the file names for small and large GIF, JPEG,
+ or PNG icon images used to represent the parent element in a
+ GUI tool.
+
+ The xml:lang attribute defines the language that the
+ icon file names are provided in. Its value is "en" (English)
+ by default.
+
+
+
+
+
+
+
+ employee-service-icon16x16.jpg
+
+ ]]>
+
+
+
+
+
+
+ employee-service-icon32x32.jpg
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An injection target specifies a class and a name within
+ that class into which a resource should be injected.
+
+ The injection target class specifies the fully qualified
+ class name that is the target of the injection. The
+ Java EE specifications describe which classes can be an
+ injection target.
+
+ The injection target name specifies the target within
+ the specified class. The target is first looked for as a
+ JavaBeans property name. If not found, the target is
+ looked for as a field name.
+
+ The specified resource will be injected into the target
+ during initialization of the class by either calling the
+ set method for the target property or by setting a value
+ into the named field.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The following transaction isolation levels are allowed
+ (see documentation for the java.sql.Connection interface):
+ TRANSACTION_READ_UNCOMMITTED
+ TRANSACTION_READ_COMMITTED
+ TRANSACTION_REPEATABLE_READ
+ TRANSACTION_SERIALIZABLE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The java-identifierType defines a Java identifier.
+ The users of this type should further verify that
+ the content does not contain Java reserved keywords.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is a generic type that designates a Java primitive
+ type or a fully qualified name of a Java interface/type,
+ or an array of such types.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+ Example:
+
+ jdbc:mysql://localhost:3307/testdb
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The jndi-nameType type designates a JNDI name in the
+ Deployment Component's environment and is relative to the
+ java:comp/env context. A JNDI name must be unique within the
+ Deployment Component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.aardvark.payroll.PayrollHome
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The lifecycle-callback type specifies a method on a
+ class to be called when a lifecycle event occurs.
+ Note that each class may have only one lifecycle callback
+ method for any given event and that the method may not
+ be overloaded.
+
+ If the lifefycle-callback-class element is missing then
+ the class defining the callback is assumed to be the
+ component class in scope at the place in the descriptor
+ in which the callback definition appears.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The listenerType indicates the deployment properties for a web
+ application listener bean.
+
+
+
+
+
+
+
+
+
+ The listener-class element declares a class in the
+ application must be registered as a web
+ application listener bean. The value is the fully
+ qualified classname of the listener class.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The localType defines the fully-qualified name of an
+ enterprise bean's local interface.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The local-homeType defines the fully-qualified
+ name of an enterprise bean's local home interface.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type is a general type that can be used to declare
+ parameter/value lists.
+
+
+
+
+
+
+
+
+
+ The param-name element contains the name of a
+ parameter.
+
+
+
+
+
+
+
+
+ The param-value element contains the value of a
+ parameter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The elements that use this type designate either a relative
+ path or an absolute path starting with a "/".
+
+ In elements that specify a pathname to a file within the
+ same Deployment File, relative filenames (i.e., those not
+ starting with "/") are considered relative to the root of
+ the Deployment File's namespace. Absolute filenames (i.e.,
+ those starting with "/") also specify names in the root of
+ the Deployment File's namespace. In general, relative names
+ are preferred. The exception is .war files where absolute
+ names are preferred for consistency with the Servlet API.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ myPersistenceContext
+
+
+
+
+ myPersistenceContext
+
+ PersistenceUnit1
+
+ Extended
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The persistence-context-ref-name element specifies
+ the name of a persistence context reference; its
+ value is the environment entry name used in
+ Deployment Component code. The name is a JNDI name
+ relative to the java:comp/env context.
+
+
+
+
+
+
+
+
+ The Application Assembler(or BeanProvider) may use the
+ following syntax to avoid the need to rename persistence
+ units to have unique names within a Java EE application.
+
+ The Application Assembler specifies the pathname of the
+ root of the persistence.xml file for the referenced
+ persistence unit and appends the name of the persistence
+ unit separated from the pathname by #. The pathname is
+ relative to the referencing application component jar file.
+ In this manner, multiple persistence units with the same
+ persistence unit name may be uniquely identified when the
+ Application Assembler cannot change persistence unit names.
+
+
+
+
+
+
+
+
+
+ Used to specify properties for the container or persistence
+ provider. Vendor-specific properties may be included in
+ the set of properties. Properties that are not recognized
+ by a vendor must be ignored. Entries that make use of the
+ namespace javax.persistence and its subnamespaces must not
+ be used for vendor-specific properties. The namespace
+ javax.persistence is reserved for use by the specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The persistence-context-typeType specifies the transactional
+ nature of a persistence context reference.
+
+ The value of the persistence-context-type element must be
+ one of the following:
+ Transaction
+ Extended
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Specifies a name/value pair.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ myPersistenceUnit
+
+
+
+
+ myPersistenceUnit
+
+ PersistenceUnit1
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The persistence-unit-ref-name element specifies
+ the name of a persistence unit reference; its
+ value is the environment entry name used in
+ Deployment Component code. The name is a JNDI name
+ relative to the java:comp/env context.
+
+
+
+
+
+
+
+
+ The Application Assembler(or BeanProvider) may use the
+ following syntax to avoid the need to rename persistence
+ units to have unique names within a Java EE application.
+
+ The Application Assembler specifies the pathname of the
+ root of the persistence.xml file for the referenced
+ persistence unit and appends the name of the persistence
+ unit separated from the pathname by #. The pathname is
+ relative to the referencing application component jar file.
+ In this manner, multiple persistence units with the same
+ persistence unit name may be uniquely identified when the
+ Application Assembler cannot change persistence unit names.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.wombat.empl.EmployeeService
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jms/StockQueue
+
+ javax.jms.Queue
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The resource-env-ref-name element specifies the name
+ of a resource environment reference; its value is
+ the environment entry name used in
+ the Deployment Component code. The name is a JNDI
+ name relative to the java:comp/env context and must
+ be unique within a Deployment Component.
+
+
+
+
+
+
+
+
+ The resource-env-ref-type element specifies the type
+ of a resource environment reference. It is the
+ fully qualified name of a Java language class or
+ interface.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc/EmployeeAppDB
+ javax.sql.DataSource
+ Container
+ Shareable
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The res-ref-name element specifies the name of a
+ resource manager connection factory reference.
+ The name is a JNDI name relative to the
+ java:comp/env context.
+ The name must be unique within a Deployment File.
+
+
+
+
+
+
+
+
+ The res-type element specifies the type of the data
+ source. The type is specified by the fully qualified
+ Java language class or interface
+ expected to be implemented by the data source.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The res-authType specifies whether the Deployment Component
+ code signs on programmatically to the resource manager, or
+ whether the Container will sign on to the resource manager
+ on behalf of the Deployment Component. In the latter case,
+ the Container uses information that is supplied by the
+ Deployer.
+
+ The value must be one of the two following:
+
+ Application
+ Container
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The res-sharing-scope type specifies whether connections
+ obtained through the given resource manager connection
+ factory reference can be shared. The value, if specified,
+ must be one of the two following:
+
+ Shareable
+ Unshareable
+
+ The default value is Shareable.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The run-asType specifies the run-as identity to be
+ used for the execution of a component. It contains an
+ optional description, and the name of a security role.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The role-nameType designates the name of a security role.
+
+ The name must conform to the lexical rules for a token.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This role includes all employees who are authorized
+ to access the employee service application.
+
+ employee
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The security-role-refType contains the declaration of a
+ security role reference in a component's or a
+ Deployment Component's code. The declaration consists of an
+ optional description, the security role name used in the
+ code, and an optional link to a security role. If the
+ security role is not specified, the Deployer must choose an
+ appropriate security role.
+
+
+
+
+
+
+
+
+
+ The value of the role-name element must be the String used
+ as the parameter to the
+ EJBContext.isCallerInRole(String roleName) method or the
+ HttpServletRequest.isUserInRole(String role) method.
+
+
+
+
+
+
+
+
+ The role-link element is a reference to a defined
+ security role. The role-link element must contain
+ the name of one of the security roles defined in the
+ security-role elements.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:QName.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:boolean.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:NMTOKEN.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:anyURI.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:integer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:positiveInteger.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:nonNegativeInteger.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type adds an "id" attribute to xsd:string.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is a special string datatype that is defined by Java EE as
+ a base type for defining collapsed strings. When schemas
+ require trailing/leading space elimination as well as
+ collapsing the existing whitespace, this base type may be
+ used.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This simple type designates a boolean with only two
+ permissible values
+
+ - true
+ - false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The url-patternType contains the url pattern of the mapping.
+ It must follow the rules specified in Section 11.2 of the
+ Servlet API Specification. This pattern is assumed to be in
+ URL-decoded form and must not contain CR(#xD) or LF(#xA).
+ If it contains those characters, the container must inform
+ the developer with a descriptive error message.
+ The container must preserve all characters including whitespaces.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CorporateStocks
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The message-destination-name element specifies a
+ name for a message destination. This name must be
+ unique among the names of message destinations
+ within the Deployment File.
+
+
+
+
+
+
+
+
+ A product specific name that this message destination
+ should be mapped to. Each message-destination-ref
+ element that references this message destination will
+ define a name in the namespace of the referencing
+ component or in one of the other predefined namespaces.
+ Many application servers provide a way to map these
+ local names to names of resources known to the
+ application server. This mapped name is often a global
+ JNDI name, but may be a name of any form. Each of the
+ local names should be mapped to this same global name.
+
+ Application servers are not required to support any
+ particular form or type of mapped name, nor the ability
+ to use mapped names. The mapped name is
+ product-dependent and often installation-dependent. No
+ use of a mapped name is portable.
+
+
+
+
+
+
+
+
+ The JNDI name to be looked up to resolve the message destination.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jms/StockQueue
+
+ javax.jms.Queue
+
+ Consumes
+
+ CorporateStocks
+
+
+
+ ]]>
+
+
+
+
+
+
+
+
+ The message-destination-ref-name element specifies
+ the name of a message destination reference; its
+ value is the environment entry name used in
+ Deployment Component code.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The message-destination-usageType specifies the use of the
+ message destination indicated by the reference. The value
+ indicates whether messages are consumed from the message
+ destination, produced for the destination, or both. The
+ Assembler makes use of this information in linking producers
+ of a destination with its consumers.
+
+ The value of the message-destination-usage element must be
+ one of the following:
+ Consumes
+ Produces
+ ConsumesProduces
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ javax.jms.Queue
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The message-destination-linkType is used to link a message
+ destination reference or message-driven bean to a message
+ destination.
+
+ The Assembler sets the value to reflect the flow of messages
+ between producers and consumers in the application.
+
+ The value must be the message-destination-name of a message
+ destination in the same Deployment File or in another
+ Deployment File in the same Java EE application unit.
+
+ Alternatively, the value may be composed of a path name
+ specifying a Deployment File containing the referenced
+ message destination with the message-destination-name of the
+ destination appended and separated from the path name by
+ "#". The path name is relative to the Deployment File
+ containing Deployment Component that is referencing the
+ message destination. This allows multiple message
+ destinations with the same name to be uniquely identified.
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd
new file mode 100644
index 00000000000..fa41e4266f1
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd
@@ -0,0 +1,389 @@
+
+
+
+
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the
+ GNU General Public License Version 2 only ("GPL") or the Common
+ Development and Distribution License("CDDL") (collectively, the
+ "License"). You may not use this file except in compliance with
+ the License. You can obtain a copy of the License at
+ https://glassfish.dev.java.net/public/CDDL+GPL.html or
+ glassfish/bootstrap/legal/LICENSE.txt. See the License for the
+ specific language governing permissions and limitations under the
+ License.
+
+ When distributing the software, include this License Header
+ Notice in each file and include the License file at
+ glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
+ particular file as subject to the "Classpath" exception as
+ provided by Sun in the GPL Version 2 section of the License file
+ that accompanied this code. If applicable, add the following
+ below the License Header, with the fields enclosed by brackets []
+ replaced by your own identifying information:
+ "Portions Copyrighted [year] [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the
+ CDDL or only the GPL Version 2, indicate your decision by adding
+ "[Contributor] elects to include this software in this
+ distribution under the [CDDL or GPL Version 2] license." If you
+ don't indicate a single choice of license, a recipient has the
+ option to distribute your version of this file under either the
+ CDDL, the GPL Version 2 or to extend the choice of license to its
+ licensees as provided above. However, if you add GPL Version 2
+ code and therefore, elected the GPL Version 2 license, then the
+ option applies only if the new code is made subject to such
+ option by the copyright holder.
+
+
+
+
+
+
+
+ This is the XML Schema for the JSP 2.2 deployment descriptor
+ types. The JSP 2.2 schema contains all the special
+ structures and datatypes that are necessary to use JSP files
+ from a web application.
+
+ The contents of this schema is used by the web-common_3_0.xsd
+ file to define JSP specific content.
+
+
+
+
+
+
+
+ The following conventions apply to all Java EE
+ deployment descriptor elements unless indicated otherwise.
+
+ - In elements that specify a pathname to a file within the
+ same JAR file, relative filenames (i.e., those not
+ starting with "/") are considered relative to the root of
+ the JAR file's namespace. Absolute filenames (i.e., those
+ starting with "/") also specify names in the root of the
+ JAR file's namespace. In general, relative names are
+ preferred. The exception is .war files where absolute
+ names are preferred for consistency with the Servlet API.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The jsp-configType is used to provide global configuration
+ information for the JSP files in a web application. It has
+ two subelements, taglib and jsp-property-group.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The jsp-file element contains the full path to a JSP file
+ within the web application beginning with a `/'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The jsp-property-groupType is used to group a number of
+ files so they can be given global property information.
+ All files so described are deemed to be JSP files. The
+ following additional properties can be described:
+
+ - Control whether EL is ignored.
+ - Control whether scripting elements are invalid.
+ - Indicate pageEncoding information.
+ - Indicate that a resource is a JSP document (XML).
+ - Prelude and Coda automatic includes.
+ - Control whether the character sequence #{ is allowed
+ when used as a String literal.
+ - Control whether template text containing only
+ whitespaces must be removed from the response output.
+ - Indicate the default contentType information.
+ - Indicate the default buffering model for JspWriter
+ - Control whether error should be raised for the use of
+ undeclared namespaces in a JSP page.
+
+
+
+
+
+
+
+
+
+
+ Can be used to easily set the isELIgnored
+ property of a group of JSP pages. By default, the
+ EL evaluation is enabled for Web Applications using
+ a Servlet 2.4 or greater web.xml, and disabled
+ otherwise.
+
+
+
+
+
+
+
+
+ The valid values of page-encoding are those of the
+ pageEncoding page directive. It is a
+ translation-time error to name different encodings
+ in the pageEncoding attribute of the page directive
+ of a JSP page and in a JSP configuration element
+ matching the page. It is also a translation-time
+ error to name different encodings in the prolog
+ or text declaration of a document in XML syntax and
+ in a JSP configuration element matching the document.
+ It is legal to name the same encoding through
+ mulitple mechanisms.
+
+
+
+
+
+
+
+
+ Can be used to easily disable scripting in a
+ group of JSP pages. By default, scripting is
+ enabled.
+
+
+
+
+
+
+
+
+ If true, denotes that the group of resources
+ that match the URL pattern are JSP documents,
+ and thus must be interpreted as XML documents.
+ If false, the resources are assumed to not
+ be JSP documents, unless there is another
+ property group that indicates otherwise.
+
+
+
+
+
+
+
+
+ The include-prelude element is a context-relative
+ path that must correspond to an element in the
+ Web Application. When the element is present,
+ the given path will be automatically included (as
+ in an include directive) at the beginning of each
+ JSP page in this jsp-property-group.
+
+
+
+
+
+
+
+
+ The include-coda element is a context-relative
+ path that must correspond to an element in the
+ Web Application. When the element is present,
+ the given path will be automatically included (as
+ in an include directive) at the end of each
+ JSP page in this jsp-property-group.
+
+
+
+
+
+
+
+
+ The character sequence #{ is reserved for EL expressions.
+ Consequently, a translation error occurs if the #{
+ character sequence is used as a String literal, unless
+ this element is enabled (true). Disabled (false) by
+ default.
+
+
+
+
+
+
+
+
+ Indicates that template text containing only whitespaces
+ must be removed from the response output. It has no
+ effect on JSP documents (XML syntax). Disabled (false)
+ by default.
+
+
+
+
+
+
+
+
+ The valid values of default-content-type are those of the
+ contentType page directive. It specifies the default
+ response contentType if the page directive does not include
+ a contentType attribute.
+
+
+
+
+
+
+
+
+ The valid values of buffer are those of the
+ buffer page directive. It specifies if buffering should be
+ used for the output to response, and if so, the size of the
+ buffer to use.
+
+
+
+
+
+
+
+
+ The default behavior when a tag with unknown namespace is used
+ in a JSP page (regular syntax) is to silently ignore it. If
+ set to true, then an error must be raised during the translation
+ time when an undeclared tag is used in a JSP page. Disabled
+ (false) by default.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The taglibType defines the syntax for declaring in
+ the deployment descriptor that a tag library is
+ available to the application. This can be done
+ to override implicit map entries from TLD files and
+ from the container.
+
+
+
+
+
+
+
+
+ A taglib-uri element describes a URI identifying a
+ tag library used in the web application. The body
+ of the taglib-uri element may be either an
+ absolute URI specification, or a relative URI.
+ There should be no entries in web.xml with the
+ same taglib-uri value.
+
+
+
+
+
+
+
+
+ the taglib-location element contains the location
+ (as a resource relative to the root of the web
+ application) where to find the Tag Library
+ Description file for the tag library.
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd
new file mode 100644
index 00000000000..bbcdf43cd3a
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd
@@ -0,0 +1,272 @@
+
+
+
+
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the
+ GNU General Public License Version 2 only ("GPL") or the Common
+ Development and Distribution License("CDDL") (collectively, the
+ "License"). You may not use this file except in compliance with
+ the License. You can obtain a copy of the License at
+ https://glassfish.dev.java.net/public/CDDL+GPL.html or
+ glassfish/bootstrap/legal/LICENSE.txt. See the License for the
+ specific language governing permissions and limitations under the
+ License.
+
+ When distributing the software, include this License Header
+ Notice in each file and include the License file at
+ glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
+ particular file as subject to the "Classpath" exception as
+ provided by Sun in the GPL Version 2 section of the License file
+ that accompanied this code. If applicable, add the following
+ below the License Header, with the fields enclosed by brackets []
+ replaced by your own identifying information:
+ "Portions Copyrighted [year] [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the
+ CDDL or only the GPL Version 2, indicate your decision by adding
+ "[Contributor] elects to include this software in this
+ distribution under the [CDDL or GPL Version 2] license." If you
+ don't indicate a single choice of license, a recipient has the
+ option to distribute your version of this file under either the
+ CDDL, the GPL Version 2 or to extend the choice of license to its
+ licensees as provided above. However, if you add GPL Version 2
+ code and therefore, elected the GPL Version 2 license, then the
+ option applies only if the new code is made subject to such
+ option by the copyright holder.
+
+
+
+
+
+
+
+ ...
+
+
+ The instance documents may indicate the published version of
+ the schema using the xsi:schemaLocation attribute for Java EE
+ namespace with the following location:
+
+ http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd
+
+ ]]>
+
+
+
+
+
+
+ The following conventions apply to all Java EE
+ deployment descriptor elements unless indicated otherwise.
+
+ - In elements that specify a pathname to a file within the
+ same JAR file, relative filenames (i.e., those not
+ starting with "/") are considered relative to the root of
+ the JAR file's namespace. Absolute filenames (i.e., those
+ starting with "/") also specify names in the root of the
+ JAR file's namespace. In general, relative names are
+ preferred. The exception is .war files where absolute
+ names are preferred for consistency with the Servlet API.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The web-app element is the root of the deployment
+ descriptor for a web application. Note that the sub-elements
+ of this element can be in the arbitrary order. Because of
+ that, the multiplicity of the elements of distributable,
+ session-config, welcome-file-list, jsp-config, login-config,
+ and locale-encoding-mapping-list was changed from "?" to "*"
+ in this schema. However, the deployment descriptor instance
+ file must not contain multiple elements of session-config,
+ jsp-config, and login-config. When there are multiple elements of
+ welcome-file-list or locale-encoding-mapping-list, the container
+ must concatenate the element contents. The multiple occurence
+ of the element distributable is redundant and the container
+ treats that case exactly in the same way when there is only
+ one distributable.
+
+
+
+
+
+
+
+ The servlet element contains the name of a servlet.
+ The name must be unique within the web application.
+
+
+
+
+
+
+
+
+
+
+ The filter element contains the name of a filter.
+ The name must be unique within the web application.
+
+
+
+
+
+
+
+
+
+
+ The ejb-local-ref-name element contains the name of an EJB
+ reference. The EJB reference is an entry in the web
+ application's environment and is relative to the
+ java:comp/env context. The name must be unique within
+ the web application.
+
+ It is recommended that name is prefixed with "ejb/".
+
+
+
+
+
+
+
+
+
+
+ The ejb-ref-name element contains the name of an EJB
+ reference. The EJB reference is an entry in the web
+ application's environment and is relative to the
+ java:comp/env context. The name must be unique within
+ the web application.
+
+ It is recommended that name is prefixed with "ejb/".
+
+
+
+
+
+
+
+
+
+
+ The resource-env-ref-name element specifies the name of
+ a resource environment reference; its value is the
+ environment entry name used in the web application code.
+ The name is a JNDI name relative to the java:comp/env
+ context and must be unique within a web application.
+
+
+
+
+
+
+
+
+
+
+ The message-destination-ref-name element specifies the name of
+ a message destination reference; its value is the
+ environment entry name used in the web application code.
+ The name is a JNDI name relative to the java:comp/env
+ context and must be unique within a web application.
+
+
+
+
+
+
+
+
+
+
+ The res-ref-name element specifies the name of a
+ resource manager connection factory reference. The name
+ is a JNDI name relative to the java:comp/env context.
+ The name must be unique within a web application.
+
+
+
+
+
+
+
+
+
+
+ The env-entry-name element contains the name of a web
+ application's environment entry. The name is a JNDI
+ name relative to the java:comp/env context. The name
+ must be unique within a web application.
+
+
+
+
+
+
+
+
+
+
+ A role-name-key is specified to allow the references
+ from the security-role-refs.
+
+
+
+
+
+
+
+
+
+
+ The keyref indicates the references from
+ security-role-ref to a specified role-name.
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd
new file mode 100644
index 00000000000..f994bc2c651
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd
@@ -0,0 +1,1575 @@
+
+
+
+
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the
+ GNU General Public License Version 2 only ("GPL") or the Common
+ Development and Distribution License("CDDL") (collectively, the
+ "License"). You may not use this file except in compliance with
+ the License. You can obtain a copy of the License at
+ https://glassfish.dev.java.net/public/CDDL+GPL.html or
+ glassfish/bootstrap/legal/LICENSE.txt. See the License for the
+ specific language governing permissions and limitations under the
+ License.
+
+ When distributing the software, include this License Header
+ Notice in each file and include the License file at
+ glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
+ particular file as subject to the "Classpath" exception as
+ provided by Sun in the GPL Version 2 section of the License file
+ that accompanied this code. If applicable, add the following
+ below the License Header, with the fields enclosed by brackets []
+ replaced by your own identifying information:
+ "Portions Copyrighted [year] [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the
+ CDDL or only the GPL Version 2, indicate your decision by adding
+ "[Contributor] elects to include this software in this
+ distribution under the [CDDL or GPL Version 2] license." If you
+ don't indicate a single choice of license, a recipient has the
+ option to distribute your version of this file under either the
+ CDDL, the GPL Version 2 or to extend the choice of license to its
+ licensees as provided above. However, if you add GPL Version 2
+ code and therefore, elected the GPL Version 2 license, then the
+ option applies only if the new code is made subject to such
+ option by the copyright holder.
+
+
+
+
+
+
+
+ ...
+
+
+ The instance documents may indicate the published version of
+ the schema using the xsi:schemaLocation attribute for Java EE
+ namespace with the following location:
+
+ http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd
+
+ ]]>
+
+
+
+
+
+
+ The following conventions apply to all Java EE
+ deployment descriptor elements unless indicated otherwise.
+
+ - In elements that specify a pathname to a file within the
+ same JAR file, relative filenames (i.e., those not
+ starting with "/") are considered relative to the root of
+ the JAR file's namespace. Absolute filenames (i.e., those
+ starting with "/") also specify names in the root of the
+ JAR file's namespace. In general, relative names are
+ preferred. The exception is .war files where absolute
+ names are preferred for consistency with the Servlet API.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The context-param element contains the declaration
+ of a web application's servlet context
+ initialization parameters.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The metadata-complete attribute defines whether this
+ deployment descriptor and other related deployment
+ descriptors for this module (e.g., web service
+ descriptors) are complete, or whether the class
+ files available to this module and packaged with
+ this application should be examined for annotations
+ that specify deployment information.
+
+ If metadata-complete is set to "true", the deployment
+ tool must ignore any annotations that specify deployment
+ information, which might be present in the class files
+ of the application.
+
+ If metadata-complete is not specified or is set to
+ "false", the deployment tool must examine the class
+ files of the application for annotations, as
+ specified by the specifications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The auth-constraintType indicates the user roles that
+ should be permitted access to this resource
+ collection. The role-name used here must either correspond
+ to the role-name of one of the security-role elements
+ defined for this web application, or be the specially
+ reserved role-name "*" that is a compact syntax for
+ indicating all roles in the web application. If both "*"
+ and rolenames appear, the container interprets this as all
+ roles. If no roles are defined, no user is allowed access
+ to the portion of the web application described by the
+ containing security-constraint. The container matches
+ role names case sensitively when determining access.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The auth-methodType is used to configure the authentication
+ mechanism for the web application. As a prerequisite to
+ gaining access to any web resources which are protected by
+ an authorization constraint, a user must have authenticated
+ using the configured mechanism. Legal values are "BASIC",
+ "DIGEST", "FORM", "CLIENT-CERT", or a vendor-specific
+ authentication scheme.
+
+ Used in: login-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The dispatcher has five legal values: FORWARD, REQUEST,
+ INCLUDE, ASYNC, and ERROR.
+
+ A value of FORWARD means the Filter will be applied under
+ RequestDispatcher.forward() calls.
+ A value of REQUEST means the Filter will be applied under
+ ordinary client calls to the path or servlet.
+ A value of INCLUDE means the Filter will be applied under
+ RequestDispatcher.include() calls.
+ A value of ASYNC means the Filter will be applied under
+ calls dispatched from an AsyncContext.
+ A value of ERROR means the Filter will be applied under the
+ error page mechanism.
+
+ The absence of any dispatcher elements in a filter-mapping
+ indicates a default of applying filters only under ordinary
+ client calls to the path or servlet.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The error-code contains an HTTP error code, ex: 404
+
+ Used in: error-page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The error-pageType contains a mapping between an error code
+ or exception type to the path of a resource in the web
+ application.
+
+ Error-page declarations using the exception-type element in
+ the deployment descriptor must be unique up to the class name of
+ the exception-type. Similarly, error-page declarations using the
+ status-code element must be unique in the deployment descriptor
+ up to the status code.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+
+ The exception-type contains a fully qualified class
+ name of a Java exception type.
+
+
+
+
+
+
+
+
+
+ The location element contains the location of the
+ resource in the web application relative to the root of
+ the web application. The value of the location must have
+ a leading `/'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The filterType is used to declare a filter in the web
+ application. The filter is mapped to either a servlet or a
+ URL pattern in the filter-mapping element, using the
+ filter-name value to reference. Filters can access the
+ initialization parameters declared in the deployment
+ descriptor at runtime via the FilterConfig interface.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+
+ The fully qualified classname of the filter.
+
+
+
+
+
+
+
+
+
+ The init-param element contains a name/value pair as
+ an initialization param of a servlet filter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Declaration of the filter mappings in this web
+ application is done by using filter-mappingType.
+ The container uses the filter-mapping
+ declarations to decide which filters to apply to a request,
+ and in what order. The container matches the request URI to
+ a Servlet in the normal way. To determine which filters to
+ apply it matches filter-mapping declarations either on
+ servlet-name, or on url-pattern for each filter-mapping
+ element, depending on which style is used. The order in
+ which filters are invoked is the order in which
+ filter-mapping declarations that match a request URI for a
+ servlet appear in the list of filter-mapping elements.The
+ filter-name value must be the value of the filter-name
+ sub-elements of one of the filter declarations in the
+ deployment descriptor.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type defines a string which contains at least one
+ character.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The logical name of the filter is declare
+ by using filter-nameType. This name is used to map the
+ filter. Each filter name is unique within the web
+ application.
+
+ Used in: filter, filter-mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The form-login-configType specifies the login and error
+ pages that should be used in form based login. If form based
+ authentication is not used, these elements are ignored.
+
+ Used in: login-config
+
+
+
+
+
+
+
+
+ The form-login-page element defines the location in the web
+ app where the page that can be used for login can be
+ found. The path begins with a leading / and is interpreted
+ relative to the root of the WAR.
+
+
+
+
+
+
+
+
+ The form-error-page element defines the location in
+ the web app where the error page that is displayed
+ when login is not successful can be found.
+ The path begins with a leading / and is interpreted
+ relative to the root of the WAR.
+
+
+
+
+
+
+
+
+
+
+
+
+ A HTTP method type as defined in HTTP 1.1 section 2.2.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The login-configType is used to configure the authentication
+ method that should be used, the realm name that should be
+ used for this application, and the attributes that are
+ needed by the form login mechanism.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+ The realm name element specifies the realm name to
+ use in HTTP Basic authorization.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The mime-mappingType defines a mapping between an extension
+ and a mime type.
+
+ Used in: web-app
+
+
+
+
+
+
+
+ The extension element contains a string describing an
+ extension. example: "txt"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The mime-typeType is used to indicate a defined mime type.
+
+ Example:
+ "text/plain"
+
+ Used in: mime-mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The security-constraintType is used to associate
+ security constraints with one or more web resource
+ collections
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The servletType is used to declare a servlet.
+ It contains the declarative data of a
+ servlet. If a jsp-file is specified and the load-on-startup
+ element is present, then the JSP should be precompiled and
+ loaded.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+
+
+ The servlet-class element contains the fully
+ qualified class name of the servlet.
+
+
+
+
+
+
+
+
+
+
+
+ The load-on-startup element indicates that this
+ servlet should be loaded (instantiated and have
+ its init() called) on the startup of the web
+ application. The optional contents of these
+ element must be an integer indicating the order in
+ which the servlet should be loaded. If the value
+ is a negative integer, or the element is not
+ present, the container is free to load the servlet
+ whenever it chooses. If the value is a positive
+ integer or 0, the container must load and
+ initialize the servlet as the application is
+ deployed. The container must guarantee that
+ servlets marked with lower integers are loaded
+ before servlets marked with higher integers. The
+ container may choose the order of loading of
+ servlets with the same load-on-start-up value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The servlet-mappingType defines a mapping between a
+ servlet and a url pattern.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The servlet-name element contains the canonical name of the
+ servlet. Each servlet name is unique within the web
+ application.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The session-configType defines the session parameters
+ for this web application.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+ The session-timeout element defines the default
+ session timeout interval for all sessions created
+ in this web application. The specified timeout
+ must be expressed in a whole number of minutes.
+ If the timeout is 0 or less, the container ensures
+ the default behaviour of sessions is never to time
+ out. If this element is not specified, the container
+ must set its default timeout period.
+
+
+
+
+
+
+
+
+ The cookie-config element defines the configuration of the
+ session tracking cookies created by this web application.
+
+
+
+
+
+
+
+
+ The tracking-mode element defines the tracking modes
+ for sessions created by this web application
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The cookie-configType defines the configuration for the
+ session tracking cookies of this web application.
+
+ Used in: session-config
+
+
+
+
+
+
+
+
+ The name that will be assigned to any session tracking
+ cookies created by this web application.
+ The default is JSESSIONID
+
+
+
+
+
+
+
+
+ The domain name that will be assigned to any session tracking
+ cookies created by this web application.
+
+
+
+
+
+
+
+
+ The path that will be assigned to any session tracking
+ cookies created by this web application.
+
+
+
+
+
+
+
+
+ The comment that will be assigned to any session tracking
+ cookies created by this web application.
+
+
+
+
+
+
+
+
+ Specifies whether any session tracking cookies created
+ by this web application will be marked as HttpOnly
+
+
+
+
+
+
+
+
+ Specifies whether any session tracking cookies created
+ by this web application will be marked as secure
+ even if the request that initiated the corresponding session
+ is using plain HTTP instead of HTTPS
+
+
+
+
+
+
+
+
+ The lifetime (in seconds) that will be assigned to any
+ session tracking cookies created by this web application.
+ Default is -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The name that will be assigned to any session tracking
+ cookies created by this web application.
+ The default is JSESSIONID
+
+ Used in: cookie-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The domain name that will be assigned to any session tracking
+ cookies created by this web application.
+
+ Used in: cookie-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The path that will be assigned to any session tracking
+ cookies created by this web application.
+
+ Used in: cookie-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The comment that will be assigned to any session tracking
+ cookies created by this web application.
+
+ Used in: cookie-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The tracking modes for sessions created by this web
+ application
+
+ Used in: session-config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The transport-guaranteeType specifies that the communication
+ between client and server should be NONE, INTEGRAL, or
+ CONFIDENTIAL. NONE means that the application does not
+ require any transport guarantees. A value of INTEGRAL means
+ that the application requires that the data sent between the
+ client and server be sent in such a way that it can't be
+ changed in transit. CONFIDENTIAL means that the application
+ requires that the data be transmitted in a fashion that
+ prevents other entities from observing the contents of the
+ transmission. In most cases, the presence of the INTEGRAL or
+ CONFIDENTIAL flag will indicate that the use of SSL is
+ required.
+
+ Used in: user-data-constraint
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The user-data-constraintType is used to indicate how
+ data communicated between the client and container should be
+ protected.
+
+ Used in: security-constraint
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The elements that use this type designate a path starting
+ with a "/" and interpreted relative to the root of a WAR
+ file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This type contains the recognized versions of
+ web-application supported. It is used to designate the
+ version of the web application.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The web-resource-collectionType is used to identify the
+ resources and HTTP methods on those resources to which a
+ security constraint applies. If no HTTP methods are specified,
+ then the security constraint applies to all HTTP methods.
+ If HTTP methods are specified by http-method-omission
+ elements, the security constraint applies to all methods
+ except those identified in the collection.
+ http-method-omission and http-method elements are never
+ mixed in the same collection.
+
+ Used in: security-constraint
+
+
+
+
+
+
+
+
+ The web-resource-name contains the name of this web
+ resource collection.
+
+
+
+
+
+
+
+
+
+
+
+ Each http-method names an HTTP method to which the
+ constraint applies.
+
+
+
+
+
+
+
+
+ Each http-method-omission names an HTTP method to
+ which the constraint does not apply.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The welcome-file-list contains an ordered list of welcome
+ files elements.
+
+ Used in: web-app
+
+
+
+
+
+
+
+
+ The welcome-file element contains file name to use
+ as a default welcome file, such as index.html
+
+
+
+
+
+
+
+
+
+
+
+
+ The localeType defines valid locale defined by ISO-639-1
+ and ISO-3166.
+
+
+
+
+
+
+
+
+
+
+
+
+ The encodingType defines IANA character sets.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The locale-encoding-mapping-list contains one or more
+ locale-encoding-mapping(s).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The locale-encoding-mapping contains locale name and
+ encoding name. The locale name must be either "Language-code",
+ such as "ja", defined by ISO-639 or "Language-code_Country-code",
+ such as "ja_JP". "Country code" is defined by ISO-3166.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This element indicates that the ordering sub-element in which
+ it was placed should take special action regarding the ordering
+ of this application resource relative to other application
+ configuration resources.
+ See section 8.2.2 of the specification for details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please see section 8.2.2 of the specification for details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please see section 8.2.2 of the specification for details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This element contains a sequence of "name" elements, each of
+ which
+ refers to an application configuration resource by the "name"
+ declared on its web.xml fragment. This element can also contain
+ a single "others" element which specifies that this document
+ comes
+ before or after other documents within the application.
+ See section 8.2.2 of the specification for details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This element specifies configuration information related to the
+ handling of multipart/form-data requests.
+
+
+
+
+
+
+
+
+ The directory location where uploaded files will be stored
+
+
+
+
+
+
+
+
+ The maximum size limit of uploaded files
+
+
+
+
+
+
+
+
+ The maximum size limit of multipart/form-data requests
+
+
+
+
+
+
+
+
+ The size threshold after which an uploaded file will be
+ written to disk
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/xml.xsd b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/xml.xsd
new file mode 100644
index 00000000000..aea7d0db0a4
--- /dev/null
+++ b/hapi-fhir-jpaserver-examples/hapi-fhir-jpaserver-example-postgres/src/main/webapp/WEB-INF/xsd/xml.xsd
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
About the XML namespace
+
+
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.
+
+
+
+
Notes
+
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
space (as an attribute name)
+
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
base (as an attribute name)
+
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+
+
+
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow xml:base,
+ xml:lang, xml:space or
+ xml:id attributes on elements they define.
+
+
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at
+ http://www.w3.org/2001/xml.xsd
+
+ will change accordingly; the version at
+
+ http://www.w3.org/2009/01/xml.xsd
+
+ will not change.
+
+
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+