From d290110126f03351f37cae32e569ccc5fe29569b Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Fri, 15 Jan 2016 18:02:20 -0500
Subject: [PATCH 1/4] Fix validation
---
.../fhir/rest/method/OperationParameter.java | 81 ++++----
.../uhn/fhir/validation/ValidationResult.java | 5 +
.../ca/uhn/fhir/i18n/hapi-messages.properties | 1 +
...ceProviderQuestionnaireResponseDstu21.java | 6 +-
.../test/java/ca/uhn/fhir/jpa/config/Tmp.java | 56 +++++
.../dstu21/ResourceProviderDstu21Test.java | 196 +++++++++++-------
.../fhir/jpa/demo/FhirServerConfigDstu21.java | 1 +
.../uhn/fhir/model/primitive/DateDtTest.java | 39 ++++
pom.xml | 7 +-
src/site/xdoc/doc_cli.xml | 9 +-
10 files changed, 277 insertions(+), 124 deletions(-)
create mode 100644 hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/Tmp.java
create mode 100644 hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
index bd3f388c393..65a565fa914 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationParameter.java
@@ -23,6 +23,7 @@ package ca.uhn.fhir.rest.method;
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.List;
import java.util.Map;
@@ -82,8 +83,6 @@ public class OperationParameter implements IParameter {
myContext = theCtx;
}
-
-
protected FhirContext getContext() {
return myContext;
}
@@ -109,22 +108,22 @@ public class OperationParameter implements IParameter {
public void initializeTypes(Method theMethod, Class extends Collection>> theOuterCollectionType, Class extends Collection>> theInnerCollectionType, Class> theParameterType) {
if (getContext().getVersion().getVersion().isRi()) {
if (IDatatype.class.isAssignableFrom(theParameterType)) {
- throw new ConfigurationException("Incorrect use of type " + theParameterType.getSimpleName() + " as parameter type for method when context is for version " + getContext().getVersion().getVersion().name() + " in method: " + theMethod.toString());
+ throw new ConfigurationException("Incorrect use of type " + theParameterType.getSimpleName() + " as parameter type for method when context is for version "
+ + getContext().getVersion().getVersion().name() + " in method: " + theMethod.toString());
}
}
-
+
myParameterType = theParameterType;
if (theInnerCollectionType != null) {
myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, myName);
} else {
myMax = 1;
}
-
+
myAllowGet = IPrimitiveType.class.isAssignableFrom(myParameterType) || String.class.equals(myParameterType);
-
+
/*
- * The parameter can be of type string for validation methods - This is a bit
- * weird. See ValidateDstu2Test. We should probably clean this up..
+ * The parameter can be of type string for validation methods - This is a bit weird. See ValidateDstu2Test. We should probably clean this up..
*/
if (!myParameterType.equals(IBase.class) && !myParameterType.equals(String.class)) {
if (IBaseResource.class.isAssignableFrom(myParameterType) && myParameterType.isInterface()) {
@@ -150,7 +149,8 @@ public class OperationParameter implements IParameter {
}
@Override
- public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
+ public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map> theTargetQueryArguments, IBaseResource theTargetResource)
+ throws InternalErrorException {
assert theTargetResource != null;
Object sourceClientArgument = theSourceClientArgument;
if (sourceClientArgument == null) {
@@ -173,7 +173,7 @@ public class OperationParameter implements IParameter {
String[] paramValues = theRequest.getParameters().get(myName);
if (paramValues != null && paramValues.length > 0) {
if (myAllowGet) {
-
+
if (DateRangeParam.class.isAssignableFrom(myParameterType)) {
List parameters = new ArrayList();
parameters.add(QualifiedParamList.singleton(paramValues[0]));
@@ -184,11 +184,11 @@ public class OperationParameter implements IParameter {
dateRangeParam.setValuesAsQueryTokens(parameters);
matchingParamValues.add(dateRangeParam);
} else if (String.class.isAssignableFrom(myParameterType)) {
-
+
for (String next : paramValues) {
matchingParamValues.add(next);
}
-
+
} else {
for (String nextValue : paramValues) {
FhirContext ctx = theRequest.getServer().getFhirContext();
@@ -212,42 +212,51 @@ public class OperationParameter implements IParameter {
return null;
}
- Class extends IBaseResource> wantedResourceType = theMethodBinding.getContext().getResourceDefinition("Parameters").getImplementingClass();
+ // Class extends IBaseResource> wantedResourceType = theMethodBinding.getContext().getResourceDefinition("Parameters").getImplementingClass();
+ Class wantedResourceType = null;
IBaseResource requestContents = ResourceParameter.loadResourceFromRequest(theRequest, theMethodBinding, wantedResourceType);
RuntimeResourceDefinition def = ctx.getResourceDefinition(requestContents);
+ if (def.getName().equals("Parameters")) {
- BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
- BaseRuntimeElementCompositeDefinition> paramChildElem = (BaseRuntimeElementCompositeDefinition>) paramChild.getChildByName("parameter");
+ BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
+ BaseRuntimeElementCompositeDefinition> paramChildElem = (BaseRuntimeElementCompositeDefinition>) paramChild.getChildByName("parameter");
- RuntimeChildPrimitiveDatatypeDefinition nameChild = (RuntimeChildPrimitiveDatatypeDefinition) paramChildElem.getChildByName("name");
- BaseRuntimeChildDefinition valueChild = paramChildElem.getChildByName("value[x]");
- BaseRuntimeChildDefinition resourceChild = paramChildElem.getChildByName("resource");
+ RuntimeChildPrimitiveDatatypeDefinition nameChild = (RuntimeChildPrimitiveDatatypeDefinition) paramChildElem.getChildByName("name");
+ BaseRuntimeChildDefinition valueChild = paramChildElem.getChildByName("value[x]");
+ BaseRuntimeChildDefinition resourceChild = paramChildElem.getChildByName("resource");
- IAccessor paramChildAccessor = paramChild.getAccessor();
- List values = paramChildAccessor.getValues(requestContents);
- for (IBase nextParameter : values) {
- List nextNames = nameChild.getAccessor().getValues(nextParameter);
- if (nextNames != null && nextNames.size() > 0) {
- IPrimitiveType> nextName = (IPrimitiveType>) nextNames.get(0);
- if (myName.equals(nextName.getValueAsString())) {
+ IAccessor paramChildAccessor = paramChild.getAccessor();
+ List values = paramChildAccessor.getValues(requestContents);
+ for (IBase nextParameter : values) {
+ List nextNames = nameChild.getAccessor().getValues(nextParameter);
+ if (nextNames != null && nextNames.size() > 0) {
+ IPrimitiveType> nextName = (IPrimitiveType>) nextNames.get(0);
+ if (myName.equals(nextName.getValueAsString())) {
- if (myParameterType.isAssignableFrom(nextParameter.getClass())) {
- matchingParamValues.add(nextParameter);
- } else {
- List paramValues = valueChild.getAccessor().getValues(nextParameter);
- List paramResources = resourceChild.getAccessor().getValues(nextParameter);
- if (paramValues != null && paramValues.size() > 0) {
- tryToAddValues(paramValues, matchingParamValues);
- } else if (paramResources != null && paramResources.size() > 0) {
- tryToAddValues(paramResources, matchingParamValues);
+ if (myParameterType.isAssignableFrom(nextParameter.getClass())) {
+ matchingParamValues.add(nextParameter);
+ } else {
+ List paramValues = valueChild.getAccessor().getValues(nextParameter);
+ List paramResources = resourceChild.getAccessor().getValues(nextParameter);
+ if (paramValues != null && paramValues.size() > 0) {
+ tryToAddValues(paramValues, matchingParamValues);
+ } else if (paramResources != null && paramResources.size() > 0) {
+ tryToAddValues(paramResources, matchingParamValues);
+ }
}
- }
+ }
}
}
- }
+ } else {
+
+ if (myParameterType.isAssignableFrom(requestContents.getClass())) {
+ tryToAddValues(Arrays.asList((IBase) requestContents), matchingParamValues);
+ }
+
+ }
}
if (matchingParamValues.isEmpty()) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
index 7b781f8cd13..7503218c34c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
@@ -111,6 +111,11 @@ public class ValidationResult {
OperationOutcomeUtil.addIssue(myCtx, oo, severity, next.getMessage(), location, ExceptionHandlingInterceptor.PROCESSING);
}
+ if (myMessages.isEmpty()) {
+ String message = myCtx.getLocalizer().getMessage(ValidationResult.class, "noIssuesDetected");
+ OperationOutcomeUtil.addIssue(myCtx, oo, "information", message, null, "informational");
+ }
+
return oo;
}
diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
index d48a019215b..356d9211828 100644
--- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
+++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
@@ -38,6 +38,7 @@ ca.uhn.fhir.rest.server.RestfulServer.rootRequest=This is the base URL of FHIR s
ca.uhn.fhir.validation.ValidationContext.unableToDetermineEncoding=Unable to determine encoding (e.g. XML / JSON) on validation input. Is this a valid FHIR resource body?
ca.uhn.fhir.validation.FhirValidator.noPhlocWarningOnStartup=Phloc-schematron library not found on classpath, will not attempt to perform schematron validation
ca.uhn.fhir.validation.FhirValidator.noPhlocError=Phloc-schematron library not found on classpath, can not enable perform schematron validation
+ca.uhn.fhir.validation.ValidationResult.noIssuesDetected=No issues detected during validation
# JPA Messages
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu21.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu21.java
index f1c75648dec..dc1a25bb7f3 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu21.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderQuestionnaireResponseDstu21.java
@@ -1,5 +1,7 @@
package ca.uhn.fhir.jpa.provider;
+import org.hl7.fhir.dstu21.model.QuestionnaireResponse;
+
/*
* #%L
* HAPI FHIR JPA Server
@@ -20,9 +22,7 @@ package ca.uhn.fhir.jpa.provider;
* #L%
*/
-import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
-
-public class BaseJpaResourceProviderQuestionnaireResponseDstu21 extends JpaResourceProviderDstu2 {
+public class BaseJpaResourceProviderQuestionnaireResponseDstu21 extends JpaResourceProviderDstu21 {
// nothing yet
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/Tmp.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/Tmp.java
new file mode 100644
index 00000000000..04bd323c8c3
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/Tmp.java
@@ -0,0 +1,56 @@
+package ca.uhn.fhir.jpa.config;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.dstu2.resource.Bundle;
+import ca.uhn.fhir.model.dstu2.resource.Organization;
+import ca.uhn.fhir.model.dstu2.resource.Patient;
+import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
+import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.rest.client.IGenericClient;
+import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
+
+public class Tmp {
+
+ public static void main(String[] args) {
+
+ FhirContext ctx = FhirContext.forDstu2();
+ ctx.getRestfulClientFactory().setSocketTimeout(200000);
+ ctx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
+ IGenericClient client = ctx.newRestfulGenericClient("http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu2");
+
+ Bundle b = new Bundle();
+ b.setType(BundleTypeEnum.TRANSACTION);
+ int resCount = 20;
+ for (int i = 0; i < (resCount / 2); i++) {
+ Organization org = new Organization();
+ org.setId(IdDt.newRandomUuid());
+ org.setName("Random Org " + i);
+ org.addAddress().addLine("Random Org Line 1");
+ org.addIdentifier().setSystem("urn:foo").setValue("some_system" + i);
+ b.addEntry().setResource(org).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Organization");
+
+ Patient patient = new Patient();
+ patient.setId(IdDt.newRandomUuid());
+ patient.addName().addFamily("Family" + i).addGiven("Gigven " + i);
+ patient.addAddress().addLine("Random Patient Line 1");
+ patient.addIdentifier().setSystem("urn:bar").setValue("some_system" + i);
+ b.addEntry().setResource(patient).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Patient");
+ }
+
+ int total = 0;
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < 300; i++) {
+ client.transaction().withBundle(b).execute();
+ ourLog.info("" + i);
+ total += resCount;
+ }
+
+ long delay = System.currentTimeMillis() - start;
+ ourLog.info("Wrote {} resources at {}ms / res", total, delay / total);
+
+ //sync 13:57:14.683 [main] INFO ca.uhn.fhir.jpa.config.Tmp - Wrote 6000 resources at 7ms / res
+ }
+private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Tmp.class);
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
index 3ee3702ea37..b3c70456a64 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
@@ -57,6 +57,7 @@ import org.hl7.fhir.dstu21.model.Encounter;
import org.hl7.fhir.dstu21.model.Encounter.EncounterClass;
import org.hl7.fhir.dstu21.model.Encounter.EncounterLocationComponent;
import org.hl7.fhir.dstu21.model.Encounter.EncounterState;
+import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu21.model.IdType;
import org.hl7.fhir.dstu21.model.ImagingStudy;
import org.hl7.fhir.dstu21.model.InstantType;
@@ -111,10 +112,10 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
@Override
public void before() throws Exception {
super.before();
-
+
myDaoConfig.setAllowMultipleDelete(true);
}
-
+
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
@@ -135,7 +136,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
Device dev1 = new Device();
dev1.setManufacturer("Some Manufacturer");
IIdType devId1 = myDeviceDao.create(dev1).getId().toUnqualifiedVersionless();
-
+
Device dev2 = new Device();
dev2.setManufacturer("Some Manufacturer 2");
myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
@@ -159,12 +160,12 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
obs3.getCode().addCoding().setCode("CODE3");
obs3.setValue(new StringType("obsvalue3"));
IIdType obsId3 = myObservationDao.create(obs3).getId().toUnqualifiedVersionless();
-
+
List actual;
StringAndListParam param;
-
- ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
-
+
+ ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] { ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart() });
+
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
@@ -176,13 +177,12 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
.withParameter(Parameters.class, Constants.PARAM_CONTENT, new StringType("obsvalue1"))
.execute();
//@formatter:on
-
- actual = toUnqualifiedVersionlessIds((Bundle)response.getParameter().get(0).getResource());
+
+ actual = toUnqualifiedVersionlessIds((Bundle) response.getParameter().get(0).getResource());
assertThat(actual, containsInAnyOrder(ptId1, obsId1, devId1));
}
-
-
+
@Test
public void testBundleCreate() throws Exception {
IGenericClient client = ourClient;
@@ -211,7 +211,6 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
}
}
-
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
@@ -244,7 +243,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
subs.getChannel().setType(SubscriptionChannelType.WEBSOCKET);
subs.setCriteria("Observation?");
IIdType id = ourClient.create().resource(subs).execute().getId().toUnqualifiedVersionless();
-
+
//@formatter:off
Bundle resp = ourClient
.search()
@@ -297,24 +296,11 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
//@formatter:on
- Bundle found = ourClient
- .search()
- .forResource(Organization.class)
- .where(Organization.NAME.matches()
- .value("rpdstu2_testCountParam_01"))
- .count(10)
- .returnBundle(Bundle.class)
- .execute();
+ Bundle found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(10).returnBundle(Bundle.class).execute();
assertEquals(100, found.getTotal());
assertEquals(10, found.getEntry().size());
- found = ourClient
- .search()
- .forResource(Organization.class)
- .where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
- .count(999)
- .returnBundle(Bundle.class)
- .execute();
+ found = ourClient.search().forResource(Organization.class).where(Organization.NAME.matches().value("rpdstu2_testCountParam_01")).count(999).returnBundle(Bundle.class).execute();
//@formatter:on
assertEquals(100, found.getTotal());
assertEquals(50, found.getEntry().size());
@@ -353,7 +339,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
assertThat(e.getMessage(), containsString("Question with linkId[link0]"));
}
}
-
+
@Test
public void testUpdateResourceConditionalComplex() throws IOException {
Patient pt = new Patient();
@@ -374,12 +360,12 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
} finally {
response.close();
}
-
+
pt.addName().addFamily("FOO");
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
-
+
IdType id2;
response = ourHttpClient.execute(put);
try {
@@ -390,7 +376,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
} finally {
response.close();
}
-
+
assertEquals(id.getIdPart(), id2.getIdPart());
assertEquals("1", id.getVersionIdPart());
assertEquals("2", id2.getVersionIdPart());
@@ -416,7 +402,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
} finally {
response.close();
}
-
+
IdType id2;
response = ourHttpClient.execute(post);
try {
@@ -427,7 +413,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
} finally {
response.close();
}
-
+
// //@formatter:off
// IIdType id3 = ourClient
// .update()
@@ -435,10 +421,10 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
// .conditionalByUrl("Patient?identifier=http://general-hospital.co.uk/Identifiers|09832345234543876876")
// .execute().getId();
// //@formatter:on
-
+
assertEquals(id.getValue(), id2.getValue());
}
-
+
@Test
public void testCreateResourceConditional() throws IOException {
String methodName = "testCreateResourceConditional";
@@ -581,12 +567,12 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
String methodName = "testDeleteConditionalMultiple";
myDaoConfig.setAllowMultipleDelete(false);
-
+
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("FAM1");
IIdType id1 = myPatientDao.create(p).getId().toUnqualifiedVersionless();
-
+
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("FAM2");
@@ -602,15 +588,16 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
//@formatter:on
fail();
} catch (PreconditionFailedException e) {
- assertEquals("HTTP 412 Precondition Failed: Failed to DELETE resource with match URL \"Patient?identifier=testDeleteConditionalMultiple\" because this search matched 2 resources", e.getMessage());
+ assertEquals("HTTP 412 Precondition Failed: Failed to DELETE resource with match URL \"Patient?identifier=testDeleteConditionalMultiple\" because this search matched 2 resources",
+ e.getMessage());
}
-
+
// Not deleted yet..
ourClient.read().resource("Patient").withId(id1).execute();
ourClient.read().resource("Patient").withId(id2).execute();
myDaoConfig.setAllowMultipleDelete(true);
-
+
//@formatter:off
ourClient
.delete()
@@ -686,7 +673,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
}
}
-
+
/**
* Based on email from Rene Spronk
*/
@@ -713,8 +700,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
}
/*
- * Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to
- * make sure that works too..
+ * Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to make sure that works too..
*/
Socket sock = new Socket();
sock.setSoTimeout(3000);
@@ -842,7 +828,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Location locParent = new Location();
- locParent.setName(methodName+"Parent");
+ locParent.setName(methodName + "Parent");
IIdType locPId = ourClient.create().resource(locParent).execute().getId().toUnqualifiedVersionless();
Location locChild = new Location();
@@ -854,7 +840,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
encU.getPatient().setReferenceElement(patientId);
encU.addLocation().getLocation().setReferenceElement(locCId);
IIdType encUId = ourClient.create().resource(encU).execute().getId().toUnqualifiedVersionless();
-
+
Encounter enc = new Encounter();
enc.getPatient().setReferenceElement(patientId);
enc.addLocation().getLocation().setReferenceElement(locCId);
@@ -867,7 +853,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
IIdType obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless();
ourLog.info("IDs: EncU:" + encUId.getIdPart() + " Enc:" + encId.getIdPart() + " " + patientId.toUnqualifiedVersionless());
-
+
Parameters output = ourClient.operation().onInstance(encId).named("everything").withNoParameters(Parameters.class).execute();
Bundle b = (Bundle) output.getParameter().get(0).getResource();
List ids = toUnqualifiedVersionlessIds(b);
@@ -906,7 +892,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
IIdType devId = ourClient.create().resource(dev).execute().getId().toUnqualifiedVersionless();
Location locParent = new Location();
- locParent.setName(methodName+"Parent");
+ locParent.setName(methodName + "Parent");
IIdType locPId = ourClient.create().resource(locParent).execute().getId().toUnqualifiedVersionless();
Location locChild = new Location();
@@ -917,7 +903,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
Encounter encU = new Encounter();
encU.addIdentifier().setValue(methodName);
IIdType encUId = ourClient.create().resource(encU).execute().getId().toUnqualifiedVersionless();
-
+
Encounter enc = new Encounter();
enc.getPatient().setReferenceElement(patientId);
enc.addLocation().getLocation().setReferenceElement(locCId);
@@ -995,18 +981,18 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
assertThat(ids.size(), greaterThan(10));
}
}
-
+
/**
* Test for #226
*/
@Test
public void testEverythingPatientIncludesBackReferences() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
-
+
Medication med = new Medication();
med.getCode().setText(methodName);
IIdType medId = myMedicationDao.create(med).getId().toUnqualifiedVersionless();
-
+
Patient pat = new Patient();
pat.addAddress().addLine(methodName);
IIdType patId = myPatientDao.create(pat).getId().toUnqualifiedVersionless();
@@ -1015,7 +1001,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
mo.getPatient().setReferenceElement(patId);
mo.setMedication(new Reference(medId));
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
-
+
Parameters output = ourClient.operation().onInstance(patId).named("everything").withNoParameters(Parameters.class).execute();
Bundle b = (Bundle) output.getParameter().get(0).getResource();
List ids = toUnqualifiedVersionlessIds(b);
@@ -1058,8 +1044,6 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
}
-
-
@Test
public void testEverythingPatientOperation() throws Exception {
String methodName = "testEverythingOperation";
@@ -1104,27 +1088,27 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
ourLog.info(ids.toString());
}
-
+
@Test
public void testEverythingPatientType() throws Exception {
String methodName = "testEverythingPatientType";
-
+
Organization o1 = new Organization();
- o1.setName(methodName+"1");
+ o1.setName(methodName + "1");
IIdType o1Id = ourClient.create().resource(o1).execute().getId().toUnqualifiedVersionless();
Organization o2 = new Organization();
- o2.setName(methodName+"2");
+ o2.setName(methodName + "2");
IIdType o2Id = ourClient.create().resource(o2).execute().getId().toUnqualifiedVersionless();
-
+
Patient p1 = new Patient();
- p1.addName().addFamily(methodName+"1");
+ p1.addName().addFamily(methodName + "1");
p1.getManagingOrganization().setReferenceElement(o1Id);
IIdType p1Id = ourClient.create().resource(p1).execute().getId().toUnqualifiedVersionless();
Patient p2 = new Patient();
- p2.addName().addFamily(methodName+"2");
+ p2.addName().addFamily(methodName + "2");
p2.getManagingOrganization().setReferenceElement(o2Id);
IIdType p2Id = ourClient.create().resource(p2).execute().getId().toUnqualifiedVersionless();
-
+
Condition c1 = new Condition();
c1.getPatient().setReferenceElement(p1Id);
IIdType c1Id = ourClient.create().resource(c1).execute().getId().toUnqualifiedVersionless();
@@ -1133,7 +1117,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
IIdType c2Id = ourClient.create().resource(c2).execute().getId().toUnqualifiedVersionless();
Condition c3 = new Condition();
- c3.addIdentifier().setValue(methodName+"3");
+ c3.addIdentifier().setValue(methodName + "3");
IIdType c3Id = ourClient.create().resource(c3).execute().getId().toUnqualifiedVersionless();
Parameters output = ourClient.operation().onType(Patient.class).named("everything").withNoParameters(Parameters.class).execute();
@@ -1152,18 +1136,18 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
Organization org = new Organization();
org.setName(methodName);
IIdType oId = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
-
+
long time1 = System.currentTimeMillis();
Thread.sleep(10);
-
+
Patient p = new Patient();
p.addName().addFamily(methodName);
p.getManagingOrganization().setReferenceElement(oId);
IIdType pId = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
-
+
long time2 = System.currentTimeMillis();
Thread.sleep(10);
-
+
Condition c = new Condition();
c.getCode().setText(methodName);
c.getPatient().setReferenceElement(pId);
@@ -1171,8 +1155,8 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
Thread.sleep(10);
long time3 = System.currentTimeMillis();
-
- // %3E=> %3C=<
+
+ // %3E=> %3C=<
HttpGet get = new HttpGet(ourServerBase + "/Patient/" + pId.getIdPart() + "/$everything?_lastUpdated=%3E" + new InstantType(new Date(time1)).getValueAsString());
CloseableHttpResponse response = ourHttpClient.execute(get);
@@ -1188,7 +1172,8 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
response.close();
}
- get = new HttpGet(ourServerBase + "/Patient/" + pId.getIdPart() + "/$everything?_lastUpdated=%3E" + new InstantType(new Date(time2)).getValueAsString() + "&_lastUpdated=%3C" + new InstantType(new Date(time3)).getValueAsString());
+ get = new HttpGet(ourServerBase + "/Patient/" + pId.getIdPart() + "/$everything?_lastUpdated=%3E" + new InstantType(new Date(time2)).getValueAsString() + "&_lastUpdated=%3C"
+ + new InstantType(new Date(time3)).getValueAsString());
response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
@@ -1229,7 +1214,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
} finally {
response.close();
}
-
+
}
@Test
@@ -1805,11 +1790,11 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
org = new Organization();
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
org.setName(methodName + "name");
- IIdType orgNotMissing = (IdType) ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
+ IIdType orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
org = new Organization();
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
- IIdType orgMissing = (IdType) ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
+ IIdType orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
{
//@formatter:off
@@ -1817,7 +1802,7 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(false))
- .limitTo(100)
+ .count(100)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
@@ -2207,14 +2192,14 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
.returnBundle(Bundle.class)
.execute();
//@formatter:on
-
+
assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getIdElement().getIdPart());
}
@Test
- public void testValidateResource() throws IOException {
+ public void testValidateResourceWithNoIdParameters() throws IOException {
Patient patient = new Patient();
patient.addName().addGiven("James");
@@ -2224,8 +2209,6 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
input.addParameter().setName("resource").setResource(patient);
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(input);
- ourLog.info(inputStr);
-
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate?_pretty=true");
post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@@ -2235,6 +2218,61 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
ourLog.info(resp);
assertEquals(200, response.getStatusLine().getStatusCode());
assertThat(resp, not(containsString("Resource has no id")));
+ assertThat(resp, containsString("No issues detected during validation
"));
+ assertThat(resp,
+ stringContainsInOrder("", "", "", "", "
"));
+ } finally {
+ IOUtils.closeQuietly(response.getEntity().getContent());
+ response.close();
+ }
+ }
+
+ @Test
+ public void testValidateResourceWithNoIdRaw() throws IOException {
+
+ Patient patient = new Patient();
+ patient.addName().addGiven("James");
+ patient.setBirthDateElement(new DateType("2011-02-02"));
+
+ String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(patient);
+ HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
+ post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+
+ CloseableHttpResponse response = ourHttpClient.execute(post);
+ try {
+ String resp = IOUtils.toString(response.getEntity().getContent());
+ ourLog.info(resp);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertThat(resp, not(containsString("Resource has no id")));
+ assertThat(resp, containsString("No issues detected during validation
"));
+ assertThat(resp,
+ stringContainsInOrder("", "", "", "", "
"));
+ } finally {
+ IOUtils.closeQuietly(response.getEntity().getContent());
+ response.close();
+ }
+ }
+
+ @Test
+ public void testValidateResourceBaseWithNoIdRaw() throws IOException {
+
+ Patient patient = new Patient();
+ patient.addName().addGiven("James");
+ patient.setBirthDateElement(new DateType("2011-02-02"));
+ patient.addContact().setGender(AdministrativeGender.MALE);
+
+ String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(patient);
+ HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
+ post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
+
+ CloseableHttpResponse response = ourHttpClient.execute(post);
+ try {
+ String resp = IOUtils.toString(response.getEntity().getContent());
+ ourLog.info(resp);
+ assertEquals(412, response.getStatusLine().getStatusCode());
+ assertThat(resp, not(containsString("Resource has no id")));
+ assertThat(resp,
+ stringContainsInOrder(">ERROR<","/f:Patient/f:contact","SHALL at least contain a contact's details or a reference to an organization
","","","",""));
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
response.close();
diff --git a/hapi-fhir-jpaserver-example/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu21.java b/hapi-fhir-jpaserver-example/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu21.java
index 5c84e90f112..5d68f49df9e 100644
--- a/hapi-fhir-jpaserver-example/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu21.java
+++ b/hapi-fhir-jpaserver-example/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu21.java
@@ -88,6 +88,7 @@ public class FhirServerConfigDstu21 extends BaseJavaConfigDstu21 {
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;
}
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
new file mode 100644
index 00000000000..cd86a67ad19
--- /dev/null
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
@@ -0,0 +1,39 @@
+package ca.uhn.fhir.model.primitive;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.TreeSet;
+
+import org.junit.Test;
+
+public class DateDtTest {
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DateDtTest.class);
+
+ @Test
+ public void testPrecision() {
+
+// ourLog.info(""+ new TreeSet(Arrays.asList(TimeZone.getAvailableIDs())));
+
+ final Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("GMT"));
+ cal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
+ ourLog.info("Time: {}", cal); // 631152000775
+
+ DateDt dateDt = new DateDt(cal.getTime());
+ long time = dateDt.getValue().getTime();
+ ourLog.info("Time: {}", time); // 631152000775
+ ourLog.info("Time: {}", dateDt.getValue()); // 631152000775
+
+ dateDt.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ time = dateDt.getValue().getTime();
+ ourLog.info("Time: {}", time); // 631152000775
+ ourLog.info("Time: {}", dateDt.getValue()); // 631152000775
+
+ String valueAsString = dateDt.getValueAsString();
+ ourLog.info(valueAsString);
+ // is 631152000030
+
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index a1180ffc885..8c427294891 100644
--- a/pom.xml
+++ b/pom.xml
@@ -248,7 +248,6 @@
5.0.6.Final
5.2.2.Final
2.5.3
- 2.18.1
1.8
3.4
2.4
@@ -731,7 +730,7 @@
org.apache.maven.plugins
maven-failsafe-plugin
- 2.19
+ 2.19.1
org.apache.maven.plugins
@@ -741,7 +740,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.19
+ 2.19.1
true
random
@@ -1314,7 +1313,7 @@
org.apache.maven.plugins
maven-surefire-report-plugin
- 2.19
+ 2.19.1
diff --git a/src/site/xdoc/doc_cli.xml b/src/site/xdoc/doc_cli.xml
index 28ad6a8ed44..0c815c46286 100644
--- a/src/site/xdoc/doc_cli.xml
+++ b/src/site/xdoc/doc_cli.xml
@@ -13,7 +13,7 @@
hapi-fhir-cli is the HAPI FHIR Command Line tool. It features a number of HAPI's
built-in features as easy to use command line options.
-
+
You can get the tool by downloading it from our
@@ -35,7 +35,12 @@
- The tool should work correctly on any system that has Java 6 (or newer) installed. If
+ Note on Java version support: The HAPI library is designed to
+ work in Java 6+, but the Command Line Tool required a minimum of Java 8. This
+ is because the Jetty Web Server that is used within the tool has this requirement.
+
+
+ The tool should work correctly on any system that has Java 8 (or newer) installed. If
it is not working correctly, first try the following command to test if Java is installed:
$ java -version
From f9960b22d53af735a499451c230deeddd9c933c8 Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Fri, 15 Jan 2016 18:44:28 -0500
Subject: [PATCH 2/4] Clean up validation
---
.../ca/uhn/fhir/validation/FhirValidator.java | 10 +-
.../dstu21/ResourceProviderDstu21Test.java | 4 +-
.../validation/ResourceValidatorTest.java | 2 +-
.../src/test/resources/smart-conf.xml | 9675 +++++++++++++++++
.../uhn/fhir/parser/ExtensionsDstu2Test.java | 29 +
.../ResourceValidatorDstu2Test.java | 2 +-
.../src/test/resources/smart-conf.xml | 9675 +++++++++++++++++
7 files changed, 19389 insertions(+), 8 deletions(-)
create mode 100644 hapi-fhir-structures-dstu2.1/src/test/resources/smart-conf.xml
create mode 100644 hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ExtensionsDstu2Test.java
create mode 100644 hapi-fhir-structures-dstu2/src/test/resources/smart-conf.xml
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java
index 41cf972684c..944fbfc04cc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java
@@ -186,11 +186,13 @@ public class FhirValidator {
next.validateBundle(ctx);
}
- IBaseOperationOutcome oo = ctx.toResult().toOperationOutcome();
- if (oo != null && OperationOutcomeUtil.hasIssues(myContext, oo)) {
- throw new ValidationFailureException(myContext, oo);
+ if (ctx.toResult().isSuccessful() == false ) {
+ IBaseOperationOutcome oo = ctx.toResult().toOperationOutcome();
+ if (oo != null && OperationOutcomeUtil.hasIssues(myContext, oo)) {
+ throw new ValidationFailureException(myContext, oo);
+ }
}
-
+
}
private void applyDefaultValidators() {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
index b3c70456a64..43fd84eb120 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu21/ResourceProviderDstu21Test.java
@@ -1771,12 +1771,12 @@ public class ResourceProviderDstu21Test extends BaseResourceProviderDstu21Test {
String methodName = "testSearchWithMissing";
Organization org = new Organization();
- IIdType deletedIdMissingTrue = (IdType) ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
+ IIdType deletedIdMissingTrue = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
ourClient.delete().resourceById(deletedIdMissingTrue).execute();
org = new Organization();
org.setName("Help I'm a Bug");
- IIdType deletedIdMissingFalse = (IdType) ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
+ IIdType deletedIdMissingFalse = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless();
ourClient.delete().resourceById(deletedIdMissingFalse).execute();
List resources = new ArrayList();
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/validation/ResourceValidatorTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/validation/ResourceValidatorTest.java
index 40c9ebd71b9..ad6b306965e 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/validation/ResourceValidatorTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/validation/ResourceValidatorTest.java
@@ -153,7 +153,7 @@ public class ResourceValidatorTest {
assertTrue(result.isSuccessful());
assertNotNull(operationOutcome);
- assertEquals(0, operationOutcome.getIssue().size());
+ assertEquals(1, operationOutcome.getIssue().size());
}
@Test
diff --git a/hapi-fhir-structures-dstu2.1/src/test/resources/smart-conf.xml b/hapi-fhir-structures-dstu2.1/src/test/resources/smart-conf.xml
new file mode 100644
index 00000000000..98a7efdd878
--- /dev/null
+++ b/hapi-fhir-structures-dstu2.1/src/test/resources/smart-conf.xml
@@ -0,0 +1,9675 @@
+
+
+
+
+
+
+ Generated Conformance Statement -- see structured representation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ExtensionsDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ExtensionsDstu2Test.java
new file mode 100644
index 00000000000..25c36875351
--- /dev/null
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ExtensionsDstu2Test.java
@@ -0,0 +1,29 @@
+package ca.uhn.fhir.parser;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.ExtensionDt;
+import ca.uhn.fhir.model.dstu2.resource.Conformance;
+import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity;
+
+public class ExtensionsDstu2Test {
+
+ private static final FhirContext ourCtx = FhirContext.forDstu2();
+
+ @Test
+ public void testParseExtensions() throws Exception {
+ String input = IOUtils.toString(getClass().getResourceAsStream("/smart-conf.xml"));
+ Conformance conf = (Conformance) ourCtx.newXmlParser().parseResource(input);
+
+ RestSecurity sec = conf.getRest().get(0).getSecurity();
+ List uris = sec.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
+ assertEquals(1, uris.size());
+ }
+
+}
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java
index f93042592c7..e2de1023ad8 100644
--- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/validation/ResourceValidatorDstu2Test.java
@@ -132,7 +132,7 @@ public class ResourceValidatorDstu2Test {
assertTrue(result.toString(), result.isSuccessful());
assertNotNull(operationOutcome);
- assertEquals(0, operationOutcome.getIssue().size());
+ assertEquals(1, operationOutcome.getIssue().size());
}
@SuppressWarnings("deprecation")
diff --git a/hapi-fhir-structures-dstu2/src/test/resources/smart-conf.xml b/hapi-fhir-structures-dstu2/src/test/resources/smart-conf.xml
new file mode 100644
index 00000000000..98a7efdd878
--- /dev/null
+++ b/hapi-fhir-structures-dstu2/src/test/resources/smart-conf.xml
@@ -0,0 +1,9675 @@
+
+
+
+
+
+
+ Generated Conformance Statement -- see structured representation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 944afc27853d9f54c29cb7520bfd7965086b4f3a Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Wed, 20 Jan 2016 07:40:57 -0500
Subject: [PATCH 3/4] Add better constructors for date types
---
.../fhir/model/api/TemporalPrecisionEnum.java | 9 +-
.../fhir/model/primitive/BaseDateTimeDt.java | 40 ++++---
.../ca/uhn/fhir/model/primitive/DateDt.java | 64 +++++++++--
.../uhn/fhir/jpa/config/TestDstu21Config.java | 1 +
.../fhir/dstu21/model/BaseDateTimeType.java | 42 +++----
.../org/hl7/fhir/dstu21/model/DateType.java | 30 +++++
.../model/BaseDateTimeTypeDstu21Test.java | 105 ++++++++++++++++++
.../java/ca/uhn/fhir/model/DateTypeTest.java | 52 +++++++++
.../primitive/BaseDateTimeDtDstu2Test.java | 15 +++
.../uhn/fhir/model/primitive/DateDtTest.java | 16 +++
.../main/java/ca/uhn/fhir/to/Controller.java | 1 -
11 files changed, 322 insertions(+), 53 deletions(-)
create mode 100644 hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/BaseDateTimeTypeDstu21Test.java
create mode 100644 hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/DateTypeTest.java
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TemporalPrecisionEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TemporalPrecisionEnum.java
index 18a8bf8085f..1f1c18a45f7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TemporalPrecisionEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TemporalPrecisionEnum.java
@@ -46,6 +46,13 @@ public enum TemporalPrecisionEnum {
return DateUtils.addDays(theInput, theAmount);
}
},
+ MINUTE(Calendar.MINUTE) {
+ @Override
+ public Date add(Date theInput, int theAmount) {
+ return DateUtils.addMinutes(theInput, theAmount);
+ }
+
+ },
SECOND(Calendar.SECOND) {
@Override
public Date add(Date theInput, int theAmount) {
@@ -58,7 +65,7 @@ public enum TemporalPrecisionEnum {
public Date add(Date theInput, int theAmount) {
return DateUtils.addMilliseconds(theInput, theAmount);
}
- },
+ },
;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
index 164acfa6ca9..45c018f5798 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
@@ -68,6 +68,8 @@ public abstract class BaseDateTimeDt extends BasePrimitive {
private static final FastDateFormat ourHumanDateFormat = FastDateFormat.getDateInstance(FastDateFormat.MEDIUM);
private static final Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
private static final Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
+ private static final FastDateFormat ourYearMonthDayTimeMinsFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm");
+ private static final FastDateFormat ourYearMonthDayTimeMinsZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmZZ");
static {
ArrayList formatters = new ArrayList();
@@ -185,36 +187,40 @@ public abstract class BaseDateTimeDt extends BasePrimitive {
if (theValue == null) {
return null;
} else {
+ GregorianCalendar cal;
+ if (myTimeZoneZulu) {
+ cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+ } else if (myTimeZone != null) {
+ cal = new GregorianCalendar(myTimeZone);
+ } else {
+ cal = new GregorianCalendar();
+ }
+ cal.setTime(theValue);
+
switch (myPrecision) {
case DAY:
- return ourYearMonthDayFormat.format(theValue);
+ return ourYearMonthDayFormat.format(cal);
case MONTH:
- return ourYearMonthFormat.format(theValue);
+ return ourYearMonthFormat.format(cal);
case YEAR:
- return ourYearFormat.format(theValue);
+ return ourYearFormat.format(cal);
+ case MINUTE:
+ if (myTimeZoneZulu) {
+ return ourYearMonthDayTimeMinsFormat.format(cal) + "Z";
+ } else {
+ return ourYearMonthDayTimeMinsZoneFormat.format(cal);
+ }
case SECOND:
if (myTimeZoneZulu) {
- GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
- cal.setTime(theValue);
return ourYearMonthDayTimeFormat.format(cal) + "Z";
- } else if (myTimeZone != null) {
- GregorianCalendar cal = new GregorianCalendar(myTimeZone);
- cal.setTime(theValue);
- return ourYearMonthDayTimeZoneFormat.format(cal);
} else {
- return ourYearMonthDayTimeFormat.format(theValue);
+ return ourYearMonthDayTimeZoneFormat.format(cal);
}
case MILLI:
if (myTimeZoneZulu) {
- GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
- cal.setTime(theValue);
return ourYearMonthDayTimeMilliFormat.format(cal) + "Z";
- } else if (myTimeZone != null) {
- GregorianCalendar cal = new GregorianCalendar(myTimeZone);
- cal.setTime(theValue);
- return ourYearMonthDayTimeMilliZoneFormat.format(cal);
} else {
- return ourYearMonthDayTimeMilliFormat.format(theValue);
+ return ourYearMonthDayTimeMilliZoneFormat.format(cal);
}
}
throw new IllegalStateException("Invalid precision (this is a HAPI bug, shouldn't happen): " + myPrecision);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DateDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DateDt.java
index fa8b645f73a..8b533aa2c86 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DateDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DateDt.java
@@ -1,5 +1,7 @@
package ca.uhn.fhir.model.primitive;
+import java.util.Calendar;
+
/*
* #%L
* HAPI FHIR - Core Library
@@ -21,6 +23,8 @@ package ca.uhn.fhir.model.primitive;
*/
import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
@@ -34,6 +38,17 @@ import ca.uhn.fhir.parser.DataFormatException;
* {@link TemporalPrecisionEnum#MONTH}
* {@link TemporalPrecisionEnum#DAY}
*
+ *
+ *
+ * Note on using Java Date objects: This type stores the date as a Java Date. Note that
+ * the Java Date has more precision (millisecond precision), and does not store a timezone. As such,
+ * it could potentially cause issues. For example, if a Date contains the number of milliseconds at
+ * midnight in a timezone across the date line from your location, it might refer to a different date than
+ * intended.
+ *
+ *
+ * As such, it is recommended to use the Calendar or int,int,int
constructors
+ *
*/
@DatatypeDef(name = "date")
public class DateDt extends BaseDateTimeDt {
@@ -51,7 +66,17 @@ public class DateDt extends BaseDateTimeDt {
}
/**
- * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type
+ * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
+ */
+ public DateDt(Calendar theCalendar) {
+ super(theCalendar.getTime(), DEFAULT_PRECISION);
+ setTimeZone(theCalendar.getTimeZone());
+ }
+
+ /**
+ * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
+ * Please see the note on timezones on the {@link DateDt class documentation} for considerations
+ * when using this constructor!
*/
@SimpleSetter(suffix = "WithDayPrecision")
public DateDt(@SimpleSetter.Parameter(name = "theDate") Date theDate) {
@@ -65,6 +90,8 @@ public class DateDt extends BaseDateTimeDt {
* {@link TemporalPrecisionEnum#MONTH}
* {@link TemporalPrecisionEnum#DAY}
*
+ * Please see the note on timezones on the {@link DateDt class documentation} for considerations
+ * when using this constructor!
*
* @throws DataFormatException
* If the specified precision is not allowed for this type
@@ -74,6 +101,17 @@ public class DateDt extends BaseDateTimeDt {
super(theDate, thePrecision);
}
+ /**
+ * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
+ *
+ * @param theYear The year, e.g. 2015
+ * @param theMonth The month, e.g. 0 for January
+ * @param theDay The day (1 indexed) e.g. 1 for the first day of the month
+ */
+ public DateDt(int theYear, int theMonth, int theDay) {
+ this(toCalendarZulu(theYear, theMonth, theDay));
+ }
+
/**
* Constructor which accepts a date as a string in FHIR format
*
@@ -84,6 +122,16 @@ public class DateDt extends BaseDateTimeDt {
super(theDate);
}
+ /**
+ * Returns the default precision for this datatype
+ *
+ * @see #DEFAULT_PRECISION
+ */
+ @Override
+ protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
+ return DEFAULT_PRECISION;
+ }
+
@Override
boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
switch (thePrecision) {
@@ -96,14 +144,12 @@ public class DateDt extends BaseDateTimeDt {
}
}
- /**
- * Returns the default precision for this datatype
- *
- * @see #DEFAULT_PRECISION
- */
- @Override
- protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
- return DEFAULT_PRECISION;
+ private static GregorianCalendar toCalendarZulu(int theYear, int theMonth, int theDay) {
+ GregorianCalendar retVal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+ retVal.set(Calendar.YEAR, theYear);
+ retVal.set(Calendar.MONTH, theMonth);
+ retVal.set(Calendar.DATE, theDay);
+ return retVal;
}
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu21Config.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu21Config.java
index 9263c171dde..0aa24e4ab05 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu21Config.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestDstu21Config.java
@@ -62,6 +62,7 @@ public class TestDstu21Config extends BaseJavaConfigDstu21 {
extraProperties.put("hibernate.search.default.directory_provider" ,"filesystem");
extraProperties.put("hibernate.search.default.indexBase", "target/lucene_index_dstu21");
extraProperties.put("hibernate.search.lucene_version","LUCENE_CURRENT");
+ extraProperties.put("hibernate.search.autoregister_listeners", "true");
return extraProperties;
}
diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/BaseDateTimeType.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/BaseDateTimeType.java
index d361551b3a9..74345103c65 100644
--- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/BaseDateTimeType.java
+++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/BaseDateTimeType.java
@@ -126,51 +126,43 @@ public abstract class BaseDateTimeType extends PrimitiveType {
if (theValue == null) {
return null;
} else {
+ GregorianCalendar cal;
+ if (myTimeZoneZulu) {
+ cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+ } else if (myTimeZone != null) {
+ cal = new GregorianCalendar(myTimeZone);
+ } else {
+ cal = new GregorianCalendar();
+ }
+ cal.setTime(theValue);
+
switch (myPrecision) {
case DAY:
- return ourYearMonthDayFormat.format(theValue);
+ return ourYearMonthDayFormat.format(cal);
case MONTH:
- return ourYearMonthFormat.format(theValue);
+ return ourYearMonthFormat.format(cal);
case YEAR:
- return ourYearFormat.format(theValue);
+ return ourYearFormat.format(cal);
case MINUTE:
if (myTimeZoneZulu) {
- GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
- cal.setTime(theValue);
return ourYearMonthDayTimeMinsFormat.format(cal) + "Z";
- } else if (myTimeZone != null) {
- GregorianCalendar cal = new GregorianCalendar(myTimeZone);
- cal.setTime(theValue);
- return (ourYearMonthDayTimeMinsZoneFormat.format(cal));
} else {
- return ourYearMonthDayTimeMinsFormat.format(theValue);
+ return ourYearMonthDayTimeMinsZoneFormat.format(cal);
}
case SECOND:
if (myTimeZoneZulu) {
- GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
- cal.setTime(theValue);
return ourYearMonthDayTimeFormat.format(cal) + "Z";
- } else if (myTimeZone != null) {
- GregorianCalendar cal = new GregorianCalendar(myTimeZone);
- cal.setTime(theValue);
- return (ourYearMonthDayTimeZoneFormat.format(cal));
} else {
- return ourYearMonthDayTimeFormat.format(theValue);
+ return ourYearMonthDayTimeZoneFormat.format(cal);
}
case MILLI:
if (myTimeZoneZulu) {
- GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
- cal.setTime(theValue);
return ourYearMonthDayTimeMilliFormat.format(cal) + "Z";
- } else if (myTimeZone != null) {
- GregorianCalendar cal = new GregorianCalendar(myTimeZone);
- cal.setTime(theValue);
- return (ourYearMonthDayTimeMilliZoneFormat.format(cal));
} else {
- return ourYearMonthDayTimeMilliFormat.format(theValue);
+ return ourYearMonthDayTimeMilliZoneFormat.format(cal);
}
}
- throw new IllegalStateException("Invalid precision (this is a bug, shouldn't happen): " + myPrecision);
+ throw new IllegalStateException("Invalid precision (this is a HAPI bug, shouldn't happen): " + myPrecision);
}
}
diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/DateType.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/DateType.java
index d60d34c645b..e84076d1fbd 100644
--- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/DateType.java
+++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/model/DateType.java
@@ -29,11 +29,14 @@ POSSIBILITY OF SUCH DAMAGE.
package org.hl7.fhir.dstu21.model;
+import java.util.Calendar;
+
/**
* Primitive type "date" in FHIR: any day in a gregorian calendar
*/
import java.util.Date;
+import java.util.GregorianCalendar;
import java.util.TimeZone;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
@@ -95,6 +98,33 @@ public class DateType extends BaseDateTimeType {
super(theDate);
}
+ /**
+ * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
+ */
+ public DateType(Calendar theCalendar) {
+ super(theCalendar.getTime(), DEFAULT_PRECISION);
+ setTimeZone(theCalendar.getTimeZone());
+ }
+
+ /**
+ * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
+ *
+ * @param theYear The year, e.g. 2015
+ * @param theMonth The month, e.g. 0 for January
+ * @param theDay The day (1 indexed) e.g. 1 for the first day of the month
+ */
+ public DateType(int theYear, int theMonth, int theDay) {
+ this(toCalendarZulu(theYear, theMonth, theDay));
+ }
+
+ private static GregorianCalendar toCalendarZulu(int theYear, int theMonth, int theDay) {
+ GregorianCalendar retVal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+ retVal.set(Calendar.YEAR, theYear);
+ retVal.set(Calendar.MONTH, theMonth);
+ retVal.set(Calendar.DATE, theDay);
+ return retVal;
+ }
+
@Override
boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
switch (thePrecision) {
diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/BaseDateTimeTypeDstu21Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/BaseDateTimeTypeDstu21Test.java
new file mode 100644
index 00000000000..353036aafb2
--- /dev/null
+++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/BaseDateTimeTypeDstu21Test.java
@@ -0,0 +1,105 @@
+package ca.uhn.fhir.model;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.hl7.fhir.dstu21.model.DateTimeType;
+import org.hl7.fhir.dstu21.model.DateType;
+import org.hl7.fhir.dstu21.model.TemporalPrecisionEnum;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class BaseDateTimeTypeDstu21Test {
+ private static Locale ourDefaultLocale;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseDateTimeTypeDstu21Test.class);
+ private SimpleDateFormat myDateInstantParser;
+
+ @Before
+ public void before() {
+ myDateInstantParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ }
+
+ /**
+ * See HAPI #101 - https://github.com/jamesagnew/hapi-fhir/issues/101
+ */
+ @Test
+ public void testPrecisionRespectedForSetValue() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(myDateInstantParser.parse("2012-01-02 22:31:02.333"));
+ cal.setTimeZone(TimeZone.getTimeZone("EST"));
+
+ Date time = cal.getTime();
+
+ DateType date = new DateType();
+ date.setValue(time);
+ assertEquals("2012-01-02", date.getValueAsString());
+ }
+
+ @Test
+ public void testMinutePrecisionEncode() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ cal.set(1990, Calendar.JANUARY, 3, 3, 22, 11);
+
+ DateTimeType date = new DateTimeType();
+ date.setValue(cal.getTime(), TemporalPrecisionEnum.MINUTE);
+ date.setTimeZone(TimeZone.getTimeZone("EST"));
+ assertEquals("1990-01-02T21:22-05:00", date.getValueAsString());
+
+ date.setTimeZoneZulu(true);
+ assertEquals("1990-01-03T02:22Z", date.getValueAsString());
+ }
+
+ /**
+ * See HAPI #101 - https://github.com/jamesagnew/hapi-fhir/issues/101
+ */
+ @Test
+ public void testPrecisionRespectedForSetValueWithPrecision() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(myDateInstantParser.parse("2012-01-02 22:31:02.333"));
+ cal.setTimeZone(TimeZone.getTimeZone("EST"));
+
+ Date time = cal.getTime();
+
+ DateType date = new DateType();
+ date.setValue(time, TemporalPrecisionEnum.DAY);
+ assertEquals("2012-01-02", date.getValueAsString());
+ }
+
+ @Test
+ public void testToHumanDisplay() {
+ DateTimeType dt = new DateTimeType("2012-01-05T12:00:00-08:00");
+ String human = dt.toHumanDisplay();
+ ourLog.info(human);
+ assertThat(human, containsString("2012"));
+ assertThat(human, containsString("12"));
+ }
+
+ public static void afterClass() {
+ Locale.setDefault(ourDefaultLocale);
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ /*
+ * We cache the default locale, but temporarily set it to a random value during this test. This helps ensure
+ * that there are no language specific dependencies in the test.
+ */
+ ourDefaultLocale = Locale.getDefault();
+
+ Locale[] available = { Locale.CANADA, Locale.GERMANY, Locale.TAIWAN };
+ Locale newLocale = available[(int) (Math.random() * available.length)];
+ Locale.setDefault(newLocale);
+
+ ourLog.info("Tests are running in locale: " + newLocale.getDisplayName());
+ }
+
+}
diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/DateTypeTest.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/DateTypeTest.java
new file mode 100644
index 00000000000..de6602de2d8
--- /dev/null
+++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/model/DateTypeTest.java
@@ -0,0 +1,52 @@
+package ca.uhn.fhir.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.hl7.fhir.dstu21.model.DateType;
+import org.junit.Test;
+
+public class DateTypeTest {
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DateTypeTest.class);
+
+ @Test
+ public void testPrecision() {
+
+// ourLog.info(""+ new TreeSet(Arrays.asList(TimeZone.getAvailableIDs())));
+
+ final Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("GMT"));
+ cal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
+ ourLog.info("Time: {}", cal); // 631152000775
+
+ DateType dateDt = new DateType(cal.getTime());
+ long time = dateDt.getValue().getTime();
+ ourLog.info("Time: {}", time); // 631152000775
+ ourLog.info("Time: {}", dateDt.getValue()); // 631152000775
+
+ dateDt.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ time = dateDt.getValue().getTime();
+ ourLog.info("Time: {}", time); // 631152000775
+ ourLog.info("Time: {}", dateDt.getValue()); // 631152000775
+
+ String valueAsString = dateDt.getValueAsString();
+ ourLog.info(valueAsString);
+ // is 631152000030
+
+ }
+
+ @Test
+ public void testConstructors() {
+ final Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ cal.set(1990, Calendar.JANUARY, 5, 0, 0, 0);
+ DateType dateDt = new DateType(cal);
+ assertEquals("1990-01-05", dateDt.getValueAsString());
+
+ dateDt = new DateType(1990, 0, 5);
+ assertEquals("1990-01-05", dateDt.getValueAsString());
+ }
+
+}
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseDateTimeDtDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseDateTimeDtDstu2Test.java
index 88c57b74cba..1fc6b134069 100644
--- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseDateTimeDtDstu2Test.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/BaseDateTimeDtDstu2Test.java
@@ -41,6 +41,21 @@ public class BaseDateTimeDtDstu2Test {
assertEquals("2012-01-02", date.getValueAsString());
}
+ @Test
+ public void testMinutePrecisionEncode() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ cal.set(1990, Calendar.JANUARY, 3, 3, 22, 11);
+
+ DateTimeDt date = new DateTimeDt();
+ date.setValue(cal.getTime(), TemporalPrecisionEnum.MINUTE);
+ date.setTimeZone(TimeZone.getTimeZone("EST"));
+ assertEquals("1990-01-02T21:22-05:00", date.getValueAsString());
+
+ date.setTimeZoneZulu(true);
+ assertEquals("1990-01-03T02:22Z", date.getValueAsString());
+ }
+
/**
* See HAPI #101 - https://github.com/jamesagnew/hapi-fhir/issues/101
*/
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
index cd86a67ad19..f2b8be5fce0 100644
--- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/model/primitive/DateDtTest.java
@@ -1,5 +1,7 @@
package ca.uhn.fhir.model.primitive;
+import static org.junit.Assert.assertEquals;
+
import java.util.Arrays;
import java.util.Calendar;
import java.util.TimeZone;
@@ -36,4 +38,18 @@ public class DateDtTest {
}
+ @Test
+ public void testConstructors() {
+ final Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
+ cal.set(1990, Calendar.JANUARY, 5, 0, 0, 0);
+ DateDt dateDt = new DateDt(cal);
+ assertEquals("1990-01-05", dateDt.getValueAsString());
+
+ dateDt = new DateDt(1990, 0, 5);
+ assertEquals("1990-01-05", dateDt.getValueAsString());
+ }
+
+
+
}
diff --git a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java
index 8cf4553db21..d8bfecdb5cd 100644
--- a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java
+++ b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java
@@ -109,7 +109,6 @@ public class Controller extends BaseController {
return "result";
}
- @SuppressWarnings("unchecked")
@RequestMapping(value = { "/delete" })
public String actionDelete(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theReq, theRequest, theModel);
From 1ba03f4a9b445c198ca67cd71716ff5a92ffc912 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Wed, 20 Jan 2016 08:11:03 -0500
Subject: [PATCH 4/4] Fix #283 - Remove servlet 3.0 dependency where possible
---
hapi-deployable-pom/pom.xml | 10 ++---
.../uhn/fhir/rest/server/RestfulServer.java | 8 ++++
hapi-fhir-structures-dstu/pom.xml | 7 ++-
.../provider/ServerConformanceProvider.java | 3 +-
hapi-fhir-structures-dstu2.1/pom.xml | 8 +++-
.../server/ServerConformanceProvider.java | 43 ++++++++++---------
hapi-fhir-structures-dstu2/pom.xml | 7 ++-
.../dstu2/ServerConformanceProvider.java | 2 +-
hapi-fhir-structures-hl7org-dstu2/pom.xml | 9 +++-
src/changes/changes.xml | 6 +++
10 files changed, 69 insertions(+), 34 deletions(-)
diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml
index c4b5272e89f..b8cdd8f1332 100644
--- a/hapi-deployable-pom/pom.xml
+++ b/hapi-deployable-pom/pom.xml
@@ -1,5 +1,4 @@
-
+
4.0.0
@@ -14,6 +13,9 @@
HAPI FHIR - Deployable Artifact Parent POM
+
+
+
@@ -53,7 +55,6 @@
org.apache.maven.plugins
maven-project-info-reports-plugin
- ${maven_project_info_plugin_version}
true
@@ -61,7 +62,6 @@
org.apache.maven.plugins
maven-javadoc-plugin
- ${maven_javadoc_plugin_version}
default
@@ -110,7 +110,6 @@
org.apache.maven.plugins
maven-source-plugin
- ${maven_source_plugin_version}
package
@@ -123,7 +122,6 @@
org.codehaus.mojo
license-maven-plugin
- ${maven_license_plugin_version}
first
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 9321d752cd0..42d61e7fd2d 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
@@ -80,6 +80,12 @@ import ca.uhn.fhir.util.VersionUtil;
public class RestfulServer extends HttpServlet implements IRestfulServer {
+ /**
+ * Requests will have an HttpServletRequest attribute set with this name, containing the servlet
+ * context, in order to avoid a dependency on Servlet-API 3.0+
+ */
+ public static final String SERVLET_CONTEXT_ATTRIBUTE = "ca.uhn.fhir.rest.server.RestfulServer.servlet_context";
+
/**
* Default setting for {@link #setETagSupport(ETagSupportEnum) ETag Support}: {@link ETagSupportEnum#ENABLED}
*/
@@ -517,6 +523,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer1.4-SNAPSHOT
+
javax.servlet
- javax.servlet-api
+ servlet-api
+ 2.5
provided
diff --git a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java
index 0d509c2c204..ccf5d71bc52 100644
--- a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java
+++ b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java
@@ -36,7 +36,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
-import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestQuery;
@@ -156,7 +155,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider1.4-SNAPSHOT
test
+
+
javax.servlet
- javax.servlet-api
+ servlet-api
+ 2.5
provided
diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/hapi/rest/server/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/hapi/rest/server/ServerConformanceProvider.java
index 31955d8e6ee..0fd2b658f59 100644
--- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/hapi/rest/server/ServerConformanceProvider.java
+++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu21/hapi/rest/server/ServerConformanceProvider.java
@@ -85,8 +85,10 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
* Server FHIR Provider which serves the conformance statement for a RESTful server implementation
*
*
- * Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is always returned unless {@link #setCache(boolean)} is called with a value of
- * false
. This means that if you are adding anything to the returned conformance instance on each call you should call setCache(false)
in your provider constructor.
+ * Note: This class is safe to extend, but it is important to note that the same instance of {@link Conformance} is
+ * always returned unless {@link #setCache(boolean)} is called with a value of false
. This means that if
+ * you are adding anything to the returned conformance instance on each call you should call
+ * setCache(false)
in your provider constructor.
*
*/
public class ServerConformanceProvider implements IServerConformanceProvider {
@@ -101,22 +103,20 @@ public class ServerConformanceProvider implements IServerConformanceProvider includes = new TreeSet();
@@ -441,7 +443,7 @@ public class ServerConformanceProvider implements IServerConformanceProvidertest
+
javax.servlet
- javax.servlet-api
+ servlet-api
+ 2.5
provided
diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java
index 88293628b53..6262181a546 100644
--- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java
+++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java
@@ -206,7 +206,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider1.4-SNAPSHOT
test
+
+
javax.servlet
- javax.servlet-api
+ servlet-api
+ 2.5
provided
-
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b401982b527..adde6698c15 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -139,6 +139,12 @@
implementations and wasn't compatible
with coming changes to that API.
+
+ Remove dependency on Servlet-API 3.0+ by using methods available in 2.5 where possible.
+ Note that we continue to use Servlet-API 3.0+ features in some parts of the JPA API, so
+ running in an old serlvet container should be tested well before use. Thanks to Bill Denton
+ for reporting!
+