From 65dc9e85b730b372b223281b803d3b04839c2886 Mon Sep 17 00:00:00 2001 From: jkv Date: Tue, 14 Feb 2017 08:01:44 +0100 Subject: [PATCH 01/31] Work in progress bringing SSE to FHIR --- example-projects/hapi-fhir-jaxrs-sse/pom.xml | 91 ++++++++++++ .../example/JaxRsPatientProvider.java | 122 ++++++++++++++++ .../example/jerseyguice/GuiceHk2Helper.java | 132 ++++++++++++++++++ .../GuiceJersey2ServletContextListener.java | 97 +++++++++++++ .../src/main/webapp/WEB-INF/web.xml | 22 +++ .../src/test/java/test/WarTester.java | 14 ++ 6 files changed, 478 insertions(+) create mode 100644 example-projects/hapi-fhir-jaxrs-sse/pom.xml create mode 100644 example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java create mode 100644 example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceHk2Helper.java create mode 100644 example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java create mode 100644 example-projects/hapi-fhir-jaxrs-sse/src/main/webapp/WEB-INF/web.xml create mode 100644 example-projects/hapi-fhir-jaxrs-sse/src/test/java/test/WarTester.java diff --git a/example-projects/hapi-fhir-jaxrs-sse/pom.xml b/example-projects/hapi-fhir-jaxrs-sse/pom.xml new file mode 100644 index 00000000000..c4c26d8e718 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + + ca.uhn.hapi.fhir + hapi-fhir + 2.3-SNAPSHOT + ../hapi-deployable-pom/pom.xml + + hapi-fhir-jaxrs-sse + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + org.eclipse.jetty + jetty-servlet + + + org.eclipse.jetty + jetty-webapp + + + + org.ebaysf.web + cors-filter + 1.0.1 + + + + org.glassfish.jersey.media + jersey-media-sse + ${jersey_version} + + + org.glassfish.jersey.containers + jersey-container-servlet + ${jersey_version} + + + ca.uhn.hapi.fhir + hapi-fhir-jaxrsserver-base + ${project.version} + + + org.slf4j + slf4j-simple + 1.7.21 + + + org.slf4j + jul-to-slf4j + 1.7.21 + + + org.slf4j + slf4j-api + 1.7.21 + + + + org.glassfish.hk2 + hk2-locator + 2.4.0-b34 + + + org.glassfish.hk2 + guice-bridge + 2.4.0-b34 + + + com.google.guava + guava + 21.0 + + + com.google.inject.extensions + guice-servlet + 4.1.0 + + + + diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java new file mode 100644 index 00000000000..7f27f1632a7 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java @@ -0,0 +1,122 @@ +package embedded.example; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.glassfish.jersey.media.sse.EventOutput; +import org.glassfish.jersey.media.sse.OutboundEvent; +import org.glassfish.jersey.media.sse.SseBroadcaster; +import org.glassfish.jersey.media.sse.SseFeature; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.Patient; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider; +import ca.uhn.fhir.rest.annotation.ConditionalUrlParam; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.RequiredParam; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.param.StringParam; +import ca.uhn.fhir.rest.server.Constants; +import ca.uhn.fhir.rest.server.ETagSupportEnum; +import jersey.repackaged.com.google.common.collect.Maps; + +@Singleton +@Path("Patient") +@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML }) +public class JaxRsPatientProvider extends AbstractJaxRsResourceProvider { + + private final Map patients = Maps.newConcurrentMap(); + private final SseBroadcaster broadcaster = new SseBroadcaster(); + + @Inject + public JaxRsPatientProvider() { + super(FhirContext.forDstu3(), JaxRsPatientProvider.class); + + new Thread() { + @Override + public void run() { + try { + while (true) { + Thread.sleep(1000); + final int id = patients.size() + 1; + final Patient p = new Patient(); + final Identifier i = new Identifier(); + i.setValue(id + ""); + p.addName().setFamily("John " + i); + p.getIdentifier().add(i); + p.setId(new IdType(id)); + patients.put(id + "", p); + + + broadcaster.broadcast(new OutboundEvent.Builder().name("patients").data(String.class, patients.size() + "").build()); + } + + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + } + + @Search + public List search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) { + final List result = new LinkedList(); + for (final Patient patient : patients.values()) { + Patient single = null; + if (name == null || patient.getName().get(0).getFamilyElement().getValueNotNull() + .equals(name.getValueNotNull())) { + single = patient; + } + if (single != null) { + result.add(single); + } + } + return result; + } + + @Create + public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam final String theConditional) + throws Exception { + + patients.put(patient.getIdentifierFirstRep().getId(), patient); + final MethodOutcome result = new MethodOutcome().setCreated(true); + result.setResource(patient); + result.setId(new IdType(patient.getId())); + return result; + } + + @Override + public ETagSupportEnum getETagSupport() { + return ETagSupportEnum.DISABLED; + } + + @Override + public Class getResourceType() { + return Patient.class; + } + + + @GET + @Path("listen") + @Produces(SseFeature.SERVER_SENT_EVENTS) + public EventOutput listenToBroadcast() throws IOException { + final EventOutput eventOutput = new EventOutput(); + eventOutput.write( + new OutboundEvent.Builder().name("patient count").data(String.class, patients.size() + "").build()); + this.broadcaster.add(eventOutput); + return eventOutput; + } +} diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceHk2Helper.java b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceHk2Helper.java new file mode 100644 index 00000000000..81743ff9242 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceHk2Helper.java @@ -0,0 +1,132 @@ +package embedded.example.jerseyguice; + +import java.net.URL; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.spi.Container; +import org.glassfish.jersey.server.spi.ContainerLifecycleListener; +import org.glassfish.jersey.servlet.ServletContainer; +import org.jvnet.hk2.guice.bridge.api.GuiceBridge; +import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.inject.Injector; +import com.google.inject.Scopes; +import com.google.inject.servlet.ServletModule; + +public abstract class GuiceHk2Helper extends ServletModule { + private static final Logger log = LoggerFactory.getLogger(GuiceHk2Helper.class); + + @Override + abstract protected void configureServlets(); + + public interface RestKeyBindingBuilder { + void packages(String... packages); + + void packages(Package... packages); + + void packages(Class... clazz); + } + + protected RestKeyBindingBuilder rest(final String... urlPatterns) { + return new RestKeyBindingBuilderImpl(Arrays.asList(urlPatterns)); + } + + private class RestKeyBindingBuilderImpl implements RestKeyBindingBuilder { + List paths; + + public RestKeyBindingBuilderImpl(final List paths) { + this.paths = paths; + } + + private boolean checkIfPackageExistsAndLog(final String packge) { + boolean exists = false; + final String resourcePath = packge.replace(".", "/"); + final URL resource = getClass().getClassLoader().getResource(resourcePath); + if (resource != null) { + exists = true; + log.info("rest(" + paths + ").packages(" + packge + ")"); + } else { + log.info("No Beans in '" + packge + "' found. Requests " + paths + " will fail."); + } + return exists; + } + + @Override + public void packages(final String... packages) { + final StringBuilder sb = new StringBuilder(); + + for (final String pkg : packages) { + if (sb.length() > 0) { + sb.append(','); + } + checkIfPackageExistsAndLog(pkg); + sb.append(pkg); + } + final Map params = new HashMap<>(); + params.put("javax.ws.rs.Application", GuiceResourceConfig.class.getCanonicalName()); + if (sb.length() > 0) { + params.put("jersey.config.server.provider.packages", sb.toString()); + } + bind(ServletContainer.class).in(Scopes.SINGLETON); + for (final String path : paths) { + serve(path).with(ServletContainer.class, params); + } + } + + @Override + public void packages(final Package... packages) { + packages(FluentIterable.from(packages).transform(new Function() { + + @Override + public String apply(final Package arg0) { + return arg0.getName(); + } + }).toArray(String.class)); + } + + @Override + public void packages(final Class... clazz) { + packages(FluentIterable.from(clazz).transform(new Function, String>() { + + @Override + public String apply(final Class arg0) { + return arg0.getPackage().getName(); + } + }).toArray(String.class)); + } + } +} + +class GuiceResourceConfig extends ResourceConfig { + public GuiceResourceConfig() { + register(new ContainerLifecycleListener() { + @Override + public void onStartup(final Container container) { + final ServletContainer servletContainer = (ServletContainer) container; + final ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator(); + GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator); + final GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class); + final Injector injector = (Injector) servletContainer.getServletContext() + .getAttribute(Injector.class.getName()); + guiceBridge.bridgeGuiceInjector(injector); + } + + @Override + public void onReload(final Container container) { + } + + @Override + public void onShutdown(final Container container) { + } + }); + } +} \ No newline at end of file diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java new file mode 100644 index 00000000000..77fe796bf38 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016 Aberger Software GmbH. All Rights Reserved. + * http://www.aberger.at + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You may + * obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package embedded.example.jerseyguice; + +import java.awt.Desktop; +import java.net.URI; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.DispatcherType; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.hl7.fhir.dstu3.model.HumanName; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Patient; +import org.slf4j.bridge.SLF4JBridgeHandler; + +import com.google.common.collect.Lists; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; +import com.google.inject.Scopes; +import com.google.inject.Stage; +import com.google.inject.name.Names; +import com.google.inject.servlet.GuiceFilter; +import com.google.inject.servlet.GuiceServletContextListener; + +import embedded.example.JaxRsPatientProvider; + +public class GuiceJersey2ServletContextListener extends GuiceServletContextListener { + + @Override + protected Injector getInjector() { + + final List modules = Lists.newArrayList(); + + modules.add(new AbstractModule() { + + @Override + protected void configure() { + final ConcurrentHashMap> patients = new ConcurrentHashMap>(); + for (int i = 0; i < 20; i++) { + + final Patient patient = new Patient(); + patient.getName().add(new HumanName().setFamily("Random Patient " + i)); + patient.setId(new IdType("Patient", "" + i, "" + 1)); + patients.put(String.valueOf(i), Lists.newArrayList(patient)); + + } + } + }); + + modules.add(new GuiceHk2Helper() { + @Override + protected void configureServlets() { + bind(String.class).annotatedWith(Names.named("1")).toInstance("sad"); + + bind(JaxRsPatientProvider.class).in(Scopes.SINGLETON); + rest("/*").packages(JaxRsPatientProvider.class); + } + }); + return Guice.createInjector(Stage.PRODUCTION, modules); + } + + public static void main(final String[] args) throws Exception { + + SLF4JBridgeHandler.removeHandlersForRootLogger(); + SLF4JBridgeHandler.install(); + + final Server server = new Server(8080); + + final ServletContextHandler sch = new ServletContextHandler(server, "/"); + sch.addEventListener(new GuiceJersey2ServletContextListener()); + sch.addFilter(GuiceFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + server.start(); + + Desktop.getDesktop().browse(new URI("http://localhost:8080/Patient")); + } +} \ No newline at end of file diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/webapp/WEB-INF/web.xml b/example-projects/hapi-fhir-jaxrs-sse/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..8c985e61d0c --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + Guice Filter + com.google.inject.servlet.GuiceFilter + + + Guice Filter + /* + + + embedded.example.ContextListener + + + + + serverAddress + http://fhirtest.uhn.ca/baseDstu2 + + \ No newline at end of file diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/test/java/test/WarTester.java b/example-projects/hapi-fhir-jaxrs-sse/src/test/java/test/WarTester.java new file mode 100644 index 00000000000..fffbc626c75 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/src/test/java/test/WarTester.java @@ -0,0 +1,14 @@ +package test; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; + +public class WarTester { + + public static void main(String[] args) throws Exception { + final Server server = new Server(8080); + server.setHandler(new WebAppContext("target/fhirtester.war", "/")); + server.start(); + } + +} From 2cb3aaa2a16ea59bfcbdf6e0d4a2266f5671c1ac Mon Sep 17 00:00:00 2001 From: jkv Date: Tue, 7 Mar 2017 22:45:49 +0100 Subject: [PATCH 02/31] =?UTF-8?q?=E2=80=98Spring=20cleaning=20=E2=80=A6.?= =?UTF-8?q?=20=E2=80=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/JaxRsPatientProvider.java | 75 ++++++++++--------- .../GuiceJersey2ServletContextListener.java | 28 +------ 2 files changed, 43 insertions(+), 60 deletions(-) diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java index 7f27f1632a7..eace4ee0df9 100644 --- a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/JaxRsPatientProvider.java @@ -16,12 +16,13 @@ import org.glassfish.jersey.media.sse.EventOutput; import org.glassfish.jersey.media.sse.OutboundEvent; import org.glassfish.jersey.media.sse.SseBroadcaster; import org.glassfish.jersey.media.sse.SseFeature; +import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; import org.hl7.fhir.dstu3.model.IdType; -import org.hl7.fhir.dstu3.model.Identifier; import org.hl7.fhir.dstu3.model.Patient; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jaxrs.server.AbstractJaxRsResourceProvider; +import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.annotation.ConditionalUrlParam; import ca.uhn.fhir.rest.annotation.Create; import ca.uhn.fhir.rest.annotation.RequiredParam; @@ -44,42 +45,17 @@ public class JaxRsPatientProvider extends AbstractJaxRsResourceProvider @Inject public JaxRsPatientProvider() { super(FhirContext.forDstu3(), JaxRsPatientProvider.class); - - new Thread() { - @Override - public void run() { - try { - while (true) { - Thread.sleep(1000); - final int id = patients.size() + 1; - final Patient p = new Patient(); - final Identifier i = new Identifier(); - i.setValue(id + ""); - p.addName().setFamily("John " + i); - p.getIdentifier().add(i); - p.setId(new IdType(id)); - patients.put(id + "", p); - - - broadcaster.broadcast(new OutboundEvent.Builder().name("patients").data(String.class, patients.size() + "").build()); - } - - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); } - + @Search public List search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) { final List result = new LinkedList(); for (final Patient patient : patients.values()) { Patient single = null; - if (name == null || patient.getName().get(0).getFamilyElement().getValueNotNull() - .equals(name.getValueNotNull())) { - single = patient; - } + if (name == null + || patient.getName().get(0).getFamilyElement().getValueNotNull().equals(name.getValueNotNull())) { + single = patient; + } if (single != null) { result.add(single); } @@ -91,13 +67,42 @@ public class JaxRsPatientProvider extends AbstractJaxRsResourceProvider public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam final String theConditional) throws Exception { - patients.put(patient.getIdentifierFirstRep().getId(), patient); + storePatient(patient); + final MethodOutcome result = new MethodOutcome().setCreated(true); result.setResource(patient); result.setId(new IdType(patient.getId())); return result; } + // Conceptual wrapper for storing in a db + private void storePatient(final Patient patient) { + + try { + patients.put(patient.getIdentifierFirstRep().getValue(), patient); + // if storing is successful the notify the listeners that listens on + // any patient => patient/* + + final String bundleToString = currentPatientsAsJsonString(); + + broadcaster + .broadcast(new OutboundEvent.Builder().name("patients").data(String.class, bundleToString).build()); + + } catch (final Exception e) { + e.printStackTrace(); + } + + } + + private String currentPatientsAsJsonString() { + final IParser jsonParser = this.getFhirContext().newJsonParser().setPrettyPrint(true); + final org.hl7.fhir.dstu3.model.Bundle bundle = new org.hl7.fhir.dstu3.model.Bundle(); + for (final Patient p : patients.values()) + bundle.addEntry(new BundleEntryComponent().setResource(p)); + final String bundleToString = jsonParser.encodeResourceToString(bundle); + return bundleToString; + } + @Override public ETagSupportEnum getETagSupport() { return ETagSupportEnum.DISABLED; @@ -108,14 +113,16 @@ public class JaxRsPatientProvider extends AbstractJaxRsResourceProvider return Patient.class; } - @GET @Path("listen") @Produces(SseFeature.SERVER_SENT_EVENTS) public EventOutput listenToBroadcast() throws IOException { final EventOutput eventOutput = new EventOutput(); + + final String bundleToString = currentPatientsAsJsonString(); + eventOutput.write( - new OutboundEvent.Builder().name("patient count").data(String.class, patients.size() + "").build()); + new OutboundEvent.Builder().name("patients").data(String.class, bundleToString).build()); this.broadcaster.add(eventOutput); return eventOutput; } diff --git a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java index 77fe796bf38..2a2bef0e11e 100644 --- a/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java +++ b/example-projects/hapi-fhir-jaxrs-sse/src/main/java/embedded/example/jerseyguice/GuiceJersey2ServletContextListener.java @@ -21,25 +21,18 @@ import java.awt.Desktop; import java.net.URI; import java.util.EnumSet; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import javax.servlet.DispatcherType; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.hl7.fhir.dstu3.model.HumanName; -import org.hl7.fhir.dstu3.model.IdType; -import org.hl7.fhir.dstu3.model.Patient; import org.slf4j.bridge.SLF4JBridgeHandler; import com.google.common.collect.Lists; -import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; -import com.google.inject.Scopes; import com.google.inject.Stage; -import com.google.inject.name.Names; import com.google.inject.servlet.GuiceFilter; import com.google.inject.servlet.GuiceServletContextListener; @@ -52,28 +45,11 @@ public class GuiceJersey2ServletContextListener extends GuiceServletContextListe final List modules = Lists.newArrayList(); - modules.add(new AbstractModule() { - - @Override - protected void configure() { - final ConcurrentHashMap> patients = new ConcurrentHashMap>(); - for (int i = 0; i < 20; i++) { - - final Patient patient = new Patient(); - patient.getName().add(new HumanName().setFamily("Random Patient " + i)); - patient.setId(new IdType("Patient", "" + i, "" + 1)); - patients.put(String.valueOf(i), Lists.newArrayList(patient)); - - } - } - }); - + modules.add(new GuiceHk2Helper() { @Override protected void configureServlets() { - bind(String.class).annotatedWith(Names.named("1")).toInstance("sad"); - - bind(JaxRsPatientProvider.class).in(Scopes.SINGLETON); +// bind(JaxRsPatientProvider.class).in(Scopes.SINGLETON); rest("/*").packages(JaxRsPatientProvider.class); } }); From 22bda7ff2779b5a5c9b8d0596d49d75e9cc90ac2 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 7 Mar 2017 23:00:26 +0100 Subject: [PATCH 03/31] Create README.md --- example-projects/hapi-fhir-jaxrs-sse/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 example-projects/hapi-fhir-jaxrs-sse/README.md diff --git a/example-projects/hapi-fhir-jaxrs-sse/README.md b/example-projects/hapi-fhir-jaxrs-sse/README.md new file mode 100644 index 00000000000..8c5785931a9 --- /dev/null +++ b/example-projects/hapi-fhir-jaxrs-sse/README.md @@ -0,0 +1,5 @@ +This example sets up a FHIR server that can ship out Server-sent events using standard Jersey 2.x components. Start up the server and eg. issue the following curl request 'curl -v -X GET http://localhost:8080/Patient/listen'. The will block curl and once any events are shipped to the server, they will automatically be sent to the curl client. + +Changes can be sent to the server on localhost:8080/Patient which accepts any kind of patients that has at least one identifier. + +Voila From d6bed58bf027dd7e9a23ff5ecd1054bf632c3a49 Mon Sep 17 00:00:00 2001 From: ANOUSH MOURADIAN Date: Fri, 5 Jan 2018 12:20:30 -0500 Subject: [PATCH 04/31] Adding new module - hapi-fhir-jpaserver-dynamic --- hapi-fhir-jpaserver-dynamic/.README.md.html | 713 +++++ hapi-fhir-jpaserver-dynamic/.gitignore | 129 + hapi-fhir-jpaserver-dynamic/Dockerfile | 4 + hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat | 4 + hapi-fhir-jpaserver-dynamic/README.md | 107 + .../build-docker-image.sh | 5 + hapi-fhir-jpaserver-dynamic/pom.xml | 338 +++ .../uhn/fhir/jpa/demo/FhirServerConfig.java | 106 + .../fhir/jpa/demo/FhirServerConfigCommon.java | 165 ++ .../fhir/jpa/demo/FhirServerConfigDstu2.java | 110 + .../uhn/fhir/jpa/demo/FhirTesterConfig.java | 68 + .../fhir/jpa/demo/FhirTesterConfigDstu2.java | 71 + .../jpa/demo/ImmutablePropertiesConfig.java | 64 + .../ca/uhn/fhir/jpa/demo/JpaServerDemo.java | 159 ++ .../uhn/fhir/jpa/demo/JpaServerDemoDstu2.java | 159 ++ .../main/java/ca/uhn/fhir/jpa/demo/Utils.java | 18 + .../ca/uhn/fhir/jpa/demo/WebInitializer.java | 74 + .../resources/config/dstu2/app_dev.properties | 2 + .../config/dstu2/app_local.properties | 2 + .../config/dstu2/app_prod.properties | 2 + .../resources/config/dstu2/app_stg.properties | 2 + .../config/dstu2/immutable.properties | 6 + .../resources/config/dstu3/app_dev.properties | 2 + .../config/dstu3/app_local.properties | 2 + .../config/dstu3/app_prod.properties | 2 + .../resources/config/dstu3/app_stg.properties | 2 + .../config/dstu3/immutable.properties | 6 + .../src/main/resources/logback.xml | 16 + .../main/webapp/WEB-INF/templates/about.html | 67 + .../webapp/WEB-INF/templates/tmpl-footer.html | 16 + .../WEB-INF/templates/tmpl-home-welcome.html | 52 + .../src/main/webapp/WEB-INF/web-dstu2.xml | 106 + .../src/main/webapp/WEB-INF/web-dstu3.xml | 108 + .../src/main/webapp/WEB-INF/web_notNeeded.xml | 106 + .../src/main/webapp/WEB-INF/xsd/javaee_6.xsd | 2419 +++++++++++++++++ .../src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd | 389 +++ .../main/webapp/WEB-INF/xsd/web-app_3_0.xsd | 272 ++ .../webapp/WEB-INF/xsd/web-common_3_0.xsd | 1575 +++++++++++ .../src/main/webapp/WEB-INF/xsd/xml.xsd | 287 ++ .../ca/uhn/fhir/jpa/demo/ExampleServerIT.java | 89 + .../jpa/demo/RandomServerPortProvider.java | 36 + .../.keep_hapi-fhir-jpaserver-example | 0 .../var/lucenefiles/keep.txt | 1 + pom.xml | 1 + 44 files changed, 7862 insertions(+) create mode 100644 hapi-fhir-jpaserver-dynamic/.README.md.html create mode 100644 hapi-fhir-jpaserver-dynamic/.gitignore create mode 100644 hapi-fhir-jpaserver-dynamic/Dockerfile create mode 100644 hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat create mode 100644 hapi-fhir-jpaserver-dynamic/README.md create mode 100755 hapi-fhir-jpaserver-dynamic/build-docker-image.sh create mode 100644 hapi-fhir-jpaserver-dynamic/pom.xml create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd create mode 100644 hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd create mode 100644 hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java create mode 100644 hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example create mode 100644 hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt diff --git a/hapi-fhir-jpaserver-dynamic/.README.md.html b/hapi-fhir-jpaserver-dynamic/.README.md.html new file mode 100644 index 00000000000..2950cf51902 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/.README.md.html @@ -0,0 +1,713 @@ + + + + +/Users/anoushmouradian/Documents/projects/chip-hapi-fhir-new/hapi-fhir-jpaserver-dynamic/.README.md.html + + + + + + + + + + +

Description

+

This project has been built with hapi-fhir-jpaserver-example as a base. It has been made more dynamic by replacing web.xml with ca.uhn.fhir.jpa.demo.WebInitializer class which extends Spring org.springframework.web.WebApplicationInitializer class and loads application contexts in a dynamic manner, so that based on environment and/or property variables it can be started either as dstu2 or dstu3 version of HAPI-FHIR JPA Server. Some of the classes have been also refactored to make them more generic.

+

Environment variables

+

There are number of environment variables that will control the behavior of the application at run time (such as start as dstu2 or dstu3 version, whether database schema gets recreated or no, database url, etc..). They can also be defined in Property files, see section below. These are environment variables that can be set before application starts:

+
    +
  • DB_URL - database url in a standard jdbc url format, specific to a database of your choosing. For example for Postgres it will be: jdbc:postgresql://localhost:5432/<databaseName>?user=<username>&password=<password>. So far support has been added for MySQL, derby and Postgres databases.

  • +
  • DATABASE_URL - if you deploy your server to HEROKU and create a Postgres database, its URL will be exposed through DATABASE_URL environment variable set by HEROKU. If DATABASE_URL is present it will overwrite DB_URL and its value will be used as jdbc url. This implementations assumes that Heroku will be setup with Postgres database, so current implementation handles postgres DATABASE_URL that gets set in this format: postgres://<username>:<password>@<hostname>:5432/<databaseName>. We convert it into standard jdbc format: jdbc:postgresql://localhost:5432/<databaseName>?user=<username>&password=<password>

  • +
  • SCHEMA_NAME - used only if DATABASE_URL is set, which is expected to be Postgres database url set by HEROKU. If it's set currentSchema parameter will be added to the jdbc url, e.g.:
    jdbc:postgresql://localhost:5432/<databaseName>?user=<username>&password=<password>&currentScema=<schemaName>. Note that schema has to be created beforehand and user should have the right permissions to create tables.

  • +
  • STU_VERSION - can be set to dstu2 or dstu3. If not set by default dstu3 will be used. Corresponding classes will get dynamically loaded at a server startup.

  • +
  • ENV - environment this server will run in, and based on which corresponding property files will be loaded.

    It can be one of those values: local, dev, stg, prod. Based on the value one of the property files will be loaded: resources/config/<STU_VERSION>/app_<ENV>.properties.

    So for example if ENV=local and STU_VERSION=dstu3 this file will be loaded:

    resources/config/dstu3/app_local.properties

  • +
  • HIBERNATE_CREATE - can be set to true or false. If set to true database schema will be dropped and recreated again upon application startup. If set to false hibernate will run with validate as a schema setting.

  • +
+

Property files

+

There are number of property files created for different environments: local, dev, stg, prod. So if ENV environment variable is set to one of those values corresponding property file will be loaded at a run time, by default local files will be loaded. Property files are located at: src/main/resources/config/dstu2 and src/main/resources/config/dstu3s directories. These are the files:

+
   app_local.properties
+   app_dev.properties
+   app_stg.properties
+   app_prod.properties
+   immutable.properties - DO NOT modify any of the properties defined in that file.
+
+

Any of the Environment variables can be defined in one of the app_<ENV>.properties property files. If a property is also defined as Environment variable it will overwrite value defined in property file. Properties defined in immutable.properties should not be changed, those are servlet/Spring mappings and names of classes that will be loaded at a run time and are specific to dstu version being used.

+

Running hapi-fhir-jpaserver-dynamic with a webapp-runner

+

You can run the web application with webapp-runner and pass environment variables to it.

+

Here is a sample command to run the webapp runner which will start dynamic HAPI-FHIR server with version dstu3, postgres database and hibernate schema being dropped and re-created.

+

Note optional command to unset DATABASE_URL, so that only DB_URL is used locally. Also make sure to replace placeholder parameters <databasename>, <username> and <password> with actual values.

+
mvn clean install
+
+unset DATABASE_URL
+
+java $JAVA_OPTS -DSTU_VERSION=dstu3 -DHIBERNATE_CREATE=true -DDB_URL='jdbc:postgresql://localhost:5432/<databaseName>?user=<username>&password=<password>' -DENV=local -jar target/dependency/webapp-runner.jar target/*.war
+
+

You should be able to access HAPI_FHIR server at: http://localhost:8080/ .

+

If you'd like to open a debugging port run this command and attach remote debugger in IDE of your choice to port 5000. Again make sure to replace placeholder parameters with actual values before you run the command.

+
java $JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=5000,suspend=n -DSTU_VERSION=dstu3 -DHIBERNATE_CREATE=false -DDB_URL='jdbc:postgresql://localhost:5432/<databaseName>?user=<username>&password=<password>' -DENV=local -jar target/dependency/webapp-runner.jar target/*.war
+
+

Running hapi-fhir-jpaserver-dynamic in Tomcat from IntelliJ

+

Install Tomcat.

+

Make sure you have Tomcat set up in IntelliJ.

+
    +
  • File->Settings->Build, Execution, Deployment->Application Servers
  • +
  • Click +
  • +
  • Select "Tomcat Server"
  • +
  • Enter the path to your tomcat deployment for both Tomcat Home (IntelliJ will fill in base directory for you)
  • +
+

Add a Run Configuration for running hapi-fhir-jpaserver-dynamic under Tomcat

+
    +
  • Run->Edit Configurations
  • +
  • Click the green +
  • +
  • Select Tomcat Server, Local
  • +
  • Change the name to whatever you wish
  • +
  • Uncheck the "After launch" checkbox
  • +
  • On the "Deployment" tab, click the green +
  • +
  • Select "Artifact"
  • +
  • Select "hapi-fhir-jpaserver-dynamic:war"
  • +
  • In "Application context" type /hapi
  • +
+

Run the configuration.

+
    +
  • You should now have an "Application Servers" in the list of windows at the bottom.
  • +
  • Click it.
  • +
  • Select your server, and click the green triangle (or the bug if you want to debug)
  • +
  • Wait for the console output to stop
  • +
+

Point your browser (or fiddler, or what have you) to http://localhost:8080/fhir/base/Patient

+

You should get an empty bundle back.

+

Running hapi-fhir-jpaserver-dynamic in a Docker container

+

Execute the build-docker-image.sh script to build the docker image.

+

Use this command to start the container: docker run -d --name hapi-fhir-jpaserver-dynamic -p 8080:8080 hapi-fhir/hapi-fhir-jpaserver-dynamic

+

Note: with this command data is persisted across container restarts, but not after removal of the container. Use a docker volume mapping on /var/lib/jetty/target to achieve this.

+

There is also Dockerfile.tomcat which contains docker commands to run hapi-fhir-jpaserver-dynamic within tomcat. Rename Dockerfile.tomcat to Dockerfile if you would rather use tomcat as your application container.

+ + diff --git a/hapi-fhir-jpaserver-dynamic/.gitignore b/hapi-fhir-jpaserver-dynamic/.gitignore new file mode 100644 index 00000000000..a6226ade347 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/.gitignore @@ -0,0 +1,129 @@ +/target +/jpaserver_derby_files +*.log +ca.uhn.fhir.jpa.entity.ResourceTable/ + +# Created by https://www.gitignore.io + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties + + +### Vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties + + + +### Eclipse ### +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + diff --git a/hapi-fhir-jpaserver-dynamic/Dockerfile b/hapi-fhir-jpaserver-dynamic/Dockerfile new file mode 100644 index 00000000000..ddd9c750572 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/Dockerfile @@ -0,0 +1,4 @@ +FROM jetty:9-jre8-alpine +USER jetty:jetty +ADD ./target/hapi-fhir-jpaserver-dynamic.war /var/lib/jetty/webapps/root.war +EXPOSE 8080 \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat b/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat new file mode 100644 index 00000000000..27876fb10fa --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat @@ -0,0 +1,4 @@ +FROM tomcat:8 +COPY ["./hapi-fhir-jpaserver-dynamic.war","/usr/local/tomcat/webapps/"] +CMD ["catalina.sh","run"] +EXPOSE 8080 diff --git a/hapi-fhir-jpaserver-dynamic/README.md b/hapi-fhir-jpaserver-dynamic/README.md new file mode 100644 index 00000000000..c76de2c0e02 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/README.md @@ -0,0 +1,107 @@ +## Description +This project has been built with hapi-fhir-jpaserver-example as a base. It has been made more dynamic by replacing `web.xml` with `ca.uhn.fhir.jpa.demo.WebInitializer` class which extends +Spring `org.springframework.web.WebApplicationInitializer` class and loads application contexts in a dynamic manner, so that based on environment and/or property variables it can be started either as dstu2 or dstu3 version of HAPI-FHIR JPA Server. Some of the classes have been also refactored to make them more generic. + +#### Environment variables +There are number of environment variables that will control the behavior of the application at run time (such as start as dstu2 or dstu3 version, whether +database schema gets recreated or no, database url, etc..). They can also be defined in Property files, see section below. These are environment variables that can be set before application starts: + * `DB_URL` - database url in a standard jdbc url format, specific to a database of your choosing. For example for Postgres it will be: `jdbc:postgresql://localhost:5432/?user=&password=`. So far support has been added for MySQL, derby and Postgres databases. + * `DATABASE_URL` - if you deploy your server to HEROKU and create a Postgres database, its URL will be exposed through `DATABASE_URL` environment variable set by HEROKU. + If `DATABASE_URL` is present it will overwrite `DB_URL` and its value will be used as jdbc url. This implementations assumes that Heroku will be setup with Postgres database, so current implementation handles postgres `DATABASE_URL` that gets set in this format: `postgres://:@:5432/`. We convert it into standard jdbc format: `jdbc:postgresql://localhost:5432/?user=&password=` + * `SCHEMA_NAME` - used only if `DATABASE_URL` is set, which is expected to be Postgres database url set by HEROKU. If it's set + `currentSchema` parameter will be added to the jdbc url, e.g.: + ```jdbc:postgresql://localhost:5432/?user=&password=¤tScema=```. + Note that schema has to be created beforehand and user should have the right permissions to create tables. + * `STU_VERSION` - can be set to `dstu2` or `dstu3`. If not set by default `dstu3` will be used. Corresponding classes will get dynamically loaded at a server startup. + * `ENV` - environment this server will run in, and based on which corresponding property files will be loaded. + + It can be one of those values: `local, dev, stg, prod`. Based on the value one of the property files will be loaded: + ```resources/config//app_.properties```. + + So for example if `ENV=local` and `STU_VERSION=dstu3` this file will be loaded: + + ```resources/config/dstu3/app_local.properties``` + * `HIBERNATE_CREATE` - can be set to `true` or `false`. If set to `true` database schema will be dropped and recreated again upon application startup. If set + to `false` hibernate will run with `validate` as a schema setting. + +#### Property files +There are number of property files created for different environments: `local, dev, stg, prod`. So if `ENV` environment variable is set +to one of those values corresponding property file will be loaded at a run time, by default `local` files will be loaded. Property files are located at: +`src/main/resources/config/dstu2` and `src/main/resources/config/dstu3s` directories. These are the files: +``` + app_local.properties + app_dev.properties + app_stg.properties + app_prod.properties + immutable.properties - DO NOT modify any of the properties defined in that file. +``` +Any of the Environment variables can be defined in one of the `app_.properties` property files. If a property is also defined as Environment variable it will overwrite value defined in property file. Properties defined in `immutable.properties` should not be changed, those are servlet/Spring mappings and names of classes that will be loaded at a run time and are specific to dstu version being used. + +## Running hapi-fhir-jpaserver-dynamic with a webapp-runner +You can run the web application with webapp-runner and pass environment variables to it. + +Here is a sample command to run the webapp runner which will start +dynamic HAPI-FHIR server with version dstu3, postgres database and hibernate schema being dropped and re-created. + +Note optional command to unset DATABASE_URL, so that only DB_URL is used locally. Also make sure to replace placeholder parameters ``, `` and `` with actual values. + +``` +mvn clean install + +unset DATABASE_URL + +java $JAVA_OPTS -DSTU_VERSION=dstu3 -DHIBERNATE_CREATE=true -DDB_URL='jdbc:postgresql://localhost:5432/?user=&password=' -DENV=local -jar target/dependency/webapp-runner.jar target/*.war +``` +You should be able to access HAPI_FHIR server at: http://localhost:8080/ . + +If you'd like to open a debugging port run this command and attach remote debugger in IDE of your choice to port 5000. Again make sure to replace placeholder parameters with actual values before you run the command. + +``` +java $JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=5000,suspend=n -DSTU_VERSION=dstu3 -DHIBERNATE_CREATE=false -DDB_URL='jdbc:postgresql://localhost:5432/?user=&password=' -DENV=local -jar target/dependency/webapp-runner.jar target/*.war +``` + +## Running hapi-fhir-jpaserver-dynamic in Tomcat from IntelliJ + +Install Tomcat. + +Make sure you have Tomcat set up in IntelliJ. + +- File->Settings->Build, Execution, Deployment->Application Servers +- Click + +- Select "Tomcat Server" +- Enter the path to your tomcat deployment for both Tomcat Home (IntelliJ will fill in base directory for you) + +Add a Run Configuration for running hapi-fhir-jpaserver-dynamic under Tomcat + +- Run->Edit Configurations +- Click the green + +- Select Tomcat Server, Local +- Change the name to whatever you wish +- Uncheck the "After launch" checkbox +- On the "Deployment" tab, click the green + +- Select "Artifact" +- Select "hapi-fhir-jpaserver-dynamic:war" +- In "Application context" type /hapi + +Run the configuration. + +- You should now have an "Application Servers" in the list of windows at the bottom. +- Click it. +- Select your server, and click the green triangle (or the bug if you want to debug) +- Wait for the console output to stop + +Point your browser (or fiddler, or what have you) to `http://localhost:8080/fhir/base/Patient` + +You should get an empty bundle back. + + +## Running hapi-fhir-jpaserver-dynamic in a Docker container + +Execute the `build-docker-image.sh` script to build the docker image. + +Use this command to start the container: + `docker run -d --name hapi-fhir-jpaserver-dynamic -p 8080:8080 hapi-fhir/hapi-fhir-jpaserver-dynamic` + +Note: with this command data is persisted across container restarts, but not after removal of the container. Use a docker volume mapping on /var/lib/jetty/target to achieve this. + +There is also Dockerfile.tomcat which contains docker commands to run hapi-fhir-jpaserver-dynamic within tomcat. Rename Dockerfile.tomcat to Dockerfile if you would rather use tomcat as your application container. diff --git a/hapi-fhir-jpaserver-dynamic/build-docker-image.sh b/hapi-fhir-jpaserver-dynamic/build-docker-image.sh new file mode 100755 index 00000000000..c5c5e35e77d --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/build-docker-image.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +mvn package && \ + docker build -t hapi-fhir/hapi-fhir-jpaserver-dynamic . + diff --git a/hapi-fhir-jpaserver-dynamic/pom.xml b/hapi-fhir-jpaserver-dynamic/pom.xml new file mode 100644 index 00000000000..18a3ef434ff --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/pom.xml @@ -0,0 +1,338 @@ + + 4.0.0 + + + + ca.uhn.hapi.fhir + hapi-fhir + 3.2.0-SNAPSHOT + ../pom.xml + + + hapi-fhir-jpaserver-dynamic + war + + HAPI FHIR JPA Server - Example for CHIP + + + + oss-snapshots + + true + + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + + org.eclipse.jetty.websocket + websocket-api + ${jetty_version} + + + org.eclipse.jetty.websocket + websocket-client + ${jetty_version} + + + mysql + mysql-connector-java + + 5.1.40 + + + + + + ca.uhn.hapi.fhir + hapi-fhir-base + ${project.version} + + + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2 + ${project.version} + + + + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-base + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + + + + + + + ca.uhn.hapi.fhir + hapi-fhir-testpage-overlay + ${project.version} + war + runtime + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + + + + + ca.uhn.hapi.fhir + hapi-fhir-testpage-overlay + ${project.version} + classes + compile + + + + + ch.qos.logback + logback-classic + + + + + javax.servlet + javax.servlet-api + provided + + + + + org.thymeleaf + thymeleaf + + + + + org.ebaysf.web + cors-filter + + + servlet-api + javax.servlet + + + + + + + org.springframework + spring-web + + + + + org.apache.commons + commons-dbcp2 + + + + + org.apache.derby + derby + + + org.apache.derby + derbynet + + + org.apache.derby + derbyclient + + + + + org.eclipse.jetty + jetty-servlets + test + + + org.eclipse.jetty + jetty-servlet + test + + + org.eclipse.jetty.websocket + websocket-server + test + + + org.eclipse.jetty + jetty-server + test + + + org.eclipse.jetty + jetty-util + test + + + org.eclipse.jetty + jetty-webapp + test + + + com.phloc + phloc-schematron + + + Saxon-HE + net.sf.saxon + + + + + + + javax.interceptor + javax.interceptor-api + provided + + + + org.postgresql + postgresql + 42.1.4 + + + + + + + + hapi-fhir-jpaserver-dynamic + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + ${maven.build.timestamp} + + + + + ca.uhn.hapi.fhir + hapi-fhir-testpage-overlay + + + + false + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + true + + + + + integration-test + verify + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + package + copy + + + + com.github.jsimone + webapp-runner-main + 8.5.23.1 + webapp-runner.jar + + + + + + + + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java new file mode 100644 index 00000000000..28911a2d325 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java @@ -0,0 +1,106 @@ +package ca.uhn.fhir.jpa.demo; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.env.Environment; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; + +/** + * This is the primary configuration file for the dynamic jpa server running with dstu3 version. + * It will load 2 property files:
+ * config/dstu3/immutable.properties and config/dstu3/app_${ENV}.properties
+ * where ${ENV} is an environment variable named ENV which should be set to one of the strings: + * local, dev, stg or prod. + * + * By default it will be set to local, so config/dstu3/app_local.properties file will be loaded. + * It expects properties to be exposed either as as environment variables or through property files. Note that environment variable take precedence over + * property files. + *
    + *
  • ENV - default value set to "local". Can be set to "local", "dev", "stg" or "prod".
  • + *
  • DB_URL - database url, can be exposed either as environment variable or in environment specific property file, e.g. app_local.properties
  • + *
  • DATABASE_URL - this url will be set by Heroku as a db url, if it's set, it'll overwrite db settings set with + * DB_URL
  • + *
  • HIBERNATE_CREATE - if set to true, hibernate will drop and recreate schema, if set to false, + * will validate the schema + *
  • SCHEMA_NAME - if set, schema name will be used in the database url, used only when DATABASE_URL is set. + *
+ * + */ +@Configuration +@EnableTransactionManagement() +@PropertySources({ + @PropertySource("classpath:config/dstu3/immutable.properties"), + @PropertySource("classpath:config/dstu3/app_${ENV:local}.properties") }) +public class FhirServerConfig extends BaseJavaConfigDstu3 { + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FhirServerConfig.class); + + @Autowired + private Environment env; + /** + * Configure FHIR properties around the the JPA server via this bean + */ + @Bean() + public DaoConfig daoConfig() { + return FhirServerConfigCommon.getDaoConfig(); + } + + /** + * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a + * directory called "jpaserver_derby_files". + * + * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. + */ + @Bean(destroyMethod = "close") + public DataSource dataSource() { + return FhirServerConfigCommon.getDataSource(env); + } + + @Bean() + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource()); + } + + /** + * Do some fancy logging to create a nice access log that has details about each incoming request. + */ + public IServerInterceptor loggingInterceptor() { + return FhirServerConfigCommon.loggingInterceptor(); + } + + /** + * This interceptor adds some pretty syntax highlighting in responses when a browser is detected + */ + @Bean(autowire = Autowire.BY_TYPE) + public IServerInterceptor responseHighlighterInterceptor() { + return FhirServerConfigCommon.getResponseHighlighterInterceptor(); + } + + @Bean(autowire = Autowire.BY_TYPE) + public IServerInterceptor subscriptionSecurityInterceptor() { + String stuVersion = (env.getProperty(Utils.STU_VERSION) == null)?Utils.DSTU3:env.getProperty(Utils.STU_VERSION) ; + logger.info("-------STU_VERSION: " + stuVersion); + SubscriptionsRequireManualActivationInterceptorDstu3 interceptor = new SubscriptionsRequireManualActivationInterceptorDstu3(); + return interceptor; + } + + @Bean() + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + return FhirServerConfigCommon.getTransactionManager(entityManagerFactory); + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java new file mode 100644 index 00000000000..1015ca79ffe --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java @@ -0,0 +1,165 @@ +package ca.uhn.fhir.jpa.demo; + +import java.sql.SQLException; +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.apache.commons.dbcp2.BasicDataSource; +import org.apache.commons.lang3.time.DateUtils; +import org.hibernate.jpa.HibernatePersistenceProvider; +import org.springframework.core.env.Environment; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; + + +/** + * Common code for dstu2 and dstu3 classes moved into static methods so that they can be called from version specific class. + * + * @author anoushmouradian + * + */ +public class FhirServerConfigCommon { + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); + + /** + * Configure FHIR properties around the the JPA server via this bean + */ + @SuppressWarnings("deprecation") + public static DaoConfig getDaoConfig() { + DaoConfig daoConfig = new DaoConfig(); + daoConfig.setSubscriptionEnabled(true); + daoConfig.setSubscriptionPollDelay(5000); + daoConfig.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR); + daoConfig.setAllowMultipleDelete(true); + return daoConfig; + } + + /** + * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a + * directory called "jpaserver_derby_files". + * + * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. + */ + public static DataSource getDataSource(Environment env) { + String dbUrl = (env.getProperty(Utils.DB_URL) != null)?env.getProperty(Utils.DB_URL).toLowerCase():""; + String herokuDbUrl = env.getProperty(Utils.HEROKU_DATABASE_URL); + + if(herokuDbUrl != null) { + // url will come as: postgres://user:pass@host:5432/dbname + String fromUserName = herokuDbUrl.substring(herokuDbUrl.indexOf("//") + 2); + String userName = fromUserName.substring(0, fromUserName.indexOf(":")); + String pass = fromUserName.substring(fromUserName.indexOf(":") +1, fromUserName.indexOf("@")); + String fromHost = fromUserName.substring(fromUserName.indexOf("@")+1); + String schemaName = env.getProperty(Utils.SCHEMA_NAME); + + //build this url: jdbc:postgresql://host:5432/dbName?user=username&password=pass¤tSchema=' + dbUrl = "jdbc:postgresql://" + fromHost + "?user=" + userName + "&password=" + pass + "&sslmode=require"; + if(schemaName != null) { + dbUrl += "¤tSchema=" + schemaName; + } + logger.info("------DB Url: " + dbUrl); + } + BasicDataSource dataSource = new BasicDataSource(); + try { + if(dbUrl.indexOf("mysql") > -1 ) { + dataSource.setDriver(new com.mysql.jdbc.Driver()); + } else if(dbUrl.indexOf("postgres") > -1) { + dataSource.setDriver(new org.postgresql.Driver()); + } else if(dbUrl.indexOf("derby") > -1) { + dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); + } + } catch (SQLException e) { + logger.error("----FhiServerConfigCommon: getDataSource: setting driver error: " + e.getMessage()); + } + dataSource.setUrl(dbUrl); + return dataSource; + } + + public static LocalContainerEntityManagerFactoryBean getEntityManagerFactory(Environment env, DataSource dataSource) { + LocalContainerEntityManagerFactoryBean retVal = new LocalContainerEntityManagerFactoryBean(); + retVal.setPersistenceUnitName("HAPI_PU"); + retVal.setDataSource(dataSource); + + retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity"); + retVal.setPersistenceProvider(new HibernatePersistenceProvider()); + retVal.setJpaProperties(jpaProperties(env)); + return retVal; + } + + + /** + * Do some fancy logging to create a nice access log that has details about each incoming request. + */ + public static IServerInterceptor loggingInterceptor() { + LoggingInterceptor retVal = new LoggingInterceptor(); + retVal.setLoggerName("fhirtest.access"); + retVal.setMessageFormat( + "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); + retVal.setLogExceptions(true); + retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}"); + return retVal; + } + + /** + * This interceptor adds some pretty syntax highlighting in responses when a browser is detected + */ + public static IServerInterceptor getResponseHighlighterInterceptor() { + ResponseHighlighterInterceptor retVal = new ResponseHighlighterInterceptor(); + return retVal; + } + + public static JpaTransactionManager getTransactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } + + private static Properties jpaProperties(Environment env) { + Properties extraProperties = new Properties(); + String dbUrl = (env.getProperty(Utils.HEROKU_DATABASE_URL) == null)?env.getProperty(Utils.DB_URL):env.getProperty(Utils.HEROKU_DATABASE_URL); + if(dbUrl != null && dbUrl.indexOf("mysql") > -1) { + extraProperties.put("hibernate.dialect", org.hibernate.dialect.MySQL5Dialect.class.getName()); + extraProperties.put("hibernate.dialect.storage_engine","innodb"); + } + else if(dbUrl != null && dbUrl.indexOf("postgres") > -1) { + extraProperties.put("hibernate.dialect", org.hibernate.dialect.PostgreSQL9Dialect.class.getName()); + } + else if(dbUrl != null && dbUrl.indexOf("derby") > -1) { + extraProperties.put("hibernate.dialect", org.hibernate.dialect.DerbyTenSevenDialect.class.getName()); + } + boolean hibernateCreate = new Boolean(env.getProperty(Utils.HIBERNATE_CREATE)); + logger.info("------DB hibernateCreate: " + hibernateCreate); + if(hibernateCreate){ + extraProperties.put("hibernate.hbm2ddl.auto", "create"); + } else { + extraProperties.put("hibernate.hbm2ddl.auto", "validate"); + } + extraProperties.put("hibernate.format_sql", "true"); + extraProperties.put("hibernate.show_sql", "false"); + + extraProperties.put("hibernate.jdbc.batch_size", "20"); + extraProperties.put("hibernate.cache.use_query_cache", "false"); + extraProperties.put("hibernate.cache.use_second_level_cache", "false"); + extraProperties.put("hibernate.cache.use_structured_entries", "false"); + extraProperties.put("hibernate.cache.use_minimal_puts", "false"); + extraProperties.put("hibernate.search.default.directory_provider", "filesystem"); + extraProperties.put("hibernate.search.model_mapping", LuceneSearchMappingFactory.class.getName()); + extraProperties.put("hibernate.search.autoregister_listeners", "false"); + extraProperties.put("hibernate.search.default.indexBase", "./target/lucenefiles"); + extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT"); + extraProperties.put("hibernate.search.indexing_strategy", "manual"); + extraProperties.put("hibernate.search.default.worker.execution", "async"); + + return extraProperties; + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java new file mode 100644 index 00000000000..982f2ab193d --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java @@ -0,0 +1,110 @@ +package ca.uhn.fhir.jpa.demo; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.env.Environment; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; + + +/** + * This is the primary configuration file for the dynamic jpa server running with dstu2 version. + * It will load 2 property files:
+ * config/dstu2/immutable.properties and config/dstu2/app_${ENV}.properties
+ * where ${ENV} is an environment variable named ENV which should be set to one of the strings: + * local, dev, stg or prod. + * + * By default it will be set to local, so config/dstu2/app_local.properties file will be loaded. + * It expects properties to be exposed either as as environment variables or through property files. Note that environment variable take precedence over + * property files. + *
    + *
  • ENV - default value set to "local". Can be set to "local", "dev", "stg" or "prod".
  • + *
  • DB_URL - database url, can be exposed either as environment variable or in environment specific property file, e.g. app_local.properties
  • + *
  • DATABASE_URL - this url will be set by Heroku as a db url, if it's set, it'll overwrite db settings set with + * DB_URL
  • + *
  • HIBERNATE_CREATE - if set to true, hibernate will drop and recreate schema, if set to false, + * will validate the schema + *
  • SCHEMA_NAME - if set, schema name will be used in the database url, used only when DATABASE_URL is set. + *
+ * + */ +@Configuration +@EnableTransactionManagement() +@PropertySources({ + @PropertySource("classpath:config/dstu2/immutable.properties"), + @PropertySource("classpath:config/dstu2/app_${ENV:local}.properties") }) +public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FhirServerConfigDstu2.class); + + @Autowired + private Environment env; + + /** + * Configure FHIR properties around the the JPA server via this bean + */ + @SuppressWarnings("deprecation") + @Bean() + public DaoConfig daoConfig() { + return FhirServerConfigCommon.getDaoConfig(); + } + + /** + * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a + * directory called "jpaserver_derby_files". + * + * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. + */ + @Bean(destroyMethod = "close") + public DataSource dataSource() { + return FhirServerConfigCommon.getDataSource(env); + } + + @Bean() + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource()); + } + + + /** + * Do some fancy logging to create a nice access log that has details about each incoming request. + */ + public IServerInterceptor loggingInterceptor() { + return FhirServerConfigCommon.loggingInterceptor(); + } + + /** + * This interceptor adds some pretty syntax highlighting in responses when a browser is detected + */ + @Bean(autowire = Autowire.BY_TYPE) + public IServerInterceptor responseHighlighterInterceptor() { + return FhirServerConfigCommon.getResponseHighlighterInterceptor(); + } + + @Bean(autowire = Autowire.BY_TYPE) + public IServerInterceptor subscriptionSecurityInterceptor() { + String stuVersion = (env.getProperty(Utils.STU_VERSION) == null)?Utils.DSTU2:env.getProperty(Utils.STU_VERSION) ; + logger.info("-------STU_VERSION: " + stuVersion); + SubscriptionsRequireManualActivationInterceptorDstu2 interceptor = new SubscriptionsRequireManualActivationInterceptorDstu2(); + return interceptor; + } + + @Bean() + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + return FhirServerConfigCommon.getTransactionManager(entityManagerFactory); + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java new file mode 100644 index 00000000000..f5eb07c4242 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java @@ -0,0 +1,68 @@ +package ca.uhn.fhir.jpa.demo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.env.Environment; + +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.to.FhirTesterMvcConfig; +import ca.uhn.fhir.to.TesterConfig; + +//@formatter:off +/** + * This spring config file configures the web testing module. It serves two + * purposes: + * 1. It imports FhirTesterMvcConfig, which is the spring config for the + * tester itself + * 2. It tells the tester which server(s) to talk to, via the testerConfig() + * method below.
+ * It will also load properties defined in config/dstu3/immutable.properties file. + */ +@Configuration +@PropertySources({ + @PropertySource("classpath:config/dstu3/immutable.properties") }) +@Import(FhirTesterMvcConfig.class) +public class FhirTesterConfig { + + @Autowired + private Environment env; + + /** + * This bean tells the testing webpage which servers it should configure itself + * to communicate with. In this example we configure it to talk to the local + * server, as well as one public server. If you are creating a project to + * deploy somewhere else, you might choose to only put your own server's + * address here. + * + * Note the use of the ${serverBase} variable below. This will be replaced with + * the base URL as reported by the server itself. Often for a simple Tomcat + * (or other container) installation, this will end up being something + * like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are + * deploying your server to a place with a fully qualified domain name, + * you might want to use that instead of using the variable. + */ + @Bean + public TesterConfig testerConfig() { + TesterConfig retVal = new TesterConfig(); + String baseFhirMapping = env.getProperty(Utils.BASE_FHIR_MAPPING); + baseFhirMapping = (baseFhirMapping == null)?"fhir":baseFhirMapping; + retVal + .addServer() + .withId("home") + .withFhirVersion(FhirVersionEnum.DSTU3) + .withBaseUrl("${serverBase}/" + baseFhirMapping) + .withName("Local Tester") + .addServer() + .withId("hapi") + .withFhirVersion(FhirVersionEnum.DSTU3) + .withBaseUrl("http://fhirtest.uhn.ca/" + baseFhirMapping) + .withName("Public HAPI Test Server"); + return retVal; + } + +} +//@formatter:on diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java new file mode 100644 index 00000000000..fb2822436b3 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java @@ -0,0 +1,71 @@ +package ca.uhn.fhir.jpa.demo; + +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.to.FhirTesterMvcConfig; +import ca.uhn.fhir.to.TesterConfig; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.env.Environment; + +//@formatter:off + +/** + * This spring config file configures the web testing module. It serves two + * purposes: + * 1. It imports FhirTesterMvcConfig, which is the spring config for the + * tester itself + * 2. It tells the tester which server(s) to talk to, via the testerConfig() + * method below
+ * It will also load properties defined in config/dstu2/immutable.properties file. + */ +@Configuration +@PropertySources({ + @PropertySource("classpath:config/dstu2/immutable.properties") }) +@Import(FhirTesterMvcConfig.class) +public class FhirTesterConfigDstu2 { + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FhirTesterConfigDstu2.class); + + @Autowired + private Environment env; + + /** + * This bean tells the testing webpage which servers it should configure itself + * to communicate with. In this example we configure it to talk to the local + * server, as well as one public server. If you are creating a project to + * deploy somewhere else, you might choose to only put your own server's + * address here. + * + * Note the use of the ${serverBase} variable below. This will be replaced with + * the base URL as reported by the server itself. Often for a simple Tomcat + * (or other container) installation, this will end up being something + * like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are + * deploying your server to a place with a fully qualified domain name, + * you might want to use that instead of using the variable. + */ + @Bean + public TesterConfig testerConfig() { + logger.info("-------FhirTesterConfigDstu2:" + "testerConfig"); + TesterConfig retVal = new TesterConfig(); + String baseFhirMapping = env.getProperty(Utils.BASE_FHIR_MAPPING); + baseFhirMapping = (baseFhirMapping == null)?"fhir":baseFhirMapping; + retVal + .addServer() + .withId("home") + .withFhirVersion(FhirVersionEnum.DSTU2) + .withBaseUrl("${serverBase}/" + baseFhirMapping) + .withName("Local Tester") + .addServer() + .withId("hapi") + .withFhirVersion(FhirVersionEnum.DSTU2) + .withBaseUrl("http://fhirtest.uhn.ca/" + baseFhirMapping) + .withName("Public HAPI Test Server"); + return retVal; + } + +} +//@formatter:on diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java new file mode 100644 index 00000000000..b625bcf4b19 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java @@ -0,0 +1,64 @@ +package ca.uhn.fhir.jpa.demo; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Load immutable properties from /resources/config//immutable.properties file. STU_VERSION environment variable can be set to dstu2 or dstu3, which will translate to the + * file path, e.g.: /resources/config/immutable/dstu3/immutable.properties + * By default it'll set path to dstu3. + * + * @author anoushmouradian + * + */ +@Configuration +@PropertySource("classpath:config/${STU_VERSION:dstu3}/immutable.properties") +public class ImmutablePropertiesConfig { + + @Value("${FHIR_VERSION}") + private String fhirVersion; + @Value("${fhirServerConfigClass}") + private String fhirServerConfigClass; + @Value("${fhirTesterConfigClass}") + private String fhirTesterConfigClass; + @Value("${jpaDemoClass}") + private String jpaDemoClass; + @Value("${jpaDemoMapping}") + private String jpaDemoMapping; + + + public String getFhirVersion() { + return fhirVersion; + } + public void setFhirVersion(String fhirVersion) { + this.fhirVersion = fhirVersion; + } + public String getFhirServerConfigClass() { + return fhirServerConfigClass; + } + public void setFhirServerConfigClass(String fhirServerConfigClass) { + this.fhirServerConfigClass = fhirServerConfigClass; + } + public String getFhirTesterConfigClass() { + return fhirTesterConfigClass; + } + public void setFhirTesterConfigClass(String fhirTesterConfigClass) { + this.fhirTesterConfigClass = fhirTesterConfigClass; + } + public String getJpaDemoClass() { + return jpaDemoClass; + } + public void setJpaDemoClass(String jpaDemoClass) { + this.jpaDemoClass = jpaDemoClass; + } + public String getJpaDemoMapping() { + return jpaDemoMapping; + } + public void setJpaDemoMapping(String jpaDemoMapping) { + this.jpaDemoMapping = jpaDemoMapping; + } + + + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java new file mode 100644 index 00000000000..9dfa49e7a21 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java @@ -0,0 +1,159 @@ + +package ca.uhn.fhir.jpa.demo; + +import java.util.Collection; +import java.util.List; + +import javax.servlet.ServletException; + +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.Meta; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.WebApplicationContext; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.IFhirSystemDao; +import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; +import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; +import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; +import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; +import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.model.dstu2.composite.MetaDt; +import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.server.ETagSupportEnum; +import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; + +public class JpaServerDemo extends RestfulServer { + + private static final long serialVersionUID = 1L; + + private WebApplicationContext myAppCtx; + + @SuppressWarnings("unchecked") + @Override + protected void initialize() throws ServletException { + super.initialize(); + + /* + * We want to support FHIR DSTU2 format. This means that the server + * will use the DSTU2 bundle format and other DSTU2 encoding changes. + * + * If you want to use DSTU1 instead, change the following line, and change the 2 occurrences of dstu2 in web.xml to dstu1 + */ + FhirVersionEnum fhirVersion = FhirVersionEnum.DSTU3; + setFhirContext(new FhirContext(fhirVersion)); + + // Get the spring context from the web container (it's declared in web.xml) + myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext(); + + /* + * The BaseJavaConfigDstu2.java class is a spring configuration + * file which is automatically generated as a part of hapi-fhir-jpaserver-base and + * contains bean definitions for a resource provider for each resource type + */ + String resourceProviderBeanName; + if (fhirVersion == FhirVersionEnum.DSTU2) { + resourceProviderBeanName = "myResourceProvidersDstu2"; + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + resourceProviderBeanName = "myResourceProvidersDstu3"; + } else { + throw new IllegalStateException(); + } + List beans = myAppCtx.getBean(resourceProviderBeanName, List.class); + setResourceProviders(beans); + + /* + * The system provider implements non-resource-type methods, such as + * transaction, and global history. + */ + Object systemProvider; + if (fhirVersion == FhirVersionEnum.DSTU2) { + systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class); + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + systemProvider = myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class); + } else { + throw new IllegalStateException(); + } + setPlainProviders(systemProvider); + + /* + * The conformance provider exports the supported resources, search parameters, etc for + * this server. The JPA version adds resource counts to the exported statement, so it + * is a nice addition. + */ + if (fhirVersion == FhirVersionEnum.DSTU2) { + IFhirSystemDao systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, + myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription("Example Server"); + setServerConformanceProvider(confProvider); + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + IFhirSystemDao systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, + myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription("Example Server"); + setServerConformanceProvider(confProvider); + } else { + throw new IllegalStateException(); + } + + /* + * Enable ETag Support (this is already the default) + */ + setETagSupport(ETagSupportEnum.ENABLED); + + /* + * This server tries to dynamically generate narratives + */ + FhirContext ctx = getFhirContext(); + ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); + + /* + * Default to JSON and pretty printing + */ + setDefaultPrettyPrint(true); + setDefaultResponseEncoding(EncodingEnum.JSON); + + /* + * -- New in HAPI FHIR 1.5 -- + * This configures the server to page search results to and from + * the database, instead of only paging them to memory. This may mean + * a performance hit when performing searches that return lots of results, + * but makes the server much more scalable. + */ + setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class)); + + /* + * Load interceptors for the server from Spring (these are defined in FhirServerConfig.java) + */ + Collection interceptorBeans = myAppCtx.getBeansOfType(IServerInterceptor.class).values(); + for (IServerInterceptor interceptor : interceptorBeans) { + this.registerInterceptor(interceptor); + } + + /* + * If you are hosting this server at a specific DNS name, the server will try to + * figure out the FHIR base URL based on what the web container tells it, but + * this doesn't always work. If you are setting links in your search bundles that + * just refer to "localhost", you might want to use a server address strategy: + */ + //setServerAddressStrategy(new HardcodedServerAddressStrategy("http://mydomain.com/fhir/baseDstu2")); + + /* + * If you are using DSTU3+, you may want to add a terminology uploader, which allows + * uploading of external terminologies such as Snomed CT. Note that this uploader + * does not have any security attached (any anonymous user may use it by default) + * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor + * with this feature. + */ + //if (fhirVersion == FhirVersionEnum.DSTU3) { + // registerProvider(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); + //} + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java new file mode 100644 index 00000000000..cf6bb8572ff --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java @@ -0,0 +1,159 @@ + +package ca.uhn.fhir.jpa.demo; + +import java.util.Collection; +import java.util.List; + +import javax.servlet.ServletException; + +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.Meta; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.WebApplicationContext; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.IFhirSystemDao; +import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; +import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; +import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; +import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; +import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.model.dstu2.composite.MetaDt; +import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.server.ETagSupportEnum; +import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; + +public class JpaServerDemoDstu2 extends RestfulServer { + + private static final long serialVersionUID = 1L; + + private WebApplicationContext myAppCtx; + + @SuppressWarnings("unchecked") + @Override + protected void initialize() throws ServletException { + super.initialize(); + + /* + * We want to support FHIR DSTU2 format. This means that the server + * will use the DSTU2 bundle format and other DSTU2 encoding changes. + * + * If you want to use DSTU1 instead, change the following line, and change the 2 occurrences of dstu2 in web.xml to dstu1 + */ + FhirVersionEnum fhirVersion = FhirVersionEnum.DSTU2; + setFhirContext(new FhirContext(fhirVersion)); + + // Get the spring context from the web container (it's declared in web.xml) + myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext(); + + /* + * The BaseJavaConfigDstu2.java class is a spring configuration + * file which is automatically generated as a part of hapi-fhir-jpaserver-base and + * contains bean definitions for a resource provider for each resource type + */ + String resourceProviderBeanName; + if (fhirVersion == FhirVersionEnum.DSTU2) { + resourceProviderBeanName = "myResourceProvidersDstu2"; + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + resourceProviderBeanName = "myResourceProvidersDstu3"; + } else { + throw new IllegalStateException(); + } + List beans = myAppCtx.getBean(resourceProviderBeanName, List.class); + setResourceProviders(beans); + + /* + * The system provider implements non-resource-type methods, such as + * transaction, and global history. + */ + Object systemProvider; + if (fhirVersion == FhirVersionEnum.DSTU2) { + systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class); + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + systemProvider = myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class); + } else { + throw new IllegalStateException(); + } + setPlainProviders(systemProvider); + + /* + * The conformance provider exports the supported resources, search parameters, etc for + * this server. The JPA version adds resource counts to the exported statement, so it + * is a nice addition. + */ + if (fhirVersion == FhirVersionEnum.DSTU2) { + IFhirSystemDao systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, + myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription("Example Server"); + setServerConformanceProvider(confProvider); + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + IFhirSystemDao systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, + myAppCtx.getBean(DaoConfig.class)); + confProvider.setImplementationDescription("Example Server"); + setServerConformanceProvider(confProvider); + } else { + throw new IllegalStateException(); + } + + /* + * Enable ETag Support (this is already the default) + */ + setETagSupport(ETagSupportEnum.ENABLED); + + /* + * This server tries to dynamically generate narratives + */ + FhirContext ctx = getFhirContext(); + ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); + + /* + * Default to JSON and pretty printing + */ + setDefaultPrettyPrint(true); + setDefaultResponseEncoding(EncodingEnum.JSON); + + /* + * -- New in HAPI FHIR 1.5 -- + * This configures the server to page search results to and from + * the database, instead of only paging them to memory. This may mean + * a performance hit when performing searches that return lots of results, + * but makes the server much more scalable. + */ + setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class)); + + /* + * Load interceptors for the server from Spring (these are defined in FhirServerConfig.java) + */ + Collection interceptorBeans = myAppCtx.getBeansOfType(IServerInterceptor.class).values(); + for (IServerInterceptor interceptor : interceptorBeans) { + this.registerInterceptor(interceptor); + } + + /* + * If you are hosting this server at a specific DNS name, the server will try to + * figure out the FHIR base URL based on what the web container tells it, but + * this doesn't always work. If you are setting links in your search bundles that + * just refer to "localhost", you might want to use a server address strategy: + */ + //setServerAddressStrategy(new HardcodedServerAddressStrategy("http://mydomain.com/fhir/baseDstu2")); + + /* + * If you are using DSTU3+, you may want to add a terminology uploader, which allows + * uploading of external terminologies such as Snomed CT. Note that this uploader + * does not have any security attached (any anonymous user may use it by default) + * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor + * with this feature. + */ + //if (fhirVersion == FhirVersionEnum.DSTU3) { + // registerProvider(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); + //} + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java new file mode 100644 index 00000000000..360c295c034 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java @@ -0,0 +1,18 @@ +package ca.uhn.fhir.jpa.demo; + +/** + * @author anoushmouradian + * + */ +public class Utils { + public static final String HEROKU_DATABASE_URL = "DATABASE_URL"; + public static final String DB_URL = "DB_URL"; + public static final String HIBERNATE_CREATE = "HIBERNATE_CREATE"; + public static final String STU_VERSION = "STU_VERSION"; + public static final String DSTU2 = "dstu2"; + public static final String DSTU3 = "dstu3"; + public static final String SCHEMA_NAME= "SCHEMA_NAME"; + public static final String BASE_FHIR_MAPPING = "baseFhirMapping"; + + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java new file mode 100644 index 00000000000..fa93042957f --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java @@ -0,0 +1,74 @@ +package ca.uhn.fhir.jpa.demo; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * replace web.xml with Spring web initializer, so that various version specific + * classes can be loaded on startup dynamically + * + * @author anoushmouradian + * + */ +public class WebInitializer implements WebApplicationInitializer { + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(WebInitializer.class); + + @Override + public void onStartup(ServletContext container) throws ServletException { + + ConfigurableApplicationContext propContext = new AnnotationConfigApplicationContext(ImmutablePropertiesConfig.class); + ImmutablePropertiesConfig props = propContext.getBean(ImmutablePropertiesConfig.class); + logger.info("This is FHIR_VERSION: " + props.getFhirVersion()); + propContext.close(); + + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setConfigLocation(props.getFhirServerConfigClass()); + + container.addListener(new ContextLoaderListener(context)); + context.close(); + + AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); + dispatcherContext.setConfigLocation(props.getFhirTesterConfigClass()); + ServletRegistration.Dynamic springDispatcher = container.addServlet("spring", new DispatcherServlet(dispatcherContext)); + springDispatcher.setLoadOnStartup(2); + springDispatcher.addMapping("/"); + dispatcherContext.close(); + + ServletRegistration.Dynamic fhirServlet = container.addServlet("fhirServlet", props.getJpaDemoClass()); + fhirServlet.setInitParameter("ImplementationDescription", "FHIR JPA Server"); + fhirServlet.setInitParameter("FhirVersion", props.getFhirVersion()); + fhirServlet.setLoadOnStartup(1); + fhirServlet.addMapping(props.getJpaDemoMapping()); + + FilterRegistration.Dynamic corsFilter = container.addFilter("CORS Filter", "org.ebaysf.web.cors.CORSFilter"); + corsFilter.addMappingForUrlPatterns(null, false, "/*"); + Map corsMap = Collections.unmodifiableMap(new HashMap() { + { + put("cors.allowed.origins", "*"); + put("cors.allowed.methods", "GET,POST,PUT,DELETE,OPTIONS"); + put("cors.allowed.headers", + "X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers"); + put("cors.exposed.headers", "Location,Content-Location"); + put("cors.support.credentials", "true"); + put("cors.logging.enabled", "true"); + put("cors.preflight.maxage", "300"); + } + }); + corsFilter.setInitParameters(corsMap); + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties new file mode 100644 index 00000000000..1ecf1b99aab --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://localhost:5432/?user=&password= +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties new file mode 100644 index 00000000000..dd1830d3567 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties @@ -0,0 +1,6 @@ +FHIR_VERSION=DSTU2 +fhirServerConfigClass=ca.uhn.fhir.jpa.demo.FhirServerConfigDstu2 +fhirTesterConfigClass=ca.uhn.fhir.jpa.demo.FhirTesterConfigDstu2 +jpaDemoClass=ca.uhn.fhir.jpa.demo.JpaServerDemoDstu2 +jpaDemoMapping=/fhir/* +baseFhirMapping=fhir \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties new file mode 100644 index 00000000000..1ecf1b99aab --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://localhost:5432/?user=&password= +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties new file mode 100644 index 00000000000..2bf5b2f1365 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties @@ -0,0 +1,2 @@ +#DB_URL=jdbc:postgresql://:5432/?user=&password=&sslmode=require +HIBERNATE_CREATE=false \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties new file mode 100644 index 00000000000..6219a557a02 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties @@ -0,0 +1,6 @@ +FHIR_VERSION=DSTU3 +fhirServerConfigClass=ca.uhn.fhir.jpa.demo.FhirServerConfig +fhirTesterConfigClass=ca.uhn.fhir.jpa.demo.FhirTesterConfig +jpaDemoClass=ca.uhn.fhir.jpa.demo.JpaServerDemo +jpaDemoMapping=/fhir/* +baseFhirMapping=fhir \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml b/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml new file mode 100644 index 00000000000..1f25a78cb31 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + ERROR + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n + + + + + + + + \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html new file mode 100644 index 00000000000..d552027e956 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html @@ -0,0 +1,67 @@ + + + + About This Server + + + +
+
+ +
+
+
+ +
+ +
+ +
+
+

About This Server

+
+
+
+ +
+

+ This server provides a nearly complete implementation of the FHIR Specification + using a 100% open source software stack. It is hosted by University Health Network. +

+

+ The architecture in use here is shown in the image on the right. This server is built + from a number of modules of the + HAPI FHIR + project, which is a 100% open-source (Apache 2.0 Licensed) Java based + implementation of the FHIR specification. +

+

+ +

+
+
+
+
+

Data On This Server

+
+
+

+ This server is regularly loaded with a standard set of test data sourced + from UHN's own testing environment. Do not use this server to store any data + that you will need later, as we will be regularly resetting it. +

+

+ This is not a production server and it provides no privacy. Do not store any + confidential data here. +

+
+
+ +
+
+
+ +
+
+ + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html new file mode 100644 index 00000000000..bf18c498a78 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html @@ -0,0 +1,16 @@ + + +
+ +
+ diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html new file mode 100644 index 00000000000..dfc4769d6e4 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html @@ -0,0 +1,52 @@ + + +
+ +

+ This is the home for the FHIR test server operated by + University Health Network. This server + (and the testing application you are currently using to access it) + is entirely built using + HAPI-FHIR, + a 100% open-source Java implementation of the + FHIR specification. +

+

+ Here are some things you might wish to try: +

+
    +
  • + View a + list of patients + on this server. +
  • +
  • + Construct a + search query + on this server. +
  • +
  • + Access a + different server + (use the Server menu at the top of the page to see a list of public FHIR servers) +
  • +
+
+ +

+ You are accessing the public FHIR server + . This server is hosted elsewhere on the internet + but is being accessed using the HAPI client implementation. +

+
+

+ + + This is not a production server! + + Do not store any information here that contains personal health information + or any other confidential information. This server will be regularly purged + and reloaded with fixed test data. +

+
+ diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml new file mode 100644 index 00000000000..de1a573d1c4 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml @@ -0,0 +1,106 @@ + + + + org.springframework.web.context.ContextLoaderListener + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + + ca.uhn.fhir.jpa.demo.FhirServerConfigDstu2 + + + + + + + spring + org.springframework.web.servlet.DispatcherServlet + + contextClass + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + contextConfigLocation + ca.uhn.fhir.jpa.demo.FhirTesterConfigDstu2 + + 2 + + + + fhirServlet + ca.uhn.fhir.jpa.demo.JpaServerDemoDstu2 + + ImplementationDescription + FHIR JPA Server + + + FhirVersion + DSTU2 + + 1 + + + + fhirServlet + /baseDstu2/* + + + + spring + / + + + + + + + CORS Filter + org.ebaysf.web.cors.CORSFilter + + A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials. + cors.allowed.origins + * + + + A comma separated list of HTTP verbs, using which a CORS request can be made. + cors.allowed.methods + GET,POST,PUT,DELETE,OPTIONS + + + A comma separated list of allowed headers when making a non simple CORS request. + cors.allowed.headers + X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers + + + A comma separated list non-standard response headers that will be exposed to XHR2 object. + cors.exposed.headers + Location,Content-Location + + + A flag that suggests if CORS is supported with cookies + cors.support.credentials + true + + + A flag to control logging + cors.logging.enabled + true + + + Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache. + cors.preflight.maxage + 300 + + + + CORS Filter + /* + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml new file mode 100644 index 00000000000..39d8f8970a3 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml @@ -0,0 +1,108 @@ + + + + org.springframework.web.context.ContextLoaderListener + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + + ca.uhn.fhir.jpa.demo.FhirServerConfig + + + + + + + spring + org.springframework.web.servlet.DispatcherServlet + + contextClass + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + contextConfigLocation + ca.uhn.fhir.jpa.demo.FhirTesterConfig + + 2 + + + + fhirServlet + ca.uhn.fhir.jpa.demo.JpaServerDemo + + ImplementationDescription + FHIR JPA Server + + + FhirVersion + DSTU3 + + 1 + + + + fhirServlet + /baseDstu3/* + + + + spring + / + + + + + + + CORS Filter + org.ebaysf.web.cors.CORSFilter + + A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials. + cors.allowed.origins + * + + + A comma separated list of HTTP verbs, using which a CORS request can be made. + cors.allowed.methods + GET,POST,PUT,DELETE,OPTIONS + + + A comma separated list of allowed headers when making a non simple CORS request. + cors.allowed.headers + X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers + + + A comma separated list non-standard response headers that will be exposed to XHR2 object. + cors.exposed.headers + Location,Content-Location + + + A flag that suggests if CORS is supported with cookies + cors.support.credentials + true + + + A flag to control logging + cors.logging.enabled + true + + + Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache. + cors.preflight.maxage + 300 + + + + CORS Filter + /* + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml new file mode 100644 index 00000000000..de1a573d1c4 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml @@ -0,0 +1,106 @@ + + + + org.springframework.web.context.ContextLoaderListener + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + + ca.uhn.fhir.jpa.demo.FhirServerConfigDstu2 + + + + + + + spring + org.springframework.web.servlet.DispatcherServlet + + contextClass + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + contextConfigLocation + ca.uhn.fhir.jpa.demo.FhirTesterConfigDstu2 + + 2 + + + + fhirServlet + ca.uhn.fhir.jpa.demo.JpaServerDemoDstu2 + + ImplementationDescription + FHIR JPA Server + + + FhirVersion + DSTU2 + + 1 + + + + fhirServlet + /baseDstu2/* + + + + spring + / + + + + + + + CORS Filter + org.ebaysf.web.cors.CORSFilter + + A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials. + cors.allowed.origins + * + + + A comma separated list of HTTP verbs, using which a CORS request can be made. + cors.allowed.methods + GET,POST,PUT,DELETE,OPTIONS + + + A comma separated list of allowed headers when making a non simple CORS request. + cors.allowed.headers + X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers + + + A comma separated list non-standard response headers that will be exposed to XHR2 object. + cors.exposed.headers + Location,Content-Location + + + A flag that suggests if CORS is supported with cookies + cors.support.credentials + true + + + A flag to control logging + cors.logging.enabled + true + + + Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache. + cors.preflight.maxage + 300 + + + + CORS Filter + /* + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd new file mode 100644 index 00000000000..9fb587749ce --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd @@ -0,0 +1,2419 @@ + + + + + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved. + + The contents of this file are subject to the terms of either the + GNU General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with + the License. You can obtain a copy of the License at + https://glassfish.dev.java.net/public/CDDL+GPL.html or + glassfish/bootstrap/legal/LICENSE.txt. See the License for the + specific language governing permissions and limitations under the + License. + + When distributing the software, include this License Header + Notice in each file and include the License file at + glassfish/bootstrap/legal/LICENSE.txt. Sun designates this + particular file as subject to the "Classpath" exception as + provided by Sun in the GPL Version 2 section of the License file + that accompanied this code. If applicable, add the following + below the License Header, with the fields enclosed by brackets [] + replaced by your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + If you wish your version of this file to be governed by only the + CDDL or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this + distribution under the [CDDL or GPL Version 2] license." If you + don't indicate a single choice of license, a recipient has the + option to distribute your version of this file under either the + CDDL, the GPL Version 2 or to extend the choice of license to its + licensees as provided above. However, if you add GPL Version 2 + code and therefore, elected the GPL Version 2 license, then the + option applies only if the new code is made subject to such + option by the copyright holder. + + + + + + + + The following definitions that appear in the common + shareable schema(s) of Java EE deployment descriptors should be + interpreted with respect to the context they are included: + + Deployment Component may indicate one of the following: + java ee application; + application client; + web application; + enterprise bean; + resource adapter; + + Deployment File may indicate one of the following: + ear file; + war file; + jar file; + rar file; + + + + + + + + + + + This group keeps the usage of the contained description related + elements consistent across Java EE deployment descriptors. + + All elements may occur multiple times with different languages, + to support localization of the content. + + + + + + + + + + + + + + + This group keeps the usage of the contained JNDI environment + reference elements consistent across Java EE deployment descriptors. + + + + + + + + + + + + + + + + + + + + + + + This group collects elements that are common to most + JNDI resource elements. + + + + + + + + + + The JNDI name to be looked up to resolve a resource reference. + + + + + + + + + + + + This group collects elements that are common to all the + JNDI resource elements. It does not include the lookup-name + element, that is only applicable to some resource elements. + + + + + + + + + A product specific name that this resource should be + mapped to. The name of this resource, as defined by the + resource's name element or defaulted, is a name that is + local to the application component using the resource. + (It's a name in the JNDI java:comp/env namespace.) Many + application servers provide a way to map these local + names to names of resources known to the application + server. This mapped name is often a global JNDI name, + but may be a name of any form. + + Application servers are not required to support any + particular form or type of mapped name, nor the ability + to use mapped names. The mapped name is + product-dependent and often installation-dependent. No + use of a mapped name is portable. + + + + + + + + + + + + + + + + Configuration of a DataSource. + + + + + + + + + Description of this DataSource. + + + + + + + + + The name element specifies the JNDI name of the + data source being defined. + + + + + + + + + DataSource, XADataSource or ConnectionPoolDataSource + implementation class. + + + + + + + + + Database server name. + + + + + + + + + Port number where a server is listening for requests. + + + + + + + + + Name of a database on a server. + + + + + + + + url property is specified + along with other standard DataSource properties + such as serverName, databaseName + and portNumber, the more specific properties will + take precedence and url will be ignored. + + ]]> + + + + + + + + User name to use for connection authentication. + + + + + + + + + Password to use for connection authentication. + + + + + + + + + JDBC DataSource property. This may be a vendor-specific + property or a less commonly used DataSource property. + + + + + + + + + Sets the maximum time in seconds that this data source + will wait while attempting to connect to a database. + + + + + + + + + Set to false if connections should not participate in + transactions. + + + + + + + + + Isolation level for connections. + + + + + + + + + Number of connections that should be created when a + connection pool is initialized. + + + + + + + + + Maximum number of connections that should be concurrently + allocated for a connection pool. + + + + + + + + + Minimum number of connections that should be concurrently + allocated for a connection pool. + + + + + + + + + The number of seconds that a physical connection should + remain unused in the pool before the connection is + closed for a connection pool. + + + + + + + + + The total number of statements that a connection pool + should keep open. + + + + + + + + + + + + + + + + The description type is used by a description element to + provide text describing the parent element. The elements + that use this type should include any information that the + Deployment Component's Deployment File file producer wants + to provide to the consumer of the Deployment Component's + Deployment File (i.e., to the Deployer). Typically, the + tools used by such a Deployment File consumer will display + the description when processing the parent element that + contains the description. + + The lang attribute defines the language that the + description is provided in. The default value is "en" (English). + + + + + + + + + + + + + + + This type defines a dewey decimal that is used + to describe versions of documents. + + + + + + + + + + + + + + + + Employee Self Service + + + The value of the xml:lang attribute is "en" (English) by default. + + ]]> + + + + + + + + + + + + + + + + EmployeeRecord + + ../products/product.jar#ProductEJB + + ]]> + + + + + + + + + + + + + + + The ejb-local-refType is used by ejb-local-ref elements for + the declaration of a reference to an enterprise bean's local + home or to the local business interface of a 3.0 bean. + The declaration consists of: + + - an optional description + - the EJB reference name used in the code of the Deployment + Component that's referencing the enterprise bean. + - the optional expected type of the referenced enterprise bean + - the optional expected local interface of the referenced + enterprise bean or the local business interface of the + referenced enterprise bean. + - the optional expected local home interface of the referenced + enterprise bean. Not applicable if this ejb-local-ref refers + to the local business interface of a 3.0 bean. + - optional ejb-link information, used to specify the + referenced enterprise bean + - optional elements to define injection of the named enterprise + bean into a component field or property. + + + + + + + + + + + + + + + + + + + + + + ejb/Payroll + + ]]> + + + + + + + + + + + + + + + The ejb-refType is used by ejb-ref elements for the + declaration of a reference to an enterprise bean's home or + to the remote business interface of a 3.0 bean. + The declaration consists of: + + - an optional description + - the EJB reference name used in the code of + the Deployment Component that's referencing the enterprise + bean. + - the optional expected type of the referenced enterprise bean + - the optional remote interface of the referenced enterprise bean + or the remote business interface of the referenced enterprise + bean + - the optional expected home interface of the referenced + enterprise bean. Not applicable if this ejb-ref + refers to the remote business interface of a 3.0 bean. + - optional ejb-link information, used to specify the + referenced enterprise bean + - optional elements to define injection of the named enterprise + bean into a component field or property + + + + + + + + + + + + + + + + + + + + + + + The ejb-ref-typeType contains the expected type of the + referenced enterprise bean. + + The ejb-ref-type designates a value + that must be one of the following: + + Entity + Session + + + + + + + + + + + + + + + + + + + This type is used to designate an empty + element when used. + + + + + + + + + + + + + + The env-entryType is used to declare an application's + environment entry. The declaration consists of an optional + description, the name of the environment entry, a type + (optional if the value is injected, otherwise required), and + an optional value. + + It also includes optional elements to define injection of + the named resource into fields or JavaBeans properties. + + If a value is not specified and injection is requested, + no injection will occur and no entry of the specified name + will be created. This allows an initial value to be + specified in the source code without being incorrectly + changed when no override has been specified. + + If a value is not specified and no injection is requested, + a value must be supplied during deployment. + + This type is used by env-entry elements. + + + + + + + + + minAmount + + ]]> + + + + + + + java.lang.Integer + + ]]> + + + + + + + 100.00 + + ]]> + + + + + + + + + + + + + + + java.lang.Boolean + java.lang.Class + com.example.Color + + ]]> + + + + + + + + + + + + + + + The elements that use this type designate the name of a + Java class or interface. The name is in the form of a + "binary name", as defined in the JLS. This is the form + of name used in Class.forName(). Tools that need the + canonical name (the name used in source code) will need + to convert this binary name to the canonical name. + + + + + + + + + + + + + + + + This type defines four different values which can designate + boolean values. This includes values yes and no which are + not designated by xsd:boolean + + + + + + + + + + + + + + + + + + + + + The icon type contains small-icon and large-icon elements + that specify the file names for small and large GIF, JPEG, + or PNG icon images used to represent the parent element in a + GUI tool. + + The xml:lang attribute defines the language that the + icon file names are provided in. Its value is "en" (English) + by default. + + + + + + + + employee-service-icon16x16.jpg + + ]]> + + + + + + + employee-service-icon32x32.jpg + + ]]> + + + + + + + + + + + + + + + + An injection target specifies a class and a name within + that class into which a resource should be injected. + + The injection target class specifies the fully qualified + class name that is the target of the injection. The + Java EE specifications describe which classes can be an + injection target. + + The injection target name specifies the target within + the specified class. The target is first looked for as a + JavaBeans property name. If not found, the target is + looked for as a field name. + + The specified resource will be injected into the target + during initialization of the class by either calling the + set method for the target property or by setting a value + into the named field. + + + + + + + + + + + + + + The following transaction isolation levels are allowed + (see documentation for the java.sql.Connection interface): + TRANSACTION_READ_UNCOMMITTED + TRANSACTION_READ_COMMITTED + TRANSACTION_REPEATABLE_READ + TRANSACTION_SERIALIZABLE + + + + + + + + + + + + + + + + + + + The java-identifierType defines a Java identifier. + The users of this type should further verify that + the content does not contain Java reserved keywords. + + + + + + + + + + + + + + + + + + This is a generic type that designates a Java primitive + type or a fully qualified name of a Java interface/type, + or an array of such types. + + + + + + + + + + + + + + + + + : + + Example: + + jdbc:mysql://localhost:3307/testdb + + ]]> + + + + + + + + + + + + + + + + + The jndi-nameType type designates a JNDI name in the + Deployment Component's environment and is relative to the + java:comp/env context. A JNDI name must be unique within the + Deployment Component. + + + + + + + + + + + + + + + com.aardvark.payroll.PayrollHome + + ]]> + + + + + + + + + + + + + + + The lifecycle-callback type specifies a method on a + class to be called when a lifecycle event occurs. + Note that each class may have only one lifecycle callback + method for any given event and that the method may not + be overloaded. + + If the lifefycle-callback-class element is missing then + the class defining the callback is assumed to be the + component class in scope at the place in the descriptor + in which the callback definition appears. + + + + + + + + + + + + + + + + + The listenerType indicates the deployment properties for a web + application listener bean. + + + + + + + + + + The listener-class element declares a class in the + application must be registered as a web + application listener bean. The value is the fully + qualified classname of the listener class. + + + + + + + + + + + + + + + + The localType defines the fully-qualified name of an + enterprise bean's local interface. + + + + + + + + + + + + + + + + The local-homeType defines the fully-qualified + name of an enterprise bean's local home interface. + + + + + + + + + + + + + + + + This type is a general type that can be used to declare + parameter/value lists. + + + + + + + + + + The param-name element contains the name of a + parameter. + + + + + + + + + The param-value element contains the value of a + parameter. + + + + + + + + + + + + + + + + The elements that use this type designate either a relative + path or an absolute path starting with a "/". + + In elements that specify a pathname to a file within the + same Deployment File, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the Deployment File's namespace. Absolute filenames (i.e., + those starting with "/") also specify names in the root of + the Deployment File's namespace. In general, relative names + are preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + + + myPersistenceContext + + + + + myPersistenceContext + + PersistenceUnit1 + + Extended + + + ]]> + + + + + + + + + The persistence-context-ref-name element specifies + the name of a persistence context reference; its + value is the environment entry name used in + Deployment Component code. The name is a JNDI name + relative to the java:comp/env context. + + + + + + + + + The Application Assembler(or BeanProvider) may use the + following syntax to avoid the need to rename persistence + units to have unique names within a Java EE application. + + The Application Assembler specifies the pathname of the + root of the persistence.xml file for the referenced + persistence unit and appends the name of the persistence + unit separated from the pathname by #. The pathname is + relative to the referencing application component jar file. + In this manner, multiple persistence units with the same + persistence unit name may be uniquely identified when the + Application Assembler cannot change persistence unit names. + + + + + + + + + + Used to specify properties for the container or persistence + provider. Vendor-specific properties may be included in + the set of properties. Properties that are not recognized + by a vendor must be ignored. Entries that make use of the + namespace javax.persistence and its subnamespaces must not + be used for vendor-specific properties. The namespace + javax.persistence is reserved for use by the specification. + + + + + + + + + + + + + + + + + The persistence-context-typeType specifies the transactional + nature of a persistence context reference. + + The value of the persistence-context-type element must be + one of the following: + Transaction + Extended + + + + + + + + + + + + + + + + + + + Specifies a name/value pair. + + + + + + + + + + + + + + + + + + + + myPersistenceUnit + + + + + myPersistenceUnit + + PersistenceUnit1 + + + + ]]> + + + + + + + + + The persistence-unit-ref-name element specifies + the name of a persistence unit reference; its + value is the environment entry name used in + Deployment Component code. The name is a JNDI name + relative to the java:comp/env context. + + + + + + + + + The Application Assembler(or BeanProvider) may use the + following syntax to avoid the need to rename persistence + units to have unique names within a Java EE application. + + The Application Assembler specifies the pathname of the + root of the persistence.xml file for the referenced + persistence unit and appends the name of the persistence + unit separated from the pathname by #. The pathname is + relative to the referencing application component jar file. + In this manner, multiple persistence units with the same + persistence unit name may be uniquely identified when the + Application Assembler cannot change persistence unit names. + + + + + + + + + + + + + + + + com.wombat.empl.EmployeeService + + ]]> + + + + + + + + + + + + + + + jms/StockQueue + + javax.jms.Queue + + + + ]]> + + + + + + + + + The resource-env-ref-name element specifies the name + of a resource environment reference; its value is + the environment entry name used in + the Deployment Component code. The name is a JNDI + name relative to the java:comp/env context and must + be unique within a Deployment Component. + + + + + + + + + The resource-env-ref-type element specifies the type + of a resource environment reference. It is the + fully qualified name of a Java language class or + interface. + + + + + + + + + + + + + + + + + jdbc/EmployeeAppDB + javax.sql.DataSource + Container + Shareable + + + ]]> + + + + + + + + + The res-ref-name element specifies the name of a + resource manager connection factory reference. + The name is a JNDI name relative to the + java:comp/env context. + The name must be unique within a Deployment File. + + + + + + + + + The res-type element specifies the type of the data + source. The type is specified by the fully qualified + Java language class or interface + expected to be implemented by the data source. + + + + + + + + + + + + + + + + + + + The res-authType specifies whether the Deployment Component + code signs on programmatically to the resource manager, or + whether the Container will sign on to the resource manager + on behalf of the Deployment Component. In the latter case, + the Container uses information that is supplied by the + Deployer. + + The value must be one of the two following: + + Application + Container + + + + + + + + + + + + + + + + + + + The res-sharing-scope type specifies whether connections + obtained through the given resource manager connection + factory reference can be shared. The value, if specified, + must be one of the two following: + + Shareable + Unshareable + + The default value is Shareable. + + + + + + + + + + + + + + + + + + + The run-asType specifies the run-as identity to be + used for the execution of a component. It contains an + optional description, and the name of a security role. + + + + + + + + + + + + + + + + + + The role-nameType designates the name of a security role. + + The name must conform to the lexical rules for a token. + + + + + + + + + + + + + + + + + This role includes all employees who are authorized + to access the employee service application. + + employee + + + ]]> + + + + + + + + + + + + + + + + + The security-role-refType contains the declaration of a + security role reference in a component's or a + Deployment Component's code. The declaration consists of an + optional description, the security role name used in the + code, and an optional link to a security role. If the + security role is not specified, the Deployer must choose an + appropriate security role. + + + + + + + + + + The value of the role-name element must be the String used + as the parameter to the + EJBContext.isCallerInRole(String roleName) method or the + HttpServletRequest.isUserInRole(String role) method. + + + + + + + + + The role-link element is a reference to a defined + security role. The role-link element must contain + the name of one of the security roles defined in the + security-role elements. + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:QName. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:boolean. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:NMTOKEN. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:anyURI. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:integer. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:positiveInteger. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:nonNegativeInteger. + + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:string. + + + + + + + + + + + + + + + + + + This is a special string datatype that is defined by Java EE as + a base type for defining collapsed strings. When schemas + require trailing/leading space elimination as well as + collapsing the existing whitespace, this base type may be + used. + + + + + + + + + + + + + + + + + + This simple type designates a boolean with only two + permissible values + + - true + - false + + + + + + + + + + + + + + + + + + The url-patternType contains the url pattern of the mapping. + It must follow the rules specified in Section 11.2 of the + Servlet API Specification. This pattern is assumed to be in + URL-decoded form and must not contain CR(#xD) or LF(#xA). + If it contains those characters, the container must inform + the developer with a descriptive error message. + The container must preserve all characters including whitespaces. + + + + + + + + + + + + + + + + CorporateStocks + + + + ]]> + + + + + + + + + The message-destination-name element specifies a + name for a message destination. This name must be + unique among the names of message destinations + within the Deployment File. + + + + + + + + + A product specific name that this message destination + should be mapped to. Each message-destination-ref + element that references this message destination will + define a name in the namespace of the referencing + component or in one of the other predefined namespaces. + Many application servers provide a way to map these + local names to names of resources known to the + application server. This mapped name is often a global + JNDI name, but may be a name of any form. Each of the + local names should be mapped to this same global name. + + Application servers are not required to support any + particular form or type of mapped name, nor the ability + to use mapped names. The mapped name is + product-dependent and often installation-dependent. No + use of a mapped name is portable. + + + + + + + + + The JNDI name to be looked up to resolve the message destination. + + + + + + + + + + + + + + + + jms/StockQueue + + javax.jms.Queue + + Consumes + + CorporateStocks + + + + ]]> + + + + + + + + + The message-destination-ref-name element specifies + the name of a message destination reference; its + value is the environment entry name used in + Deployment Component code. + + + + + + + + + + + + + + + + + + + + The message-destination-usageType specifies the use of the + message destination indicated by the reference. The value + indicates whether messages are consumed from the message + destination, produced for the destination, or both. The + Assembler makes use of this information in linking producers + of a destination with its consumers. + + The value of the message-destination-usage element must be + one of the following: + Consumes + Produces + ConsumesProduces + + + + + + + + + + + + + + + + + + + javax.jms.Queue + + + ]]> + + + + + + + + + + + + + + + The message-destination-linkType is used to link a message + destination reference or message-driven bean to a message + destination. + + The Assembler sets the value to reflect the flow of messages + between producers and consumers in the application. + + The value must be the message-destination-name of a message + destination in the same Deployment File or in another + Deployment File in the same Java EE application unit. + + Alternatively, the value may be composed of a path name + specifying a Deployment File containing the referenced + message destination with the message-destination-name of the + destination appended and separated from the path name by + "#". The path name is relative to the Deployment File + containing Deployment Component that is referencing the + message destination. This allows multiple message + destinations with the same name to be uniquely identified. + + + + + + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd new file mode 100644 index 00000000000..fa41e4266f1 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd @@ -0,0 +1,389 @@ + + + + + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved. + + The contents of this file are subject to the terms of either the + GNU General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with + the License. You can obtain a copy of the License at + https://glassfish.dev.java.net/public/CDDL+GPL.html or + glassfish/bootstrap/legal/LICENSE.txt. See the License for the + specific language governing permissions and limitations under the + License. + + When distributing the software, include this License Header + Notice in each file and include the License file at + glassfish/bootstrap/legal/LICENSE.txt. Sun designates this + particular file as subject to the "Classpath" exception as + provided by Sun in the GPL Version 2 section of the License file + that accompanied this code. If applicable, add the following + below the License Header, with the fields enclosed by brackets [] + replaced by your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + If you wish your version of this file to be governed by only the + CDDL or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this + distribution under the [CDDL or GPL Version 2] license." If you + don't indicate a single choice of license, a recipient has the + option to distribute your version of this file under either the + CDDL, the GPL Version 2 or to extend the choice of license to its + licensees as provided above. However, if you add GPL Version 2 + code and therefore, elected the GPL Version 2 license, then the + option applies only if the new code is made subject to such + option by the copyright holder. + + + + + + + + This is the XML Schema for the JSP 2.2 deployment descriptor + types. The JSP 2.2 schema contains all the special + structures and datatypes that are necessary to use JSP files + from a web application. + + The contents of this schema is used by the web-common_3_0.xsd + file to define JSP specific content. + + + + + + + + The following conventions apply to all Java EE + deployment descriptor elements unless indicated otherwise. + + - In elements that specify a pathname to a file within the + same JAR file, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the JAR file's namespace. Absolute filenames (i.e., those + starting with "/") also specify names in the root of the + JAR file's namespace. In general, relative names are + preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + The jsp-configType is used to provide global configuration + information for the JSP files in a web application. It has + two subelements, taglib and jsp-property-group. + + + + + + + + + + + + + + + + + + The jsp-file element contains the full path to a JSP file + within the web application beginning with a `/'. + + + + + + + + + + + + + + + + The jsp-property-groupType is used to group a number of + files so they can be given global property information. + All files so described are deemed to be JSP files. The + following additional properties can be described: + + - Control whether EL is ignored. + - Control whether scripting elements are invalid. + - Indicate pageEncoding information. + - Indicate that a resource is a JSP document (XML). + - Prelude and Coda automatic includes. + - Control whether the character sequence #{ is allowed + when used as a String literal. + - Control whether template text containing only + whitespaces must be removed from the response output. + - Indicate the default contentType information. + - Indicate the default buffering model for JspWriter + - Control whether error should be raised for the use of + undeclared namespaces in a JSP page. + + + + + + + + + + + Can be used to easily set the isELIgnored + property of a group of JSP pages. By default, the + EL evaluation is enabled for Web Applications using + a Servlet 2.4 or greater web.xml, and disabled + otherwise. + + + + + + + + + The valid values of page-encoding are those of the + pageEncoding page directive. It is a + translation-time error to name different encodings + in the pageEncoding attribute of the page directive + of a JSP page and in a JSP configuration element + matching the page. It is also a translation-time + error to name different encodings in the prolog + or text declaration of a document in XML syntax and + in a JSP configuration element matching the document. + It is legal to name the same encoding through + mulitple mechanisms. + + + + + + + + + Can be used to easily disable scripting in a + group of JSP pages. By default, scripting is + enabled. + + + + + + + + + If true, denotes that the group of resources + that match the URL pattern are JSP documents, + and thus must be interpreted as XML documents. + If false, the resources are assumed to not + be JSP documents, unless there is another + property group that indicates otherwise. + + + + + + + + + The include-prelude element is a context-relative + path that must correspond to an element in the + Web Application. When the element is present, + the given path will be automatically included (as + in an include directive) at the beginning of each + JSP page in this jsp-property-group. + + + + + + + + + The include-coda element is a context-relative + path that must correspond to an element in the + Web Application. When the element is present, + the given path will be automatically included (as + in an include directive) at the end of each + JSP page in this jsp-property-group. + + + + + + + + + The character sequence #{ is reserved for EL expressions. + Consequently, a translation error occurs if the #{ + character sequence is used as a String literal, unless + this element is enabled (true). Disabled (false) by + default. + + + + + + + + + Indicates that template text containing only whitespaces + must be removed from the response output. It has no + effect on JSP documents (XML syntax). Disabled (false) + by default. + + + + + + + + + The valid values of default-content-type are those of the + contentType page directive. It specifies the default + response contentType if the page directive does not include + a contentType attribute. + + + + + + + + + The valid values of buffer are those of the + buffer page directive. It specifies if buffering should be + used for the output to response, and if so, the size of the + buffer to use. + + + + + + + + + The default behavior when a tag with unknown namespace is used + in a JSP page (regular syntax) is to silently ignore it. If + set to true, then an error must be raised during the translation + time when an undeclared tag is used in a JSP page. Disabled + (false) by default. + + + + + + + + + + + + + + + + The taglibType defines the syntax for declaring in + the deployment descriptor that a tag library is + available to the application. This can be done + to override implicit map entries from TLD files and + from the container. + + + + + + + + + A taglib-uri element describes a URI identifying a + tag library used in the web application. The body + of the taglib-uri element may be either an + absolute URI specification, or a relative URI. + There should be no entries in web.xml with the + same taglib-uri value. + + + + + + + + + the taglib-location element contains the location + (as a resource relative to the root of the web + application) where to find the Tag Library + Description file for the tag library. + + + + + + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd new file mode 100644 index 00000000000..bbcdf43cd3a --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd @@ -0,0 +1,272 @@ + + + + + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved. + + The contents of this file are subject to the terms of either the + GNU General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with + the License. You can obtain a copy of the License at + https://glassfish.dev.java.net/public/CDDL+GPL.html or + glassfish/bootstrap/legal/LICENSE.txt. See the License for the + specific language governing permissions and limitations under the + License. + + When distributing the software, include this License Header + Notice in each file and include the License file at + glassfish/bootstrap/legal/LICENSE.txt. Sun designates this + particular file as subject to the "Classpath" exception as + provided by Sun in the GPL Version 2 section of the License file + that accompanied this code. If applicable, add the following + below the License Header, with the fields enclosed by brackets [] + replaced by your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + If you wish your version of this file to be governed by only the + CDDL or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this + distribution under the [CDDL or GPL Version 2] license." If you + don't indicate a single choice of license, a recipient has the + option to distribute your version of this file under either the + CDDL, the GPL Version 2 or to extend the choice of license to its + licensees as provided above. However, if you add GPL Version 2 + code and therefore, elected the GPL Version 2 license, then the + option applies only if the new code is made subject to such + option by the copyright holder. + + + + + + + + ... + + + The instance documents may indicate the published version of + the schema using the xsi:schemaLocation attribute for Java EE + namespace with the following location: + + http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd + + ]]> + + + + + + + The following conventions apply to all Java EE + deployment descriptor elements unless indicated otherwise. + + - In elements that specify a pathname to a file within the + same JAR file, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the JAR file's namespace. Absolute filenames (i.e., those + starting with "/") also specify names in the root of the + JAR file's namespace. In general, relative names are + preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + The web-app element is the root of the deployment + descriptor for a web application. Note that the sub-elements + of this element can be in the arbitrary order. Because of + that, the multiplicity of the elements of distributable, + session-config, welcome-file-list, jsp-config, login-config, + and locale-encoding-mapping-list was changed from "?" to "*" + in this schema. However, the deployment descriptor instance + file must not contain multiple elements of session-config, + jsp-config, and login-config. When there are multiple elements of + welcome-file-list or locale-encoding-mapping-list, the container + must concatenate the element contents. The multiple occurence + of the element distributable is redundant and the container + treats that case exactly in the same way when there is only + one distributable. + + + + + + + + The servlet element contains the name of a servlet. + The name must be unique within the web application. + + + + + + + + + + + The filter element contains the name of a filter. + The name must be unique within the web application. + + + + + + + + + + + The ejb-local-ref-name element contains the name of an EJB + reference. The EJB reference is an entry in the web + application's environment and is relative to the + java:comp/env context. The name must be unique within + the web application. + + It is recommended that name is prefixed with "ejb/". + + + + + + + + + + + The ejb-ref-name element contains the name of an EJB + reference. The EJB reference is an entry in the web + application's environment and is relative to the + java:comp/env context. The name must be unique within + the web application. + + It is recommended that name is prefixed with "ejb/". + + + + + + + + + + + The resource-env-ref-name element specifies the name of + a resource environment reference; its value is the + environment entry name used in the web application code. + The name is a JNDI name relative to the java:comp/env + context and must be unique within a web application. + + + + + + + + + + + The message-destination-ref-name element specifies the name of + a message destination reference; its value is the + environment entry name used in the web application code. + The name is a JNDI name relative to the java:comp/env + context and must be unique within a web application. + + + + + + + + + + + The res-ref-name element specifies the name of a + resource manager connection factory reference. The name + is a JNDI name relative to the java:comp/env context. + The name must be unique within a web application. + + + + + + + + + + + The env-entry-name element contains the name of a web + application's environment entry. The name is a JNDI + name relative to the java:comp/env context. The name + must be unique within a web application. + + + + + + + + + + + A role-name-key is specified to allow the references + from the security-role-refs. + + + + + + + + + + + The keyref indicates the references from + security-role-ref to a specified role-name. + + + + + + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd new file mode 100644 index 00000000000..f994bc2c651 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd @@ -0,0 +1,1575 @@ + + + + + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved. + + The contents of this file are subject to the terms of either the + GNU General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with + the License. You can obtain a copy of the License at + https://glassfish.dev.java.net/public/CDDL+GPL.html or + glassfish/bootstrap/legal/LICENSE.txt. See the License for the + specific language governing permissions and limitations under the + License. + + When distributing the software, include this License Header + Notice in each file and include the License file at + glassfish/bootstrap/legal/LICENSE.txt. Sun designates this + particular file as subject to the "Classpath" exception as + provided by Sun in the GPL Version 2 section of the License file + that accompanied this code. If applicable, add the following + below the License Header, with the fields enclosed by brackets [] + replaced by your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + If you wish your version of this file to be governed by only the + CDDL or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this + distribution under the [CDDL or GPL Version 2] license." If you + don't indicate a single choice of license, a recipient has the + option to distribute your version of this file under either the + CDDL, the GPL Version 2 or to extend the choice of license to its + licensees as provided above. However, if you add GPL Version 2 + code and therefore, elected the GPL Version 2 license, then the + option applies only if the new code is made subject to such + option by the copyright holder. + + + + + + + + ... + + + The instance documents may indicate the published version of + the schema using the xsi:schemaLocation attribute for Java EE + namespace with the following location: + + http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd + + ]]> + + + + + + + The following conventions apply to all Java EE + deployment descriptor elements unless indicated otherwise. + + - In elements that specify a pathname to a file within the + same JAR file, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the JAR file's namespace. Absolute filenames (i.e., those + starting with "/") also specify names in the root of the + JAR file's namespace. In general, relative names are + preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + + + + The context-param element contains the declaration + of a web application's servlet context + initialization parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The metadata-complete attribute defines whether this + deployment descriptor and other related deployment + descriptors for this module (e.g., web service + descriptors) are complete, or whether the class + files available to this module and packaged with + this application should be examined for annotations + that specify deployment information. + + If metadata-complete is set to "true", the deployment + tool must ignore any annotations that specify deployment + information, which might be present in the class files + of the application. + + If metadata-complete is not specified or is set to + "false", the deployment tool must examine the class + files of the application for annotations, as + specified by the specifications. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The auth-constraintType indicates the user roles that + should be permitted access to this resource + collection. The role-name used here must either correspond + to the role-name of one of the security-role elements + defined for this web application, or be the specially + reserved role-name "*" that is a compact syntax for + indicating all roles in the web application. If both "*" + and rolenames appear, the container interprets this as all + roles. If no roles are defined, no user is allowed access + to the portion of the web application described by the + containing security-constraint. The container matches + role names case sensitively when determining access. + + + + + + + + + + + + + + + + + + The auth-methodType is used to configure the authentication + mechanism for the web application. As a prerequisite to + gaining access to any web resources which are protected by + an authorization constraint, a user must have authenticated + using the configured mechanism. Legal values are "BASIC", + "DIGEST", "FORM", "CLIENT-CERT", or a vendor-specific + authentication scheme. + + Used in: login-config + + + + + + + + + + + + + + + + The dispatcher has five legal values: FORWARD, REQUEST, + INCLUDE, ASYNC, and ERROR. + + A value of FORWARD means the Filter will be applied under + RequestDispatcher.forward() calls. + A value of REQUEST means the Filter will be applied under + ordinary client calls to the path or servlet. + A value of INCLUDE means the Filter will be applied under + RequestDispatcher.include() calls. + A value of ASYNC means the Filter will be applied under + calls dispatched from an AsyncContext. + A value of ERROR means the Filter will be applied under the + error page mechanism. + + The absence of any dispatcher elements in a filter-mapping + indicates a default of applying filters only under ordinary + client calls to the path or servlet. + + + + + + + + + + + + + + + + + + + + + + The error-code contains an HTTP error code, ex: 404 + + Used in: error-page + + + + + + + + + + + + + + + + + + + The error-pageType contains a mapping between an error code + or exception type to the path of a resource in the web + application. + + Error-page declarations using the exception-type element in + the deployment descriptor must be unique up to the class name of + the exception-type. Similarly, error-page declarations using the + status-code element must be unique in the deployment descriptor + up to the status code. + + Used in: web-app + + + + + + + + + + + The exception-type contains a fully qualified class + name of a Java exception type. + + + + + + + + + + The location element contains the location of the + resource in the web application relative to the root of + the web application. The value of the location must have + a leading `/'. + + + + + + + + + + + + + + + + The filterType is used to declare a filter in the web + application. The filter is mapped to either a servlet or a + URL pattern in the filter-mapping element, using the + filter-name value to reference. Filters can access the + initialization parameters declared in the deployment + descriptor at runtime via the FilterConfig interface. + + Used in: web-app + + + + + + + + + + + The fully qualified classname of the filter. + + + + + + + + + + The init-param element contains a name/value pair as + an initialization param of a servlet filter + + + + + + + + + + + + + + + + Declaration of the filter mappings in this web + application is done by using filter-mappingType. + The container uses the filter-mapping + declarations to decide which filters to apply to a request, + and in what order. The container matches the request URI to + a Servlet in the normal way. To determine which filters to + apply it matches filter-mapping declarations either on + servlet-name, or on url-pattern for each filter-mapping + element, depending on which style is used. The order in + which filters are invoked is the order in which + filter-mapping declarations that match a request URI for a + servlet appear in the list of filter-mapping elements.The + filter-name value must be the value of the filter-name + sub-elements of one of the filter declarations in the + deployment descriptor. + + + + + + + + + + + + + + + + + + + + + + This type defines a string which contains at least one + character. + + + + + + + + + + + + + + + + + + The logical name of the filter is declare + by using filter-nameType. This name is used to map the + filter. Each filter name is unique within the web + application. + + Used in: filter, filter-mapping + + + + + + + + + + + + + + + + The form-login-configType specifies the login and error + pages that should be used in form based login. If form based + authentication is not used, these elements are ignored. + + Used in: login-config + + + + + + + + + The form-login-page element defines the location in the web + app where the page that can be used for login can be + found. The path begins with a leading / and is interpreted + relative to the root of the WAR. + + + + + + + + + The form-error-page element defines the location in + the web app where the error page that is displayed + when login is not successful can be found. + The path begins with a leading / and is interpreted + relative to the root of the WAR. + + + + + + + + + + + + + A HTTP method type as defined in HTTP 1.1 section 2.2. + + + + + + + + + + + + + + + + + + + + + + + + + + The login-configType is used to configure the authentication + method that should be used, the realm name that should be + used for this application, and the attributes that are + needed by the form login mechanism. + + Used in: web-app + + + + + + + + + + The realm name element specifies the realm name to + use in HTTP Basic authorization. + + + + + + + + + + + + + + + + + The mime-mappingType defines a mapping between an extension + and a mime type. + + Used in: web-app + + + + + + + + The extension element contains a string describing an + extension. example: "txt" + + + + + + + + + + + + + + + + + The mime-typeType is used to indicate a defined mime type. + + Example: + "text/plain" + + Used in: mime-mapping + + + + + + + + + + + + + + + + + + The security-constraintType is used to associate + security constraints with one or more web resource + collections + + Used in: web-app + + + + + + + + + + + + + + + + + + + + The servletType is used to declare a servlet. + It contains the declarative data of a + servlet. If a jsp-file is specified and the load-on-startup + element is present, then the JSP should be precompiled and + loaded. + + Used in: web-app + + + + + + + + + + + + The servlet-class element contains the fully + qualified class name of the servlet. + + + + + + + + + + + + The load-on-startup element indicates that this + servlet should be loaded (instantiated and have + its init() called) on the startup of the web + application. The optional contents of these + element must be an integer indicating the order in + which the servlet should be loaded. If the value + is a negative integer, or the element is not + present, the container is free to load the servlet + whenever it chooses. If the value is a positive + integer or 0, the container must load and + initialize the servlet as the application is + deployed. The container must guarantee that + servlets marked with lower integers are loaded + before servlets marked with higher integers. The + container may choose the order of loading of + servlets with the same load-on-start-up value. + + + + + + + + + + + + + + + + + + + + + The servlet-mappingType defines a mapping between a + servlet and a url pattern. + + Used in: web-app + + + + + + + + + + + + + + + + + + The servlet-name element contains the canonical name of the + servlet. Each servlet name is unique within the web + application. + + + + + + + + + + + + + + + + The session-configType defines the session parameters + for this web application. + + Used in: web-app + + + + + + + + + The session-timeout element defines the default + session timeout interval for all sessions created + in this web application. The specified timeout + must be expressed in a whole number of minutes. + If the timeout is 0 or less, the container ensures + the default behaviour of sessions is never to time + out. If this element is not specified, the container + must set its default timeout period. + + + + + + + + + The cookie-config element defines the configuration of the + session tracking cookies created by this web application. + + + + + + + + + The tracking-mode element defines the tracking modes + for sessions created by this web application + + + + + + + + + + + + + + + + The cookie-configType defines the configuration for the + session tracking cookies of this web application. + + Used in: session-config + + + + + + + + + The name that will be assigned to any session tracking + cookies created by this web application. + The default is JSESSIONID + + + + + + + + + The domain name that will be assigned to any session tracking + cookies created by this web application. + + + + + + + + + The path that will be assigned to any session tracking + cookies created by this web application. + + + + + + + + + The comment that will be assigned to any session tracking + cookies created by this web application. + + + + + + + + + Specifies whether any session tracking cookies created + by this web application will be marked as HttpOnly + + + + + + + + + Specifies whether any session tracking cookies created + by this web application will be marked as secure + even if the request that initiated the corresponding session + is using plain HTTP instead of HTTPS + + + + + + + + + The lifetime (in seconds) that will be assigned to any + session tracking cookies created by this web application. + Default is -1 + + + + + + + + + + + + + + + + The name that will be assigned to any session tracking + cookies created by this web application. + The default is JSESSIONID + + Used in: cookie-config + + + + + + + + + + + + + + + + The domain name that will be assigned to any session tracking + cookies created by this web application. + + Used in: cookie-config + + + + + + + + + + + + + + + + The path that will be assigned to any session tracking + cookies created by this web application. + + Used in: cookie-config + + + + + + + + + + + + + + + + The comment that will be assigned to any session tracking + cookies created by this web application. + + Used in: cookie-config + + + + + + + + + + + + + + + + The tracking modes for sessions created by this web + application + + Used in: session-config + + + + + + + + + + + + + + + + + + + + The transport-guaranteeType specifies that the communication + between client and server should be NONE, INTEGRAL, or + CONFIDENTIAL. NONE means that the application does not + require any transport guarantees. A value of INTEGRAL means + that the application requires that the data sent between the + client and server be sent in such a way that it can't be + changed in transit. CONFIDENTIAL means that the application + requires that the data be transmitted in a fashion that + prevents other entities from observing the contents of the + transmission. In most cases, the presence of the INTEGRAL or + CONFIDENTIAL flag will indicate that the use of SSL is + required. + + Used in: user-data-constraint + + + + + + + + + + + + + + + + + + + + The user-data-constraintType is used to indicate how + data communicated between the client and container should be + protected. + + Used in: security-constraint + + + + + + + + + + + + + + + + + + The elements that use this type designate a path starting + with a "/" and interpreted relative to the root of a WAR + file. + + + + + + + + + + + + + + + This type contains the recognized versions of + web-application supported. It is used to designate the + version of the web application. + + + + + + + + + + + + + + + + The web-resource-collectionType is used to identify the + resources and HTTP methods on those resources to which a + security constraint applies. If no HTTP methods are specified, + then the security constraint applies to all HTTP methods. + If HTTP methods are specified by http-method-omission + elements, the security constraint applies to all methods + except those identified in the collection. + http-method-omission and http-method elements are never + mixed in the same collection. + + Used in: security-constraint + + + + + + + + + The web-resource-name contains the name of this web + resource collection. + + + + + + + + + + + + Each http-method names an HTTP method to which the + constraint applies. + + + + + + + + + Each http-method-omission names an HTTP method to + which the constraint does not apply. + + + + + + + + + + + + + + + + + The welcome-file-list contains an ordered list of welcome + files elements. + + Used in: web-app + + + + + + + + + The welcome-file element contains file name to use + as a default welcome file, such as index.html + + + + + + + + + + + + + The localeType defines valid locale defined by ISO-639-1 + and ISO-3166. + + + + + + + + + + + + + The encodingType defines IANA character sets. + + + + + + + + + + + + + + + + The locale-encoding-mapping-list contains one or more + locale-encoding-mapping(s). + + + + + + + + + + + + + + + + + The locale-encoding-mapping contains locale name and + encoding name. The locale name must be either "Language-code", + such as "ja", defined by ISO-639 or "Language-code_Country-code", + such as "ja_JP". "Country code" is defined by ISO-3166. + + + + + + + + + + + + + + + + + + This element indicates that the ordering sub-element in which + it was placed should take special action regarding the ordering + of this application resource relative to other application + configuration resources. + See section 8.2.2 of the specification for details. + + + + + + + + + + + + + + Please see section 8.2.2 of the specification for details. + + + + + + + + + + + + + + + + + Please see section 8.2.2 of the specification for details. + + + + + + + + + + + + + + + + + This element contains a sequence of "name" elements, each of + which + refers to an application configuration resource by the "name" + declared on its web.xml fragment. This element can also contain + a single "others" element which specifies that this document + comes + before or after other documents within the application. + See section 8.2.2 of the specification for details. + + + + + + + + + + + + + + + + + This element specifies configuration information related to the + handling of multipart/form-data requests. + + + + + + + + + The directory location where uploaded files will be stored + + + + + + + + + The maximum size limit of uploaded files + + + + + + + + + The maximum size limit of multipart/form-data requests + + + + + + + + + The size threshold after which an uploaded file will be + written to disk + + + + + + + + diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd new file mode 100644 index 00000000000..aea7d0db0a4 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd @@ -0,0 +1,287 @@ + + + + + + +
+

About the XML namespace

+ +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+
+
+ + + + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + +
+ + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + +
+ + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ +
+ diff --git a/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java b/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java new file mode 100644 index 00000000000..6a792e9687f --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java @@ -0,0 +1,89 @@ +package ca.uhn.fhir.jpa.demo; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; + +public class ExampleServerIT { + + private static IGenericClient ourClient; + private static FhirContext ourCtx = FhirContext.forDstu2(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerIT.class); + + private static int ourPort; + + private static Server ourServer; + private static String ourServerBase; + + @Test + @Ignore + public void testCreateAndRead() throws IOException { + ourLog.info("Base URL is: http://localhost:" + ourPort + "/baseDstu2"); + String methodName = "testCreateResourceConditional"; + + Patient pt = new Patient(); + StringDt famName = new StringDt(methodName); + List famNames =Arrays.asList(famName); + pt.addName().setFamily(famNames); + IIdType id = ourClient.create().resource(pt).execute().getId(); + + Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute(); + assertEquals(famNames, pt2.getName().get(0).getFamily()); + } + + @AfterClass + public static void afterClass() throws Exception { + ourServer.stop(); + } + + @BeforeClass + public static void beforeClass() throws Exception { + /* + * This runs under maven, and I'm not sure how else to figure out the target directory from code.. + */ + String path = ExampleServerIT.class.getClassLoader().getResource(".keep_hapi-fhir-jpaserver-example").getPath(); + path = new File(path).getParent(); + path = new File(path).getParent(); + path = new File(path).getParent(); + + ourLog.info("Project base path is: {}", path); + + ourPort = RandomServerPortProvider.findFreePort(); + ourServer = new Server(ourPort); + + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath("/"); + //webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml"); + webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-example"); + webAppContext.setParentLoaderPriority(true); + + ourServer.setHandler(webAppContext); + ourServer.start(); + + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + ourServerBase = "http://localhost:" + ourPort + "/baseDstu2"; + ourClient = ourCtx.newRestfulGenericClient(ourServerBase); + ourClient.registerInterceptor(new LoggingInterceptor(true)); + + } + +} diff --git a/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java b/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java new file mode 100644 index 00000000000..b97428b6975 --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java @@ -0,0 +1,36 @@ +package ca.uhn.fhir.jpa.demo; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.ArrayList; +import java.util.List; + +/** + * Provides server ports + */ +public class RandomServerPortProvider { + + private static List ourPorts = new ArrayList(); + + public static int findFreePort() { + ServerSocket server; + try { + server = new ServerSocket(0); + int port = server.getLocalPort(); + ourPorts.add(port); + server.close(); + Thread.sleep(500); + return port; + } catch (IOException e) { + throw new Error(e); + } catch (InterruptedException e) { + throw new Error(e); + } + } + + public static List list() { + return ourPorts; + } + +} + \ No newline at end of file diff --git a/hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example b/hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example new file mode 100644 index 00000000000..e69de29bb2d diff --git a/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt b/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt new file mode 100644 index 00000000000..46269f76f7f --- /dev/null +++ b/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt @@ -0,0 +1 @@ +nothing \ No newline at end of file diff --git a/pom.xml b/pom.xml index e6077336513..a546492191d 100644 --- a/pom.xml +++ b/pom.xml @@ -1896,6 +1896,7 @@ hapi-fhir-jaxrsserver-example hapi-fhir-jpaserver-base hapi-fhir-jpaserver-example + hapi-fhir-jpaserver-dynamic restful-server-example restful-server-example-test hapi-fhir-testpage-overlay From 66b6149bf6285ada538bb28a39b8f71d5123a587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dywicki?= Date: Sat, 30 Dec 2017 00:52:03 +0100 Subject: [PATCH 05/31] Support for negation in search operations #815. --- .../main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 522c169513a..7f6662246e5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -1223,7 +1223,11 @@ public class SearchBuilder implements ISearchBuilder { */ if (StringUtils.isNotBlank(system)) { - singleCodePredicates.add(theBuilder.equal(theFrom.get("mySystem"), system)); + if (modifier != null && modifier == TokenParamModifier.NOT) { + singleCodePredicates.add(theBuilder.notEqual(theFrom.get("mySystem"), system)); + } else { + singleCodePredicates.add(theBuilder.equal(theFrom.get("mySystem"), system)); + } } else if (system == null) { // don't check the system } else { @@ -1232,7 +1236,11 @@ public class SearchBuilder implements ISearchBuilder { } if (StringUtils.isNotBlank(code)) { - singleCodePredicates.add(theBuilder.equal(theFrom.get("myValue"), code)); + if (modifier != null && modifier == TokenParamModifier.NOT) { + singleCodePredicates.add(theBuilder.notEqual(theFrom.get("myValue"), code)); + } else { + singleCodePredicates.add(theBuilder.equal(theFrom.get("myValue"), code)); + } } else { /* * As of HAPI FHIR 1.5, if the client searched for a token with a system but no specified value this means to From 8e3e693d297c36238d8f3a9308ba71176517df07 Mon Sep 17 00:00:00 2001 From: James Daily Date: Mon, 29 Jan 2018 10:37:04 -0500 Subject: [PATCH 06/31] Conformance Statement -> Capability Statement Removed broken link to old conformance.html with link to capabilitysatement.html. Hope this is true that HAPI exports a capability statement now as of STU3? Note - there are still references to Conformance Statement elsewhere within the documentation (such as doc_rest_operations.xml), but they contained coding / server behavior assertions that I was not comfortable modifying. --- src/site/xdoc/doc_rest_server.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/site/xdoc/doc_rest_server.xml b/src/site/xdoc/doc_rest_server.xml index 27d6aa2e6c4..d0a535afdf1 100644 --- a/src/site/xdoc/doc_rest_server.xml +++ b/src/site/xdoc/doc_rest_server.xml @@ -204,7 +204,8 @@

The HAPI FHIR RESTful Server will automatically export a - conformance statement, + capability statement (or a + conformance statement for DSTU2 and prior), as required by the FHIR Specification.

From a8f3c2efb62336cd2b55671c5a3f80d8bebe5b52 Mon Sep 17 00:00:00 2001 From: patrick-werner Date: Wed, 21 Feb 2018 16:03:31 +0100 Subject: [PATCH 07/31] added Test for #11 to Dstu3 and R4 --- .../uhn/fhir/parser/XmlParserDstu3Test.java | 22 ++++++++++++++++ .../src/test/java/z/TestTest.java | 25 ------------------- .../ca/uhn/fhir/parser/XmlParserR4Test.java | 24 ++++++++++++++++++ 3 files changed, 46 insertions(+), 25 deletions(-) delete mode 100644 hapi-fhir-structures-dstu3/src/test/java/z/TestTest.java diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java index 8cd9f644d03..4414ec18937 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java @@ -51,6 +51,8 @@ import java.util.*; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder; import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; @@ -3242,6 +3244,26 @@ public class XmlParserDstu3Test { } } + /** + * See #11 + */ + @Test + public void testDuplicateContainedResources() { + + Observation resA = new Observation(); + resA.setComment("A"); + + Observation resB = new Observation(); + resB.setComment("B"); + resB.addBasedOn(new Reference(resA)); + resB.addBasedOn(new Reference(resA)); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resB); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + } /** * See #551 */ diff --git a/hapi-fhir-structures-dstu3/src/test/java/z/TestTest.java b/hapi-fhir-structures-dstu3/src/test/java/z/TestTest.java deleted file mode 100644 index 82132d8609a..00000000000 --- a/hapi-fhir-structures-dstu3/src/test/java/z/TestTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package z; - -import org.junit.AfterClass; -import org.junit.Ignore; -import org.junit.Test; - -import ca.uhn.fhir.util.TestUtil; - -public class TestTest { - - @Test - @Ignore - public void testId() throws InterruptedException { - Thread.sleep(1000000); - } - - - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); - } - - - -} diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java index c2f4bd90413..908d8626a9b 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java @@ -4,17 +4,21 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.util.TestUtil; import com.google.common.collect.Sets; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Reference; import org.junit.AfterClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder; import static org.junit.Assert.*; public class XmlParserR4Test { @@ -161,6 +165,26 @@ public class XmlParserR4Test { } + /** + * See #11 + */ + @Test + public void testDuplicateContainedResources() { + + Observation resA = new Observation(); + resA.setComment("A"); + + Observation resB = new Observation(); + resB.setComment("B"); + resB.addHasMember(new Reference(resA)); + resB.addHasMember(new Reference(resA)); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resB); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + } @AfterClass public static void afterClassClearContext() { From 0af95842a940c7732fb97b728a1e6d5f3ff59924 Mon Sep 17 00:00:00 2001 From: patrick-werner Date: Thu, 22 Feb 2018 12:23:42 +0100 Subject: [PATCH 08/31] fixes #853 performer validation implementation is now list based added Test --- .../fhir/r4/validation/InstanceValidator.java | 4 +++- .../validation/FhirInstanceValidatorR4Test.java | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java index 985d77a87b6..1b6517746d6 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java @@ -3538,7 +3538,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat // all observations should have a subject, a performer, and a time bpCheck(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), element.getNamedChild("subject") != null, "All observations should have a subject"); - bpCheck(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), element.getNamedChild("performer") != null, "All observations should have a performer"); + List performer = new ArrayList(); + element.getNamedChildren("performer", performer); + bpCheck(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !performer.isEmpty(), "All observations should have a performer"); bpCheck(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), element.getNamedChild("effectiveDateTime") != null || element.getNamedChild("effectivePeriod") != null, "All observations should have an effectiveDateTime or an effectivePeriod"); } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java index 9bb949c1381..a9c9080e035 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java @@ -208,6 +208,23 @@ public class FhirInstanceValidatorR4Test { } + /** + * See #853 + */ + @Test + public void testObservationsWithMultiplePerformers() { + Observation observation = new Observation(); + observation.setStatus(ObservationStatus.FINAL); + observation.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://system").setCode("code"))); + Practitioner p1 = new Practitioner(); + Practitioner p2 = new Practitioner(); + observation.addPerformer(new Reference(p1)); + observation.addPerformer(new Reference(p2)); + + ValidationResult output = myVal.validateWithResult(observation); + List errors = logResultsAndReturnNonInformationalOnes(output); + assertThat(errors, empty()); + } @Test public void testBase64Invalid() { From 66ebfa0ed306fa2e4e5f6987cd037ae086243745 Mon Sep 17 00:00:00 2001 From: jpoth Date: Tue, 27 Feb 2018 18:52:47 +0100 Subject: [PATCH 09/31] Implement #826 - add OSGI support and Apache Karaf features with integration tests --- hapi-fhir-base/pom.xml | 17 +- hapi-fhir-client/pom.xml | 7 +- hapi-fhir-converter/pom.xml | 18 +- hapi-fhir-karaf-features/pom.xml | 218 ++ .../src/main/resources/features.xml | 128 + hapi-fhir-karaf-integration-tests/pom.xml | 176 + .../integration/karaf/PaxExamOptions.java | 132 + .../Dstu2ResourceValidatorDstu2Test.java | 331 ++ .../karaf/dstu2/PatientProfileDstu2.java | 72 + .../karaf/dstu21/JsonParserDstu2_1Test.java | 1438 ++++++++ .../PatientWithExtendedContactDstu3.java | 60 + .../karaf/dstu21/XmlParserDstu2_1Test.java | 2480 +++++++++++++ .../FhirInstanceValidatorTest.java | 136 + .../JsonParserHl7OrgDstu2Test.java | 1320 +++++++ .../MyObservationWithExtensions.java | 106 + .../dstu2hl7org/MyOrganizationDstu2.java | 11 + .../karaf/dstu2hl7org/MyPatientHl7Org.java | 64 + ...ntWithOneDeclaredEnumerationExtension.java | 26 + .../dstu2hl7org/ResourceWithExtensionsA.java | 206 ++ .../dstu2hl7org/XmlParserHl7OrgDstu2Test.java | 1521 ++++++++ .../karaf/dstu3/CustomDiagnosticReport.java | 13 + .../karaf/dstu3/CustomObservation.java | 13 + .../karaf/dstu3/CustomPatientDstu3.java | 29 + .../karaf/dstu3/Dstu3JsonParserTest.java | 1700 +++++++++ .../karaf/dstu3/Dstu3XmlParserTest.java | 3235 +++++++++++++++++ .../karaf/dstu3/FooMessageHeader.java | 46 + .../FooMessageHeaderWithExplicitField.java | 57 + .../MyPatientWithCustomUrlExtension.java | 52 + ...hOneDeclaredEnumerationExtensionDstu3.java | 66 + .../karaf/dstu3/PatientProfileDstu3.java | 72 + .../PatientWithCustomCompositeExtension.java | 81 + .../ResourceValidatorDstu3FeatureTest.java | 410 +++ .../karaf/r4/FhirInstanceValidatorR4Test.java | 114 + .../karaf/r4/R4JsonParserTest.java | 275 ++ .../integration/karaf/r4/R4XmlParserTest.java | 195 + .../src/test/resources/bundle-example.json | 53 + .../src/test/resources/bundle_orion.xml | 72 + .../test/resources/bundle_ref_by_uuid_544.xml | 174 + .../bundle_with_contained_with_no_id.xml | 77 + .../bundle_with_invalid_contained_ref.xml | 50 + .../test/resources/bundle_with_woven_obs.xml | 317 ++ .../src/test/resources/conformance.json.gz | Bin 0 -> 40983 bytes .../resources/dstu3/myconsent-resource.json | 55 + .../example-patient-general-hl7orgdstu2.json | 140 + .../example-patient-general-hl7orgdstu2.xml | 128 + .../src/test/resources/extension-on-line.txt | 58 + .../test/resources/patient-example-dicom.json | 60 + .../src/test/resources/q_jon.json | 1369 +++++++ .../src/test/resources/qr_jon.xml | 455 +++ .../resources/r4/bundle-with-no-type.json | 73 + ...iagnosticreport-example-gingival-mass.json | 58 + .../src/test/resources/sample-document.xml | 1864 ++++++++++ .../src/test/resources/testscript-search.json | 298 ++ hapi-fhir-structures-dstu2.1/pom.xml | 18 +- hapi-fhir-structures-dstu2/pom.xml | 18 +- hapi-fhir-structures-dstu3/pom.xml | 15 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 18 +- hapi-fhir-structures-r4/pom.xml | 30 +- hapi-fhir-utilities/pom.xml | 7 +- .../pom.xml | 16 +- hapi-fhir-validation-resources-dstu2/pom.xml | 16 +- hapi-fhir-validation-resources-dstu3/pom.xml | 16 +- hapi-fhir-validation-resources-r4/pom.xml | 16 +- hapi-fhir-validation/pom.xml | 14 +- pom.xml | 28 +- 65 files changed, 20308 insertions(+), 30 deletions(-) create mode 100644 hapi-fhir-karaf-features/pom.xml create mode 100644 hapi-fhir-karaf-features/src/main/resources/features.xml create mode 100644 hapi-fhir-karaf-integration-tests/pom.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml create mode 100644 hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 8f8cafe83f8..ea2984f4091 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -10,7 +10,7 @@ hapi-fhir-base - jar + bundle http://jamesagnew.github.io/hapi-fhir/ @@ -150,6 +150,21 @@ --> + + org.apache.felix + maven-bundle-plugin + true + + + + + ca.uhn.fhir.rest.api.server;resolution:=optional, + ca.uhn.fhir.model.api;resolution:=optional, + * + + + + diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index b9adc3031f0..1f1db04dd59 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -9,7 +9,7 @@ hapi-fhir-client - jar + bundle HAPI FHIR - Client Framework @@ -69,6 +69,11 @@ ${argLine} -Dfile.encoding=UTF-8 -Xmx712m + + org.apache.felix + maven-bundle-plugin + true + diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index d57d06bca18..465c0dc121f 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -10,7 +10,7 @@ hapi-fhir-converter - jar + bundle @@ -134,5 +134,21 @@ false + + + org.apache.felix + maven-bundle-plugin + true + + + + ca.uhn.fhir.rest.server*;resolution:=optional, + javax.servlet.http;resolution:=optional, + * + + + + + diff --git a/hapi-fhir-karaf-features/pom.xml b/hapi-fhir-karaf-features/pom.xml new file mode 100644 index 00000000000..6a15b39b115 --- /dev/null +++ b/hapi-fhir-karaf-features/pom.xml @@ -0,0 +1,218 @@ + + + 4.0.0 + + + ca.uhn.hapi.fhir + hapi-deployable-pom + 3.3.0-SNAPSHOT + ../hapi-deployable-pom/pom.xml + + + ca.uhn.hapi.fhir.karaf + hapi-fhir + pom + HAPI FHIR - Apache Karaf :: Features + + + features.xml + 1.8.6 + 3.2.2 + + + + + ca.uhn.hapi.fhir + hapi-fhir-base + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2.1 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-hl7org-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-r4 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu3 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu2.1 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-r4 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-converter + ${project.version} + + + + + org.osgi + org.osgi.core + 4.3.1 + provided + + + org.ops4j.pax.logging + pax-logging-api + ${pax-logging-version} + provided + + + org.ops4j.pax.logging + pax-logging-service + ${pax-logging-version} + provided + + + org.apache.felix + org.apache.felix.framework + ${felix-framework-version} + provided + + + org.apache.felix + org.apache.felix.configadmin + 1.8.8 + provided + + + org.apache.aries.blueprint + org.apache.aries.blueprint.api + 1.0.1 + provided + + + org.apache.aries.blueprint + org.apache.aries.blueprint.core + 1.0.1 + provided + + + org.apache.karaf.shell + org.apache.karaf.shell.core + ${apache_karaf_version} + provided + + + org.apache.karaf.features + framework + ${apache_karaf_version} + kar + provided + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.2 + + + filter + generate-resources + + resources + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + target/classes/features.xml + xml + features + + + + + + + + org.apache.karaf.tooling + karaf-maven-plugin + ${apache_karaf_version} + + + file://${project.build.directory}/classes/${features.file} + mvn:org.apache.karaf.features/enterprise/${apache_karaf_version}/xml/features + + org.apache.karaf.features:framework + 1.8 + + framework + + + hapi-fhir* + + + + + validate + process-resources + + verify + + + + + + + diff --git a/hapi-fhir-karaf-features/src/main/resources/features.xml b/hapi-fhir-karaf-features/src/main/resources/features.xml new file mode 100644 index 00000000000..b6ceaadf1ff --- /dev/null +++ b/hapi-fhir-karaf-features/src/main/resources/features.xml @@ -0,0 +1,128 @@ + + + + + + wrap + mvn:com.google.code.gson/gson/${gson_version} + mvn:org.apache.commons/commons-lang3/${commons_lang3_version} + mvn:commons-codec/commons-codec/${commons_codec_version} + mvn:commons-io/commons-io/${commons_io_version} + mvn:com.google.guava/guava/${guava_version} + wrap:mvn:com.google.errorprone/error_prone_annotations/${error_prone_annotations_version} + mvn:org.codehaus.woodstox/stax2-api/${stax2_api_version} + mvn:org.codehaus.woodstox/woodstox-core-asl/${woodstox_core_asl_version} + mvn:ca.uhn.hapi.fhir/hapi-fhir-base/${project.version} + + + + hapi-fhir + mvn:com.google.code.gson/gson/${gson_version} + mvn:commons-codec/commons-codec/${commons_codec_version} + mvn:commons-io/commons-io/${commons_io_version} + mvn:ca.uhn.hapi.fhir/hapi-fhir-utilities/${project.version} + + + + hapi-fhir + mvn:ca.uhn.hapi.fhir/hapi-fhir-structures-dstu2/${project.version} + + + + hapi-fhir + hapi-fhir-utilities + + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.saxon/${servicemix_saxon_version} + + + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xmlresolver/${servicemix_xmlresolver_version} + + mvn:ca.uhn.hapi.fhir/hapi-fhir-structures-hl7org-dstu2/${project.version} + + + + hapi-fhir + hapi-fhir-utilities + mvn:ca.uhn.hapi.fhir/hapi-fhir-structures-dstu2.1/${project.version} + + + + hapi-fhir + hapi-fhir-utilities + mvn:ca.uhn.hapi.fhir/hapi-fhir-structures-dstu3/${project.version} + + + + hapi-fhir + hapi-fhir-utilities + mvn:ca.uhn.hapi.fhir/hapi-fhir-structures-r4/${project.version} + + + + + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.saxon/${servicemix_saxon_version} + + + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xmlresolver/${servicemix_xmlresolver_version} + + mvn:com.google.code.findbugs/jsr305/${jsr305_version} + mvn:com.phloc/phloc-schematron/${phloc_schematron_version} + mvn:com.phloc/phloc-commons/${phloc_commons_version} + + + + hapi-fhir + hapi-fhir-utilities + hapi-fhir-ph-schematron + mvn:ca.uhn.hapi.fhir/hapi-fhir-converter/${project.version} + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation/${project.version} + + + + hapi-fhir-validation + hapi-fhir-dstu2 + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation-resources-dstu2/${project.version} + + + + hapi-fhir-validation + hapi-fhir-hl7org-dstu2 + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation-resources-dstu2/${project.version} + + + + hapi-fhir-validation + hapi-fhir-dstu2.1 + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation-resources-dstu2.1/${project.version} + + + + hapi-fhir-validation + hapi-fhir-dstu3 + hapi-fhir-r4 + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation-resources-dstu3/${project.version} + + + + hapi-fhir-validation + hapi-fhir-r4 + mvn:ca.uhn.hapi.fhir/hapi-fhir-validation-resources-r4/${project.version} + + diff --git a/hapi-fhir-karaf-integration-tests/pom.xml b/hapi-fhir-karaf-integration-tests/pom.xml new file mode 100644 index 00000000000..e32b5c555c2 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/pom.xml @@ -0,0 +1,176 @@ + + + 4.0.0 + + + ca.uhn.hapi.fhir + hapi-deployable-pom + 3.3.0-SNAPSHOT + ../hapi-deployable-pom/pom.xml + + + hapi-fhir-karaf-integration-tests + jar + HAPI-FHIR Apache Karaf Integration Tests + + + Integration tests for the HAPI-FHIR Apache Karaf features + + + + 4.9.1 + + + + + ca.uhn.hapi.fhir + hapi-fhir-base + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2.1 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-hl7org-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-structures-r4 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu3 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu2 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-dstu2.1 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation-resources-r4 + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-validation + ${project.version} + + + + + org.ops4j.pax.exam + pax-exam-container-karaf + ${pax.exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit4 + ${pax.exam.version} + test + + + org.xmlunit + xmlunit-core + test + + + org.apache.karaf + apache-karaf + ${apache_karaf_version} + test + tar.gz + + + org.apache.karaf.shell + org.apache.karaf.shell.console + ${apache_karaf_version} + test + + + ca.uhn.hapi.fhir.karaf + hapi-fhir + ${project.version} + features + xml + test + + + org.apache.karaf.features + enterprise + ${apache_karaf_version} + features + xml + test + + + org.apache.servicemix.bundles + org.apache.servicemix.bundles.hamcrest + 1.3_1 + runtime + + + + + + + org.apache.servicemix.tooling + depends-maven-plugin + 1.2 + + + generate-depends-file + + generate-depends-file + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 1 + false + + + + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java new file mode 100644 index 00000000000..5ddc2de9cf7 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java @@ -0,0 +1,132 @@ +package ca.uhn.fhir.tests.integration.karaf; + +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.karaf.options.LogLevelOption; +import org.ops4j.pax.exam.options.DefaultCompositeOption; + +import java.io.File; + +import static org.ops4j.pax.exam.CoreOptions.maven; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features; + +public enum PaxExamOptions { + KARAF( + karafDistributionConfiguration() + .frameworkUrl( + maven() + .groupId("org.apache.karaf") + .artifactId("apache-karaf") + .versionAsInProject() + .type("zip")) + .name("Apache Karaf") + .useDeployFolder(false) + .unpackDirectory(new File("target/paxexam/unpack/")), + keepRuntimeFolder(), + configureConsole().ignoreLocalConsole(), + logLevel(LogLevelOption.LogLevel.INFO) + ), + WRAP( + features( + maven() + .groupId("org.apache.karaf.features") + .artifactId("enterprise") + .type("xml") + .classifier("features") + .versionAsInProject(), + "wrap") + ), + HAPI_FHIR_HL7ORG_DSTU2( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-hl7org-dstu2") + ), + HAPI_FHIR_DSTU2_1( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-dstu2.1") + ), + HAPI_FHIR_DSTU3( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-dstu3") + ), + HAPI_FHIR_R4( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-r4") + ), + HAPI_FHIR_VALIDATION_DSTU2( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-validation-dstu2") + ), + HAPI_FHIR_VALIDATION_HL7ORG_DSTU2( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-validation-hl7org-dstu2") + ), + HAPI_FHIR_VALIDATION_DSTU3( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-validation-dstu3") + ), + HAPI_FHIR_VALIDATION_R4( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-validation-r4") + ); + + private final Option[] options; + + PaxExamOptions(Option... options) { + this.options = options; + } + + public Option option() { + return new DefaultCompositeOption(options); + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java new file mode 100644 index 00000000000..ff2cc52a836 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java @@ -0,0 +1,331 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; +import ca.uhn.fhir.model.api.TemporalPrecisionEnum; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; +import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu2.resource.Bundle; +import ca.uhn.fhir.model.dstu2.resource.Condition; +import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.dstu2.valueset.ConditionVerificationStatusEnum; +import ca.uhn.fhir.model.dstu2.valueset.NarrativeStatusEnum; +import ca.uhn.fhir.model.primitive.DateDt; +import ca.uhn.fhir.model.primitive.InstantDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.validation.FhirValidator; +import ca.uhn.fhir.validation.SchemaBaseValidator; +import ca.uhn.fhir.validation.ValidationFailureException; +import ca.uhn.fhir.validation.ValidationResult; +import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; +import org.apache.commons.io.IOUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.StringContains; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_DSTU2; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class Dstu2ResourceValidatorDstu2Test { + + private FhirContext ourCtx = FhirContext.forDstu2(); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu2ResourceValidatorDstu2Test.class); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_VALIDATION_DSTU2.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + private FhirValidator createFhirValidator() { + FhirValidator val = ourCtx.newValidator(); + val.setValidateAgainstStandardSchema(true); + val.setValidateAgainstStandardSchematron(true); + return val; + } + + private String logOperationOutcome(ValidationResult result) { + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + return encoded; + } + + /** + * See issue #50 + */ + @Test() + public void testOutOfBoundsDate() { + Patient p = new Patient(); + p.setBirthDate(new DateDt("2000-12-31")); + + // Put in an invalid date + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + + String encoded = parser.setPrettyPrint(true).encodeResourceToString(p).replace("2000-12-31", "2000-15-31"); + ourLog.info(encoded); + + assertThat(encoded, StringContains.containsString("2000-15-31")); + + ValidationResult result = ourCtx.newValidator().validateWithResult(encoded); + String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(resultString); + + assertEquals(2, ((OperationOutcome)result.toOperationOutcome()).getIssue().size()); + assertThat(resultString, StringContains.containsString("cvc-pattern-valid")); + + try { + parser.parseResource(encoded); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"2000-15-31\": Invalid date/time format: \"2000-15-31\"", e.getMessage()); + } + } + + @Test + public void testSchemaBundleValidatorIsSuccessful() throws IOException { + String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("bundle-example.json"), StandardCharsets.UTF_8); + Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, res); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b)); + + FhirValidator val = createFhirValidator(); + + ValidationResult result = val.validateWithResult(b); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + + assertTrue(result.toString(), result.isSuccessful()); + assertNotNull(operationOutcome); + assertEquals(1, operationOutcome.getIssue().size()); + } + + @SuppressWarnings("deprecation") + @Test + public void testSchemaResourceValidator() throws IOException { + String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("patient-example-dicom.json")); + Patient p = ourCtx.newJsonParser().parseResource(Patient.class, res); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p)); + + FhirValidator val = ourCtx.newValidator(); + val.setValidateAgainstStandardSchema(true); + val.setValidateAgainstStandardSchematron(false); + + val.validate(p); + + p.getAnimal().getBreed().setText("The Breed"); + try { + val.validate(p); + fail(); + } catch (ValidationFailureException e) { + OperationOutcome operationOutcome = (OperationOutcome) e.getOperationOutcome(); + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome)); + assertEquals(1, operationOutcome.getIssue().size()); + assertThat(operationOutcome.getIssueFirstRep().getDetailsElement().getValue(), containsString("cvc-complex-type")); + } + } + + /** + * Make sure that the elements that appear in all resources (meta, language, extension, etc) + * all appear in the correct order + */ + @Test + public void testValidateResourceWithResourceElements() { + TestPatientFor327 patient = new TestPatientFor327(); + patient.setBirthDate(new Date(), TemporalPrecisionEnum.DAY); + patient.setId("123"); + patient.getText().setDiv("
FOO
"); + patient.getText().setStatus(NarrativeStatusEnum.GENERATED); + patient.getLanguage().setValue("en"); + patient.addUndeclaredExtension(true, "http://foo").setValue(new StringDt("MOD")); + ResourceMetadataKeyEnum.UPDATED.put(patient, new InstantDt(new Date())); + + List conditions = new ArrayList(); + Condition condition = new Condition(); + condition.getPatient().setReference("Patient/123"); + condition.addBodySite().setText("BODY SITE"); + condition.getCode().setText("CODE"); + condition.setVerificationStatus(ConditionVerificationStatusEnum.CONFIRMED); + conditions.add(new ResourceReferenceDt(condition)); + patient.setCondition(conditions); + patient.addIdentifier().setSystem("http://foo").setValue("123"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + FhirValidator val = createFhirValidator(); + ValidationResult result = val.validateWithResult(encoded); + + String messageString = logOperationOutcome(result); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("No issues")); + + } + + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsJson() { + PatientProfileDstu2 myPatient = new PatientProfileDstu2(); + myPatient.setColorPrimary(new CodeableConceptDt("http://example.com#animalColor", "furry-grey")); + myPatient.setColorSecondary(new CodeableConceptDt("http://example.com#animalColor", "furry-white")); + myPatient.setOwningOrganization(new ResourceReferenceDt("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addUndeclaredExtension(new ExtensionDt().setUrl("http://foo.com/example").setValue(new StringDt("String Extension"))); + + IParser p = FhirContext.forDstu2().newJsonParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "String Extension", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + + ValidationResult result = val.validateWithResult(messageString); + + logOperationOutcome(result); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + /** + * See + * https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= + * email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsXml() { + PatientProfileDstu2 myPatient = new PatientProfileDstu2(); + myPatient.setColorPrimary(new CodeableConceptDt("http://example.com#animalColor", "furry-grey")); + myPatient.setColorSecondary(new CodeableConceptDt("http://example.com#animalColor", "furry-white")); + myPatient.setOwningOrganization(new ResourceReferenceDt("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().addFamily("FamilyName"); + myPatient.addUndeclaredExtension(new ExtensionDt().setUrl("http://foo.com/example").setValue(new StringDt("String Extension"))); + + IParser p = FhirContext.forDstu2().newXmlParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + assertThat(messageString, stringContainsInOrder( + "meta", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "String Extension", + "FamilyName" + )); + assertThat(messageString, not(stringContainsInOrder( + "extension", + "meta" + ))); + assertThat(messageString, containsString("url=\"http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary\"")); + assertThat(messageString, containsString("url=\"http://foo.com/example\"")); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + + ValidationResult result = val.validateWithResult(messageString); + + logOperationOutcome(result); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + @ResourceDef(name = "Patient") + public static class TestPatientFor327 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "testCondition") + @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false) + private List testConditions = null; + + public List getConditions() { + return this.testConditions; + } + + public void setCondition(List ref) { + this.testConditions = ref; + } + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java new file mode 100644 index 00000000000..dfd33d12e46 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java @@ -0,0 +1,72 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; +import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.util.ElementUtil; + +@ResourceDef(name="Patient", profile = "http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient") +public class PatientProfileDstu2 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name="owner", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#owningOrganization", definedLocally=false, isModifier=false) + @Description(shortDefinition="The organization that owns this animal") + private ResourceReferenceDt owningOrganization; + + public ResourceReferenceDt getOwningOrganization() { + if (owningOrganization == null) { + owningOrganization = new ResourceReferenceDt(); + } + return owningOrganization; + } + + public PatientProfileDstu2 setOwningOrganization(ResourceReferenceDt owningOrganization) { + this.owningOrganization = owningOrganization; + return this; + } + + @Child(name="colorPrimary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorPrimary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals primary color") + private CodeableConceptDt colorPrimary; + + @Child(name="colorSecondary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals secondary color") + private CodeableConceptDt colorSecondary; + + public CodeableConceptDt getColorPrimary() { + if (this.colorPrimary == null) { + return new CodeableConceptDt(); + } + return colorPrimary; + } + + public void setColorPrimary(CodeableConceptDt colorPrimary) { + this.colorPrimary = colorPrimary; + } + + public CodeableConceptDt getColorSecondary() { + if (this.colorSecondary == null) { + return new CodeableConceptDt(); + } + return colorSecondary; + } + + public void setColorSecondary(CodeableConceptDt colorSecondary) { + this.colorSecondary = colorSecondary; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(owningOrganization) && ElementUtil.isEmpty(colorPrimary) + && ElementUtil.isEmpty(colorSecondary) ; + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java new file mode 100644 index 00000000000..48a48095dcf --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java @@ -0,0 +1,1438 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu21; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.LenientErrorHandler; +import ca.uhn.fhir.parser.StrictErrorHandler; +import com.google.common.collect.Sets; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hl7.fhir.dstu2016may.model.Conformance; +import org.hl7.fhir.dstu2016may.model.PrimitiveType; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU2_1; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class JsonParserDstu2_1Test { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserDstu2_1Test.class); + private FhirContext ourCtx = FhirContext.forDstu2_1(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_DSTU2_1.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + org.hl7.fhir.dstu2016may.model.Bundle bundle = (org.hl7.fhir.dstu2016may.model.Bundle) ourCtx.newJsonParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + org.hl7.fhir.dstu2016may.model.Patient o1 = (org.hl7.fhir.dstu2016may.model.Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu2_1(); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + org.hl7.fhir.dstu2016may.model.Bundle bundle = (org.hl7.fhir.dstu2016may.model.Bundle) ourCtx.newJsonParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + org.hl7.fhir.dstu2016may.model.Patient o1 = (org.hl7.fhir.dstu2016may.model.Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu2_1(); + } + } + + /** + * #480 + */ + @Test + public void testEncodeEmptyValue() { + org.hl7.fhir.dstu2016may.model.QuestionnaireResponse qr = new org.hl7.fhir.dstu2016may.model.QuestionnaireResponse(); + qr.setId("123"); + qr.getAuthoredElement().setValueAsString(""); + qr.addItem().setLinkIdElement(new org.hl7.fhir.dstu2016may.model.StringType()); + qr.getItem().get(0).addItem().setLinkIdElement(new org.hl7.fhir.dstu2016may.model.StringType("")); + qr.getItem().get(0).addItem().setLinkIdElement(new org.hl7.fhir.dstu2016may.model.StringType("LINKID")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(qr); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("123")); + assertThat(encoded, not(stringContainsInOrder("\"\""))); + assertThat(encoded, not(stringContainsInOrder("null"))); + } + + + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.addIdentifier().setUse(org.hl7.fhir.dstu2016may.model.Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + org.hl7.fhir.dstu2016may.model.Extension ext = new org.hl7.fhir.dstu2016may.model.Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new org.hl7.fhir.dstu2016may.model.DateTimeType("2011-01-02T11:13:15")); + patient.addExtension(ext); + + org.hl7.fhir.dstu2016may.model.Extension parent = new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + org.hl7.fhir.dstu2016may.model.Extension child1 = new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.dstu2016may.model.StringType("value1")); + parent.addExtension(child1); + org.hl7.fhir.dstu2016may.model.Extension child2 = new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.dstu2016may.model.StringType("value2")); + parent.addExtension(child2); + + org.hl7.fhir.dstu2016may.model.Extension modExt = new org.hl7.fhir.dstu2016may.model.Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new org.hl7.fhir.dstu2016may.model.DateType("1995-01-02")); + patient.addModifierExtension(modExt); + + org.hl7.fhir.dstu2016may.model.HumanName name = patient.addName(); + name.addFamily("Blah"); + org.hl7.fhir.dstu2016may.model.StringType given = name.addGivenElement(); + given.setValue("Joe"); + org.hl7.fhir.dstu2016may.model.Extension ext2 = new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.dstu2016may.model.StringType("given")); + given.addExtension(ext2); + + org.hl7.fhir.dstu2016may.model.StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + org.hl7.fhir.dstu2016may.model.Extension given2ext = new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + given2ext.addExtension(new org.hl7.fhir.dstu2016may.model.Extension().setUrl("http://examples.com#givenext_child").setValue(new org.hl7.fhir.dstu2016may.model.StringType("CHILD"))); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + assertThat(enc, stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}", + "{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}")); + assertThat(enc, stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],")); + assertThat(enc, + containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{" + + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + + "]" + "}")); + + /* + * Now parse this back + */ + + org.hl7.fhir.dstu2016may.model.Patient parsed = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((org.hl7.fhir.dstu2016may.model.DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((org.hl7.fhir.dstu2016may.model.StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((org.hl7.fhir.dstu2016may.model.StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((org.hl7.fhir.dstu2016may.model.DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((org.hl7.fhir.dstu2016may.model.StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + org.hl7.fhir.dstu2016may.model.Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((org.hl7.fhir.dstu2016may.model.StringType) given2ext2.getValue()).getValue()); + + } + + @Test + public void testEncodeAndParseMetaProfileAndTags() { + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.addName().addFamily("FAMILY"); + + p.getMeta().addProfile("http://foo/Profile1"); + p.getMeta().addProfile("http://foo/Profile2"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1"); + p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2"); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder("\"meta\": {", + "\"profile\": [", + "\"http://foo/Profile1\",", + "\"http://foo/Profile2\"", + "],", + "\"security\": [", + "{", + "\"system\": \"sec_scheme1\",", + "\"code\": \"sec_term1\",", + "\"display\": \"sec_label1\"", + "},", + "{", + "\"system\": \"sec_scheme2\",", + "\"code\": \"sec_term2\",", + "\"display\": \"sec_label2\"", + "}", + "],", + "\"tag\": [", + "{", + "\"system\": \"scheme1\",", + "\"code\": \"term1\",", + "\"display\": \"label1\"", + "},", + "{", + "\"system\": \"scheme2\",", + "\"code\": \"term2\",", + "\"display\": \"label2\"", + "}", + "]", + "},")); + //@formatter:on + + org.hl7.fhir.dstu2016may.model.Patient parsed = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Patient.class, enc); + + List gotLabels = parsed.getMeta().getProfile(); + assertEquals(2, gotLabels.size()); + org.hl7.fhir.dstu2016may.model.UriType label = gotLabels.get(0); + assertEquals("http://foo/Profile1", label.getValue()); + label = gotLabels.get(1); + assertEquals("http://foo/Profile2", label.getValue()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + + tagList = parsed.getMeta().getSecurity(); + assertEquals(2, tagList.size()); + assertEquals("sec_scheme1", tagList.get(0).getSystem()); + assertEquals("sec_term1", tagList.get(0).getCode()); + assertEquals("sec_label1", tagList.get(0).getDisplay()); + assertEquals("sec_scheme2", tagList.get(1).getSystem()); + assertEquals("sec_term2", tagList.get(1).getCode()); + assertEquals("sec_label2", tagList.get(1).getDisplay()); + } + + /** + * See #336 + */ + @Test + public void testEncodeAndParseNullPrimitiveWithExtensions() { + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setId("patid"); + org.hl7.fhir.dstu2016may.model.HumanName name = p.addName(); + name.addGivenElement().setValue(null).setId("f0").addExtension(new org.hl7.fhir.dstu2016may.model.Extension("http://foo", new org.hl7.fhir.dstu2016may.model.StringType("FOOEXT0"))); + name.addGivenElement().setValue("V1").setId("f1").addExtension((org.hl7.fhir.dstu2016may.model.Extension) new org.hl7.fhir.dstu2016may.model.Extension("http://foo", new org.hl7.fhir.dstu2016may.model.StringType("FOOEXT1")).setId("ext1id")); + name.addGivenElement(); // this one shouldn't get encoded + name.addGivenElement().setValue(null).addExtension(new org.hl7.fhir.dstu2016may.model.Extension("http://foo", new org.hl7.fhir.dstu2016may.model.StringType("FOOEXT3"))); + name.setId("nameid"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + output = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(p); + String expected = "{\"resourceType\":\"Patient\",\"id\":\"patid\",\"name\":[{\"id\":\"nameid\",\"given\":[null,\"V1\",null],\"_given\":[{\"id\":\"f0\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT0\"}]},{\"id\":\"f1\",\"extension\":[{\"id\":\"ext1id\",\"url\":\"http://foo\",\"valueString\":\"FOOEXT1\"}]},{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT3\"}]}]}]}"; + + ourLog.info("Exp: {}", expected); + ourLog.info("Act: {}", output); + + assertEquals(expected, output); + + p = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Patient.class, output); + assertEquals("patid", p.getIdElement().getIdPart()); + + name = p.getName().get(0); + assertEquals("nameid", name.getId()); + assertEquals(3, name.getGiven().size()); + + assertEquals(null, name.getGiven().get(0).getValue()); + assertEquals("V1", name.getGiven().get(1).getValue()); + assertEquals(null, name.getGiven().get(2).getValue()); + + assertEquals("f0", name.getGiven().get(0).getId()); + assertEquals("f1", name.getGiven().get(1).getId()); + assertEquals(null, name.getGiven().get(2).getId()); + + assertEquals(1, name.getGiven().get(0).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl()); + assertEquals("FOOEXT0", ((org.hl7.fhir.dstu2016may.model.StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(1).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl()); + assertEquals("FOOEXT1", ((org.hl7.fhir.dstu2016may.model.StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue()); + assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(2).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl()); + assertEquals("FOOEXT3", ((org.hl7.fhir.dstu2016may.model.StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId()); + + } + + + + @Test + public void testEncodeBundleNewBundleNoText() { + + org.hl7.fhir.dstu2016may.model.Bundle b = new org.hl7.fhir.dstu2016may.model.Bundle(); + + org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent e = b.addEntry(); + e.setResource(new org.hl7.fhir.dstu2016may.model.Patient()); + + String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + assertThat(val, not(containsString("text"))); + + val = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + assertThat(val, not(containsString("text"))); + + } + + /** + * See #326 + */ + @Test + public void testEncodeContainedResource() { + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.getBirthDateElement().setValueAsString("2016-04-05"); + patient.addExtension().setUrl("test").setValue(new org.hl7.fhir.dstu2016may.model.Reference(new org.hl7.fhir.dstu2016may.model.Condition())); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "{", + "\"resourceType\": \"Patient\",", + "\"contained\": [", + "{", + "\"resourceType\": \"Condition\",", + "\"id\": \"1\"", + "}", + "],", + "\"extension\": [", + "{", + "\"url\": \"test\",", + "\"valueReference\": {", + "\"reference\": \"#1\"", + "}", + "}", + "],", + "\"birthDate\": \"2016-04-05\"", + "}" + )); + //@formatter:on + } + + @Test + public void testEncodeDoesntIncludeUuidId() { + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setId(new org.hl7.fhir.dstu2016may.model.IdType("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2")); + p.addIdentifier().setSystem("ACME"); + + String actual = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + assertThat(actual, not(containsString("78ef6f64c2f2"))); + } + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newJsonParser().encodeResourceToString(new org.hl7.fhir.dstu2016may.model.Binary()); + assertEquals("{\"resourceType\":\"Binary\"}", output); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag() { + ArrayList tagList = new ArrayList(); + tagList.add(new org.hl7.fhir.dstu2016may.model.Coding()); + tagList.add(new org.hl7.fhir.dstu2016may.model.Coding().setDisplay("Label")); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(p); + assertThat(encoded, not(containsString("tag"))); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag2() { + ArrayList tagList = new ArrayList(); + tagList.add(new org.hl7.fhir.dstu2016may.model.Coding().setSystem("scheme").setCode("code")); + tagList.add(new org.hl7.fhir.dstu2016may.model.Coding().setDisplay("Label")); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(p); + assertThat(encoded, containsString("tag")); + assertThat(encoded, containsString("scheme")); + assertThat(encoded, not(containsString("Label"))); + } + + @Test + public void testEncodeExtendedInfrastructureComponent() { + IParser parser = ourCtx.newJsonParser(); + + PatientWithExtendedContactDstu3 patient = new PatientWithExtendedContactDstu3(); + patient.setId("123"); + + PatientWithExtendedContactDstu3.CustomContactComponent customContactComponent = new PatientWithExtendedContactDstu3.CustomContactComponent(); + customContactComponent.getEyeColour().setValue("EYE"); + customContactComponent.getName().addFamily("FAMILY"); + patient.getCustomContact().add(customContactComponent); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + + assertEquals( + "{\"resourceType\":\"Patient\",\"id\":\"123\",\"contact\":[{\"extension\":[{\"url\":\"http://foo.com/contact-eyecolour\",\"valueIdentifier\":{\"value\":\"EYE\"}}],\"name\":{\"family\":[\"FAMILY\"]}}]}", + val); + + FhirContext newCtx = FhirContext.forDstu2_1(); + PatientWithExtendedContactDstu3 actual = newCtx.newJsonParser().parseResource(PatientWithExtendedContactDstu3.class, val); + assertEquals("EYE", actual.getCustomContact().get(0).getEyeColour().getValue()); + + } + + @Test + public void testEncodeExtensionInPrimitiveElement() { + + Conformance c = new Conformance(); + c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new org.hl7.fhir.dstu2016may.model.StringType("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + // Now with a value + ourLog.info("---------------"); + + c = new Conformance(); + c.getAcceptUnknownElement().setValue(Conformance.UnknownContentCode.ELEMENTS); + c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new org.hl7.fhir.dstu2016may.model.StringType("AAA")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":\"elements\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + } + + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + org.hl7.fhir.dstu2016may.model.Observation obs = new org.hl7.fhir.dstu2016may.model.Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + org.hl7.fhir.dstu2016may.model.Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new org.hl7.fhir.dstu2016may.model.StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\": \"1\"", + "\"meta\"", + "\"extension\"", + "\"url\": \"http://exturl\"", + "\"valueString\": \"ext_url_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\": \"http://exturl\"", + ",", + "\"url\": \"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(org.hl7.fhir.dstu2016may.model.Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((org.hl7.fhir.dstu2016may.model.StringType) obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + org.hl7.fhir.dstu2016may.model.Observation obs = new org.hl7.fhir.dstu2016may.model.Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + org.hl7.fhir.dstu2016may.model.Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + org.hl7.fhir.dstu2016may.model.Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new org.hl7.fhir.dstu2016may.model.StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\": \"1\"", + "\"meta\"", + "\"extension\"", + "\"url\": \"http://exturl\"", + "\"extension\"", + "\"url\": \"http://subext\"", + "\"valueString\": \"sub_ext_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\": \"http://exturl\"", + ",", + "\"url\": \"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(org.hl7.fhir.dstu2016may.model.Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((org.hl7.fhir.dstu2016may.model.StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath1() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath2() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath3() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + org.hl7.fhir.dstu2016may.model.AuditEvent auditEvent = new org.hl7.fhir.dstu2016may.model.AuditEvent(); + auditEvent.addEntity().setReference(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList()); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setDontStripVersionsFromReferencesAtPaths((String[]) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setDontStripVersionsFromReferencesAtPaths((List) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPathUsingOptions() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths(), empty()); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(Arrays.asList("Patient.managingOrganization")); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(new HashSet(Arrays.asList("Patient.managingOrganization"))); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + } + + @Test + public void testEncodeHistoryStripVersionsFromReferences() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setStripVersionsFromReferences(false); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx = FhirContext.forDstu2_1(); + } + + @Test + public void testEncodeHistoryStripVersionsFromReferencesFromContext() { + ourCtx = FhirContext.forDstu2_1(); + + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + ourCtx.getParserOptions().setStripVersionsFromReferences(false); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + parser.setStripVersionsFromReferences(true); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + ourCtx = FhirContext.forDstu2_1(); + } + + @Test + public void testEncodeNarrativeShouldIncludeNamespace() { + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.getText().setDivAsString("
VALUE
"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + assertThat(output, containsString("\"div\": \"
VALUE
\"")); + } + + @Test + public void testEncodeNarrativeShouldIncludeNamespaceWithProcessingInstruction() { + + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.getText().setDivAsString("
VALUE
"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + assertThat(output, containsString("\"div\": \"
VALUE
\"")); + } + + @Test + public void testEncodeNarrativeSuppressed() throws Exception { + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder(ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM, ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE)); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeParametersWithId() { + org.hl7.fhir.dstu2016may.model.Parameters reqParms = new org.hl7.fhir.dstu2016may.model.Parameters(); + org.hl7.fhir.dstu2016may.model.IdType patient = new org.hl7.fhir.dstu2016may.model.IdType(1); + reqParms.addParameter().setName("patient").setValue(patient); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(reqParms); + ourLog.info(enc); + + assertThat(enc, containsString("\"valueId\": \"1\"")); + } + + @Test + public void testEncodeSummary() { + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.addPhoto().setTitle("green"); + patient.getMaritalStatus().addCoding().setCode("D"); + + ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient)); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\"")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() { + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"foo\",", "\"code\": \"bar\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\"", + "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\"")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + /** + * See #205 + */ + @Test + public void testEncodeTags() { + org.hl7.fhir.dstu2016may.model.Patient pt = new org.hl7.fhir.dstu2016may.model.Patient(); + pt.addIdentifier().setSystem("sys").setValue("val"); + + pt.getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("display"); + + String enc = ourCtx.newJsonParser().encodeResourceToString(pt); + ourLog.info(enc); + + assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}", + enc); + + } + + /** + * See #241 + */ + @Test + public void testEncodeThenParseShouldNotAddSpuriousId() throws Exception { + org.hl7.fhir.dstu2016may.model.Condition condition = new org.hl7.fhir.dstu2016may.model.Condition().setVerificationStatus(org.hl7.fhir.dstu2016may.model.Condition.ConditionVerificationStatus.CONFIRMED); + org.hl7.fhir.dstu2016may.model.Bundle bundle = new org.hl7.fhir.dstu2016may.model.Bundle(); + org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent entry = new org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent(); + entry.setId("123"); + entry.setResource(condition); + bundle.getEntry().add(entry); + IParser parser = ourCtx.newJsonParser(); + String json = parser.encodeResourceToString(bundle); + ourLog.info(json); + bundle = (org.hl7.fhir.dstu2016may.model.Bundle) parser.parseResource(json); + + assertEquals("123", bundle.getEntry().get(0).getId()); + + condition = (org.hl7.fhir.dstu2016may.model.Condition) bundle.getEntry().get(0).getResource(); + assertEquals(null, condition.getId()); + } + + @Test + public void testEncodeWithDontEncodeElements() throws Exception { + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + patient.setId("123"); + + patient.getMeta().addProfile(("http://profile")); + patient.addName().addFamily("FAMILY").addGiven("GIVEN"); + patient.addAddress().addLine("LINE1"); + + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.name.family")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("GIVEN")); + assertThat(out, not(containsString("FAMILY"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta")); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("id")); + assertThat(out, not(containsString("address"))); + assertThat(out, not(containsString("meta"))); + } + } + + @Test + public void testEncodingNullExtension() { + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + org.hl7.fhir.dstu2016may.model.Extension extension = new org.hl7.fhir.dstu2016may.model.Extension("http://foo#bar"); + p.addExtension(extension); + String str = ourCtx.newJsonParser().encodeResourceToString(p); + + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new org.hl7.fhir.dstu2016may.model.StringType()); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new org.hl7.fhir.dstu2016may.model.StringType("")); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + } + + + @Test + public void testExponentDoesntGetEncodedAsSuch() { + org.hl7.fhir.dstu2016may.model.Observation obs = new org.hl7.fhir.dstu2016may.model.Observation(); + obs.setValue(new org.hl7.fhir.dstu2016may.model.Quantity().setValue(new BigDecimal("0.000000000000000100"))); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str); + } + + @Test + public void testExponentParseWorks() { + String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}"; + org.hl7.fhir.dstu2016may.model.Observation obs = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Observation.class, input); + + assertEquals("0.0000000000000001", ((org.hl7.fhir.dstu2016may.model.Quantity) obs.getValue()).getValueElement().getValueAsString()); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}", str); + } + + /** + * #516 + */ + @Test(expected = DataFormatException.class) + public void testInvalidEnumValue() { + String res = "{ \"resourceType\": \"ValueSet\", \"url\": \"http://sample/ValueSet/education-levels\", \"version\": \"1\", \"name\": \"Education Levels\", \"status\": \"draft\", \"compose\": { \"include\": [ { \"filter\": [ { \"property\": \"n\", \"op\": \"n\", \"value\": \"365460000\" } ], \"system\": \"http://snomed.info/sct\" } ], \"exclude\": [ { \"concept\": [ { \"code\": \"224298008\" }, { \"code\": \"365460000\" }, { \"code\": \"473462005\" }, { \"code\": \"424587006\" } ], \"system\": \"http://snomed.info/sct\" } ] }, \"description\": \"A selection of Education Levels\", \"text\": { \"status\": \"generated\", \"div\": \"

Education Levels

http://csiro.au/ValueSet/education-levels

A selection of Education Levels

\" }, \"experimental\": true, \"date\": \"2016-07-26\" }"; + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + org.hl7.fhir.dstu2016may.model.ValueSet parsed = parser.parseResource(org.hl7.fhir.dstu2016may.model.ValueSet.class, res); + fail("DataFormat Invalid attribute exception should be thrown"); + } + + /** + * #65 + */ + @Test + public void testJsonPrimitiveWithExtensionEncoding() { + + org.hl7.fhir.dstu2016may.model.QuestionnaireResponse parsed = new org.hl7.fhir.dstu2016may.model.QuestionnaireResponse(); + parsed.addItem().setLinkId("value123"); + parsed.getItem().get(0).getLinkIdElement().addExtension(new org.hl7.fhir.dstu2016may.model.Extension("http://123", new org.hl7.fhir.dstu2016may.model.StringType("HELLO"))); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(parsed); + ourLog.info(encoded); + assertThat(encoded, containsString("{\"linkId\":\"value123\",\"_linkId\":{\"extension\":[{\"url\":\"http://123\",\"valueString\":\"HELLO\"}]}}")); + + } + + @Test + public void testLinkage() { + org.hl7.fhir.dstu2016may.model.Linkage l = new org.hl7.fhir.dstu2016may.model.Linkage(); + l.addItem().getResource().setDisplay("FOO"); + String out = ourCtx.newXmlParser().encodeResourceToString(l); + ourLog.info(out); + assertEquals("", out); + } + + @Test + public void testOmitResourceId() { + org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); + p.setId("123"); + p.addName().addFamily("ABC"); + + assertThat(ourCtx.newJsonParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC")); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC")); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + } + + @Test + public void testParseAndEncodeBundleWithUuidBase() { + //@formatter:off + String input = + "{\n" + + " \"resourceType\":\"Bundle\",\n" + + " \"type\":\"document\",\n" + + " \"entry\":[\n" + + " {\n" + + " \"fullUrl\":\"urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" + + " \"resource\":{\n" + + " \"resourceType\":\"Composition\",\n" + + " \"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" + + " \"meta\":{\n" + + " \"lastUpdated\":\"2013-05-28T22:12:21Z\"\n" + + " },\n" + + " \"text\":{\n" + + " \"status\":\"generated\",\n" + + " \"div\":\"

Generated Narrative with Details

id: 180f219f-97a8-486d-99d9-ed631fe4fc57

meta:

date: Feb 1, 2013 12:30:02 PM

type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)

status: final

confidentiality: N

author: Doctor Dave. Generated Summary: 23; Adam Careful

encounter: http://fhir.healthintersections.com.au/open/Encounter/doc-example

\"\n" + + " },\n" + + " \"date\":\"2013-02-01T12:30:02Z\",\n" + + " \"type\":{\n" + + " \"coding\":[\n" + + " {\n" + + " \"system\":\"http://loinc.org\",\n" + + " \"code\":\"28655-9\"\n" + + " }\n" + + " ],\n" + + " \"text\":\"Discharge Summary from Responsible Clinician\"\n" + + " },\n" + + " \"status\":\"final\",\n" + + " \"confidentiality\":\"N\",\n" + + " \"subject\":{\n" + + " \"reference\":\"http://fhir.healthintersections.com.au/open/Patient/d1\",\n" + + " \"display\":\"Eve Everywoman\"\n" + + " },\n" + + " \"author\":[\n" + + " {\n" + + " \"reference\":\"Practitioner/example\",\n" + + " \"display\":\"Doctor Dave\"\n" + + " }\n" + + " ],\n" + + " \"encounter\":{\n" + + " \"reference\":\"http://fhir.healthintersections.com.au/open/Encounter/doc-example\"\n" + + " },\n" + + " \"section\":[\n" + + " {\n" + + " \"title\":\"Reason for admission\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:d0dd51d3-3ab2-4c84-b697-a630c3e40e7a\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\":\"Medications on Discharge\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:673f8db5-0ffd-4395-9657-6da00420bbc1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\":\"Known allergies\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:68f86194-e6e1-4f65-b64a-5314256f8d7b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }" + + " ]" + + "}"; + //@formatter:on + + org.hl7.fhir.dstu2016may.model.Bundle parsed = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Bundle.class, input); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed); + ourLog.info(encoded); + + assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + assertEquals(null, parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl()); + assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart()); + assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\""))); + } + + @Test + public void testParseAndEncodeComments() { + //@formatter:off + String input = "{\n" + + " \"resourceType\": \"Patient\",\n" + + " \"id\": \"pat1\",\n" + + " \"text\": {\n" + + " \"status\": \"generated\",\n" + + " \"div\": \"
\\n \\n

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

\\n \\n
\"\n" + + " },\n" + + " \"identifier\": [\n" + + " {\n" + + " \"fhir_comments\":[\"identifier comment 1\",\"identifier comment 2\"],\n" + + " \"use\": \"usual\",\n" + + " \"_use\": {\n" + + " \"fhir_comments\":[\"use comment 1\",\"use comment 2\"]\n" + + " },\n" + + " \"type\": {\n" + + " \"coding\": [\n" + + " {\n" + + " \"system\": \"http://hl7.org/fhir/v2/0203\",\n" + + " \"code\": \"MR\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"system\": \"urn:oid:0.1.2.3.4.5.6.7\",\n" + + " \"value\": \"654321\"\n" + + " }\n" + + " ],\n" + + " \"active\": true" + + "}"; + //@formatter:off + + org.hl7.fhir.dstu2016may.model.Patient res = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Patient.class, input); + res.getFormatCommentsPre(); + assertEquals("Patient/pat1", res.getId()); + assertEquals("654321", res.getIdentifier().get(0).getValue()); + assertEquals(true, res.getActive()); + + assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "\"identifier\": [", + "{", + "\"fhir_comments\":", + "[", + "\"identifier comment 1\"", + ",", + "\"identifier comment 2\"", + "]", + "\"use\": \"usual\",", + "\"_use\": {", + "\"fhir_comments\":", + "[", + "\"use comment 1\"", + ",", + "\"use comment 2\"", + "]", + "},", + "\"type\"" + )); + //@formatter:off + } + + @Test + public void testParseBundleWithBinary() { + org.hl7.fhir.dstu2016may.model.Binary patient = new org.hl7.fhir.dstu2016may.model.Binary(); + patient.setId(new org.hl7.fhir.dstu2016may.model.IdType("http://base/Binary/11/_history/22")); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newJsonParser().encodeResourceToString(patient); + + String expected = "{\"resourceType\":\"Binary\",\"id\":\"11\",\"meta\":{\"versionId\":\"22\"},\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"; + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", val); + assertEquals(expected, val); + } + + + + + /** + * See #342 + */ + @Test() + public void testParseInvalid() { + try { + ourCtx.newJsonParser().parseResource("FOO"); + fail(); + } catch (DataFormatException e) { + assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage()); + } + try { + ourCtx.newJsonParser().parseResource("[\"aaa\"]"); + fail(); + } catch (DataFormatException e) { + assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage()); + } + + assertEquals(org.hl7.fhir.dstu2016may.model.Bundle.class, ourCtx.newJsonParser().parseResource(" {\"resourceType\" : \"Bundle\"}").getClass()); + + } + + /** + * See #414 + */ + @Test + public void testParseJsonExtensionWithoutUrl() { + //@formatter:off + String input = + "{\"resourceType\":\"Patient\"," + + "\"extension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" + + "}"; + //@formatter:on + + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + org.hl7.fhir.dstu2016may.model.Patient parsed = (org.hl7.fhir.dstu2016may.model.Patient) parser.parseResource(input); + assertEquals(1, parsed.getExtension().size()); + assertEquals(null, parsed.getExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", ((PrimitiveType)parsed.getExtension().get(0).getValue()).getValueAsString()); + + try { + parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getMessage()); + } + + } + + /** + * See #414 + */ + @Test + public void testParseJsonModifierExtensionWithoutUrl() { + //@formatter:off + String input = + "{\"resourceType\":\"Patient\"," + + "\"modifierExtension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" + + "}"; + //@formatter:on + + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + org.hl7.fhir.dstu2016may.model.Patient parsed = (org.hl7.fhir.dstu2016may.model.Patient) parser.parseResource(input); + assertEquals(1, parsed.getModifierExtension().size()); + assertEquals(null, parsed.getModifierExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", ((PrimitiveType)parsed.getModifierExtension().get(0).getValue()).getValueAsString()); + + try { + parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getMessage()); + } + + } + + /** + * See #484 + */ + @Test + public void testParseNarrativeWithEmptyDiv() { + String input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + org.hl7.fhir.dstu2016may.model.Basic basic = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Basic.class, input); + assertEquals(null, basic.getText().getDivAsString()); + + input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + basic = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Basic.class, input); + assertEquals(null, basic.getText().getDivAsString()); + + input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + basic = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Basic.class, input); + assertEquals("
", basic.getText().getDivAsString()); + + } + + /** + * See #163 + */ + @Test + public void testParseResourceType() { + IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true); + + // Patient + org.hl7.fhir.dstu2016may.model.Patient patient = new org.hl7.fhir.dstu2016may.model.Patient(); + String patientId = UUID.randomUUID().toString(); + patient.setId(new org.hl7.fhir.dstu2016may.model.IdType("Patient", patientId)); + patient.addName().addGiven("John").addFamily("Smith"); + patient.setGender(org.hl7.fhir.dstu2016may.model.Enumerations.AdministrativeGender.MALE); + patient.setBirthDateElement(new org.hl7.fhir.dstu2016may.model.DateType("1987-04-16")); + + // Bundle + org.hl7.fhir.dstu2016may.model.Bundle bundle = new org.hl7.fhir.dstu2016may.model.Bundle(); + bundle.setType(org.hl7.fhir.dstu2016may.model.Bundle.BundleType.COLLECTION); + bundle.addEntry().setResource(patient); + + String bundleText = jsonParser.encodeResourceToString(bundle); + ourLog.info(bundleText); + + org.hl7.fhir.dstu2016may.model.Bundle reincarnatedBundle = jsonParser.parseResource(org.hl7.fhir.dstu2016may.model.Bundle.class, bundleText); + org.hl7.fhir.dstu2016may.model.Patient reincarnatedPatient = (org.hl7.fhir.dstu2016may.model.Patient) reincarnatedBundle.getEntry().get(0).getResource(); + + assertEquals("Patient", patient.getIdElement().getResourceType()); + assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType()); + } + + /** + * See #207 + */ + @Test + public void testParseResourceWithInvalidType() { + String input = "{" + "\"resourceType\":\"Patient\"," + "\"contained\":[" + " {" + " \"rezType\":\"Organization\"" + " }" + " ]" + "}"; + + IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true); + try { + jsonParser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Missing required element 'resourceType' from JSON resource object, unable to parse", e.getMessage()); + } + } + + /** + * See #344 + */ + @Test + public void testParserIsCaseSensitive() { + org.hl7.fhir.dstu2016may.model.Observation obs = new org.hl7.fhir.dstu2016may.model.Observation(); + org.hl7.fhir.dstu2016may.model.SampledData data = new org.hl7.fhir.dstu2016may.model.SampledData(); + data.setData("1 2 3"); + data.setOrigin((org.hl7.fhir.dstu2016may.model.SimpleQuantity) new org.hl7.fhir.dstu2016may.model.SimpleQuantity().setValue(0L)); + data.setPeriod(1000L); + obs.setValue(data); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler()); + String encoded = p.encodeResourceToString(obs); + ourLog.info(encoded); + + p.parseResource(encoded); + + try { + p.parseResource(encoded.replace("Observation", "observation")); + fail(); + } catch (DataFormatException e) { + assertEquals("Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", e.getMessage()); + } + + try { + p.parseResource(encoded.replace("valueSampledData", "valueSampleddata")); + fail(); + } catch (DataFormatException e) { + assertEquals("Unknown element 'valueSampleddata' found during parse", e.getMessage()); + } + } + + @Test + public void testParseWithPrecision() { + String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}"; + org.hl7.fhir.dstu2016may.model.Observation obs = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Observation.class, input); + + org.hl7.fhir.dstu2016may.model.DecimalType valueElement = ((org.hl7.fhir.dstu2016may.model.Quantity) obs.getValue()).getValueElement(); + assertEquals("0.000000000000000100", valueElement.getValueAsString()); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str); + } + + @Test(expected = DataFormatException.class) + public void testParseWithTrailingContent() throws Exception { + //@formatter:off + String bundle = "{\n" + + " \"resourceType\" : \"Bundle\",\n" + + " \"total\" : 1\n" + + "}}"; + //@formatter:on + + org.hl7.fhir.dstu2016may.model.Bundle b = ourCtx.newJsonParser().parseResource(org.hl7.fhir.dstu2016may.model.Bundle.class, bundle); + } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + org.hl7.fhir.dstu2016may.model.Patient fhirPat = new org.hl7.fhir.dstu2016may.model.Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new org.hl7.fhir.dstu2016may.model.Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(org.hl7.fhir.dstu2016may.model.Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((org.hl7.fhir.dstu2016may.model.Reference) extlst.get(0).getValue()).getReference()); + } + + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java new file mode 100644 index 00000000000..186cac8e6a6 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java @@ -0,0 +1,60 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu21; + +import java.util.ArrayList; +import java.util.List; +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu2016may.model.Identifier; +import org.hl7.fhir.dstu2016may.model.Patient; + +@ResourceDef(name = "Patient") +public class PatientWithExtendedContactDstu3 extends Patient { + + private static final long serialVersionUID = 1L; + + /** + * A contact party (e.g. guardian, partner, friend) for the patient. + */ + @Child(name = "contact", type = {}, order = Child.REPLACE_PARENT, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) + @Description(shortDefinition = "A contact party (e.g. guardian, partner, friend) for the patient", formalDefinition = "A contact party (e.g. guardian, partner, friend) for the patient.") + protected List customContact; + + public List getCustomContact() { + if (customContact == null) { + customContact = new ArrayList(); + } + return customContact; + } + + @Block() + public static class CustomContactComponent extends ContactComponent { + + private static final long serialVersionUID = 1L; + @Child(name = "contact-eyecolour", type = { Identifier.class }, modifier = true) + @Description(shortDefinition = "Application ID") + @Extension(url = "http://foo.com/contact-eyecolour", definedLocally = false, isModifier = false) + private Identifier myEyeColour; + + /* + * Get messageHeaderApplicationId + */ + public Identifier getEyeColour() { + if (myEyeColour == null) { + myEyeColour = new Identifier(); + } + return myEyeColour; + } + + /* + * Set messageHeaderApplicationId + */ + public void setEyeColour(Identifier messageHeaderApplicationId) { + this.myEyeColour = messageHeaderApplicationId; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java new file mode 100644 index 00000000000..25a4e0f3ee2 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java @@ -0,0 +1,2480 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu21; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.LenientErrorHandler; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.rest.api.Constants; +import com.google.common.collect.Sets; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.hl7.fhir.dstu2016may.model.Address; +import org.hl7.fhir.dstu2016may.model.Appointment; +import org.hl7.fhir.dstu2016may.model.AuditEvent; +import org.hl7.fhir.dstu2016may.model.Binary; +import org.hl7.fhir.dstu2016may.model.Bundle; +import org.hl7.fhir.dstu2016may.model.CodeType; +import org.hl7.fhir.dstu2016may.model.CodeableConcept; +import org.hl7.fhir.dstu2016may.model.Coding; +import org.hl7.fhir.dstu2016may.model.Condition; +import org.hl7.fhir.dstu2016may.model.ContactPoint; +import org.hl7.fhir.dstu2016may.model.DateTimeType; +import org.hl7.fhir.dstu2016may.model.DateType; +import org.hl7.fhir.dstu2016may.model.DiagnosticReport; +import org.hl7.fhir.dstu2016may.model.DocumentManifest; +import org.hl7.fhir.dstu2016may.model.Duration; +import org.hl7.fhir.dstu2016may.model.Encounter; +import org.hl7.fhir.dstu2016may.model.Enumerations; +import org.hl7.fhir.dstu2016may.model.Extension; +import org.hl7.fhir.dstu2016may.model.HumanName; +import org.hl7.fhir.dstu2016may.model.IdType; +import org.hl7.fhir.dstu2016may.model.Identifier; +import org.hl7.fhir.dstu2016may.model.InstantType; +import org.hl7.fhir.dstu2016may.model.Location; +import org.hl7.fhir.dstu2016may.model.Medication; +import org.hl7.fhir.dstu2016may.model.MedicationOrder; +import org.hl7.fhir.dstu2016may.model.Observation; +import org.hl7.fhir.dstu2016may.model.Organization; +import org.hl7.fhir.dstu2016may.model.Patient; +import org.hl7.fhir.dstu2016may.model.PrimitiveType; +import org.hl7.fhir.dstu2016may.model.Quantity; +import org.hl7.fhir.dstu2016may.model.Reference; +import org.hl7.fhir.dstu2016may.model.Resource; +import org.hl7.fhir.dstu2016may.model.SampledData; +import org.hl7.fhir.dstu2016may.model.SimpleQuantity; +import org.hl7.fhir.dstu2016may.model.StringType; +import org.hl7.fhir.dstu2016may.model.UriType; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.builder.Input; +import org.xmlunit.diff.ComparisonControllers; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.Diff; +import org.xmlunit.diff.ElementSelectors; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU2_1; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class XmlParserDstu2_1Test { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2_1Test.class); + private FhirContext ourCtx = FhirContext.forDstu2_1(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_DSTU2_1.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + try { + String tmp = ""; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + Bundle bundle = (Bundle) ourCtx.newXmlParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = null; + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + try { + String tmp = ""; + Bundle bundle = (Bundle) ourCtx.newXmlParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = null; + } + } + + /** + * See #414 + */ + @Test + public void testParseXmlExtensionWithoutUrl() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getExtension().size()); + assertEquals(null, parsed.getExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", ((PrimitiveType)parsed.getExtension().get(0).getValue()).getValueAsString()); + + try { + parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getCause().getMessage()); + } + + } + + + /** + * See #414 + */ + @Test + public void testParseXmlModifierExtensionWithoutUrl() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getModifierExtension().size()); + assertEquals(null, parsed.getModifierExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", ((PrimitiveType)parsed.getModifierExtension().get(0).getValue()).getValueAsString()); + + try { + parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getCause().getMessage()); + } + + } + + @Test + public void testEncodeChainedContainedResourcer() { + Organization gp = new Organization(); + gp.setName("grandparent"); + + Organization parent = new Organization(); + parent.setName("parent"); + parent.getPartOf().setResource(gp); + + Organization child = new Organization(); + child.setName("child"); + child.getPartOf().setResource(parent); + + Patient patient = new Patient(); + patient.getManagingOrganization().setResource(child); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + patient = ourCtx.newXmlParser().parseResource(Patient.class, encoded); + + child = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("child", child.getName()); + + parent = (Organization) child.getPartOf().getResource(); + assertEquals("parent", parent.getName()); + + gp = (Organization) parent.getPartOf().getResource(); + assertEquals("grandparent", gp.getName()); + } + + @Test + public void testBundleWithBinary() { + //@formatter:off + String bundle = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, bundle); + assertEquals(1, b.getEntry().size()); + + Binary bin = (Binary) b.getEntry().get(0).getResource(); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, bin.getContent()); + + } + + @Test + public void testContainedResourceInExtensionUndeclared() { + Patient p = new Patient(); + p.addName().addFamily("PATIENT"); + + Organization o = new Organization(); + o.setName("ORG"); + p.addExtension(new Extension("urn:foo", new Reference(o))); + + String str = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(str); + + p = ourCtx.newXmlParser().parseResource(Patient.class, str); + assertEquals("PATIENT", p.getName().get(0).getFamilyAsSingleString()); + + List exts = p.getExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + Reference rr = (Reference) exts.get(0).getValue(); + o = (Organization) rr.getResource(); + assertEquals("ORG", o.getName()); + } + + @Test + public void testDuration() { + Encounter enc = new Encounter(); + Duration duration = new Duration(); + duration.setUnit("day").setValue(123L); + enc.setLength(duration); + + String str = ourCtx.newXmlParser().encodeResourceToString(enc); + ourLog.info(str); + + assertThat(str, not(containsString("meta"))); + assertThat(str, containsString("")); + } + + @Test + public void testEncodeAndParseBundleWithResourceRefs() { + + Patient pt = new Patient(); + pt.setId("patid"); + pt.addName().addFamily("PATIENT"); + + Organization org = new Organization(); + org.setId("orgid"); + org.setName("ORG"); + pt.getManagingOrganization().setResource(org); + + Bundle bundle = new Bundle(); + bundle.addEntry().setResource(pt); + bundle.addEntry().setResource(org); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "" + )); + //@formatter:on + + bundle = ourCtx.newXmlParser().parseResource(Bundle.class, encoded); + pt = (Patient) bundle.getEntry().get(0).getResource(); + org = (Organization) bundle.getEntry().get(1).getResource(); + + assertEquals("Organization/orgid", org.getIdElement().getValue()); + assertEquals("Organization/orgid", pt.getManagingOrganization().getReferenceElement().getValue()); + assertSame(org, pt.getManagingOrganization().getResource()); + } + + @Test + public void testEncodeAndParseContained() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + + // Create a bundle with just the patient resource + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + // Encode the bundle + encoded = xmlParser.encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + // Re-parse the bundle + patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReference()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getIdElement().getValue()); + assertEquals("Contained Test Organization", org.getName()); + + // And re-encode a second time + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared + patient.getContained().clear(); + patient.getManagingOrganization().setReference((String) null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().clear(); + patient.getManagingOrganization().setReference((String) null); + patient.getManagingOrganization().getResource().setId(("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + + } + + @Test + public void testEncodeAndParseContainedNonCustomTypes() { + ourCtx = FhirContext.forDstu2_1(); + + Observation obs = new Observation(); + obs.setStatus(Observation.ObservationStatus.FINAL); + + DiagnosticReport dr = new DiagnosticReport(); + dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL); + dr.addResult().setResource(obs); + + IParser parser = ourCtx.newXmlParser(); + parser.setPrettyPrint(true); + + String output = parser.encodeResourceToString(dr); + ourLog.info(output); + + //@formatter:off + assertThat(output,stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + /* + * Now PARSE! + */ + + dr = (DiagnosticReport) parser.parseResource(output); + assertEquals(DiagnosticReport.DiagnosticReportStatus.FINAL, dr.getStatus()); + + assertEquals("#1", dr.getResult().get(0).getReference()); + obs = (Observation) dr.getResult().get(0).getResource(); + assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus()); + + ourCtx = null; + } + + @Test + public void testEncodeAndParseExtensionOnCode() { + Organization o = new Organization(); + o.setName("ORG"); + o.addExtension(new Extension("urn:foo", new CodeType("acode"))); + + String str = ourCtx.newXmlParser().encodeResourceToString(o); + ourLog.info(str); + assertThat(str, containsString("")); + + o = ourCtx.newXmlParser().parseResource(Organization.class, str); + + List exts = o.getExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + CodeType code = (CodeType) exts.get(0).getValue(); + assertEquals("acode", code.getValue()); + + } + + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + patient.addExtension(ext); + + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child1); + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); + parent.addExtension(child2); + + Extension modExt = new Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new DateType("1995-01-02")); + patient.addModifierExtension(modExt); + + HumanName name = patient.addName(); + name.addFamily("Blah"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.addExtension(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + given2ext.addExtension(new Extension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"))); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + + /* + * Now parse this back + */ + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); + + } + + /** + * See #216 + */ + @Test + public void testEncodeAndParseIdentifierDstu2() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + Patient patient = new Patient(); + patient.addIdentifier().setSystem("SYS").setValue("VAL").setType(new CodeableConcept().addCoding(new Coding().setSystem("http://hl7.org/fhir/v2/0203").setCode("MR"))); + + String out = xmlParser.encodeResourceToString(patient); + ourLog.info(out); + + //@formatter:off + assertThat(out, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + patient = ourCtx.newXmlParser().parseResource(Patient.class, out); + assertEquals("http://hl7.org/fhir/v2/0203", patient.getIdentifier().get(0).getType().getCoding().get(0).getSystem()); + assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode()); + } + + /** + * See #347 + */ + @Test + public void testEncodeAndParseMedicationOrder() { + MedicationOrder mo = new MedicationOrder(); + mo.getDateWrittenElement().setValueAsString("2015-10-05"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(mo); + ourLog.info(encoded); + + mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, encoded); + assertEquals("2015-10-05", mo.getDateWrittenElement().getValueAsString()); + } + + @Test + public void testEncodeAndParseMetaProfileAndTags() { + Patient p = new Patient(); + p.addName().addFamily("FAMILY"); + + p.getMeta().addProfile("http://foo/Profile1"); + p.getMeta().addProfile("http://foo/Profile2"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1"); + p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2"); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + List gotLabels = parsed.getMeta().getProfile(); + assertEquals(2, gotLabels.size()); + UriType label = gotLabels.get(0); + assertEquals("http://foo/Profile1", label.getValue()); + label = gotLabels.get(1); + assertEquals("http://foo/Profile2", label.getValue()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + + tagList = parsed.getMeta().getSecurity(); + assertEquals(2, tagList.size()); + assertEquals("sec_scheme1", tagList.get(0).getSystem()); + assertEquals("sec_term1", tagList.get(0).getCode()); + assertEquals("sec_label1", tagList.get(0).getDisplay()); + assertEquals("sec_scheme2", tagList.get(1).getSystem()); + assertEquals("sec_term2", tagList.get(1).getCode()); + assertEquals("sec_label2", tagList.get(1).getDisplay()); + } + + @Test + public void testEncodeAndParseMetaProfiles() { + Patient p = new Patient(); + p.addName().addFamily("FAMILY"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + assertThat(parsed.getMeta().getProfile(), empty()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + } + + /** + * See #336 + */ + @Test + public void testEncodeAndParseNullPrimitiveWithExtensions() { + + Patient p = new Patient(); + p.setId("patid"); + HumanName name = p.addName(); + name.addGivenElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0"))); + name.addGivenElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id")); + name.addGivenElement(); // this one shouldn't get encoded + name.addGivenElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3"))); + name.setId("nameid"); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p); + String expected = ""; + + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", output); + + assertEquals(expected, output); + + p = ourCtx.newXmlParser().parseResource(Patient.class, output); + assertEquals("patid", p.getIdElement().getIdPart()); + + name = p.getName().get(0); + assertEquals("nameid", name.getId()); + assertEquals(3, name.getGiven().size()); + + assertEquals(null, name.getGiven().get(0).getValue()); + assertEquals("V1", name.getGiven().get(1).getValue()); + assertEquals(null, name.getGiven().get(2).getValue()); + + assertEquals("f0", name.getGiven().get(0).getId()); + assertEquals("f1", name.getGiven().get(1).getId()); + assertEquals(null, name.getGiven().get(2).getId()); + + assertEquals(1, name.getGiven().get(0).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl()); + assertEquals("FOOEXT0", ((StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(1).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl()); + assertEquals("FOOEXT1", ((StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue()); + assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(2).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl()); + assertEquals("FOOEXT3", ((StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId()); + + } + + + + + @Test + public void testEncodeAndParseSecurityLabels() { + Patient p = new Patient(); + p.addName().addFamily("FAMILY"); + + List labels = new ArrayList(); + labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1")); + labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2")); + p.getMeta().getSecurity().addAll(labels); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + List gotLabels = parsed.getMeta().getSecurity(); + + assertEquals(2, gotLabels.size()); + + Coding label = gotLabels.get(0); + assertEquals("SYSTEM1", label.getSystem()); + assertEquals("CODE1", label.getCode()); + assertEquals("DISPLAY1", label.getDisplay()); + assertEquals("VERSION1", label.getVersion()); + + label = gotLabels.get(1); + assertEquals("SYSTEM2", label.getSystem()); + assertEquals("CODE2", label.getCode()); + assertEquals("DISPLAY2", label.getDisplay()); + assertEquals("VERSION2", label.getVersion()); + } + + + @Test + public void testEncodeBinaryWithNoContentType() { + Binary b = new Binary(); + b.setContent(new byte[] { 1, 2, 3, 4 }); + + String output = ourCtx.newXmlParser().encodeResourceToString(b); + ourLog.info(output); + + assertEquals("", output); + } + + @Test + public void testEncodeBundleWithContained() { + DiagnosticReport rpt = new DiagnosticReport(); + rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Sharp1")).setId("#1")); + rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Uuid1")).setId("urn:uuid:UUID1")); + + Bundle b = new Bundle(); + b.addEntry().setResource(rpt); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + )); + //@formatter:on + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResources() { + + MedicationOrder medicationPrescript = new MedicationOrder(); + + String medId = "123"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding().setSystem("urn:sys").setCode("code1")); + + // Adding medication to Contained. + Medication medResource = new Medication(); + medResource.setCode(codeDt); + medResource.setId("#" + String.valueOf(medId)); + medicationPrescript.getContained().add(medResource); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference("#" + medId); + medRefDt.setDisplay("MedRef"); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + // @formatter:on + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + //@formatter:off + + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResourcesAutomatic() { + + MedicationOrder medicationPrescript = new MedicationOrder(); + String nameDisp = "MedRef"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null)); + + // Adding medication to Contained. + Medication medResource = new Medication(); + // No ID set + medResource.setCode(codeDt); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference(); + medRefDt.setDisplay(nameDisp); + // Resource reference set, but no ID + medRefDt.setResource(medResource); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + //@formatter:on + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + //@formatter:off + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResourcesManualContainUsingNonLocalId() { + + MedicationOrder medicationPrescript = new MedicationOrder(); + + String medId = "123"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null)); + + // Adding medication to Contained. + Medication medResource = new Medication(); + medResource.setCode(codeDt); + medResource.setId(String.valueOf(medId)); // ID does not start with '#' + medicationPrescript.getContained().add(medResource); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference("#" + medId); + medRefDt.setDisplay("MedRef"); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + //@formatter:on + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + //@formatter:off + + } + + @Test + public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + org.getText().setDivAsString("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getText().setDivAsString("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("", "
BARFOO
", "", "", "", "\n\n

A P TAG

line1\nline2\nline3  BOLD

"); + + String output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "A P TAG

", + "

line1\nline2\nline3  BOLD
" + )); + //@formatter:on + + } + + @Test + public void testEncodeDivWithPrePrettyPrint() { + + Patient p = new Patient(); + p.getText().setDivAsString("
\n\n

A P TAG

line1\nline2\nline3  BOLD

"); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + " ", + " line1\nline2\nline3 BOLD" + )); + //@formatter:on + + } + + @Test + public void testEncodeDoesntIncludeUuidId() { + Patient p = new Patient(); + p.setId(new IdType("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2")); + p.addIdentifier().setSystem("ACME"); + + String actual = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + assertThat(actual, not(containsString("78ef6f64c2f2"))); + } + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newXmlParser().encodeResourceToString(new Binary()); + assertEquals("", output); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding()); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, not(containsString("tag"))); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag2() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding().setSystem("scheme").setCode("code")); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, containsString("tag")); + assertThat(encoded, containsString("scheme")); + assertThat(encoded, not(containsString("Label"))); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType) obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "" + )); + assertThat(output, not(stringContainsInOrder( + "" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + + /** + * See #327 + */ + @Test + public void testEncodeExtensionWithContainedResource() { + + TestPatientFor327 patient = new TestPatientFor327(); + patient.setBirthDateElement(new DateType("2016-04-14")); + + List conditions = new ArrayList(); + Condition condition = new Condition(); + condition.addBodySite().setText("BODY SITE"); + conditions.add(new Reference(condition)); + patient.setCondition(conditions); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + )); + //@formatter:on + } + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + patient.addExtension(new Extension("urn:foo", new Reference("Organization/123"))); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + List ext = actual.getExtension(); + assertEquals(1, ext.size()); + Reference ref = (Reference) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReference()); + + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath3() { + ourCtx = FhirContext.forDstu2_1(); + + assertNull(ourCtx.newXmlParser().getStripVersionsFromReferences()); + + AuditEvent auditEvent = new AuditEvent(); + auditEvent.addEntity().setReference(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newXmlParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList()); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths((String[]) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths((List) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + } + + @Test + public void testEncodeNarrativeSuppressed() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", "", "")); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeNonContained() { + // Create an organization + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getManagingOrganization().setResource(org); + + // Create a list containing both resources. In a server method, you might just + // return this list, but here we will create a bundle to encode. + List resources = new ArrayList(); + resources.add(org); + resources.add(patient); + + // Create a bundle with both + Bundle b = new Bundle(); + b.addEntry().setResource(org); + b.addEntry().setResource(patient); + + // Encode the buntdle + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, stringContainsInOrder("", "")); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder("", "
")); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, containsString("")); + + } + + + + + + @Test + public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() { + + Patient patient = new Patient(); + patient.setId("phitcc_pat_normal"); + patient.addName().addGiven("Patty").setUse(HumanName.NameUse.NICKNAME); + patient.addTelecom().setSystem(ContactPoint.ContactPointSystem.EMAIL).setValue("patpain@ehealthinnovation.org"); + patient.setGender(Enumerations.AdministrativeGender.FEMALE); + patient.setBirthDateElement(new DateType("2001-10-13")); + + DateTimeType obsEffectiveTime = new DateTimeType("2015-04-11T12:22:01-04:00"); + + Observation obsParent = new Observation(); + obsParent.setId("phitcc_obs_bp_parent"); + obsParent.getSubject().setResource(patient); + obsParent.setStatus(Observation.ObservationStatus.FINAL); + obsParent.setEffective(obsEffectiveTime); + + Observation obsSystolic = new Observation(); + obsSystolic.setId("phitcc_obs_bp_dia"); + obsSystolic.getSubject().setResource(patient); + obsSystolic.setEffective(obsEffectiveTime); + obsParent.addRelated().setType(Observation.ObservationRelationshipType.HASMEMBER).setTarget(new Reference(obsSystolic)); + + Observation obsDiastolic = new Observation(); + obsDiastolic.setId("phitcc_obs_bp_dia"); + obsDiastolic.getSubject().setResource(patient); + obsDiastolic.setEffective(obsEffectiveTime); + obsParent.addRelated().setType(Observation.ObservationRelationshipType.HASMEMBER).setTarget(new Reference(obsDiastolic)); + + String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(obsParent); + ourLog.info(str); + + assertThat(str, containsString("")); + assertThat(str, containsString("")); + } + + + @Test + public void testEncodeSummary() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", "", "")); + assertThat(encoded, stringContainsInOrder("", "", "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeWithContained() { + List contained = new ArrayList(); + + // Will be added by reference + Patient p = new Patient(); + p.setId("#" + "1000"); + contained.add(p); + + // Will be added by direct resource object + Location l = new Location(); + l.setId("#" + "1001"); + contained.add(l); + + // Will not be referred to (and therefore shouldn't appear in output) + Location l2 = new Location(); + l2.setId("#1002"); + contained.add(l2); + + Appointment appointment = new Appointment(); + appointment.setId("1234"); + appointment.getContained().addAll(contained); + + appointment.addParticipant().getActor().setReference("#1000"); + appointment.addParticipant().getActor().setResource(l); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(appointment); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + )); + //@formatter:on + + assertThat(encoded, not(containsString("#1002"))); + } + + @Test + public void testEncodeWithDontEncodeElements() throws Exception { + Patient patient = new Patient(); + patient.setId("123"); + patient.getMeta().addProfile("http://profile"); + patient.addName().addFamily("FAMILY").addGiven("GIVEN"); + patient.addAddress().addLine("LINE1"); + + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.name.family")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("GIVEN")); + assertThat(out, not(containsString("FAMILY"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta")); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("id")); + assertThat(out, not(containsString("address"))); + assertThat(out, not(containsString("meta"))); + } + } + + @Test + public void testEncodeWithEncodeElements() throws Exception { + Patient patient = new Patient(); + patient.getMeta().addProfile("http://profile"); + patient.addName().addFamily("FAMILY"); + patient.addAddress().addLine("LINE1"); + + Bundle bundle = new Bundle(); + bundle.setTotal(100); + bundle.addEntry().setResource(patient); + + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name", "Bundle.entry"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, not(containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, not(containsString("address"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, (containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, not(containsString("address"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet(Arrays.asList("Patient"))); + p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, (containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, (containsString("address"))); + } + + } + + @Test + public void testMoreExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + + // Add the extension to the resource + patient.addExtension(ext); + // END SNIPPET: resourceExtension + + // START SNIPPET: resourceStringExtension + HumanName name = patient.addName(); + name.addFamily("Shmoe"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.addExtension(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + Extension givenExtChild = new Extension(); + givenExtChild.setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); + given2ext.addExtension(givenExtChild); + // END SNIPPET: resourceStringExtension + + // START SNIPPET: subExtension + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child1); + + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child2); + // END SNIPPET: subExtension + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + } + + @Test + public void testOmitResourceId() { + Patient p = new Patient(); + p.setId("123"); + p.addName().addFamily("ABC"); + + assertThat(ourCtx.newXmlParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC")); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC")); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + } + + + @Test + public void testParseAndEncodeComments() throws IOException { + //@formatter:off + String input = "\n" + + " " + + " \n" + + " \n" + + " \n" + + "
\n" + + "\n" + + "

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

\n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " " + + "
"; + //@formatter:off + + Patient res = ourCtx.newXmlParser().parseResource(Patient.class, input); + res.getFormatCommentsPre(); + assertEquals("Patient/pat1", res.getId()); + assertEquals("654321", res.getIdentifier().get(0).getValue()); + assertEquals(true, res.getActive()); + + assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment")); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "\"identifier\": [", + "{", + "\"fhir_comments\":", + "[", + "\"identifier comment 1\"", + ",", + "\"identifier comment 2\"", + "]", + "\"use\": \"usual\",", + "\"_use\": {", + "\"fhir_comments\":", + "[", + "\"use comment 1\"", + ",", + "\"use comment 2\"", + "]", + "},", + "\"type\"" + )); + //@formatter:off + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "
", + "

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

", + "
", + "
", + " \n", + " ", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "
" + )); + //@formatter:off + + } + + @Test + public void testParseAndEncodeCommentsOnExtensions() { + //@formatter:off + String input = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient pat = ourCtx.newXmlParser().parseResource(Patient.class, input); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + )); + + output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(pat); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "{", + " \"resourceType\": \"Patient\",", + " \"id\": \"someid\",", + " \"_id\": {", + " \"fhir_comments\": [", + " \" comment 1 \"", + " ]", + " },", + " \"extension\": [", + " {", + " \"fhir_comments\": [", + " \" comment 2 \",", + " \" comment 7 \"", + " ],", + " \"url\": \"urn:patientext:att\",", + " \"valueAttachment\": {", + " \"fhir_comments\": [", + " \" comment 3 \",", + " \" comment 6 \"", + " ],", + " \"contentType\": \"aaaa\",", + " \"_contentType\": {", + " \"fhir_comments\": [", + " \" comment 4 \"", + " ]", + " },", + " \"data\": \"AAAA\",", + " \"_data\": {", + " \"fhir_comments\": [", + " \" comment 5 \"", + " ]", + " }", + " }", + " }", + " ]", + "}" + )); + + //@formatter:on + } + + + @Test + public void testParseAndEncodeNestedExtensions() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input); + DateType bd = p.getBirthDateElement(); + assertEquals("2005-03-04", bd.getValueAsString()); + + List exts = bd.getExtensionsByUrl("http://my.fancy.extension.url"); + assertEquals(1, exts.size()); + Extension ext = exts.get(0); + assertEquals(null, ext.getValue()); + + exts = ext.getExtensionsByUrl("http://my.fancy.extension.url"); + assertEquals(1, exts.size()); + ext = exts.get(0); + assertEquals("myNestedValue", ((StringType) ext.getValue()).getValue()); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "")); + //@formatter:on + + } + + @Test + public void testParseBundleNewWithPlaceholderIds() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + } + + @Test + public void testParseBundleNewWithPlaceholderIdsInBase1() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + } + + @Test + public void testParseBundleNewWithPlaceholderIdsInBase2() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + //@formatter:off + input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on + + parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + } + + @Test + public void testParseBundleOldStyleWithUnknownLinks() throws Exception { + //@formatter:off + String bundle = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Bundle b = (Bundle) ourCtx.newXmlParser().parseResource(bundle); + assertEquals(1, b.getEntry().size()); + + } + + @Test + public void testParseBundleOldWithPlaceholderIds() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on + + Bundle parsed = (Bundle) ourCtx.newXmlParser().parseResource(input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getId()); + + } + + @Test + public void testParseBundleWithBinary() { + // TODO: implement this test, make sure we handle ID and meta correctly in Binary + } + + + + @Test + public void testParseBundleWithResourceId() { + //@formatter:off + String input = "" + + "" + + "" + + "" + + "\n"; + //@formatter:on + + Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/3", bundle.getEntry().get(0).getResource().getIdElement().getValue()); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/2", bundle.getEntry().get(1).getResource().getIdElement().getValue()); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/1", bundle.getEntry().get(2).getResource().getIdElement().getValue()); + } + + /** + * Thanks to Alexander Kley! + */ + @Test + public void testParseContainedBinaryResource() { + byte[] bin = new byte[] { 0, 1, 2, 3, 4 }; + final Binary binary = new Binary(); + binary.setContentType("PatientConsent").setContent(bin); + + DocumentManifest manifest = new DocumentManifest(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setSystem("mySystem").setCode("PatientDocument"); + manifest.setType(cc); + manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString())); + manifest.addContent().setP(new Reference(binary)); + manifest.setStatus(Enumerations.DocumentReferenceStatus.CURRENT); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest); + ourLog.info(encoded); + assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", ""))); + + DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded); + assertEquals(1, actual.getContained().size()); + assertEquals(1, actual.getContent().size()); + + /* + * If this fails, it's possibe the DocumentManifest structure is wrong: It should be + * + * @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true) + */ + assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource()); + } + + /** + * See #426 + */ + @Test + public void testParseExtensionWithIdType() { + //@formatter:off + String input = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare"); + extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id"); + Extension ext = extList.get(0); + IdType value = (IdType) ext.getValue(); + assertEquals("mc1", value.getValueAsString()); + } + + /** + * See #426 + * + * Value type of FOO isn't a valid datatype + */ + @Test + public void testParseExtensionWithInvalidType() { + //@formatter:off + String input = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare"); + extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id"); + Extension ext = extList.get(0); + IdType value = (IdType) ext.getValue(); + assertEquals(null, value); + } + + /** + * See #342 + */ + @Test(expected = DataFormatException.class) + public void testParseInvalid() { + ourCtx.newXmlParser().parseResource("FOO"); + } + + /** + * See #366 + */ + @Test() + public void testParseInvalidBoolean() { + //@formatter:off + String resource = "\n" + + " \n" + + ""; + //@formatter:on + + IParser p = ourCtx.newXmlParser(); + + try { + p.parseResource(resource); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"1\": Invalid boolean string: '1'", e.getMessage()); + } + + LenientErrorHandler errorHandler = new LenientErrorHandler(); + assertEquals(true, errorHandler.isErrorOnInvalidValue()); + errorHandler.setErrorOnInvalidValue(false); + p.setParserErrorHandler(errorHandler); + } + + @Test + public void testParseInvalidTextualNumber() { + Observation obs = new Observation(); + obs.setValue(new Quantity().setValue(1234)); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); + encoded = encoded.replace("1234", "\"1234\""); + ourLog.info(encoded); + ourCtx.newJsonParser().parseResource(encoded); + } + + @Test + public void testParseMetadata() throws Exception { + //@formatter:off + String bundle = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, bundle); + assertEquals(1, b.getEntry().size()); + + Bundle.BundleEntryComponent entry = b.getEntry().get(0); + Patient pt = (Patient) entry.getResource(); + assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getIdElement().getValue()); + assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString()); + assertEquals("0.123", entry.getSearch().getScore().toString()); + assertEquals("match", entry.getSearch().getMode().toCode()); + assertEquals("POST", entry.getRequest().getMethod().toCode()); + assertEquals("http://foo/Patient?identifier=value", entry.getRequest().getUrl()); + assertEquals("2001-02-22T09:22:33-07:00", pt.getMeta().getLastUpdatedElement().getValueAsString()); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String reEncoded = p.encodeResourceToString(b); + ourLog.info(reEncoded); + + compareXml(bundle, reEncoded); + + } + + @Test + public void testParseMetaUpdatedDate() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, input); + + InstantType updated = b.getMeta().getLastUpdatedElement(); + assertEquals("2015-06-22T15:48:57.554-04:00", updated.getValueAsString()); + + } + + @Test + public void testParseNestedExtensionsInvalid() { + //@formatter:off + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + try { + ourCtx.newXmlParser().parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("Extension (URL='http://my.fancy.extension.url') must not have both a value and other contained extensions")); + } + } + + /** + * See #163 + */ + @Test + public void testParseResourceType() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Patient + Patient patient = new Patient(); + String patientId = UUID.randomUUID().toString(); + patient.setId(new IdType("Patient", patientId)); + patient.addName().addGiven("John").addFamily("Smith"); + patient.setGender(Enumerations.AdministrativeGender.MALE); + patient.setBirthDateElement(new DateType("1987-04-16")); + + // Bundle + Bundle bundle = new Bundle(); + bundle.setType(Bundle.BundleType.COLLECTION); + bundle.addEntry().setResource(patient); + + String bundleText = xmlParser.encodeResourceToString(bundle); + ourLog.info(bundleText); + + Bundle reincarnatedBundle = xmlParser.parseResource(Bundle.class, bundleText); + Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource(); + + assertEquals("Patient", patient.getIdElement().getResourceType()); + assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType()); + } + + /** + * See #344 + */ + @Test + public void testParserIsCaseSensitive() { + Observation obs = new Observation(); + SampledData data = new SampledData(); + data.setData("1 2 3"); + data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L)); + data.setPeriod(1000L); + obs.setValue(data); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler()); + String encoded = p.encodeResourceToString(obs); + ourLog.info(encoded); + + p.parseResource(encoded); + + try { + p.parseResource(encoded.replace("Observation", "observation")); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [1,1]]: Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", + e.getMessage()); + } + + try { + p.parseResource(encoded.replace("valueSampledData", "valueSampleddata")); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Unknown element 'valueSampleddata' found during parse", e.getMessage()); + } + } + + /** + * See #339 + * + * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing + */ + @Test + public void testXxe() { + //@formatter:off + String input = + "" + + "" + + "]>" + + "" + + "" + + "
TEXT &xxe; TEXT
" + + "
" + + "
" + + "" + + "
" + + "
"; + //@formatter:on + + ourLog.info(input); + + try { + ourCtx.newXmlParser().parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.toString(), containsString("Undeclared general entity")); + } + + } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + + public static void compareXml(String content, String reEncoded) { + Diff d = DiffBuilder.compare(Input.fromString(content)) + .withTest(Input.fromString(reEncoded)) + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)) + .checkForSimilar() + .ignoreWhitespace() + .ignoreComments() + .withComparisonController(ComparisonControllers.Default) + .build(); + + assertTrue(d.toString(), !d.hasDifferences()); + } + + @ResourceDef(name = "Patient") + public static class TestPatientFor327 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "testCondition") + @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false) + private List testConditions = null; + + public List getConditions() { + return this.testConditions; + } + + public void setCondition(List ref) { + this.testConditions = ref; + } + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + private Matcher stringContainsInOrder(List substrings) { + return Matchers.stringContainsInOrder(substrings); + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java new file mode 100644 index 00000000000..9adf2c836d9 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java @@ -0,0 +1,136 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import java.io.IOException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.validation.FhirValidator; +import ca.uhn.fhir.validation.ValidationResult; +import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport; +import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator; +import org.hl7.fhir.instance.model.DateType; +import org.hl7.fhir.instance.model.Observation; +import org.hl7.fhir.instance.model.QuestionnaireResponse; +import org.hl7.fhir.instance.model.StringType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_HL7ORG_DSTU2; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class FhirInstanceValidatorTest { + private FhirInstanceValidator ourValidator = new FhirInstanceValidator(new DefaultProfileValidationSupport()); + private FhirContext ourCtxHl7OrgDstu2 = FhirContext.forDstu2Hl7Org(); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorTest.class); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_VALIDATION_HL7ORG_DSTU2.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testQuestionnaireResponse() { + QuestionnaireResponse qr = new QuestionnaireResponse(); + qr.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED); + qr.getGroup().addGroup().addQuestion().setLinkId("foo"); + qr.getGroup().addQuestion().setLinkId("bar"); + + FhirValidator val = ourCtxHl7OrgDstu2.newValidator(); + + val.registerValidatorModule(ourValidator); + + ValidationResult result = val.validateWithResult(qr); + + String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + } + + @Test + public void testObservation() { + Observation o = new Observation(); + o.addIdentifier().setSystem("http://acme.org").setValue("1234"); + o.setStatus(Observation.ObservationStatus.FINAL); + o.getCode().addCoding().setSystem("http://loinc.org").setCode("12345"); + o.getEncounter().setReference("Encounter/1234"); + + FhirValidator val = ourCtxHl7OrgDstu2.newValidator(); + + val.registerValidatorModule(ourValidator); + + ValidationResult result = val.validateWithResult(o); + + String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + } + + @Test + public void testParametersWithTwoParameters() { + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addName().addGiven("James"); + patient.setBirthDateElement(new DateType("2011-02-02")); + + org.hl7.fhir.instance.model.Parameters input = new org.hl7.fhir.instance.model.Parameters(); + input.addParameter().setName("mode").setValue(new StringType("create")); + input.addParameter().setName("resource").setResource(patient); + + FhirValidator val = ourCtxHl7OrgDstu2.newValidator(); + + val.registerValidatorModule(ourValidator); + + ValidationResult result = val.validateWithResult(input); + + String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + assertThat(encoded, not(containsString("A parameter must have a value or a resource, but not both"))); + } + + @Test + public void testParametersHl7OrgDstu2() { + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addName().addGiven("James"); + patient.setBirthDateElement(new DateType("2011-02-02")); + + org.hl7.fhir.instance.model.Parameters input = new org.hl7.fhir.instance.model.Parameters(); + input.addParameter().setName("resource").setResource(patient); + + FhirValidator val = ourCtxHl7OrgDstu2.newValidator(); + + val.registerValidatorModule(ourValidator); + + ValidationResult result = val.validateWithResult(input); + + ourLog.info(ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome())); + assertTrue(result.isSuccessful()); + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java new file mode 100644 index 00000000000..28e98cd4656 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java @@ -0,0 +1,1320 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.narrative.INarrativeGenerator; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.Constants; +import org.apache.commons.io.IOUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.IsNot; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.hl7.fhir.instance.model.Address; +import org.hl7.fhir.instance.model.Address.AddressUse; +import org.hl7.fhir.instance.model.Address.AddressUseEnumFactory; +import org.hl7.fhir.instance.model.Binary; +import org.hl7.fhir.instance.model.Bundle; +import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.instance.model.CodeableConcept; +import org.hl7.fhir.instance.model.Conformance; +import org.hl7.fhir.instance.model.Conformance.UnknownContentCode; +import org.hl7.fhir.instance.model.DateTimeType; +import org.hl7.fhir.instance.model.DateType; +import org.hl7.fhir.instance.model.DecimalType; +import org.hl7.fhir.instance.model.DiagnosticReport; +import org.hl7.fhir.instance.model.EnumFactory; +import org.hl7.fhir.instance.model.Enumeration; +import org.hl7.fhir.instance.model.Extension; +import org.hl7.fhir.instance.model.HumanName; +import org.hl7.fhir.instance.model.Identifier.IdentifierUse; +import org.hl7.fhir.instance.model.InstantType; +import org.hl7.fhir.instance.model.List_; +import org.hl7.fhir.instance.model.Narrative.NarrativeStatus; +import org.hl7.fhir.instance.model.Observation; +import org.hl7.fhir.instance.model.Organization; +import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.Patient.ContactComponent; +import org.hl7.fhir.instance.model.PrimitiveType; +import org.hl7.fhir.instance.model.Reference; +import org.hl7.fhir.instance.model.Specimen; +import org.hl7.fhir.instance.model.StringType; +import org.hl7.fhir.instance.model.ValueSet; +import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent; +import org.hl7.fhir.instance.model.ValueSet.ValueSetCodeSystemComponent; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.INarrative; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.xml.sax.SAXException; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class JsonParserHl7OrgDstu2Test { + + private FhirContext ourCtx = FhirContext.forDstu2Hl7Org(); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserHl7OrgDstu2Test.class); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_HL7ORG_DSTU2.option(), + mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlEnabled() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertEquals("http://lalaland.org", o1Id.getBaseUrl()); + assertEquals("patient", o1Id.getResourceType()); + assertEquals("pat1", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu2Hl7Org(); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu2Hl7Org(); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + Bundle bundle = (Bundle) ourCtx.newJsonParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu2Hl7Org(); + } + } + + @Test + public void testEncodeUndeclaredExtensionWithEnumerationContent() { + IParser parser = ourCtx.newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + EnumFactory fact = new AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueCode\":\"home\"}]")); + + MyPatientWithOneDeclaredEnumerationExtension actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + + @Test + public void testEncodeNarrativeSuppressed() throws Exception { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE)); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + patient.getExtension().add(ext); + + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.getExtension().add(parent); + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.getExtension().add(child1); + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); + parent.getExtension().add(child2); + + Extension modExt = new Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new DateType("1995-01-02")); + patient.getModifierExtension().add(modExt); + + HumanName name = patient.addName(); + name.addFamily("Blah"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.getExtension().add(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.getExtension().add(given2ext); + given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + assertThat(enc, + stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}", + "{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}")); + assertThat(enc, stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],")); + assertThat(enc, containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + "]" + "}")); + + /* + * Now parse this back + */ + + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); + + } + + @Test + public void testEncodeBinaryResource() { + + Binary patient = new Binary(); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newJsonParser().encodeResourceToString(patient); + assertEquals("{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", val); + + } + + @Test + public void testEncodeBundle() throws InterruptedException { + Bundle b = new Bundle(); + + InstantType pub = InstantType.now(); + b.getMeta().setLastUpdatedElement(pub); + Thread.sleep(2); + + Patient p1 = new Patient(); + p1.addName().addFamily("Family1"); + p1.setId("1"); + BundleEntryComponent entry = b.addEntry(); + entry.setResource(p1); + + Patient p2 = new Patient(); + p2.setId("Patient/2"); + p2.addName().addFamily("Family2"); + entry = b.addEntry(); + entry.setResource(p2); + + BundleEntryComponent deletedEntry = b.addEntry(); + Patient dp = new Patient(); + deletedEntry.setResource(dp); + + dp.setId(("3")); + InstantType nowDt = InstantType.withCurrentTime(); + dp.getMeta().setLastUpdatedElement(nowDt); + + String bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(bundleString); + + // List strings = new ArrayList(); + // strings.addAll(Arrays.asList("\"published\":\"" + pub.getValueAsString() + "\"")); + // strings.addAll(Arrays.asList("\"id\":\"1\"")); + // strings.addAll(Arrays.asList("\"id\":\"2\"", "\"rel\":\"alternate\"", "\"href\":\"http://foo/bar\"")); + // strings.addAll(Arrays.asList("\"deleted\":\"" + nowDt.getValueAsString() + "\"", "\"id\":\"Patient/3\"")); + + //@formatter:off + String[] strings = new String[] { + "\"resourceType\": \"Bundle\",", + "\"lastUpdated\": \"" + pub.getValueAsString() + "\"", + "\"entry\": [", + "\"resource\": {", + "\"id\": \"1\"", + "\"resource\": {", + "\"id\": \"2\"", + "\"resource\": {", + "\"id\": \"3\"", + "\"meta\": {", + "\"lastUpdated\": \"" + nowDt.getValueAsString() + "\"" + }; + //@formatter:off + assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(Arrays.asList(strings))); + + b.getEntry().remove(2); + bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + assertThat(bundleString, not(containsString("deleted"))); + + } + + + @Test + public void testEncodeBundleCategory() { + + Bundle b = new Bundle(); + BundleEntryComponent e = b.addEntry(); + + Patient pt = new Patient(); + pt.addIdentifier().setSystem("idsystem"); + e.setResource(pt); + + b.getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("label"); + + String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"label\"}]")); + b = ourCtx.newJsonParser().parseResource(Bundle.class, val); + assertEquals(1, b.getMeta().getTag().size()); + assertEquals("scheme", b.getMeta().getTag().get(0).getSystem()); + assertEquals("term", b.getMeta().getTag().get(0).getCode()); + assertEquals("label", b.getMeta().getTag().get(0).getDisplay()); + + assertNotNull(b.getEntry().get(0).getResource()); + Patient p = (Patient) b.getEntry().get(0).getResource(); + assertEquals("idsystem", p.getIdentifier().get(0).getSystem()); + + } + + + @Test + public void testEncodeBundleEntryCategory() { + + Bundle b = new Bundle(); + BundleEntryComponent e = b.addEntry(); + e.setResource(new Patient()); + e.getResource().getMeta().addTag().setSystem("scheme").setCode( "term").setDisplay( "label"); + + String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"label\"}]}}}]}")); + + b = ourCtx.newJsonParser().parseResource(Bundle.class, val); + assertEquals(1, b.getEntry().size()); + assertEquals(1, b.getEntry().get(0).getResource().getMeta().getTag().size()); + assertEquals("scheme", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getSystem()); + assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode()); + assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay()); + + } + + + @Test + public void testEncodeContained() { + IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = jsonParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\""))); + + // Create a bundle with just the patient resource + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + // Encode the bundle + encoded = jsonParser.encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\""))); + + // Re-parse the bundle + patient = (Patient) jsonParser.parseResource(jsonParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReference()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getIdElement().getValue()); + assertEquals("Contained Test Organization", org.getName()); + + // And re-encode a second time + encoded = jsonParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + // And re-encode once more, with the references cleared + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + encoded = jsonParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + patient.getManagingOrganization().getResource().setId(("#333")); + encoded = jsonParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"333\"", "\"identifier\"", "\"reference\": \"#333\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + } + + @Test + public void testEncodeContained__() { + // Create an organization + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue( "253345"); + patient.getManagingOrganization().setResource(org); + + // Create a bundle with just the patient resource + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + // Encode the buntdle + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\": \"Organization", "id\": \"1\""))); + assertThat(encoded, containsString("reference\": \"#1\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\": \"Organization", "id\": \"1\""))); + assertThat(encoded, containsString("reference\": \"#1\"")); + } + + @Test + public void testEncodeContainedResourcesMore() throws Exception { + + DiagnosticReport rpt = new DiagnosticReport(); + Specimen spm = new Specimen(); + rpt.getText().setDivAsString("AAA"); + rpt.addSpecimen().setResource(spm); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + assertThat(str, StringContains.containsString("
AAA
")); + String substring = "\"reference\": \"#"; + assertThat(str, StringContains.containsString(substring)); + + int idx = str.indexOf(substring) + substring.length(); + int idx2 = str.indexOf('"', idx + 1); + String id = str.substring(idx, idx2); + assertThat(str, StringContains.containsString("\"id\": \"" + id + "\"")); + assertThat(str, IsNot.not(StringContains.containsString(""))); + + } + + @Test + public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + org.getText().setDivAsString("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue( "253345"); + patient.getText().setDivAsString("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("FOOBAR"))); + assertThat(encoded, (containsString("BARFOO"))); + + } + + + + @Test + public void testEncodeDeclaredExtensionWithAddressContent() { + IParser parser = ourCtx.newJsonParser(); + + MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension(); + patient.addAddress().setUse(AddressUse.HOME); + patient.setFoo(new Address().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Address ref = actual.getFoo(); + assertEquals("line1", ref.getLine().get(0).getValue()); + + } + + @Test + public void testEncodeDeclaredExtensionWithResourceContent() { + IParser parser = ourCtx.newJsonParser(); + + MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension(); + patient.addAddress().setUse(AddressUse.HOME); + patient.setFoo(new Reference("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueReference\":{\"reference\":\"Organization/123\"}}]")); + + MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Reference ref = actual.getFoo(); + assertEquals("Organization/123", ref.getReference()); + + } + + @Test + public void testEncodeExt() throws Exception { + + ValueSet valueSet = new ValueSet(); + valueSet.setId("123456"); + + ValueSetCodeSystemComponent define = valueSet.getCodeSystem(); + ConceptDefinitionComponent code = define.addConcept(); + code.setCode("someCode"); + code.setDisplay("someDisplay"); + code.addExtension().setUrl("urn:alt").setValue( new StringType("alt name")); + + + String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + ourLog.info(encoded); + + assertThat(encoded, (containsString("123456"))); + assertEquals( + "{\"resourceType\":\"ValueSet\",\"id\":\"123456\",\"codeSystem\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}", + encoded); + + } + + @Test + public void testEncodeExtensionInCompositeElement() { + + Conformance c = new Conformance(); + c.addRest().getSecurity().addExtension().setUrl("http://foo").setValue(new StringType("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"rest\":[{\"security\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}]}"); + + } + + + + @Test + public void testEncodeExtensionInPrimitiveElement() { + + Conformance c = new Conformance(); + c.getAcceptUnknownElement().addExtension().setUrl( "http://foo").setValue( new StringType("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + // Now with a value + ourLog.info("---------------"); + + c = new Conformance(); + c.getAcceptUnknownElement().setValue(UnknownContentCode.EXTENSIONS); + c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue( new StringType("AAA")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":\"extensions\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + } + + @Test + public void testEncodeExtensionInResourceElement() { + + Conformance c = new Conformance(); + // c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringType("AAA")); + c.addExtension().setUrl("http://foo").setValue( new StringType("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"); + + } + + @Test + public void testEncodeExtensionOnEmptyElement() throws Exception { + + ValueSet valueSet = new ValueSet(); + valueSet.addUseContext().addExtension().setUrl("http://foo").setValue( new StringType("AAA")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + assertThat(encoded, containsString("\"useContext\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}")); + + } + + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = ourCtx.newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue( new Reference("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueReference\":{\"reference\":\"Organization/123\"}}]")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + List ext = actual.getExtension(); + assertEquals(1, ext.size()); + Reference ref = (Reference) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReference()); + + } + + @Test + public void testEncodeIds() { + Patient pt = new Patient(); + pt.addIdentifier().setSystem("sys").setValue( "val"); + + List_ list = new List_(); + list.setId("listId"); + list.addEntry().setItem(new Reference(pt)).setDeleted(true); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(list); + ourLog.info(enc); + + assertThat(enc, containsString("\"id\": \"1\"")); + + List_ parsed = ourCtx.newJsonParser().parseResource(List_.class,enc); + assertEquals(Patient.class, parsed.getEntry().get(0).getItem().getResource().getClass()); + } + + @Test + public void testEncodeInvalidChildGoodException() { + Observation obs = new Observation(); + obs.setValue(new DecimalType(112.22)); + + IParser p = ourCtx.newJsonParser(); + + try { + p.encodeResourceToString(obs); + } catch (DataFormatException e) { + assertThat(e.getMessage(), StringContains.containsString("DecimalType")); + } + } + + @Test + public void testEncodeNarrativeBlockInBundle() throws Exception { + Patient p = new Patient(); + p.addIdentifier().setSystem("foo").setValue("bar"); + p.getText().setStatus(NarrativeStatus.GENERATED); + p.getText().setDivAsString("
AAA
"); + + Bundle b = new Bundle(); + b.setTotal(123); + b.addEntry().setResource(p); + + String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(str); + assertThat(str, StringContains.containsString("
AAA
")); + + p.getText().setDivAsString("hello"); + str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(str); + // Backslashes need to be escaped because they are in a JSON value + assertThat(str, containsString(">hello<")); + + } + + @Test + public void testEncodeNonContained() { + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getNameElement().setValue("Contained Test Organization"); + + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getManagingOrganization().setResource(org); + + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\": \"Organization/65546\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\": \"Organization/65546\"")); + } + + + + + @Test + public void testEncodeResourceRef() throws DataFormatException { + + Patient patient = new Patient(); + patient.setManagingOrganization(new Reference()); + + IParser p = ourCtx.newJsonParser(); + String str = p.encodeResourceToString(patient); + assertThat(str, IsNot.not(StringContains.containsString("managingOrganization"))); + + patient.setManagingOrganization(new Reference("Organization/123")); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("\"managingOrganization\":{\"reference\":\"Organization/123\"}")); + + Organization org = new Organization(); + org.addIdentifier().setSystem("foo").setValue("bar"); + patient.setManagingOrganization(new Reference(org)); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("\"contained\":[{\"resourceType\":\"Organization\"")); + + } + + @Test + public void testEncodeSummary() throws Exception { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().setText("D")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", + "\"system\": \"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + Constants.TAG_SUBSETTED_CODE+"\",")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() throws Exception { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().setText("D")); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", + "\"system\": \"foo\",", "\"code\": \"bar\"", + "\"system\": \"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + Constants.TAG_SUBSETTED_CODE+"\",")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeUndeclaredExtensionWithAddressContent() { + IParser parser = ourCtx.newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(new Address().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse()); + Address ref = actual.getFoo(); + assertEquals("line1", ref.getLine().get(0).getValue()); + + } + + @Test + public void testEncodingNullExtension() { + Patient p = new Patient(); + Extension extension = new Extension().setUrl("http://foo#bar"); + p.getExtension().add(extension); + String str = ourCtx.newJsonParser().encodeResourceToString(p); + + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringType()); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringType("")); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + } + + @Test + public void testExtensionOnComposite() throws Exception { + + Patient patient = new Patient(); + + HumanName name = patient.addName(); + name.addFamily("Shmoe"); + HumanName given = name.addGiven("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello")); + given.getExtension().add(ext2); + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + ourLog.info(enc); + assertEquals("{\"resourceType\":\"Patient\",\"name\":[{\"extension\":[{\"url\":\"http://examples.com#givenext\",\"valueString\":\"Hello\"}],\"family\":[\"Shmoe\"],\"given\":[\"Joe\"]}]}", enc); + + IParser newJsonParser = ourCtx.newJsonParser(); + StringReader reader = new StringReader(enc); + Patient parsed = newJsonParser.parseResource(Patient.class, reader); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed)); + + assertEquals(1, parsed.getName().get(0).getExtension().size()); + Extension ext = parsed.getName().get(0).getExtension().get(0); + assertEquals("Hello", ((IPrimitiveType)ext.getValue()).getValue()); + + } + + @Test + public void testExtensionOnPrimitive() throws Exception { + + Patient patient = new Patient(); + + HumanName name = patient.addName(); + StringType family = name.addFamilyElement(); + family.setValue("Shmoe"); + + family.addExtension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello")); + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + ourLog.info(enc); + //@formatter:off + assertThat(enc, containsString(("{\n" + + " \"resourceType\":\"Patient\",\n" + + " \"name\":[\n" + + " {\n" + + " \"family\":[\n" + + " \"Shmoe\"\n" + + " ],\n" + + " \"_family\":[\n" + + " {\n" + + " \"extension\":[\n" + + " {\n" + + " \"url\":\"http://examples.com#givenext\",\n" + + " \"valueString\":\"Hello\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}").replace("\n", "").replaceAll(" +", ""))); + //@formatter:on + + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size()); + Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0); + assertEquals("Hello", ((IPrimitiveType) ext.getValue()).getValue()); + + } + + @Test + public void testMoreExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + + // Add the extension to the resource + patient.getExtension().add(ext); + // END SNIPPET: resourceExtension + + // START SNIPPET: resourceStringExtension + HumanName name = patient.addName(); + name.addFamily("Shmoe"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.getExtension().add(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.getExtension().add(given2ext); + given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); + // END SNIPPET: resourceStringExtension + + // START SNIPPET: subExtension + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.getExtension().add(parent); + + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.getExtension().add(child1); + + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.getExtension().add(child2); + // END SNIPPET: subExtension + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + //@formatter:off + assertThat(enc, containsString(("{" + + "\"resourceType\":\"Patient\"," + + " \"extension\":[" + + " {" + + " \"url\":\"http://example.com/extensions#someext\"," + + " \"valueDateTime\":\"2011-01-02T11:13:15\"" + + " }," + + " {" + + " \"url\":\"http://example.com#parent\"," + + " \"extension\":[" + + " {" + + " \"url\":\"http://example.com#child\"," + + " \"valueString\":\"value1\"" + + " }," + + " {" + + " \"url\":\"http://example.com#child\"," + + " \"valueString\":\"value1\"" + + " }" + + " ]" + + " }" + + " ]").replace(" ", ""))); + //@formatter:on + + //@formatter:off + assertThat(enc, containsString(( + " \"given\":[" + + " \"Joe\"," + + " \"Shmoe\"" + + " ]," + + " \"_given\":[" + + " {" + + " \"extension\":[" + + " {" + + " \"url\":\"http://examples.com#givenext\"," + + " \"valueString\":\"given\"" + + " }" + + " ]" + + " }," + + " {" + + " \"extension\":[" + + " {" + + " \"url\":\"http://examples.com#givenext_parent\"," + + " \"extension\":[" + + " {" + + " \"url\":\"http://examples.com#givenext_child\"," + + " \"valueString\":\"CHILD\"" + + " }" + + " ]" + + " }" + + " ]" + + " }" + + "").replace(" ", ""))); + //@formatter:on + } + + @Test + public void testNestedContainedResources() { + + Observation A = new Observation(); + A.getCode().setText("A"); + + Observation B = new Observation(); + B.getCode().setText("B"); + A.addRelated().setTarget(new Reference(B)); + + Observation C = new Observation(); + C.getCode().setText("C"); + B.addRelated().setTarget(new Reference(C)); + + String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(A); + ourLog.info(str); + + assertThat(str, stringContainsInOrder(Arrays.asList("\"text\": \"B\"", "\"text\": \"C\"", "\"text\": \"A\""))); + + // Only one (outer) contained block + int idx0 = str.indexOf("\"contained\""); + int idx1 = str.indexOf("\"contained\"", idx0 + 1); + + assertNotEquals(-1, idx0); + assertEquals(-1, idx1); + + Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, str); + assertEquals("A", obs.getCode().getTextElement().getValue()); + + Observation obsB = (Observation) obs.getRelated().get(0).getTarget().getResource(); + assertEquals("B", obsB.getCode().getTextElement().getValue()); + + Observation obsC = (Observation) obsB.getRelated().get(0).getTarget().getResource(); + assertEquals("C", obsC.getCode().getTextElement().getValue()); + + } + + @Test + public void testParseBinaryResource() { + + Binary val = ourCtx.newJsonParser().parseResource(Binary.class, "{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"); + assertEquals("foo", val.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); + + } + + @Test + public void testParseEmptyNarrative() throws Exception { + //@formatter:off + String text = "{\n" + + " \"resourceType\" : \"Patient\",\n" + + " \"extension\" : [\n" + + " {\n" + + " \"url\" : \"http://clairol.org/colour\",\n" + + " \"valueCode\" : \"B\"\n" + + " }\n" + + " ],\n" + + " \"text\" : {\n" + + " \"div\" : \"\"\n" + + " }" + + "}"; + //@formatter:on + + Patient res = (Patient) ourCtx.newJsonParser().parseResource(text); + XhtmlNode div = res.getText().getDiv(); + String value = div.getValueAsString(); + + assertNull(value); + List childNodes = div.getChildNodes(); + assertTrue(childNodes == null || childNodes.isEmpty()); + } + + @Test + public void testParseSimpleBundle() { + String bundle = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"identifier\":[{\"system\":\"idsystem\"}]}}]}"; + Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, bundle); + + assertNotNull(b.getEntry().get(0).getResource()); + Patient p = (Patient) b.getEntry().get(0).getResource(); + assertEquals("idsystem", p.getIdentifier().get(0).getSystem()); + } + + @Test + public void testParseSingleQuotes() { + ourCtx.newJsonParser().parseResource(Bundle.class, "{ \"resourceType\": \"Bundle\" }"); + ourCtx.newJsonParser().parseResource(Bundle.class, "{ 'resourceType': 'Bundle' }"); + } + + @Test + public void testSimpleParse() throws DataFormatException, IOException { + + String msg = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json")); + IParser p = ourCtx.newJsonParser(); + // ourLog.info("Reading in message: {}", msg); + Patient res = p.parseResource(Patient.class, msg); + + assertEquals(2, res.getExtension().size()); + assertEquals(1, res.getModifierExtension().size()); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + } + + @Test + public void testParsePrimitiveExtension() { + //@formatter:off + String input = "{\n" + + " \"resourceType\":\"Patient\",\n" + + " \"contact\":[\n" + + " {\n" + + " \"name\":{\n" + + " \"family\":[\n" + + " \"du\",\n" + + " \"Marché\"\n" + + " ],\n" + + " \"_family\":[\n" + + " {\n" + + " \"extension\":[\n" + + " {\n" + + " \"url\":\"http://hl7.org/fhir/Profile/iso-21090#qualifier\",\n" + + " \"valueCode\":\"VV\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " null\n" + + " ]\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + //@formatter:off + + Patient p = ourCtx.newJsonParser().parseResource(Patient.class, input); + ContactComponent contact = p.getContact().get(0); + StringType family = contact.getName().getFamily().get(0); + + assertEquals("du", family.getValueAsString()); + assertEquals(1, family.getExtension().size()); + } + + + @Test + public void testSimpleResourceEncodeWithCustomType() throws IOException, SAXException { + + String jsonString = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"), Charset.forName("UTF-8")); + MyObservationWithExtensions obs = ourCtx.newJsonParser().parseResource(MyObservationWithExtensions.class, jsonString); + + { + ContactComponent contact = obs.getContact().get(0); + StringType family = contact.getName().getFamily().get(0); + assertEquals("du", family.getValueAsString()); + assertEquals(1, family.getExtension().size()); + } + + assertEquals(0, obs.getExtension().size()); + assertEquals("aaaa", obs.getExtAtt().getContentType()); + assertEquals("str1", obs.getMoreExt().getStr1().getValue()); + assertEquals("2011-01-02", obs.getModExt().getValueAsString()); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getExtension(); + Extension undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl()); + + IParser xmlParser = ourCtx.newXmlParser(); + String encoded = xmlParser.encodeResourceToString(obs); + encoded = encoded.replaceAll("", "").replace("\n", "").replace("\r", "").replaceAll(">\\s+<", "><"); + + String xmlString = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.xml"), Charset.forName("UTF-8")); + xmlString = xmlString.replaceAll("", "").replace("\n", "").replace("\r", "").replaceAll(">\\s+<", "><"); + + ourLog.info("Expected: " + xmlString); + ourLog.info("Actual : " + encoded); + + String expected = (xmlString); + String actual = (encoded.trim()); + + XmlParserHl7OrgDstu2Test.compareXml(expected, actual); + } + + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtension(); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredAddressExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Address myFoo; + + public Address getFoo() { + return myFoo; + } + + public void setFoo(Address theFoo) { + myFoo = theFoo; + } + + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Reference myFoo; + + public Reference getFoo() { + return myFoo; + } + + public void setFoo(Reference theFoo) { + myFoo = theFoo; + } + + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + private Matcher stringContainsInOrder(List substrings) { + return Matchers.stringContainsInOrder(substrings); + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java new file mode 100644 index 00000000000..f9b030253d9 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java @@ -0,0 +1,106 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.Attachment; +import org.hl7.fhir.instance.model.BackboneElement; +import org.hl7.fhir.instance.model.DateType; +import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.StringType; +import org.hl7.fhir.instance.model.api.IBaseBackboneElement; + + +@ResourceDef(name="Patient") +public class MyObservationWithExtensions extends Patient { + + @Extension(url = "urn:patientext:att", definedLocally = false, isModifier = false) + @Child(name = "extAtt", order = 0) + private Attachment myExtAtt; + + @Extension(url = "urn:patientext:moreext", definedLocally = false, isModifier = false) + @Child(name = "moreExt", order = 1) + private MoreExt myMoreExt; + + @Extension(url = "urn:modext", definedLocally = false, isModifier = true) + @Child(name = "modExt", order = 2) + private DateType myModExt; + + public Attachment getExtAtt() { + return myExtAtt; + } + + public MoreExt getMoreExt() { + return myMoreExt; + } + + public void setMoreExt(MoreExt theMoreExt) { + myMoreExt = theMoreExt; + } + + public DateType getModExt() { + return myModExt; + } + + public void setModExt(DateType theModExt) { + myModExt = theModExt; + } + + public void setExtAtt(Attachment theExtAtt) { + myExtAtt = theExtAtt; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(myExtAtt, myModExt, myMoreExt); + } + + /** + * Block class for child element: Observation.referenceRange (Provides guide for interpretation) + * + *

+ * Definition: Guidance on how to interpret the value by comparison to a normal or recommended range + *

+ */ + @Block(name = "Observation.someExtensions") + public static class MoreExt extends BackboneElement implements IBaseBackboneElement { + + @Extension(url = "urn:patientext:moreext:1", definedLocally = false, isModifier = false) + @Child(name = "str1", order = 0) + private StringType myStr1; + + @Extension(url = "urn:patientext:moreext:2", definedLocally = false, isModifier = false) + @Child(name = "str2", order = 1) + private StringType myStr2; + + public StringType getStr1() { + return myStr1; + } + + public void setStr1(StringType theStr1) { + myStr1 = theStr1; + } + + public StringType getStr2() { + return myStr2; + } + + public void setStr2(StringType theStr2) { + myStr2 = theStr2; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(myStr1, myStr2); + } + + @Override + public BackboneElement copy() { + throw new UnsupportedOperationException(); + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java new file mode 100644 index 00000000000..d0d6820a724 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java @@ -0,0 +1,11 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.instance.model.Organization; + +@ResourceDef() +public class MyOrganizationDstu2 extends Organization { + + private static final long serialVersionUID = 1L; + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java new file mode 100644 index 00000000000..c76e2bbf8fb --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java @@ -0,0 +1,64 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import java.util.ArrayList; +import java.util.List; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.instance.model.DateTimeType; +import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.Reference; +import org.hl7.fhir.instance.model.StringType; + + +@ResourceDef() +public class MyPatientHl7Org extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name="petName") + @Extension(url="http://example.com/dontuse#petname", definedLocally=false, isModifier=false) + @Description(shortDefinition="The name of the patient's favourite pet") + private StringType myPetName; + + @Child(name="importantDates", max=Child.MAX_UNLIMITED) + @Extension(url="http://example.com/dontuse#importantDates", definedLocally=false, isModifier=true) + @Description(shortDefinition="Some dates of note for the patient") + private List myImportantDates; + + @Child(name="managingOrganization", order=Child.REPLACE_PARENT, min=0, max=1, type={ + MyOrganizationDstu2.class }) + @Description( + shortDefinition="Organization that is the custodian of the patient record", + formalDefinition="Organization that is the custodian of the patient record" + ) + private Reference myManagingOrganization; + + + @Override + public boolean isEmpty() { + return super.isEmpty() && myPetName.isEmpty(); + } + + + public List getImportantDates() { + if (myImportantDates==null) { + myImportantDates = new ArrayList(); + } + return myImportantDates; + } + + public StringType getPetName() { + return myPetName; + } + + public void setImportantDates(List theImportantDates) { + myImportantDates = theImportantDates; + } + + public void setPetName(StringType thePetName) { + myPetName = thePetName; + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java new file mode 100644 index 00000000000..2f62b1b27fe --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java @@ -0,0 +1,26 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.instance.model.Address.AddressUse; +import org.hl7.fhir.instance.model.Enumeration; +import org.hl7.fhir.instance.model.Patient; + +@ResourceDef(name = "Patient") +public class MyPatientWithOneDeclaredEnumerationExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Enumeration myFoo; + + public Enumeration getFoo() { + return myFoo; + } + + public void setFoo(Enumeration theFoo) { + myFoo = theFoo; + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java new file mode 100644 index 00000000000..5f8241084cf --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java @@ -0,0 +1,206 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import java.util.List; +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.instance.model.BackboneElement; +import org.hl7.fhir.instance.model.CodeableConcept; +import org.hl7.fhir.instance.model.DateType; +import org.hl7.fhir.instance.model.DomainResource; +import org.hl7.fhir.instance.model.Identifier; +import org.hl7.fhir.instance.model.ResourceType; +import org.hl7.fhir.instance.model.StringType; + +@ResourceDef(name = "ResourceWithExtensionsA", id="0001") +public class ResourceWithExtensionsA extends DomainResource { + + /* + * NB: several unit tests depend on the structure here + * so check the unit tests immediately after any changes + */ + + + private static final long serialVersionUID = 1L; + + @Child(name = "foo1", type = StringType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED) + @Extension(url = "http://foo/#f1", definedLocally=true, isModifier=false) + private List myFoo1; + + @Child(name = "foo2", type = StringType.class, order = 1, min = 0, max = 1) + @Extension(url = "http://foo/#f2", definedLocally=true, isModifier=true) + private StringType myFoo2; + + @Child(name = "bar1", type = Bar1.class, order = 2, min = 1, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b1", definedLocally=true, isModifier=false) + private List myBar1; + + @Child(name = "bar2", type = Bar1.class, order = 3, min = 1, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b2", definedLocally=true, isModifier=false) + private Bar1 myBar2; + + @Child(name="baz", type = CodeableConcept.class, order = 4) + @Extension(url= "http://baz/#baz", definedLocally=true, isModifier=false) + @Description(shortDefinition = "Contains a codeable concept") + private CodeableConcept myBaz; + + @Child(name = "identifier", type = Identifier.class, order = 0, min = 0, max = Child.MAX_UNLIMITED) + private List myIdentifier; + + public List getBar1() { + return myBar1; + } + + public Bar1 getBar2() { + return myBar2; + } + + public List getFoo1() { + return myFoo1; + } + + public StringType getFoo2() { + return myFoo2; + } + + public CodeableConcept getBaz() { return myBaz; } + + public List getIdentifier() { + return myIdentifier; + } + + public void setBar1(List theBar1) { + myBar1 = theBar1; + } + + public void setBar2(Bar1 theBar2) { + myBar2 = theBar2; + } + + public void setFoo1(List theFoo1) { + myFoo1 = theFoo1; + } + + public void setFoo2(StringType theFoo2) { + myFoo2 = theFoo2; + } + + public void setBaz(CodeableConcept myBaz) { this.myBaz = myBaz; } + + public void setIdentifier(List theValue) { + myIdentifier = theValue; + } + + @Block(name = "Bar1") + public static class Bar1 extends BackboneElement { + + public Bar1() { + super(); + } + + @Child(name = "bar11", type = DateType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b1/1", definedLocally=true, isModifier=false) + private List myBar11; + + @Child(name = "bar12", type = DateType.class, order = 1, min = 0, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b1/2", definedLocally=true, isModifier=false) + private List myBar12; + + @Override + public boolean isEmpty() { + return false; // not implemented + } + + public List getBar11() { + return myBar11; + } + + public List getBar12() { + return myBar12; + } + + public void setBar11(List theBar11) { + myBar11 = theBar11; + } + + public void setBar12(List theBar12) { + myBar12 = theBar12; + } + + + @Override + public BackboneElement copy() { + // TODO Auto-generated method stub + return null; + } + + + + } + + @Block(name = "Bar2") + public static class Bar2 extends BackboneElement { + + @Child(name = "bar121", type = DateType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b1/2/1", definedLocally=true, isModifier=false) + private List myBar121; + + @Child(name = "bar122", type = DateType.class, order = 1, min = 0, max = Child.MAX_UNLIMITED) + @Extension(url = "http://bar/#b1/2/2", definedLocally=true, isModifier=false) + private List myBar122; + + @Override + public boolean isEmpty() { + return false; // not implemented + } + + + public List getBar121() { + return myBar121; + } + + public List getBar122() { + return myBar122; + } + + public void setBar121(List theBar121) { + myBar121 = theBar121; + } + + public void setBar122(List theBar122) { + myBar122 = theBar122; + } + + @Override + public BackboneElement copy() { + // TODO Auto-generated method stub + return null; + } + + + + } + + @Override + public boolean isEmpty() { + return false; // not implemented + } + + + @Override + public DomainResource copy() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ResourceType getResourceType() { + // TODO Auto-generated method stub + return null; + } + + + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java new file mode 100644 index 00000000000..ea8c81ed73b --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java @@ -0,0 +1,1521 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.api.AddProfileTagEnum; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.narrative.INarrativeGenerator; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.Constants; +import org.apache.commons.io.IOUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.IsNot; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.hl7.fhir.instance.model.Address; +import org.hl7.fhir.instance.model.CodeableConcept; +import org.hl7.fhir.instance.model.Composition; +import org.hl7.fhir.instance.model.DiagnosticReport; +import org.hl7.fhir.instance.model.EnumFactory; +import org.hl7.fhir.instance.model.Enumeration; +import org.hl7.fhir.instance.model.InstantType; +import org.hl7.fhir.instance.model.Narrative; +import org.hl7.fhir.instance.model.Organization; +import org.hl7.fhir.instance.model.Patient; +import org.hl7.fhir.instance.model.PrimitiveType; +import org.hl7.fhir.instance.model.Reference; +import org.hl7.fhir.instance.model.Resource; +import org.hl7.fhir.instance.model.Specimen; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.INarrative; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.xml.sax.SAXException; +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.builder.Input; +import org.xmlunit.diff.ComparisonControllers; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.Diff; +import org.xmlunit.diff.ElementSelectors; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class XmlParserHl7OrgDstu2Test { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserHl7OrgDstu2Test.class); + private FhirContext ourCtx = FhirContext.forDstu2Hl7Org(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_HL7ORG_DSTU2.option(), + mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlEnabled() { + String tmp = ""; + org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertEquals("http://lalaland.org", o1Id.getBaseUrl()); + assertEquals("patient", o1Id.getResourceType()); + assertEquals("pat1", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + String tmp = ""; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + String tmp = ""; + org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } + + @Test + public void testComposition() { + + Composition comp = new Composition(); + comp.setId("1"); + + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + + // comp. + + } + + @Test + public void testContainedResourceInExtensionUndeclared() { + org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient(); + p.addName().addFamily("PATIENT"); + + Organization o = new Organization(); + o.setName("ORG"); + p.addExtension().setUrl("urn:foo").setValue(new org.hl7.fhir.instance.model.Reference(o)); + + String str = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(str); + + p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, str); + assertEquals("PATIENT", p.getName().get(0).getFamily().get(0).getValue()); + + List exts = p.getExtension(); + assertEquals(1, exts.size()); + org.hl7.fhir.instance.model.Reference rr = (org.hl7.fhir.instance.model.Reference) exts.get(0).getValue(); + o = (Organization) rr.getResource(); + assertEquals("ORG", o.getName()); + } + + @Test + public void testDuplicateContainedResources() { + + org.hl7.fhir.instance.model.Observation resA = new org.hl7.fhir.instance.model.Observation(); + resA.getCode().setText("A"); + + org.hl7.fhir.instance.model.Observation resB = new org.hl7.fhir.instance.model.Observation(); + resB.getCode().setText("B"); + resB.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(resA)); + resB.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(resA)); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resB); + ourLog.info(encoded); + + assertThat(encoded, + stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder( + Arrays.asList("", "", "")))); + + } + + @Test + public void testEncodeAndParseContained() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + + // Create a bundle with just the patient resource + org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle(); + b.addEntry().setResource(patient); + + // Encode the bundle + encoded = xmlParser.encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + // Re-parse the bundle + patient = (org.hl7.fhir.instance.model.Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReferenceElement().getValue()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getIdElement().getValue()); + assertEquals("Contained Test Organization", org.getName()); + + // And re-encode a second time + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", + "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", + "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared and a manually set + // local ID + patient.getContained().clear(); + patient.getManagingOrganization().setReference(null); + patient.getManagingOrganization().getResource().setId(("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", + "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + + } + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addIdentifier().setUse(org.hl7.fhir.instance.model.Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + org.hl7.fhir.instance.model.Extension ext = new org.hl7.fhir.instance.model.Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new org.hl7.fhir.instance.model.DateTimeType("2011-01-02T11:13:15")); + patient.getExtension().add(ext); + + org.hl7.fhir.instance.model.Extension parent = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#parent"); + patient.getExtension().add(parent); + org.hl7.fhir.instance.model.Extension child1 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1")); + parent.getExtension().add(child1); + org.hl7.fhir.instance.model.Extension child2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value2")); + parent.getExtension().add(child2); + + org.hl7.fhir.instance.model.Extension modExt = new org.hl7.fhir.instance.model.Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new org.hl7.fhir.instance.model.DateType("1995-01-02")); + patient.getModifierExtension().add(modExt); + + org.hl7.fhir.instance.model.HumanName name = patient.addName(); + name.addFamily("Blah"); + org.hl7.fhir.instance.model.StringType given = name.addGivenElement(); + given.setValue("Joe"); + org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("given")); + given.getExtension().add(ext2); + + org.hl7.fhir.instance.model.StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + org.hl7.fhir.instance.model.Extension given2ext = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext_parent"); + given2.getExtension().add(given2ext); + given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new org.hl7.fhir.instance.model.StringType("CHILD")); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + + /* + * Now parse this back + */ + + org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((org.hl7.fhir.instance.model.DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((org.hl7.fhir.instance.model.StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((org.hl7.fhir.instance.model.StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((org.hl7.fhir.instance.model.DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((org.hl7.fhir.instance.model.StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + org.hl7.fhir.instance.model.Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((org.hl7.fhir.instance.model.StringType) given2ext2.getValue()).getValue()); + + } + + @Test + public void testEncodeBinaryResource() { + + org.hl7.fhir.instance.model.Binary patient = new org.hl7.fhir.instance.model.Binary(); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + assertEquals( + "", + val); + + } + + @Test + public void testEncodeBinaryWithNoContentType() { + org.hl7.fhir.instance.model.Binary b = new org.hl7.fhir.instance.model.Binary(); + b.setContent(new byte[] { 1, 2, 3, 4 }); + + String output = ourCtx.newXmlParser().encodeResourceToString(b); + ourLog.info(output); + + assertEquals("", output); + } + + @Test + public void testEncodeBoundCode() { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + + patient.getGenderElement().setValue(org.hl7.fhir.instance.model.Enumerations.AdministrativeGender.MALE); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + ourLog.info(val); + + assertThat(val, containsString("home")); + assertThat(val, containsString("male")); + } + + @Test + public void testEncodeBundle() throws InterruptedException { + org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle(); + b.getMeta().addTag().setSystem("http://hl7.org/fhir/tag").setCode("http://hl7.org/fhir/tag/message") + .setDisplay("Message"); + + InstantType pub = InstantType.withCurrentTime(); + b.getMeta().setLastUpdatedElement(pub); + + org.hl7.fhir.instance.model.Patient p1 = new org.hl7.fhir.instance.model.Patient(); + p1.addName().addFamily("Family1"); + org.hl7.fhir.instance.model.Bundle.BundleEntryComponent entry = b.addEntry(); + p1.getIdElement().setValue("1"); + entry.setResource(p1); + + org.hl7.fhir.instance.model.Patient p2 = new org.hl7.fhir.instance.model.Patient(); + p2.addName().addFamily("Family2"); + entry = b.addEntry(); + p2.getIdElement().setValue("2"); + entry.setResource(p2); + + String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(bundleString); + + // @formatter:on + String[] strings = { "", + "", "", + "", "", "" }; + // @formatter:off + + assertThat(bundleString, stringContainsInOrder(strings)); + } + + @Test + public void testEncodeBundleCategory() { + + org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle(); + org.hl7.fhir.instance.model.Bundle.BundleEntryComponent e = b.addEntry(); + e.setResource(new org.hl7.fhir.instance.model.Patient()); + e.getResource().getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("label"); + + String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(val); + + // @formatter:off + assertThat(val, stringContainsInOrder("", "", "", + "", "")); + // @formatter:on + + b = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Bundle.class, val); + assertEquals(1, b.getEntry().size()); + assertEquals(1, b.getEntry().get(0).getResource().getMeta().getTag().size()); + assertEquals("scheme", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getSystem()); + assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode()); + assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay()); + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + private Matcher stringContainsInOrder(List substrings) { + return Matchers.stringContainsInOrder(substrings); + } + + @Test + public void testEncodeContainedAndIncludedResources() { + + DiagnosticReport rpt = new DiagnosticReport(); + rpt.getCode().setText("Report"); + + Specimen spm = new Specimen(); + spm.addIdentifier().setValue("Report1ContainedSpecimen1"); + rpt.addSpecimen().setResource(spm); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + + } + + @Test + public void testEncodeContainedResources() throws Exception { + + DiagnosticReport rpt = new DiagnosticReport(); + Specimen spm = new Specimen(); + spm.addIdentifier().setSystem("urn").setValue("123"); + rpt.getText().setDivAsString("AAA"); + rpt.addSpecimen().setResource(spm); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + assertThat(str, StringContains.containsString("
AAA
")); + assertThat(str, StringContains.containsString("reference value=\"#")); + + int idx = str.indexOf("reference value=\"#") + "reference value=\"#".length(); + int idx2 = str.indexOf('"', idx + 1); + String id = str.substring(idx, idx2); + assertThat(str, stringContainsInOrder("", "")); + assertThat(str, IsNot.not(StringContains.containsString(""))); + + } + + @Test + public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + org.getText().setDivAsString("
FOOBAR
"); + + // Create a patient + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getText().setDivAsString("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("", + "
BARFOO
", "", "", "", "
")); + + MyPatientWithOneDeclaredAddressExtension actual = parser + .parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + Address ref = actual.getFoo(); + assertEquals("line1", ref.getLine().get(0).getValue()); + + } + + @Test + public void testEncodeDeclaredExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension(); + patient.addAddress().setUse(Address.AddressUse.HOME); + patient.setFoo(new org.hl7.fhir.instance.model.Reference("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString( + "")); + + MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + org.hl7.fhir.instance.model.Reference ref = actual.getFoo(); + assertEquals("Organization/123", ref.getReferenceElement().getValue()); + + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag() { + org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient(); + p.getMeta().addTag(); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, not(containsString("tag"))); + + // With tag + + p = new org.hl7.fhir.instance.model.Patient(); + p.getMeta().addTag().setSystem("sys").setCode("code"); + + encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, (containsString("tag"))); + } + + @Test + public void testEncodeEscapedChars() { + + org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient(); + p.addName().addFamily("and <>&ü"); + + String enc = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(enc); + + p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, enc); + assertEquals("and <>&ü", p.getName().get(0).getFamily().get(0).getValue()); + + p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, + ""); + assertEquals("quot \"", p.getName().get(0).getFamily().get(0).getValue()); + + } + + @Test + public void testEncodeEscapedExtendedChars() { + org.hl7.fhir.instance.model.Patient p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, + ""); + assertEquals("uuml ü", p.getName().get(0).getFamily().get(0).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + org.hl7.fhir.instance.model.Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new org.hl7.fhir.instance.model.StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + // @formatter:off + assertThat(output, stringContainsInOrder("", "", "", + "", "", "")); + assertThat(output, not(stringContainsInOrder(""))); + // @formatter:on + + obs = parser.parseResource(org.hl7.fhir.instance.model.Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((org.hl7.fhir.instance.model.StringType) obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + org.hl7.fhir.instance.model.Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + org.hl7.fhir.instance.model.Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new org.hl7.fhir.instance.model.StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + // @formatter:off + assertThat(output, + stringContainsInOrder("", "", "", + "", "", + "", "")); + assertThat(output, not(stringContainsInOrder(""))); + // @formatter:on + + obs = parser.parseResource(org.hl7.fhir.instance.model.Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((org.hl7.fhir.instance.model.StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + + /** + * See #327 + */ + @Test + public void testEncodeExtensionWithContainedResource() { + + TestPatientFor327 patient = new TestPatientFor327(); + patient.setBirthDateElement(new org.hl7.fhir.instance.model.DateType("2016-04-14")); + + List conditions = new ArrayList(); + org.hl7.fhir.instance.model.Condition condition = new org.hl7.fhir.instance.model.Condition(); + condition.addBodySite().setText("BODY SITE"); + conditions.add(new org.hl7.fhir.instance.model.Reference(condition)); + patient.setCondition(conditions); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + )); + //@formatter:on + } + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(new org.hl7.fhir.instance.model.Reference().setReference("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString( + "")); + + org.hl7.fhir.instance.model.Patient actual = parser.parseResource(org.hl7.fhir.instance.model.Patient.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + List ext = actual.getExtension(); + assertEquals(1, ext.size()); + org.hl7.fhir.instance.model.Reference ref = (org.hl7.fhir.instance.model.Reference) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReferenceElement().getValue()); + + } + + @Test + public void testEncodeInvalidChildGoodException() { + org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation(); + obs.setValue(new org.hl7.fhir.instance.model.DecimalType(112.22)); + + IParser p = ourCtx.newJsonParser(); + + try { + p.encodeResourceToString(obs); + } catch (DataFormatException e) { + assertThat(e.getMessage(), StringContains.containsString("DecimalType")); + } + } + + @Test + public void testEncodeNarrativeSuppressed() throws Exception { + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSuppressNarratives(true) + .encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", + "", "")); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeNonContained() { + // Create an organization + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getManagingOrganization().setResource(org); + + // Create a list containing both resources. In a server method, you might + // just + // return this list, but here we will create a bundle to encode. + List resources = new ArrayList(); + resources.add(org); + resources.add(patient); + + // Create a bundle with both + org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle(); + b.addEntry().setResource(org); + b.addEntry().setResource(patient); + + // Encode the buntdle + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, stringContainsInOrder("", "")); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder("", "
")); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, containsString("")); + + } + + @Test + public void testEncodePrettyPrint() throws Exception { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.getText().setDivAsString("
\n hello
\n  LINE1\n  LINE2
\n\n\n\n
"); + patient.addName().addFamily("Family").addGiven("Given"); + + // @formatter:off + String encoded = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(patient); + ourLog.info(encoded); + /* + * Note at least one space is placed where any whitespace was, as it is hard + * to tell what whitespace had no purpose + */ + String expected = "
" + + " hello " + "
\n  LINE1\n  LINE2
" + + "
"; + assertEquals(expected, encoded); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + expected = "\n" + " \n" + + "
\n" + " hello \n" + + "
\n  LINE1\n  LINE2
\n" + "
\n" + "
\n" + "
\n" + + " \n" + " \n" + " \n" + " \n" + + "
"; + // @formatter:on + + // Whitespace should be preserved and not reformatted in narrative blocks + assertEquals(expected, encoded); + + } + + @Test + public void testEncodeResourceRef() throws DataFormatException { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setManagingOrganization(new org.hl7.fhir.instance.model.Reference()); + + IParser p = ourCtx.newXmlParser(); + String str = p.encodeResourceToString(patient); + assertThat(str, IsNot.not(StringContains.containsString("managingOrganization"))); + + org.hl7.fhir.instance.model.Reference ref = new org.hl7.fhir.instance.model.Reference(); + ref.setReference("Organization/123"); + ref.setDisplay("DISPLAY!"); + patient.setManagingOrganization(ref); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString( + "")); + + Organization org = new Organization(); + org.addIdentifier().setSystem("foo").setValue("bar"); + patient.setManagingOrganization(new org.hl7.fhir.instance.model.Reference(org)); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("THE DIV"); + patient.addName().addFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", + "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() throws Exception { + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().addFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().setText("D")); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", "", "")); + assertThat(encoded, stringContainsInOrder("", "", + "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeUndeclaredExtensionWithAddressContent() { + IParser parser = ourCtx.newXmlParser(); + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(new Address().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains + .containsString("")); + + MyPatientWithOneDeclaredAddressExtension actual = parser + .parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + Address ref = actual.getFoo(); + assertEquals("line1", ref.getLine().get(0).getValue()); + + } + + @Test + public void testEncodeUndeclaredExtensionWithEnumerationContent() { + IParser parser = ourCtx.newXmlParser(); + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + EnumFactory fact = new Address.AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(Address.AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, + StringContains.containsString("")); + + MyPatientWithOneDeclaredEnumerationExtension actual = parser + .parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + + @Test + public void testEncodingNullExtension() { + org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient(); + org.hl7.fhir.instance.model.Extension extension = new org.hl7.fhir.instance.model.Extension().setUrl("http://foo#bar"); + p.getExtension().add(extension); + String str = ourCtx.newXmlParser().encodeResourceToString(p); + + assertEquals("", str); + + extension.setValue(new org.hl7.fhir.instance.model.StringType()); + + str = ourCtx.newXmlParser().encodeResourceToString(p); + assertEquals("", str); + + extension.setValue(new org.hl7.fhir.instance.model.StringType("")); + + str = ourCtx.newXmlParser().encodeResourceToString(p); + assertEquals("", str); + + } + + @Test + public void testExtensionOnComposite() throws Exception { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + + org.hl7.fhir.instance.model.HumanName name = patient.addName(); + name.addFamily("Shmoe"); + org.hl7.fhir.instance.model.HumanName given = name.addGiven("Joe"); + org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("Hello")); + given.getExtension().add(ext2); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString( + "")); + + org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getName().get(0).getExtension().size()); + org.hl7.fhir.instance.model.Extension ext = parsed.getName().get(0).getExtension().get(0); + assertEquals("Hello", ((IPrimitiveType) ext.getValue()).getValue()); + + } + + @Test + public void testExtensionOnPrimitive() throws Exception { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + + org.hl7.fhir.instance.model.HumanName name = patient.addName(); + org.hl7.fhir.instance.model.StringType family = name.addFamilyElement(); + family.setValue("Shmoe"); + + org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("Hello")); + family.getExtension().add(ext2); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString( + "")); + + org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size()); + org.hl7.fhir.instance.model.Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0); + assertEquals("Hello", ((IPrimitiveType) ext.getValue()).getValue()); + + } + + @Test + public void testExtensions() throws DataFormatException { + + MyPatientHl7Org patient = new MyPatientHl7Org(); + patient.setPetName(new org.hl7.fhir.instance.model.StringType("Fido")); + patient.getImportantDates().add(new org.hl7.fhir.instance.model.DateTimeType("2010-01-02")); + patient.getImportantDates().add(new org.hl7.fhir.instance.model.DateTimeType("2014-01-26T11:11:11")); + + patient.addName().addFamily("Smith"); + + IParser p = ourCtx.newXmlParser(); + String str = p.encodeResourceToString(patient); + + ourLog.info(str); + + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString( + "")); + assertThat(str, StringContains.containsString( + "")); + assertThat(str, StringContains.containsString( + "")); + assertThat(str, StringContains.containsString("")); + + } + + @Test + public void testLoadAndAncodeMessage() throws Exception { + + // @formatter:off + String msg = "" + + "
John Cardinal: 444333333
" + + "" + + "" + + "" + + "" + + "" + + "" + "
" + + "
"; + // @formatter:on + + org.hl7.fhir.instance.model.Patient patient = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, msg); + + assertEquals(Narrative.NarrativeStatus.GENERATED, patient.getText().getStatus()); + assertThat(patient.getText().getDiv().getValueAsString(), containsString(">John Cardinal: 444333333 <")); + assertEquals("PRP1660", patient.getIdentifier().get(0).getValue()); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(patient); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient)); + + ourLog.info("Expected: {}", msg); + ourLog.info("Actual: {}", encoded); + + compareXml(msg, encoded); + + } + + @Test + public void testLoadAndEncodeDeclaredExtensions() + throws ConfigurationException, DataFormatException, SAXException, IOException { + IParser p = ourCtx.newXmlParser(); + ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER); + + // @formatter:off + String msg = "\n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + " \n" + " \n" + + ""; + // @formatter:on + + ResourceWithExtensionsA resource = (ResourceWithExtensionsA) p.parseResource(ResourceWithExtensionsA.class, msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getValue()); + assertEquals("Foo1Value", resource.getFoo1().get(0).getValue()); + assertEquals("Foo1Value2", resource.getFoo1().get(1).getValue()); + assertEquals("Foo2Value1", resource.getFoo2().getValue()); + assertEquals("2013-01-01", resource.getBar1().get(0).getBar11().get(0).getValueAsString()); + assertEquals("2013-01-02", resource.getBar1().get(0).getBar12().get(0).getBar121().get(0).getValueAsString()); + assertEquals("2013-01-12", resource.getBar1().get(0).getBar12().get(0).getBar121().get(1).getValueAsString()); + assertEquals("2013-01-03", resource.getBar1().get(0).getBar12().get(0).getBar122().get(0).getValueAsString()); + + String encoded = p.setPrettyPrint(true).encodeResourceToString(resource); + ourLog.info(encoded); + + compareXml(msg, encoded); + } + + @Test + public void testLoadAndEncodeUndeclaredExtensions() + throws ConfigurationException, DataFormatException, SAXException, IOException { + IParser p = ourCtx.newXmlParser(); + + // @formatter:off + String msg = "\n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + " \n" + + " \n" + " \n" + " \n" + " \n" + + ""; + // @formatter:on + + org.hl7.fhir.instance.model.Patient resource = (org.hl7.fhir.instance.model.Patient) p.parseResource(msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getValue()); + assertEquals("Foo1Value", ((IPrimitiveType) resource.getExtension().get(0).getValue()).getValueAsString()); + assertEquals("Foo1Value2", ((IPrimitiveType) resource.getExtension().get(1).getValue()).getValueAsString()); + assertEquals("Foo2Value1", + ((IPrimitiveType) resource.getModifierExtension().get(0).getValue()).getValueAsString()); + + assertEquals("2013-01-01", + ((IPrimitiveType) resource.getExtension().get(2).getExtension().get(0).getValue()).getValueAsString()); + assertEquals("2013-01-02", + ((IPrimitiveType) resource.getExtension().get(2).getExtension().get(1).getExtension().get(0).getValue()) + .getValueAsString()); + + String encoded = p.encodeResourceToString(resource); + ourLog.info(encoded); + + compareXml(msg, encoded); + } + + @Test + public void testMoreExtensions() throws Exception { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addIdentifier().setUse(org.hl7.fhir.instance.model.Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + org.hl7.fhir.instance.model.Extension ext = new org.hl7.fhir.instance.model.Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new org.hl7.fhir.instance.model.DateTimeType("2011-01-02T11:13:15")); + + // Add the extension to the resource + patient.getExtension().add(ext); + // END SNIPPET: resourceExtension + + // START SNIPPET: resourceStringExtension + org.hl7.fhir.instance.model.HumanName name = patient.addName(); + name.addFamily("Shmoe"); + org.hl7.fhir.instance.model.StringType given = name.addGivenElement(); + given.setValue("Joe"); + org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("given")); + given.getExtension().add(ext2); + + org.hl7.fhir.instance.model.StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + org.hl7.fhir.instance.model.Extension given2ext = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext_parent"); + given2.getExtension().add(given2ext); + given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new org.hl7.fhir.instance.model.StringType("CHILD")); + // END SNIPPET: resourceStringExtension + + // START SNIPPET: subExtension + org.hl7.fhir.instance.model.Extension parent = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#parent"); + patient.getExtension().add(parent); + + org.hl7.fhir.instance.model.Extension child1 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1")); + parent.getExtension().add(child1); + + org.hl7.fhir.instance.model.Extension child2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1")); + parent.getExtension().add(child2); + // END SNIPPET: subExtension + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString( + "")); + } + + // Narrative generation not currently supported for HL7org structures + public void testNarrativeGeneration() throws DataFormatException, IOException { + + org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient(); + patient.addName().addFamily("Smith"); + Organization org = new Organization(); + patient.getManagingOrganization().setResource(org); + + INarrativeGenerator gen = new INarrativeGenerator() { + + @Override + public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) { + try { + theNarrative.setDivAsString("
help
"); + } catch (Exception e) { + throw new Error(e); + } + theNarrative.setStatusAsString("generated"); + } + + }; + + FhirContext context = ourCtx; + context.setNarrativeGenerator(gen); + IParser p = context.newXmlParser(); + String str = p.encodeResourceToString(patient); + + ourLog.info(str); + + assertThat(str, StringContains.containsString(",\"text\":{\"status\":\"generated\",\"div\":\"
help
\"},")); + } + + @Test + public void testNestedContainedResources() { + + org.hl7.fhir.instance.model.Observation A = new org.hl7.fhir.instance.model.Observation(); + A.getCode().setText("A"); + + org.hl7.fhir.instance.model.Observation B = new org.hl7.fhir.instance.model.Observation(); + B.getCode().setText("B"); + A.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(B)); + + org.hl7.fhir.instance.model.Observation C = new org.hl7.fhir.instance.model.Observation(); + C.getCode().setText("C"); + B.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(C)); + + String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A); + ourLog.info(str); + + assertThat(str, + stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(str, stringContainsInOrder(Arrays.asList("", "", "", ""))); + + org.hl7.fhir.instance.model.Observation obs = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Observation.class, str); + assertEquals("A", obs.getCode().getText()); + + org.hl7.fhir.instance.model.Observation obsB = (org.hl7.fhir.instance.model.Observation) obs.getRelated().get(0).getTarget().getResource(); + assertEquals("B", obsB.getCode().getText()); + + org.hl7.fhir.instance.model.Observation obsC = (org.hl7.fhir.instance.model.Observation) obsB.getRelated().get(0).getTarget().getResource(); + assertEquals("C", obsC.getCode().getText()); + + } + + @Test + public void testParseBinaryResource() { + + org.hl7.fhir.instance.model.Binary val = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Binary.class, + ""); + assertEquals("foo", val.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); + + } + + /** + * Thanks to Alexander Kley! + */ + @Test + public void testParseContainedBinaryResource() throws Exception { + byte[] bin = new byte[] { 0, 1, 2, 3, 4 }; + final org.hl7.fhir.instance.model.Binary binary = new org.hl7.fhir.instance.model.Binary(); + binary.setContentType("PatientConsent").setContent(bin); + // binary.setId(UUID.randomUUID().toString()); + + org.hl7.fhir.instance.model.DocumentManifest manifest = new org.hl7.fhir.instance.model.DocumentManifest(); + // manifest.setId(UUID.randomUUID().toString()); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setSystem("mySystem").setCode("PatientDocument"); + manifest.setType(cc); + manifest.setMasterIdentifier(new org.hl7.fhir.instance.model.Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString())); + manifest.addContent().setP(new org.hl7.fhir.instance.model.Reference(binary)); + manifest.setStatus(org.hl7.fhir.instance.model.Enumerations.DocumentReferenceStatus.CURRENT); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest); + ourLog.info(encoded); + assertThat(encoded, + StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", ""))); + + org.hl7.fhir.instance.model.DocumentManifest actual = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.DocumentManifest.class, encoded); + assertEquals(1, actual.getContained().size()); + assertEquals(1, actual.getContent().size()); + + /* + * If this fails, the child named "p" in DocumentManifest is missing the + * type IBaseResource in its definition... This isn't being auto added right + * now, need to figure out why + * + * @Child(name = "p", type = {Attachment.class, IBaseResource.class}, + * order=1, min=1, max=1, modifier=false, summary=true) + */ + assertNotNull(actual.getContent().get(0).getPReference().getResource()); + + } + + @Test + public void testParseEncodeNarrative() { + + String input = "
Donald null DUCK
Identifier7000135
Address10 Duxon Street
VICTORIA BC Can
Date of birth01 June 1980
"; + IBaseResource res = ourCtx.newXmlParser().parseResource(input); + + String output = ourCtx.newXmlParser().encodeResourceToString(res); + + // Should occur exactly twice (once for the resource, once for the DIV + assertThat(output, (StringContainsInOrder.stringContainsInOrder(Arrays.asList("Patient xmlns", "div xmlns")))); + assertThat(output, not(StringContainsInOrder.stringContainsInOrder(Arrays.asList("b xmlns")))); + + output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + + // Should occur exactly twice (once for the resource, once for the DIV + assertThat(output, (StringContainsInOrder.stringContainsInOrder(Arrays.asList("Patient xmlns", "div xmlns")))); + assertThat(output, not(StringContainsInOrder.stringContainsInOrder(Arrays.asList("b xmlns")))); + + } + + @Test + public void testParseLanguage() { + String input = "
海生
IdentifierURNo
Address99 Houston Road
BENTLEIGH Victoria
Date of birth01 January 1997
"; + org.hl7.fhir.instance.model.Patient pt = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, input); + + assertEquals("zh-CN", pt.getLanguage()); + } + + @Test + public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException { + IParser p = ourCtx.newXmlParser(); + + // @formatter:off + String msg = "" + "\n" + + " \n" + " \n" + " \n" + ""; + // @formatter:on + + org.hl7.fhir.instance.model.Patient resource = (org.hl7.fhir.instance.model.Patient) p.parseResource(msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getValue()); + } + + @Test + public void testReEncode() throws SAXException, IOException { + + // @formatter:off + String msg = "" + + "" + + ""; + // @formatter:on + + org.hl7.fhir.instance.model.Patient patient1 = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, msg); + String encoded1 = ourCtx.newXmlParser().encodeResourceToString(patient1); + + ourLog.info("Expected: {}", msg); + ourLog.info("Actual: {}", encoded1); + + compareXml(msg, encoded1); + } + + @Test + public void testSimpleResourceEncode() throws IOException, SAXException { + + String xmlString = IOUtils.toString( + XmlParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"), + Charset.forName("UTF-8")); + org.hl7.fhir.instance.model.Patient obs = ourCtx.newJsonParser().parseResource(org.hl7.fhir.instance.model.Patient.class, xmlString); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getExtension(); + org.hl7.fhir.instance.model.Extension undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl()); + + ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out)); + + IParser jsonParser = ourCtx.newXmlParser(); + String encoded = jsonParser.encodeResourceToString(obs); + ourLog.info(encoded); + + String jsonString = IOUtils.toString( + XmlParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.xml"), + Charset.forName("UTF-8")); + + String expected = (jsonString); + String actual = (encoded.trim()); + + compareXml(expected, actual); + } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + org.hl7.fhir.instance.model.Patient fhirPat = new org.hl7.fhir.instance.model.Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new org.hl7.fhir.instance.model.Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(org.hl7.fhir.instance.model.Patient.class, output); + + List extlst = fhirPat.getExtension(); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((org.hl7.fhir.instance.model.Reference) extlst.get(0).getValue()).getReference()); + } + + @ResourceDef(name = "Patient") + public static class TestPatientFor327 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "testCondition") + @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false) + private List testConditions = null; + + public List getConditions() { + return this.testConditions; + } + + public void setCondition(List ref) { + this.testConditions = ref; + } + } + + public static void compareXml(String content, String reEncoded) { + Diff d = DiffBuilder.compare(Input.fromString(content)) + .withTest(Input.fromString(reEncoded)) + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)) + .checkForSimilar() + .ignoreWhitespace() + .ignoreComments() + .withComparisonController(ComparisonControllers.Default) + .build(); + + assertTrue(d.toString(), !d.hasDifferences()); + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredAddressExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Address myFoo; + + public Address getFoo() { + return myFoo; + } + + public void setFoo(Address theFoo) { + myFoo = theFoo; + } + + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Reference myFoo; + + public Reference getFoo() { + return myFoo; + } + + public void setFoo(Reference theFoo) { + myFoo = theFoo; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java new file mode 100644 index 00000000000..37edb7a955f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java @@ -0,0 +1,13 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.DiagnosticReport; + +@ResourceDef(name = "DiagnosticReport", profile = CustomDiagnosticReport.PROFILE) +public class CustomDiagnosticReport extends DiagnosticReport { + + public static final String PROFILE = "http://custom_DiagnosticReport"; + + private static final long serialVersionUID = 1L; + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java new file mode 100644 index 00000000000..470ba8690da --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java @@ -0,0 +1,13 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.Observation; + +@ResourceDef(name = "Observation", profile = CustomObservation.PROFILE) +public class CustomObservation extends Observation { + + public static final String PROFILE = "http://custom_Observation"; + + private static final long serialVersionUID = 1L; + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java new file mode 100644 index 00000000000..e4baa629e05 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.BooleanType; +import org.hl7.fhir.dstu3.model.Patient; + +@ResourceDef(name = "Patient", profile = "Patient") +public class CustomPatientDstu3 extends Patient { + + + private static final long serialVersionUID = 1L; + + @Child(name = "homeless", order = 1) + @Extension(url = "/StructureDefinition/homeless", definedLocally = true, isModifier = false) + @Description(shortDefinition = "The patient being homeless, true if homeless") + private BooleanType homeless; + + + public BooleanType getHomeless() { + return homeless; + } + + public void setHomeless(final BooleanType homeless) { + this.homeless = homeless; + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java new file mode 100644 index 00000000000..1e3ff368610 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java @@ -0,0 +1,1700 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import java.io.IOException; +import java.io.StringReader; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.LenientErrorHandler; +import ca.uhn.fhir.parser.StrictErrorHandler; +import com.google.common.collect.Sets; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hl7.fhir.dstu3.model.AuditEvent; +import org.hl7.fhir.dstu3.model.Basic; +import org.hl7.fhir.dstu3.model.Binary; +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.CapabilityStatement; +import org.hl7.fhir.dstu3.model.Claim; +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.Condition; +import org.hl7.fhir.dstu3.model.Coverage; +import org.hl7.fhir.dstu3.model.DateTimeType; +import org.hl7.fhir.dstu3.model.DateType; +import org.hl7.fhir.dstu3.model.DecimalType; +import org.hl7.fhir.dstu3.model.DocumentManifest; +import org.hl7.fhir.dstu3.model.Enumerations; +import org.hl7.fhir.dstu3.model.ExplanationOfBenefit; +import org.hl7.fhir.dstu3.model.Extension; +import org.hl7.fhir.dstu3.model.HumanName; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.Linkage; +import org.hl7.fhir.dstu3.model.Observation; +import org.hl7.fhir.dstu3.model.Parameters; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.Quantity; +import org.hl7.fhir.dstu3.model.QuestionnaireResponse; +import org.hl7.fhir.dstu3.model.Reference; +import org.hl7.fhir.dstu3.model.SampledData; +import org.hl7.fhir.dstu3.model.SimpleQuantity; +import org.hl7.fhir.dstu3.model.StringType; +import org.hl7.fhir.dstu3.model.UriType; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.apache.commons.lang3.StringUtils.countMatches; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class Dstu3JsonParserTest { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu3JsonParserTest.class); + private FhirContext ourCtx = FhirContext.forDstu3(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_DSTU3.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + + /** + * See #544 + */ + @Test + public void testBundleStitchReferencesByUuid() throws Exception { + Bundle bundle = new Bundle(); + + DocumentManifest dm = new DocumentManifest(); + dm.getSubject().setReference("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3"); + bundle.addEntry().setResource(dm); + + Patient patient = new Patient(); + patient.addName().setFamily("FAMILY"); + bundle.addEntry().setResource(patient).setFullUrl("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle); + ourLog.info(encoded); + + bundle = ourCtx.newJsonParser().parseResource(Bundle.class, encoded); + dm = (DocumentManifest) bundle.getEntry().get(0).getResource(); + + assertEquals("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3", dm.getSubject().getReference()); + + Patient subject = (Patient) dm.getSubject().getResource(); + assertNotNull(subject); + assertEquals("FAMILY", subject.getNameFirstRep().getFamily()); + } + + /** + * Test for the url generated based on the server config + */ + @Test + public void testCustomUrlExtension() { + final String expected = "{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}"; + + final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setPetName(new StringType("myName")); + + final IParser jsonParser = ourCtx.newJsonParser(); + jsonParser.setServerBaseUrl("http://www.example.com"); + + final String parsedPatient = jsonParser.encodeResourceToString(patient); + System.out.println(parsedPatient); + assertEquals(expected, parsedPatient); + + // Parse with string + MyPatientWithCustomUrlExtension newPatient = jsonParser.parseResource(MyPatientWithCustomUrlExtension.class, parsedPatient); + assertEquals("myName", newPatient.getPetName().getValue()); + + // Parse with stream + newPatient = jsonParser.parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); + assertEquals("myName", newPatient.getPetName().getValue()); + + // Check no NPE if base server not configure + newPatient = ourCtx.newJsonParser().parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); + assertNull("myName", newPatient.getPetName().getValue()); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + } + + @Test + public void testCustomUrlExtensioninBundle() { + final String expected = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}}]}"; + + final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setPetName(new StringType("myName")); + + final Bundle bundle = new Bundle(); + final Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent(); + entry.setResource(patient); + bundle.addEntry(entry); + + final IParser jsonParser = ourCtx.newJsonParser(); + jsonParser.setServerBaseUrl("http://www.example.com"); + + final String parsedBundle = jsonParser.encodeResourceToString(bundle); + System.out.println(parsedBundle); + assertEquals(expected, parsedBundle); + + // Parse with string + Bundle newBundle = jsonParser.parseResource(Bundle.class, parsedBundle); + assertNotNull(newBundle); + assertEquals(1, newBundle.getEntry().size()); + Patient newPatient = (Patient) newBundle.getEntry().get(0).getResource(); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + + // Parse with stream + newBundle = jsonParser.parseResource(Bundle.class, new StringReader(parsedBundle)); + assertNotNull(newBundle); + assertEquals(1, newBundle.getEntry().size()); + newPatient = (Patient) newBundle.getEntry().get(0).getResource(); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + + } + + /** + * See #276 + */ + @Test + public void testDoubleEncodingContainedResources() throws Exception { + Patient patient = new Patient(); + patient.setId("#patient-1"); + patient.setActive(true); + + Coverage coverage = new Coverage(); + coverage.setId("#coverage-1"); + coverage.getBeneficiary().setResource(patient); + + Claim resource = new Claim(); + resource.getContained().add(patient); + resource.getContained().add(coverage); + resource.getPatient().setReference("#patient-1"); + resource.addInsurance().getCoverage().setReference("#coverage-1"); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(resource); + ourLog.info(encoded); + + assertEquals(3, countMatches(encoded, "resourceType")); + } + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + patient.addExtension(ext); + + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child1); + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); + parent.addExtension(child2); + + Extension modExt = new Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new DateType("1995-01-02")); + patient.addModifierExtension(modExt); + + HumanName name = patient.addName(); + name.setFamily("Blah"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.addExtension(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + given2ext.addExtension(new Extension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"))); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newJsonParser().encodeResourceToString(patient); + assertThat(enc, stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}", + "{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}")); + assertThat(enc, stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],")); + assertThat(enc, + containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{" + + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + + "]" + "}")); + + /* + * Now parse this back + */ + + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); + + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + @Test + public void testEncodeAndParseMetaProfileAndTags() { + Patient p = new Patient(); + p.addName().setFamily("FAMILY"); + + p.getMeta().addProfile("http://foo/Profile1"); + p.getMeta().addProfile("http://foo/Profile2"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1"); + p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2"); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder("\"meta\": {", + "\"profile\": [", + "\"http://foo/Profile1\",", + "\"http://foo/Profile2\"", + "],", + "\"security\": [", + "{", + "\"system\": \"sec_scheme1\",", + "\"code\": \"sec_term1\",", + "\"display\": \"sec_label1\"", + "},", + "{", + "\"system\": \"sec_scheme2\",", + "\"code\": \"sec_term2\",", + "\"display\": \"sec_label2\"", + "}", + "],", + "\"tag\": [", + "{", + "\"system\": \"scheme1\",", + "\"code\": \"term1\",", + "\"display\": \"label1\"", + "},", + "{", + "\"system\": \"scheme2\",", + "\"code\": \"term2\",", + "\"display\": \"label2\"", + "}", + "]", + "},")); + //@formatter:on + + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc); + + List gotLabels = parsed.getMeta().getProfile(); + assertEquals(2, gotLabels.size()); + UriType label = gotLabels.get(0); + assertEquals("http://foo/Profile1", label.getValue()); + label = gotLabels.get(1); + assertEquals("http://foo/Profile2", label.getValue()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + + tagList = parsed.getMeta().getSecurity(); + assertEquals(2, tagList.size()); + assertEquals("sec_scheme1", tagList.get(0).getSystem()); + assertEquals("sec_term1", tagList.get(0).getCode()); + assertEquals("sec_label1", tagList.get(0).getDisplay()); + assertEquals("sec_scheme2", tagList.get(1).getSystem()); + assertEquals("sec_term2", tagList.get(1).getCode()); + assertEquals("sec_label2", tagList.get(1).getDisplay()); + } + + /** + * See #336 + */ + @Test + public void testEncodeAndParseNullPrimitiveWithExtensions() { + + Patient p = new Patient(); + p.setId("patid"); + HumanName name = p.addName(); + name.addGivenElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0"))); + name.addGivenElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id")); + name.addGivenElement(); // this one shouldn't get encoded + name.addGivenElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3"))); + name.setId("nameid"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + output = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(p); + String expected = "{\"resourceType\":\"Patient\",\"id\":\"patid\",\"name\":[{\"id\":\"nameid\",\"given\":[null,\"V1\",null],\"_given\":[{\"id\":\"f0\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT0\"}]},{\"id\":\"f1\",\"extension\":[{\"id\":\"ext1id\",\"url\":\"http://foo\",\"valueString\":\"FOOEXT1\"}]},{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT3\"}]}]}]}"; + assertEquals(expected, output); + + p = ourCtx.newJsonParser().parseResource(Patient.class, output); + assertEquals("patid", p.getIdElement().getIdPart()); + + name = p.getName().get(0); + assertEquals("nameid", name.getId()); + assertEquals(3, name.getGiven().size()); + + assertEquals(null, name.getGiven().get(0).getValue()); + assertEquals("V1", name.getGiven().get(1).getValue()); + assertEquals(null, name.getGiven().get(2).getValue()); + + assertEquals("f0", name.getGiven().get(0).getId()); + assertEquals("f1", name.getGiven().get(1).getId()); + assertEquals(null, name.getGiven().get(2).getId()); + + assertEquals(1, name.getGiven().get(0).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl()); + assertEquals("FOOEXT0", ((StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(1).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl()); + assertEquals("FOOEXT1", ((StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue()); + assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(2).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl()); + assertEquals("FOOEXT3", ((StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId()); + + } + + @Test + public void testEncodeAndParseSecurityLabels() { + Patient p = new Patient(); + p.addName().setFamily("FAMILY"); + + List labels = new ArrayList(); + labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1")); + labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2")); + p.getMeta().getSecurity().addAll(labels); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + //@formatter:off + assertEquals("{\n" + + " \"resourceType\": \"Patient\",\n" + + " \"meta\": {\n" + + " \"security\": [\n" + + " {\n" + + " \"system\": \"SYSTEM1\",\n" + + " \"version\": \"VERSION1\",\n" + + " \"code\": \"CODE1\",\n" + + " \"display\": \"DISPLAY1\"\n" + + " },\n" + + " {\n" + + " \"system\": \"SYSTEM2\",\n" + + " \"version\": \"VERSION2\",\n" + + " \"code\": \"CODE2\",\n" + + " \"display\": \"DISPLAY2\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"name\": [\n" + + " {\n" + + " \"family\": \"FAMILY\"\n" + + " }\n" + + " ]\n" + + "}", enc.trim()); + //@formatter:on + + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc); + List gotLabels = parsed.getMeta().getSecurity(); + + assertEquals(2, gotLabels.size()); + + Coding label = gotLabels.get(0); + assertEquals("SYSTEM1", label.getSystem()); + assertEquals("CODE1", label.getCode()); + assertEquals("DISPLAY1", label.getDisplay()); + assertEquals("VERSION1", label.getVersion()); + + label = gotLabels.get(1); + assertEquals("SYSTEM2", label.getSystem()); + assertEquals("CODE2", label.getCode()); + assertEquals("DISPLAY2", label.getDisplay()); + assertEquals("VERSION2", label.getVersion()); + } + + @Test + public void testEncodeBinaryWithSecurityContext() { + Binary bin = new Binary(); + bin.setContentType("text/plain"); + bin.setContent("Now is the time".getBytes()); + Reference securityContext = new Reference(); + securityContext.setReference("DiagnosticReport/1"); + bin.setSecurityContext(securityContext); + String encoded = ourCtx.newJsonParser().encodeResourceToString(bin); + ourLog.info(encoded); + assertThat(encoded, containsString("Binary")); + assertThat(encoded, containsString("\"contentType\":\"text/plain\"")); + assertThat(encoded, containsString("\"content\":\"Tm93IGlzIHRoZSB0aW1l\"")); + assertThat(encoded, containsString("\"securityContext\":{\"reference\":\"DiagnosticReport/1\"}")); + } + + @Test + public void testEncodeBundleNewBundleNoText() { + + Bundle b = new Bundle(); + + Bundle.BundleEntryComponent e = b.addEntry(); + e.setResource(new Patient()); + + String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + assertThat(val, not(containsString("text"))); + + val = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(b); + ourLog.info(val); + assertThat(val, not(containsString("text"))); + + } + + /** + * See #326 + */ + @Test + public void testEncodeContainedResource() { + Patient patient = new Patient(); + patient.getBirthDateElement().setValueAsString("2016-04-05"); + patient.addExtension().setUrl("test").setValue(new Reference(new Condition())); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "{", + "\"resourceType\": \"Patient\",", + "\"contained\": [", + "{", + "\"resourceType\": \"Condition\",", + "\"id\": \"1\"", + "}", + "],", + "\"extension\": [", + "{", + "\"url\": \"test\",", + "\"valueReference\": {", + "\"reference\": \"#1\"", + "}", + "}", + "],", + "\"birthDate\": \"2016-04-05\"", + "}" + )); + //@formatter:on + } + + @Test + public void testEncodeDoesntIncludeUuidId() { + Patient p = new Patient(); + p.setId(new IdType("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2")); + p.addIdentifier().setSystem("ACME"); + + String actual = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + assertThat(actual, not(containsString("78ef6f64c2f2"))); + } + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newJsonParser().encodeResourceToString(new Binary()); + assertEquals("{\"resourceType\":\"Binary\"}", output); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding()); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(p); + assertThat(encoded, not(containsString("tag"))); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag2() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding().setSystem("scheme").setCode("code")); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(p); + assertThat(encoded, containsString("tag")); + assertThat(encoded, containsString("scheme")); + assertThat(encoded, not(containsString("Label"))); + } + + /** + * #480 + */ + @Test + public void testEncodeEmptyValue() { + QuestionnaireResponse qr = new QuestionnaireResponse(); + qr.setId("123"); + qr.getAuthoredElement().setValueAsString(""); + qr.getItemFirstRep().setLinkIdElement(new StringType()); + qr.getItemFirstRep().addItem().setLinkIdElement(new StringType("")); + qr.getItemFirstRep().addItem().setLinkIdElement(new StringType("LINKID")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(qr); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("123")); + assertThat(encoded, not(stringContainsInOrder("\"\""))); + assertThat(encoded, not(stringContainsInOrder("null"))); + } + + @Test + public void testEncodeExtensionInPrimitiveElement() { + + CapabilityStatement c = new CapabilityStatement(); + c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new StringType("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"CapabilityStatement\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + // Now with a value + ourLog.info("---------------"); + + c = new CapabilityStatement(); + c.getAcceptUnknownElement().setValue(CapabilityStatement.UnknownContentCode.ELEMENTS); + c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new StringType("AAA")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"CapabilityStatement\",\"acceptUnknown\":\"elements\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + } + + @Test + public void testEncodeExtensionOnRoot() { + Patient p = new Patient(); + p.setId("Patient/B"); + p + .addExtension() + .setUrl("http://foo") + .setValue(new Reference("Practitioner/A")); + + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + parser.setDontEncodeElements(new HashSet(Arrays.asList("*.id", "*.meta"))); + + String encoded = parser.encodeResourceToString(p); + ourLog.info(encoded); + + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("Practitioner/A")); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + obs.setStatus(Observation.ObservationStatus.FINAL); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\": \"1\"", + "\"meta\"", + "\"extension\"", + "\"url\": \"http://exturl\"", + "\"valueString\": \"ext_url_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\": \"http://exturl\"", + ",", + "\"url\": \"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType) obs.getExtension().get(0).getValue()).getValue()); + assertEquals("final", obs.getStatusElement().getValueAsString()); + assertEquals(Observation.ObservationStatus.FINAL, obs.getStatusElement().getValue()); + + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newJsonParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + //@formatter:off + assertThat(output, stringContainsInOrder( + "\"id\": \"1\"", + "\"meta\"", + "\"extension\"", + "\"url\": \"http://exturl\"", + "\"extension\"", + "\"url\": \"http://subext\"", + "\"valueString\": \"sub_ext_value\"", + "\"code\":" + )); + assertThat(output, not(stringContainsInOrder( + "\"url\": \"http://exturl\"", + ",", + "\"url\": \"http://exturl\"" + ))); + //@formatter:on + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + + + @Test + public void testEncodeHistoryEncodeVersionsAtPath1() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + Patient p = new Patient(); + p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath2() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + + Patient p = new Patient(); + p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath3() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + AuditEvent auditEvent = new AuditEvent(); + auditEvent.addEntity().setReference(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList()); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setDontStripVersionsFromReferencesAtPaths((String[]) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setDontStripVersionsFromReferencesAtPaths((List) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPathUsingOptions() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths(), empty()); + + Patient p = new Patient(); + p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(Arrays.asList("Patient.managingOrganization")); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(new HashSet(Arrays.asList("Patient.managingOrganization"))); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + } + + @Test + public void testEncodeHistoryStripVersionsFromReferences() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); + + Patient p = new Patient(); + p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + parser.setStripVersionsFromReferences(false); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + ourCtx = FhirContext.forDstu3(); + } + + @Test + public void testEncodeHistoryStripVersionsFromReferencesFromContext() { + ourCtx = FhirContext.forDstu3(); + + assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); + + Patient p = new Patient(); + p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newJsonParser(); + String enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + ourCtx.getParserOptions().setStripVersionsFromReferences(false); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\"")); + + parser.setStripVersionsFromReferences(true); + enc = parser.setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\"")); + + ourCtx = FhirContext.forDstu3(); + } + + @Test + public void testEncodeNarrativeShouldIncludeNamespace() { + + Patient p = new Patient(); + p.getText().setDivAsString("
VALUE
"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + assertThat(output, containsString("\"div\": \"
VALUE
\"")); + } + + @Test + public void testEncodeNarrativeShouldIncludeNamespaceWithProcessingInstruction() { + + Patient p = new Patient(); + p.getText().setDivAsString("
VALUE
"); + + String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + assertThat(output, containsString("\"div\": \"
VALUE
\"")); + } + + @Test + public void testEncodeNarrativeSuppressed() throws Exception { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder(ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM, ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE)); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeParametersWithId() { + Parameters reqParms = new Parameters(); + IdType patient = new IdType(1); + reqParms.addParameter().setName("patient").setValue(patient); + + String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(reqParms); + ourLog.info(enc); + + assertThat(enc, containsString("\"valueId\": \"1\"")); + } + + @Test + public void testEncodeSummary() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.addPhoto().setTitle("green"); + patient.getMaritalStatus().addCoding().setCode("D"); + + ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient)); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\"")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.getMaritalStatus().addCoding().setCode("D"); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("Patient")); + assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"foo\",", "\"code\": \"bar\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\"", + "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\"")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + /** + * See #205 + */ + @Test + public void testEncodeTags() { + Patient pt = new Patient(); + pt.addIdentifier().setSystem("sys").setValue("val"); + + pt.getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("display"); + + String enc = ourCtx.newJsonParser().encodeResourceToString(pt); + ourLog.info(enc); + + assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}", + enc); + + } + + /** + * See #241 + */ + @Test + public void testEncodeThenParseShouldNotAddSpuriousId() throws Exception { + Condition condition = new Condition().setVerificationStatus(Condition.ConditionVerificationStatus.CONFIRMED); + Bundle bundle = new Bundle(); + Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent(); + entry.setId("123"); + entry.setResource(condition); + bundle.getEntry().add(entry); + IParser parser = ourCtx.newJsonParser(); + String json = parser.encodeResourceToString(bundle); + ourLog.info(json); + bundle = (Bundle) parser.parseResource(json); + + assertEquals("123", bundle.getEntry().get(0).getId()); + + condition = (Condition) bundle.getEntry().get(0).getResource(); + assertEquals(null, condition.getId()); + } + + @Test + public void testEncodeWithDontEncodeElements() throws Exception { + Patient patient = new Patient(); + patient.setId("123"); + + patient.getMeta().addProfile(("http://profile")); + patient.addName().setFamily("FAMILY").addGiven("GIVEN"); + patient.addAddress().addLine("LINE1"); + + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.name.family")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("GIVEN")); + assertThat(out, not(containsString("FAMILY"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newJsonParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta")); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("id")); + assertThat(out, not(containsString("address"))); + assertThat(out, not(containsString("meta"))); + } + } + + @Test + public void testEncodingNullExtension() { + Patient p = new Patient(); + Extension extension = new Extension("http://foo#bar"); + p.addExtension(extension); + String str = ourCtx.newJsonParser().encodeResourceToString(p); + + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringType()); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringType("")); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + } + + /** + * See #341 + */ + @Test + public void testExplanationOfBenefit() { + //@formatter:off + String input = "{" + + " \"resourceType\": \"ExplanationOfBenefit\"," + + " \"insurance\": {\n" + + " \"coverage\": {\n" + + " \"reference\": \"Coverage/123\"\n" + + " }\n" + + " },\n" + + " \"relationship\": {\n" + + " \"system\": \"http://hl7.org/fhir/relationship\",\n" + + " \"code\": \"1\",\n" + + " \"display\": \"self\"\n" + + " }\n" + + "}"; + //@formatter:on + + ExplanationOfBenefit eob = ourCtx.newJsonParser().parseResource(ExplanationOfBenefit.class, input); + assertEquals(Reference.class, eob.getInsurance().getCoverage().getClass()); + + Reference coverage = eob.getInsurance().getCoverage(); + assertEquals("Coverage/123", coverage.getReference()); + } + + @Test + public void testExponentDoesntGetEncodedAsSuch() { + Observation obs = new Observation(); + obs.setValue(new Quantity().setValue(new BigDecimal("0.000000000000000100"))); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str); + } + + @Test + public void testExponentParseWorks() { + String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}"; + Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input); + + assertEquals("0.0000000000000001", ((Quantity) obs.getValue()).getValueElement().getValueAsString()); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}", str); + } + + /** + * #516 + */ + @Test(expected = DataFormatException.class) + public void testInvalidEnumValue() { + String res = "{ \"resourceType\": \"ValueSet\", \"url\": \"http://sample/ValueSet/education-levels\", \"version\": \"1\", \"name\": \"Education Levels\", \"status\": \"draft\", \"compose\": { \"include\": [ { \"filter\": [ { \"property\": \"n\", \"op\": \"n\", \"value\": \"365460000\" } ], \"system\": \"http://snomed.info/sct\" } ], \"exclude\": [ { \"concept\": [ { \"code\": \"224298008\" }, { \"code\": \"365460000\" }, { \"code\": \"473462005\" }, { \"code\": \"424587006\" } ], \"system\": \"http://snomed.info/sct\" } ] }, \"description\": \"A selection of Education Levels\", \"text\": { \"status\": \"generated\", \"div\": \"

Education Levels

http://csiro.au/ValueSet/education-levels

A selection of Education Levels

\" }, \"experimental\": true, \"date\": \"2016-07-26\" }"; + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + ValueSet parsed = parser.parseResource(ValueSet.class, res); + fail("DataFormat Invalid attribute exception should be thrown"); + } + + /** + * #65 + */ + @Test + public void testJsonPrimitiveWithExtensionEncoding() { + + QuestionnaireResponse parsed = new QuestionnaireResponse(); + parsed.addItem().setLinkId("value123"); + parsed.getItem().get(0).getLinkIdElement().addExtension(new Extension("http://123", new StringType("HELLO"))); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(parsed); + ourLog.info(encoded); + assertThat(encoded, containsString("{\"linkId\":\"value123\",\"_linkId\":{\"extension\":[{\"url\":\"http://123\",\"valueString\":\"HELLO\"}]}}")); + + } + + @Test + public void testLinkage() { + Linkage l = new Linkage(); + l.addItem().getResource().setDisplay("FOO"); + String out = ourCtx.newXmlParser().encodeResourceToString(l); + ourLog.info(out); + assertEquals("", out); + } + + + @Test + public void testOmitResourceId() { + Patient p = new Patient(); + p.setId("123"); + p.addName().setFamily("ABC"); + + assertThat(ourCtx.newJsonParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC")); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC")); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu3(); + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + try { + String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}"; + Bundle bundle = (Bundle) ourCtx.newJsonParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = FhirContext.forDstu3(); + } + } + + + @Test + public void testParseAndEncodeBundleWithUuidBase() { + //@formatter:off + String input = + "{\n" + + " \"resourceType\":\"Bundle\",\n" + + " \"type\":\"document\",\n" + + " \"entry\":[\n" + + " {\n" + + " \"fullUrl\":\"urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" + + " \"resource\":{\n" + + " \"resourceType\":\"Composition\",\n" + + " \"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" + + " \"meta\":{\n" + + " \"lastUpdated\":\"2013-05-28T22:12:21Z\"\n" + + " },\n" + + " \"text\":{\n" + + " \"status\":\"generated\",\n" + + " \"div\":\"

Generated Narrative with Details

id: 180f219f-97a8-486d-99d9-ed631fe4fc57

meta:

date: Feb 1, 2013 12:30:02 PM

type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)

status: final

confidentiality: N

author: Doctor Dave. Generated Summary: 23; Adam Careful

encounter: http://fhir.healthintersections.com.au/open/Encounter/doc-example

\"\n" + + " },\n" + + " \"date\":\"2013-02-01T12:30:02Z\",\n" + + " \"type\":{\n" + + " \"coding\":[\n" + + " {\n" + + " \"system\":\"http://loinc.org\",\n" + + " \"code\":\"28655-9\"\n" + + " }\n" + + " ],\n" + + " \"text\":\"Discharge Summary from Responsible Clinician\"\n" + + " },\n" + + " \"status\":\"final\",\n" + + " \"confidentiality\":\"N\",\n" + + " \"subject\":{\n" + + " \"reference\":\"http://fhir.healthintersections.com.au/open/Patient/d1\",\n" + + " \"display\":\"Eve Everywoman\"\n" + + " },\n" + + " \"author\":[\n" + + " {\n" + + " \"reference\":\"Practitioner/example\",\n" + + " \"display\":\"Doctor Dave\"\n" + + " }\n" + + " ],\n" + + " \"encounter\":{\n" + + " \"reference\":\"http://fhir.healthintersections.com.au/open/Encounter/doc-example\"\n" + + " },\n" + + " \"section\":[\n" + + " {\n" + + " \"title\":\"Reason for admission\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:d0dd51d3-3ab2-4c84-b697-a630c3e40e7a\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\":\"Medications on Discharge\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:673f8db5-0ffd-4395-9657-6da00420bbc1\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"title\":\"Known allergies\",\n" + + " \"content\":{\n" + + " \"reference\":\"urn:uuid:68f86194-e6e1-4f65-b64a-5314256f8d7b\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }" + + " ]" + + "}"; + //@formatter:on + + Bundle parsed = ourCtx.newJsonParser().parseResource(Bundle.class, input); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed); + ourLog.info(encoded); + + assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + assertEquals(null, parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl()); + assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart()); + assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\""))); + } + + @Test + public void testParseAndEncodeComments() { + //@formatter:off + String input = "{\n" + + " \"resourceType\": \"Patient\",\n" + + " \"id\": \"pat1\",\n" + + " \"text\": {\n" + + " \"status\": \"generated\",\n" + + " \"div\": \"
\\n \\n

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

\\n \\n
\"\n" + + " },\n" + + " \"identifier\": [\n" + + " {\n" + + " \"fhir_comments\":[\"identifier comment 1\",\"identifier comment 2\"],\n" + + " \"use\": \"usual\",\n" + + " \"_use\": {\n" + + " \"fhir_comments\":[\"use comment 1\",\"use comment 2\"]\n" + + " },\n" + + " \"type\": {\n" + + " \"coding\": [\n" + + " {\n" + + " \"system\": \"http://hl7.org/fhir/v2/0203\",\n" + + " \"code\": \"MR\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"system\": \"urn:oid:0.1.2.3.4.5.6.7\",\n" + + " \"value\": \"654321\"\n" + + " }\n" + + " ],\n" + + " \"active\": true" + + "}"; + //@formatter:off + + Patient res = ourCtx.newJsonParser().parseResource(Patient.class, input); + res.getFormatCommentsPre(); + assertEquals("Patient/pat1", res.getId()); + assertEquals("654321", res.getIdentifier().get(0).getValue()); + assertEquals(true, res.getActive()); + + assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + //@formatter:off + assertThat(encoded, stringContainsInOrder( + "\"identifier\": [", + "{", + "\"fhir_comments\":", + "[", + "\"identifier comment 1\"", + ",", + "\"identifier comment 2\"", + "]", + "\"use\": \"usual\",", + "\"_use\": {", + "\"fhir_comments\":", + "[", + "\"use comment 1\"", + ",", + "\"use comment 2\"", + "]", + "},", + "\"type\"" + )); + //@formatter:off + } + + @Test + public void testParseBundleWithBinary() { + Binary patient = new Binary(); + patient.setId(new IdType("http://base/Binary/11/_history/22")); + patient.setContentType("foo"); + patient.setContent(new byte[]{1, 2, 3, 4}); + + String val = ourCtx.newJsonParser().encodeResourceToString(patient); + + String expected = "{\"resourceType\":\"Binary\",\"id\":\"11\",\"meta\":{\"versionId\":\"22\"},\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"; + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", val); + assertEquals(expected, val); + } + + /** + * #480 + */ + @Test + public void testParseEmptyValue() { + String input = "{\"resourceType\":\"QuestionnaireResponse\",\"id\":\"123\",\"authored\":\"\",\"group\":{\"linkId\":\"\"}}"; + IParser parser = ourCtx.newJsonParser(); + + parser.setParserErrorHandler(new LenientErrorHandler().setErrorOnInvalidValue(false)); + QuestionnaireResponse qr = parser.parseResource(QuestionnaireResponse.class, input); + + assertEquals("QuestionnaireResponse/123", qr.getIdElement().getValue()); + assertEquals(null, qr.getAuthored()); + assertEquals(null, qr.getAuthoredElement().getValue()); + assertEquals(null, qr.getAuthoredElement().getValueAsString()); + assertEquals(null, qr.getItemFirstRep().getLinkId()); + assertEquals(null, qr.getItemFirstRep().getLinkIdElement().getValue()); + } + + /** + * See #342 + */ + @Test() + public void testParseInvalid() { + try { + ourCtx.newJsonParser().parseResource("FOO"); + fail(); + } catch (DataFormatException e) { + assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage()); + } + try { + ourCtx.newJsonParser().parseResource("[\"aaa\"]"); + fail(); + } catch (DataFormatException e) { + assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage()); + } + + assertEquals(Bundle.class, ourCtx.newJsonParser().parseResource(" {\"resourceType\" : \"Bundle\"}").getClass()); + + } + + /** + * See #414 + */ + @Test + public void testParseJsonExtensionWithoutUrl() { + //@formatter:off + String input = + "{\"resourceType\":\"Patient\"," + + "\"extension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" + + "}"; + //@formatter:on + + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getExtension().size()); + assertEquals(null, parsed.getExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", parsed.getExtension().get(0).getValueAsPrimitive().getValueAsString()); + + try { + parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getMessage()); + } + + } + + /** + * See #414 + */ + @Test + public void testParseJsonModifierExtensionWithoutUrl() { + //@formatter:off + String input = + "{\"resourceType\":\"Patient\"," + + "\"modifierExtension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" + + "}"; + //@formatter:on + + IParser parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getModifierExtension().size()); + assertEquals(null, parsed.getModifierExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", parsed.getModifierExtension().get(0).getValueAsPrimitive().getValueAsString()); + + try { + parser = ourCtx.newJsonParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getMessage()); + } + + } + + + /** + * See #484 + */ + @Test + public void testParseNarrativeWithEmptyDiv() { + String input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + Basic basic = ourCtx.newJsonParser().parseResource(Basic.class, input); + assertEquals(null, basic.getText().getDivAsString()); + + input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + basic = ourCtx.newJsonParser().parseResource(Basic.class, input); + assertEquals(null, basic.getText().getDivAsString()); + + input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"
\"}}"; + basic = ourCtx.newJsonParser().parseResource(Basic.class, input); + assertEquals("
", basic.getText().getDivAsString()); + + } + + /** + * See #163 + */ + @Test + public void testParseResourceType() { + IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true); + + // Patient + Patient patient = new Patient(); + String patientId = UUID.randomUUID().toString(); + patient.setId(new IdType("Patient", patientId)); + patient.addName().addGiven("John").setFamily("Smith"); + patient.setGender(Enumerations.AdministrativeGender.MALE); + patient.setBirthDateElement(new DateType("1987-04-16")); + + // Bundle + Bundle bundle = new Bundle(); + bundle.setType(Bundle.BundleType.COLLECTION); + bundle.addEntry().setResource(patient); + + String bundleText = jsonParser.encodeResourceToString(bundle); + ourLog.info(bundleText); + + Bundle reincarnatedBundle = jsonParser.parseResource(Bundle.class, bundleText); + Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource(); + + assertEquals("Patient", patient.getIdElement().getResourceType()); + assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType()); + } + + /** + * See #207 + */ + @Test + public void testParseResourceWithInvalidType() { + String input = "{" + "\"resourceType\":\"Patient\"," + "\"contained\":[" + " {" + " \"rezType\":\"Organization\"" + " }" + " ]" + "}"; + + IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true); + try { + jsonParser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Missing required element 'resourceType' from JSON resource object, unable to parse", e.getMessage()); + } + } + + @Test + public void testParseWithPrecision() { + String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}"; + Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input); + + DecimalType valueElement = ((Quantity) obs.getValue()).getValueElement(); + assertEquals("0.000000000000000100", valueElement.getValueAsString()); + + String str = ourCtx.newJsonParser().encodeResourceToString(obs); + ourLog.info(str); + assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str); + } + + @Test(expected = DataFormatException.class) + public void testParseWithTrailingContent() throws Exception { + //@formatter:off + String bundle = "{\n" + + " \"resourceType\" : \"Bundle\",\n" + + " \"total\" : 1\n" + + "}}"; + //@formatter:on + + Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, bundle); + } + + /** + * See #344 + */ + @Test + public void testParserIsCaseSensitive() { + Observation obs = new Observation(); + SampledData data = new SampledData(); + data.setData("1 2 3"); + data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L)); + data.setPeriod(1000L); + obs.setValue(data); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler()); + String encoded = p.encodeResourceToString(obs); + ourLog.info(encoded); + + p.parseResource(encoded); + + try { + p.parseResource(encoded.replace("Observation", "observation")); + fail(); + } catch (DataFormatException e) { + assertEquals("Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", e.getMessage()); + } + + try { + p.parseResource(encoded.replace("valueSampledData", "valueSampleddata")); + fail(); + } catch (DataFormatException e) { + assertEquals("Unknown element 'valueSampleddata' found during parse", e.getMessage()); + } + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java new file mode 100644 index 00000000000..4f1194afe09 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java @@ -0,0 +1,3235 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.LenientErrorHandler; +import ca.uhn.fhir.parser.StrictErrorHandler; +import com.google.common.collect.Sets; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.hl7.fhir.dstu3.model.Address; +import org.hl7.fhir.dstu3.model.AllergyIntolerance; +import org.hl7.fhir.dstu3.model.Annotation; +import org.hl7.fhir.dstu3.model.Appointment; +import org.hl7.fhir.dstu3.model.AuditEvent; +import org.hl7.fhir.dstu3.model.Binary; +import org.hl7.fhir.dstu3.model.BooleanType; +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.CodeType; +import org.hl7.fhir.dstu3.model.CodeableConcept; +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.Composition; +import org.hl7.fhir.dstu3.model.ConceptMap; +import org.hl7.fhir.dstu3.model.Condition; +import org.hl7.fhir.dstu3.model.ContactPoint; +import org.hl7.fhir.dstu3.model.DataElement; +import org.hl7.fhir.dstu3.model.DateTimeType; +import org.hl7.fhir.dstu3.model.DateType; +import org.hl7.fhir.dstu3.model.DiagnosticReport; +import org.hl7.fhir.dstu3.model.DocumentManifest; +import org.hl7.fhir.dstu3.model.Duration; +import org.hl7.fhir.dstu3.model.ElementDefinition; +import org.hl7.fhir.dstu3.model.Encounter; +import org.hl7.fhir.dstu3.model.EnumFactory; +import org.hl7.fhir.dstu3.model.Enumeration; +import org.hl7.fhir.dstu3.model.Enumerations; +import org.hl7.fhir.dstu3.model.Extension; +import org.hl7.fhir.dstu3.model.GuidanceResponse; +import org.hl7.fhir.dstu3.model.HumanName; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.InstantType; +import org.hl7.fhir.dstu3.model.Location; +import org.hl7.fhir.dstu3.model.Medication; +import org.hl7.fhir.dstu3.model.MedicationRequest; +import org.hl7.fhir.dstu3.model.MedicationStatement; +import org.hl7.fhir.dstu3.model.Observation; +import org.hl7.fhir.dstu3.model.Organization; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.Practitioner; +import org.hl7.fhir.dstu3.model.PrimitiveType; +import org.hl7.fhir.dstu3.model.ProcedureRequest; +import org.hl7.fhir.dstu3.model.Quantity; +import org.hl7.fhir.dstu3.model.Reference; +import org.hl7.fhir.dstu3.model.Resource; +import org.hl7.fhir.dstu3.model.SampledData; +import org.hl7.fhir.dstu3.model.SimpleQuantity; +import org.hl7.fhir.dstu3.model.StringType; +import org.hl7.fhir.dstu3.model.UriType; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.builder.Input; +import org.xmlunit.diff.ComparisonControllers; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.Diff; +import org.xmlunit.diff.ElementSelectors; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class Dstu3XmlParserTest { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu3XmlParserTest.class); + private FhirContext ourCtx = FhirContext.forDstu3(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_DSTU3.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() { + String refVal = "http://my.org/FooBar"; + + Patient fhirPat = new Patient(); + fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal)); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.encodeResourceToString(fhirPat); + System.out.println("output: " + output); + + // Deserialize then check that valueReference value is still correct + fhirPat = parser.parseResource(Patient.class, output); + + List extlst = fhirPat.getExtensionsByUrl("x1"); + Assert.assertEquals(1, extlst.size()); + Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference()); + } + + /** + * See #544 + */ + @Test + public void testBundleStitchReferencesByUuid() throws Exception { + Bundle bundle = new Bundle(); + + DocumentManifest dm = new DocumentManifest(); + dm.getSubject().setReference("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3"); + bundle.addEntry().setResource(dm); + + Patient patient = new Patient(); + patient.addName().setFamily("FAMILY"); + bundle.addEntry().setResource(patient).setFullUrl("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle); + ourLog.info(encoded); + + bundle = ourCtx.newXmlParser().parseResource(Bundle.class, encoded); + dm = (DocumentManifest) bundle.getEntry().get(0).getResource(); + + assertEquals("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3", dm.getSubject().getReference()); + + Patient subject = (Patient) dm.getSubject().getResource(); + assertNotNull(subject); + assertEquals("FAMILY", subject.getNameFirstRep().getFamily()); + } + + @Test + public void testBundleWithBinary() { + + String bundle = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, bundle); + assertEquals(1, b.getEntry().size()); + + Binary bin = (Binary) b.getEntry().get(0).getResource(); + assertArrayEquals(new byte[]{1, 2, 3, 4}, bin.getContent()); + + } + + + @Test + public void testContainedResourceInExtensionUndeclared() { + Patient p = new Patient(); + p.addName().setFamily("PATIENT"); + + Organization o = new Organization(); + o.setName("ORG"); + p.addExtension(new Extension("urn:foo", new Reference(o))); + + String str = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(str); + + p = ourCtx.newXmlParser().parseResource(Patient.class, str); + assertEquals("PATIENT", p.getName().get(0).getFamily()); + + List exts = p.getExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + Reference rr = (Reference) exts.get(0).getValue(); + o = (Organization) rr.getResource(); + assertEquals("ORG", o.getName()); + } + + @Test(expected = DataFormatException.class) + public void testContainedResourceWithNoId() throws IOException { + String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_contained_with_no_id.xml"), StandardCharsets.UTF_8); + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(Bundle.class, string); + } + + @Test() + public void testContainedResourceWithNoIdLenient() throws IOException { + String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_contained_with_no_id.xml"), StandardCharsets.UTF_8); + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + parser.parseResource(Bundle.class, string); + } + + /** + * Test for the url generated based on the server config + */ + @Test + public void testCustomUrlExtension() { + final String expected = ""; + + final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setPetName(new StringType("myName")); + + final IParser xmlParser = ourCtx.newXmlParser(); + xmlParser.setServerBaseUrl("http://www.example.com"); + + final String parsedPatient = xmlParser.encodeResourceToString(patient); + System.out.println(parsedPatient); + assertEquals(expected, parsedPatient); + + // Parse with string + MyPatientWithCustomUrlExtension newPatient = xmlParser.parseResource(MyPatientWithCustomUrlExtension.class, parsedPatient); + assertEquals("myName", newPatient.getPetName().getValue()); + + // Parse with stream + newPatient = xmlParser.parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); + assertEquals("myName", newPatient.getPetName().getValue()); + + // Check no NPE if base server not configure + newPatient = ourCtx.newXmlParser().parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); + assertNull("myName", newPatient.getPetName().getValue()); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + } + + @Test + public void testCustomUrlExtensioninBundle() { + final String expected = ""; + + final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setPetName(new StringType("myName")); + + final Bundle bundle = new Bundle(); + final Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent(); + entry.setResource(patient); + bundle.addEntry(entry); + + final IParser xmlParser = ourCtx.newXmlParser(); + xmlParser.setServerBaseUrl("http://www.example.com"); + + final String parsedBundle = xmlParser.encodeResourceToString(bundle); + System.out.println(parsedBundle); + assertEquals(expected, parsedBundle); + + // Parse with string + Bundle newBundle = xmlParser.parseResource(Bundle.class, parsedBundle); + assertNotNull(newBundle); + assertEquals(1, newBundle.getEntry().size()); + Patient newPatient = (Patient) newBundle.getEntry().get(0).getResource(); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + + // Parse with stream + newBundle = xmlParser.parseResource(Bundle.class, new StringReader(parsedBundle)); + assertNotNull(newBundle); + assertEquals(1, newBundle.getEntry().size()); + newPatient = (Patient) newBundle.getEntry().get(0).getResource(); + assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); + + } + + @Test + public void testDuration() { + Encounter enc = new Encounter(); + Duration duration = new Duration(); + duration.setUnit("day").setValue(123L); + enc.setLength(duration); + + String str = ourCtx.newXmlParser().encodeResourceToString(enc); + ourLog.info(str); + + assertThat(str, not(containsString("meta"))); + assertThat(str, containsString("")); + } + + @Test + public void testEncodeAndParseBundleWithResourceRefs() { + + Patient pt = new Patient(); + pt.setId("patid"); + pt.addName().setFamily("PATIENT"); + + Organization org = new Organization(); + org.setId("orgid"); + org.setName("ORG"); + pt.getManagingOrganization().setResource(org); + + Bundle bundle = new Bundle(); + bundle.addEntry().setResource(pt); + bundle.addEntry().setResource(org); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "")); + + bundle = ourCtx.newXmlParser().parseResource(Bundle.class, encoded); + pt = (Patient) bundle.getEntry().get(0).getResource(); + org = (Organization) bundle.getEntry().get(1).getResource(); + + assertEquals("Organization/orgid", org.getIdElement().getValue()); + assertEquals("Organization/orgid", pt.getManagingOrganization().getReferenceElement().getValue()); + assertSame(org, pt.getManagingOrganization().getResource()); + } + + @Test + public void testEncodeAndParseCompositeExtension() { + PatientWithCustomCompositeExtension pat = new PatientWithCustomCompositeExtension(); + pat.setId("123"); + pat.setFooParentExtension(new PatientWithCustomCompositeExtension.FooParentExtension()); + pat.getFooParentExtension().setChildA(new StringType("ValueA")); + pat.getFooParentExtension().setChildB(new StringType("ValueB")); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat); + ourLog.info(enc); + + pat = ourCtx.newXmlParser().parseResource(PatientWithCustomCompositeExtension.class, enc); + + assertEquals("ValueA", pat.getFooParentExtension().getChildA().getValue()); + assertEquals("ValueB", pat.getFooParentExtension().getChildB().getValue()); + } + + @Test + public void testEncodeAndParseContained() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + + // Create a bundle with just the patient resource + Bundle b = new Bundle(); + b.addEntry().setResource(patient); + + // Encode the bundle + encoded = xmlParser.encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + // Re-parse the bundle + patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReference()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getIdElement().getValue()); + assertEquals("Contained Test Organization", org.getName()); + + // And re-encode a second time + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared + patient.getContained().clear(); + patient.getManagingOrganization().setReference((String) null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().clear(); + patient.getManagingOrganization().setReference((String) null); + patient.getManagingOrganization().getResource().setId(("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + + } + + @Test + public void testEncodeAndParseContainedCustomTypes() { + ourCtx = FhirContext.forDstu3(); + ourCtx.setDefaultTypeForProfile(CustomObservation.PROFILE, CustomObservation.class); + ourCtx.setDefaultTypeForProfile(CustomDiagnosticReport.PROFILE, CustomDiagnosticReport.class); + + CustomObservation obs = new CustomObservation(); + obs.setStatus(Observation.ObservationStatus.FINAL); + + CustomDiagnosticReport dr = new CustomDiagnosticReport(); + dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL); + dr.addResult().setResource(obs); + + IParser parser = ourCtx.newXmlParser(); + parser.setPrettyPrint(true); + + String output = parser.encodeResourceToString(dr); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + /* + * Now PARSE! + */ + + dr = (CustomDiagnosticReport) parser.parseResource(output); + assertEquals(DiagnosticReport.DiagnosticReportStatus.FINAL, dr.getStatus()); + + assertEquals("#1", dr.getResult().get(0).getReference()); + obs = (CustomObservation) dr.getResult().get(0).getResource(); + assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus()); + + ourCtx = null; + } + + @Test + public void testEncodeAndParseContainedNonCustomTypes() { + ourCtx = FhirContext.forDstu3(); + + Observation obs = new Observation(); + obs.setStatus(Observation.ObservationStatus.FINAL); + + DiagnosticReport dr = new DiagnosticReport(); + dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL); + dr.addResult().setResource(obs); + + IParser parser = ourCtx.newXmlParser(); + parser.setPrettyPrint(true); + + String output = parser.encodeResourceToString(dr); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + /* + * Now PARSE! + */ + + dr = (DiagnosticReport) parser.parseResource(output); + assertEquals(DiagnosticReport.DiagnosticReportStatus.FINAL, dr.getStatus()); + + assertEquals("#1", dr.getResult().get(0).getReference()); + obs = (Observation) dr.getResult().get(0).getResource(); + assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus()); + + ourCtx = null; + } + + @Test + public void testEncodeAndParseExtensionOnCode() { + Organization o = new Organization(); + o.setName("ORG"); + o.addExtension(new Extension("urn:foo", new CodeType("acode"))); + + String str = ourCtx.newXmlParser().encodeResourceToString(o); + ourLog.info(str); + assertThat(str, containsString("")); + + o = ourCtx.newXmlParser().parseResource(Organization.class, str); + + List exts = o.getExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + CodeType code = (CodeType) exts.get(0).getValue(); + assertEquals("acode", code.getValue()); + + } + + @Test + public void testEncodeAndParseExtensionOnReference() { + DataElement de = new DataElement(); + ElementDefinition.ElementDefinitionBindingComponent b = de.addElement().getBinding(); + b.setDescription("BINDING"); + + Organization o = new Organization(); + o.setName("ORG"); + b.addExtension(new Extension("urn:foo", new Reference(o))); + + String str = ourCtx.newXmlParser().encodeResourceToString(de); + ourLog.info(str); + + de = ourCtx.newXmlParser().parseResource(DataElement.class, str); + b = de.getElement().get(0).getBinding(); + assertEquals("BINDING", b.getDescription()); + + List exts = b.getExtensionsByUrl("urn:foo"); + assertEquals(1, exts.size()); + Reference rr = (Reference) exts.get(0).getValue(); + o = (Organization) rr.getResource(); + assertEquals("ORG", o.getName()); + + } + + @Test + public void testEncodeAndParseExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + patient.addExtension(ext); + + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child1); + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2")); + parent.addExtension(child2); + + Extension modExt = new Extension(); + modExt.setUrl("http://example.com/extensions#modext"); + modExt.setValue(new DateType("1995-01-02")); + patient.addModifierExtension(modExt); + + HumanName name = patient.addName(); + name.setFamily("Blah"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.addExtension(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + given2ext.addExtension(new Extension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"))); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + + /* + * Now parse this back + */ + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + ext = parsed.getExtension().get(0); + assertEquals("http://example.com/extensions#someext", ext.getUrl()); + assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString()); + + parent = patient.getExtension().get(1); + assertEquals("http://example.com#parent", parent.getUrl()); + assertNull(parent.getValue()); + child1 = parent.getExtension().get(0); + assertEquals("http://example.com#child", child1.getUrl()); + assertEquals("value1", ((StringType) child1.getValue()).getValueAsString()); + child2 = parent.getExtension().get(1); + assertEquals("http://example.com#child", child2.getUrl()); + assertEquals("value2", ((StringType) child2.getValue()).getValueAsString()); + + modExt = parsed.getModifierExtension().get(0); + assertEquals("http://example.com/extensions#modext", modExt.getUrl()); + assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString()); + + name = parsed.getName().get(0); + + ext2 = name.getGiven().get(0).getExtension().get(0); + assertEquals("http://examples.com#givenext", ext2.getUrl()); + assertEquals("given", ((StringType) ext2.getValue()).getValueAsString()); + + given2ext = name.getGiven().get(1).getExtension().get(0); + assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); + assertNull(given2ext.getValue()); + Extension given2ext2 = given2ext.getExtension().get(0); + assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); + assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue()); + + } + + /** + * See #216 + */ + @Test + public void testEncodeAndParseIdentifierDstu2() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + Patient patient = new Patient(); + patient.addIdentifier().setSystem("SYS").setValue("VAL").setType(new CodeableConcept().addCoding(new Coding().setSystem("http://hl7.org/fhir/v2/0203").setCode("MR"))); + + String out = xmlParser.encodeResourceToString(patient); + ourLog.info(out); + + assertThat(out, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + patient = ourCtx.newXmlParser().parseResource(Patient.class, out); + assertEquals("http://hl7.org/fhir/v2/0203", patient.getIdentifier().get(0).getType().getCoding().get(0).getSystem()); + assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode()); + } + + private Matcher stringContainsInOrder(java.lang.String... substrings) { + return Matchers.stringContainsInOrder(Arrays.asList(substrings)); + } + + private Matcher stringContainsInOrder(List substrings) { + return Matchers.stringContainsInOrder(substrings); + } + + /** + * See #347 + */ + @Test + public void testEncodeAndParseMedicationRequest() { + MedicationRequest mo = new MedicationRequest(); + mo.getAuthoredOnElement().setValueAsString("2015-10-05"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(mo); + ourLog.info(encoded); + + mo = ourCtx.newXmlParser().parseResource(MedicationRequest.class, encoded); + assertEquals("2015-10-05", mo.getAuthoredOnElement().getValueAsString()); + } + + @Test + public void testEncodeAndParseMetaProfileAndTags() { + Patient p = new Patient(); + p.addName().setFamily("FAMILY"); + + p.getMeta().addProfile("http://foo/Profile1"); + p.getMeta().addProfile("http://foo/Profile2"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1"); + p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2"); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + List gotLabels = parsed.getMeta().getProfile(); + assertEquals(2, gotLabels.size()); + UriType label = gotLabels.get(0); + assertEquals("http://foo/Profile1", label.getValue()); + label = gotLabels.get(1); + assertEquals("http://foo/Profile2", label.getValue()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + + tagList = parsed.getMeta().getSecurity(); + assertEquals(2, tagList.size()); + assertEquals("sec_scheme1", tagList.get(0).getSystem()); + assertEquals("sec_term1", tagList.get(0).getCode()); + assertEquals("sec_label1", tagList.get(0).getDisplay()); + assertEquals("sec_scheme2", tagList.get(1).getSystem()); + assertEquals("sec_term2", tagList.get(1).getCode()); + assertEquals("sec_label2", tagList.get(1).getDisplay()); + } + + @Test + public void testEncodeAndParseMetaProfiles() { + Patient p = new Patient(); + p.addName().setFamily("FAMILY"); + + p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1"); + p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2"); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + assertThat(parsed.getMeta().getProfile(), empty()); + + List tagList = parsed.getMeta().getTag(); + assertEquals(2, tagList.size()); + assertEquals("scheme1", tagList.get(0).getSystem()); + assertEquals("term1", tagList.get(0).getCode()); + assertEquals("label1", tagList.get(0).getDisplay()); + assertEquals("scheme2", tagList.get(1).getSystem()); + assertEquals("term2", tagList.get(1).getCode()); + assertEquals("label2", tagList.get(1).getDisplay()); + } + + /** + * See #336 + */ + @Test + public void testEncodeAndParseNullPrimitiveWithExtensions() { + + Patient p = new Patient(); + p.setId("patid"); + HumanName name = p.addName(); + name.addGivenElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0"))); + name.addGivenElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id")); + name.addGivenElement(); // this one shouldn't get encoded + name.addGivenElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3"))); + name.setId("nameid"); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p); + String expected = ""; + + ourLog.info("Expected: {}", expected); + ourLog.info("Actual : {}", output); + + assertEquals(expected, output); + + p = ourCtx.newXmlParser().parseResource(Patient.class, output); + assertEquals("patid", p.getIdElement().getIdPart()); + + name = p.getName().get(0); + assertEquals("nameid", name.getId()); + assertEquals(3, name.getGiven().size()); + + assertEquals(null, name.getGiven().get(0).getValue()); + assertEquals("V1", name.getGiven().get(1).getValue()); + assertEquals(null, name.getGiven().get(2).getValue()); + + assertEquals("f0", name.getGiven().get(0).getId()); + assertEquals("f1", name.getGiven().get(1).getId()); + assertEquals(null, name.getGiven().get(2).getId()); + + assertEquals(1, name.getGiven().get(0).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl()); + assertEquals("FOOEXT0", ((StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(1).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl()); + assertEquals("FOOEXT1", ((StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue()); + assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId()); + + assertEquals(1, name.getGiven().get(2).getExtension().size()); + assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl()); + assertEquals("FOOEXT3", ((StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue()); + assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId()); + + } + + @Test + public void testEncodeAndParseProfiledDatatype() { + MedicationRequest mo = new MedicationRequest(); + mo.addDosageInstruction().getTiming().getRepeat().setBounds(new Duration().setCode("code")); + String out = ourCtx.newXmlParser().encodeResourceToString(mo); + ourLog.info(out); + assertThat(out, containsString("")); + + mo = ourCtx.newXmlParser().parseResource(MedicationRequest.class, out); + Duration duration = (Duration) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds(); + assertEquals("code", duration.getCode()); + } + + /** + * See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name + */ + @Test + public void testEncodeAndParseProfiledDatatypeChoice() throws Exception { + IParser xmlParser = ourCtx.newXmlParser(); + + MedicationStatement ms = new MedicationStatement(); + ms.addDosage().setDose(new SimpleQuantity().setValue(123)); + + String output = xmlParser.encodeResourceToString(ms); + assertThat(output, containsString("")); + } + + @Test + public void testEncodeAndParseSecurityLabels() { + Patient p = new Patient(); + p.addName().setFamily("FAMILY"); + + List labels = new ArrayList(); + labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1")); + labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2")); + p.getMeta().getSecurity().addAll(labels); + + String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(enc); + + assertThat(enc, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); + List gotLabels = parsed.getMeta().getSecurity(); + + assertEquals(2, gotLabels.size()); + + Coding label = gotLabels.get(0); + assertEquals("SYSTEM1", label.getSystem()); + assertEquals("CODE1", label.getCode()); + assertEquals("DISPLAY1", label.getDisplay()); + assertEquals("VERSION1", label.getVersion()); + + label = gotLabels.get(1); + assertEquals("SYSTEM2", label.getSystem()); + assertEquals("CODE2", label.getCode()); + assertEquals("DISPLAY2", label.getDisplay()); + assertEquals("VERSION2", label.getVersion()); + } + + /** + * See #103 + */ + @Test + public void testEncodeAndReEncodeContainedJson() { + Composition comp = new Composition(); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section0_Allergy0"))); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section1_Allergy0"))); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section2_Allergy0"))); + + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + + String string = parser.encodeResourceToString(comp); + ourLog.info(string); + + Composition parsed = parser.parseResource(Composition.class, string); + parsed.getSection().remove(0); + + string = parser.encodeResourceToString(parsed); + ourLog.info(string); + + parsed = parser.parseResource(Composition.class, string); + assertEquals(2, parsed.getContained().size()); + } + + /** + * See #103 + */ + @Test + public void testEncodeAndReEncodeContainedXml() { + Composition comp = new Composition(); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section0_Allergy0"))); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section1_Allergy0"))); + comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section2_Allergy0"))); + + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + + String string = parser.encodeResourceToString(comp); + ourLog.info(string); + + Composition parsed = parser.parseResource(Composition.class, string); + parsed.getSection().remove(0); + + string = parser.encodeResourceToString(parsed); + ourLog.info(string); + + parsed = parser.parseResource(Composition.class, string); + assertEquals(2, parsed.getContained().size()); + } + + @Test + public void testEncodeBinaryWithNoContentType() { + Binary b = new Binary(); + b.setContent(new byte[]{1, 2, 3, 4}); + + String output = ourCtx.newXmlParser().encodeResourceToString(b); + ourLog.info(output); + + assertEquals("", output); + } + + @Test + public void testEncodeBinaryWithSecurityContext() { + Binary bin = new Binary(); + bin.setContentType("text/plain"); + bin.setContent("Now is the time".getBytes()); + Reference securityContext = new Reference(); + securityContext.setReference("DiagnosticReport/1"); + bin.setSecurityContext(securityContext); + String encoded = ourCtx.newXmlParser().encodeResourceToString(bin); + ourLog.info(encoded); + assertThat(encoded, containsString("Binary")); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + } + + @Test + public void testEncodeBundleWithContained() { + DiagnosticReport rpt = new DiagnosticReport(); + rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Sharp1")).setId("#1")); + rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Uuid1")).setId("urn:uuid:UUID1")); + + Bundle b = new Bundle(); + b.addEntry().setResource(rpt); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResources() { + + MedicationRequest medicationPrescript = new MedicationRequest(); + + String medId = "123"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding().setSystem("urn:sys").setCode("code1")); + + // Adding medication to Contained. + Medication medResource = new Medication(); + medResource.setCode(codeDt); + medResource.setId("#" + String.valueOf(medId)); + medicationPrescript.getContained().add(medResource); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference("#" + medId); + medRefDt.setDisplay("MedRef"); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + // @formatter:on + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResourcesAutomatic() { + + MedicationRequest medicationPrescript = new MedicationRequest(); + String nameDisp = "MedRef"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null)); + + // Adding medication to Contained. + Medication medResource = new Medication(); + // No ID set + medResource.setCode(codeDt); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference(); + medRefDt.setDisplay(nameDisp); + // Resource reference set, but no ID + medRefDt.setResource(medResource); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + + } + + /** + * See #113 + */ + @Test + public void testEncodeContainedResourcesManualContainUsingNonLocalId() { + + MedicationRequest medicationPrescript = new MedicationRequest(); + + String medId = "123"; + CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null)); + + // Adding medication to Contained. + Medication medResource = new Medication(); + medResource.setCode(codeDt); + medResource.setId(String.valueOf(medId)); // ID does not start with '#' + medicationPrescript.getContained().add(medResource); + + // Medication reference. This should point to the contained resource. + Reference medRefDt = new Reference("#" + medId); + medRefDt.setDisplay("MedRef"); + medicationPrescript.setMedication(medRefDt); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = p.encodeResourceToString(medicationPrescript); + ourLog.info(encoded); + + assertThat(encoded, + stringContainsInOrder("", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "")); + + } + + @Test + public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getNameElement().setValue("Contained Test Organization"); + org.getText().setDivAsString("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getText().setDivAsString("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder("", "
BARFOO
", "", "", "", "")); + assertThat(encode, stringContainsInOrder("\n\n

A P TAG

line1\nline2\nline3  BOLD

"); + + String output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "A P TAG

", + "

line1\nline2\nline3  BOLD
")); + + } + + @Test + public void testEncodeDivWithPrePrettyPrint() { + + Patient p = new Patient(); + p.getText().setDivAsString("
\n\n

A P TAG

line1\nline2\nline3  BOLD

"); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + " ", + " line1\nline2\nline3 BOLD")); + + } + + @Test + public void testEncodeDoesntIncludeUuidId() { + Patient p = new Patient(); + p.setId(new IdType("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2")); + p.addIdentifier().setSystem("ACME"); + + String actual = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + assertThat(actual, not(containsString("78ef6f64c2f2"))); + } + + @Test + public void testEncodeEmptyBinary() { + String output = ourCtx.newXmlParser().encodeResourceToString(new Binary()); + assertEquals("", output); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding()); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, not(containsString("tag"))); + } + + /** + * #158 + */ + @Test + public void testEncodeEmptyTag2() { + ArrayList tagList = new ArrayList(); + tagList.add(new Coding().setSystem("scheme").setCode("code")); + tagList.add(new Coding().setDisplay("Label")); + + Patient p = new Patient(); + p.getMeta().getTag().addAll(tagList); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + assertThat(encoded, containsString("tag")); + assertThat(encoded, containsString("scheme")); + assertThat(encoded, not(containsString("Label"))); + } + + @Test + public void testEncodeExtensionOnRoot() { + Patient p = new Patient(); + p.setId("Patient/B"); + p + .addExtension() + .setUrl("http://foo") + .setValue(new Reference("Practitioner/A")); + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + parser.setDontEncodeElements(new HashSet(Arrays.asList("*.id", "*.meta"))); + + String encoded = parser.encodeResourceToString(p); + ourLog.info(encoded); + + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("Practitioner/A")); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifier() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl").setValue(new StringType("ext_url_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "")); + assertThat(output, not(stringContainsInOrder( + ""))); + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals("ext_url_value", ((StringType) obs.getExtension().get(0).getValue()).getValue()); + } + + @Test + public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() { + Observation obs = new Observation(); + obs.setId("1"); + obs.getMeta().addProfile("http://profile"); + Extension ext = obs.addExtension(); + ext.setUrl("http://exturl"); + + Extension subExt = ext.addExtension(); + subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value")); + + obs.getCode().setText("CODE"); + + IParser parser = ourCtx.newXmlParser(); + + String output = parser.setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "")); + assertThat(output, not(stringContainsInOrder( + ""))); + + obs = parser.parseResource(Observation.class, output); + assertEquals(1, obs.getExtension().size()); + assertEquals("http://exturl", obs.getExtension().get(0).getUrl()); + assertEquals(1, obs.getExtension().get(0).getExtension().size()); + assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl()); + assertEquals("sub_ext_value", ((StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue()); + } + + /** + * See #327 + */ + @Test + public void testEncodeExtensionWithContainedResource() { + + TestPatientFor327 patient = new TestPatientFor327(); + patient.setBirthDateElement(new DateType("2016-04-14")); + + List conditions = new ArrayList(); + Condition condition = new Condition(); + condition.addBodySite().setText("BODY SITE"); + conditions.add(new Reference(condition)); + patient.setCondition(conditions); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + } + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(Address.AddressUse.HOME); + patient.addExtension(new Extension("urn:foo", new Reference("Organization/123"))); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + List ext = actual.getExtension(); + assertEquals(1, ext.size()); + Reference ref = (Reference) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReference()); + + } + + @Test + public void testEncodeHistoryEncodeVersionsAtPath3() { + ourCtx = FhirContext.forDstu3(); + + assertNull(ourCtx.newXmlParser().getStripVersionsFromReferences()); + + AuditEvent auditEvent = new AuditEvent(); + auditEvent.addEntity().setReference(new Reference("http://foo.com/Organization/2/_history/1")); + + IParser parser = ourCtx.newXmlParser(); + + parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference"); + String enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList()); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths((String[]) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + parser.setDontStripVersionsFromReferencesAtPaths((List) null); + enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent); + ourLog.info(enc); + assertThat(enc, containsString("")); + + } + + @Test + public void testEncodeNarrativeSuppressed() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", + "", "")); + assertThat(encoded, not(containsString("text"))); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, containsString("maritalStatus")); + } + + @Test + public void testEncodeNonContained() { + // Create an organization + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getNameElement().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier().setSystem("urn:mrns").setValue("253345"); + patient.getManagingOrganization().setResource(org); + + // Create a list containing both resources. In a server method, you might just + // return this list, but here we will create a bundle to encode. + List resources = new ArrayList(); + resources.add(org); + resources.add(patient); + + // Create a bundle with both + Bundle b = new Bundle(); + b.addEntry().setResource(org); + b.addEntry().setResource(patient); + + // Encode the buntdle + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, stringContainsInOrder("", "")); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder("", "
")); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, containsString("")); + + } + + /** + * See #312 + */ + @Test + public void testEncodeNullElement() { + Patient patient = new Patient(); + patient.addName().getGiven().add(null); + + IParser parser = ourCtx.newXmlParser(); + String xml = parser.encodeResourceToString(patient); + + ourLog.info(xml); + assertEquals("", xml); + } + + /** + * See #312 + */ + @Test + public void testEncodeNullExtension() { + Patient patient = new Patient(); + patient.getExtension().add(null); // Purposely add null + patient.getModifierExtension().add(null); // Purposely add null + patient.getExtension().add(new Extension("http://hello.world", new StringType("Hello World"))); + patient.getName().add(null); + patient.addName().getGiven().add(null); + + IParser parser = ourCtx.newXmlParser(); + String xml = parser.encodeResourceToString(patient); + + ourLog.info(xml); + assertEquals("", xml); + } + + @Test + public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() { + + Patient patient = new Patient(); + patient.setId("phitcc_pat_normal"); + patient.addName().addGiven("Patty").setUse(HumanName.NameUse.NICKNAME); + patient.addTelecom().setSystem(ContactPoint.ContactPointSystem.EMAIL).setValue("patpain@ehealthinnovation.org"); + patient.setGender(Enumerations.AdministrativeGender.FEMALE); + patient.setBirthDateElement(new DateType("2001-10-13")); + + DateTimeType obsEffectiveTime = new DateTimeType("2015-04-11T12:22:01-04:00"); + + Observation obsParent = new Observation(); + obsParent.setId("phitcc_obs_bp_parent"); + obsParent.getSubject().setResource(patient); + obsParent.setStatus(Observation.ObservationStatus.FINAL); + obsParent.setEffective(obsEffectiveTime); + + Observation obsSystolic = new Observation(); + obsSystolic.setId("phitcc_obs_bp_dia"); + obsSystolic.getSubject().setResource(patient); + obsSystolic.setEffective(obsEffectiveTime); + obsParent.addRelated().setType(Observation.ObservationRelationshipType.HASMEMBER).setTarget(new Reference(obsSystolic)); + + Observation obsDiastolic = new Observation(); + obsDiastolic.setId("phitcc_obs_bp_dia"); + obsDiastolic.getSubject().setResource(patient); + obsDiastolic.setEffective(obsEffectiveTime); + obsParent.addRelated().setType(Observation.ObservationRelationshipType.HASMEMBER).setTarget(new Reference(obsDiastolic)); + + String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(obsParent); + ourLog.info(str); + + assertThat(str, containsString("")); + assertThat(str, containsString("")); + } + + @Test + public void testEncodeReferenceWithUuid() { + + Practitioner pract = new Practitioner(); + pract.setId(IdType.newRandomUuid()); + pract.addName().setFamily("PRACT FAMILY"); + + Patient patient = new Patient(); + patient.addGeneralPractitioner().setResource(pract); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(pract.getId(), startsWith("urn:uuid:")); + assertThat(encoded, containsString("")); + } + + @Test + public void testEncodeSummary() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", + "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeSummary2() { + Patient patient = new Patient(); + patient.setId("Patient/1/_history/1"); + patient.getText().setDivAsString("
THE DIV
"); + patient.addName().setFamily("FAMILY"); + patient.setMaritalStatus(new CodeableConcept().addCoding(new Coding().setCode("D"))); + + patient.getMeta().addTag().setSystem("foo").setCode("bar"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient); + ourLog.info(encoded); + + assertThat(encoded, containsString("", "", "", "")); + assertThat(encoded, stringContainsInOrder("", "", + "", "")); + assertThat(encoded, not(containsString("THE DIV"))); + assertThat(encoded, containsString("family")); + assertThat(encoded, not(containsString("maritalStatus"))); + } + + @Test + public void testEncodeUndeclaredBlock() throws Exception { + FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent(); + source.getMessageHeaderApplicationId().setValue("APPID"); + source.setName("NAME"); + + FooMessageHeader header = new FooMessageHeader(); + header.setSource(source); + + header.addDestination().setName("DEST"); + + Bundle bundle = new Bundle(); + bundle.addEntry().setResource(header); + + IParser p = ourCtx.newXmlParser(); + p.setPrettyPrint(true); + + String encode = p.encodeResourceToString(bundle); + ourLog.info(encode); + + assertThat(encode, containsString("")); + assertThat(encode, stringContainsInOrder(" fact = new Address.AddressUseEnumFactory(); + PrimitiveType enumeration = new Enumeration(fact).setValue(Address.AddressUse.HOME); + patient.addExtension().setUrl("urn:foo").setValue(enumeration); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + MyPatientWithOneDeclaredEnumerationExtensionDstu3 actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtensionDstu3.class, val); + assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse()); + Enumeration ref = actual.getFoo(); + assertEquals("home", ref.getValue().toCode()); + + } + + @Test + public void testEncodeWithContained() { + List contained = new ArrayList(); + + // Will be added by reference + Patient p = new Patient(); + p.setId("#" + "1000"); + contained.add(p); + + // Will be added by direct resource object + Location l = new Location(); + l.setId("#" + "1001"); + contained.add(l); + + // Will not be referred to (and therefore shouldn't appear in output) + Location l2 = new Location(); + l2.setId("#1002"); + contained.add(l2); + + Appointment appointment = new Appointment(); + appointment.setId("1234"); + appointment.getContained().addAll(contained); + + appointment.addParticipant().getActor().setReference("#1000"); + appointment.addParticipant().getActor().setResource(l); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(appointment); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + assertThat(encoded, not(containsString("#1002"))); + } + + @Test + public void testEncodeWithDontEncodeElements() throws Exception { + Patient patient = new Patient(); + patient.setId("123"); + patient.getMeta().addProfile("http://profile"); + patient.addName().setFamily("FAMILY").addGiven("GIVEN"); + patient.addAddress().addLine("LINE1"); + + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.name.family")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("GIVEN")); + assertThat(out, not(containsString("FAMILY"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id")); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("address")); + assertThat(out, not(containsString("id"))); + assertThat(out, not(containsString("meta"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setDontEncodeElements(Sets.newHashSet("Patient.meta")); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(patient); + ourLog.info(out); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, containsString("id")); + assertThat(out, not(containsString("address"))); + assertThat(out, not(containsString("meta"))); + } + } + + @Test + public void testEncodeWithEncodeElements() throws Exception { + Patient patient = new Patient(); + patient.getMeta().addProfile("http://profile"); + patient.addName().setFamily("FAMILY"); + patient.addAddress().addLine("LINE1"); + + Bundle bundle = new Bundle(); + bundle.setTotal(100); + bundle.addEntry().setResource(patient); + + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name", "Bundle.entry"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, not(containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, not(containsString("address"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet(Arrays.asList("Patient.name"))); + p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, (containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, not(containsString("address"))); + } + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet(Arrays.asList("Patient"))); + p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient"))); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, (containsString("total"))); + assertThat(out, (containsString("Patient"))); + assertThat(out, (containsString("name"))); + assertThat(out, (containsString("address"))); + } + + } + + @Test + public void testEncodeWithEncodeElementsAppliesToChildResourcesOnly() throws Exception { + Patient patient = new Patient(); + patient.getMeta().addProfile("http://profile"); + patient.addName().setFamily("FAMILY"); + patient.addAddress().addLine("LINE1"); + + Bundle bundle = new Bundle(); + bundle.setTotal(100); + bundle.addEntry().setResource(patient); + + { + IParser p = ourCtx.newXmlParser(); + p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name"))); + p.setEncodeElementsAppliesToChildResourcesOnly(true); + p.setPrettyPrint(true); + String out = p.encodeResourceToString(bundle); + ourLog.info(out); + assertThat(out, containsString("total")); + assertThat(out, containsString("Patient")); + assertThat(out, containsString("name")); + assertThat(out, not(containsString("address"))); + } + } + + /** + * Test for the url generated based on the server config + */ + @Test + public void testGeneratedUrls() { + final IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + xmlParser.setServerBaseUrl("http://myserver.com"); + + final CustomPatientDstu3 patient = new CustomPatientDstu3(); + patient.setHomeless(new BooleanType(true)); + + final String parsedPatient = xmlParser.encodeResourceToString(patient); + + assertTrue(parsedPatient.contains("")); + assertTrue(parsedPatient.contains("")); + } + + @Test + public void testMoreExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135"); + + Extension ext = new Extension(); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeType("2011-01-02T11:13:15")); + + // Add the extension to the resource + patient.addExtension(ext); + // END SNIPPET: resourceExtension + + // START SNIPPET: resourceStringExtension + HumanName name = patient.addName(); + name.setFamily("Shmoe"); + StringType given = name.addGivenElement(); + given.setValue("Joe"); + Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given")); + given.addExtension(ext2); + + StringType given2 = name.addGivenElement(); + given2.setValue("Shmoe"); + Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent"); + given2.addExtension(given2ext); + Extension givenExtChild = new Extension(); + givenExtChild.setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")); + given2ext.addExtension(givenExtChild); + // END SNIPPET: resourceStringExtension + + // START SNIPPET: subExtension + Extension parent = new Extension().setUrl("http://example.com#parent"); + patient.addExtension(parent); + + Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child1); + + Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1")); + parent.addExtension(child2); + // END SNIPPET: subExtension + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + assertThat(enc, containsString("")); + assertThat(enc, containsString( + "")); + } + + @Test + public void testOmitResourceId() { + Patient p = new Patient(); + p.setId("123"); + p.addName().setFamily("ABC"); + + assertThat(ourCtx.newXmlParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC")); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC")); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() { + try { + String tmp = ""; + ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false); + Bundle bundle = (Bundle) ourCtx.newXmlParser().parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = null; + } + } + + @Test + public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() { + try { + String tmp = ""; + Bundle bundle = (Bundle) ourCtx.newXmlParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp); + assertEquals(1, bundle.getEntry().size()); + { + Patient o1 = (Patient) bundle.getEntry().get(0).getResource(); + IIdType o1Id = o1.getIdElement(); + assertFalse(o1Id.hasBaseUrl()); + assertEquals("Patient", o1Id.getResourceType()); + assertEquals("patxuzos", o1Id.getIdPart()); + assertFalse(o1Id.hasVersionIdPart()); + } + } finally { + // ensure we cleanup ourCtx so other tests continue to work + ourCtx = null; + } + } + + @Test + public void testParseAndEncodeComments() { + String input = "\n" + + " " + + " \n" + + " \n" + + " \n" + + "
\n" + + "\n" + + "

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

\n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " " + + "
"; + + Patient res = ourCtx.newXmlParser().parseResource(Patient.class, input); + res.getFormatCommentsPre(); + assertEquals("Patient/pat1", res.getId()); + assertEquals("654321", res.getIdentifier().get(0).getValue()); + assertEquals(true, res.getActive()); + + assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment")); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "\"identifier\": [", + "{", + "\"fhir_comments\":", + "[", + "\"identifier comment 1\"", + ",", + "\"identifier comment 2\"", + "]", + "\"use\": \"usual\",", + "\"_use\": {", + "\"fhir_comments\":", + "[", + "\"use comment 1\"", + ",", + "\"use comment 2\"", + "]", + "},", + "\"type\"")); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "
", + "

Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321

", + "
", + "
", + " \n", + " ", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "
")); + + } + + @Test + public void testParseAndEncodeCommentsOnExtensions() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient pat = ourCtx.newXmlParser().parseResource(Patient.class, input); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "")); + + output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(pat); + ourLog.info(output); + + assertThat(output, stringContainsInOrder( + "{", + " \"resourceType\": \"Patient\",", + " \"id\": \"someid\",", + " \"_id\": {", + " \"fhir_comments\": [", + " \" comment 1 \"", + " ]", + " },", + " \"extension\": [", + " {", + " \"fhir_comments\": [", + " \" comment 2 \",", + " \" comment 7 \"", + " ],", + " \"url\": \"urn:patientext:att\",", + " \"valueAttachment\": {", + " \"fhir_comments\": [", + " \" comment 3 \",", + " \" comment 6 \"", + " ],", + " \"contentType\": \"aaaa\",", + " \"_contentType\": {", + " \"fhir_comments\": [", + " \" comment 4 \"", + " ]", + " },", + " \"data\": \"AAAA\",", + " \"_data\": {", + " \"fhir_comments\": [", + " \" comment 5 \"", + " ]", + " }", + " }", + " }", + " ]", + "}")); + + } + + @Test + public void testParseAndEncodeExtensionOnReference() { + + String input = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + DataElement de = ourCtx.newXmlParser().parseResource(DataElement.class, input); + String output = ourCtx.newXmlParser().encodeResourceToString(de).replace(" xmlns=\"http://hl7.org/fhir\"", ""); + + ElementDefinition elem = de.getElement().get(0); + ElementDefinition.ElementDefinitionBindingComponent b = elem.getBinding(); + // assertEquals("All codes representing the gender of a person.", b.getDescription()); + + Reference ref = (Reference) b.getValueSet(); + assertEquals("#2179414", ref.getReference()); + + assertEquals(2, ref.getExtension().size()); + Extension ext = ref.getExtension().get(0); + assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset", ext.getUrl()); + assertEquals(Reference.class, ext.getValue().getClass()); + assertEquals("#2179414-permitted", ((Reference) ext.getValue()).getReference()); + assertEquals(ValueSet.class, ((Reference) ext.getValue()).getResource().getClass()); + + ext = ref.getExtension().get(1); + assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-conceptmap", ext.getUrl()); + assertEquals(Reference.class, ext.getValue().getClass()); + assertEquals("#2179414-cm", ((Reference) ext.getValue()).getReference()); + assertEquals(ConceptMap.class, ((Reference) ext.getValue()).getResource().getClass()); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de)); + + assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset")); + + } + + @Test + public void testParseAndEncodeNestedExtensions() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input); + DateType bd = p.getBirthDateElement(); + assertEquals("2005-03-04", bd.getValueAsString()); + + List exts = bd.getExtensionsByUrl("http://my.fancy.extension.url"); + assertEquals(1, exts.size()); + Extension ext = exts.get(0); + assertEquals(null, ext.getValue()); + + exts = ext.getExtensionsByUrl("http://my.fancy.extension.url"); + assertEquals(1, exts.size()); + ext = exts.get(0); + assertEquals("myNestedValue", ((StringType) ext.getValue()).getValue()); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder( + "", + "", + "", + "", + "", + "", + "", + "", + "")); + + } + + @Test + public void testParseBundleNewWithPlaceholderIds() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + } + + @Test + public void testParseBundleNewWithPlaceholderIdsInBase1() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + } + + @Test + public void testParseBundleNewWithPlaceholderIdsInBase2() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); + + } + + @Test + public void testParseBundleOldStyleWithUnknownLinks() throws Exception { + + String bundle = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Bundle b = (Bundle) ourCtx.newXmlParser().parseResource(bundle); + assertEquals(1, b.getEntry().size()); + + } + + @Test + public void testParseBundleOldWithPlaceholderIds() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + Bundle parsed = (Bundle) ourCtx.newXmlParser().parseResource(input); + assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getId()); + + } + + @Test + public void testParseBundleWithBinary() { + // TODO: implement this test, make sure we handle ID and meta correctly in Binary + } + + /** + * See #191 + */ + @Test + public void testParseBundleWithLinksOfUnknownRelation() throws Exception { + String input = IOUtils.toString(Dstu3XmlParserTest.class.getResourceAsStream("/bundle_orion.xml"), StandardCharsets.UTF_8); + Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input); + + Bundle.BundleLinkComponent link = parsed.getLink().get(0); + assertEquals("just trying add link", link.getRelation()); + assertEquals("blarion", link.getUrl()); + + Bundle.BundleEntryComponent entry = parsed.getEntry().get(0); + link = entry.getLink().get(0); + assertEquals("orionhealth.edit", link.getRelation()); + assertEquals("Observation", link.getUrl()); + } + + @Test + public void testParseBundleWithResourceId() { + + String input = "" + + "" + + "" + + "" + + "\n"; + + Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, input); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/3", bundle.getEntry().get(0).getResource().getIdElement().getValue()); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/2", bundle.getEntry().get(1).getResource().getIdElement().getValue()); + assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/1", bundle.getEntry().get(2).getResource().getIdElement().getValue()); + } + + + /** + * Thanks to Alexander Kley! + */ + @Test + public void testParseContainedBinaryResource() { + byte[] bin = new byte[]{0, 1, 2, 3, 4}; + final Binary binary = new Binary(); + binary.setContentType("PatientConsent").setContent(bin); + + DocumentManifest manifest = new DocumentManifest(); + CodeableConcept cc = new CodeableConcept(); + cc.addCoding().setSystem("mySystem").setCode("PatientDocument"); + manifest.setType(cc); + manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString())); + manifest.addContent().setP(new Reference(binary)); + manifest.setStatus(Enumerations.DocumentReferenceStatus.CURRENT); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest); + ourLog.info(encoded); + assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", ""))); + + DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded); + assertEquals(1, actual.getContained().size()); + assertEquals(1, actual.getContent().size()); + + /* + * If this fails, it's possibe the DocumentManifest structure is wrong: It should be + * + * @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true) + */ + assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource()); + } + + /** + * See #426 + */ + @Test + public void testParseExtensionWithIdType() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare"); + extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id"); + Extension ext = extList.get(0); + IdType value = (IdType) ext.getValue(); + assertEquals("mc1", value.getValueAsString()); + } + + /** + * See #426 + *

+ * Value type of FOO isn't a valid datatype + */ + @Test + public void testParseExtensionWithInvalidType() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare"); + extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id"); + Extension ext = extList.get(0); + IdType value = (IdType) ext.getValue(); + assertEquals(null, value); + } + + /** + * See #342 + */ + @Test(expected = DataFormatException.class) + public void testParseInvalid() { + ourCtx.newXmlParser().parseResource("FOO"); + } + + /** + * See #366 + */ + @Test() + public void testParseInvalidBoolean() { + + String resource = "\n" + + " \n" + + ""; + + IParser p = ourCtx.newXmlParser(); + + try { + p.parseResource(resource); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"1\": Invalid boolean string: '1'", e.getMessage()); + } + + LenientErrorHandler errorHandler = new LenientErrorHandler(); + assertEquals(true, errorHandler.isErrorOnInvalidValue()); + errorHandler.setErrorOnInvalidValue(false); + p.setParserErrorHandler(errorHandler); + } + + @Test + public void testParseInvalidTextualNumber() { + Observation obs = new Observation(); + obs.setValue(new Quantity().setValue(1234)); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); + encoded = encoded.replace("1234", "\"1234\""); + ourLog.info(encoded); + ourCtx.newJsonParser().parseResource(encoded); + } + + @Test + public void testParseMetaUpdatedDate() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, input); + + InstantType updated = b.getMeta().getLastUpdatedElement(); + assertEquals("2015-06-22T15:48:57.554-04:00", updated.getValueAsString()); + + } + + @Test + public void testParseMetadata() throws Exception { + + String content = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, content); + assertEquals(1, b.getEntry().size()); + + Bundle.BundleEntryComponent entry = b.getEntry().get(0); + Patient pt = (Patient) entry.getResource(); + assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getIdElement().getValue()); + assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString()); + assertEquals("0.123", entry.getSearch().getScore().toString()); + assertEquals("match", entry.getSearch().getMode().toCode()); + assertEquals("POST", entry.getRequest().getMethod().toCode()); + assertEquals("http://foo/Patient?identifier=value", entry.getRequest().getUrl()); + assertEquals("2001-02-22T09:22:33-07:00", pt.getMeta().getLastUpdatedElement().getValueAsString()); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String reEncoded = p.encodeResourceToString(b); + ourLog.info(reEncoded); + + compareXml(content, reEncoded); + + } + + @Test + public void testParseNestedExtensionsInvalid() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + try { + ourCtx.newXmlParser().parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("Extension (URL='http://my.fancy.extension.url') must not have both a value and other contained extensions")); + } + } + + /** + * See #163 + */ + @Test + public void testParseResourceType() { + IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); + + // Patient + Patient patient = new Patient(); + String patientId = UUID.randomUUID().toString(); + patient.setId(new IdType("Patient", patientId)); + patient.addName().addGiven("John").setFamily("Smith"); + patient.setGender(Enumerations.AdministrativeGender.MALE); + patient.setBirthDateElement(new DateType("1987-04-16")); + + // Bundle + Bundle bundle = new Bundle(); + bundle.setType(Bundle.BundleType.COLLECTION); + bundle.addEntry().setResource(patient); + + String bundleText = xmlParser.encodeResourceToString(bundle); + ourLog.info(bundleText); + + Bundle reincarnatedBundle = xmlParser.parseResource(Bundle.class, bundleText); + Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource(); + + assertEquals("Patient", patient.getIdElement().getResourceType()); + assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType()); + } + + @Test(expected = DataFormatException.class) + public void testParseWithInvalidLocalRef() throws IOException { + String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_invalid_contained_ref.xml"), StandardCharsets.UTF_8); + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(Bundle.class, string); + } + + @Test() + public void testParseWithInvalidLocalRefLenient() throws IOException { + String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_invalid_contained_ref.xml"), StandardCharsets.UTF_8); + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + parser.parseResource(Bundle.class, string); + } + + /** + * If a contained resource refers to a contained resource that comes after it, it should still be successfully + * woven together. + */ + @Test + public void testParseWovenContainedResources() throws IOException { + String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_woven_obs.xml"), StandardCharsets.UTF_8); + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + org.hl7.fhir.dstu3.model.Bundle bundle = parser.parseResource(Bundle.class, string); + + DiagnosticReport resource = (DiagnosticReport) bundle.getEntry().get(0).getResource(); + Observation obs = (Observation) resource.getResult().get(1).getResource(); + assertEquals("#2", obs.getId()); + Reference performerFirstRep = obs.getPerformerFirstRep(); + Practitioner performer = (Practitioner) performerFirstRep.getResource(); + assertEquals("#3", performer.getId()); + } + + /** + * See #414 + */ + @Test + public void testParseXmlExtensionWithoutUrl() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + ""; + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getExtension().size()); + assertEquals(null, parsed.getExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", parsed.getExtension().get(0).getValueAsPrimitive().getValueAsString()); + + try { + parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getCause().getMessage()); + } + + } + + /** + * See #414 + */ + @Test + public void testParseXmlModifierExtensionWithoutUrl() { + + String input = "\n" + + " \n" + + " \n" + + " \n" + + ""; + + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new LenientErrorHandler()); + Patient parsed = (Patient) parser.parseResource(input); + assertEquals(1, parsed.getModifierExtension().size()); + assertEquals(null, parsed.getModifierExtension().get(0).getUrl()); + assertEquals("2011-01-02T11:13:15", parsed.getModifierExtension().get(0).getValueAsPrimitive().getValueAsString()); + + try { + parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + parser.parseResource(input); + fail(); + } catch (DataFormatException e) { + assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getCause().getMessage()); + } + + } + + /** + * See #344 + */ + @Test + public void testParserIsCaseSensitive() { + Observation obs = new Observation(); + SampledData data = new SampledData(); + data.setData("1 2 3"); + data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L)); + data.setPeriod(1000L); + obs.setValue(data); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler()); + String encoded = p.encodeResourceToString(obs); + ourLog.info(encoded); + + p.parseResource(encoded); + + try { + p.parseResource(encoded.replace("Observation", "observation")); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [1,1]]: Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", + e.getMessage()); + } + + try { + p.parseResource(encoded.replace("valueSampledData", "valueSampleddata")); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Unknown element 'valueSampleddata' found during parse", e.getMessage()); + } + } + + /** + * See #551 + */ + @Test + public void testXmlLargeAttribute() { + String largeString = StringUtils.leftPad("", (int) FileUtils.ONE_MB, 'A'); + + Patient p = new Patient(); + p.addName().setFamily(largeString); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + + p = ourCtx.newXmlParser().parseResource(Patient.class, encoded); + + assertEquals(largeString, p.getNameFirstRep().getFamily()); + } + + /** + * See #339 + *

+ * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing + */ + @Test + public void testXxe() { + + String input = "" + + "" + + "]>" + + "" + + "" + + "

TEXT &xxe; TEXT
" + + "" + + "
" + + "" + + "
" + + "
"; + + ourLog.info(input); + + try { + ourCtx.newXmlParser().parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.toString(), containsString("Undeclared general entity")); + } + + } + + public static void compareXml(String content, String reEncoded) { + Diff d = DiffBuilder.compare(Input.fromString(content)) + .withTest(Input.fromString(reEncoded)) + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)) + .checkForSimilar() + .ignoreWhitespace() // this is working with newest Saxon 9.8.0-2 (not worked with 9.7.0-15 + .ignoreComments() // this is not working even with newest Saxon 9.8.0-2 + .withComparisonController(ComparisonControllers.Default) + .build(); + + assertTrue(d.toString(), !d.hasDifferences()); + } + + @ResourceDef(name = "Patient") + public static class TestPatientFor327 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "testCondition") + @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false) + private List testConditions = null; + + public List getConditions() { + return this.testConditions; + } + + public void setCondition(List ref) { + this.testConditions = ref; + } + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java new file mode 100644 index 00000000000..84b8ceaf4ae --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java @@ -0,0 +1,46 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.MessageHeader; +import org.hl7.fhir.exceptions.FHIRException; + +@ResourceDef(name = "MessageHeader") +public class FooMessageHeader extends MessageHeader { + + private static final long serialVersionUID = 1L; + + @Block() + public static class FooMessageSourceComponent extends MessageSourceComponent { + + private static final long serialVersionUID = 1L; + @Child(name = "ext-messageheader-application-id", type = Identifier.class, modifier = true) + @Description(shortDefinition = "Message Header Application ID") + @Extension(url = "http://foo", definedLocally = false, isModifier = false) + private Identifier messageHeaderApplicationId; + + /* + * Get messageHeaderApplicationId + */ + public Identifier getMessageHeaderApplicationId() throws FHIRException { + + if (messageHeaderApplicationId == null) { + messageHeaderApplicationId = new Identifier(); + } + return messageHeaderApplicationId; + } + + /* + * Set messageHeaderApplicationId + */ + public void setmessageHeaderApplicationId(Identifier messageHeaderApplicationId) { + this.messageHeaderApplicationId = messageHeaderApplicationId; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java new file mode 100644 index 00000000000..97714273f47 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java @@ -0,0 +1,57 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.MessageHeader; +import org.hl7.fhir.exceptions.FHIRException; + +@ResourceDef(name = "FooMessageHeader") +public class FooMessageHeaderWithExplicitField extends MessageHeader { + + private static final long serialVersionUID = 1L; + + /** + * The source application from which this message originated. + */ + @Child(name = "source", type = {}, order = Child.REPLACE_PARENT, min = 1, max = 1, modifier = false, summary = true) + @Description(shortDefinition = "Message Source Application", formalDefinition = "The source application from which this message originated.") + protected FooMessageSourceComponent source; + + public void setSourceNew(FooMessageSourceComponent theSource) { + source = theSource; + } + + @Block() + public static class FooMessageSourceComponent extends MessageSourceComponent { + + private static final long serialVersionUID = 1L; + @Child(name = "ext-messageheader-application-id", type = Identifier.class, modifier = true) + @Description(shortDefinition = "Message Header Application ID") + @Extension(url = "http://foo", definedLocally = false, isModifier = false) + private Identifier messageHeaderApplicationId; + + /* + * Get messageHeaderApplicationId + */ + public Identifier getMessageHeaderApplicationId() throws FHIRException { + + if (messageHeaderApplicationId == null) { + messageHeaderApplicationId = new Identifier(); + } + return messageHeaderApplicationId; + } + + /* + * Set messageHeaderApplicationId + */ + public void setmessageHeaderApplicationId(Identifier messageHeaderApplicationId) { + this.messageHeaderApplicationId = messageHeaderApplicationId; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java new file mode 100644 index 00000000000..c4949c0e6aa --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java @@ -0,0 +1,52 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.StringType; + +@ResourceDef() +public class MyPatientWithCustomUrlExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "petName") + @Extension(url = "/petname", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The name of the patient's favourite pet") + private StringType myPetName; + + @Child(name = "customid") + @Extension(url = "/customid", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The customid of the patient's ") + private IdType myCustomId; + + public StringType getPetName() { + if (myPetName == null) { + myPetName = new StringType(); + } + return myPetName; + } + + public void setPetName(final StringType thePetName) { + myPetName = thePetName; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && getCustomId().isEmpty() && getPetName().isEmpty(); + } + + public IdType getCustomId() { + if (myCustomId == null) { + myCustomId = new IdType(); + } + return myCustomId; + } + + public void setCustomId(final IdType myCustomId) { + this.myCustomId = myCustomId; + } +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java new file mode 100644 index 00000000000..2be26671ce4 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java @@ -0,0 +1,66 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import java.util.List; +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.dstu3.model.Address.AddressUse; +import org.hl7.fhir.dstu3.model.Enumeration; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.Patient; + +@ResourceDef(name = "Patient") +public class MyPatientWithOneDeclaredEnumerationExtensionDstu3 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(order = 0, name = "foo") + @Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private Enumeration myFoo; + + /** + * A contact party (e.g. guardian, partner, friend) for the patient. + */ + @Child(name = "contact", type = {}, order=Child.REPLACE_PARENT, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=false) + @Description(shortDefinition="A contact party (e.g. guardian, partner, friend) for the patient", formalDefinition="A contact party (e.g. guardian, partner, friend) for the patient." ) + protected List contact; + + public Enumeration getFoo() { + return myFoo; + } + + public void setFoo(Enumeration theFoo) { + myFoo = theFoo; + } + + @Block() + public static class MessageSourceComponent extends ContactComponent { + + private static final long serialVersionUID = 1L; + @Child(name = "contact-eyecolour", type = { Identifier.class }, modifier = true) + @Description(shortDefinition = "Application ID") + @Extension(url = "http://foo.com/contact-eyecolour", definedLocally = false, isModifier = false) + private Identifier myEyeColour; + + /* + * Get messageHeaderApplicationId + */ + public Identifier getEyeColour() { + if (myEyeColour == null) { + myEyeColour = new Identifier(); + } + return myEyeColour; + } + + /* + * Set messageHeaderApplicationId + */ + public void setEyeColour(Identifier messageHeaderApplicationId) { + this.myEyeColour = messageHeaderApplicationId; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java new file mode 100644 index 00000000000..f05e39f37c6 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java @@ -0,0 +1,72 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.dstu3.model.CodeableConcept; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.Reference; + +@ResourceDef(name="Patient", profile = "http://hl7.org/fhir/StructureDefinition/Patient") +public class PatientProfileDstu3 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name="owner", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#owningOrganization", definedLocally=false, isModifier=false) + @Description(shortDefinition="The organization that owns this animal") + private Reference owningOrganization; + + public Reference getOwningOrganization() { + if (owningOrganization == null) { + owningOrganization = new Reference(); + } + return owningOrganization; + } + + public PatientProfileDstu3 setOwningOrganization(Reference owningOrganization) { + this.owningOrganization = owningOrganization; + return this; + } + + @Child(name="colorPrimary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorPrimary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals primary color") + private CodeableConcept colorPrimary; + + @Child(name="colorSecondary", min=0, max=1) + @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary", definedLocally=false, isModifier=false) + @Description(shortDefinition="The animals secondary color") + private CodeableConcept colorSecondary; + + public CodeableConcept getColorPrimary() { + if (this.colorPrimary == null) { + return new CodeableConcept(); + } + return colorPrimary; + } + + public void setColorPrimary(CodeableConcept colorPrimary) { + this.colorPrimary = colorPrimary; + } + + public CodeableConcept getColorSecondary() { + if (this.colorSecondary == null) { + return new CodeableConcept(); + } + return colorSecondary; + } + + public void setColorSecondary(CodeableConcept colorSecondary) { + this.colorSecondary = colorSecondary; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(owningOrganization) && ElementUtil.isEmpty(colorPrimary) + && ElementUtil.isEmpty(colorSecondary) ; + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java new file mode 100644 index 00000000000..9521c2f96ff --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java @@ -0,0 +1,81 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.dstu3.model.BackboneElement; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.StringType; + +@ResourceDef(name = "Patient") +public class PatientWithCustomCompositeExtension extends Patient { + + private static final long serialVersionUID = 1L; + + /** + * A custom extension + */ + @Child(name = "foo") + @Extension(url="http://acme.org/fooParent", definedLocally = false, isModifier = false) + protected FooParentExtension fooParentExtension; + + public FooParentExtension getFooParentExtension() { + return fooParentExtension; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(fooParentExtension); + } + + public void setFooParentExtension(FooParentExtension theFooParentExtension) { + fooParentExtension = theFooParentExtension; + } + + @Block + public static class FooParentExtension extends BackboneElement { + + private static final long serialVersionUID = 4522090347756045145L; + + @Child(name = "childA") + @Extension(url = "http://acme.org/fooChildA", definedLocally = false, isModifier = false) + private StringType myChildA; + + @Child(name = "childB") + @Extension(url = "http://acme.org/fooChildB", definedLocally = false, isModifier = false) + private StringType myChildB; + + @Override + public FooParentExtension copy() { + FooParentExtension copy = new FooParentExtension(); + copy.myChildA = myChildA; + copy.myChildB = myChildB; + return copy; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(myChildA, myChildB); + } + + public StringType getChildA() { + return myChildA; + } + + public StringType getChildB() { + return myChildB; + } + + public void setChildA(StringType theChildA) { + myChildA = theChildA; + } + + public void setChildB(StringType theChildB) { + myChildB = theChildB; + } + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java new file mode 100644 index 00000000000..d0918aa628f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java @@ -0,0 +1,410 @@ +package ca.uhn.fhir.tests.integration.karaf.dstu3; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.validation.*; +import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.Validate; +import org.hamcrest.core.StringContains; +import org.hl7.fhir.dstu3.conformance.ProfileUtilities; +import org.hl7.fhir.dstu3.context.IWorkerContext; +import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext; +import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport; +import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator; +import org.hl7.fhir.dstu3.model.*; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.utilities.validation.ValidationMessage; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_DSTU3; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class ResourceValidatorDstu3FeatureTest { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorDstu3FeatureTest.class); + private FhirContext ourCtx = FhirContext.forDstu3(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + HAPI_FHIR_VALIDATION_DSTU3.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + WRAP.option(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + + private List logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) { + List retVal = new ArrayList<>(); + + int index = 0; + for (SingleValidationMessage next : theOutput.getMessages()) { + ourLog.info("Result {}: {} - {} - {}", + new Object[]{index, next.getSeverity(), next.getLocationString(), next.getMessage()}); + index++; + + if (next.getSeverity() != ResultSeverityEnum.INFORMATION) { + retVal.add(next); + } + } + + return retVal; + } + + /** + * See issue #50 + */ + @Test + public void testOutOfBoundsDate() { + Patient p = new Patient(); + p.setBirthDateElement(new DateType("2000-12-31")); + + // Put in an invalid date + IParser parser = ourCtx.newXmlParser(); + parser.setParserErrorHandler(new StrictErrorHandler()); + + String encoded = parser.setPrettyPrint(true).encodeResourceToString(p).replace("2000-12-31", "2000-15-31"); + ourLog.info(encoded); + + assertThat(encoded, StringContains.containsString("2000-15-31")); + + ValidationResult result = ourCtx.newValidator().validateWithResult(encoded); + String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(resultString); + + assertEquals(2, ((OperationOutcome) result.toOperationOutcome()).getIssue().size()); + assertThat(resultString, StringContains.containsString("cvc-pattern-valid")); + + try { + parser.parseResource(encoded); + fail(); + } catch (DataFormatException e) { + assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"2000-15-31\": Invalid date/time format: \"2000-15-31\"", e.getMessage()); + } + } + @Test + public void testValidateCareTeamXsd() { + CareTeam careTeam = new CareTeam(); + careTeam + .addParticipant() + .setMember(new Reference("http://example.com/Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881")) + .setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828")); + + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + String encoded = parser.encodeResourceToString(careTeam); + + ourLog.info(encoded); + + FhirValidator val = ourCtx.newValidator(); + + ValidationResult result = val.validateWithResult(encoded); + String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()); + ourLog.info(resultString); + + assertThat(resultString, containsString("No issues detected during validation")); + + } + + @Test + public void testValidateCodeableConceptContainingOnlyBadCode() { + Patient p = new Patient(); + p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("FOO"); + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult output = val.validateWithResult(p); + List all = logResultsAndReturnNonInformationalOnes(output); + + assertEquals("None of the codes provided are in the value set http://hl7.org/fhir/ValueSet/marital-status (http://hl7.org/fhir/ValueSet/marital-status, and a code should come from this value set unless it has no suitable code) (codes = http://hl7.org/fhir/v3/MaritalStatus#FOO)", output.getMessages().get(0).getMessage()); + assertEquals(ResultSeverityEnum.WARNING, output.getMessages().get(0).getSeverity()); + } + + @Test + public void testValidateCodeableConceptContainingOnlyGoodCode() { + Patient p = new Patient(); + p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("M"); + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult output = val.validateWithResult(p); + List all = logResultsAndReturnNonInformationalOnes(output); + assertEquals(0, all.size()); + assertEquals(0, output.getMessages().size()); + } + + @Test + public void testValidateJsonNumericId() { + String input = "{\"resourceType\": \"Patient\",\n" + + " \"id\": 123,\n" + + " \"meta\": {\n" + + " \"versionId\": \"29\",\n" + + " \"lastUpdated\": \"2015-12-22T19:53:11.000Z\"\n" + + " },\n" + + " \"communication\": {\n" + + " \"language\": {\n" + + " \"coding\": [\n" + + " {\n" + + " \"system\": \"urn:ietf:bcp:47\",\n" + + " \"code\": \"hi\",\n" + + " \"display\": \"Hindi\",\n" + + " \"userSelected\": false\n" + + " }],\n" + + " \"text\": \"Hindi\"\n" + + " },\n" + + " \"preferred\": true\n" + + " }\n" + + "}"; + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new FhirInstanceValidator()); + ValidationResult output = val.validateWithResult(input); + + OperationOutcome operationOutcome = (OperationOutcome) output.toOperationOutcome(); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); +// ourLog.info(encoded); + + assertThat(encoded, containsString("Error parsing JSON: the primitive value must be a string")); + + } + + @Test + public void testValidateQuestionnaireWithCanonicalUrl() { + String input = "{\n" + + " \"resourceType\": \"Questionnaire\",\n" + + " \"url\": \"http://some.example.url\",\n" + + " \"status\": \"active\",\n" + + " \"subjectType\": [\n" + + " \"Patient\"\n" + + " ],\n" + + " \"item\": [\n" + + " {\n" + + " \"linkId\": \"example-question\",\n" + + " \"text\": \"Is the sky blue?\",\n" + + " \"type\": \"choice\",\n" + + " \"options\": {\n" + + " \"reference\": \"http://loinc.org/vs/LL3044-6\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + Questionnaire q = new Questionnaire(); + q = ourCtx.newJsonParser().parseResource(Questionnaire.class, input); + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(q); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + } + + /** + * Make sure that the elements that appear in all resources (meta, language, extension, etc) all appear in the correct order + */ + @Test + public void testValidateResourceWithResourceElements() { + TestPatientFor327 patient = new TestPatientFor327(); + patient.setBirthDate(new Date()); + patient.setId("123"); + patient.getText().setDivAsString("
FOO
"); + patient.getText().setStatus(Narrative.NarrativeStatus.GENERATED); + patient.getLanguageElement().setValue("en"); + patient.addExtension().setUrl("http://foo").setValue(new StringType("MOD")); + patient.getMeta().setLastUpdated(new Date()); + + List conditions = new ArrayList(); + Condition condition = new Condition(); + condition.getSubject().setReference("Patient/123"); + condition.addBodySite().setText("BODY SITE"); + condition.getCode().setText("CODE"); + condition.setClinicalStatus(Condition.ConditionClinicalStatus.ACTIVE); + condition.setVerificationStatus(Condition.ConditionVerificationStatus.CONFIRMED); + conditions.add(new Reference(condition)); + patient.setCondition(conditions); + patient.addIdentifier().setSystem("http://foo").setValue("123"); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(encoded); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String ooencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(ooencoded); + + assertTrue(result.isSuccessful()); + + assertThat(ooencoded, containsString("Unknown extension http://foo")); + } + + /** + * See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsJson() { + PatientProfileDstu3 myPatient = new PatientProfileDstu3(); + myPatient.setId("1"); + myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey"))); + myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-white"))); + myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().setFamily("FamilyName"); + myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension")); + + IParser p = ourCtx.newJsonParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); +// ourLog.info(messageString); + + String[] strings = {"meta", + "String Extension", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "FamilyName"}; + assertThat(messageString, stringContainsInOrder( + Arrays.asList(strings) + )); + String[] strings1 = {"extension", + "meta"}; + assertThat(messageString, not(stringContainsInOrder( + Arrays.asList(strings1) + ))); + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + /** + * See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer + */ + @Test + public void testValidateWithExtensionsXml() { + PatientProfileDstu3 myPatient = new PatientProfileDstu3(); + myPatient.setId("1"); + myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey"))); + myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-white"))); + myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393")); + myPatient.addName().setFamily("FamilyName"); + myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension")); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String messageString = p.encodeResourceToString(myPatient); + ourLog.info(messageString); + + //@formatter:off + String[] strings = {"meta", + "Organization/2.25.79433498044103547197447759549862032393", + "furry-grey", + "furry-white", + "String Extension", + "FamilyName"}; + assertThat(messageString, stringContainsInOrder( + Arrays.asList(strings) + )); + String[] strings1 = {"extension", + "meta"}; + assertThat(messageString, not(stringContainsInOrder( + Arrays.asList(strings1) + ))); + assertThat(messageString, containsString("url=\"http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary\"")); + assertThat(messageString, containsString("url=\"http://foo.com/example\"")); + //@formatter:on + + FhirValidator val = ourCtx.newValidator(); + val.registerValidatorModule(new SchemaBaseValidator(ourCtx)); + val.registerValidatorModule(new SchematronBaseValidator(ourCtx)); + val.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = val.validateWithResult(messageString); + + OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome(); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome); + ourLog.info(encoded); + + assertTrue(result.isSuccessful()); + + assertThat(messageString, containsString("valueReference")); + assertThat(messageString, not(containsString("valueResource"))); + } + + @ResourceDef(name = "Patient") + public static class TestPatientFor327 extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "testCondition") + @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false) + private List testConditions = null; + + public List getConditions() { + return this.testConditions; + } + + public void setCondition(List ref) { + this.testConditions = ref; + } + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java new file mode 100644 index 00000000000..1ae2468018f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java @@ -0,0 +1,114 @@ +package ca.uhn.fhir.tests.integration.karaf.r4; + +import java.io.IOException; +import java.util.List; +import ca.uhn.fhir.context.FhirContext; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport; +import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext; +import org.hl7.fhir.r4.model.Base; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.utils.FHIRPathEngine; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_R4; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class FhirInstanceValidatorR4Test { + + private FhirContext ourCtx = FhirContext.forR4(); + private FHIRPathEngine ourEngine = new FHIRPathEngine(new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport())); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorR4Test.class); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + HAPI_FHIR_VALIDATION_R4.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + WRAP.option(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testAs() throws Exception { + Observation obs = new Observation(); + obs.setValue(new StringType("FOO")); + + List value = ourEngine.evaluate(obs, "Observation.value.as(String)"); + assertEquals(1, value.size()); + assertEquals("FOO", ((StringType)value.get(0)).getValue()); + } + + @Test + public void testExistsWithNoValue() throws FHIRException { + Patient patient = new Patient(); + patient.setDeceased(new BooleanType()); + List eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); + ourLog.info(eval.toString()); + assertFalse(((BooleanType)eval.get(0)).getValue()); + } + + @Test + public void testExistsWithValue() throws FHIRException { + Patient patient = new Patient(); + patient.setDeceased(new BooleanType(false)); + List eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); + ourLog.info(eval.toString()); + assertTrue(((BooleanType)eval.get(0)).getValue()); + } + + @Test + public void testConcatenation() throws FHIRException { + String exp = "Patient.name.family & '.'"; + + Patient p = new Patient(); + p.addName().setFamily("TEST"); + String result = ourEngine.evaluateToString(p, exp); + assertEquals("TEST.", result); + } + + @Test + public void testConcatenationFunction() throws FHIRException { + String exp = "element.first().path.startsWith(%resource.type) and element.tail().all(path.startsWith(%resource.type&'.'))"; + + StructureDefinition sd = new StructureDefinition(); + StructureDefinition.StructureDefinitionDifferentialComponent diff = sd.getDifferential(); + + diff.addElement().setPath("Patient.name"); + + + Patient p = new Patient(); + p.addName().setFamily("TEST"); + List result = ourEngine.evaluate(null, p, diff, exp); + ourLog.info(result.toString()); +// assertEquals("TEST.", result); + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java new file mode 100644 index 00000000000..e5c617d5de2 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java @@ -0,0 +1,275 @@ +package ca.uhn.fhir.tests.integration.karaf.r4; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import com.google.common.collect.Sets; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Medication; +import org.hl7.fhir.r4.model.MedicationDispense; +import org.hl7.fhir.r4.model.MedicationRequest; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.StringType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThat; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class R4JsonParserTest { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(R4JsonParserTest.class); + private FhirContext ourCtx = FhirContext.forR4(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_R4.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + private Bundle createBundleWithPatient() { + Bundle b = new Bundle(); + b.setId("BUNDLEID"); + b.getMeta().addProfile("http://FOO"); + + Patient p = new Patient(); + p.setId("PATIENTID"); + p.getMeta().addProfile("http://BAR"); + p.addName().addGiven("GIVEN"); + b.addEntry().setResource(p); + return b; + } + + /** + * See #814 + */ + @Test + public void testDuplicateContainedResourcesNotOutputtedTwice() { + MedicationDispense md = new MedicationDispense(); + + MedicationRequest mr = new MedicationRequest(); + md.addAuthorizingPrescription().setResource(mr); + + Medication med = new Medication(); + md.setMedication(new Reference(med)); + mr.setMedication(new Reference(med)); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(md); + ourLog.info(encoded); + + int idx = encoded.indexOf("\"Medication\""); + assertNotEquals(-1, idx); + + idx = encoded.indexOf("\"Medication\"", idx + 1); + assertEquals(-1, idx); + + } + + /** + * See #814 + */ + @Test + public void testDuplicateContainedResourcesNotOutputtedTwiceWithManualIds() { + MedicationDispense md = new MedicationDispense(); + + MedicationRequest mr = new MedicationRequest(); + mr.setId("#MR"); + md.addAuthorizingPrescription().setResource(mr); + + Medication med = new Medication(); + med.setId("#MED"); + md.setMedication(new Reference(med)); + mr.setMedication(new Reference(med)); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(md); + ourLog.info(encoded); + + int idx = encoded.indexOf("\"Medication\""); + assertNotEquals(-1, idx); + + idx = encoded.indexOf("\"Medication\"", idx + 1); + assertEquals(-1, idx); + + } + + @Test + public void testExcludeNothing() { + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); +// excludes.add("*.id"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, containsString("BUNDLEID")); + assertThat(encoded, containsString("http://FOO")); + assertThat(encoded, containsString("PATIENTID")); + assertThat(encoded, containsString("http://BAR")); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + @Test + public void testExcludeRootStuff() { + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); + excludes.add("id"); + excludes.add("meta"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, not(containsString("BUNDLEID"))); + assertThat(encoded, not(containsString("http://FOO"))); + assertThat(encoded, (containsString("PATIENTID"))); + assertThat(encoded, (containsString("http://BAR"))); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertNotEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + @Test + public void testExcludeStarDotStuff() { + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); + excludes.add("*.id"); + excludes.add("*.meta"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, not(containsString("BUNDLEID"))); + assertThat(encoded, not(containsString("http://FOO"))); + assertThat(encoded, not(containsString("PATIENTID"))); + assertThat(encoded, not(containsString("http://BAR"))); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertNotEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertNotEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + /** + * Test that long JSON strings don't get broken up + */ + @Test + public void testNoBreakInLongString() { + String longString = StringUtils.leftPad("", 100000, 'A'); + + Patient p = new Patient(); + p.addName().setFamily(longString); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p); + + assertThat(encoded, containsString(longString)); + } + + @Test + public void testParseAndEncodeExtensionWithValueWithExtension() { + String input = "{\n" + + " \"resourceType\": \"Patient\",\n" + + " \"extension\": [\n" + + " {\n" + + " \"url\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/BirthWeight\",\n" + + " \"_valueDecimal\": {\n" + + " \"extension\": [\n" + + " {\n" + + " \"url\": \"http://www.hl7.org/fhir/extension-data-absent-reason.html\",\n" + + " \"valueCoding\": {\n" + + " \"system\": \"http://hl7.org/fhir/ValueSet/birthweight\",\n" + + " \"code\": \"Underweight\",\n" + + " \"userSelected\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/EuroPrevallStudySubjects\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " ],\n" + + " \"gender\": \"female\"\n" + + "}"; + + IParser jsonParser = ourCtx.newJsonParser(); + IParser xmlParser = ourCtx.newXmlParser(); + jsonParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + xmlParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + + Patient parsed = jsonParser.parseResource(Patient.class, input); + + ourLog.info(jsonParser.setPrettyPrint(true).encodeResourceToString(parsed)); + assertThat(xmlParser.encodeResourceToString(parsed), containsString("Underweight")); + assertThat(jsonParser.encodeResourceToString(parsed), containsString("Underweight")); + + } + + @Test + public void testParseExtensionOnPrimitive() throws IOException { + String input = IOUtils.toString(R4JsonParserTest.class.getResourceAsStream("/extension-on-line.txt")); + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + Patient pt = parser.parseResource(Patient.class, input); + + StringType line0 = pt.getAddressFirstRep().getLine().get(0); + assertEquals("535 Sheppard Avenue West, Unit 1907", line0.getValue()); + Extension houseNumberExt = line0.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-houseNumber"); + assertEquals("535", ((StringType) houseNumberExt.getValue()).getValue()); + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java new file mode 100644 index 00000000000..67b75f1148f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java @@ -0,0 +1,195 @@ +package ca.uhn.fhir.tests.integration.karaf.r4; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import com.google.common.collect.Sets; +import org.hamcrest.core.IsNot; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Patient; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThat; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class R4XmlParserTest { + + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(R4XmlParserTest.class); + private FhirContext ourCtx = FhirContext.forR4(); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + WRAP.option(), + HAPI_FHIR_R4.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + private Bundle createBundleWithPatient() { + Bundle b = new Bundle(); + b.setId("BUNDLEID"); + b.getMeta().addProfile("http://FOO"); + + Patient p = new Patient(); + p.setId("PATIENTID"); + p.getMeta().addProfile("http://BAR"); + p.addName().addGiven("GIVEN"); + b.addEntry().setResource(p); + return b; + } + + @Test + public void testParseAndEncodeXmlNumericEntity() { + String input = "\n" + + " \n" + + " \n" + + " \n" + + ""; + + Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input); + assertEquals("A \n B", p.getNameFirstRep().getFamily()); + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); + ourLog.info(output); + + } + + @Test + public void testExcludeNothing() { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); +// excludes.add("*.id"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, containsString("BUNDLEID")); + assertThat(encoded, containsString("http://FOO")); + assertThat(encoded, containsString("PATIENTID")); + assertThat(encoded, containsString("http://BAR")); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + @Test + public void testExcludeRootStuff() { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); + excludes.add("id"); + excludes.add("meta"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, IsNot.not(containsString("BUNDLEID"))); + assertThat(encoded, IsNot.not(containsString("http://FOO"))); + assertThat(encoded, (containsString("PATIENTID"))); + assertThat(encoded, (containsString("http://BAR"))); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertNotEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + @Test + public void testExcludeStarDotStuff() { + IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + Set excludes = new HashSet<>(); + excludes.add("*.id"); + excludes.add("*.meta"); + parser.setDontEncodeElements(excludes); + + Bundle b = createBundleWithPatient(); + + String encoded = parser.encodeResourceToString(b); + ourLog.info(encoded); + + assertThat(encoded, IsNot.not(containsString("BUNDLEID"))); + assertThat(encoded, IsNot.not(containsString("http://FOO"))); + assertThat(encoded, IsNot.not(containsString("PATIENTID"))); + assertThat(encoded, IsNot.not(containsString("http://BAR"))); + assertThat(encoded, containsString("GIVEN")); + + b = parser.parseResource(Bundle.class, encoded); + + assertNotEquals("BUNDLEID", b.getIdElement().getIdPart()); + assertNotEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId()); + assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString()); + } + + @Test + public void testParseAndEncodeExtensionWithValueWithExtension() { + String input = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + IParser xmlParser = ourCtx.newXmlParser(); + IParser jsonParser = ourCtx.newJsonParser(); + jsonParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + xmlParser.setDontEncodeElements(Sets.newHashSet("id", "meta")); + + Patient parsed = xmlParser.parseResource(Patient.class, input); + + ourLog.info(jsonParser.setPrettyPrint(true).encodeResourceToString(parsed)); + assertThat(xmlParser.encodeResourceToString(parsed), containsString("Underweight")); + assertThat(jsonParser.encodeResourceToString(parsed), containsString("Underweight")); + + } + +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json new file mode 100644 index 00000000000..24557e54b65 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json @@ -0,0 +1,53 @@ +{ + "resourceType": "Bundle", + "id": "example", + "meta": { + "versionId": "1", + "lastUpdated": "2014-08-18T01:43:30Z" + }, + "type": "searchset", + "total": 3, + "link": [ + { + "relation": "next", + "url": "https://example.com/base/MedicationOrder?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2" + }, + { + "relation": "self", + "url": "https://example.com/base/MedicationOrder?patient=347&_include=MedicationOrder.medication" + } + ], + "entry": [ + { + "fullUrl": "http://example.com/base/MedicationOrder/3123/_history/1", + "resource": { + "resourceType": "MedicationOrder", + "id": "3123", + "meta" : { + "versionId" : "1", + "lastUpdated" : "2014-08-16T05:31:17Z" + }, + "patient": { + "reference": "Patient/347" + }, + "medicationReference": { + "reference": "Medication/example" + } + }, + "search": { + "mode": "match", + "score": 1 + } + }, + { + "fullUrl": "http://example.com/base/Medication/example", + "resource": { + "resourceType": "Medication", + "id": "example" + }, + "search": { + "mode": "include" + } + } + ] +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml new file mode 100644 index 00000000000..37a83687b99 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml new file mode 100644 index 00000000000..8fe8320c489 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml new file mode 100644 index 00000000000..cd189a0838e --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml new file mode 100644 index 00000000000..d10ece0f0b4 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml new file mode 100644 index 00000000000..a7d0cca0016 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz b/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..9f5ca59e23715949f366c9b61fe80fce5daba832 GIT binary patch literal 40983 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 literal 0 HcmV?d00001 diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json b/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json new file mode 100644 index 00000000000..eb4365037b5 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json @@ -0,0 +1,55 @@ +{ + "resourceType": "Consent", + "id": "consent-example-basic", + "text": { + "status": "generated", + "div": "

\n

\n\tAuthorize Normal access for Treatment\n\t

\n Patient "P. van de Heuvel" wishes to have all of the PHI collected at the Good Health Psychiatric Hospital \n available for normal treatment use.\n

\n
" + }, + "status": "active", + "patient": { + "reference": "Patient/f001", + "display": "P. van de Heuvel" + }, + "period": { + "start": "1964-01-01", + "end": "2016-01-01" + }, + "dateTime": "2016-05-11", + "organization": [ + { + "reference": "Organization/Infoway", + "display": "Canada Infoway" + } + ], + "sourceAttachment": { + "title": "The terms of the consent in lawyer speak." + }, + "identifier": [ + { + "use": "usual", + "type": { + "coding": [ + { + "system": "http://hl7.org/fhir/v2/0203", + "code": "MR" + } + ] + }, + "system": "urn:oid:1.2.36.146.595.217.0.1", + "value": "12345", + "period": { + "start": "2001-05-06" + }, + "assigner": { + "display": "Acme Healthcare" + } + } + ], + "extension":[ + { + "url" : "http://hl7.org/fhir/StructureDefinition/PruebaExtension", + "valueString" : "123456789" + } + ], + "policyRule": "http://goodhealth.org/consent/policy/opt-in" +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json b/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json new file mode 100644 index 00000000000..2e740d86b27 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json @@ -0,0 +1,140 @@ +{ + "resourceType":"Patient", + "text":{ + "status":"generated", + "div":"
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
NamePeter James Chalmers (\"Jim\")
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
\n
" + }, + "extension":[ + { + "url":"urn:patientext:att", + "valueAttachment":{ + "contentType":"aaaa", + "data":"AAAA" + } + }, + { + "url":"urn:patientext:moreext", + "extension":[ + { + "url":"urn:patientext:moreext:1", + "valueString":"str1" + }, + { + "url":"urn:patientext:moreext:2", + "valueString":"str2" + } + ] + } + ], + "modifierExtension":[ + { + "url":"urn:modext", + "valueDate":"2011-01-02" + } + ], + "identifier":[ + { + "use":"usual", + "system":"urn:oid:1.2.36.146.595.217.0.1", + "value":"12345", + "period":{ + "start":"2001-05-06" + }, + "assigner":{ + "display":"Acme Healthcare" + } + } + ], + "active":true, + "name":[ + { + "use":"official", + "family":[ + "Chalmers" + ], + "given":[ + "Peter", + "James" + ] + }, + { + "use":"usual", + "given":[ + "Jim" + ] + } + ], + "telecom":[ + { + "use":"home" + }, + { + "system":"phone", + "value":"(03) 5555 6473", + "use":"work" + } + ], + "gender":"male", + "birthDate":"1974-12-25", + "deceasedBoolean":false, + "address":[ + { + "use":"home", + "line":[ + "534 Erewhon St" + ], + "city":"PleasantVille", + "state":"Vic", + "postalCode":"3999" + }, + { + "use":"old", + "line":[ + "SecondAddress" + ] + } + ], + "contact":[ + { + "relationship":[ + { + "coding":[ + { + "system":"http://hl7.org/fhir/patient-contact-relationship", + "code":"partner" + } + ] + } + ], + "name":{ + "family":[ + "du", + "Marché" + ], + "_family":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/Profile/iso-21090#qualifier", + "valueCode":"VV" + } + ] + }, + null + ], + "given":[ + "Bénédicte" + ] + }, + "telecom":[ + { + "system":"phone", + "value":"+33 (237) 998327" + } + ] + } + ], + "managingOrganization":{ + "reference":"Organization/1" + } +} \ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml new file mode 100644 index 00000000000..2cfd768c113 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml @@ -0,0 +1,128 @@ + + + +
+ + + + + + + + + + + + + + + + + + + +
NamePeter James Chalmers ("Jim")
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt b/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt new file mode 100644 index 00000000000..13c6990b92f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt @@ -0,0 +1,58 @@ +{ + "resourceType": "Patient", + "name": [ + { + "family": "Doe", + "given": [ + "John", + "W." + ] + } + ], + "gender": "male", + "birthDate": "2012-02-14", + "address": [ + { + "use": "home", + "line": [ + "535 Sheppard Avenue West, Unit 1907", + "RR 66, Station A, RPO 123" + ], + "_line": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-houseNumber", + "valueString": "535" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-streetName", + "valueString": "Sheppard" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-streetNameType", + "valueString": "Avenue" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-direction", + "valueString": "West" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-unitID", + "valueString": "1907" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-postBox", + "valueString": "1234" + } + ] + } + ], + "city": "Toronto", + "state": "ON", + "postalCode": "M3H4X8" + } + ] +} + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json b/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json new file mode 100644 index 00000000000..7b8bc14d2b5 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json @@ -0,0 +1,60 @@ +{ + "resourceType": "Patient", + "id": "dicom", + "text": { + "status": "generated", + "div": "
Patient MINT_TEST, ID = MINT1234. Age = 56y, Size =\n 1.83m, Weight = 72.58kg
" + }, + "http://nema.org/fhir/extensions#0010:1010": [ + { + "valueQuantity": { + "value": 56, + "units": "Y" + } + } + ], + "http://nema.org/fhir/extensions#0010:1020": [ + { + "valueQuantity": { + "value": 1.83, + "units": "m" + } + } + ], + "http://nema.org/fhir/extensions#0010:1030": [ + { + "valueQuantity": { + "value": 72.58, + "units": "kg" + } + } + ], + "identifier": [ + { + "system": "http://nema.org/examples/patients", + "value": "MINT1234" + } + ], + "name": [ + { + "family": [ + "MINT_TEST" + ] + } + ], + "gender": "male", + "_gender": { + "http://nema.org/examples/extensions#gender": [ + { + "valueCoding": { + "system": "http://nema.org/examples/gender", + "code": "M" + } + } + ] + }, + "managingOrganization": { + "reference": "Organization/1" + }, + "active": true +} \ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json b/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json new file mode 100644 index 00000000000..d7decea0fed --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json @@ -0,0 +1,1369 @@ + +{ + "resourceType":"Questionnaire", + "version":"October 2015", + "status":"draft", + "date":"2015-10-29", + "publisher":"Cancer Care Ontario", + "telecom":[ + { + "system":"email", + "value":"jon.zammit@cancercare.on.ca" + } + ], + "title":"CT Lung for Cancer Staging Template - DRAFT (Short Version)", + "item":[ + { + "text":"Patient with high suspicion of cancer as per the PEBC document (EBS #24-2) or radiological/laboratory tests suggesting cancer. Excluding: patients with synchronous lung primary, previous diagnosis of lung cancer, lung cancer surgery or therapy. New single lung primary only.", + "type":"display" + }, + { + "linkId":"root", + "type":"group", + "required":true, + "item":[ + { + "linkId":"g1", + "concept":[ + { + "system":"http://loinc.org", + "code":"55752-0", + "display":"Clinical Information" + } + ], + "text":"CLINICAL INFORMATION", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"1.1" + } + ], + "linkId":"1.1", + "text":"Patient Clinical Information", + "type":"text" + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"1.2" + } + ], + "linkId":"1.2", + "text":"Previous Examination (Date and Modality)", + "type":"text" + } + ] + }, + { + "linkId":"g2", + "text":"IMAGING PROCEDURE DESCRIPTION", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"2.1" + } + ], + "linkId":"2.1", + "text":"Overall Image Quality:", + "type":"choice", + "option":[{ + "valueCoding":{ + "code":"2.1a", + "display":"Adequate" + }}, + {"valueCoding":{ + "code":"2.1b", + "display":"Suboptimal" + }}, + {"valueCoding":{ + "code":"2.1c", + "display":"Non-diagnostic" + }} + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"2.2" + } + ], + "linkId":"2.2", + "text":"Intravenous Contrast Used?", + "type":"boolean" + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"2.3" + } + ], + "linkId":"2.3", + "text":"Additional Comments", + "type":"text" + } + ] + }, + { + "linkId":"g3", + "text":"FINDINGS", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3" + } + ], + "linkId":"g3.0", + "text":"T Category", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.1" + } + ], + "linkId":"g3.1", + "text":"Location of Main Nodule/Mass (Primary tumor, or Reference tumor)", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.1.1" + } + ], + "linkId":"q3.1.1", + "text":"Location of main nodule/mass:", + "type":"choice", + "option":[ + {"valueCoding":{ + "code":"3.1.1a", + "display":"Peripheral" + }}, + {"valueCoding":{ + "code":"3.1.1b", + "display":"Central*" + }}, + {"valueCoding":{ + "code":"3.1.1c", + "display":"Both*" + }} + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"q3.1.1" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.1.1b" + } + } + ] + }, + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"q3.1.1" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.1.1c" + } + } + ] + } + ], + "linkId":"g3.1.1i", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"i)" + } + ], + "linkId":"q3.1.1i", + "text":"What is the distance of the nodule/mass to the carina?", + "type":"integer", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-item-control", + "code":"unit" + } + ] + } + } + ], + "text":"mm", + "type":"display" + } + ] + }, + { + "linkId":"3.1.1i.image", + "text":"image", + "type":"string" + }, + { + "linkId":"3.1.1i.series", + "text":"series", + "type":"string" + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.1.2" + } + ], + "linkId":"3.1.2", + "text":"State the lobe(s) and segment(s) where the nodule/mass is located", + "type":"text" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.2" + } + ], + "linkId":"g3.2", + "text":"Size and characteristics of main nodule/mass", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.2.1" + } + ], + "linkId":"3.2.1", + "text":"Size of the nodule/mass:", + "type":"choice", + "option":[ + {"valueCoding":{ + "code":"3.2.1a", + "display":"Solid nodule/mass" + }}, + {"valueCoding":{ + "code":"3.2.1b", + "display":"Part-solid nodule/mass" + }}, + {"valueCoding":{ + "code":"3.2.1c", + "display":"Pure Ground glass" + }} + ], + "item":[ + { + "linkId":"g3.2.1", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.2.1" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.2.1a" + } + } + ] + } + ], + "linkId":"g3.2.1a", + "type":"group", + "item":[ + { + "linkId":"3.2.1a", + "text":"largest dimension:", + "type":"integer", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-item-control", + "code":"unit" + } + ] + } + } + ], + "text":"mm", + "type":"display" + } + ] + }, + { + "linkId":"3.2.1a.image", + "text":"image", + "type":"string" + }, + { + "linkId":"3.2.1a.series", + "text":"series", + "type":"string" + } + ] + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.2.2" + } + ], + "linkId":"3.2.2", + "text":"Plane in which the mass was measured:", + "type":"choice", + "option":[ + { + "code":"3.2.2a", + "display":"Axial" + }, + { + "code":"3.2.2b", + "display":"Coronal" + }, + { + "code":"3.2.2c", + "display":"Sagittal" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.2.3" + } + ], + "linkId":"3.2.3", + "text":"Other characteristics of the main nodule/mass:", + "type":"text" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.3" + } + ], + "linkId":"g3.3", + "text":"Structures directly involved", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.3.1" + } + ], + "linkId":"3.3.1", + "text":"State if there is bronchial involvement:", + "type":"choice", + "option":[ + { + "code":"3.3.1a", + "display":"*Yes" + }, + { + "code":"3.3.1b", + "display":"No" + }, + { + "code":"3.3.1c", + "display":"Uncertain" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, answer i and ii.", + "type":"display" + }, + { + "linkId":"g3.3.1", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.1" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.3.1a" + } + } + ] + } + ], + "linkId":"g3.3.1.yes", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"i)" + } + ], + "linkId":"3.3.1i", + "text":"Type of involvement:", + "type":"text" + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"ii)" + } + ], + "linkId":"3.3.1ii", + "text":"State if there is endobronchial involvement:", + "type":"choice", + "option":[ + { + "code":"3.3.1.iia", + "display":"*Yes" + }, + { + "code":"3.3.1.iib", + "display":"No" + }, + { + "code":"3.3.1.iic", + "display":"Uncertain" + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.1ii" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.3.1.iia" + } + } + ] + } + ], + "linkId":"3.3.1iic", + "text":"Describe:", + "type":"text" + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.3.2" + } + ], + "linkId":"3.3.2", + "text":"Is there direct involvement of any other anatomical structures?", + "type":"boolean", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, indicate and describe all ipsilateral anatomical structures involved by the mass. If no, go to 3.3.3.", + "type":"display" + }, + { + "linkId":"g3.3.2.yes", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.2" + }, + { + "url":"#answer", + "valueBoolean":true + } + ] + } + ], + "linkId":"3.3.2.Yes", + "text":"Indicate and describe all ipsilateral anatomical structures involved by the mass:", + "type":"choice", + "repeats":true, + "option":[ + { + "code":"3.3.2.Yes.a", + "display":"Pleura" + }, + { + "code":"3.3.2.Yes.b", + "display":"Brachial Plexus" + }, + { + "code":"3.3.2.Yes.c", + "display":"Diaphragm" + }, + { + "code":"3.3.2.Yes.d", + "display":"Mediastinal fat" + }, + { + "code":"3.3.2.Yes.e", + "display":"Aorta" + }, + { + "code":"3.3.2.Yes.f", + "display":"Pulmonary Vessel" + }, + { + "code":"3.3.2.Yes.g", + "display":"Pericardium or Heart" + }, + { + "code":"3.3.2.Yes.h", + "display":"Mediastinal Vessels (including SVC)" + }, + { + "code":"3.3.2.Yes.i", + "display":"Trachea/carina" + }, + { + "code":"3.3.2.Yes.j", + "display":"Esophagus" + }, + { + "code":"3.3.2.Yes.k", + "display":"Trachea esophageal groove" + }, + { + "code":"3.3.2.Yes.l", + "display":"Vertebral Body" + }, + { + "code":"3.3.2.Yes.m", + "display":"Chest wall and Ribs" + }, + { + "code":"3.3.2.Yes.n", + "display":"Other structures" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.2.Yes" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.3.2.Yes.a" + } + } + ] + } + ], + "linkId":"3.3.2.Yes.a.text", + "text":"Pleura, description:", + "type":"string" + } + ] + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.3.3" + } + ], + "linkId":"3.3.3", + "text":"Are there additional suspicious pulmonary nodules?", + "type":"boolean", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, indicate and describe pulmonary nodules which apply. If no, go to 3.3.4.", + "type":"display" + }, + { + "linkId":"g3.3.3.yes", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.3" + }, + { + "url":"#answer", + "valueBoolean":true + } + ] + } + ], + "linkId":"3.3.3.Yes", + "text":"Indicate and describe pulmonary nodules which apply:", + "type":"choice", + "option":[ + { + "code":"3.3.3.Yes.a", + "display":"In the same lobe" + }, + { + "code":"3.3.3.Yes.b", + "display":"In a different lobe, same lung" + }, + { + "code":"3.3.3.Yes.c", + "display":"In the opposite lung (M1a)" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"3.3.3.Yes" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"3.3.3.Yes.a" + } + } + ] + } + ], + "linkId":"3.3.3.Yes.a.text", + "text":"In the same lobe, description:", + "type":"string" + } + ] + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"3.3.4" + } + ], + "linkId":"3.3.4", + "text":"Other notable intrathoracic findings (eg lymphangitis carcinomatosis):", + "type":"text" + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"4" + } + ], + "linkId":"4.0", + "text":"N Category", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"4.1" + } + ], + "linkId":"4.1", + "text":"Are there enlarged lymph nodes?", + "type":"boolean", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, indicate and describe the nodes which apply. If no, go to 4.2.", + "type":"display" + }, + { + "linkId":"g4.1.yes", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"4.1" + }, + { + "url":"#answer", + "valueBoolean":true + } + ] + } + ], + "linkId":"4.1.yes", + "text":"Nodes and Descriptions:", + "type":"choice", + "repeats":true, + "option":[ + { + "code":"4.1.yes.a", + "display":"1 Low Cervical, supraclavicular, and sternal notch nodes" + }, + { + "code":"4.1.yes.b", + "display":"2R Upper Paratracheal (right)" + }, + { + "code":"4.1.yes.c", + "display":"2L Upper paratracheal (left)" + }, + { + "code":"4.1.yes.d", + "display":"3a Pre-vascular" + }, + { + "code":"4.1.yes.e", + "display":"3p Retrotracheal" + }, + { + "code":"4.1.yes.f", + "display":"4R Lower paratracheal (right)" + }, + { + "code":"4.1.yes.g", + "display":"4L Upper paratracheal (left)" + }, + { + "code":"4.1.yes.h", + "display":"5 Subaortic" + }, + { + "code":"4.1.yes.i", + "display":"6 Para-aortic (ascending aorta or phrenic)" + }, + { + "code":"4.1.yes.j", + "display":"7 Subcarinal" + }, + { + "code":"4.1.yes.k", + "display":"8 Paraesophageal (below carina)" + }, + { + "code":"4.1.yes.l", + "display":"9 Pulmonary ligament" + }, + { + "code":"4.1.yes.m", + "display":"10 Hilar" + }, + { + "code":"4.1.yes.n", + "display":"11 Interlobar" + }, + { + "code":"4.1.yes.o", + "display":"12 Lobar" + }, + { + "code":"4.1.yes.p", + "display":"13 Segmental" + }, + { + "code":"4.1.yes.q", + "display":"14 Subsegmental" + }, + { + "code":"4.1.yes.r", + "display":"Other Nodes (axilla, sub-diaphragmatic)" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"4.1.yes" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"4.1.yes.a" + } + } + ] + } + ], + "linkId":"4.1.yes.description", + "text":"Description of node:", + "type":"string" + } + ] + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"4.2" + } + ], + "linkId":"4.2", + "text":"Other notable findings:", + "type":"text" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"5" + } + ], + "linkId":"5.0", + "text":"M Category (Suspicious Extrathoracic Findings (M1b))", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"5.1" + } + ], + "linkId":"5.1", + "text":"Are there suspicious extrathoracic findings?", + "type":"boolean", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, indicate and describe the structures below which apply. If no, go to 6.", + "type":"display" + }, + { + "linkId":"g5.1.yes", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"5.1" + }, + { + "url":"#answer", + "valueBoolean":true + } + ] + } + ], + "linkId":"5.1.yes", + "text":"Applicable Structures and Descriptions:", + "type":"choice", + "repeats":true, + "option":[ + { + "code":"5.1.yes.a", + "display":"Adrenals" + }, + { + "code":"5.1.yes.b", + "display":"Liver" + }, + { + "code":"5.1.yes.c", + "display":"Bone" + }, + { + "code":"5.1.yes.d", + "display":"Other" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"5.1.yes" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"5.1.yes.d" + } + } + ] + } + ], + "linkId":"5.1.yes.d.description", + "text":"Description of structures:", + "type":"string" + } + ] + } + ] + } + ] + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"6" + } + ], + "linkId":"6.0", + "text":"Additional Findings", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"6.1" + } + ], + "linkId":"6.1", + "text":"Are there additional findings?", + "type":"boolean", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept":{ + "coding":[ + { + "system":"http://hl7.org/fhir/ValueSet/questionnaire-display-category", + "code":"instructions" + } + ] + } + } + ], + "text":"*If yes, indicate and describe the findings below which apply. If no, go to Impressions.", + "type":"display" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"6.2" + }, + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"6.1" + }, + { + "url":"#answer", + "valueBoolean":true + } + ] + } + ], + "linkId":"6.2", + "text":"Findings and Descriptions:", + "type":"open-choice", + "repeats":true, + "option":[ + { + "code":"6.2a", + "display":"Emphysema" + }, + { + "code":"6.2b", + "display":"Fibrosis" + }, + { + "code":"6.2c", + "display":"Coronary artery classification" + }, + { + "code":"6.2d", + "display":"Asbestos related pleural disease" + }, + { + "code":"6.2e", + "display":"Interstitial lung disease" + }, + { + "code":"6.2f", + "display":"Atherosclerosis" + }, + { + "code":"6.2g", + "display":"Pulmonary Embolism" + } + ], + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-enableWhen", + "extension":[ + { + "url":"#question", + "valueString":"6.2" + }, + { + "url":"#answer", + "valueCoding":{ + "code":"6.2a" + } + } + ] + } + ], + "linkId":"6.2a", + "text":"Pulmonary, description:", + "type":"string" + } + ] + } + ] + } + ] + }, + { + "linkId":"g7", + "text":"IMPRESSIONS", + "type":"group", + "item":[ + { + "linkId":"g7.1", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"7.1" + } + ], + "linkId":"7.1", + "text":"Impression/Summary:", + "type":"text" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"7.2" + } + ], + "linkId":"g7.2", + "text":"Radiologic Staging (TNM Version – 7th edition)", + "type":"group", + "item":[ + { + "linkId":"g7.20", + "text":"If this is a biopsy proven carcinoma, the preliminary radiologic stage is:", + "type":"group", + "item":[ + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"i)" + }, + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-questionControl", + "valueCodeableConcept":{ + "coding":[ + { + "code":"radio-button", + "display":"Radio Button" + } + ] + } + }, + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation", + "valueCode":"horizontal" + } + ], + "linkId":"7.2i", + "text":"Primary Tumour (T):", + "type":"choice", + "option":[ + { + "code":"T1a", + "display":"T1a" + }, + { + "code":"T1b", + "display":"T1b" + }, + { + "code":"T2", + "display":"T2" + }, + { + "code":"T2a", + "display":"T2a" + }, + { + "code":"T2b", + "display":"T2b" + }, + { + "code":"T3", + "display":"T3" + }, + { + "code":"T4", + "display":"T4" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"ii)" + } + ], + "linkId":"7.2ii", + "text":"Regional Lymph Nodes (N):", + "type":"choice", + "option":[ + { + "code":"NX", + "display":"NX" + }, + { + "code":"N0", + "display":"N0" + }, + { + "code":"N1", + "display":"N1" + }, + { + "code":"N2", + "display":"N2" + }, + { + "code":"N3", + "display":"N3" + } + ] + }, + { + "extension":[ + { + "url":"http://hl7.org/fhir/StructureDefinition/questionnaire-label", + "valueString":"iii)" + } + ], + "linkId":"7.2iii", + "text":"Distant Metastasis (M):", + "type":"choice", + "option":[ + { + "code":"M0", + "display":"M0" + }, + { + "code":"M1", + "display":"M1" + }, + { + "code":"M1a", + "display":"M1a" + }, + { + "code":"M1b", + "display":"M1b" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml new file mode 100644 index 00000000000..6379703c20e --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml @@ -0,0 +1,455 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json b/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json new file mode 100644 index 00000000000..64b109613f8 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json @@ -0,0 +1,73 @@ +{ + "resourceType": "Bundle", + "entry": [ + { + "fullUrl": "http://localhost:5555/phr/baseDstu3/Person/PERSON1", + "resource": { + "resourceType": "Person", + "id": "PERSON1", + "meta": { + "versionId": "1", + "lastUpdated": "2017-08-17T16:19:40.109+03:00" + }, + "identifier": [ + { + "value": "081181-9984" + } + ], + "name": [ + { + "text": "Anna Testi", + "family": "Testi", + "given": [ + "Anna" + ] + }, + { + "family": "asdfas" + } + ], + "telecom": [ + { + "use": "home" + }, + { + "system": "phone", + "value": "(044) 1234567", + "use": "work" + } + ], + "gender": "female", + "birthDate": "1981-11-08", + "address": [ + { + "line": [ + "Osuuspankkitie 2" + ], + "city": "Helsinki", + "postalCode": "00120", + "country": "Suomi" + }, + { + "city": "Blo-49847020" + } + ], + "active": true, + "link": [ + { + "target": { + "reference": "Patient/PATIENT1", + "display": "Anna Testi" + } + } + ] + }, + "request": { + "method": "PUT", + "url": "Person/PERSON1", + "ifMatch": "1" + } + } + ] +} + diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json b/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json new file mode 100644 index 00000000000..f0180a92c12 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json @@ -0,0 +1,58 @@ +{ + "resourceType": "DiagnosticReport", + "id": "gingival-mass", + "text": { + "status": "generated", + "div": "

Generated Narrative with Details

id: gingival-mass

identifier: P73456090

status: final

category: Pathology (Details : {http://hl7.org/fhir/v2/0074 code 'PAT' = 'Pathology (gross & histopath, not surgical)', given as 'Pathology (gross & histopath, not surgical)'})

code: Biopsy without Microscopic Description (1 Site/Lesion)-Standard (Details : {https://www.acmeonline.com code '4503' = '4503', given as 'Biopsy without Microscopic Description (1 Site/Lesion)-Standard'})

subject: Max Jones

effective: 2-Mar-2017

issued: 15-Mar-2017 8:13:08 AM

performer: Acme Animal Labs

resultsInterpreter: Sean Stover, BS, DVM, DABVP (Canine/Feline), DACVP

presentedForm:

" + }, + "identifier": [ + { + "system": "https://www.acmeonline.com", + "value": "P73456090" + } + ], + "status": "final", + "category": { + "coding": [ + { + "system": "http://hl7.org/fhir/v2/0074", + "code": "PAT", + "display": "Pathology (gross & histopath, not surgical)" + } + ], + "text": "Pathology" + }, + "code": { + "coding": [ + { + "system": "https://www.acmeonline.com", + "code": "4503", + "display": "Biopsy without Microscopic Description (1 Site/Lesion)-Standard" + } + ], + "text": "Biopsy without Microscopic Description (1 Site/Lesion)-Standard" + }, + "subject": { + "display": "Max Jones" + }, + "effectiveDateTime": "2017-03-02", + "issued": "2017-03-15T08:13:08Z", + "performer": [ + { + "display": "Acme Animal Labs" + } + ], + "resultsInterpreter": [ + { + "display": "Sean Stover, BS, DVM, DABVP (Canine/Feline), DACVP" + } + ], + "presentedForm": [ + { + "contentType": "application/pdf", + "language": "en", + "data": "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 dIqzutC+VtofK52ftFY6xVldaF8r7e9YaUmntdIXktZK65JWF5LXSj911kr7dlorne+sLoxz1kqt 1YVXndWF5LXS+c7qgrVWOgIrHdFprXS+s7owzlkrHYGVxpLWKuuw0pizVjkWK62wtW46uUpinbIO K41hpZOx0rG27u2+TjnRWVUYgZUOwUr7Y6Xzk9YppzirCu3rlP07rVPOd1YVrHXKEVjpiE7rlPOd VYVx1jqlrZdWzhR29LLaWcWPY4lxZ91ruZNVT8MSJzrrXjXOWlcLltjirNwvT8quJzqr9nEsMe6s cy13suxpWOJEZ50rjiXGscT5TrY9rdM6VxxLjDvrXPOdrHsalji00zpXC5bYspd1rqHOOlccS4w7 61zznex7GpY41FnnimOJcWeda76ThU/DEocmrXM1Y4lxLDGOJb7qZOPTnHWuGixxPpY4zcnGpxE1 PU42XoIlNmGJcSwx7qxz1ThZ+bSkda75WGIdltiCJbZgiTWd1rksS2zCEuNYYtxZ56pxsvNpjiVa a1wtWGKLs2q+PClLn+ismMexxLizvrXcydanYYkTnfWtFiyxZS/rW0Od9a04lhh31rfmO1n7NCxx KJZYhyW2YIktWGJNp/UtyxKbsMQ4lhh31rdqnOx9muiqHSyyrd/ZZG53ilwnjpdxcYorUxzveVrM 8/1F+MWRSWccbx/5Vvg9SmR7uwq/1015CKWHMpPySMpjKI+jzKE8iXIE5emUF0AR28WUEymvpiyl vJFZbrnwG7dR3kF5F+XdlL+lvJdyPmWQcgHlE5RPimxxpjxUFcu+MABOAD9cBaVwG9wDLwpDLlMR uRLetz6DJhasoVyrTNmqTK9UxV4XpMBBEIevwIT1sAE2wibYDFvga9gK26ANvoHt8C3sgO9gJyhV bAjQgPsY3MfgPkYqdIEDoCscCN1gCgRUse8QFfH1goHK9B0Hx7OdDSPgVDhDRTJWA8+REYO18KWK CI+2RjVav+usrSPKDRaZ6EuVPI6nPV5kyWy2T+Pp/0e1ybPolXOIhheoajmO8mJ6YyrnoKaynGMV bN+S+J1pkautUhHtC+Ce2lbYxhUPVavp+9Wo2Cb6fzV32iSP5crHq1bGYrU8he1xnOdn/yoohQpi 8G2q1fO5aqPfV9Pvq+n31fT7au9F1I2DuGql/1vp/1b6v5X+b6X/W+n/Vvq/lf5vpf9b6f9W+r+V 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 4kaUuBElbkSJG1HiRuyyESVuRIkbyZMj5MkR8uQIeXKEPDlCnhwhT46QJ0fIkyPkyRHy5Ah5coQ8 OUKeHCFPjpAnk4WJHO9XYMJ62AAbYRNshi3wNWyFbdAG38B2+BZ2wHewE5TIMQRoIMEFKZAKXeAA 6AoHQjfoLnTyaJ08WieP1smjdfJonTxaJ4/WyaN18midPFonj9bJo3XyaJ08WieP1smjdfJonTxa J4/WyaN18midPFonj9bJo3XyaJ08WieP1smjdfJonTxaJ4/WyaN18midPFonj9bJo3XyaJ08Wsfv dfJonTxaJ4/W0QCdPFpHB3R0QCeP1smjdfJoHU3QyaN18mgdlWxEJRtRyUZUshGVbEQlG1HJRlSy kTxaJ4/WjSki0wiITHELulGGbpShGWVoRBk5XNDOQc9VAdSuCrWbg9KVkZsFyM2CWHyA3CuAhuSg ITloSA4akoNVBtCQMjSkDA0pQ0PKyHOC5DlB8pwgeU6QPCdInhNEKYPkOUHynCB5ThDVDKKaQVQz SJ4TJM8JkucEyXOC5DlB8pwgeU4QRQ2S5wTJc4LkOUHUNYg1Z2PN5R05xYvkGWEU9GXa83d4BRbD q/AavA5vwAfwITRCE0TgI/gYPoFm+BQ+g89hFbRAFL4A63nXQAzWQit8CeuAKIJmYtWwHjbARtgE m2ELfA1bYRu0wTewHb6FHfAd7ASlsGrQQIILUiAVusAB0BUOhG4wjCixK1pko6FlaGiZOMTblRhz CGTCMZADxBNvEUyEUlFglMMdcDfcC0FYIPoYT1A+KfpY39xF5cYxY+mClZj276WdT80FaM0S/LmW WU2KPI05wnn2TMW0VsrFNViVSW29/Z5zbE01sa4o1sV70eML2S8ES18vobzUXtsIoLEBLM5EY000 1kRjTazPxNqsdVIT6zKxLhPrMrEuE+sysS4T6zKxLhPrMrEuE+sysS4T6zKxLhPrMrEuE+sysS4T 6zKxLhPrMrEuE+sysS5rjSGAdgbQzgDaGcDaAlhbAO0MYHEBLC6AdgbQzQCWF0A3A1hfAOszsT4T 6zOxPhPrM7E+E+szsT4T3TTRTRPdNNFNE9000U0T3TTRTRPdNNFNE9000U0T3TTRTRPdNNFNE+s1 sV4T6zWxXhPrNbFeE+s1sV4T6zWxXhPrNbFeE+s1sV4T6zWxXtNr9d8aiMFasD7V+RLWKVNo8iyR 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 31Uhe0VIvWpHOGt1+xDxEFY4QMyyV7+WsF1rryvN4gqLuMITXGGWz1o5/ItYzBUWc4XFzhUWpU+0 V/mKxFCsQxdzyYgfxttfYjsML8PfYQd1O0GJWej8LHR+Fjo/Sx+ArwwisxzKdo4YiBXpWJGO5pdi STq6X4ruz0L3Z2FNul7DuU/BUvbfpoWLtB6ep1CtpzUfscDnxIJSW7metPO/7bR8OzFhGDFhGDGh lJiAlmvDiAkfpk+gD67U+mF572F5y4gJw7C8NfaaZTktTY5E5U4kyqM15bTAikAbuHs2d+/B3Xtw 9wInEhXYkegZOxr14879uLN1Vx93S9kjAp3a4VWWJu5ND5fbs/Lsdr1z8uEOXUuefVua1rFOcQxY uXJuknd21q7LOafdY9tn1tbq4gP2rLhDe5iFFDlP5ufJ/B05dfKMmAx/D/1BMztmJqW2h1uzk+ft jOooLCbPWR/Ow0LysJA8nm5BclblrBfnYTF5PNkynmwZVpNnrxkPsy0kz143rqF8ChLrx3mMz2Js mCyBWPWk7TuLafliWr6Blm+gtRvQHmtV1poFfEILF9A6vIIxulEsEsc468hFtK6I1hXRuiJatp2W badl22lZES0romVFtGwNLVvjrB8X0e+L6NtcWldE64qS1oyLaF2R51HV5LRuA5aTTd/mOuvGy2jl ciwnBctJwXJyE3mM2E5fLiCHyXPWkbfT4mdp8UJa7KPFi8WxtNjvZFmltLiUFpeSZfUgy+pBltXD ybJKaXFph20PYpQTmVaBbd+T2LYyrRrqn4JExlVKi+N21vWUpUVkXonsy7L5AtsynrQzsPc62X2R 43H97Cws0XpL73fS+sW0/vkOP+hP63dvuRDv7ZYj7mr5GqflpfTz805+aLW4lBbbrbVnJqg7LfqE Fn1Ci3rQoh62JybyQh8tepEWFdCiUscz21vUjxa9J4bs7/MvJwsZmJSF9NnHOllyBjIvKQNp99g8 ez1sb5+lTbDnZvZnaR2e+Mg+16FyrbUW+3O2LPqy3FKx/eTb5Un59nb6czv9We4oXbsllNtqVwNP JVTPyb0t5cvdiwWUJymflYf77M8asQD6ejF97aevy+nrHskqKFLlo6pOLlZ1xgbYCJus+KeliRR+ hOhCJq6JHuJgtnoJQ3QV6WIE++eI84k8F4kSMVxMFdPFeeIOcZe4VFSReRYTb2aLK8Q9xCS/eEA8 La4VIXykksxyBb3zDj/zxEoRF/NFm9ZFPKcdqB0o3tC6a26xROupHSKWarqmizc1r5bOXK+3Nki8 rR2vZYuPtVxtpGjWztXOE6u0Am2siGoXaxPEau0K7TqxXrtZu0N8q1Vqd2pdtD9oj2ldtWrtSe0g bZUW0w7RWvnxaeu0uJaumZrSekspD9AGy+6yuzZUHiQP0k6QB8uDtRx5iDxEGybTZJp2ovRIjzZc GtLQTpKHykztZHmEPEI7TR4pB2iny4HyaO0MeYzM1vLkCTJHO1cOl6do58tT5anahfI0ebpWKM+Q Z2jj5Gh5lnaxPEeeoxXJc2WBNl5eIAu1X8hx8hLtCnmZvFqbKK+R12hl8jpZqk2R18sbtZvkVFmh VcjbZECbJu+Qldrt8h45T6uUD8oHtd/IR+Qj2iz5B/mENlv+ST6p3Sdr5J+1efIZ+YL2oHxRvqgt kGG5WFso35BvaNWyVr6p/VEul8u1GvmOfEd7Sq6UK7U/ywbZoD0tP5AR7Rn5iWzWnpefyVXaX2VU xrSX5Jcyri2WptygvS43yU1arWyTSlvqki6pvePq4uqi1bm6urpq9a5urh7au65DXL20D1y6y6s1 unyuPtpHrkxXprbKdYTrKK3FleMapsVcha7LtVbXJNcN2mbX467Hte9c77je0Xa66l3vair1wNRu Uus1s9fD0tXr970WSaPXn3stl/17vd2rSZ7e6+Ne6+V5vbandZFXph2Y5pHXp12Xdr0MpJWl3Szv SLsl7Rb5v2mBtICsSpuedrucmTYj7U55d1pV2kw5O21W2mx5Txo/ck7anLS5cm7afWn3yfvSHkpb KO9PeyztCflI2qK0P8sFaaG05+TjaeG0f8g/pS1Pe0u+kPZ2Wr38W1pD2mfy5bRY2ldyWdrX+gGy Xj9Iz5At+qF6H7lBP1w/XG7W++lHyC36kfpRcqt+tH60/EYfrB8rt+vH68Pkd/pw/RSXSx+hj3Ad oJ+hF7q66hfrRa4M/XK92NVH/6V+hetw3a9PcvXTr9Wvcx2lT9avdw3Sp+rlriw9oAdcx+rT9UrX cfqv9VmuHP23+v2uk/QH9Yddp+sL9JdcZ+qv6nWuYv1dvdFVqn+kf+S6Sf9UX+W6WV+jr3Xdqq/T 17mm6aZuuqbrW/SvXbfrbfo3rhn6d/pO150el8fl+l9PqifVVeXp7nG7Znp6eHq57vboHq/rHk9v z6GuuZ5MT3/XfZ4szzGuBzxDPENdD3lyPMNcCzwne052PeoZ4RnpesxzpudMV7XnLM+5rj96LvQU up7yXOa5wvW0p8RznesFz/We21wveWZ4fuP6h2e2Z67rXc99nvtcH3rmeR5wNXoe9ixwfeR51POY 63PPIk+Nq8XztOcZ1xee5z0vuNZ4PvZ87lrr+cLzhcv0rPGsca33tHpaXRs86zzrXBs9X3k2uDZ5 2ryHubZ6j/eelHKoN887LuVIb4n3xpRh3hpDSxlpdDd6pcwzTjNGp/zeONsYl1JtTDFuS3nO+Lvx 95S/G68ar6W8YrxhvJHyqlFrrEh5zagz6lOWGe8ZH6S8ZUSMj1LqjE+Mz1PeNaLG2pQPjLjxTcrH PoQlpdWX4uuS8qWvq69ryle+br6DU0xfmi8tZYvP60tP+dp3mO+wlG98fX39Urb7BvmyUnb6jvMN S9V8w30jUrv6TvOdltrDN9p3durBvjG+C1PTfBf7Lk7t7SvyXZ56qO+XvitSD/f5fVel9vNd47s2 dYBvsu/61IG+Kb47Uo/2zfbNTh3uu8d3T+pJvgd8D6We7HvEtzB1hO9x3xOpo3x/8i1KPdP3Z9+z qaN9z/teSD3X9zff31LP973keym1wPey7+XUsb4lvtrUC3z/8L2VWuh7x1efeqnvPV9D6mW+D31N qcW+Zt+nqb/0xXxrU6/0xX3x1InpZ6Sfn/qr9LHpF6SWpV+Sfknq1PSi9MtSb0ovTp+QWpF+RfqV qbelT0y/JnVa+nXppal3pV+ffkNqVUZ9Rn3qrzM+yGhMvTtjdcba1NkZWzK2pc7pPab3ean3C3nq X62Yc/qfzh0jxoorxf+DLxXrvKdiaiM/c9UHbH8GMy3UVueMUT9TO0Lw9051dVCftD+XnykqlGiD +ko1Wf9+z+u3JPh5XyoObRD93u/4UoX5+fJ7nr1WfaLWUm4UP9lLxRM/9vYa69rc5QtrvKlt/SHX ccpdbdPtq21J1OyyNLuX4uIne9n22kKrW9pHWG3+V+7CVaz3bP2eZ//ET7Gfu2z+we9qcspOY9Fe g49vcva/51OorXvvl93r2dvET5P6HJp2teBfGIuZalxCe/67X7vrihre6WiJ6qJ0VWJvL1N19Eod qtbH3tto19RhtavYX9XeS7bqoQn7uWdI1Xaco9s1TfZPiJ9Er9fa12qxfzba/1pXnWIfi3ceD84O Owps31UNSbpXk+0XLf9McxJ9YOmY/Y4m8TO/7Bat/f76b9um1Q+7rFXfyzlNu7ZUg/0kG8RP9rLu 3q5Rtu99wWjHYOs/7d34D45emvgvfvHMLf8O9fx5X2q9+odaotaL/4qXla/96Gu823mvvWYfGYou /m0vNReqkyoGcvdsyuw9zqzbdQ7aVaeqEzWUy/G/5c61wt/jng2qoWOnzz7qrb1afirITitU0Kmz fL16z7vQmiloS/Cf+/Pu3rFLsYkp7/OvxbgEzhlzxc/yUhPhtk51ndquhjs/E/7p1RydU0E04C37 qeaqIbva/tNEfOJgnRUNnb1N3CGsxlHX6ep2HN0VvYc4JOYXa239Xyv+T706ayrxpVY9vvss7z/3 UpFO+/vIbPewrwb1V+vf/V571/zC8vDlP/cz23Nla57x1j7PiLdnh05WFkOB/vgD7mBr78+VS9m2 /4VIzPG3JhRlr+d1qKmTuVSqsda/9vZeVg/szfSOyt0VOl38PC/rDgN3v36HJyQyZLu94oj2iKXG qr6qv6Vtu0WVbFuPrIgRSooilvZniz72SAZR9IH7agbvCjvnOE/tZObUODZQ3V7b8R5LZcZZv7to 3yUR0zriKt7b7gvpHWq/6+gUS6sSef3/nZfq0mn/zp07VD91p729brcj6zrX7Ha0aX++oT5SH1l5 S+fMJVFvb23cW9atbui03zEDSMy62vd27tjPvfcSu9VmtcWZd1ssS/DzvizF3ENz95F37NmXyd6t Wml7Y6KG3Cau3nNmmAtsr9ikNiRmifu49sfqY7sP4nurt7esNSh71QDvW2PPi+POvV7jzn8m116y 2zutjCsxq21pb73N3+y91epT61+xn5e11uVsrbW1+Weejdj99a+t22WK/8MvNdHWqITS7s0v4v8d 88BdtmTvDel0dKmdzS/9QVfcJP7Drz3yqHo1Tf06eU39e17nZxkj9Wyn/c/3cV6n9qpfqTOtf+3t 13Y78poF3r9vz+8j/m0v22JCHXv97Xtb2PmDGr5zrcpQ0+ztuahZ0Pqx1wanqGfsvTqoduJO0NY8 a69kv1HP0sUmNcaeh+baNTP5qaWmNjHLUhMYzSa7bpr902LlD8yQvnTuUp0onevNVKPITjIoJ9ge krw2OK3TvaOd91TU9u+W9pVna63k518v2bXOnVT3L3/2Y+XHdhnuWDmtE2K37PBHvuw+ClursMlX tUf9J7zLvl/M24P7OWrZSDXnzMTuBto5vlUzR/XEEu903l9N263amfZPcH/rANj6GP61SKyLj0m+ l/hRr5/mE772uPQvvrv2x6wZqLVY7qJ9Ht2Y+MxmL7N8y94XiUV7zWkX/YAGLEriX36RrVmevuV7 nv0fj5M/98v5XP0/sgrj2Mw+PidRzfYcYQ+rseqdz+4S74/9t6wh/dgXs5hmaBT/f335f5KrLPqX 35f0zqSx+LdrlPX6adbWyKZW738tYq/vqt3Fj3v9RFEv6dPJH/Cujqf40a04Yp/3iO+rfi9HBpJB D+Sn2/e6p71e6GQ/fXbV7OOVK378q499n+zvca3sPT/Z+kleP89V/xtf3299bU89TKwM5Ykf81rm MO/HXAR1/FT02dc3khLeuit76viOXstPpAjDxX/Zi1xk695Xbb/n+3/stzn67OveylTmXvMou/4n eP1E6xbqffuT4330QyKKYXVOrtdRdkS3PdfT/8n9mpLjk/P5xY9+Fmdtfx/zBrXG+R5j+2fN8eR6 e2v9j/kGZWLe+u9cSfppXt9/RpvcO1Zfqc+cuUA12+/a84G56tqkT+0n7NMvNuzd1navR7Gi/PxZ vQJ/7qibqWpUlVqu/rTbO5tUmHN3fSpprSScLjq+mcy8JSL2+0r67K0Fe/6JvxVM+9Z2fPvRtGdO zl2sb3t9z2uM3rlD9Wz/dNL+NMT63uBAe+8Le7Wl/fOO3bJOxqF6P1e11hRb1BQ730msQYbtnyLq X7X3p9ntTNyv1v7XWhEs3sf16uzvVYyxvtdo72ckHQvbV7NW/hMrnLt9dm/PORus74rus7H/znVa K3/dtU47nHvrdv8k+mjMzk2qi/PdyVq7X/hxxqLWXrVrsupFYl0wkQtbWzP3+x1O6xPmJrzIGq8C uyYxFlMSnyHbo1Vnr9Nan0ZX21ZgfWup0F5XTbqbc725jH3IXkf+kz2Gyeu0Qfu49W2hxArwF7u1 xPoOwBf/NWOx+6cwozqtmd+kMtRxiXzd/vyvxfa0gfaeNQoNdp3zPYTEty/sf6v3t5Jqj6LtVaJ9 zTzhAdYaecKya2zvTYx0YoXdGuer7GO7fcfDrmlSj9ir603OSA5Pvlene7/VeU/9f+x9C3xUxdn+ O7NJCCGEsOec3bMhhBBCCEkIYVlCsoSQ7P2ezV7ObjYXMUWkESlFRIqIiIiUIkVESilFpDQiIqWU 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 Hd9utriCYz+p4xrePwld+c7n+vylzma+9thl6e9gtuF47cs7Y/j9j9bu/E7gqKTsPRc+Oj0Y4v3a 2etzZX95Wzs+//2dHOO+PgnWd1lzaL9kzF7bKP7iGLx2/Yy9/I1zfWW7rm1e4Hf0cyV8Gab/xxUl /9mONdf0xgi7r5/2FP2O7/RXHP9Mrj+vkb/ZukVcoz/7bXUuahImUew9i2+EJb7qfeFrzL38yoxB uc5eDt/hca167Ks02de9v/2t+rnv5Xn9a1aK6Pvt5t+vPng/M8x0uZ+/01n56/r56kqRqKXf+vL8 X94X//J4voxr6Sdo6Nry/Wvj+W34Dx14dxnWY+tr/VPUemX2Y3eCz31XVunoA18zF15TG/7H1ln7 d+rpa9cb37DcfxjPiMWvnvnOr+bTeeRfG8/XfHwHT6b+OS7+ylwb4NserM2jkA++1vlyZ/OVX1dL 5evU/ZMnQfmIve9kKOOyD9f81i7jvJ3JnVdZ2OtXORdnxPd23vJVeAnTfukbTJeu5bnY5+7ON9RR 2m8Yf21H8mUt9fm9db7suLKqwnPw3Rx9r3Lxr5l/XV+I+5feyv4ujn9hpH+rg2OG1/8D9V7RXVfq pXAzt8cB2odmAmH7X4OKW+XE0TyaB/G0gBZcsdDpQofSYZBIS+lI6EYt1AKp1Eu90JNW0SpQ0yit AYHW0lqQ6HX0OtDQ79ExoKU30nGgY/tfQy9uv5NOJ9FJ0JtOppMhg95Gb4M+dBq9AzLpXXQ2ZNP7 6SLIpYvpYshje2FDPrfxKaAr6SoYRFfTX0MR2xEb9GxHbDDQ39DfwHD6e/p7KKFb6TYopS20Bcro H+kfYSTdRXdBOd1NW2EU2xcbTNzqx8z2xQYLfZUeBCs9RF8HO9sdG5xsd2xw07fp2+CjJ+hfoIp2 0DMQpB/RjyBKL9FOqGG7Y0MttwaqY7tjQ70qSdUNGlTdVSkwmu2RDY1sj2wYo5JVMtyo6qfqD+NU A1QD4CbpiHQExkttUjvczHY6holsp2P4IdvpGCaxnY7hFrbTMUyWzmuSYapGo+kN92lsmu/Dg5pb ND+BJzSLNWthv+ZJzU74s+ZVLYG/sV2PSaa2QttEctl+xySoXapdSerYfsfkBrbfMbmR7XdMxrH9 jslEtt8xmcT2OyZT2H7HZCrb75jcwfY7Jnez/Y7J/Wy/Y7JITpR7kAfZTsfkl7JG7k1WsD2OSbPc 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 d6jvgBL1neo7oVR9l/ouMKrvVt8NI9T3qO+BMmGUMApGCkEhCOVCWAjDKCEqRKFCiAkxqBTqhDow CQ1CA5iF0cJosAiNQiNYhTHCGLAJNwo3gl16QnoCHNKT0pPglJ6SngKX9LT0NLilZ6RnwCP9Ufoj eKVnpWfBJz0nPQdV0vPSi+CXXpIOQzitJa0Frk/bnrYdGtN2pO2A76XtTNsJY9J2pe2CG9J2p+2G sb0G9yqCG//7PO+/z/P++zzv/+/neQkTEqZ8yt5L1rKPKt9zwDTadtw02nPY024s8Rw3+UwZptme U54z1l0mh+d8ZWt5ktXkuVRywRvnTXLuqMwtbzU5vKmmkGm2V2Oaat3lTbeaMCbLm+stNMleQ6XB a/RWeG2WVK/HG/BGvQ1lRd4x3ibvxIoV3iklG73TvbO8c0dd9JyxLfUavLayed4F3sXeZaap3pXG M5i22bvOfbK80LvRu6Ui0dtiPuzdOSqhZKe31bvPe7Cywx71HvG2eI96T3g7RslGvWdC2STvWe8F 22r7CR/4EuxjfMmVHT61T/a2+DKMel+C+bgz0Z3gOVDZWnkBr2BKZa7nuMfFrtSX7cvznCkr87h8 Ra6kERqrqTTDtN6bZE7xFfvKjCW+vPKj5m3GbT6Tz+Hz2Tt8Iec2d4IvVr6svNA01TfaN9a+zrOh rMhz2DfemVlyomKzb5Jvqm+Gb7ZvHmu9ZYuxzrvTXOdtte7xLfQetK9jrcf2tviWmA+XbDTqy5fZ dngv2Ff6lnsOuDoqW32rKqf41lRm+dZbjvo2YeuOX26b7bhvq2+7OcWcWdHo22VOM2eWL/DtGZVQ nuvb7zvka/Mds2U62kw+30nfad8530WPy7nDm2tsLJtnClUanLRiRRWtSrSvq0qpEsuKqtK8Y0xy paEqsyoH78bBqoLSbGdOydkqvfeoO7mqpKrcfdJ6uuKwJbXKUuXy2sovGHNMqzwrvFssnopEV5J3 p6Ooyl+l+GR7K15Rq7elqs58uHKiUV/V6Gn0XvA2VI2rmlDSXDW5alrZqqqZ3immjIo59gujZN9C 8xlbXdWcki2YZ77X6JArPaUZVYuqllaIVSsqL1StrlpbtaFqc9W2qh1GvU0pn1sxzjvL2Gi9aJvj 3GveVmayhnwJpuLKDttq7NGsisM4eh2OvKrd5m3WXeUHjSVVe0uB3duqA9ZdVYc9K3Bsl7A7W9Ve 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 xLPiOXFjQX7RpKs2bo5b4jZXb9ztvBUPxCOxU8q+uEY+aUtfsUj6jHych8NH4yvKD5QfiK+MN8Sb 4s3x9eW25XXxTcVtsVPxLfH2eGdRJL4jviu+x7nPURTfF+uxt8X3xA/ED8cHiK7sjA+WZ8VPxE8u 3xsfi43YuuJn4xPxi/ErJNVk7HK5EL8RvxWfic/G5xPkmeGjzsOxvbGRxMLEokR+ojBRYh1I2F3V CU9CSkQTCU1JVCdqqVYk6hONiTWJdYkNVKMSrYm2xDalObGdaMVkojuxO9Gb2E/7T9mXOJjoTxxN HE8MJ0YTpxPjysXE+cQlpT0xnriamNJWJaYTt4kGaIm7ibkklzQks5O5SVOyKGlNOpO+pKycSCrJ VDJDNHClsidZl1yVXK3sSq5NtignE7XJjcnN8U2u6lhXSb9zR3JrssMa8XuSXcmdyR5Pd3Jv2Q5L i+aMDSX73COWltip5CFXr7M5eaRsj+Xy0ubkseRQciR5imh1gOR1JnlO7U1eSF5OXkteT95M3lEC zsPJe8n7KUEdT2VZWlI5KWPKrJ5OWRJiypZypwKpiFqd0qjupdKpFamV9qlUQ6ohtjfVRD7NS+pS 69Wr6rR6KbUpdi21pWyP5ly2ieTSnuqMdaV2pHal9hRtSe1LHUgdTna4j6QGUoOpE6mTyuHUWOps aiJ1MXUlNUnqakrdSN2iepiaSc2m5ivFyoWViyrzKwsrC5WGypJKe6UnuVbrSF5XxiqlxLAyWRmt TCiDldWVtZX1lY2VayrXVW6obK1sS2yo3Fa53dmuDld2V+6u7FVPV+6vPBi/4tle2V9Jer9oj7PZ 3lZ5vHK4cvQJn+u8pW/xjmXpytOV45XnKy9VXq2cqpyuvF15NzZSOZfm0gaSvimdnc5Nm9JF1oG0 tWxP2ultSfvSclpJp9KZdF16lX06vbrols/tOp9em25Jb0xvTm9Nd5TneLalu2Km9M50T3pvus+9 2b05faj4UvpIan3h7aKG9LH0UHqkIJ/cfar8QPqM/W65rfBg+lz6Qvpy+lr6evpm+k7iUvpe+r4j 27WmSqjKqsqpMlaZi85WWapsVe6le6oCls1VkSrNdKUqXbWipL9qZVVDVVNVc9X6qk1VW6raqzqr dlTtqtpTtS+1vupA1eFUJNYR6yo/UDVQNcjm4KpmOv9WnSCz7wU68zrbS/pjO5Md6umqk2Qmqbb3 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 AGnY7oABCP+2CL+ZjvmiB4Bfpsj1cP2vvxVFmfjD90++uYW+A47TsbemkKs+5RjBvcoQkfUph8iv oHQrx8nVbqWX/Ao0Jbmib40bI1cblVPkarOylfwKygZllFytw+9/9L+x//AWF90G3ZbX/+aMUvTH X/7zSofSpexUekhZaDmOKMeUIWWEhE8pZ5RzygXyvaxcU64rN5U7yj3lviqoWUqHmqPsVI3KXtWs HFMtSp9qU93KOTWgRpDyDInbrGpqWl2hrlQb1Ca1WV2vbiLX9GqL2q52qjvUXeoedR9JdYCWQT2s DpD8skgJzpEyjChWWgJ1kOR6QrmgnlSuq2PqWfL8CfWiekWdVG+ot9QZdVad10RtobZIy9cKtRLN rnk0SYsqHVpC6dKqtVplr1avNWprtHXaBpLjEZYfqfF1rVVrU+5r27TtWjf57NZ6tf3aQa1ftWhH tePaMKkLaQttVDutjWvntUvKOe2qNqVNa7e1u9ocqYk7zqkr4oZ4tjoWz1XOxU1KX7wobo074z5t jtSiLy7HFeV6PBXPxOtIylVaQtuv7IyvVo3xtVoi3kJybCSpNsY3x7fSOsc7aJvHu8gdO9UIrTO5 u4d8SLvE++KH4kfix+JD8ZH4qfiZ+Lk46Zv4ZXJ9LX49flNrjN+J3yPttzd+P0H163oii/TsTcWa yFGGEkblsiooRxLmhJnU/nLCop0naXcmbKT9aT/RnlpBeqlTsyfciUAiktASaYIrEisTDYmmRHNi fWJTYkuiPdGZ2IE7VpJPZ2KXNpXYo5xK7EscSBxODKjpxGDiBMnhZGIscTYxkbhIWhqfxJX4vcRk 4kbiVmImMZuYT4rJhaQ1LmjVyUXJfK0xWahe1NYlSxKWpD3pSUq0h4iuCcmoYiK1255MJKuT1cqx ZG2yXttAyr892Ui08Fy8j7RiNcllDenL/cl1SktyQ7I12ZbcltxOcu1O7iblXK+mk73qyoQ7uT95 MNmvScmjic7kcaJ/K5LDydHk6eR48nxiQitMnMTVpeTV5FRyOnk7eTc5l8hJcSlDKjuVmzKlilLW lPOhZhOdTvkSg2pDYr16QjtPx1xeKo+eZha4/f+H3oWwncwvXRz1N+8gHw/XTT5ebie3m+RN/2Jf CO9FCHNnyCdCbMuz5Gn0vQhRvBchhr/Pp/Iir+fi/FH+KJfE+wlSeD/BGkERFG6toAlx7nkhKSS5 F4RKoZJbJ1QR6/BF4UnhSe6dxF6r5dYLbxfezr0kPE2s/A14k8G78CaDLfh7ezvx9/Z20zcZcB/D X93rEb4qjHGfEE4Lp7lPCt8Xvs/tE/5Z+GfuU3jr2X689ezTwq+EX3F9wl1im35GeE14jTuA95p9 Vk//7/VB/QL9Au6w/k3EVvu8/hH9I1y//lH9Iu4LeqN+Mfc39H0G3BfpOwy4Y/QdBtyX8sg/bjBv SV4B92X6l/O4IfrGAu5V+sYC7kf0jQXcNfrGAu7H9I0F3E/oGwu46/SNBdw/0zcWcNP0jQXcz+kb C7h7xiXGEu41o9Vo5XVGm7GMF41Oo5s3GL1GL/8mY8AY4BcaI8Yo/wjeYZBjfM64ln8MfxvvceNG 40Y+1/he43v5PONW4/t5o/EVYwefjzejmfFmtKV4M1oh3oz2hPG88TxfhL+NV2ycN87zyxZzizm+ ZLGwWOCXLyb/eOti02ITX7r404s/zdsWf2bxZ/myxYcWf453Lv784s/z7sVHFh/hyxcfW/wl3kPf Z8D7Fv9k8RQvLZ5ePM3L9H0GfJi+z4CP0PcZ8BX0vQV8lL63gI/R9xbwCn1vAa/S9xbwjfS9Bfwa +t4C/jn63gJ+LX1vAf88fW8B37zknkngXzBlm7L5VpPZZObfQ//+HL/ZpJo0/r2mT5n28+8z9ZkO 8C+bPm/6PN9u+oLpC/wrpmOmL/HbTF82Hec7TK+aXuU7TSOmk/wHTaOmUb7L9HXT1/kPm86YzvE7 TBOmb/N/afqO6Xv8x0yvmV7je033Tff5vypIF1TzewvqC+r5TxU0Fqzm9xc0FTzLf6bghYIX+M8W vFTwEn+wYFPBJv6vC1oLWvlDS2uX1vKfK/x44cfp/zTierkDr6+JoYX/5vsn13HZHDNwOtkoN5Bf Qc6W6wgaovNExskp8iuEZqP3OV1oRpaiO8nVzehdcnVdtpFfIXQ1OkOuLskm8iuEJqJ3yNVZeSH5 /ePZ4/W/F7dHv4uWk6/m6jhOan7j+5/5Rgkvi17kP19xsKK/4mjF8YrhitGK0xXjQQ/92xoVV+Xa iqmKaSKdrrhdcbdiLspFDZISzY7mRk0VB6NFFUej1orhqDPoIb9Xo76oXDEdVaIpmrJiisj6o5lo XXRVdHV0bbQlupF8N5NrerU1fDPaEe2K7oz2RPdG+8jTaBlGo4dIfqaK8YppUoZL0SO0BNFjJNch Ih8h+Z6KniHPPxe9EL0cvRa9XtEvXY7ejN6J3ovejwmxrFhOzBgzxywxW8xdcTAWqOiPRWJaxXAs HVsRWxlriLSTHMdZfqTGc7Emkld2rDm2PrYpdCK2JXot1h7rjO2I7YrtiR6L7YumaFvEDsQOxwYq jsYGK6ZjJ6J9sZOkXqRGsbHY2dgEqd+92MXoqdgVEjtZMRq7EbsVm4lNRlvI9WxsPnqkYi6coh9F lIdjAWWhskjJj1qVQlpbpUSxV4wqntgJRaJ1ls7QNleiSkKpVmppnSvmlHqlUVkTNZGcIxVXwWtb lTZlm7Jd6SZpd8v1hBPvrzhO6rhPOUjab1jpV47GBpTj5EnDpNeOKKMV55XTyng0t2JcOU8+lypu K1eVqaiJpJgmtckot2NGUpNVyt1oB2nBHEVU5pS7KqfMqQY1W81VTWqRalWd0lbVp8qqgp5dHV2t ptSMWqeuUlfLx9W1akssh8j7SF6r1Y3qZvLZGu2oOKosol+1Q+2K3lN3qj3qXrUvdlg9pB6JtVcM q8fIZyi2Qh1RT0mrwrJyVT0TPaKeoz1EdC23ol+9oF6OrVevSeekc0GPel29qd6pGCeSe9EipSR2 o2IaedyPZmuClqXlaEbNXHFQ6VaPKfZIO8qpaBbSV5vVjGbT3FogZtMimqalyXeFtlJr0Jq0ZmlI Wx/LUTfialNoXtsS3au1a53aDm2XtkcjbRu7pdyO9mkHtMNMs0lrtWgD0b7oWm0wOqSdIHOTg/8y /2UyNb3Kv0pP8PNf4QT+H/h/4HT8GD/GifwZ/gyn58f5cc7AT/AT3AL+An+By+Iv8Ze4N/FX+Cvc Qp1X5+UeyW3LbeOyc7fmbuUezW3PbedycrflbuMey+3I7eAW5XbmdnKP527P3c7l5nbldnF5uTty d3DGvOI8O7c4z5MX5YrzEnkJzk1mzXquPG9V3ipOy2vIa+Diec/kPcMl8t6R9w4umfds3rNcKu+5 vOe4yrzn857n0nkv5L3AVeW9mPciV523Pm89V2P+qvmrXMb8NfPXuCfNXzd/nVth/ob5G9ybzf9o /keu1vxN8zcJQ3uD073B6d7gdP+FOR1/kmjoH7iSS37j+5/5+g+R75E/zX2l+6EthK9uCbWHOgl7 3RjqINhCUBfqCHWFKNttDHWTq/pQd2g3uVoR2kWu0qFdoT3kSgn1kCsZv0LIE2olV/ZQa6jt/+pV 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 Yo2UVWJXK6vEmiirxK5RVomVKavErlNWiV2vrBJrrqwSa6GsEmuprBJrrawSa6esEq2HZHdoJSS7 wzoou8Nuhtd3i7I7rFzZHXarsjjsNmVfWFdlX9jtyr6wbsq+sDuUfWF3KvvCeir7wnop+8J6K/vC +ij7wiqVfWFVyr6we5R9Yf2VfWH3KfvCBij7woYr+8JGKvvCxij7wh5U9oWNVfaFPazsCxuv7At7 RNkX9qiyL2yysi/sMWVf0MPaX1rrj+r6/9eMYW68pf9yp/RL492UpSkrUlanrEvZmLI1ZVfKnpT9 KYdSjqacSDmVciblfKqRmpqakeqkxlMTqdVSa6bWT22U2jS1eWqb1A6p5andUitSK1P7pw5JHZU6 NnVi6pTUmanzUhemLkldnroqdW3qhtTNqTtT30ndl3ow9XDqsdSTqadTz4ZYKBgyQ5GQF8oNFYWq h2qHGoQah8pCLUPtQp1CXULdQ71CVaEBoWGh0aFxoUmhaaHZofmhRaGloRWh1aF1oY2hraHdob2h A6FDoaOhE6FToTOh86ZhppoZpmPGzYRZzaxp1jcbmU3N5mYbs4NZbnYzK8xKs785xBxljjUnmlPM meY8c6G5xFxurjLXmhvMzeZO8x1zn3nQPGweM0+ap82zYRYOhs1wJOyFc8NF4erh2uEG4cbhsnDL cLtwp3CXcPdwr3BVeEB4WHh0eFx4UnhaeHZ4fnhReFl4ZXhNeH14U3h7eHd4b/hA+FD4aPhE+FT4 TPh8mpGWmpaR5qTF0xJp1dJqptVPa5TWNK15Wpu0Dmnlad3SKtIq0/qnDUkblTY2bWLalLSZafPS FqYtSVuetiptbdqGtM1pO9PeSduXdjDtcNqxtJNpp9POprP0YLqZHkn30nPTi9Krp9dOb5DeOL0s vWV6u/RO6V3Su6f3Sq9KH5A+LH10+rj0SenT0menz09flL40fUX66vR16RvTt6bvSt+Tvj/9o/Qj 6cfTv0z/Nv1chshIzkjLsDJiGfkZJRk1MupmNMxoktEso3VG+4zOGV0zemT0yeiXMShjRMaYjPEZ kzNmZMzNWJCxJGN5xqqMtRkbMrZm7MrYk7E/46OMIxnHM77MOJNxPtPITM3MyHQy45mJzGqZtTMb ZDbOLMtsmdkus1Nml8zumb0yqzIHZA7LHJ05LnNS5rTM2ZnzMxdlLs1ckbkmc33mpsztmbsz92Ue zDyceSzzZObpzLMRFkmOpEWsSCySHymJ1IjUjTSMNI00j7SJdIiUR7pFKiKVkf7kDY4ib29iZEpk ZmReZGFkSWR5ZFVkbWRDZGtkV2RPZH/ko8jRyInIqciZyPmoEU2NZkQ9sotF0erR2tEG5P+VRVtG 25O/15VWzD7RftFB0RHRMdHx0cnRGdG50QXRxdFl0ZXRNdH10U3RndE90QPRw9Hj0VPRM9HzlmGl WhmWY8WthFXNqmnVtxpZTa3mVhurg1VudbMqrEqrP9nNMdZ4a4o105pnLbSWWMutVdZaa4O12dpJ dnS/dcg6ap2wTllnrPO2YafaGbZjx+0iu7pd225gN7ab2a3t9nZnu6vdw+5j97MH2SPssfYke4Y9 z15oL7GX26vsdfZGe6u9y95rH7SP2MftL+1v7XOOcJKdNMdxcp0ip7pT22ngNHbKnJZOO6eT08Xp 7vRyqpwBzghnrDPJmeHMcxY5S50VzmpnnbPR2erscvY4+52PnCPOcedL51vnnCvcZDfNtdyYm++W uDXdBm5jt5nb2m3vdna7uj3cPm4/slMj3LHuJHeaO9ud7y5yl7or3NXuOneju9Xd5e51D7iH3KPu Cfe0e9ZjXpDWhIjnqeh4XnWvrtfIK/Nae+29zl5Xr4dX6fX3hnijvHHeZG+GN9db4C32lnkrvTW0 ApDd9/Z4+72PvCPece9L71vvXJbISs5Ky7KyYln5WSVZNbLqZjXMakJrQJusTmT3K7KqsgZljcga kzU+a3LWjKy5WQuyFmcty1qZtSZrfdamrO1Zu7P2Zh3IOpR1NOtE1qmsszERS45lxJxYPJaIVYvV jNWPNYo1jTWPtYl1iHWJ9Yj1ifWLDYqNiI2JjY9Njs2IzY0tiC2JLY+tiq0lb2trbFdsT2x/7KPY kdjx2Jexb2Pnso1sM9vKjmcnsqtl18yun904uyy7ZXa77M7Z3bIrsiuz+2cPyR6VPTZ7Yva07LnZ C7IXZy/LXpm9Jnt99qbs7dm7s/dmH8g+lH00+0T2qewz2efjRjw1nhF34vF4Il4tXjNeP94o3jTe PN4m3iFeHu8W7xXvFx8SHx0fH58Snx1fEF8cXxZfGV8TXx/fFN8e3x3fGz8QPxQ/Gj8RPxU/Ez+f Y+Sk5mTkODnxnEROtZyaOfVzGuU0zWmZ0z6nPKd7Tp+c/jnDcsbkjM+ZnDMjZ27OgpzFOctyVuas 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 zYros5XDCyF0RgviLVnpNZk9bp1Dm6B9EboWQuinVtrmMDCHi1b+ScuYRG8pkUqoVOjZ1Wb10NnK oT3UT4M0TOfFnHeFrtEI3aK79FDMlc9pil4be51M3/RSZfqyZHg5chGbWoDctpcIeLI9Q55J72Xv Ve+ob9R30xfxTf49GxbxDz6W6xMKZW5kc3RyZWFtCmVuZG9iagoxMSAwIG9iago8PAovQmFzZUZv bnQgL0NJREZvbnQrRjEKL0Rlc2NlbmRhbnRGb250cyBbIDw8Ci9CYXNlRm9udCAvQ0lERm9udCtG MQovQ0lEU3lzdGVtSW5mbyA8PAovT3JkZXJpbmcgNCAwIFIKL1JlZ2lzdHJ5IDUgMCBSCi9TdXBw bGVtZW50IDAKPj4KL0NJRFRvR0lETWFwIC9JZGVudGl0eQovRm9udERlc2NyaXB0b3IgPDwKL0Fz Y2VudCA5NTAKL0NhcEhlaWdodCA2NjYKL0Rlc2NlbnQgLTIyMgovRmxhZ3MgNgovRm9udEJCb3gg NiAwIFIKL0ZvbnRGaWxlMiA4IDAgUgovRm9udE5hbWUgL0NJREZvbnQrRjEKL0l0YWxpY0FuZ2xl IDAKL1N0ZW1WIDcgMCBSCi9UeXBlIC9Gb250RGVzY3JpcHRvcgo+PgovU3VidHlwZSAvQ0lERm9u dFR5cGUyCi9UeXBlIC9Gb250Ci9XIDkgMCBSCj4+IF0KL0VuY29kaW5nIC9JZGVudGl0eS1ICi9T dWJ0eXBlIC9UeXBlMAovVG9Vbmljb2RlIDEwIDAgUgovVHlwZSAvRm9udAo+PgplbmRvYmoKMTIg MCBvYmoKKElkZW50aXR5KQplbmRvYmoKMTMgMCBvYmoKKEFkb2JlKQplbmRvYmoKMTYgMCBvYmoK PDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aCAxNTU4NDEKL1R5cGUgL1N0cmVhbQo+Pgpz dHJlYW0KeJzsvQlgVNXZN37OXWbf931fkkwyM9n3ZAJJSIBAWIIJEAhLAEElbKIoglVRqbgvVatQ q9UWl2QACYJKlWpbpbVKtdVqbbWvtTXVWpcWyeR7zj0zWVgUbd/vfb//P2fyzO+e9Z7zPM9ZnnPP nSCMEDLBF4e66mc1Twrf2WxG/JTfIOQ80jChfvavj8beRXjmdxFSPtAwYerE72df+RbCLbMR4psm 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 9GD0UPT56AvRw9EXo0eif4q+FP1z9OXoK9FXo+qMkhDyQ8hPBPmx/XjGRsdFx0cnRCdGb49Oit4R vTN6F9/1h+iM6P1cwgeis6J/jD4YfQjPqDzsieLMEiWP9nP2fvuAyqm92d5MZD9vv6ByKnbQO+Yo c7Q5xhxrjjPHmxPMiebt5iRzj/mMudfcZz5r7jcPmM+ZB81D5vPmC+Zh80XziPkn8yXzz+bL5ivm q1bISrDCVqKVZCVbKVbESrXSrHRLt/JYhhW1TMuybKuIVdTKsopZxa0SVkmrlFXaKmNlW2WtclZ5 q4LV2GpiNbWaWc2tFlZLq5V1i9XaamO1tdpZ7a0OVkerk9XZmmTdYd1p3WXdbU22plj3WFOte61p 1qPWAusxa6H1uLXIWmett560NlgvWIetF60j1p+sl6w/Wy9b/7C+sP5pfWl9ZX1tfWOdtr61ztia HbIT7LCdaDe0G9mN7SZ2U7uZ3dxuYbe0W9m32K3tNnZbu53d3u5gd7Q72Z3t7vZoe4w91h5nj7cn 2BPt++zp9h/sGfYqe7W9xn7CXmuvs9fbT9ob7N32HvsZe6990D5kH+b/B+237Xfso/a79jH7Pfu4 /b59wv7APml/aH9kf2x/Yn9qn3LyOvmc/M5NTgHnZifTKegUcgo7RZyiTpZTzCnulHBKOqWdsk45 p6pTjdswwxxgjuRR5w6TJcT8i3mCbrYcqzCVtypajaie1cXqQ+2t+6yZ1NNabC2jftZGaxsNsl6x 3qRR1nfWj3SHnWTnpSl2F7sLzbNvtfvQI/bt9p20yL7fnk3L7I32Flpn77OfpY0sOc/RZsjLFvtF +y3aan9m/0iHnFJOKXrDKeNk09+d8k4FeoulqTQ9Yq4215hPmGvNdeZ680lzg7nR3GRuNreYT5lb zafNbeZ2c4e509xl7ja/Nc+Y35nfmz+YZ80fzXPmefOC+ZN50bxkXjavWGQJS7NGWCOtUdZoa4w1 1hpnjbcmWBOt263Z1hxrrjXPesSab6221lhPWGutfdaz1n7rgPWcddA6ZD1vfWCdtD60PrI+tj6x PrVOWZ9Zn1uXrMvWFVbXhF3WLmeXtyvYFe1KdmW7il3VrmZXt2vYNe1adm27jl3XrmfXtxvY3ewh 9lB7mD3cHmGPtEfZ99hT7Xvtafbj9iJ7sb3EXmovs5fbK+yV9nZ7h73T3uWkOBEn1Ulz0h3dyeMY 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 qVRen65Ppwr6/fr9VFF/QH+AKukP6g9SZf1h/WGqos/V51JV/RH9EaqmP6o/StX1x/THqIb+uP44 1dQX64uplr5UX0q19eX6cqqjr9RXUl19tb6a6ulP6E9QfX2dvo4a6E/qT1JDfaO+kRrpm/XN1Fjf qm+lJvo2fRs11XfoO6iZvkvfRc31PfoeaqHv1fdSS32/vp9a6Qf1g3SL/rz+PLXWD+uHqY1+RD9C bfWX9Jeonf6y/jK111/VX6UO+mv6a9RRf11/nTrpb+hvUGf9Tf1N6qK/rb9NXfWj+lHqph/Tj1F3 /YR+gm7Vv9S/pB76N/o31FP/Vv+Weunf6d/RbfoP+g+kTig0KCwGhi39p8TLyXXVuzR8RZHEAMH9 O2F3wm71tcfESxRSXzvHuzTuVWJoohoZNTEk8T3CiRUJ6v2sCKl99XkpkmAnOAkywU3wEjIS8ibk S8ifoL5rJxIKJBSLeZXZWq2tKe9U7GvMMU5LbTjlfM1YE9/Tj1o5rbJWje9oyLw2Wjuts9ZN66H1 14ZqoyNdI5MZv+Ev8kjwx7EEf9Wu/0V2B3+c6o1/Da/5NeG8BX9trv9FTgd/XJaf+aXODP64zMFf txv9UjcHf1xLwV8v/K7+3f+a3yD+Df2Z3+gb/VIvB39pxjW/jGt+hYI/v3yx/CIG+r9fnb7xV6fV iX75oEXGdMju3HOv6nHxWtx62kI7aC8dpCP0Kr2h9GHuDzX/DVrt36Jt/h36M1+2VmcDP6xGFXzN UP1Vk3JOSk3OOdUUGksBjB9qdVyCOlvdP4F6qx/KOR326hnEOedax+IYSGnqTXCuNhhfy5pRJF19 fasEaDZoZdAqoFVBq4FWB60BWhu0A+itiv7G7yhOZO3UPysvV/uO173/s3w1BG1xXR7/7RMrEwrg e1r/6svJY8UkMUVMF7PEHLFALBGrxHqxRX3rTxwUR9TXAMVRcUJ9LZC1m7PioqZpyZoe+/qglqWV 1iqwlNXhkaAFjwCdeQzrqw3WRsa+f6jNwPcRF2rLtDXaBm2rtkt7Vntee0l7TXtTO6ad1E5pX2pn tHPa5VBCKBIyQjKUP1QoVDyUHaoUqhGqF2oSahVqH+oa6hXqHxoaGh2aGLo7NC00M/RwaH5oUWhF aG1oU2hbaE/oQOhw6OXQ66G3Q8dDH4U+D30d+j50IYESEhPSEswEj7RwSno5tI+iRUGzQIuBFgct AVoStBRoadAyoNmgZUHLgZYHrQBaEbQSaGXQKqBVQauBVgetAVoTtBZobdA6oHVB64HWB20A2hC0 EWhj0CagTUGbgTYHbQHaErQVaGvQ9qAdQDuBdge9FbQHaE/Q20B7g/YF7QfaH3QA6CDQwaBDQIeC DgcdAToKdDToGNBxoBNAJ4LeDjoJ9A7Qu0Ang04BvQf0XtBpoNNBZ4DeDzoT9EHQh0AfBp0NOgd0 Lug80EdA54M+CroAdBHoYtAloEtBl4EuB10BuhJ0Fehq0DWga0HXga4HfRJ0A+hG0E2gm0G3gD4F uhX0adBtoNtBd4DuBN0Fuht0D+gzoHtB94E+C7of9ADoc6AHQQ8p+r/g1NYmlBk9G/0xei56Pnoh +lP0YvRS9HL0SvSz6OfRf0S/iP4z+mX0q+jX0W+ip3N530bPRL/zed9Hf6BfPuFSpfB+9ET0g+jJ 6IfRj6IfRz+Jfho9FX0t+tfo69G/Rd+I/j36ZvSt6NvRd3J5R6PvRo/5vPeix38xBSESKfO6eWAi 3Y0vBD9M82kRraC1tIm20R46QIfpZXqd3qbj9BF9Tl/Hvm9PmqlF3wc9AfoB6EnQD0E/Av0Y9BPQ T0FPgb4G+lfQ10H/BvoG6N9B3wR9C/Rt0Hd+8dmjoO+CHvuZZ98D/X1qKBz6EvQr0K9BvwE9Dfot 6BnQ70C/B/1B0ehY0HGg40EngE4EvR10EugdoHeC3vWLz84EfQB01s88uwt09y/XEE5Jja1900yK qhN2Q1F1fm5CtA9deyLqv9CMnJHevaBjQCeoE+G8FaB/BH2Q+aNwzyjcMwr3DME9Q3DPEHXPNauL 1XvNlNjavEC6mjPcE6CTcYrbkwjfDXoPOBtAp4AzB1Sd1xc8Sw6ao/0cxc5di9MJ+S8tOoZip67h rqhaSRM732Ia1fE0L+QleGEv0Uv2UryIl6rOz1KnZ3mWZ3uOJ70ML6+Xz8vv3aRO0PLUKV0lvVJe aa+MV9Yr55VX52ep07PU2Vnq5Cx1bpY6Nctr7rXwWnqtvFu81l4br63XzmvvdfA6ep28zl4Xr6vX 7Xdd25JNtpfm5fFMdW6UV8Ar6GV7FdQpUV51r5Y6G8prpE6FwplQ/9NncyVjBXDOiVLFKeoud1e4 K91V7mp3jfuEu9Zd5653n3Q3uBvdTe5md4v7FP23zlvSKUGtBOP/yt/28ycHCdIhQyw95iiKnaOB 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 77LfNfiuCd3W6sembnnd9nVvxdGpe2aPgz3D6nH39Ls3akdlr1a9lurHh3dX0l/ay6P1PL1+5lh6 j7N3Zu+cPskP9ObY2y/t7un1V9N66q96qJ163UNd+9sQarv+iwbEa0e3AcO0IzTQOLD5wNYDQrxK 43h2kBhkGTRmUHhQeHDLwT6u6zZk+JDhA9P49yn1FcfYIZOHzE6zaEentMHakZ42EdLTpqa9mjaV 9yeneYaOGpo+tGZozbAmwz7kuk68p70z7Je0qQ8/9fCER1x/vH+E+4lFT7z/RM6fX/2zZ+yjY6de bseuH7t+3G0TsyeufiE8SUzqNSl90vhJGZNenbRp0q5JFZOCk36ZbJnsnNxxctfJ905Omxx8scmL 7V584cWZLy56ce+LZRndM4ZnbM4om9JiytEpdZm3ZT6bOTXz/cwtL7V4afhLm6eOnfrm1C1TXVPL smxZLbP6Zi3K2j+t7bS+08ZOmzZt7rS10zZNO/Ky8+W+L694efPLB6dbpjef3n/6mOkbp1fO6Dgj Y8bGGWUzW83sOnP8zHkz3bOcs0bNWjfLN7vl7B3/ImptioxMjePO7IrfDjWivBL/21EfS/6F9/WP 9LnGnlJv61eNP5djUIOjcRR5petvhxofXrn3t6M+MqjRtElO873NlhKRj/byED+1aKy1RN6E/kTa JfGrmiyK2385eiZkxx1NONtmhHpv3Kb4Jb9F0XopEad7aZG4/qqW8asuS089q0Vl9dqj6vva9boE GXdT3HFi+iruOKqNtp/ZLaI9qh2/5YmKiPzQq0FG+C0nrFLn/bs8kBOZB4j9Zj3uz70c8bVxuDu+ F6+XXI6F6GOdri+iU30Eqo9wuh6JisRAVWsjrsTHyxolyjXvr17/m4bb9GUc9f0Q59NSyun3v0oE Ptogml4lxjaMqb+Pp3rU3qvZUX0E7X05dqoxnTN91XHp922edmf7IcOTLtVnMq0lazWrI1ddSraT h/TMczmjJCYnXfot+9Tbo5rf1OuTLqlXcPeuZLv6jnpGy2WcUd9LTI7bf9lOm7fg/TKewBjN5mo9 7fxvGbVhTlXnpOXPyxn0Sg5V/+fmq+TMpb/LmYX1mZIc6by8Ft6vq5+HNpO5A7ol/dj8fubWSBuq FCM997LE6z1SlW29xbQZgfT7q7pV5dI8zblU0/w6VVMNvPuWlI2JyVdy7VF91Nn19qDqpd6+Ujbe 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 fZShjzL0UYYEA0gwgAQDSDCABANIMIAEA0hQ9QY/3uDHG/x4gx9v8OMNfrzBjzf48QY/3uDHG/x4 gx9v8OMNfrzBjzf4/wNv8KEhHxryoSEfGvKhIR8a8qEhHxryoSEfGvKhIR8a8qEhHxryoSEfGvKh IR8a8qEhHxryoSEfGvJpOb6aqvSkuPNK9FpKxKGWRPYBZP//JqKMgWfgWfgzjIVxgM5ZY4A1Blhj gDUGWGOANQZYY4A1BlhjIFa1hSmQCS8B9sYaA6wxQI2byYp+85kAHh8i3qqeHiamhv+dj1C7Z1Jj z8WOX8de3+L1Amqlhey+l4tEMRjJBZFcUKvKZ8BMrppLO5+4/yaw78M31eyscFcHrbpdxusVsgYJ 12Dd1Vh3NdZdjXVXY93VWHc1kg8i+SCSDyL5IJIPIvkgkg8i+SCSDyL5IJIPIvkgkg8i+SCSDyL5 IJIPIvkgkg8i+SCSDyL5IJIPIvkgkg9ifdVYXzXWV431VWN91VhfNdZXjfVVo5kaNFODZmrQTA2a qUEzNWimBs3UoJkaNFODZmrQTA2aqUEzNWimBs3UoJkaNFODZmrQTA2aqUEzNWimRtutnEdSB67s WxRh0vY17KTR0kXxCLJ1I1s3+qtGf9Xk0nO8W4omYpFvJfKt1OLfQrS0lIiyjEppBRXse7IKuVYi 10rkWolcK5FrpU3NDUbpRq5u5OpGrm7k6kaubuTqRq5u5OpGrm7k6kaubuTqRq5u5OpGrm7k6kau buTqRq5u5OpGrm7k6kaubuTqxqaqsalqbKoam6rGpqqxqWpsqhqbqkbulci9ErlXIvdK5F6J3CuR eyVyr0TuVci9CrlXIfcq5F6F3KuQexVyr0LuVci9CrlXIfcq5F6F3KuQexVyr0LuVci9CrlXIfcq 5F6F3KuQe5UmY1Xup5HxLyLRuBVLzpd7jLuwy+9khvF7+YmxVv5oPCffNF6QP5jiZLmpszxtulWu M3WVZVd+T/lR0cL0R+HQf1+5HG3loI2NeNgurP87atjdaGIPfI+n7UMzB3jtohY9iiaLad1QKZKM VWSxc9wX5v7zUMfThDxhskI0kBt5ut90O+dToQvcIc+aeshT9nQZsD8jC+zPAfHB/jwt0rAjDTvx wP4y7QxZaZ8Js2AO5xZw7m3IBvY79nc4txTe5TXWY1/FGDkybP+c8b+ATfK0/UvYzLm/0t9Gy5rs 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 Czg7OJWa3cB9rpSag7aOmiM1x22barpqztCcl+a/NedrLtVcDdHdjLUa9pdqI1RN8uy1NhoYx7mq TawdWTumNhF0GjCjNrM2295da6512rt5Dlvrry2uDaoz1to6YAtwquNE7QzHntrZtfN6keeY+SbG 2gW1i2uXqfPK2pW1q2vXOa7VbqzdQkh84myr3anOMWsTgWnADPbiavcA9wMP1R6tPUEzR5o/1p6q PVt7gWaLNIusvVx7rU7Yt9bp6iIJ9XVGmiEm1CXZOrhe6kYBx9pO1o2rG183sS7HfrDOWud27qor qCt1XqyrqmuwBuva6qa5skqn1s10J9bNqZvvzXLvd20memHdkjJ93fK6jro1devrNnkT6jrrtrvP 1u2q22tq78MDwdN1h+uO1Z0kPA08R3ix7krd9Xq5Prw+qt5ATy1T53SlU+vJ5tcn16fUp9an10+o z6o31dvrvaWH2H4yehPqA/Xl9TX1TR53/ZT66YSzPNb6ue5r9e31i+qX1q+oX1W/tn5D/eb6rfU7 6nfX76s/WH/Ec5Gx/jjbyfoudW6lYv2Zehqp6y95J9Rfre9u0DRENEQ3xDUkNoxsGNOQ1pDRkNmQ 3WBucBJmNPgbihuCDXUNLcCpDTMaZjfMI1xAuLhhWdFiwpVFi9mWNqxuWNewsWFLw7aGnQ17GvY3 HGo42nCi4VTD2YYLDZcbrrEVbRSNusbIRn2jsTHJObFxVOPYxnGN4xsnmi825jRaffvL5za6K8Mb CxpLG6vUEYqxscE/qjylsc0/qnFa40zVcytOapzTOL9xYeOSxuWNHY1rGtebxzduMuc0djZub9zV uLfxQN31xsONxxpPNp5uPFe4vPFi45XG601yU3hTVJOhKaEpuSmlKbUpvb+0pglNWU0mQnuTtynQ VN5U09TUNKVpetOsprlN7U2LmpY2rWha1bS2aUPT5qatTTuadjftazrYdKTpeFNX05mm802Xmq42 dTdrmq42RzRHN8c1JzaPbB7TnNac0ZzZnO1a22xudjb7m4ubg811zS3NU5tnhHB287zmBWpr8Vib Fzcva17ZvLp5XfPG5i3N25p3Nu9p3t98qPlo84nmU81nmy80X26+Vj2tubhFNNe16FoiW/Qtxpak llEtY1vGtYxvmdiS493cYm1xtxTUzWkp9Wa1VLU0ELa1TGuZ2TKnZb4linAh4ZKW5S0dLWta1rds auls2W5vb9nVsrflQMvhlmMtJ1tOt5xrudhypeV6q9wa3hrluNZqaE1oTW5NaU31dremt05o3NWa 1Wpqtbd6WwNFi1vLW2uaL6iptDa1Tmmd3jqrdW5ru2tD66LWpa6rrSvcmtZVrWtbN3hOt25u3eq5 0rqjdTchzdNbD7YeaT1O2NV63Hup9Uzr+dZLrVdtHf5Rrd1tmraItui2uLbEtpFtY9rS2jLaMtuy 28xtzuaVbX7SEmFbsTrrbwu21bW1tE1tm9E2m72XtnnspbQtaFvsnt0W6nHsY+SdDa1U3NQ7sG7Q tzLQsLptZdvqtnU8vrdt5Dl42xa1TaqrQ1hbSGjb1razbY/qibXtbztEeLTthHtqaPUG6yp1C127 205x72g7q8762y60XW67xv5PPr9dGy9dlP4khPRn6YqQpWvSe0Ij9ciS0MlaWScGyYPlSDFYjpZj xBB5mBwnhsoJ8l0iRh4p3yti5THyfWKY/BX5KyJesSo2YdSatRaRoJ2mfVIkat/QviGSougS90Ql R7lEcpQ3qly4oyqjPiPKop6Pel3Mi9oXdV58N+pC1BVxlHLjExo+0SGixFAxSMSIAjFYBESN8Ig6 8TlRLj4vFov5Yon4mWgXPxdvi/3iN1KE+IUUKQ0RPdJQaZgkSQnSGClc8koFUrxUKjVKiVKz1C6N lRZIyySrtEL6ilQovSz9VCpTvq18W5qhma75hPSUZq5mnvS0ZoHmc9JszfOa56W5mhc1X5Ke1byk +Zo0X7NJs1l6TrNV86q0SPO65nVpieaHmjel5zU/0fxUWqY5rPmZ9KLmpKZL+pLmjOYdqUPzR80f pdWaP2v+In1Vc0PTI63VxmpjpW9of6btltbrtLpR0hHdR3QfkS7r7tOlSX/WPazLlN7TTdRlSz26 XJ1J1ujMOpes03l05XKUrlpXJyfqGnTT5GTdJ3Rz5Pt1z+kWyw/rlug65Em6l3TrZLvuW7pvyX7d Jt2P5XzdQd1B+QndId0xeZruhO6E/Eldl65Lnq37ne6c/Cnded1F+Vndu7rLcrvuiq5bXhAmwobI z4fpw4bJL4XFh90rfy0sJewheXPY5LA2eVfYk2FL5fNhXwz7ohIZ9mJYhzIk7Fthm5TYsM1hnUp8 2Cth25TEsO1hbyhJYT8IO6SkhP087JiSEXY87IwyIeydsL8oeeEp4VuUgvB3B41Q3o56L+o9TbSQ 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 DU++TFsdMvrdWa8s886wpHcXV96f/fTrl2HdR/Z91CK/wq4xM3fv6/pVTGR2cI1962YV/nxp23LL zBmNx3m+OtrBL3fwD2/6Lntr8rlibHnhs3yHvImWHy7eievY6EGvG243OvhX7+nxwGnC5cVPXzfM vzn/fXM5e9Vr8ObNcnOR5V3NDt+c1t240HHKjmELZqn5dUt3vAt1GT+0evMhCTH2xYcbePVKD45a te3XQ1u6jWgT1W/ps+5J3dqnzEqISqyw5lqLybfq/lZjv0/btKvayKG1N+b9Nn76yQEx77R1j71S nq/p0yJl286Qrl9+4vnlzZrnxjrv9UyJXxDe9qdJ3kN31nx4YeXyTJkJwhND6TNSWDJlTmCqQkNz 2n/t4+zv/+GtzJj8VNSUHZLlS/+AyMHFS1Lklkr0R7JaMNBDq9cKDun4P0akbPvdqw6GWS8aFq0P OKbuwV+cvjz/o89oOFYiHffpuK3dA6dNvuK636ltdvs5C4P7eCbubxNqzPzCvk4Fxyc5dQq+XVnp wHd7to08q5k40vVVw/33jjkL9d2ObXFsu+TrTq3GVNLd+N7f2N35+Izyq+s1vet0dMeNAWIBn8iv OdJ9/k9jlzonZNp1/NpPuWb1uLwOrzYFc4vXRPt/O8Q5n+mOzz7RYY1PcutytWo0c/lVt7LJJ8+T vO+v3J12c4ZnVdM33+75vvtnfbOuHeu3wLvZJc+h25yy6y5Uvbjq+3XR+a3clJT81tl1wzrFDhzN V6ywIEHeh7tZ57VW1v+TLT3iEo/zL8zxa2LOv4x/5HY3S5GxPr/e+VqdkvtPk+vGVdbN8ll3WPNz NmPs/wHU+7WDCmVuZHN0cmVhbQplbmRvYmoKMTkgMCBvYmoKPDwKL0Jhc2VGb250IC9DSURGb250 K0YyCi9EZXNjZW5kYW50Rm9udHMgWyA8PAovQmFzZUZvbnQgL0NJREZvbnQrRjIKL0NJRFN5c3Rl bUluZm8gPDwKL09yZGVyaW5nIDEyIDAgUgovUmVnaXN0cnkgMTMgMCBSCi9TdXBwbGVtZW50IDAK Pj4KL0NJRFRvR0lETWFwIC9JZGVudGl0eQovRm9udERlc2NyaXB0b3IgPDwKL0FzY2VudCA5NTIK L0NhcEhlaWdodCA2MzEKL0Rlc2NlbnQgLTI2OAovRmxhZ3MgNgovRm9udEJCb3ggMTQgMCBSCi9G b250RmlsZTIgMTYgMCBSCi9Gb250TmFtZSAvQ0lERm9udCtGMgovSXRhbGljQW5nbGUgMAovU3Rl bVYgMTUgMCBSCi9UeXBlIC9Gb250RGVzY3JpcHRvcgo+PgovU3VidHlwZSAvQ0lERm9udFR5cGUy Ci9UeXBlIC9Gb250Ci9XIDE3IDAgUgo+PiBdCi9FbmNvZGluZyAvSWRlbnRpdHktSAovU3VidHlw ZSAvVHlwZTAKL1RvVW5pY29kZSAxOCAwIFIKL1R5cGUgL0ZvbnQKPj4KZW5kb2JqCjIwIDAgb2Jq CihJZGVudGl0eSkKZW5kb2JqCjIxIDAgb2JqCihBZG9iZSkKZW5kb2JqCjI0IDAgb2JqCjw8Ci9G aWx0ZXIgL0ZsYXRlRGVjb2RlCi9MZW5ndGggMTg2MTIwCi9UeXBlIC9TdHJlYW0KPj4Kc3RyZWFt Cnic7L0HfBzF2T8+s7vXe9UVne5OJ53KqUtWsyyd1a1iW5JlS7JlS5bkxrnb2BjbmGaI6MFATDUJ gQQTkM42Ft3kNS2UkMSEJJRASIAAIpAAARfp98zOjopt2pv3//+Vj0b+3vPd2ZnZnWdmnnlmdu+M MELIDh8C6qpsmVVT/+Oug0juex0hz9Gq8sp579/0u+sQF+9AyGGsKm+o6Fws/z3inO8jpMyqqayq nv/FKh/iM2MRkhtr5s5p2dzzZjXip6Uh7sOBmpbWcsV7VzsQV3w5Qp/9cE5LZs7eX+YMI4QhP+rq Wd29Tq267xBCbfchJLu/59xNvofW/WEaQtduheNHl61bvvrL2xctQGjxIoR0Wcu7N65DcSgA1/8D 5Dcuj5y37LfT+p9A6MY8hLXbVvR1936uvudRKD8C5/NXQITuF7ZaOL4LjhNWrN601RBc0okQB3Hz l57Tt2FN/kVFLyH8ihIhy48ia3u6K/eNbED4xwMI5cxf3b11XZoumA/5n4X8vtV9m7pf/0nsHKhP Mrn/Nd2r+6597Oh0qM4+hLJt69Zu3DTqRrvh/oZI+nUb+tZZlsc7ETrnSrj8h6Ku5RnWL1NvPLnE UPI5csJlITzy4fYXiDwmjyafOH5ql+ojJVwTqRCHaIB8cjSC8FH1vhPHj+9TfSSWNCGYFSTGmYru REa0FfGQ04gy0WVwJh+uy8FZXgjha5EMKWV7ZblQZByV/MtoN4eUiDPIOI4TeE54C6WOHkEJ54t3 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 MbKQkQ5G2hlpY2QBI/MZaWVkHiMtjDQz0sTIXEbmMDKbkUZGGhipZ6SOkVmM1DJSw0g1I1WMVDJS wUg5IzMZCTNSxkgpIzMYKWFkOiPFjBQxUshIASP5jExjJI+RXEZyGMlmJIuRTEYyGElnJI2RECOp jKQwksxIEiNBRhIZSWAkwEg8I35GfIx4GYljxMNILCNuRlyMOBlxMBLDiJ0RGyNWRiyMmBkxMWJk xMCInhEdI1pGNIyoGVExomREwYicERkjAiM8IxwjmBEkETzKyAgjpxg5ycgJRo4z8hUjXzLyb0a+ YORzRj5j5F+M/JORTxn5hJF/MPIxI8OMfMTIh4x8wMjfGXmfkfcYeZeRvzHyV0beYeQvjLzNyFuM /JmRNxl5g5HXGXmNkT8x8kdG/sDIq4z8npFXGDnGyO8Y+S0jv2HkZUZ+zchLjLzIyAuMPM/Irxh5 jpFnGXmGkacZeYqRo4z8FyO/ZORJRo4w8gQjjzPyGCOPMvIIIw8z8hAjQ4wcZuRBRg4xcpCRA4xE GRlkZICRBxi5n5FfMHIfI/sZuZeRnzPyM0buYeRuRn7KyF2M/ISRHzNyJyP7GLmDkdsZuY2RWxm5 hZGbGdnLyI8YuYmRGxm5gZE9jFzPyA8ZuY6Raxm5hpGrGbmKkSsZuYKRfkZ+wMjljFzGyG5GLmWE uT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT2YuT14AyPM /8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM /8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM/8HM7cHM7cHM7cHM28HM28HM28HM 28HM28HM28HM28HM28HM28EVBwgZ4i6JxpV6wWeOxtlAXESPLozGFYPYRY8uoGJnNE4LYgc92k7F +VRso+K8qGcmiK1RTwWILVScS8Vmem4TPdpIxQYauT7qKQexjoq1VKyhSVZTEaHinGhsFYhVVKyk YgUVy6lYFo2tBNFHj3qp6KFiKRXdVHRRsYSKxTRfJz1aRMVCKjqoaKeijYoFVMynopWKeVS0UNFM RRMVc6mYQ8VsKhqpaKCinoq6qHsWiFlU1EbddSBqqKiOuutBVEXdDSAqqaigopyem0nzhakoo/lK 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 g0ZHYky0Zi9W6PqrFdFoNY1dwrUK27HGTTxh5ZOjKAvJfG5k42S5Htn6vEcLyLFy81d5tIBrNZln Y21RZsdXSxozbctbU5YWpOiiNWadt6LJW9tdk+go2tD4KXZPHBtwxUUnelLsXytZ21QZt6Q1OjYa V2FGTXS0JXlJW3bGyg1b6w5BynQ2iWsRxpgWpup4QVUOFbI+2Y2//qiAJTkxOS/55uSRZFVysqrK onKEhvBHlDniarOXEHfBRi4Tw4+upqeENgFb8GNwpWfO0E+zuJbc1ZPLM5vK0zR6lV2bXNSYu2nz LROrDTaroT2roSjemlySnr6sKFVr0KG3mRXNmTt2xebUpBWsKk3gXOUb/ammKIdG64jPjXJFtdc2 rYxyu6KcGWXJ7txkhzPWaXfHOPVap8O8pSejriRVywlJRQ1EVz1sLrdaGMIMKjKpJ9x2g0i6rgvw CU6DQePUnCTjlBdxo551kNv09AuZEmXQ2LCmwG6TuNWx7Z6EBPfstMGi1bEmbXpWbmZ77CvcLMtw ztyvktubX7UnJaba2FdsJqv56hV2etZPd4lmRa5JuIkpYjKP5cVBjscCeXmqtGw6KGmq6Ejy85QZ ml2wPg8zH3knPdoxdx+9Kbdz+3Jfc1GiWqvR6HXxvrq8TcP942lViXZrtJ29IzZ29qSrIqFluCWN K1o20JhmMFsElSve5rTYLDdsbFuls8eyKx3RBQW/4bjkpevAYSzsfS3sPRurxsxjGQVU8owMlS2R Sm5TLZlv+fMll5+fCX81/qFPc65NadrW2jnsjzV6itpHlletMJg0OoPamVaSWtNV7uZTty1ruHlJ bNCWXpm95MYUJ7xFbo3Xzi1Z0tuaXTH46TVFW/u7lqXbNVob2cRTr82/YWulMy3N31WdVpnl9MSs CiyL9+TXkNGIY7O4TmEzE8NEH+cdWNo9ezzgUPRBVnm1hn7FOP894U6uU6effVYjpsa4DZzAtsxu thjNJva9KJuQ5052XB20GekPax6Kd7niHORNhg42mbsR/MUxXqaYyfLrYnUZGTk5fIg/vjDkM8Ij X0TvQIf3TC5LT/+w5ybTM+jjduT26o13f/bQ5/r61q9NqtvS2LC5JmHt+oG+u5avWNlsS1+a8ylX V/e6lWtu7OrkNCOTW7a03pKb0V+f01qemFDY6K0byPL1sxuLa6pLXVlpqVH+2WPlKzLT2suW1i1j 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 ymslLd9Pc/Qz29BmP/1mjaCoSBTKK9L0IB3TIcgSGr25fpDz45BiCCWDYKGO9maI9mQo3I8e/N+G ErKEcn96aBuiMtZDqJHU2oN8pK6dONqO2DgdhyD6txnxAJVpjHJB+jsE3KIwJdc6TvsktzlMe9RL JR2mrQTpOLXQURlACtHHCcpgkNbbr4zFEO2TzEWQakUQtfYo+kpGbFRJD7WyDfUEKD+jipTDSNlG W5XrDFKm5iQgLY7Svsi2EeJWlj1AtYZowqCiuUSqbcjbg/bH6dEwHeuQXsucya3I4zis9GuEcruZ 5pyTOLJHhLUdtJzc66049lHbjRzNDFrbNlrDTsrDhGKlkXyHtG9Y0WTSf3lcxqg2hHS0n4410dzR cG9kGbcoeYI42qXUPo5eyCM0GR6lHqojxAK2zetXyPP0QpIe2n6v0r6PepctdKzImWv9VcU1vV6r aE5I80tRSwFT/iGaPk7b7KOaSFrZGh6DOcu81k9uUfR6NJybaK484sPI309157/H3+oXPe7/Go/b Bkl6GS+1skzlvMg0Ua0YoZKNI4xCs/MQttPgo152vub4FH3LQ3wn1Z8tVIPIuOxEKrGhASoL0Zv5 tQaoDESCuRyh+q6no0Gq56O07zILoXJkVNdT5mVPs5MyLTMzHh7tUO6QX+hVfDex8hzKAck3qmhF pJ8epbwOK/5BrqVfOe5RfHI/9ShDtIeydJupHKFRXjhi40oJWX/GrkkZCPch5yN5AnlW6KOcjiuz j2yfcrs54XYW9kD2otspT73Unq7H2Xalp0PU0gLUpmTLv5Z7UkaeWbzInzlPg69fuyzDf5bbSPuQ Z3dRmZ/H6cj1zpsnF/ZgblZcKFdlhA6Qnsh9kVcLIV85Fl559NG5d5j6kZ4P7Kmsez3ztEr2ByMK yr2S4xPUXmT/1EfnsSHFt8j1kJwB6v0/WEdlLz6sjMxc7SELGYpYVQxSfzek8Ey8uon6y36lD6EV Rojl+VqdQ0emh8b7mND6aqGfW2gJ3gV+oZ/66e10RTFER5+Mag/SCENbqD+Sz+Updd68wHdmKtY7 5y3mVgMhaf6e2ekjzgZi/II62kJ1iAlhbb4FafI4hbRGXp0ElFlkTrs/bIYLaeUHz3Jk5NrDlhOM WIvI4y1rQb/Sluy1h5Vxz6F9HlNmn9C6Ql4XbVHGOaTHsl6NKusduYURuu7uof0MaUoPMzfLL/Rn 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 xgTEJuG8v/TiH/UK/4hkM4rKmhHAQ1/ibdhtTtz0tRLXydsS9Yj/NKjUIv2rPGpF5RpA5ZwEXgcQ d2PAn3gHzWS6Qr3Xg36Ednoh1B/PUO1Z4bjqOJXyaZq1OB3KiTuTSpxaVGK/bgTdTecHSgn8+9rC CIE4WISQ/48V/tA6HBVfu9pyh7aaQ19CDikI+XPxh9JwdLrk7vt/hzvUntt6/Hc5VZhYkV2BFb7/ jpElPEHlodx18cUqE886Y/Vx+nh9gj5Rn6Q/qqfRbmoL7dtmngzPbLRLYo90OPPvxxZ7XMV+bLHj lf5PrFxR8pXf5X8enSpX49TyahVLB9sg28O2obZU23jbRNujWoJWXrtLq6RV0appNbSa2t1aXa2e 1kBrqDXWmmrNtZZaa629NkAbrA3RhmmjtEe0sdpE7VHtMW2G9rj2hPaUNkd7VpuvLdIWa0u0pdpL 2jJtubZSW6Wt1tZoa7V12nptg/aulqm9p72vfaht07K0T7RPtc+0z7UvtC+1r7SvtW+0b7Vs7Yj2 nZaj/aD9ol3WrmrXtHzw8ZByWcGoTPEqXqYoN5QbeLL3KT5mUW2qjVnVSDWS2dQYNYbZVQwrWJha Ui3JwtVyajkWoVZWKzOHpb2lPYu0DbQNZFG2wbbBLNo2xDaEabZhtmGshG2cbRyLsU2wTWBO2yTb JObSymplmVsrp5VjHq2CVoHpWkWtIuNaZa0yM7SqWlVmatW16ixWS9QSWUmtllaLxWl1tDosXrtH u4eV0upr9Vlp7V7tXlZGa6Q1YmW1JloTlqA105qxcloLrQUrr7XSWrEKWjutHbtLe0B7gFXUBmmD WCXtYe1hVlkbqg1lVbSR2khWVRutjWbVtDHaGFZdm6BNYDW0SdoklqilaWmspjZdm85qaelaOrtb m6XNYrW1J7UnWR3tae1pVlebq81l92jztHmsnrZQW8jqa89pz7EG2vPa8+xe7QXtBdZQe1F7kTXS XtZeZo21V7RXWBNthbaCNdVe1V5lzbTXtNdYc+117XXWQntDe4O11N7U3mSttLe0t1hr7W3tbdZG 26htZG21Tdom1k7brG1m7bUt2hbWQftA+4B11LZqW1kn7SPtI9ZZ26HtYPdpO7WdLEnbpe1iXbTd 2m6WrO3R9rCu2l5tL+um7dP2se7afm0/66Ed0A6wntpB7SDrpR3SDrH7tcPaYdZbO6odZX20Y9ox 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 6pZoXaJHibQSy0rsKHE2JjymekxyzISYpTHbY/bFHI/Ji7npjHLGO6s7Gzs7O/s7RzqnOuc6lznX O7c79zmPO/OcNzFSiHdVdzV2dXb1d410TXXNdS1zrXdtd+1zHXfluW66o9zx7uruxu7O7v7uke6p 7rnuZe717u3ufe7j7jz3TU+UJ95T3dPY09nT3zPSM9Uz17PMs96z3bPPc9yT57mpR+nxenW9sd5Z 76+P1Kfqc/Vl+np9u75PP67n6Td5FI/n1Xlj3pn35yP5VD6XL+Pr+Xa+jx+HDTD55Ipaq/dmEfS1 6SjYZjzNRjB9jd9fdtXvbxoccA36uiXrguPvWYPjWzoHxz9sEBzfdjIornItOG7uDI6XbBkcr4Ay 2wPid8UHnLcztf7g4HjjTYhHyLewgiNF7ez3w7cw/+47mVPTXiHx9QFxwBVO8dvSEsc6Sr+X9AcG 59FiHcVvr9P0p1ok/WXSXyt9f4lM9ClN0baJmewBbAgbTW8OZ7N5bAlbztawDWyLfEd1mJ1g59hF efUH0t8l/QPSPyH9C9Iv8PtuVfox0i8r/drSby79ZOmnSH+c9GdJf6n010h/i/R3S/+o9OX93bf8 vschfZO4LkfzmOLdwXA2Ts7kLWIvsVVsHc3Z72R72UF2DGM98d7mBr2RcykllXJKVaW20lBpqXSk //+IHBOl31D67aXfW/pDpD9J+k9Jf7H0V0l/k/R3SF9K1HNa+pf9vi7tTZcr8XUpSb2W9FtKX5ZP Hyz9NOnPlv4S6Ut70LdKf7/0z0r/mt/ndumXlH5V6TeWfnKwNTZvGGzRRhLFo8gyE4uxOn+q7dKX +jQOSv+k9KVejXy/b1qlr0lfls6sLH1pX2bTO+uTeUz656R/jdJE0pxydXqr3preRfeXX49EmtjJ 0pdSjJVajF0t/Y3Sz5K+lGasvFfseenLelHSWlydLble+lInJfdK/zilbsSmynf7y4LesBxix9lZ lseusZuKVYlSPEq8UkGpXvQGuYfSXxmsjFQmKFOVWegnF6OnXK2sVzYr25Vdyj7lkHJcOavkKdeU m6pVjVI9arxaQa2u1lUbq62pJUMZ4qTdxUm7i5N2FydrcJyswXEDpT9B+tLu416SvuQxTtp73CHp Sw3H3fD78VHSLy19eb/41tKX9Sx+tPRnSl/ad7y8T/xO6UtNxMv7xMv7lJL3KSXvU0rep5SsT6Vk q1tquPTTpS/b11LSAkrJlrHUPunL+ltKWmxp2RKVlvcpXVf6baXfV/qSn9Ky5Sst5VZa1tfS8j6l 90hftnylJV+lb/r9MrLFLVNO+vJ+ZWQ7VaZ/cL1tyYLrbdkdIfGDIfG84D6w1cmA84i3TgyOt4m/ syaWlbW8rOw9yl4IuWbjndckyPIn9JC+vze0iX9ZYJRbmUn9lZN2Wq669BtIX9pPueQ/uW6l9KX9 lJPyLid7vHIHguVQvmmxZQ6p2eWXS3+d9GWu5fcEa6HtQBpJ+ONw5W8GxIEKPCCOvrXCpJD41uB4 tY7B8RrTWURYQOnrDmMRaoiE68oRQ11pcXW3BI1ucKSetPF6h4Jzr787NGVDWUsbXgzmo9GYkPgH weVqdINF2IrRTmOpzcaylWk8RvqyRI2PsYjCPESJmiQGy7dN1RCLwrH23O/3GuD3l7YMuMaG+BwW ER6Qx6vpAXGcX30o2CJarKZ4gBRaytFMy+nF2BxyWHPV779Zwe+/dcDvv93R72ead9aDVrJnaiX7 91azg+4KS9w6RPpXWUREQPlaraH4P+mRW0vLbS170tZyXNK2v/Rl+9Zuut9vL9O3l+nby76ro+wX OsrrO/VlEY6A0nS6FhzvPJVKJ96El8R4TbzjlSOszrLFvk+OSJJki5ok36F1kWOA5HjK4Q7bSZYj rq6yhe0qJddVtrRdF4RK8MOLfv+jclRLHAElalk0kqRre8jerKcsQ88K0pejwJ7STntKKfSUY4+e srXuJXvZ+8+FliFrtN//NIbKUCSn3iUD2l8RTw+JLwqJrwmJbw2JHwiJn6N4kM31lqOXPtKu+1S/ M00fqa0+st/sM66YNLKv7iNbxT5bi0kj7aePHDn1td+Zpq8p/XrS71FMGqmBvlLLfVcVk2az9OVY pO+1O9P0k3LpJ0eY/doXk0bWjX5Tpb+smDRypNhPWkK/y0EtlDJuc3B8YsPg+KSk4Pijwf24kjY8 JL47OD55bnB8ysrg+FQ1OD4tJiQ+Mjg+PaR8M0LKlx78tKo8Pimov1RmHg2OZySGxGcFX59xLDj+ REpwj9l3T0BPgh5gQFRAvRHxkB4z5XxwfODp4PigkPjgkPjDZsD94B5uTz3Xn8cHhMQnBPAj4nNC 4otC4i8FtOYiviokfiM4PiQ5JL4mJH4zOD60W0h8bUj8VnB8WI+Q+LrgeCoLaN9FvHdIfGNw+uHh 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 Is+VN8r4LxvkCpnlf1tCzdgoPmlrPH89QXT0PecJfqlffrpx5H69IyfzPu3g8XyVyx32zYob4ju3 ir+JP4nT/HVi2vlXDh17sHqtTKyu9D3lQnmfnKN8mBwmn1R71Pr8Yc3WfAfsvmPobx/5AON/wD9w 2Ovj8+aTvqdOQ5f51TW/pP/cXxXkwMuXrOwXryNPHNPr8G8U/sp7Yv43AlSc4FuTb81LOTb9y+4v xjvqrlriPHqvi/SjrGPXLb6O3RPiMk3X6ose/up0j/qr0z3rr073vNZNu12M1nppvcRr/rp0r2sD tOfFOG2kNlbMVKvTiflqdTqxQK1OJxaq1enEIu1rbY34Uj9V7yRW62foZ4lUtTqdSNe76F1Ehlqd TqzTL9OvEBv0h/V+IqI/qg8SWfpo/VWxWZ+iTxE5+gf6TJGrf6Z/Lnbo8/R5okhfqC8Wnr5UXyZK 9O/078QufZW+WpTpqXqaqNDT9XRRpa/X14vdhmuExB6jtlFX7FMrzAnprzAn/BXmAkZbo61m+yvM Of6qconGWcZZWshfVS7JX1Wutr+qXF1/Pbl6RjfjVi3Z6G7coaWo38ppDdWqb1pjteqbdrL5ublY 66ZWfdP+oVZ60+5RK71p9wZqB+poPQPJgUZaL7Xem/ZAICuwVRuo1nvTHlPrvWlD1Xpv2jC13pv2 uFrvTXs6UB7Yqz2j1njTXlJrvGlj1Rpv2iS1xpv2tlrjTZui1njTZqg13rTFao037Uu1xpuWat1u Pa1tUKu76Zpa3U031epuekCt7qbbanU33bHetibrSWpdN72uWtdNr6fWddObqnXd9DZqXTe9g/Wd FdaPUyu66eeoFd30zla+tUM/T63opl+kVnTTr1IruunXqhXd9N5qRTd9kPp9nD7M0R1dH+5Yjq0/ 7iQ6ifoTTi2ntv6kk+wk6085DZ1G+tNOM6eZ/qzTymmtP6dWXNNfUCuu6SPVimv6KKeT00l/Wa27 pr+i1l3TX1XrrumvOxc6F+lj1bpr+htq3TV9glp3TZ+o1l3TJ6l11/R3nXudnvpkte6a/p7T3+mv T1Wrr+nT1Opr+nS1+po+w3nOeU6f6Yx0RuqznFHOaH22Wn1N/0StvqbPUauv6fPU6mv6AmeOs1hf 6HzlpOsrnPXOBj3L2ehk6pudTU6+vtUpdHbpMbUqm16pVmXTqxyZoOm71aps+j61Kpu+X63KZmgJ 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 dFTmVxbL/WClr7K8sqayqXJS5VSOcypnVM6unOfSeWdduRB4aeWKytW0a6ZAy7ubceU67KbPgd7I tVRukbhyeyXtjiv3jd3iOl55oPIg7Xlp/1t5pPJ45SmDPgPczvFS5QXZk7x7rbxsYNKqSlSZq2Kr hKSB+1b1q0rKG1TVvyqNdq+0h60aWjWyKkPuWKtyemBXXmeVO+9kVUlVgHAlY95jFq+UuKquaoLc V1ZNrppWNXNsStWcqvmEiU+cRVXL5B6zamUPvIajuKr1wJskrtpatYN2jrR/rNpT1VzVki94F1l1 qOpo1Yn8/lWnq84SPl91MX9k1ZWwWr6VxyUcDWwZExuOqzwSTggnj80PDwgPyhfh9PCo/JHhzLDN OTecFy4Ke3jvINcj9l3kFaeEQ+FwuCE8MTwlPL2gKDzLkxCeG17Aa0d4SXh5eBVjoteGN4Q3h7eF dxLe24X3h1vDh8PHwifDbeFzVKpD7unCHeFL4c5qvTqm2lodX51YnVKdWj2kekR4LvtPxoUTqkdX Z/kHsLesdgDnu9dV0/6u2lddXl1T3VQ9qXpqYd/qGe7V1bOr51UvrF5avaJ6NfA69pPVG429FeHq LdXbq3dX75P7rOoD1Qerj1Qfrz5VPrL6THV79YXqyzWixlwTW9OXcL+apJr+7DNr0oCH1oysyajJ IewqOFnjrikpP1QTqKksPyTXlJq6mgk1k2um1cysmVMzv2ZRzbKalTVratbXbKrZ6k1lL+pvqNlR s8cVX9Nc01JzqOZozYma0zVna87XXByXWHNlXGqtWhs9Lr7WUhs3NkWuUIxrE8bNDqxjujY56JKR mzexdkDtoNr02lG1mQVxtbbavNqiWk9tqDZc2xD2hPfXTgwfrp1SOz3cWTurdm7tgtoltctrV9Wu rd1Qu7l2W+3OMVdq94YX1O6/Rlpr7eHaY7Una9tqz9V21F6q7azT62LqrHXxdYl1KXWpdUPqRtSN rsuisCi/rrjOV1deV1PXVDepbmrZiLoZdbMJz6tbWLvfwEvrVuQvqltdt65uY92Wuu3VR+p21+2r O1B3sO5I3fG6U3Vn6trrLtRdrhf15vrY+r71/eqT6vvz+Nan1Q8d56sfWZ9Rn1Pvqt1W7x5zpb6k PlBfKceuvq5+Qv3k+mn1M0sS6+fUz69fVL+sfiXhNfXr6zfVb63fUb+nvrm+xb+kcGb9ocL59Ufr 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 qXpm9rfXTPUpyyKLAh8Qndz5375+qFv+m9uTS555xTl1YK+7dj31Wcb9jz97o/qXyMtebfnhqfVK Q8wVJf4fTe9si7q0baJ5iVrkBXdHvvCsiuLXTW6NgnYzzy9OLLxGRHbUdRp/c9ydzJcYC7VdYYlw z1oqZ6ZZC92zHplp61BbNTp7ePcnv4yztvT4PGjYE9cdXfnsTStv/LcPz6pOd78c8mxh9fMvD7mj tDnAmjLWXSSnxMvdg92DqnOrB87J+v1T4nl1JeXIcxmmw5J202GBO9+d12467P//ZDrkeuTKVH/n VEht3enJee+M1PL6fvr1hpfv+qTh7quvVF5NmXz79bcGW19qqLvn0U0pey01828ds+la9f2hUdai P386LfvItW++Uros4vNIZU7tm1NPP7z7RIbSdKTu0SDTzkcKjpwaZv/0qpcWHf3qkQl/n/nXY4tP m3s+oH39WI/YmIqfzrQcnfrnlMt+CDhSscUx9OkFtwRVPrHp2QHLxyW/e3WH42NGZoUsfTgq60hA WOqPu3oVTumVmVR56c7jFZn+B4Ksn20LunHBqX9sCv1m6MP3vdsnadRzb3+z5d5Lc+7ZO6wyusld /+bUsSOvV0KDbB32HLAt/d7zRnnpa8k9v/rxgTm7rh7e+HTF4om1A4bsPXP322sc08Yknqx5KjHN fFfYmPcynbd2rTp16X+53vww97Uvfzxx71++WLl6cp9NQ9+9vZslfsqlnuL5t4/Iz7Vtee21dVeO 2/lMjn/m3dEzV9jd5Y05llFhO1fERO/O/Trp6zebC3a59u5PnTkkvkdB7A0jjg8/uerQn5+uT7/t rVndJ5s7N02Jfvupqr92L9n46oTMh56dcuOGSc9aV729ZvApy22t81Inrvd9dvXO+d3eK3/r6cgH LWVqZvIr1z266Wj0l39ZV3/Thqklpr0DU4pqF697fupLr1UvuTPs40UPWu+M6Zm6OnBS9fXz496u Pjm7PnrfN86r3lvWdPnhH5Sxtz106b07b955bNLxF55s6JXo7/Du9SP3Xxn+7P5zPVdkpVwTcst7 1udaaSnoREvB2XY72rLBsxfP+WRgl/5YE8raj5pLaU2Y8W+ZkhPc8fLC7NpeXzY2atjN4yZRqjwp R6W6e/XCxrZPL3dq/1RaJtL6yo1tr/On7ln3/7+xsTXMtX9h/pvrx+MpB/Yf8y79OLxj2Q1Xri69 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 FTRMEa/jvAzpCoZY4l8AZw11TlV4xUnXp55IvFpqvTArhjNRp2dydMTKC7/JKXrec50P/2h5Pip7 30mFKyQiDAluT0S+/UdUKCKMDezauyPNq/9acvbHhbddmrQFOHdLku5bAREKTv71CiWKcadIpgwK XUFOebsq9r0i+xGfpiXXamJz2k94v9jYI5ESntf+XRptWytKGMrYsQGaW69EVh/fbJ/Xy8y6yKHI MHk8W/rO0TAVU/dgRPxrTEF3aHplH9M6nmPA90kwZe21uiXBNiW6vt61D91EB9cDlSzviyQEoS4c wuXp6ezdwqrsQT4tj5xoRMtEdR+gSp+8FWMmEit1Hq9UFcbrVMswpJ1NGYybx7y3UPemmzWndsjO CMCxK+DuseCMi6iCr1ZNm5FrPUfI/aab+1TPU06cKyZ3Bmg+axXLaGKVW3SmKpxVNhAZflbFaO0i t8fxc/Iiz+gNHlZKOlSW69xyjvyeQI3TNFmLfQ5Vl71NlN7S8L4U18Xdua5TRR0eDXiqUyfKssPu 1z1tvaxbjyRAIL8BeEyxFQplbmRzdHJlYW0KZW5kb2JqCjI3IDAgb2JqCjw8Ci9CYXNlRm9udCAv Q0lERm9udCtGMwovRGVzY2VuZGFudEZvbnRzIFsgPDwKL0Jhc2VGb250IC9DSURGb250K0YzCi9D SURTeXN0ZW1JbmZvIDw8Ci9PcmRlcmluZyAyMCAwIFIKL1JlZ2lzdHJ5IDIxIDAgUgovU3VwcGxl bWVudCAwCj4+Ci9DSURUb0dJRE1hcCAvSWRlbnRpdHkKL0ZvbnREZXNjcmlwdG9yIDw8Ci9Bc2Nl bnQgOTUyCi9DYXBIZWlnaHQgNjMxCi9EZXNjZW50IC0yNjgKL0ZsYWdzIDYKL0ZvbnRCQm94IDIy IDAgUgovRm9udEZpbGUyIDI0IDAgUgovRm9udE5hbWUgL0NJREZvbnQrRjMKL0l0YWxpY0FuZ2xl IDAKL1N0ZW1WIDIzIDAgUgovVHlwZSAvRm9udERlc2NyaXB0b3IKPj4KL1N1YnR5cGUgL0NJREZv bnRUeXBlMgovVHlwZSAvRm9udAovVyAyNSAwIFIKPj4gXQovRW5jb2RpbmcgL0lkZW50aXR5LUgK L1N1YnR5cGUgL1R5cGUwCi9Ub1VuaWNvZGUgMjYgMCBSCi9UeXBlIC9Gb250Cj4+CmVuZG9iagoy OCAwIG9iago8PAovQml0c1BlckNvbXBvbmVudCA4Ci9Db2xvclNwYWNlIC9EZXZpY2VSR0IKL0Zp bHRlciAvRENURGVjb2RlCi9IZWlnaHQgNjE1Ci9MZW5ndGggMjUwNTMKL1N1YnR5cGUgL0ltYWdl Ci9UeXBlIC9YT2JqZWN0Ci9XaWR0aCA2MTUKPj4Kc3RyZWFtCv/Y/+AAEEpGSUYAAQEBAAAAAAAA /9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUV FQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgCZwJnAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEB AAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQci cRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpj ZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfI ycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgME BQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkj M1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2 d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ 2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/VH+GjPvS8+lHPpQAn40Hml59KOfSgBP 4qSnc+lHPpQAjUbqXn0o59KAE/GhqXn0o59KAE/hoal59KOfSgBN1H8NLz6Uc+lACH7oo9aXn0o5 9KAE/ho3UvPpRz6UANpf4aXn0o59KAG0v8NLz6Uc+lACZxSU7n0o59KAEH3TR6UvPpRz6UAIPrSU 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 4IX7Qkp/PysfjQB+DVFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQA UUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH1 b/wS98Uf8Ix+2t4DV32Qakt5p8vvvtZSg/7+LHX7855r+cD9jH7UP2s/hD9jYib/AISjT9xH/PPz 18wf98bq/pA5oATPtQTS80c0AJuozzS80nNABuoz7UvNHNACbqN1LzRzQAm6jdRzS80AJn2opeaK AG0u6l5o5oATdQTS80c0AJnmgml5o5oATdRupeaOaAE3UE0vNHNACbqCaXmjmgAyK+KP+CuGnahe /sh6rc297HBYWeo2cl1bNb73n3TIibX3DZtLEnhs5A4r7X5r5O/4KmWouP2G/iG+MmGTTZBxn/mI Wy/hwxoA/AmiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi iigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD6T/4Jx6N /bv7a3wtt8bhHfT3X/fm1ml/9kr+hPdX4T/8EkdG/tT9s7Q7nbn+ztKv7rP1h8r/ANq1+7PNACbq CaXmjmgBN1G6l5o5oATdRnFLzRzQAmcUZxS80c0AJuo3UvNHNACbqKXmigBaT+Kk3UHrQA6im7qC aAF/iobpSZ5ozxQA6im7qN1AC/jQfrSbqCelACmlpu6gnpQA6vmT/gpRbfbP2I/ignXFrayc8fdv bdv6V9M8V8Of8FfviWPBv7Kg8PRShbrxVq1vYlAcMYIibiQ/TdFEp/36APw8ooooAKKKKACiiigA ooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi iigAooooAKKKKACiiigAooooAKKKKACiiigAoorvvgX8JNU+O3xc8M+BNGDLeazeLA023cIIR80s zD0SNXc/7tAH6b/8Ea/2c30Hwprvxj1a3KXetBtJ0UMMYtEcGeUf78qKg9PJbs1fpnXP+A/Bek/D nwbovhfQrb7Jo+j2cVlaQ/3Y41CjJ7k4yT3JJ71vbqAF/hoyKTdQTQAuRS03dRnmgBcilpu6jdQA 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 io3Uu0UbRQAhNG6l2ijaKAE3UHtS7RRtFACbqM8Uu0UbRQAm6jPFLtFG0UAIfuij1pdoo2igBM8U bqXaKD0oATdR/DS7RRtFACbqB0NLtFG0UAJuoBpdooHSgBM8Gj0pdoo2igBAaN1LtFG0UAIOtHNK BijaKAE3UZ5pdoo2igBN1GeaXaKNooATmjdS7RRtFACbqN1LtFG0UAJuo/ipcc5paAG7qN1LtFG0 UAJuo3Uu0UY5zQAm6jdTqTaKAE3UbqXaKNooATdRnil2ijaKAEPWjdS7RRtFACbqN1LtFG0UAJuo Bpdoo2igBN1GeaXaKNooATdRupdoo2igBN1GeaXaKNooATdRnml2ijaKAE3UZ5pQMUbRQAm6gml2 ijaKAE3UbqXaKNooATdQTS7RRtFACE0bqXaKNooATdRupdoo2igBN1FLtFFACbaXHOaKKAE20Hii igBf4qRqKKAFxzmk9aKKAA/dFKRmiigBGpSM0UUAGOc0n8NFFABjil6UUUAJjijbRRQAu0UgXiii gBccYpMcUUUALtFG0UUUAIBmlAxRRQAn8NJRRQA7aKRaKKAACj+KiigAWl2iiigBtKBRRQAfxUAU UUAG2j+KiigAxzRjmiigBKXbRRQAlLjmiigAIpKKKAHbRTaKKAFPWgrxRRQANS7RRRQA2l20UUAG 2jbRRQAfw0u0UUUAJ/DS7RRRQA2nbRRRQAn8NG2iigA20lFFAC/w0baKKAEpdtFFABtoAoooASii igBdtFFFAH//2QplbmRzdHJlYW0KZW5kb2JqCjI5IDAgb2JqCjw8Ci9CaXRzUGVyQ29tcG9uZW50 IDgKL0NvbG9yU3BhY2UgL0RldmljZUdyYXkKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0hlaWdodCAx MzEKL0xlbmd0aCAzMTEKL1N1YnR5cGUgL0ltYWdlCi9UeXBlIC9YT2JqZWN0Ci9XaWR0aCAxMzEK Pj4Kc3RyZWFtCnic7dRBDsJADEPR3P/SRlmwQGLadJrEaeW/RMh5KhWmlFLPDuH4gioEnkaACDMI ZnSD0Q1W259DXae/DSc0GfRDeHoXFvf0Q/x8ZD3pXfD0FDw9BU8ET++CJ4Knd8ETwdO74OkpePyn gENCh+HvtQGEVsPiFhoNq1N9hPWlLsPRnSYDn3B8pcNwcmMAocFwfqHaENgfQCg2xNZLDXxCdLvO EF5GmSE+XEW4sltjwChC+rdjXd3MN1xeHEBIN2zsDSAkG/bWMg27W4kGPmF/KctwY2cAIclwbyXF cG8jg4C8+IJdA58AsA14HwF8wa3/VxIBYBsAuoFPANgGgG7gEwC2AW8ngC+IGPgEgG0A6AY+AT3x BRMImExAXyJ4Inh8ghndwCeY0Q3GNthZfIFSSikzsw9/x5SFCmVuZHN0cmVhbQplbmRvYmoKMzAg MCBvYmoKPDwKL0JpdHNQZXJDb21wb25lbnQgOAovQ29sb3JTcGFjZSAvRGV2aWNlUkdCCi9GaWx0 ZXIgL0ZsYXRlRGVjb2RlCi9IZWlnaHQgMTMxCi9MZW5ndGggNTAwCi9TTWFzayAyOSAwIFIKL1N1 YnR5cGUgL0ltYWdlCi9UeXBlIC9YT2JqZWN0Ci9XaWR0aCAxMzEKPj4Kc3RyZWFtCnic7dzbboMw EADR/Pl+Oq0UqUItUIeLPeud816p9mCHQGCRJEmSJOmUiHgN9f0PLOUNr/Cjcg5OhZchSMq2MASE ISAMweFZEwehhRX2/Ftnb+pO/6E2GQLCEBCGgDAEhCEgDAFhCAhDQBgCwhAQhoAwBIQhIAwBYQgI Q0AYAsIQEIaAMASEISAMAWEICENAGALCEBCGgDAEhCEgDEEQDU9MnA5hi0bR9tyKIZ52fSZtcd0t c3hxTWm572B2UVxx7+zZ4pzb580N6oSHJs1F8annZswW7R7dQwzR7um5skWLPrNki2PdTmwMcazn /NhiT+eZ8WvFpiHT4qL4a9Sc2GJt4Gy4Qa2NPSxdFG+EebAFZGdwg+IcipUXBW3sNVsAdwNDcEZd rQV2vNU+tckHXp1FwR9phRYpxlhhg8pysM29KHKNbtYW6cZlCI75WuQd0UwtUp+EFAyRGr9FhQpv 5BZ1KrwMQZL3Y24yhuDI+FVoVrmu0swN0sIQWS4gV5Dlrsr0+DcZ6yDfdq+G+YugggzBQfuxYmXd WhjiGOcH7YI84iFDcMTQxwC1FoOeUNYvhuCI7i9P0J7o/kYRbTIERHR805GO3dLCENcZAsIQEIaA MASEJ04Efo+A8CoHgdf9hvPeEEH4Bn5JkiRJknpali+d/ANdCmVuZHN0cmVhbQplbmRvYmoKMzEg MCBvYmoKPDwKL0JpdHNQZXJDb21wb25lbnQgOAovQ29sb3JTcGFjZSAvRGV2aWNlUkdCCi9GaWx0 ZXIgL0RDVERlY29kZQovSGVpZ2h0IDM5OAovTGVuZ3RoIDQ1MTY1Ci9TdWJ0eXBlIC9JbWFnZQov VHlwZSAvWE9iamVjdAovV2lkdGggOTA2Cj4+CnN0cmVhbQr/2P/gABBKRklGAAEBAQBgAGAAAP/b AEMADQkKCwoIDQsLCw8ODRAUIRUUEhIUKB0eGCEwKjIxLyouLTQ7S0A0OEc5LS5CWUJHTlBUVVQz P11jXFJiS1NUUf/bAEMBDg8PFBEUJxUVJ1E2LjZRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFR UVFRUVFRUVFRUVFRUVFRUVFRUVFRUf/AABEIAY4DigMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAA AAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEU MoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2Rl ZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK 0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUG BwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS 8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4 eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri 4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AO10zTbF9NtXezgZmiUkmMEkkDOTjmrf9l6d /wA+Vv8A9+l/wo0j/kE2f/XFP5Crnf2pyk7kRirIp/2Vp3/Pjb/9+l/wo/srTv8Anxt/+/S/4Vd5 o5pczHyopf2Vp3/Pjb/9+l/wo/srTv8Anxt/+/S/4Vd5o5o5mHKil/ZWnf8APjb/APfpf8KP7K07 /nxt/wDv0v8AhV3mjmjmYcqKX9lad/z42/8A36X/AAo/srTv+fG3/wC/S/4Vd5o5o5mHKil/ZWnf 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 jpkcUryO5y5z3GegpincvHXOOaUDBPJz/hS6itd3GDuCQT2zTipI4zj69M0AfMccY5pyjeQckUxp DQQoAfJJ6dqfmJYiCp3nndTSFUYx70hbAB96LA1cUEYJzx19QR/jQSx3BQSB1IHA/wA4pjE5Kk+1 SzRmBAyu21hk+49KAbBIFlg5YBuhH+TTngdCCTkA/SoGYhc5weOn+fenIzFAM8D5QM9McUEq6YfK M7gST074p4kLAIOFB4GMUwcjIGMUFhtGFA5znvQVYtwLHPGS6gsBg4OMj1qqNiSYY5G4gk8cZpgz 1B/OoriRoymMZIJz7Dt+tCWpNrE5IGcHgc80hOcHORUlmouHzjqCRk/zqJtv7w8jHAx3+tFhp9BA SSfl+v0pQhK8EgdAcdTViCYJGylAQSRnuSR3pkUfmSCMHGSaLhcRFeSEnIO3nBHIFOjuZIwEB49x kiorj/R94PIXJ44qGGbzG2qgUsMg59u/HtRa4rX3LtzIkpDp94DBBFV846jOT69KgF1uJDLkg8+9 SNKBHvRRnPfv0ppFJWQ8FeOQDjketQyRBsuSQep9CabNMHjzsAYd/wAajjXPKnGR0PIppWAVCCDj AIpSM5PTigDbQRuKRjjewXPpTuPbU2dOBFkmepyf1NWhTI1CoEAwAAKfmsG7s427tsWkJpKKBXDv RRRQAUUUUAFFFFADqKDQOpoAKM0Dk47+tWEiVRk8mgdiFImbnoPU1Okar0GT61JRSAKKKKAP/9kK ZW5kc3RyZWFtCmVuZG9iagozMiAwIG9iago8PAovQzAgWyAwLjYyNzQ1IDAuNjI3NDUgMC42Mjc0 NSBdCi9DMSBbIDAuNjI3NDUgMC42Mjc0NSAwLjYyNzQ1IF0KL0RvbWFpbiBbIDAuMCAxLjAgXQov RnVuY3Rpb25UeXBlIDIKL04gMS4wCj4+CmVuZG9iagozMyAwIG9iago8PAovQzAgWyAwLjYyNzQ1 IDAuNjI3NDUgMC42Mjc0NSBdCi9DMSBbIDAuODkwMiAwLjg5MDIgMC44OTAyIF0KL0RvbWFpbiBb IDAuMCAxLjAgXQovRnVuY3Rpb25UeXBlIDIKL04gMS4wCj4+CmVuZG9iagozNCAwIG9iago8PAov QzAgWyAwLjg5MDIgMC44OTAyIDAuODkwMiBdCi9DMSBbIDAuODkwMiAwLjg5MDIgMC44OTAyIF0K L0RvbWFpbiBbIDAuMCAxLjAgXQovRnVuY3Rpb25UeXBlIDIKL04gMS4wCj4+CmVuZG9iagozNSAw IG9iago8PAovQm91bmRzIFsgMC4xODE4MiAwLjE4MTgyIF0KL0RvbWFpbiBbIDAuMCAxLjAgXQov RW5jb2RlIFsgMC4wIDEuMCAwLjAgMS4wIDAuMCAxLjAgXQovRnVuY3Rpb25UeXBlIDMKL0Z1bmN0 aW9ucyBbIDMyIDAgUiAzMyAwIFIgMzQgMCBSIF0KPj4KZW5kb2JqCjM2IDAgb2JqCjw8Ci9NYXRy aXggWyAwLjc1IDAuMCAwLjAgLTAuNzUgMC4wIDc5Mi4wIF0KL1BhdHRlcm5UeXBlIDIKL1NoYWRp bmcgPDwKL0NvbG9yU3BhY2UgL0RldmljZVJHQgovQ29vcmRzIFsgMC4wIDM5Ny40NCAwLjAgMzk5 LjIwMDAxIF0KL0V4dGVuZCBbIHRydWUgdHJ1ZSBdCi9GdW5jdGlvbiAzNSAwIFIKL1NoYWRpbmdU eXBlIDIKPj4KL1R5cGUgL1BhdHRlcm4KPj4KZW5kb2JqCjM3IDAgb2JqCjw8Ci9GaWx0ZXIgL0Zs YXRlRGVjb2RlCi9MZW5ndGggNjczNgo+PgpzdHJlYW0KeJztXUuP5DaSvtevqLOBTIt6CzAK6G53 AbOnHcDAHhZ7GBjzOHR6Yc/8fwyp5/cFIyipSvK4bfWpMzKLQcabFPVFdm+qzP97zu5Zxv+5xd81 XT7998fH089P8R/N//nl708ff3jKnn/45enbV/fsynvd5c5/8cPfntwzsnHPXT196NrmXuVZlvvf PZ7+9ztPK1/8RLKybpvKf2yr8LFzTVd34ePry60d/zh8bMK3fpbDt1kRPuaubMsyHqrLXhz+7cfw bVvkWeGUkYsX/PQ5/NYPW/QjST6vLzX9ZfiydXnVf+wnUdSFp4g//b/nH/7r6fMPT3/2ks2z9l42 XdfVz11T3Cv/v6Z+fjwVWXnvwieH9C9E77wInKc7T8dxkP6Pp//55vmnoxSIXCINuqwXltdJ28by 6Hp5VE2Zu07R74deoVXTumKQlstm0RZNP1Tjsq5ow8cGP7rP7qVa1MA6KpqS/zTnj/7HDfDplm9R SX7emetqL43oP156XXnPWj9A7jXlORdePJnU4ExnDTb53fn/NoWn4zBA/sfT38Y5HOyC/gflPeiy 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 Cj4+Ci9QYXR0ZXJuIDw8Ci9QYXR0ZXJuMSAzNiAwIFIKPj4KL1hPYmplY3QgPDwKL0ltYWdlMSAy OCAwIFIKL0ltYWdlMiAzMCAwIFIKL0ltYWdlMyAzMSAwIFIKPj4KPj4KZW5kb2JqCjMgMCBvYmoK PDwKL0NvbnRlbnRzIFsgMzcgMCBSIF0KL0Nyb3BCb3ggWyAwLjAgMC4wIDYxMi4wIDc5Mi4wIF0K L01lZGlhQm94IFsgMC4wIDAuMCA2MTIuMCA3OTIuMCBdCi9QYXJlbnQgMiAwIFIKL1Jlc291cmNl cyAzOCAwIFIKL1JvdGF0ZSAwCi9UeXBlIC9QYWdlCj4+CmVuZG9iago0MCAwIG9iago8PAovRmls dGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDI4NzgKPj4Kc3RyZWFtCnic7VzLjts4Ft37K+oH7OH7 AQQGKpXyoncBateY1QA9vZgsJv+/GJKSXLyX5KEVx5VGYwIEKFqiSN7HuU9JnLwV6d+TOAlB/zi2 13xU25//+nb476GddP3j+78Pn98O4unt++EfF/kkzclFJdOFtz8O8qleRj5Ftw1i8CerhFDpvm+H 3z+l38w5bUQYF7xNw2DzMEofXczDy/kY1sl56PPVtMvlqtB5qKQJxrSPiuIs67mf89WgldCy82R9 rkev+d70WF2exNe5nB2ZmS8GqWwZlk1op9Mv7VQpznY4Naapvrpqz1JUw+fzMb4P6YO112epr1e1 9/Wj5Kusl+VTybLaq0JjKaIOy4PJMPKrZFlDly1znZeFIdo7OpcM867q4zJmJsJljiTGh97NaSEl vK9+kmXtkB9vOlyKZ3OjWLFDkav/fHr77fD6dvhadMUKGV2S/eaPpCsxLRfSZPUU0y6VjjGKp28H r2QS9hiDrn//D/1dnaSN0ev0e/2Y6uc/D3+se1j17Gfpa7rBJMKkjYSrwg7Pf9vaCq+tlNqOmFh3 8q78uawtRZHNtIUoXBr6BBZSvctb4uq7mEv7XI/8l6KXWaPXW/MwPUfZ5l5b7jVpj1nYpLuQIbua JTMQ8XgHB7mIbbDSOp2GL0XQnE4qkQRNxudKCjs7rLbE9sAIkaFOVk+idFlZJrxRZVlORVcvJJ/P 0g6nsj2+iBqT+FVOqOea5IxQLSkqXOH3FqJKuUAsmyoLdFsbbNZ7TreWjJHsIdsetwASexJnLF3m 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 XBxFwNcPpuI+9vZ39QnMOvyOMM/jR2HEpHQA3wPFzViow4CZf+yhttHV2C/Gb6hz1wEWUmHr1q7C ASuS74Yq6GZMgIripxsiESzr83XoXFh1gBzAnt72osbGH/KuKHNueq5cLqnE5RM/phbjhHLpOKJC jiKN0W7rkJvl8IXlxxplKwzs0cNfAeikQodKw1m2w5UVAr+lwVzo2RtXROupJqdhnXonF5lN44dn QWxbKvLD0zLAwCVNlCnkW+R7mvXA3votFZZsmnXS7XgbjtZUqHfNvV5UAfzRjthPO0M9hoXTTjqg Lp1YopKR1sdnVlzij9AMuSfEgz6+Mq2Jx5scjQfjn2KfpprU0GAyauIho/aeG2poYxDjSPQMKrYT hu6oXu17uQIhEfzWDi5XUaOKmzRYBQO2ru6qz6CUZKcIcbz5TRHqIN1hQe94w6ZnfEclMPz2NXP3 drsWQ73ryNr4PUZKNZyq+3meYp7qRwEPfjOnTeeHG8PEj8RRY0+5BOuvn3thCSwW4kU2GoNdU1WC uJmZzWg5SizwLMTyzUq5fnEk58mPNG0OhmlunVSn+ew0ZBfrRGUzFT5o/NwaJh/wqrsO/pTjBNnj dU/Ovh7+ByfObk4KZW5kc3RyZWFtCmVuZG9iago0MSAwIG9iago8PAovRm9udCA8PAovRjEgMTEg MCBSCi9GMiAyNyAwIFIKL0YzIDE5IDAgUgo+Pgo+PgplbmRvYmoKMzkgMCBvYmoKPDwKL0NvbnRl bnRzIFsgNDAgMCBSIF0KL0Nyb3BCb3ggWyAwLjAgMC4wIDYxMi4wIDc5Mi4wIF0KL01lZGlhQm94 IFsgMC4wIDAuMCA2MTIuMCA3OTIuMCBdCi9QYXJlbnQgMiAwIFIKL1Jlc291cmNlcyA0MSAwIFIK L1JvdGF0ZSAwCi9UeXBlIC9QYWdlCj4+CmVuZG9iagoxMCAwIG9iago8PAovTGVuZ3RoIDY3NQo+ PgpzdHJlYW0KL0NJREluaXQgL1Byb2NTZXQgZmluZHJlc291cmNlIGJlZ2luIDEyIGRpY3QgYmVn aW4gYmVnaW5jbWFwIC9DSURTeXN0ZW1JbmZvIDw8IC9SZWdpc3RyeSAoQWRvYmUpIC9PcmRlcmlu ZyAoVUNTKSAvU3VwcGxlbWVudCAwID4+IGRlZiAvQ01hcE5hbWUgL0Fkb2JlLUlkZW50aXR5LVVD UyBkZWYgL0NNYXBUeXBlIDIgZGVmIDEgYmVnaW5jb2Rlc3BhY2VyYW5nZSA8MDAwMD4gPEZGRkY+ IGVuZGNvZGVzcGFjZXJhbmdlIDI1IGJlZ2luYmZjaGFyIDwwMDAzPiA8MDAyMD4gPDAwMDQ+IDww MDQxPiA8MDAwRj4gPDAwNEM+IDwwMDEwPiA8MDA0RD4gPDAwMTM+IDwwMDUwPiA8MDA4Mz4gPDAw NjE+IDwwMDg0PiA8MDA2Mj4gPDAwODU+IDwwMDYzPiA8MDA4Nz4gPDAwNjU+IDwwMDg5PiA8MDA2 Nz4gPDAwOEE+IDwwMDY4PiA8MDA4Qj4gPDAwNjk+IDwwMDhFPiA8MDA2Qz4gPDAwOEY+IDwwMDZE PiA8MDA5MD4gPDAwNkU+IDwwMDk0PiA8MDA3Mj4gPDAwOTU+IDwwMDczPiA8MDFFMT4gPDAwMkM+ IDwwMUUzPiA8MDAzQT4gPDAzNzI+IDwwMDMwPiA8MDM3Mz4gPDAwMzE+IDwwMzc0PiA8MDAzMj4g PDAzNzY+IDwwMDM0PiA8MDM3Nz4gPDAwMzU+IDwwMzc5PiA8MDAzNz4gZW5kYmZjaGFyIGVuZGNt YXAgQ01hcE5hbWUgY3VycmVudGRpY3QgL0NNYXAgZGVmaW5lcmVzb3VyY2UgcG9wIGVuZCBlbmQg CmVuZHN0cmVhbQplbmRvYmoKOSAwIG9iagpbIDMgMyAyMjAgNCA0IDYyMyAxNSAxNSA1MzYgMTYg MTYgODE1IDE5IDE5IDU2NyAxMzEgMTMxIDQ4OCAxMzIgMTMyIDU0NyAxMzMgMTMzIDQ0MCAxMzUg MTM1IDQ4NyAxMzcgMTM3IDQ5NCAxMzggMTM4IDU1MSAxMzkgMTM5IDI3NyAxNDIgMTQyIDI3MSAx NDMgMTQzIDgzMiAxNDQgMTQ0IDU1OCAxNDggMTQ4IDQxMyAxNDkgMTQ5IDQyOSA0ODEgNDgxIDIw NSA0ODMgNDgzIDI2MyA4ODIgODgyIDU1MyA4ODMgODgzIDU1MyA4ODQgODg0IDU1MyA4ODYgODg2 IDU1MyA4ODcgODg3IDU1MyA4ODkgODg5IDU1MyBdCmVuZG9iago2IDAgb2JqClsgLTgzMiAtMjIy IDgzMiA5NTAgXQplbmRvYmoKNyAwIG9iago4MzIKZW5kb2JqCjE4IDAgb2JqCjw8Ci9MZW5ndGgg ODQzCj4+CnN0cmVhbQovQ0lESW5pdCAvUHJvY1NldCBmaW5kcmVzb3VyY2UgYmVnaW4gMTIgZGlj dCBiZWdpbiBiZWdpbmNtYXAgL0NJRFN5c3RlbUluZm8gPDwgL1JlZ2lzdHJ5IChBZG9iZSkgL09y ZGVyaW5nIChVQ1MpIC9TdXBwbGVtZW50IDAgPj4gZGVmIC9DTWFwTmFtZSAvQWRvYmUtSWRlbnRp dHktVUNTIGRlZiAvQ01hcFR5cGUgMiBkZWYgMSBiZWdpbmNvZGVzcGFjZXJhbmdlIDwwMDAwPiA8 RkZGRj4gZW5kY29kZXNwYWNlcmFuZ2UgMzcgYmVnaW5iZmNoYXIgPDAwMDM+IDwwMDIwPiA8MDAw ND4gPDAwNDE+IDwwMDExPiA8MDA0Mj4gPDAwMTI+IDwwMDQzPiA8MDAxOD4gPDAwNDQ+IDwwMDFD PiA8MDA0NT4gPDAwMkM+IDwwMDQ4PiA8MDAyRj4gPDAwNDk+IDwwMDNBPiA8MDA0QT4gPDAwM0U+ IDwwMDRDPiA8MDA0ND4gPDAwNEQ+IDwwMDQ1PiA8MDA0RT4gPDAwNEI+IDwwMDRGPiA8MDA1RT4g PDAwNTM+IDwwMDc5PiA8MDA1OD4gPDAxMDI+IDwwMDYxPiA8MDExMD4gPDAwNjM+IDwwMTFBPiA8 MDA2ND4gPDAxMUU+IDwwMDY1PiA8MDE1QT4gPDAwNjg+IDwwMTVEPiA8MDA2OT4gPDAxNzU+IDww MDZEPiA8MDE3Nj4gPDAwNkU+IDwwMTdEPiA8MDA2Rj4gPDAxODk+IDwwMDcwPiA8MDE4Qz4gPDAw NzI+IDwwMTkwPiA8MDA3Mz4gPDAxOUE+IDwwMDc0PiA8MDFCNT4gPDAwNzU+IDwwMUMxPiA8MDA3 Nz4gPDAxQzc+IDwwMDc5PiA8MDM1Nz4gPDAwM0E+IDwwMzZDPiA8MDAyRj4gPDAzNzI+IDwwMDJE PiA8MDM3RT4gPDAwMjg+IDwwMzdGPiA8MDAyOT4gPDAzRUQ+IDwwMDMxPiBlbmRiZmNoYXIgZW5k Y21hcCBDTWFwTmFtZSBjdXJyZW50ZGljdCAvQ01hcCBkZWZpbmVyZXNvdXJjZSBwb3AgZW5kIGVu ZCAKZW5kc3RyZWFtCmVuZG9iagoxNyAwIG9iagpbIDMgMyAyMjYgNCA0IDYwNSAxNyAxNyA1NjAg MTggMTggNTI5IDI0IDI0IDYzMCAyOCAyOCA0ODcgNDQgNDQgNjMwIDQ3IDQ3IDI2NiA1OCA1OCAz MzEgNjIgNjIgNDIyIDY4IDY4IDg3NCA2OSA2OSA2NTggNzUgNzUgNjc2IDk0IDk0IDQ3MiAxMjEg MTIxIDU1MCAyNTggMjU4IDQ5MyAyNzIgMjcyIDQxOCAyODIgMjgyIDUzNiAyODYgMjg2IDUwMyAz NDYgMzQ2IDUzNiAzNDkgMzQ5IDI0NSAzNzMgMzczIDgxMyAzNzQgMzc0IDUzNiAzODEgMzgxIDUz NyAzOTMgMzkzIDUzNiAzOTYgMzk2IDM1NSA0MDAgNDAwIDM5OCA0MTAgNDEwIDM0NiA0MzcgNDM3 IDUzNiA0NDkgNDQ5IDc0NSA0NTUgNDU1IDQ3MyA4NTUgODU1IDI3NSA4NzYgODc2IDQyOSA4ODIg ODgyIDMwNiA4OTQgODk0IDMxMSA4OTUgODk1IDMxMSAxMDA1IDEwMDUgNTA2IF0KZW5kb2JqCjE0 IDAgb2JqClsgLTg3NCAtMjY4IDg3NCA5NTIgXQplbmRvYmoKMTUgMCBvYmoKODc0CmVuZG9iagoy NiAwIG9iago8PAovTGVuZ3RoIDEyNjMKPj4Kc3RyZWFtCi9DSURJbml0IC9Qcm9jU2V0IGZpbmRy ZXNvdXJjZSBiZWdpbiAxMiBkaWN0IGJlZ2luIGJlZ2luY21hcCAvQ0lEU3lzdGVtSW5mbyA8PCAv UmVnaXN0cnkgKEFkb2JlKSAvT3JkZXJpbmcgKFVDUykgL1N1cHBsZW1lbnQgMCA+PiBkZWYgL0NN YXBOYW1lIC9BZG9iZS1JZGVudGl0eS1VQ1MgZGVmIC9DTWFwVHlwZSAyIGRlZiAxIGJlZ2luY29k ZXNwYWNlcmFuZ2UgPDAwMDA+IDxGRkZGPiBlbmRjb2Rlc3BhY2VyYW5nZSA2NyBiZWdpbmJmY2hh ciA8MDAwMz4gPDAwMjA+IDwwMDA0PiA8MDA0MT4gPDAwMTE+IDwwMDQyPiA8MDAxMj4gPDAwNDM+ IDwwMDE4PiA8MDA0ND4gPDAwMUM+IDwwMDQ1PiA8MDAyNj4gPDAwNDY+IDwwMDI3PiA8MDA0Nz4g PDAwMkM+IDwwMDQ4PiA8MDAyRj4gPDAwNDk+IDwwMDNBPiA8MDA0QT4gPDAwM0U+IDwwMDRDPiA8 MDA0ND4gPDAwNEQ+IDwwMDQ1PiA8MDA0RT4gPDAwNEI+IDwwMDRGPiA8MDA1Nz4gPDAwNTA+IDww MDVBPiA8MDA1Mj4gPDAwNUU+IDwwMDUzPiA8MDA2ND4gPDAwNTQ+IDwwMDY4PiA8MDA1NT4gPDAw NzM+IDwwMDU2PiA8MDA3ND4gPDAwNTc+IDwwMDdBPiA8MDA1OT4gPDAxMDI+IDwwMDYxPiA8MDEw Rj4gPDAwNjI+IDwwMTEwPiA8MDA2Mz4gPDAxMUE+IDwwMDY0PiA8MDExRT4gPDAwNjU+IDwwMTI4 PiA8MDA2Nj4gPDAxNTA+IDwwMDY3PiA8MDE1QT4gPDAwNjg+IDwwMTVEPiA8MDA2OT4gPDAxNkY+ IDwwMDZDPiA8MDE3NT4gPDAwNkQ+IDwwMTc2PiA8MDA2RT4gPDAxN0Q+IDwwMDZGPiA8MDE4OT4g PDAwNzA+IDwwMThDPiA8MDA3Mj4gPDAxOTA+IDwwMDczPiA8MDE5QT4gPDAwNzQ+IDwwMUI1PiA8 MDA3NT4gPDAxQzA+IDwwMDc2PiA8MDFDMT4gPDAwNzc+IDwwMUM2PiA8MDA3OD4gPDAxQzc+IDww MDc5PiA8MDFDQz4gPDAwN0E+IDwwMzU1PiA8MDAyQz4gPDAzNTY+IDwwMDNCPiA8MDM1Nz4gPDAw M0E+IDwwMzU4PiA8MDAyRT4gPDAzNkM+IDwwMDJGPiA8MDM3Mj4gPDAwMkQ+IDwwMzdFPiA8MDAy OD4gPDAzN0Y+IDwwMDI5PiA8MDM5Nj4gPDAwMjc+IDwwMzk3PiA8MDAyMj4gPDAzQjc+IDwwMDIz PiA8MDNFQz4gPDAwMzA+IDwwM0VEPiA8MDAzMT4gPDAzRUU+IDwwMDMyPiA8MDNFRj4gPDAwMzM+ IDwwM0YwPiA8MDAzND4gPDAzRjE+IDwwMDM1PiA8MDNGMj4gPDAwMzY+IDwwM0YzPiA8MDAzNz4g PDAzRjQ+IDwwMDM4PiA8MDNGNT4gPDAwMzk+IGVuZGJmY2hhciBlbmRjbWFwIENNYXBOYW1lIGN1 cnJlbnRkaWN0IC9DTWFwIGRlZmluZXJlc291cmNlIHBvcCBlbmQgZW5kIAplbmRzdHJlYW0KZW5k b2JqCjI1IDAgb2JqClsgMyAzIDIyNiA0IDQgNTc4IDE3IDE3IDU0MyAxOCAxOCA1MzMgMjQgMjQg NjE1IDI4IDI4IDQ4OCAzOCAzOCA0NTkgMzkgMzkgNjMwIDQ0IDQ0IDYyMyA0NyA0NyAyNTEgNTgg NTggMzE4IDYyIDYyIDQyMCA2OCA2OCA4NTQgNjkgNjkgNjQ1IDc1IDc1IDY2MiA4NyA4NyA1MTYg OTAgOTAgNTQyIDk0IDk0IDQ1OSAxMDAgMTAwIDQ4NyAxMDQgMTA0IDY0MSAxMTUgMTE1IDU2NyAx MTYgMTE2IDg4OSAxMjIgMTIyIDQ4NyAyNTggMjU4IDQ3OSAyNzEgMjcxIDUyNSAyNzIgMjcyIDQy MiAyODIgMjgyIDUyNSAyODYgMjg2IDQ5NyAyOTYgMjk2IDMwNSAzMzYgMzM2IDQ3MCAzNDYgMzQ2 IDUyNSAzNDkgMzQ5IDIyOSAzNjcgMzY3IDIyOSAzNzMgMzczIDc5OCAzNzQgMzc0IDUyNSAzODEg MzgxIDUyNyAzOTMgMzkzIDUyNSAzOTYgMzk2IDM0OCA0MDAgNDAwIDM5MSA0MTAgNDEwIDMzNCA0 MzcgNDM3IDUyNSA0NDggNDQ4IDQ1MSA0NDkgNDQ5IDcxNCA0NTQgNDU0IDQzMyA0NTUgNDU1IDQ1 MiA0NjAgNDYwIDM5NSA4NTMgODUzIDI0OSA4NTQgODU0IDI2NyA4NTUgODU1IDI2NyA4NTYgODU2 IDI1MiA4NzYgODc2IDM4NiA4ODIgODgyIDMwNiA4OTQgODk0IDMwMyA4OTUgODk1IDMwMyA5MTgg OTE4IDIyMCA5MTkgOTE5IDQwMCA5NTEgOTUxIDQ5OCAxMDA0IDEwMDQgNTA2IDEwMDUgMTAwNSA1 MDYgMTAwNiAxMDA2IDUwNiAxMDA3IDEwMDcgNTA2IDEwMDggMTAwOCA1MDYgMTAwOSAxMDA5IDUw NiAxMDEwIDEwMTAgNTA2IDEwMTEgMTAxMSA1MDYgMTAxMiAxMDEyIDUwNiAxMDEzIDEwMTMgNTA2 IF0KZW5kb2JqCjIyIDAgb2JqClsgLTg4OSAtMjY4IDg4OSA5NTIgXQplbmRvYmoKMjMgMCBvYmoK ODg5CmVuZG9iagoyIDAgb2JqCjw8Ci9Db3VudCAyCi9LaWRzIFsgMyAwIFIgMzkgMCBSIF0KL1R5 cGUgL1BhZ2VzCj4+CmVuZG9iagoxIDAgb2JqCjw8Ci9QYWdlcyAyIDAgUgovVHlwZSAvQ2F0YWxv Zwo+PgplbmRvYmoKNDIgMCBvYmoKPDwKL0F1dGhvciAoRXJpYykKL0NyZWF0aW9uRGF0ZSAoRDoy MDE3MDMxNTAwNTEwMC0wNycwMCcpCi9Nb2REYXRlIChEOjIwMTcwMzE1MDA1MTAwLTA3JzAwJykK L1Byb2R1Y2VyIChNaWNyb3NvZnQ6IFByaW50IFRvIFBERikKL1RpdGxlIChNaWNyb3NvZnQgV29y ZCAtIEFjbWUgQW5pbWFsIExhYnMuZG9jeCkKPj4KZW5kb2JqCnhyZWYKMCA0Mw0KMDAwMDAwMDAw MCA2NTUzNSBmDQowMDAwNTUwODEwIDAwMDAwIG4NCjAwMDA1NTA3NDQgMDAwMDAgbg0KMDAwMDU0 Mjc0NSAwMDAwMCBuDQowMDAwMDAwMDA5IDAwMDAwIG4NCjAwMDAwMDAwMzUgMDAwMDAgbg0KMDAw MDU0NzEyMyAwMDAwMCBuDQowMDAwNTQ3MTYwIDAwMDAwIG4NCjAwMDAwMDAwNTggMDAwMDAgbg0K MDAwMDU0NjgxOCAwMDAwMCBuDQowMDAwNTQ2MDkxIDAwMDAwIG4NCjAwMDAxMTk2MjMgMDAwMDAg bg0KMDAwMDEyMDA5NSAwMDAwMCBuDQowMDAwMTIwMTIyIDAwMDAwIG4NCjAwMDA1NDg1MDggMDAw MDAgbg0KMDAwMDU0ODU0NiAwMDAwMCBuDQowMDAwMTIwMTQ2IDAwMDAwIG4NCjAwMDA1NDgwNzQg MDAwMDAgbg0KMDAwMDU0NzE3OSAwMDAwMCBuDQowMDAwMjc2MDc3IDAwMDAwIG4NCjAwMDAyNzY1 NTUgMDAwMDAgbg0KMDAwMDI3NjU4MiAwMDAwMCBuDQowMDAwNTUwNjg2IDAwMDAwIG4NCjAwMDA1 NTA3MjQgMDAwMDAgbg0KMDAwMDI3NjYwNiAwMDAwMCBuDQowMDAwNTQ5ODgyIDAwMDAwIG4NCjAw MDA1NDg1NjYgMDAwMDAgbg0KMDAwMDQ2MjgxNiAwMDAwMCBuDQowMDAwNDYzMjk0IDAwMDAwIG4N CjAwMDA0ODg1MTcgMDAwMDAgbg0KMDAwMDQ4ODk5OSAwMDAwMCBuDQowMDAwNDg5NjgzIDAwMDAw IG4NCjAwMDA1MzUwMTggMDAwMDAgbg0KMDAwMDUzNTE0NyAwMDAwMCBuDQowMDAwNTM1MjczIDAw MDAwIG4NCjAwMDA1MzUzOTYgMDAwMDAgbg0KMDAwMDUzNTU1NCAwMDAwMCBuDQowMDAwNTM1Nzc2 IDAwMDAwIG4NCjAwMDA1NDI1ODYgMDAwMDAgbg0KMDAwMDU0NTkyNyAwMDAwMCBuDQowMDAwNTQy OTA4IDAwMDAwIG4NCjAwMDA1NDU4NjAgMDAwMDAgbg0KMDAwMDU1MDg1OSAwMDAwMCBuDQp0cmFp bGVyCjw8Ci9JbmZvIDQyIDAgUgovUm9vdCAxIDAgUgovU2l6ZSA0Mwo+PgpzdGFydHhyZWYKNTUx MDU2CiUlRU9GCg==", + "title": "LAB ID: P73456090 MAX JONES Biopsy without Microscopic Description (1 Site/Lesion)-Standard" + } + ] +} diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml new file mode 100644 index 00000000000..e162df28ecc --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml @@ -0,0 +1,1864 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <confidentiality value="N"/> + <section> + <title value="Reason for Visit"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="29299-5"/> + <display value="Reason for Visit"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <span>Fever and chills - The fever and chills have been occurring for 2 days. There has been associated cough (green sputum).</span> + </div> + </text> + <mode value="snapshot"/> + <emptyReason> + <coding> + <system value="http://hl7.fhir.org/fhir/list-empty-reason"/> + <code value="unavailable"/> + </coding> + </emptyReason> + </section> + <section> + <title value="Plan of Care"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="18776-5"/> + <display value="Plan of Care"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <p> + <b>Instructions: </b> + </p> + <ul> + <li> + <span class="Bold"> + <span>No Known Planned Instructions</span> + </span> + </li> + </ul> + <p> + <b>Planned Observations: </b> + </p> + <ul> + <li> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"> + <span>HGB (85018)</span> + </span> + </span> + <span class="xdiv"> + <span class="xlabel">Reason: </span> + <span> + <span>Community acquired pneumonia</span> + </span> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">13-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">4:21 PM</span> + </span> + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel">Request</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"> + <span>CULTURE, SPUTUM (87070)</span> + </span> + </span> + <span class="xdiv"> + <span class="xlabel">Reason: </span> + <span> + <span>Community acquired pneumonia</span> + </span> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">3:46 PM</span> + </span> + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel">Request</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <p> + <b>Planned Encounters: </b> + </p> + <ul> + <li> + <table> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">Clinic One</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">8-Aug-2013</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">9:00 AM</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + <li> + <table> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">Clinic One</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">7-Aug-2013</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">9:00 AM</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + <li> + <table> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">Clinic One</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">6-Aug-2013</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">9:00 AM</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <p> + <b>Planned Procedures: </b> + </p> + <ul> + <li> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"> + <span>DIAGNOSTIC COLONOSCOPY (45378)</span> + </span> + </span> + <span class="xdiv"> + <span class="xlabel">By: </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </span> + </td> + <td class="xdates"> + <span class="xlabel">On </span> + <span class="Bold">22-Sep-2012</span> + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel">Intent</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold"> + <span>CHEST XRAY, PA & LATERAL (71020)</span> + </span> + </span> + <span class="xdiv"> + <span class="xlabel">By: </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </span> + </td> + <td class="xdates"> + <span class="xlabel">On </span> + <span class="Bold">13-Aug-2012</span> + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel">Intent</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Instructions"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="69730-0"/> + <display value="Instructions"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <ul> + <li> + <span>Community acquired ... : Breathing Exercises: breathing exercises</span> + </li> + <li> + <span>Community acquired ... : Pneumococcal Pneumonia Shot *: immunization</span> + </li> + <li> + <span>Community acquired ... : Pneumonia *: coughing</span> + </li> + <li> + <span>Community acquired ... : DISCONTINUED - HGB (HEMOGLOBIN) (85018)</span> + </li> + <li> + <span>Community acquired ... : Return to clinic if symptoms worsen</span> + </li> + </ul> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Vital Signs"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="8716-3"/> + <display value="Vital Signs"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Date</th> + <th>Test</th> + <th>Result</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xdateTime"/> + <td class="xtest"/> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + <tr> + <td class="xdateTime" rowspan="7"> + <span class="xdiv">6-Aug-2012 3:15 PM</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xtest"> + <span class="Bold">BP Systolic</span> + </td> + <td class="xresults"> + <span class="Bold">135</span> + mm[Hg] + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Patient Position: Sitting; Cuff Location: Left Arm; Cuff Size: Standard</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + <tr> + <td class="xtest"> + <span class="Bold">BP Diastolic</span> + </td> + <td class="xresults"> + <span class="Bold">92</span> + mm[Hg] + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Patient Position: Sitting; Cuff Location: Left Arm; Cuff Size: Standard</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + <tr> + <td class="xtest"> + <span class="Bold">Weight</span> + </td> + <td class="xresults"> + <span class="Bold">88</span> + kg + </td> + <td class="xdetails"/> + </tr> + <tr> + <td class="xtest"> + <span class="Bold">Height</span> + </td> + <td class="xresults"> + <span class="Bold">177</span> + cm + </td> + <td class="xdetails"/> + </tr> + <tr> + <td class="xtest"> + <span class="Bold">Body Mass Index Calculated</span> + </td> + <td class="xresults"> + <span class="Bold">28.09</span> + kg/m2 + </td> + <td class="xdetails"/> + </tr> + <tr> + <td class="xtest"> + <span class="Bold">Body Surface Area Calculated</span> + </td> + <td class="xresults"> + <span class="Bold">2.05</span> + </td> + <td class="xdetails"/> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Medications"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="10160-0"/> + <display value="History of medication use"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">CLARITHROMYCIN, 500MG (Oral Tablet)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"> + <span> 1 (one) Tablet two times daily for 7 days</span> + </span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Quantity: </span> + <span> + <span class="xlabel">14</span> + </span> + </td> + <td> + <span class="xlabel"> Refills: </span> + <span> + <span class="xlabel">0</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Ordered + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdetails"> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Started </span> + 6-Aug-2012 + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xstatus"> + <span class="xlabel"/> + <span class="xvalue">Active</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">METOPROLOL TARTRATE, 25MG (Oral Tablet)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"> + <span> 1 (one) Tablet daily for 30 days</span> + </span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Quantity: </span> + <span> + <span class="xlabel">30</span> + </span> + </td> + <td> + <span class="xlabel"> Refills: </span> + <span> + <span class="xlabel">0</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Ordered + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdetails"> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Started </span> + 6-Aug-2012 + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xstatus"> + <span class="xlabel"/> + <span class="xvalue">Active</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">PROVENTIL HFA, 108 (90 Base)MCG/ACT (Inhalation Aerosol Solution)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"> + <span> 2 (two) Puff every six hours, as needed for wheezing for 30 days</span> + </span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Quantity: </span> + <span> + <span class="xlabel">1</span> + </span> + </td> + <td> + <span class="xlabel"> Refills: </span> + <span> + <span class="xlabel">0</span> + </span> + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Ordered + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdetails"> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Started </span> + 6-Aug-2012 + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xstatus"> + <span class="xlabel"/> + <span class="xvalue">Active</span> + </span> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Medication taken as needed. </span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Medications Administered"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="29549-3"/> + <display value="Medications Administered"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">PROVENTIL HFA, 108 (90 Base)MCG/ACT (Inhalation Aerosol Solution)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"> + <span> 2 (two) Puff</span> + </span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Ordered + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xproviderName"> + <span class="xproviderLastName"> Seven</span> + , Henry + </span> + </td> + <td class="xdetails"> + <ul> + <li> + <table class="xtableWithinTable"> + <tbody class="xtableWithinTable"> + <tr> + <td> + <span class="xlabel"> Started </span> + 6-Aug-2012 + </td> + <td> + <span class="xlabel"> Ended </span> + 6-Aug-2012 + </td> + </tr> + </tbody> + </table> + </li> + </ul> + <span class="xstatus"> + <span class="xlabel"/> + <span class="xvalue">Administered</span> + </span> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Site: Nose and Mouth</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Problems"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="11450-4"/> + <display value="Problem List"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Asthma, moderate persistent</span> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Community acquired pneumonia</span> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Patient may continue to experience low grade fever and chills</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Hypoxemia</span> + </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Allergies and Adverse Reactions"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="48765-2"/> + <display value="Allergies, adverse reactions, alerts"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Aspirin *ANALGESICS - NonNarcotic*</span> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xdiv"> + <span class="xlabel"> + Onset + <span class="xasIgnore">:</span> + </span> + <span class="Bold">2011</span> + </span> + </span> + </td> + <td class="xdetails"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Codeine Sulfate *ANALGESICS - OPIOID*</span> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xdiv"> + <span class="xlabel"> + Onset + <span class="xasIgnore">:</span> + </span> + <span class="Bold">2010</span> + </span> + </span> + </td> + <td class="xdetails"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Penicillin G Benzathine *PENICILLINS*</span> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xdiv"> + <span class="xlabel"> + Onset + <span class="xasIgnore">:</span> + </span> + <span class="Bold">1-June-2012</span> + </span> + </span> + </td> + <td class="xdetails"> + <span class="xstatus"> + <span class="xlabel">Status: </span> + <span class="xvalue">Active</span> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Results"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="30954-2"/> + <display value="Relevant diagnostic tests and/or laboratory data"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Date</th> + <th>Description</th> + <th>Value</th> + <th>Details</th> + </tr> + </thead> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xdiv"> + <span class="xlabel">Resulted on:</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">6-Aug-2012 4:06 PM</span> + </td> + <td class="xorderName"> + <span class="Bold">PNEUMOCOCCAL VACCINE (90732)</span> + </td> + <td class="xresults"> + <span class="Bold"/> + </td> + <td class="xdetails"> + <span class="xdiv">Normal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + <tr> + <td/> + <td class="xresultName"/> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + </tbody> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">3:30 PM</span> + </td> + <td class="xorderName"> + <span class="Bold">CHEST XRAY, PA & LATERAL (71020)</span> + </td> + <td class="xresults"> + <span class="Bold">Comments: consistent with pneumonia </span> + </td> + <td class="xdetails"> + <span class="xdiv">Normal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + <tr> + <td/> + <td class="xresultName"/> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + </tbody> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">18-July-2013 3:21 PM</span> + </td> + <td colspan="2" class="xorderName"> + <span class="Bold">HCT (85014)</span> + </td> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + <tr> + <td/> + <td class="xresultName"> + <span class="Bold">HCT</span> + </td> + <td class="xresults"> + <span class="Bold">45 %</span> + </td> + <td class="xdetails"> + <span class="xdiv">Range: 42.9 - 49.1 = Normal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">3:21 PM</span> + </td> + <td colspan="2" class="xorderName"> + <span class="Bold">HGB (85018)</span> + </td> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + <tr> + <td/> + <td class="xresultName"> + <span class="Bold">HGB</span> + </td> + <td class="xresults"> + <span class="Bold">14.2 g/dL</span> + </td> + <td class="xdetails"> + <span class="xdiv">Range: 14.4 - 16.6 = Abnormal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">3:21 PM</span> + </td> + <td colspan="2" class="xorderName"> + <span class="Bold">PLT (85049)</span> + </td> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + <tr> + <td/> + <td class="xresultName"> + <span class="Bold">PLT</span> + </td> + <td class="xresults"> + <span class="Bold">220 10^3/ul</span> + </td> + <td class="xdetails"> + <span class="xdiv">Normal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + <tbody class="xorganizer"> + <tr> + <td class="xdateTime"> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv">3:21 PM</span> + </td> + <td colspan="2" class="xorderName"> + <span class="Bold">WBC (85048)</span> + </td> + <td class="xresults"/> + <td class="xdetails"/> + </tr> + <tr> + <td/> + <td class="xresultName"> + <span class="Bold">WBC</span> + </td> + <td class="xresults"> + <span class="Bold">7.6 10^3/ul</span> + </td> + <td class="xdetails"> + <span class="xdiv">Range: 4.5 - 11.0 = Normal</span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Procedures"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="47519-4"/> + <display value="History of Procedures"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Procedure</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="Bold">PNEUMOCOCCAL VACCINE (90732)</span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel"> + Completed + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold">CHEST XRAY, PA & LATERAL (71020)</span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel"> + Completed + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="Bold">ALBUTEROL, INHALATION SOLUTION, COMPOUNDED PRODUCT, ADMINISTERED THROUGH DME, UNIT DOSE, 1 MG (J7609)</span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xlabel"> + Completed + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Immunization"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="11369-6"/> + <display value="Immunizations"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">Influenza (3 years and up)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Administered on + <span class="xasIgnore">:</span> + </span> + <span class="Bold">1-Nov-2010</span> + </span> + </td> + <td class="xdetails"/> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">Influenza (3 years and up)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Administered on + <span class="xasIgnore">:</span> + </span> + <span class="Bold">10-Sep-2011</span> + </span> + </td> + <td class="xdetails"/> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">Pneumococcal (2 years and up)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xlabel">Lot #: </span> + <span class="xlabel">MK456987</span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Administered on + <span class="xasIgnore">:</span> + </span> + <span class="Bold">6-Aug-2012</span> + </span> + </td> + <td class="xdetails"> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Site: Deltoid (Left)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">Td (7 years and up)</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel"> + Administered on + <span class="xasIgnore">:</span> + </span> + <span class="Bold">4-Jan-2007</span> + </span> + </td> + <td class="xdetails"/> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Social History"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="29762-2"/> + <display value="Social History"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <thead> + <tr> + <th>Name</th> + <th>Dates</th> + <th>Details</th> + </tr> + </thead> + <tbody> + <tr> + <td class="xmain"> + <span class="Bold"> + <span>Tobacco use</span> + </span> + <span class="Bold"> Current every day smoker. </span> + <span class="xdiv"> + <span class="xsecondary"/> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"/> + <td class="xdetails"> + <span class="xdiv"> + <span class="xcommentlabel"> Comments: </span> + <span>Current every day smoker. Start: 1992</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + </tr> + </tbody> + </table> + <p> + <b>Smoking Status: </b> + </p> + <ul> + <li> + <span class="xlabel">Current every day smoker</span> + </li> + </ul> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Encounters"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="46240-8"/> + <display value="Encounters"/> + </coding> + </code> + <text> + <status value="additional"/> + <div xmlns="http://www.w3.org/1999/xhtml"> + <table> + <tbody> + <tr> + <td class="xmain"> + <span class="xdiv"> + <span class="Bold">Office Visit</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">Encounter Reason: </span> + <span>Fever and chills - The fever and chills have been occurring for 2 days. There has been associated cough (green sputum).</span> + </span> + <span class="xdiv"> + <span class="xlabel">Encounter Diagnosis: </span> + <span>Community acquired pneumonia</span> + <span>, </span> + <span>Asthma, moderate persistent</span> + <span>, </span> + <span>Hypoxemia</span> + </span> + <span class="xasIgnore"/> + <span class="xdiv"> + <span class="xlabel">Clinic One</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + </td> + <td class="xdates"> + <span class="xdiv"> + <span class="xlabel">On </span> + <span class="Bold">6-Aug-2012</span> + </span> + <span class="xasIgnore"> + <br/> + </span> + <span class="xdiv"> + <span class="xlabel">3:03 PM</span> + </span> + </td> + </tr> + </tbody> + </table> + </div> + </text> + <mode value="snapshot"/> + </section> + <section> + <title value="Advance Directives"/> + <code> + <coding> + <system value="http://loinc.org"/> + <code value="42348-3"/> + <display value="Advance Directives"/> + </coding> + </code> + <text> + <status value="generated"/> + <div xmlns="http://www.w3.org/1999/xhtml">No Information + </div> + </text> + <mode value="snapshot"/> + <emptyReason> + <coding> + <system value="http://hl7.fhir.org/fhir/list-empty-reason"/> + <code value="nilknown"/> + </coding> + </emptyReason> + </section> + </Composition> + </resource> + </entry> + <entry> + <fullUrl value="urn:oid:1.3.6.1.4.1.22812.4.111.1.1703142"/> + <resource> + <Patient> + <text> + <status value="generated"/> + <div xmlns="http://www.w3.org/1999/xhtml">Dr. Jones, Isabella + </div> + </text> + <identifier> + <use value="usual"/> + <type> + <coding> + <system value="http://hl7.org/fhir/v2/0203"/> + <code value="MR"/> + </coding> + </type> + <system value="urn:oid:1.3.6.1.4.1.22812.4.111.1"/> + <value value="1703142"/> + </identifier> + <name> + <use value="official"/> + <text value="Dr. Jones, Isabella"/> + <family value="Jones"/> + <given value="Isabella"/> + <prefix value="Dr."/> + </name> + <name> + <use value="nickname"/> + <text value="Ms. Isla2, Isabella Marie"/> + <family value="Isla2"/> + <given value="Isabella"/> + <given value="Marie"/> + <prefix value="Ms."/> + </name> + <telecom> + <system value="phone"/> + <value value="+1-(919)888-9658"/> + <use value="mobile"/> + </telecom> + <telecom> + <system value="fax"/> + <value value="+1-(919)888-2222"/> + </telecom> + <telecom> + <system value="phone"/> + <value value="+1-(919)888-3333"/> + <use value="temp"/> + </telecom> + <telecom> + <system value="email"/> + <value value="someone@somewhere.com"/> + <use value="work"/> + </telecom> + <gender value="female"/> + <birthDate value="1947-05-01"/> + <address> + <line value="1234 DGI Blvd"/> + <city value="Raleigh"/> + <state value="NC"/> + <postalCode value="27615"/> + <country value="US"/> + </address> + <address> + <line value="C/O: Receiving Dept."/> + <line value="a1234 DGI Blvd"/> + <city value="Raleigh"/> + <state value="NC"/> + <postalCode value="27615"/> + <country value="US"/> + </address> + <maritalStatus> + <coding> + <system value="http://hl7.org/fhir/v3/MaritalStatus"/> + <code value="M"/> + </coding> + </maritalStatus> + <contact> + <relationship> + <coding> + <system value="http://hl7.org/fhir/ValueSet/patient-contact-relationship"/> + <code value="guardian"/> + </coding> + </relationship> + <relationship> + <coding> + <system value="http://hl7.org/fhir/v3/RoleCode"/> + <code value="GPARNT"/> + <display value="Grandfather"/> + </coding> + </relationship> + <name> + <use value="official"/> + <text value="Jones, Ralph"/> + <family value="Jones"/> + <given value="Ralph"/> + </name> + <telecom> + <system value="phone"/> + <value value="(816)276-6909"/> + <use value="home"/> + </telecom> + <address> + <line value="1357 Amber Drive"/> + <line value="2222 Amber Drive"/> + <city value="Beaverton"/> + <state value="OR"/> + <postalCode value="97006"/> + <country value="US"/> + </address> + </contact> + <contact> + <relationship> + <coding> + <system value="http://hl7.org/fhir/ValueSet/patient-contact-relationship"/> + <code value="guardian"/> + </coding> + </relationship> + <relationship> + <coding> + <system value="http://hl7.org/fhir/v3/RoleCode"/> + <code value="PRN"/> + <display value="Parent"/> + </coding> + </relationship> + <name> + <text value="Wilkinson, Jackson"/> + <family value="Wilkinson"/> + <given value="Jackson"/> + </name> + <telecom> + <system value="other"/> + <value value="207-841-9103"/> + <use value="work"/> + </telecom> + <telecom> + <system value="other"/> + <value value="703-373-1575"/> + <use value="home"/> + </telecom> + <telecom> + <system value="phone"/> + <value value="207-841-9103"/> + <use value="home"/> + </telecom> + <address> + <line value="119 Grattan St"/> + <city value="San Francisco"/> + <state value="CA"/> + <postalCode value="94117"/> + <country value="US"/> + </address> + </contact> + </Patient> + </resource> + </entry> + <entry> + <fullUrl value="urn:oid:2.16.840.1.113883.4.6.1569874562"/> + <resource> + <Practitioner> + <text> + <status value="generated"/> + <div xmlns="http://www.w3.org/1999/xhtml">Dr. Seven, Henry Levin + </div> + </text> + <identifier> + <system value="urn:oid:2.16.840.1.113883.4.6"/> + <value value="1569874562"/> + </identifier> + <identifier> + <system value="urn:oid:1.3.6.1.4.1.22812.4.111.0"/> + <value value="10077"/> + </identifier> + <name> + <text value="Dr. Seven, Henry Levin"/> + <family value="Seven"/> + <given value="Henry"/> + <given value="Levin"/> + <prefix value="Dr."/> + </name> + <telecom> + <system value="phone"/> + <value value="+1-(555)555-1002"/> + </telecom> + <address> + <line value="1002 Healthcare Dr."/> + <city value="Portland"/> + <state value="OR"/> + <postalCode value="97005"/> + <country value="US"/> + </address> + </Practitioner> + </resource> + </entry> + <entry> + <fullUrl value="urn:oid:1.3.6.1.4.1.22812.4.111.0.123.100"/> + <resource> + <RelatedPerson> + <text> + <status value="generated"/> + <div xmlns="http://www.w3.org/1999/xhtml">Mr. Owens, Stanley David + </div> + </text> + <identifier> + <system value="urn:oid:1.3.6.1.4.1.22812.4.111.0.123"/> + <value value="100"/> + </identifier> + <patient> + <reference value="Patient/1.3.6.1.4.1.22812.4.111.1.1703142"/> + <display value="Dr. Jones, Isabella"/> + </patient> + <name> + <text value="Mr. Owens, Stanley David"/> + <family value="Owens"/> + <given value="Stanley"/> + <given value="David"/> + <prefix value="Mr."/> + </name> + <telecom> + <system value="phone"/> + <value value="+1-(555)555-1002"/> + </telecom> + <address> + <line value="1002 Homecare Dr."/> + <city value="Portland"/> + <state value="OR"/> + <postalCode value="97005"/> + <country value="US"/> + </address> + </RelatedPerson> + </resource> + </entry> +</Bundle> \ No newline at end of file diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json b/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json new file mode 100644 index 00000000000..8fb07ae10a5 --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json @@ -0,0 +1,298 @@ +{ + "resourceType": "TestScript", + "id": "search", + "text": { + "status": "generated", + "div": "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: search</p><p><b>name</b>: Read, Search and Conditional Create and Delete</p><p><b>description</b>: Test Script for testing search, read, and conditional create and delete</p><h3>Fixtures</h3><table><tr><td>-</td><td><b>Resource</b></td></tr><tr><td>*</td><td><a>Patient/patient-example.xml</a></td></tr></table><blockquote><p><b>variable</b></p><p><b>name</b>: V1</p><p><b>sourceId</b>: R1</p><p><b>headerField</b>: Location</p></blockquote><blockquote><p><b>variable</b></p><p><b>name</b>: V2</p><p><b>sourceId</b>: R3</p><p><b>path</b>: fhir:Patient/fhir:name/fhir:given/@value</p></blockquote><blockquote><p><b>setup</b></p><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td><td><b>Type</b></td><td><b>Resource</b></td><td><b>Params</b></td></tr><tr><td>*</td><td>delete</td><td>Patient</td><td>given=John&family=Doe</td></tr></table></blockquote></blockquote><blockquote><p><b>test</b></p><p><b>name</b>: Create</p><p><b>description</b>: Create, read, search, conditional create, conditional delete.</p><blockquote><p><b>metadata</b></p><h3>Links</h3><table><tr><td>-</td><td><b>Url</b></td><td><b>Description</b></td></tr><tr><td>*</td><td><a>http://hl7.org/implement/standards/FHIR-Develop/patient.html</a></td><td>FHIR Patient</td></tr></table><blockquote><p><b>operation</b></p><p><b>type</b>: create</p><p><b>resource</b>: Patient</p><p><b>description</b>: Conditional Create Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.13.1</a></p><p><b>required</b>: true</p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: delete</p><p><b>resource</b>: Patient</p><p><b>description</b>: Conditional Delete Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.12.1</a></p><p><b>required</b>: true</p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: read</p><p><b>resource</b>: Patient</p><p><b>description</b>: Patient Read Operation</p><p><b>link</b>: <a>http://hl7.org/implement/standards/FHIR-Develop/http.html#read</a></p><p><b>validated</b>: true</p></blockquote><blockquote><p><b>operation</b></p><p><b>type</b>: search</p><p><b>resource</b>: Patient</p><p><b>description</b>: Patient Search Operation</p><p><b>link</b>: <a>http://hl7-fhir.github.io/http.html#2.1.0.14</a></p><p><b>validated</b>: true</p></blockquote></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Operations</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote><blockquote><p><b>action</b></p><h3>Asserts</h3><table><tr><td>-</td></tr><tr><td>*</td></tr></table></blockquote></blockquote></div>" + }, + "url": "http://hl7.org/fhir/TestScript/search", + "name": "Read, Search and Conditional Create and Delete", + "status": "draft", + "description": "Test Script for testing search, read, and conditional create and delete", + "metadata": { + "capability": [ + { + "required": true, + "description": "Patient Create and Read Operations", + "link": [ + "http://hl7.org/implement/standards/FHIR-Develop/http.html#create", + "http://hl7.org/implement/standards/FHIR-Develop/http.html#read" + ], + "conformance": { + "reference": "Conformance/example" + } + }, + { + "required": true, + "description": "Patient Conditional Delete Operation", + "link": [ + "http://hl7-fhir.github.io/http.html#2.1.0.12.1" + ], + "conformance": { + "reference": "Conformance/example" + } + }, + { + "required": true, + "description": "Patient Conditional Create Operation", + "link": [ + "http://hl7-fhir.github.io/http.html#2.1.0.13.1" + ], + "conformance": { + "reference": "Conformance/example" + } + } + ] + }, + "fixture": [ + { + "id": "example-patient", + "resource": { + "reference": "Patient/example" + } + } + ], + "variable": [ + { + "name": "V1", + "headerField": "Location", + "sourceId": "R1" + }, + { + "name": "V2", + "path": "fhir:Patient/fhir:name/fhir:given/@value", + "sourceId": "R3" + }, + { + "name": "DefaultValue", + "defaultValue": "Replace at Runtime" + } + ], + "setup": { + "action": [ + { + "fhir_comments": [ + " Conditional Delete " + ], + "operation": { + "type": { + "code": "delete" + }, + "resource": "Patient", + "params": "given=John&family=Doe" + } + } + ] + }, + "test": [ + { + "id": "Test1", + "name": "Create", + "description": "Create, read, search, conditional create, conditional delete.", + "metadata": { + "link": [ + { + "url": "http://hl7.org/implement/standards/FHIR-Develop/patient.html", + "description": "FHIR Patient" + } + ], + "capability": [ + { + "validated": true, + "description": "Patient Search Operation", + "link": [ + "http://hl7.org/implement/standards/FHIR-Develop/http.html#search" + ], + "conformance": { + "reference": "Conformance/example" + } + } + ] + }, + "action": [ + { + "fhir_comments": [ + " Create the patient using fixture " + ], + "operation": { + "type": { + "code": "create" + }, + "sourceId": "example-patient" + } + }, + { + "assert": { + "responseCode": "201" + } + }, + { + "fhir_comments": [ + " Patient search by name. Save the responseBody in 'F1' fixture.\n\t\t\t\tSave the responseHeader in H1 " + ], + "operation": { + "type": { + "code": "search" + }, + "resource": "Patient", + "contentType": "json", + "params": "?given=John&family=Doe", + "responseId": "R1" + } + }, + { + "fhir_comments": [ + " Verify that the Location in response-header is valid " + ], + "assert": { + "headerField": "Location", + "operator": "notEmpty", + "warningOnly": true + } + }, + { + "fhir_comments": [ + " Verify that the birthdate got persisted and is being returned properly " + ], + "assert": { + "operator": "equals", + "path": "fhir:Patient/fhir:birthDate/@value", + "sourceId": "R1", + "value": "1974-12-31" + } + }, + { + "fhir_comments": [ + " Verify that the navigation links are valid " + ], + "assert": { + "navigationLinks": true, + "warningOnly": true + } + }, + { + "fhir_comments": [ + " Use the Location returned earlier to grab the resource\n\t\t \t\tto verify that Location was pointing to correct resource. " + ], + "operation": { + "type": { + "code": "search" + }, + "accept": "json", + "responseId": "R2", + "url": "${V1}" + } + }, + { + "assert": { + "contentType": "json" + } + }, + { + "assert": { + "response": "okay" + } + }, + { + "fhir_comments": [ + " Search for the resource but this time using the birthdate\n\t\t\t\tas a search parameter to make sure search by birthDate works " + ], + "operation": { + "type": { + "code": "search" + }, + "resource": "Patient", + "accept": "json", + "params": "?given=John&family=Doe&birthdate=1974-12-31", + "responseId": "R3" + } + }, + { + "assert": { + "contentType": "json" + } + }, + { + "assert": { + "response": "okay" + } + }, + { + "fhir_comments": [ + " Verify that the birthDate matches expectations " + ], + "assert": { + "compareToSourceId": "R2", + "compareToSourcePath": "fhir:Patient/fhir:birthDate/@value", + "path": "fhir:Patient/fhir:birthDate/@value", + "sourceId": "R3" + } + }, + { + "fhir_comments": [ + " Verify that the name matches expectations " + ], + "assert": { + "path": "fhir:Patient/fhir:name/fhir:given/@value", + "sourceId": "R3", + "value": "John" + } + }, + { + "fhir_comments": [ + " Conditional Create " + ], + "operation": { + "type": { + "code": "create" + }, + "requestHeader": [ + { + "field": "If-None-Exist", + "value": "Patient?given=John&Doe&birthdate=1974-12-31" + } + ], + "sourceId": "F1" + } + }, + { + "fhir_comments": [ + " The response code of 200 verifies that the resource\n\t\t\t\talready exists and did not get created " + ], + "assert": { + "responseCode": "200" + } + }, + { + "fhir_comments": [ + " Conditional Delete " + ], + "operation": { + "type": { + "code": "delete" + }, + "resource": "Patient", + "params": "?given=John&family=Doe&birthdate=1974-12-31" + } + }, + { + "fhir_comments": [ + " Search again and make sure the patient has been deleted.\n\t\t \t\t This time perform read by id using variable " + ], + "operation": { + "type": { + "code": "read" + }, + "resource": "Patient", + "params": "/${V2}" + } + }, + { + "assert": { + "responseCode": "410" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index f15bbf9b9e0..6f5e60e0e13 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-structures-dstu2.1</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR Structures - DSTU2.1 (2016May)</name> @@ -273,6 +273,22 @@ <fork>true</fork> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + <Import-Package> + javax.servlet*;resolution:=optional, + * + </Import-Package> + </instructions> + </configuration> + </plugin> </plugins> </build> diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 12b30916ca8..f98a2ba52b1 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -9,7 +9,7 @@ </parent> <artifactId>hapi-fhir-structures-dstu2</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR Structures - DSTU2 (FHIR v1.0.0)</name> @@ -357,6 +357,22 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + <Import-Package> + javax.servlet*;resolution:=optional, + * + </Import-Package> + </instructions> + </configuration> + </plugin> </plugins> <pluginManagement> <plugins> diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 48ed0097333..5e8d23e29b0 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-structures-dstu3</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR Structures - DSTU3</name> @@ -28,6 +28,18 @@ <build> <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> @@ -268,5 +280,4 @@ <scope>test</scope> </dependency> </dependencies> - </project> diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index dddf38d6594..581cce6fec9 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR Structures - HL7.org DSTU2</name> @@ -272,6 +272,22 @@ <fork>true</fork> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + <Import-Package> + javax.servlet*;resolution:=optional, + * + </Import-Package> + </instructions> + </configuration> + </plugin> </plugins> </build> diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index f69d32900b5..85e0d9a5f07 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -1,5 +1,5 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-structures-r4</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR Structures - FHIR R4</name> @@ -29,16 +29,16 @@ <!-- Optional dependencies from RI codebase --> - <dependency> - <groupId>org.codehaus.woodstox</groupId> - <artifactId>woodstox-core-asl</artifactId> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>woodstox-core-asl</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>es.nitaur.markdown</groupId> <artifactId>txtmark</artifactId> <optional>true</optional> - </dependency> + </dependency> <dependency> <groupId>org.antlr</groupId> <artifactId>ST4</artifactId> @@ -49,7 +49,7 @@ <artifactId>xpp3</artifactId> <optional>true</optional> </dependency> - + <!-- Test dependencies on other optional parts of HAPI --> @@ -262,6 +262,18 @@ <fork>true</fork> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> </plugins> </build> diff --git a/hapi-fhir-utilities/pom.xml b/hapi-fhir-utilities/pom.xml index 2031fff370c..fdf9ce22e8d 100644 --- a/hapi-fhir-utilities/pom.xml +++ b/hapi-fhir-utilities/pom.xml @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-utilities</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Utilities</name> @@ -122,6 +122,11 @@ <fork>true</fork> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + </plugin> </plugins> </build> diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index a239c743c2f..2778252ee29 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -9,7 +9,7 @@ </parent> <artifactId>hapi-fhir-validation-resources-dstu2.1</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Validation Resources DSTU2.1 (2016May)</name> @@ -20,6 +20,20 @@ <filtering>false</filtering> </resource> </resources> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 0f880deb8a5..2ffcd1a5102 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -9,7 +9,7 @@ </parent> <artifactId>hapi-fhir-validation-resources-dstu2</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Validation Resources (DSTU2)</name> @@ -20,6 +20,20 @@ <filtering>false</filtering> </resource> </resources> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 01350d1b933..a313bad15e5 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -9,7 +9,7 @@ </parent> <artifactId>hapi-fhir-validation-resources-dstu3</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Validation Resources (DSTU3)</name> @@ -34,6 +34,20 @@ <filtering>false</filtering> </resource> </resources> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index 8ff27c60b26..d6c899f1941 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -9,7 +9,7 @@ </parent> <artifactId>hapi-fhir-validation-resources-r4</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Validation Resources (FHIR R4)</name> @@ -34,6 +34,20 @@ <filtering>false</filtering> </resource> </resources> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 671336e6554..9f2a2b151ec 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -10,7 +10,7 @@ </parent> <artifactId>hapi-fhir-validation</artifactId> - <packaging>jar</packaging> + <packaging>bundle</packaging> <name>HAPI FHIR - Validation</name> @@ -246,6 +246,18 @@ <fork>true</fork> </configuration> </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> + </plugin> </plugins> </build> diff --git a/pom.xml b/pom.xml index 00c25f54116..143a7788aca 100644 --- a/pom.xml +++ b/pom.xml @@ -407,11 +407,19 @@ <scmPubCheckoutDirectory>${user.home}/sites/scm/hapi-fhir</scmPubCheckoutDirectory> <!-- Dependency Versions --> + <apache_karaf_version>4.1.4</apache_karaf_version> + <commons_codec_version>1.10</commons_codec_version> + <commons_io_version>2.5</commons_io_version> + <commons_lang3_version>3.6</commons_lang3_version> <derby_version>10.14.1.0</derby_version> + <error_prone_annotations_version>2.0.18</error_prone_annotations_version> + <guava_version>23.0</guava_version> + <gson_version>2.8.1</gson_version> <jaxb_api_version>2.3.0</jaxb_api_version> <jaxb_core_version>2.3.0</jaxb_core_version> <jersey_version>2.25.1</jersey_version> <jetty_version>9.4.8.v20171121</jetty_version> + <jsr305_version>3.0.2</jsr305_version> <!--<hibernate_version>5.2.10.Final</hibernate_version>--> <hibernate_version>5.2.12.Final</hibernate_version> <hibernate_validator_version>5.4.1.Final</hibernate_validator_version> @@ -422,9 +430,13 @@ <maven_license_plugin_version>1.8</maven_license_plugin_version> <phloc_schematron_version>2.7.1</phloc_schematron_version> <phloc_commons_version>4.4.11</phloc_commons_version> + <servicemix_saxon_version>9.5.1-5_1</servicemix_saxon_version> + <servicemix_xmlresolver_version>1.2_5</servicemix_xmlresolver_version> <spring_version>5.0.3.RELEASE</spring_version> <spring-boot.version>1.5.6.RELEASE</spring-boot.version> + <stax2_api_version>3.1.4</stax2_api_version> <thymeleaf-version>3.0.9.RELEASE</thymeleaf-version> + <woodstox_core_asl_version>4.4.1</woodstox_core_asl_version> <!-- We are aiming to still work on a very old version of SLF4j even though we depend on the newest, just to be nice to users of the API. This version is tested in the hapi-fhir-cobertura. --> <slf4j_target_version>1.6.0</slf4j_target_version> @@ -508,7 +520,7 @@ <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <version>23.0</version> + <version>${guava_version}</version> </dependency> <dependency> <groupId>com.phloc</groupId> @@ -538,12 +550,12 @@ <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> - <version>1.10</version> + <version>${commons_codec_version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.5</version> + <version>${commons_io_version}</version> </dependency> <dependency> <groupId>directory-naming</groupId> @@ -590,7 +602,7 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.8.1</version> + <version>${gson_version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> @@ -684,7 +696,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.6</version> + <version>${commons_lang3_version}</version> </dependency> <dependency> <groupId>org.apache.derby</groupId> @@ -799,7 +811,7 @@ <dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>woodstox-core-asl</artifactId> - <version>4.4.1</version> + <version>${woodstox_core_asl_version}</version> </dependency> <dependency> <groupId>org.ebaysf.web</groupId> @@ -1093,7 +1105,7 @@ <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> - <version>3.3.0</version> + <version>3.5.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -1926,6 +1938,8 @@ <module>hapi-tinder-plugin</module> <module>hapi-tinder-test</module> <module>hapi-fhir-client</module> + <module>hapi-fhir-karaf-features</module> + <module>hapi-fhir-karaf-integration-tests</module> <module>hapi-fhir-server</module> <module>hapi-fhir-validation</module> <!--<module>hapi-fhir-narrativegenerator</module>--> From 2c65a6dda72f85e47d54fb397512d7ed01665d05 Mon Sep 17 00:00:00 2001 From: jpoth <poth.john@gmail.com> Date: Wed, 28 Feb 2018 18:09:30 +0100 Subject: [PATCH 10/31] Add OSGI support for HAPI-FHIR client --- hapi-fhir-client/pom.xml | 7 ++ .../src/main/resources/features.xml | 7 ++ hapi-fhir-karaf-integration-tests/pom.xml | 5 + .../karaf/client/FhirClientTest.java | 114 ++++++++++++++++++ pom.xml | 6 +- 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index 1f1db04dd59..635f8bb1728 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -73,6 +73,13 @@ <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> + <configuration> + <instructions> + <Fragment-Host> + ca.uhn.hapi.fhir.hapi-fhir-base + </Fragment-Host> + </instructions> + </configuration> </plugin> </plugins> </build> diff --git a/hapi-fhir-karaf-features/src/main/resources/features.xml b/hapi-fhir-karaf-features/src/main/resources/features.xml index b6ceaadf1ff..8d844b054f4 100644 --- a/hapi-fhir-karaf-features/src/main/resources/features.xml +++ b/hapi-fhir-karaf-features/src/main/resources/features.xml @@ -32,6 +32,13 @@ <bundle>mvn:ca.uhn.hapi.fhir/hapi-fhir-base/${project.version}</bundle> </feature> + <feature name='hapi-fhir-client' version='${project.version}' start-level='50'> + <feature version='${project.version}'>hapi-fhir</feature> + <bundle dependency='true'>mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore_version}</bundle> + <bundle dependency='true'>mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient_version}</bundle> + <bundle>mvn:ca.uhn.hapi.fhir/hapi-fhir-client/${project.version}</bundle> + </feature> + <feature name='hapi-fhir-utilities' version='${project.version}' start-level='50'> <feature version='${project.version}'>hapi-fhir</feature> <bundle dependency='true'>mvn:com.google.code.gson/gson/${gson_version}</bundle> diff --git a/hapi-fhir-karaf-integration-tests/pom.xml b/hapi-fhir-karaf-integration-tests/pom.xml index e32b5c555c2..a8369d685d7 100644 --- a/hapi-fhir-karaf-integration-tests/pom.xml +++ b/hapi-fhir-karaf-integration-tests/pom.xml @@ -42,6 +42,11 @@ <artifactId>hapi-fhir-base</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>ca.uhn.hapi.fhir</groupId> + <artifactId>hapi-fhir-client</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu2</artifactId> diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java new file mode 100644 index 00000000000..1ae2468018f --- /dev/null +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java @@ -0,0 +1,114 @@ +package ca.uhn.fhir.tests.integration.karaf.r4; + +import java.io.IOException; +import java.util.List; +import ca.uhn.fhir.context.FhirContext; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport; +import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext; +import org.hl7.fhir.r4.model.Base; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.utils.FHIRPathEngine; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_R4; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; + +/** + * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class FhirInstanceValidatorR4Test { + + private FhirContext ourCtx = FhirContext.forR4(); + private FHIRPathEngine ourEngine = new FHIRPathEngine(new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport())); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorR4Test.class); + + @Configuration + public Option[] config() throws IOException { + return options( + KARAF.option(), + HAPI_FHIR_VALIDATION_R4.option(), + mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), + WRAP.option(), + when(false) + .useOptions( + debugConfiguration("5005", true)) + ); + } + + @Test + public void testAs() throws Exception { + Observation obs = new Observation(); + obs.setValue(new StringType("FOO")); + + List<Base> value = ourEngine.evaluate(obs, "Observation.value.as(String)"); + assertEquals(1, value.size()); + assertEquals("FOO", ((StringType)value.get(0)).getValue()); + } + + @Test + public void testExistsWithNoValue() throws FHIRException { + Patient patient = new Patient(); + patient.setDeceased(new BooleanType()); + List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); + ourLog.info(eval.toString()); + assertFalse(((BooleanType)eval.get(0)).getValue()); + } + + @Test + public void testExistsWithValue() throws FHIRException { + Patient patient = new Patient(); + patient.setDeceased(new BooleanType(false)); + List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); + ourLog.info(eval.toString()); + assertTrue(((BooleanType)eval.get(0)).getValue()); + } + + @Test + public void testConcatenation() throws FHIRException { + String exp = "Patient.name.family & '.'"; + + Patient p = new Patient(); + p.addName().setFamily("TEST"); + String result = ourEngine.evaluateToString(p, exp); + assertEquals("TEST.", result); + } + + @Test + public void testConcatenationFunction() throws FHIRException { + String exp = "element.first().path.startsWith(%resource.type) and element.tail().all(path.startsWith(%resource.type&'.'))"; + + StructureDefinition sd = new StructureDefinition(); + StructureDefinition.StructureDefinitionDifferentialComponent diff = sd.getDifferential(); + + diff.addElement().setPath("Patient.name"); + + + Patient p = new Patient(); + p.addName().setFamily("TEST"); + List<Base> result = ourEngine.evaluate(null, p, diff, exp); + ourLog.info(result.toString()); +// assertEquals("TEST.", result); + } + +} diff --git a/pom.xml b/pom.xml index 143a7788aca..c6b7b2c4cc1 100644 --- a/pom.xml +++ b/pom.xml @@ -425,6 +425,8 @@ <hibernate_validator_version>5.4.1.Final</hibernate_validator_version> <!-- Update lucene version when you update hibernate-search version --> <hibernate_search_version>5.7.1.Final</hibernate_search_version> + <httpcore_version>4.4.6</httpcore_version> + <httpclient_version>4.5.3</httpclient_version> <lucene_version>5.5.4</lucene_version> <maven_assembly_plugin_version>2.5.3</maven_assembly_plugin_version> <maven_license_plugin_version>1.8</maven_license_plugin_version> @@ -716,7 +718,7 @@ <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> - <version>4.5.3</version> + <version>${httpclient_version}</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> @@ -726,7 +728,7 @@ <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> - <version>4.4.6</version> + <version>${httpcore_version}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> From 4da46cdb26682d906d065ef9ed418b5cb568c14f Mon Sep 17 00:00:00 2001 From: Anthony Sute <asute@yahoo.com> Date: Tue, 6 Mar 2018 11:18:53 -0500 Subject: [PATCH 11/31] Fixes for issue #512 (:contains modifier not working). --- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 12 +++++++++ .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 25 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index a5bfbc6fb8f..9f6491c6b86 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -60,6 +60,8 @@ public class DaoConfig { * update setter javadoc if default changes */ private boolean myAllowExternalReferences = false; + private boolean myAllowContainsSearches = true; + /** * update setter javadoc if default changes */ @@ -1097,6 +1099,16 @@ public class DaoConfig { } + public boolean allowContainsSearches() { + + return myAllowContainsSearches; + } + + public void setAllowContainsSearches(boolean myAllowContainsSearches) { + + this.myAllowContainsSearches = myAllowContainsSearches; + } + public enum IndexEnabledEnum { ENABLED, DISABLED diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 417883ca0e0..9d157b8adcc 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -28,6 +28,7 @@ import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.jpa.util.BaseIterator; +import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.base.composite.BaseCodingDt; @@ -1090,6 +1091,11 @@ public class SearchBuilder implements ISearchBuilder { } else if (theParameter instanceof StringParam) { StringParam id = (StringParam) theParameter; rawSearchTerm = id.getValue(); + if ((id.isContains()) && + (!myCallingDao.getConfig().allowContainsSearches())) + { + throw new MethodNotAllowedException(":contains modifier is disabled on this server"); + } } else if (theParameter instanceof IPrimitiveDatatype<?>) { IPrimitiveDatatype<?> id = (IPrimitiveDatatype<?>) theParameter; rawSearchTerm = id.getValueAsString(); @@ -1103,7 +1109,20 @@ public class SearchBuilder implements ISearchBuilder { } String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm); - likeExpression = createLeftMatchLikeExpression(likeExpression); + if (myCallingDao.getConfig().allowContainsSearches()) { + if (theParameter instanceof StringParam) { + if (((StringParam) theParameter).isContains()) { + likeExpression = createLeftAndRightMatchLikeExpression(likeExpression); + } else { + likeExpression = createLeftMatchLikeExpression(likeExpression); + } + } else { + likeExpression = createLeftMatchLikeExpression(likeExpression); + } + } + else { + likeExpression = createLeftMatchLikeExpression(likeExpression); + } Predicate singleCode = theBuilder.like(theFrom.get("myValueNormalized").as(String.class), likeExpression); if (theParameter instanceof StringParam && ((StringParam) theParameter).isExact()) { @@ -1997,6 +2016,10 @@ public class SearchBuilder implements ISearchBuilder { return likeExpression.replace("%", "[%]") + "%"; } + private static String createLeftAndRightMatchLikeExpression(String likeExpression) { + return "%" + likeExpression.replace("%", "[%]") + "%"; + } + private static Predicate createResourceLinkPathPredicate(IDao theCallingDao, FhirContext theContext, String theParamName, From<?, ? extends ResourceLink> theFrom, String theResourceType) { RuntimeResourceDefinition resourceDef = theContext.getResourceDefinition(theResourceType); From b18bb033bf5b33ffcdabb899c77df060926a7087 Mon Sep 17 00:00:00 2001 From: darktyco <darktyco@gmail.com> Date: Tue, 6 Mar 2018 12:03:34 -0500 Subject: [PATCH 12/31] Fixes issue #878 where resources in a bundle are updated even when no data changes --- .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 2 +- .../jpa/dao/dstu2/FhirSystemDaoDstu2Test.java | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 96007600126..8c06a482c5f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -129,7 +129,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao { HashSet<String> excludeElementsInEncoded = new HashSet<String>(); excludeElementsInEncoded.add("id"); - excludeElementsInEncoded.add("meta"); + excludeElementsInEncoded.add("*.meta"); EXCLUDE_ELEMENTS_IN_ENCODED = Collections.unmodifiableSet(excludeElementsInEncoded); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java index cd1f4652783..b894e83a823 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java @@ -1193,6 +1193,62 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest { } + @Test + public void testTransactionUpdateResourceNewVersionCreatedWhenDataChanges() { + + Bundle request = new Bundle(); + String patientId = "Patient/IShouldUpdate"; + Patient p = new Patient(); + p.addName().addFamily("Hello"); + p.setId(patientId); + request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.PUT).setUrl(patientId); + + Bundle initialBundleResponse = mySystemDao.transaction(mySrd, request); + assertEquals(1, initialBundleResponse.getEntry().size()); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(initialBundleResponse)); + + Entry initialBundleResponseEntry = initialBundleResponse.getEntry().get(0); + assertEquals("201 Created", initialBundleResponseEntry.getResponse().getStatus()); + assertThat(initialBundleResponseEntry.getResponse().getEtag(), is(equalTo("1"))); + + p.addName().addFamily("AnotherName"); + + Bundle secondBundleResponse = mySystemDao.transaction(mySrd, request); + assertEquals(1, secondBundleResponse.getEntry().size()); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(secondBundleResponse)); + + Entry secondBundleResponseEntry = secondBundleResponse.getEntry().get(0); + assertEquals("200 OK", secondBundleResponseEntry.getResponse().getStatus()); + assertThat(secondBundleResponseEntry.getResponse().getEtag(), is(equalTo("2"))); + } + + @Test + public void testTransactionUpdateResourceNewVersionNotCreatedWhenDataNotChanged() { + + Bundle request = new Bundle(); + String patientId = "Patient/IShouldNotUpdate"; + Patient p = new Patient(); + p.addName().addFamily("Hello"); + p.setId(patientId); + request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.PUT).setUrl(patientId); + + Bundle initialBundleResponse = mySystemDao.transaction(mySrd, request); + assertEquals(1, initialBundleResponse.getEntry().size()); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(initialBundleResponse)); + + Entry initialBundleResponseEntry = initialBundleResponse.getEntry().get(0); + assertEquals("201 Created", initialBundleResponseEntry.getResponse().getStatus()); + assertThat(initialBundleResponseEntry.getResponse().getEtag(), is(equalTo("1"))); + + Bundle secondBundleResponse = mySystemDao.transaction(mySrd, request); + assertEquals(1, secondBundleResponse.getEntry().size()); + ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(secondBundleResponse)); + + Entry secondBundleResponseEntry = secondBundleResponse.getEntry().get(0); + assertEquals("200 OK", secondBundleResponseEntry.getResponse().getStatus()); + assertThat(secondBundleResponseEntry.getResponse().getEtag(), is(equalTo("1"))); + } + @Test public void testTransactionUpdateMatchUrlWithTwoMatch() { String methodName = "testTransactionUpdateMatchUrlWithTwoMatch"; From 5b89b28652fc87892be74523e68aac154bf4be3f Mon Sep 17 00:00:00 2001 From: patrick-werner <pa.f.werner@gmail.com> Date: Wed, 7 Mar 2018 11:49:30 -0300 Subject: [PATCH 13/31] deleted my old github name from developer list --- pom.xml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 795aa1fc93d..20b2fca6d78 100644 --- a/pom.xml +++ b/pom.xml @@ -323,9 +323,6 @@ <id>joelsch</id> <name>Joel Schneider</name> </developer> - <developer> - <id>elnin0815</id> - </developer> <developer> <id>dangerousben</id> <name>Ben Spencer</name> @@ -1777,6 +1774,21 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.owasp</groupId> + <artifactId>dependency-check-maven</artifactId> + <version>3.1.1</version> + <configuration> + <failBuildOnCVSS>8</failBuildOnCVSS> + </configuration> + <executions> + <execution> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> From 9125a78f33bd11f628fbb1892c72bbe9d9bc4707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dywicki?= <luke@code-house.org> Date: Mon, 26 Feb 2018 13:42:58 +0100 Subject: [PATCH 14/31] Avoid unecessary reference to javassist. --- .../src/main/java/ca/uhn/fhir/util/ReflectionUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java index 6e27645ca0a..b286f89ef08 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ReflectionUtil.java @@ -28,7 +28,6 @@ import org.apache.commons.lang3.Validate; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.support.IContextValidationSupport; -import javassist.Modifier; public class ReflectionUtil { From 1689dc889e3f15359442629af3a444d97845d08d Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Thu, 22 Mar 2018 06:48:08 -0400 Subject: [PATCH 15/31] Make server operation interceptor not perform superfluous calls for conditional and no-op operations --- .../fhir/rest/client/impl/GenericClient.java | 22 +-- .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 34 ++-- .../r4/ResourceProviderInterceptorR4Test.java | 147 +++++++++++++++--- .../subscription/r4/RestHookTestR4Test.java | 35 +++++ .../search/ElasticsearchMappingProvider.java | 20 +++ src/changes/changes.xml | 6 + 6 files changed, 210 insertions(+), 54 deletions(-) diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java index b3b0acbce9b..809f7aebf73 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java @@ -130,19 +130,6 @@ public class GenericClient extends BaseClient implements IGenericClient { } - // public IResource read(UriDt url) { - // return read(inferResourceClass(url), url); - // } - // - // @SuppressWarnings("unchecked") - // public <T extends IResource> T read(final Class<T> theType, UriDt url) { - // return (T) invoke(theType, url, new ResourceResponseHandler<T>(theType)); - // } - // - // public Bundle search(UriDt url) { - // return search(inferResourceClass(url), url); - // } - @Override public IFetchConformanceUntyped fetchConformance() { return new FetchConformanceInternal(); @@ -169,11 +156,6 @@ public class GenericClient extends BaseClient implements IGenericClient { return theResource.getIdElement().getIdPart(); } - // @Override - // public <T extends IBaseResource> T read(final Class<T> theType, IdDt theId) { - // return doReadOrVRead(theType, theId, false, null, null); - // } - @Override public IHistory history() { return new HistoryInternal(); @@ -2105,14 +2087,14 @@ public class GenericClient extends BaseClient implements IGenericClient { @Override public IUpdateTyped resource(IBaseResource theResource) { - //Validate.notNull(theResource, "Resource can not be null"); + Validate.notNull(theResource, "Resource can not be null"); myResource = theResource; return this; } @Override public IUpdateTyped resource(String theResourceBody) { - //Validate.notBlank(theResourceBody, "Body can not be null or blank"); + Validate.notBlank(theResourceBody, "Body can not be null or blank"); myResourceBody = theResourceBody; return this; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 8fabeeb5e4b..30dd60c30c2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -431,7 +431,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B } // Perform actual DB update - updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing); + ResourceTable updatedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing); theResource.setId(entity.getIdDt()); @@ -445,12 +445,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B } // Notify JPA interceptors - if (theRequestDetails != null) { - theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); - } - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IServerOperationInterceptor) { - ((IServerOperationInterceptor) next).resourceCreated(theRequestDetails, theResource); + if (!updatedEntity.isUnchangedInCurrentOperation()) { + if (theRequestDetails != null) { + theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); + } + for (IServerInterceptor next : getConfig().getInterceptors()) { + if (next instanceof IServerOperationInterceptor) { + ((IServerOperationInterceptor) next).resourceCreated(theRequestDetails, theResource); + } } } @@ -1262,14 +1264,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B } // Notify interceptors - if (theRequestDetails != null) { - theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource); - theRequestDetails.getRequestOperationCallback().resourceUpdated(oldResource, theResource); - } - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IServerOperationInterceptor) { - ((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, theResource); - ((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, oldResource, theResource); + if (!savedEntity.isUnchangedInCurrentOperation()) { + if (theRequestDetails != null) { + theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource); + theRequestDetails.getRequestOperationCallback().resourceUpdated(oldResource, theResource); + } + for (IServerInterceptor next : getConfig().getInterceptors()) { + if (next instanceof IServerOperationInterceptor) { + ((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, theResource); + ((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, oldResource, theResource); + } } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java index 1ec71b6358f..f1ae45d2b73 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java @@ -8,6 +8,7 @@ import ca.uhn.fhir.rest.api.server.ResponseDetails; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; +import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; import ca.uhn.fhir.util.TestUtil; import org.apache.commons.io.IOUtils; @@ -43,9 +44,9 @@ import static org.mockito.Mockito.*; public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderInterceptorR4Test.class); - private IServerInterceptor myDaoInterceptor; + private IServerOperationInterceptor myDaoInterceptor; - private IServerInterceptor myServerInterceptor; + private IServerOperationInterceptor myServerInterceptor; @Override @After @@ -60,8 +61,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes public void before() throws Exception { super.before(); - myServerInterceptor = mock(IServerInterceptor.class); - myDaoInterceptor = mock(IServerInterceptor.class); + myServerInterceptor = mock(IServerOperationInterceptor.class); + myDaoInterceptor = mock(IServerOperationInterceptor.class); resetServerInterceptor(); @@ -88,6 +89,57 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes when(myServerInterceptor.outgoingResponse(any(RequestDetails.class), any(ResponseDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true); } + @Test + public void testCreateConditionalNoOpResourceInTransaction() throws Exception { + String methodName = "foo"; + + Patient pt = new Patient(); + pt.addName().setFamily(methodName); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + BundleEntryComponent entry = bundle.addEntry(); + entry.setFullUrl("Patient"); + entry.setResource(pt); + entry.getRequest().setMethod(HTTPVerb.POST); + entry.getRequest().setUrl("Patient"); + + // Transaction time! + transaction(bundle); + + // Do it again but with a conditional create that shouldn't actually create + resetServerInterceptor(); + entry.getRequest().setIfNoneExist("Patient?name=" + methodName); + transaction(bundle); + + /* + * Server Interceptor + */ + + ArgumentCaptor<ActionRequestDetails> ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class); + ArgumentCaptor<RestOperationTypeEnum> opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class); + verify(myServerInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture()); + assertEquals(RestOperationTypeEnum.TRANSACTION, opTypeCaptor.getAllValues().get(0)); + + verify(myServerInterceptor, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(myServerInterceptor, times(0)).resourceCreated(any(RequestDetails.class), any(IBaseResource.class)); + verify(myServerInterceptor, times(0)).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class)); + + /* + * DAO Interceptor + */ + + ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class); + opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class); + verify(myDaoInterceptor, times(1)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture()); + assertEquals(RestOperationTypeEnum.TRANSACTION, opTypeCaptor.getAllValues().get(0)); + + verify(myDaoInterceptor, times(0)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(myDaoInterceptor, times(0)).resourceCreated(any(RequestDetails.class), any(IBaseResource.class)); + verify(myDaoInterceptor, times(0)).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class)); + + } + @Test public void testCreateResource() throws IOException { String methodName = "testCreateResource"; @@ -123,11 +175,11 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes } /* - * This is a weird way of verifying, but because this class - * is a child of a superclass that has other test children - * it's possible that other tests are hitting the server - * at the same time - */ + * This is a weird way of verifying, but because this class + * is a child of a superclass that has other test children + * it's possible that other tests are hitting the server + * at the same time + */ @Test public void testCreateResourceInTransaction() throws IOException { String methodName = "testCreateResourceInTransaction"; @@ -143,16 +195,7 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes entry.getRequest().setMethod(HTTPVerb.POST); entry.getRequest().setUrl("Patient"); - String resource = myFhirCtx.newXmlParser().encodeResourceToString(bundle); - - HttpPost post = new HttpPost(ourServerBase + "/"); - post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); - CloseableHttpResponse response = ourHttpClient.execute(post); - try { - assertEquals(200, response.getStatusLine().getStatusCode()); - } finally { - response.close(); - } + transaction(bundle); /* * Server Interceptor @@ -246,6 +289,72 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes } + @Test + public void testUpdateNoOpResourceInTransaction() throws Exception { + String methodName = "foo"; + + Patient pt = new Patient(); + pt.addName().setFamily(methodName); + String ptId = myPatientDao.create(pt).getId().toUnqualifiedVersionless().getValue(); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + BundleEntryComponent entry = bundle.addEntry(); + entry.setFullUrl(ptId); + entry.setResource(pt); + entry.getRequest().setMethod(HTTPVerb.PUT); + entry.getRequest().setUrl(ptId); + + // Transaction time! + transaction(bundle); + + // Do it again but with an update that shouldn't actually create + resetServerInterceptor(); + entry.getRequest().setIfNoneExist("Patient?name=" + methodName); + transaction(bundle); + + /* + * Server Interceptor + */ + + ArgumentCaptor<ActionRequestDetails> ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class); + ArgumentCaptor<RestOperationTypeEnum> opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class); + verify(myServerInterceptor, times(2)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture()); + assertEquals(RestOperationTypeEnum.TRANSACTION, opTypeCaptor.getAllValues().get(0)); + assertEquals(RestOperationTypeEnum.UPDATE, opTypeCaptor.getAllValues().get(1)); + + verify(myServerInterceptor, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(myServerInterceptor, times(0)).resourceCreated(any(RequestDetails.class), any(IBaseResource.class)); + verify(myServerInterceptor, times(0)).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class)); + + /* + * DAO Interceptor + */ + + ardCaptor = ArgumentCaptor.forClass(ActionRequestDetails.class); + opTypeCaptor = ArgumentCaptor.forClass(RestOperationTypeEnum.class); + verify(myDaoInterceptor, times(2)).incomingRequestPreHandled(opTypeCaptor.capture(), ardCaptor.capture()); + assertEquals(RestOperationTypeEnum.TRANSACTION, opTypeCaptor.getAllValues().get(0)); + assertEquals(RestOperationTypeEnum.UPDATE, opTypeCaptor.getAllValues().get(1)); + + verify(myDaoInterceptor, times(0)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(myDaoInterceptor, times(0)).resourceCreated(any(RequestDetails.class), any(IBaseResource.class)); + verify(myDaoInterceptor, times(0)).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class)); + + } + + private void transaction(Bundle theBundle) throws IOException { + String resource = myFhirCtx.newXmlParser().encodeResourceToString(theBundle); + HttpPost post = new HttpPost(ourServerBase + "/"); + post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + assertEquals(200, response.getStatusLine().getStatusCode()); + } finally { + response.close(); + } + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java index a8a5d3a702d..5a9c817e71e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java @@ -135,6 +135,41 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test { waitForSize(0, ourCreatedObservations); waitForSize(1, ourUpdatedObservations); assertEquals(Constants.CT_FHIR_JSON_NEW, ourContentTypes.get(0)); + } + + @Test + public void testRestHookSubscriptionNoopUpdateDoesntTriggerNewDelivery() throws Exception { + String payload = "application/fhir+json"; + + String code = "1000000050"; + String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml"; + String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml"; + + createSubscription(criteria1, payload, ourListenerServerBase); + createSubscription(criteria2, payload, ourListenerServerBase); + + Observation obs = sendObservation(code, "SNOMED-CT"); + + // Should see 1 subscription notification + waitForQueueToDrain(); + waitForSize(0, ourCreatedObservations); + waitForSize(1, ourUpdatedObservations); + assertEquals(Constants.CT_FHIR_JSON_NEW, ourContentTypes.get(0)); + + // Send an update with no changes + obs.setId(obs.getIdElement().toUnqualifiedVersionless()); + myClient.update().resource(obs).execute(); + + // Should be no further deliveries + Thread.sleep(1000); + waitForQueueToDrain(); + waitForSize(0, ourCreatedObservations); + waitForSize(1, ourUpdatedObservations); + + + + + } @Test diff --git a/hapi-fhir-jpaserver-elasticsearch/src/main/java/ca/uhn/fhir/jpa/search/ElasticsearchMappingProvider.java b/hapi-fhir-jpaserver-elasticsearch/src/main/java/ca/uhn/fhir/jpa/search/ElasticsearchMappingProvider.java index 12f25874116..2fe8b5824aa 100644 --- a/hapi-fhir-jpaserver-elasticsearch/src/main/java/ca/uhn/fhir/jpa/search/ElasticsearchMappingProvider.java +++ b/hapi-fhir-jpaserver-elasticsearch/src/main/java/ca/uhn/fhir/jpa/search/ElasticsearchMappingProvider.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.search; +/*- + * #%L + * HAPI FHIR JPA Server - ElasticSearch Integration + * %% + * Copyright (C) 2014 - 2018 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import org.hibernate.search.elasticsearch.analyzer.definition.ElasticsearchAnalysisDefinitionRegistryBuilder; import org.hibernate.search.elasticsearch.analyzer.definition.spi.ElasticsearchAnalysisDefinitionProvider; diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8869cddb77e..2ab3593d359 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -240,6 +240,12 @@ is supported according to the FHIR specification. Thanks to Jeff Chung for the pull request! </action> + <action type="fix"> + JPA Server Operation Interceptor create/update methods will now no + longer be fired if the create/update operation being performed + is a no-op (e.g. a conditional create that did not need to perform + any action, or an update where the contents didn't actually change) + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From 1ba00f6b11c0e71eda4cbd9f238584728f08c354 Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Thu, 22 Mar 2018 06:52:18 -0400 Subject: [PATCH 16/31] Credit for #879 --- src/changes/changes.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2ab3593d359..0cc28a7fddd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -246,6 +246,12 @@ is a no-op (e.g. a conditional create that did not need to perform any action, or an update where the contents didn't actually change) </action> + <action type="fix" issue="879"> + JPA server sometimes updated resources even though the client + supplied an update with no actual changes in it, due to + changes in the metadata section being considered content + changes. Thanks to Kyle Meadows for the pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From 37f12ac28bb2e72105a9bc0506fa3cca132a45c1 Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Fri, 23 Mar 2018 06:35:53 -0400 Subject: [PATCH 17/31] Credit for #817 --- pom.xml | 6 +++++- src/changes/changes.xml | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 48fe9e694fe..465cd1eb498 100644 --- a/pom.xml +++ b/pom.xml @@ -402,6 +402,10 @@ <id>javajeff</id> <name>Jeff Chung</name> </developer> + <developer> + <id>anoush-bch</id> + <name>Anoush Mouradian</name> + </developer> </developers> <licenses> @@ -1968,7 +1972,6 @@ <module>hapi-fhir-jpaserver-base</module> <module>hapi-fhir-jpaserver-elasticsearch</module> <module>hapi-fhir-jpaserver-example</module> - <module>hapi-fhir-jpaserver-dynamic</module> <module>restful-server-example</module> <module>restful-server-example-test</module> <module>hapi-fhir-testpage-overlay</module> @@ -1982,6 +1985,7 @@ <module>example-projects/hapi-fhir-base-example-embedded-ws</module> <module>example-projects/hapi-fhir-standalone-overlay-example</module> <module>example-projects/hapi-fhir-jpaserver-cds-example</module> + <module>example-projects/hapi-fhir-jpaserver-dynamic</module> <module>hapi-fhir-jacoco</module> <module>hapi-fhir-igpacks</module> <module>hapi-fhir-spring-boot</module> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0cc28a7fddd..62adf19f0dc 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -252,6 +252,12 @@ changes in the metadata section being considered content changes. Thanks to Kyle Meadows for the pull request! </action> + <action type="add" issue="817"> + A new example project has been added called hapi-fhir-jpaserver-dynamic, + which uses application/environment properties to configure which version + of FHIR the server supports and other configuration. Thanks to + Anoush Mouradian for the pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From fc580d859815b35629fee73882da293d09b2b79a Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Fri, 23 Mar 2018 06:36:12 -0400 Subject: [PATCH 18/31] Moving example project to examples directory --- .../hapi-fhir-jpaserver-dynamic}/.README.md.html | 0 .../hapi-fhir-jpaserver-dynamic}/.gitignore | 0 .../hapi-fhir-jpaserver-dynamic}/Dockerfile | 0 .../hapi-fhir-jpaserver-dynamic}/Dockerfile.tomcat | 0 .../hapi-fhir-jpaserver-dynamic}/README.md | 0 .../hapi-fhir-jpaserver-dynamic}/build-docker-image.sh | 0 .../hapi-fhir-jpaserver-dynamic}/pom.xml | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java | 0 .../main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java | 0 .../main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/Utils.java | 0 .../src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java | 0 .../src/main/resources/config/dstu2/app_dev.properties | 0 .../src/main/resources/config/dstu2/app_local.properties | 0 .../src/main/resources/config/dstu2/app_prod.properties | 0 .../src/main/resources/config/dstu2/app_stg.properties | 0 .../src/main/resources/config/dstu2/immutable.properties | 0 .../src/main/resources/config/dstu3/app_dev.properties | 0 .../src/main/resources/config/dstu3/app_local.properties | 0 .../src/main/resources/config/dstu3/app_prod.properties | 0 .../src/main/resources/config/dstu3/app_stg.properties | 0 .../src/main/resources/config/dstu3/immutable.properties | 0 .../hapi-fhir-jpaserver-dynamic}/src/main/resources/logback.xml | 0 .../src/main/webapp/WEB-INF/templates/about.html | 0 .../src/main/webapp/WEB-INF/templates/tmpl-footer.html | 0 .../src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html | 0 .../src/main/webapp/WEB-INF/web-dstu2.xml | 0 .../src/main/webapp/WEB-INF/web-dstu3.xml | 0 .../src/main/webapp/WEB-INF/web_notNeeded.xml | 0 .../src/main/webapp/WEB-INF/xsd/javaee_6.xsd | 0 .../src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd | 0 .../src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd | 0 .../src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd | 0 .../src/main/webapp/WEB-INF/xsd/xml.xsd | 0 .../src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java | 0 .../test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java | 0 .../src/test/resources/.keep_hapi-fhir-jpaserver-example | 0 .../hapi-fhir-jpaserver-dynamic}/var/lucenefiles/keep.txt | 0 43 files changed, 0 insertions(+), 0 deletions(-) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/.README.md.html (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/.gitignore (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/Dockerfile (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/Dockerfile.tomcat (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/README.md (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/build-docker-image.sh (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/pom.xml (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu2/app_dev.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu2/app_local.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu2/app_prod.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu2/app_stg.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu2/immutable.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu3/app_dev.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu3/app_local.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu3/app_prod.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu3/app_stg.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/config/dstu3/immutable.properties (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/resources/logback.xml (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/templates/about.html (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/templates/tmpl-footer.html (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/web-dstu2.xml (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/web-dstu3.xml (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/web_notNeeded.xml (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/xsd/javaee_6.xsd (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/main/webapp/WEB-INF/xsd/xml.xsd (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/src/test/resources/.keep_hapi-fhir-jpaserver-example (100%) rename {hapi-fhir-jpaserver-dynamic => example-projects/hapi-fhir-jpaserver-dynamic}/var/lucenefiles/keep.txt (100%) diff --git a/hapi-fhir-jpaserver-dynamic/.README.md.html b/example-projects/hapi-fhir-jpaserver-dynamic/.README.md.html similarity index 100% rename from hapi-fhir-jpaserver-dynamic/.README.md.html rename to example-projects/hapi-fhir-jpaserver-dynamic/.README.md.html diff --git a/hapi-fhir-jpaserver-dynamic/.gitignore b/example-projects/hapi-fhir-jpaserver-dynamic/.gitignore similarity index 100% rename from hapi-fhir-jpaserver-dynamic/.gitignore rename to example-projects/hapi-fhir-jpaserver-dynamic/.gitignore diff --git a/hapi-fhir-jpaserver-dynamic/Dockerfile b/example-projects/hapi-fhir-jpaserver-dynamic/Dockerfile similarity index 100% rename from hapi-fhir-jpaserver-dynamic/Dockerfile rename to example-projects/hapi-fhir-jpaserver-dynamic/Dockerfile diff --git a/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat b/example-projects/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat similarity index 100% rename from hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat rename to example-projects/hapi-fhir-jpaserver-dynamic/Dockerfile.tomcat diff --git a/hapi-fhir-jpaserver-dynamic/README.md b/example-projects/hapi-fhir-jpaserver-dynamic/README.md similarity index 100% rename from hapi-fhir-jpaserver-dynamic/README.md rename to example-projects/hapi-fhir-jpaserver-dynamic/README.md diff --git a/hapi-fhir-jpaserver-dynamic/build-docker-image.sh b/example-projects/hapi-fhir-jpaserver-dynamic/build-docker-image.sh similarity index 100% rename from hapi-fhir-jpaserver-dynamic/build-docker-image.sh rename to example-projects/hapi-fhir-jpaserver-dynamic/build-docker-image.sh diff --git a/hapi-fhir-jpaserver-dynamic/pom.xml b/example-projects/hapi-fhir-jpaserver-dynamic/pom.xml similarity index 100% rename from hapi-fhir-jpaserver-dynamic/pom.xml rename to example-projects/hapi-fhir-jpaserver-dynamic/pom.xml diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigCommon.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu2.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfig.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/FhirTesterConfigDstu2.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/ImmutablePropertiesConfig.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemoDstu2.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/Utils.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/java/ca/uhn/fhir/jpa/demo/WebInitializer.java diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_dev.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_local.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_prod.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/app_stg.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu2/immutable.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_dev.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_local.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_prod.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/app_stg.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/config/dstu3/immutable.properties diff --git a/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/resources/logback.xml diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/about.html diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-footer.html diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/templates/tmpl-home-welcome.html diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu2.xml diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web-dstu3.xml diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/web_notNeeded.xml diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/javaee_6.xsd diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd diff --git a/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd b/example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd rename to example-projects/hapi-fhir-jpaserver-dynamic/src/main/webapp/WEB-INF/xsd/xml.xsd diff --git a/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java diff --git a/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java b/example-projects/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java rename to example-projects/hapi-fhir-jpaserver-dynamic/src/test/java/ca/uhn/fhir/jpa/demo/RandomServerPortProvider.java diff --git a/hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example b/example-projects/hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example similarity index 100% rename from hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example rename to example-projects/hapi-fhir-jpaserver-dynamic/src/test/resources/.keep_hapi-fhir-jpaserver-example diff --git a/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt b/example-projects/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt similarity index 100% rename from hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt rename to example-projects/hapi-fhir-jpaserver-dynamic/var/lucenefiles/keep.txt From 352a9b85936b1f57b2cf74e192061a8e31955e3c Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Fri, 23 Mar 2018 06:37:48 -0400 Subject: [PATCH 19/31] Credit for #581 --- src/changes/changes.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 62adf19f0dc..d5de40c066c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -258,6 +258,10 @@ of FHIR the server supports and other configuration. Thanks to Anoush Mouradian for the pull request! </action> + <action type="add" issue="581"> + A new example project showing the use of JAX-RS Server Side Events has + been added. Thanks to Jens Kristian Villadsen for the pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From d5a1c089b831b94f4c47232efa337e70431dde4f Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Fri, 23 Mar 2018 06:49:41 -0400 Subject: [PATCH 20/31] Credit for #864 --- pom.xml | 4 ++++ src/changes/changes.xml | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index 465cd1eb498..706afe2186d 100644 --- a/pom.xml +++ b/pom.xml @@ -406,6 +406,10 @@ <id>anoush-bch</id> <name>Anoush Mouradian</name> </developer> + <developer> + <id>splatch</id> + <name>Łukasz Dywicki</name> + </developer> </developers> <licenses> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d5de40c066c..6a4983a5373 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -262,6 +262,11 @@ A new example project showing the use of JAX-RS Server Side Events has been added. Thanks to Jens Kristian Villadsen for the pull request! </action> + <action type="remove" issue="864"> + An unneccesary reference to the Javassist library has been + removed from the build. Thanks to Łukasz Dywicki for the + pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From e5903f79f04366795dc34f74f1435801b2812151 Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Fri, 23 Mar 2018 07:15:22 -0400 Subject: [PATCH 21/31] A bit of test cleanup --- .../uhn/fhirtest/interceptor/PublicSecurityInterceptor.java | 6 ++---- pom.xml | 4 ++-- .../hapi-fhir-base-test-mindeps-client}/pom.xml | 4 ++-- .../src/test/java/ca/uhn/fhir/rest/client/ClientTest.java | 0 .../hapi-fhir-base-test-mindeps-server}/.gitignore | 0 .../hapi-fhir-base-test-mindeps-server}/pom.xml | 6 +++--- .../java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java | 0 .../java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java | 0 .../test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java | 0 .../src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java | 0 .../src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java | 0 .../test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java | 0 12 files changed, 9 insertions(+), 11 deletions(-) rename {hapi-fhir-base-test-mindeps-client => tests/hapi-fhir-base-test-mindeps-client}/pom.xml (96%) rename {hapi-fhir-base-test-mindeps-client => tests/hapi-fhir-base-test-mindeps-client}/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/.gitignore (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/pom.xml (94%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java (100%) rename {hapi-fhir-base-test-mindeps-server => tests/hapi-fhir-base-test-mindeps-server}/src/test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java (100%) diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java index 15614f2ecd4..f3011982d53 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java @@ -18,7 +18,7 @@ public class PublicSecurityInterceptor extends AuthorizationInterceptor { public PublicSecurityInterceptor() { String passwordsString = System.getProperty("fhir.tdlpass"); String[] passwords = passwordsString.split(","); - myTokens = new HashSet<String>(Arrays.asList(passwords)); + myTokens = new HashSet<>(Arrays.asList(passwords)); ourLog.info("We have {} valid security tokens", myTokens.size()); } @@ -27,7 +27,6 @@ public class PublicSecurityInterceptor extends AuthorizationInterceptor { public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) { String authHeader = theRequestDetails.getHeader("Authorization"); - //@formatter:off if (isBlank(authHeader)) { return new RuleBuilder() .deny().operation().named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING).onServer().andThen() @@ -35,8 +34,7 @@ public class PublicSecurityInterceptor extends AuthorizationInterceptor { .allowAll() .build(); } - //@formatter:off - + if (!authHeader.startsWith("Bearer ")) { throw new ForbiddenOperationException("Invalid bearer token, must be in the form \"Authorization: Bearer [token]\""); } diff --git a/pom.xml b/pom.xml index 706afe2186d..1a2c13f137b 100644 --- a/pom.xml +++ b/pom.xml @@ -1954,8 +1954,6 @@ <module>hapi-deployable-pom</module> <module>hapi-fhir-base</module> <module>hapi-fhir-utilities</module> - <module>hapi-fhir-base-test-mindeps-client</module> - <module>hapi-fhir-base-test-mindeps-server</module> <module>hapi-tinder-plugin</module> <module>hapi-tinder-test</module> <module>hapi-fhir-client</module> @@ -1990,6 +1988,8 @@ <module>example-projects/hapi-fhir-standalone-overlay-example</module> <module>example-projects/hapi-fhir-jpaserver-cds-example</module> <module>example-projects/hapi-fhir-jpaserver-dynamic</module> + <module>tests/hapi-fhir-base-test-mindeps-client</module> + <module>tests/hapi-fhir-base-test-mindeps-server</module> <module>hapi-fhir-jacoco</module> <module>hapi-fhir-igpacks</module> <module>hapi-fhir-spring-boot</module> diff --git a/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml similarity index 96% rename from hapi-fhir-base-test-mindeps-client/pom.xml rename to tests/hapi-fhir-base-test-mindeps-client/pom.xml index f5b2437dd8b..1df31b9ed08 100644 --- a/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -5,10 +5,10 @@ <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> <version>3.3.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> + <relativePath>../../pom.xml</relativePath> </parent> - <artifactId>hapi-fhir-base-testmindeps-client</artifactId> + <artifactId>hapi-fhir-base-test-mindeps-client</artifactId> <packaging>jar</packaging> <name>HAPI FHIR - Minimal Dependency Test - Client</name> diff --git a/hapi-fhir-base-test-mindeps-client/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java b/tests/hapi-fhir-base-test-mindeps-client/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-client/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java rename to tests/hapi-fhir-base-test-mindeps-client/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java diff --git a/hapi-fhir-base-test-mindeps-server/.gitignore b/tests/hapi-fhir-base-test-mindeps-server/.gitignore similarity index 100% rename from hapi-fhir-base-test-mindeps-server/.gitignore rename to tests/hapi-fhir-base-test-mindeps-server/.gitignore diff --git a/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml similarity index 94% rename from hapi-fhir-base-test-mindeps-server/pom.xml rename to tests/hapi-fhir-base-test-mindeps-server/pom.xml index a300729423e..77214e67bf0 100644 --- a/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -1,4 +1,4 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> @@ -6,10 +6,10 @@ <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> <version>3.3.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> + <relativePath>../../pom.xml</relativePath> </parent> - <artifactId>hapi-fhir-base-testmindeps-server</artifactId> + <artifactId>hapi-fhir-base-test-mindeps-server</artifactId> <packaging>jar</packaging> <name>HAPI FHIR - Minimal Dependency Test - Server</name> diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionJsonParserTest.java diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/parser/MultiVersionXmlParserTest.java diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/FhirContextTest.java diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ReadTest.java diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/SetupTest.java diff --git a/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java b/tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java similarity index 100% rename from hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java rename to tests/hapi-fhir-base-test-mindeps-server/src/test/java/ca/uhn/fhir/testmindeps/ValidatorTest.java From a3a15ac9d88323ce3424bbda3f05cec6f25115ca Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Sat, 24 Mar 2018 06:45:41 -0400 Subject: [PATCH 22/31] Add test and credit for #819 --- .../r4/FhirResourceDaoR4SearchNoFtTest.java | 581 ++++++++++-------- src/changes/changes.xml | 4 + 2 files changed, 314 insertions(+), 271 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java index 2f603eed7b3..05185a32150 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java @@ -1,133 +1,114 @@ package ca.uhn.fhir.jpa.dao.r4; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; - -import java.io.IOException; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.r4.model.*; -import org.hl7.fhir.r4.model.Bundle.*; -import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; -import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; -import org.hl7.fhir.r4.model.Observation.ObservationStatus; -import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType; -import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus; -import org.hl7.fhir.instance.model.api.*; -import org.junit.*; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.*; - -import ca.uhn.fhir.jpa.dao.*; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.SearchParameterMap; import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum; import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.parser.StrictErrorHandler; import ca.uhn.fhir.rest.api.Constants; -import ca.uhn.fhir.rest.api.SortOrderEnum; -import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.TestUtil; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.r4.model.*; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.hl7.fhir.r4.model.Bundle.HTTPVerb; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; +import org.hl7.fhir.r4.model.Observation.ObservationStatus; +import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType; +import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus; +import org.junit.*; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; @SuppressWarnings("unchecked") public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4SearchNoFtTest.class); - @Before - public void beforeDisableCacheReuse() { - myDaoConfig.setReuseCachedSearchResultsForMillis(null); - } - @After public void afterResetSearchSize() { myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum()); } - /** - * See #744 - */ - @Test - public void testSearchWithVeryLongUrlShorter() { - myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); - - Patient p = new Patient(); - p.addName().setFamily("A1"); - myPatientDao.create(p); - - assertEquals(0, mySearchEntityDao.count()); - - SearchParameterMap map = new SearchParameterMap(); - StringOrListParam or = new StringOrListParam(); - or.addOr(new StringParam("A1")); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'A'))); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'B'))); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'C'))); - map.add(Patient.SP_NAME, or); - IBundleProvider results = myPatientDao.search(map); - assertEquals(1, results.getResources(0, 10).size()); - assertEquals(1, mySearchEntityDao.count()); - - map = new SearchParameterMap(); - or = new StringOrListParam(); - or.addOr(new StringParam("A1")); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'A'))); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'B'))); - or.addOr(new StringParam(StringUtils.leftPad("", 200, 'C'))); - map.add(Patient.SP_NAME, or); - results = myPatientDao.search(map); - assertEquals(1, results.getResources(0, 10).size()); - assertEquals(1, mySearchEntityDao.count()); - + @Before + public void beforeDisableCacheReuse() { + myDaoConfig.setReuseCachedSearchResultsForMillis(null); } - /** - * See #744 - */ @Test - public void testSearchWithVeryLongUrlLonger() { - myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); + public void testChainWithMultipleTypePossibilities() { - Patient p = new Patient(); - p.addName().setFamily("A1"); - myPatientDao.create(p); + Patient sub1 = new Patient(); + sub1.setActive(true); + sub1.addIdentifier().setSystem("foo").setValue("bar"); + String sub1Id = myPatientDao.create(sub1).getId().toUnqualifiedVersionless().getValue(); - assertEquals(0, mySearchEntityDao.count()); + Group sub2 = new Group(); + sub2.setActive(true); + sub2.addIdentifier().setSystem("foo").setValue("bar"); + String sub2Id = myGroupDao.create(sub2).getId().toUnqualifiedVersionless().getValue(); - SearchParameterMap map = new SearchParameterMap(); - StringOrListParam or = new StringOrListParam(); - or.addOr(new StringParam("A1")); - for (int i = 0; i < 50; i++) { - or.addOr(new StringParam(StringUtils.leftPad("", 200, (char)('A' + i)))); - } - map.add(Patient.SP_NAME, or); - IBundleProvider results = myPatientDao.search(map); - assertEquals(1, results.getResources(0, 10).size()); - assertEquals(1, mySearchEntityDao.count()); + Encounter enc1 = new Encounter(); + enc1.getSubject().setReference(sub1Id); + String enc1Id = myEncounterDao.create(enc1).getId().toUnqualifiedVersionless().getValue(); + + Encounter enc2 = new Encounter(); + enc2.getSubject().setReference(sub2Id); + String enc2Id = myEncounterDao.create(enc2).getId().toUnqualifiedVersionless().getValue(); + + List<String> ids; + SearchParameterMap map; + IBundleProvider results; map = new SearchParameterMap(); - or = new StringOrListParam(); - or.addOr(new StringParam("A1")); - or.addOr(new StringParam("A1")); - for (int i = 0; i < 50; i++) { - or.addOr(new StringParam(StringUtils.leftPad("", 200, (char)('A' + i)))); - } - map.add(Patient.SP_NAME, or); - results = myPatientDao.search(map); - assertEquals(1, results.getResources(0, 10).size()); - // We expect a new one because we don't cache the search URL for very long search URLs - assertEquals(2, mySearchEntityDao.count()); + map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject", "foo|bar").setChain("identifier")); + results = myEncounterDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, hasItems(enc1Id, enc2Id)); + map = new SearchParameterMap(); + map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject:Patient", "foo|bar").setChain("identifier")); + results = myEncounterDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, hasItems(enc1Id)); + + map = new SearchParameterMap(); + map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject:Group", "foo|bar").setChain("identifier")); + results = myEncounterDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, hasItems(enc2Id)); + + map = new SearchParameterMap(); + map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject", "04823543").setChain("identifier")); + results = myEncounterDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, empty()); } /** @@ -151,50 +132,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(ids, contains(moId.getValue())); } - @Test - public void testIncludeLinkedObservations() { - - DiagnosticReport dr = new DiagnosticReport(); - dr.setId("DiagnosticReport/DR"); - dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL); - - Observation parentObs = new Observation(); - parentObs.setStatus(ObservationStatus.FINAL); - parentObs.setId("Observation/parentObs"); - - Observation childObs = new Observation(); - childObs.setId("Observation/childObs"); - childObs.setStatus(ObservationStatus.FINAL); - - dr.addResult().setReference("Observation/parentObs").setResource(parentObs); - parentObs.addHasMember(new Reference(childObs).setReference("Observation/childObs")); - childObs.addDerivedFrom(new Reference(parentObs).setReference("Observation/parentObs")); - - Bundle input = new Bundle(); - input.setType(BundleType.TRANSACTION); - input.addEntry() - .setResource(dr) - .getRequest().setMethod(HTTPVerb.PUT).setUrl(dr.getId()); - input.addEntry() - .setResource(parentObs) - .getRequest().setMethod(HTTPVerb.PUT).setUrl(parentObs.getId()); - input.addEntry() - .setResource(childObs) - .getRequest().setMethod(HTTPVerb.PUT).setUrl(childObs.getId()); - mySystemDao.transaction(mySrd, input); - - SearchParameterMap params = new SearchParameterMap(); - params.add("_id", new TokenParam(null, "DR")); - params.addInclude(new Include("DiagnosticReport:subject").setRecurse(true)); - params.addInclude(new Include("DiagnosticReport:result").setRecurse(true)); - params.addInclude(Observation.INCLUDE_HAS_MEMBER.setRecurse(true)); - - IBundleProvider result = myDiagnosticReportDao.search(params); - List<String> resultIds = toUnqualifiedVersionlessIdValues(result); - assertThat(resultIds, containsInAnyOrder("DiagnosticReport/DR", "Observation/parentObs", "Observation/childObs")); - - } - @Test public void testEmptyChain() { @@ -206,56 +143,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(ids, empty()); } - @Test - public void testChainWithMultipleTypePossibilities() { - - Patient sub1 = new Patient(); - sub1.setActive(true); - sub1.addIdentifier().setSystem("foo").setValue("bar"); - String sub1Id = myPatientDao.create(sub1).getId().toUnqualifiedVersionless().getValue(); - - Group sub2 = new Group(); - sub2.setActive(true); - sub2.addIdentifier().setSystem("foo").setValue("bar"); - String sub2Id = myGroupDao.create(sub2).getId().toUnqualifiedVersionless().getValue(); - - Encounter enc1 = new Encounter(); - enc1.getSubject().setReference(sub1Id); - String enc1Id = myEncounterDao.create(enc1).getId().toUnqualifiedVersionless().getValue(); - - Encounter enc2 = new Encounter(); - enc2.getSubject().setReference(sub2Id); - String enc2Id = myEncounterDao.create(enc2).getId().toUnqualifiedVersionless().getValue(); - - List<String> ids; - SearchParameterMap map; - IBundleProvider results; - - map = new SearchParameterMap(); - map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject", "foo|bar").setChain("identifier")); - results = myEncounterDao.search(map); - ids = toUnqualifiedVersionlessIdValues(results); - assertThat(ids, hasItems(enc1Id, enc2Id)); - - map = new SearchParameterMap(); - map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject:Patient", "foo|bar").setChain("identifier")); - results = myEncounterDao.search(map); - ids = toUnqualifiedVersionlessIdValues(results); - assertThat(ids, hasItems(enc1Id)); - - map = new SearchParameterMap(); - map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject:Group", "foo|bar").setChain("identifier")); - results = myEncounterDao.search(map); - ids = toUnqualifiedVersionlessIdValues(results); - assertThat(ids, hasItems(enc2Id)); - - map = new SearchParameterMap(); - map.add(Encounter.SP_SUBJECT, new ReferenceParam("subject", "04823543").setChain("identifier")); - results = myEncounterDao.search(map); - ids = toUnqualifiedVersionlessIdValues(results); - assertThat(ids, empty()); - } - @Test public void testEverythingTimings() { String methodName = "testEverythingTimings"; @@ -506,6 +393,50 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } + @Test + public void testIncludeLinkedObservations() { + + DiagnosticReport dr = new DiagnosticReport(); + dr.setId("DiagnosticReport/DR"); + dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL); + + Observation parentObs = new Observation(); + parentObs.setStatus(ObservationStatus.FINAL); + parentObs.setId("Observation/parentObs"); + + Observation childObs = new Observation(); + childObs.setId("Observation/childObs"); + childObs.setStatus(ObservationStatus.FINAL); + + dr.addResult().setReference("Observation/parentObs").setResource(parentObs); + parentObs.addHasMember(new Reference(childObs).setReference("Observation/childObs")); + childObs.addDerivedFrom(new Reference(parentObs).setReference("Observation/parentObs")); + + Bundle input = new Bundle(); + input.setType(BundleType.TRANSACTION); + input.addEntry() + .setResource(dr) + .getRequest().setMethod(HTTPVerb.PUT).setUrl(dr.getId()); + input.addEntry() + .setResource(parentObs) + .getRequest().setMethod(HTTPVerb.PUT).setUrl(parentObs.getId()); + input.addEntry() + .setResource(childObs) + .getRequest().setMethod(HTTPVerb.PUT).setUrl(childObs.getId()); + mySystemDao.transaction(mySrd, input); + + SearchParameterMap params = new SearchParameterMap(); + params.add("_id", new TokenParam(null, "DR")); + params.addInclude(new Include("DiagnosticReport:subject").setRecurse(true)); + params.addInclude(new Include("DiagnosticReport:result").setRecurse(true)); + params.addInclude(Observation.INCLUDE_HAS_MEMBER.setRecurse(true)); + + IBundleProvider result = myDiagnosticReportDao.search(params); + List<String> resultIds = toUnqualifiedVersionlessIdValues(result); + assertThat(resultIds, containsInAnyOrder("DiagnosticReport/DR", "Observation/parentObs", "Observation/childObs")); + + } + @Test public void testIndexNoDuplicatesDate() { Encounter order = new Encounter(); @@ -519,7 +450,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { IIdType id = myEncounterDao.create(order, mySrd).getId().toUnqualifiedVersionless(); List<IIdType> actual = toUnqualifiedVersionlessIds( - myEncounterDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Encounter.SP_LOCATION_PERIOD, new DateParam("2011-12-12T11:12:12Z")))); + myEncounterDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Encounter.SP_LOCATION_PERIOD, new DateParam("2011-12-12T11:12:12Z")))); assertThat(actual, contains(id)); Class<ResourceIndexedSearchParamDate> type = ResourceIndexedSearchParamDate.class; @@ -553,9 +484,9 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { List<ResourceIndexedSearchParamNumber> results = myEntityManager.createQuery("SELECT i FROM " + type.getSimpleName() + " i", type).getResultList(); ourLog.info(toStringMultiline(results)); assertThat(results, containsInAnyOrder( - ((ResourceIndexedSearchParamNumber)(new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_SEQUENCE, null).setResource(resource).setMissing(true))), - ((ResourceIndexedSearchParamNumber)(new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_NUMBER, new BigDecimal("1.00")).setResource(resource))), - ((ResourceIndexedSearchParamNumber)(new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_NUMBER, new BigDecimal("2.00")).setResource(resource))) + ((ResourceIndexedSearchParamNumber) (new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_SEQUENCE, null).setResource(resource).setMissing(true))), + ((ResourceIndexedSearchParamNumber) (new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_NUMBER, new BigDecimal("1.00")).setResource(resource))), + ((ResourceIndexedSearchParamNumber) (new ResourceIndexedSearchParamNumber(ImmunizationRecommendation.SP_DOSE_NUMBER, new BigDecimal("2.00")).setResource(resource))) )); } }); @@ -577,7 +508,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertEquals(2, results.size()); List<IIdType> actual = toUnqualifiedVersionlessIds( - mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, "http://foo", "UNIT")))); + mySubstanceDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Substance.SP_QUANTITY, new QuantityParam(null, 123, "http://foo", "UNIT")))); assertThat(actual, contains(id)); } @@ -610,11 +541,11 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { ourLog.info(toStringMultiline(results)); assertEquals(2, results.size()); List<IIdType> actual = toUnqualifiedVersionlessIds( - myServiceRequestDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ServiceRequest.SP_REPLACES, new ReferenceParam("ServiceRequest/somepract")))); + myServiceRequestDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ServiceRequest.SP_REPLACES, new ReferenceParam("ServiceRequest/somepract")))); assertThat(actual, contains(id)); } }); - + } @Test @@ -681,6 +612,17 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(actual, contains(id)); } + /** + * #454 + */ + @Test + public void testIndexWithUtf8Chars() throws IOException { + String input = IOUtils.toString(getClass().getResourceAsStream("/bug454_utf8.json"), StandardCharsets.UTF_8); + + CodeSystem cs = (CodeSystem) myFhirCtx.newJsonParser().parseResource(input); + myCodeSystemDao.create(cs); + } + @Test public void testReturnOnlyCorrectResourceType() { ValueSet vsRes = new ValueSet(); @@ -702,17 +644,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(actual, contains(csId)); } - /** - * #454 - */ - @Test - public void testIndexWithUtf8Chars() throws IOException { - String input = IOUtils.toString(getClass().getResourceAsStream("/bug454_utf8.json"), StandardCharsets.UTF_8); - - CodeSystem cs = (CodeSystem) myFhirCtx.newJsonParser().parseResource(input); - myCodeSystemDao.create(cs); - } - @Test public void testSearchAll() { { @@ -1324,8 +1255,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(patients, (hasItems(id1a, id1b))); assertThat(patients, not(hasItems(id2))); } - - + + { SearchParameterMap params = new SearchParameterMap(); params.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, beforeR2))); @@ -1401,7 +1332,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { map = new SearchParameterMap(); map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN, startDateTime.getValue()), - new DateParam(ParamPrefixEnum.LESSTHAN, myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValue()))); + new DateParam(ParamPrefixEnum.LESSTHAN, myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValue()))); ourLog.info("Searching: {}", map.getLastUpdated()); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a)); } @@ -1473,6 +1404,43 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } + /** + * See #819 + */ + @Test + public void testSearchTokenWithNotModifier() { + String male, female; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + patient.setGender(AdministrativeGender.MALE); + male = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); + } + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("002"); + patient.addName().setFamily("Tester").addGiven("Jane"); + patient.setGender(AdministrativeGender.FEMALE); + female = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); + } + + List<String> patients; + SearchParameterMap params; + + params = new SearchParameterMap(); + params.add(Patient.SP_GENDER, new TokenParam(null, "male")); + params.setLoadSynchronous(true); + patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); + assertThat(patients, contains(male)); + + params = new SearchParameterMap(); + params.add(Patient.SP_GENDER, new TokenParam(null, "male").setModifier(TokenParamModifier.NOT)); + params.setLoadSynchronous(true); + patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); + assertThat(patients, contains(female)); + } + @Test public void testSearchNumberParam() { ImmunizationRecommendation e1 = new ImmunizationRecommendation(); @@ -1542,7 +1510,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { { IBundleProvider found = myPatientDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(Patient.SP_GENDER, new TokenParam().setModifier(TokenParamModifier.IN).setValue("urn:testSearchOnCodesWithNone"))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(Patient.SP_GENDER, new TokenParam().setModifier(TokenParamModifier.IN).setValue("urn:testSearchOnCodesWithNone"))); assertThat(toUnqualifiedVersionlessIdValues(found), empty()); assertEquals(0, found.size().intValue()); } @@ -1682,7 +1650,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", patientId01, patientId02, obsId01, obsId02, drId01); List<Observation> result = toList(myObservationDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "urn:system|testSearchResourceLinkWithChain01")))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "urn:system|testSearchResourceLinkWithChain01")))); assertEquals(1, result.size()); assertEquals(obsId01.getIdPart(), result.get(0).getIdElement().getIdPart()); @@ -1696,15 +1664,15 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertEquals(0, result.size()); result = toList(myObservationDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "urn:system|testSearchResourceLinkWithChainXX")))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "urn:system|testSearchResourceLinkWithChainXX")))); assertEquals(2, result.size()); result = toList( - myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "testSearchResourceLinkWithChainXX")))); + myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "testSearchResourceLinkWithChainXX")))); assertEquals(2, result.size()); result = toList( - myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "|testSearchResourceLinkWithChainXX")))); + myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "|testSearchResourceLinkWithChainXX")))); assertEquals(0, result.size()); } @@ -1788,12 +1756,12 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { SearchParameterMap params; result = toUnqualifiedVersionlessIds(myObservationDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesXX")))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesXX")))); assertThat(result, containsInAnyOrder(obsId01)); assertEquals(1, result.size()); result = toUnqualifiedVersionlessIds(myObservationDao.search( - new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")))); + new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01")))); assertThat(result, containsInAnyOrder(obsId01)); assertEquals(1, result.size()); @@ -1811,7 +1779,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(result, containsInAnyOrder(obsId02)); result = toUnqualifiedVersionlessIds(myObservationDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesYY")))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypesYY")))); assertEquals(0, result.size()); } @@ -1848,7 +1816,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", patientId01, patientId02, obsId01, obsId02, drId01); List<Observation> result = toList( - myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId01")))); + myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_SUBJECT, new ReferenceParam("testSearchResourceLinkWithTextLogicalId01")))); assertEquals(1, result.size()); assertEquals(obsId01.getIdPart(), result.get(0).getIdElement().getIdPart()); @@ -1860,7 +1828,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } - @SuppressWarnings("unused") @Test public void testSearchResourceReferenceOnlyCorrectPath() { @@ -1893,48 +1860,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } - @Test - public void testSearchStringParamDoesntMatchWrongType() { - IIdType pid1; - IIdType pid2; - { - Patient patient = new Patient(); - patient.addName().setFamily("HELLO"); - pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); - } - { - Practitioner patient = new Practitioner(); - patient.addName().setFamily("HELLO"); - pid2 = myPractitionerDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); - } - - SearchParameterMap params; - List<IIdType> patients; - - params = new SearchParameterMap(); - params.add(Patient.SP_FAMILY, new StringParam("HELLO")); - patients = toUnqualifiedVersionlessIds(myPatientDao.search(params)); - assertThat(patients, containsInAnyOrder(pid1)); - assertThat(patients, not(containsInAnyOrder(pid2))); - } - - @Test - public void testSearchWithFetchSizeDefaultMaximum() { - myDaoConfig.setFetchSizeDefaultMaximum(5); - - for (int i = 0; i < 10; i++) { - Patient p = new Patient(); - p.addName().setFamily("PT" + i); - myPatientDao.create(p); - } - - SearchParameterMap map = new SearchParameterMap(); - map.setLoadSynchronous(true); - IBundleProvider values = myPatientDao.search(map); - assertEquals(5, values.size().intValue()); - assertEquals(5, values.getResources(0, 1000).size()); - } - @Test public void testSearchStringParam() throws Exception { IIdType pid1; @@ -1978,6 +1903,31 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } + @Test + public void testSearchStringParamDoesntMatchWrongType() { + IIdType pid1; + IIdType pid2; + { + Patient patient = new Patient(); + patient.addName().setFamily("HELLO"); + pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + { + Practitioner patient = new Practitioner(); + patient.addName().setFamily("HELLO"); + pid2 = myPractitionerDao.create(patient, mySrd).getId().toUnqualifiedVersionless(); + } + + SearchParameterMap params; + List<IIdType> patients; + + params = new SearchParameterMap(); + params.add(Patient.SP_FAMILY, new StringParam("HELLO")); + patients = toUnqualifiedVersionlessIds(myPatientDao.search(params)); + assertThat(patients, containsInAnyOrder(pid1)); + assertThat(patients, not(containsInAnyOrder(pid2))); + } + @Test public void testSearchStringParamReallyLong() { String methodName = "testSearchStringParamReallyLong"; @@ -2071,7 +2021,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam001"); patient.addName().setFamily("Tester").addGiven("testSearchTokenParam1"); patient.addCommunication().getLanguage().setText("testSearchTokenParamComText").addCoding().setCode("testSearchTokenParamCode").setSystem("testSearchTokenParamSystem") - .setDisplay("testSearchTokenParamDisplay"); + .setDisplay("testSearchTokenParamDisplay"); myPatientDao.create(patient, mySrd); patient = new Patient(); @@ -2145,7 +2095,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { patient.addIdentifier().setSystem("urn:system").setValue("testSearchTokenParam001"); patient.addName().setFamily("Tester").addGiven("testSearchTokenParam1"); patient.addCommunication().getLanguage().setText("testSearchTokenParamComText").addCoding().setCode("testSearchTokenParamCode").setSystem("testSearchTokenParamSystem") - .setDisplay("testSearchTokenParamDisplay"); + .setDisplay("testSearchTokenParamDisplay"); myPatientDao.create(patient, mySrd); patient = new Patient(); @@ -2355,6 +2305,22 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } + @Test + public void testSearchWithFetchSizeDefaultMaximum() { + myDaoConfig.setFetchSizeDefaultMaximum(5); + + for (int i = 0; i < 10; i++) { + Patient p = new Patient(); + p.addName().setFamily("PT" + i); + myPatientDao.create(p); + } + + SearchParameterMap map = new SearchParameterMap(); + map.setLoadSynchronous(true); + IBundleProvider values = myPatientDao.search(map); + assertEquals(5, values.size().intValue()); + assertEquals(5, values.getResources(0, 1000).size()); + } @Test public void testSearchWithIncludes() { @@ -2670,7 +2636,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } - @Test public void testSearchWithNoResults() { Device dev = new Device(); @@ -2887,7 +2852,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } - /** * https://chat.fhir.org/#narrow/stream/implementers/topic/Understanding.20_include */ @@ -2933,7 +2897,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(toUnqualifiedVersionlessIds(result), contains(id1)); result = myValueSetDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type").setQualifier(UriParamQualifierEnum.BELOW))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type").setQualifier(UriParamQualifierEnum.BELOW))); assertThat(toUnqualifiedVersionlessIds(result), contains(id1)); result = myValueSetDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/").setQualifier(UriParamQualifierEnum.BELOW))); @@ -2969,7 +2933,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(toUnqualifiedVersionlessIds(result), containsInAnyOrder(id2)); result = myValueSetDao - .search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type").setQualifier(UriParamQualifierEnum.ABOVE))); + .search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type").setQualifier(UriParamQualifierEnum.ABOVE))); assertThat(toUnqualifiedVersionlessIds(result), empty()); result = myValueSetDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org").setQualifier(UriParamQualifierEnum.ABOVE))); @@ -3004,6 +2968,81 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { assertThat(toUnqualifiedVersionlessIds(result), containsInAnyOrder()); } + /** + * See #744 + */ + @Test + public void testSearchWithVeryLongUrlLonger() { + myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); + + Patient p = new Patient(); + p.addName().setFamily("A1"); + myPatientDao.create(p); + + assertEquals(0, mySearchEntityDao.count()); + + SearchParameterMap map = new SearchParameterMap(); + StringOrListParam or = new StringOrListParam(); + or.addOr(new StringParam("A1")); + for (int i = 0; i < 50; i++) { + or.addOr(new StringParam(StringUtils.leftPad("", 200, (char) ('A' + i)))); + } + map.add(Patient.SP_NAME, or); + IBundleProvider results = myPatientDao.search(map); + assertEquals(1, results.getResources(0, 10).size()); + assertEquals(1, mySearchEntityDao.count()); + + map = new SearchParameterMap(); + or = new StringOrListParam(); + or.addOr(new StringParam("A1")); + or.addOr(new StringParam("A1")); + for (int i = 0; i < 50; i++) { + or.addOr(new StringParam(StringUtils.leftPad("", 200, (char) ('A' + i)))); + } + map.add(Patient.SP_NAME, or); + results = myPatientDao.search(map); + assertEquals(1, results.getResources(0, 10).size()); + // We expect a new one because we don't cache the search URL for very long search URLs + assertEquals(2, mySearchEntityDao.count()); + + } + + /** + * See #744 + */ + @Test + public void testSearchWithVeryLongUrlShorter() { + myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); + + Patient p = new Patient(); + p.addName().setFamily("A1"); + myPatientDao.create(p); + + assertEquals(0, mySearchEntityDao.count()); + + SearchParameterMap map = new SearchParameterMap(); + StringOrListParam or = new StringOrListParam(); + or.addOr(new StringParam("A1")); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'A'))); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'B'))); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'C'))); + map.add(Patient.SP_NAME, or); + IBundleProvider results = myPatientDao.search(map); + assertEquals(1, results.getResources(0, 10).size()); + assertEquals(1, mySearchEntityDao.count()); + + map = new SearchParameterMap(); + or = new StringOrListParam(); + or.addOr(new StringParam("A1")); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'A'))); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'B'))); + or.addOr(new StringParam(StringUtils.leftPad("", 200, 'C'))); + map.add(Patient.SP_NAME, or); + results = myPatientDao.search(map); + assertEquals(1, results.getResources(0, 10).size()); + assertEquals(1, mySearchEntityDao.count()); + + } private String toStringMultiline(List<?> theResults) { StringBuilder b = new StringBuilder(); diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6a4983a5373..8f9d12bc336 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -267,6 +267,10 @@ removed from the build. Thanks to Łukasz Dywicki for the pull request! </action> + <action type="add" issue="819"> + Support has been added to the JPA server for the :not modifier. Thanks + to Łukasz Dywicki for the pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From ca3e7fe38fe72cbcb3736d6e8cfda4842a2edec7 Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Mon, 26 Mar 2018 08:43:28 -0400 Subject: [PATCH 23/31] Credit for #877 --- pom.xml | 4 ++++ src/changes/changes.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index 83ebc17c541..894083c1e82 100644 --- a/pom.xml +++ b/pom.xml @@ -407,6 +407,10 @@ <id>splatch</id> <name>Łukasz Dywicki</name> </developer> + <developer> + <id>anthonys123</id> + <name>Anthony Sute</name> + </developer> </developers> <licenses> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8f9d12bc336..77cb09770e0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -271,6 +271,10 @@ Support has been added to the JPA server for the :not modifier. Thanks to Łukasz Dywicki for the pull request! </action> + <action type="add" issue="877"> + Suport for the :contains string search parameter modifier has been added to + the JPA server. Thanks to Anthony Sute for the pull request! + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From 55fc20b87e4ada1712f272d0fb9f9162040307ef Mon Sep 17 00:00:00 2001 From: James Agnew <jamesagnew@gmail.com> Date: Mon, 26 Mar 2018 10:04:49 -0400 Subject: [PATCH 24/31] Add tests for #877 --- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 44 ++++-- .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 41 +++--- .../r4/FhirResourceDaoR4SearchNoFtTest.java | 137 +++++++++++++----- 3 files changed, 146 insertions(+), 76 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 9f6491c6b86..4a9fb531754 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -17,9 +17,9 @@ import java.util.*; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -60,6 +60,9 @@ public class DaoConfig { * update setter javadoc if default changes */ private boolean myAllowExternalReferences = false; + /** + * update setter javadoc if default changes + */ private boolean myAllowContainsSearches = true; /** @@ -137,6 +140,7 @@ public class DaoConfig { myTreatReferencesAsLogical.add(theTreatReferencesAsLogical); } + /** * Specifies the highest number that a client is permitted to use in a * <code>Cache-Control: nostore, max-results=NNN</code> @@ -376,9 +380,9 @@ public class DaoConfig { * of higher importance than raw write performance * </p> * <p> - * Note that this setting also has an impact on sorting (i.e. using the - * <code>_sort</code> parameter on searches): If the server is configured - * to not index missing field. + * Note that this setting also has an impact on sorting (i.e. using the + * <code>_sort</code> parameter on searches): If the server is configured + * to not index missing field. * </p> */ public void setIndexMissingFields(IndexEnabledEnum theIndexMissingFields) { @@ -650,6 +654,26 @@ public class DaoConfig { return this; } + /** + * If enabled, the server will support the use of :contains searches, + * which are helpful but can have adverse effects on performance. + * + * Default is <code>true</code> + */ + public boolean isAllowContainsSearches() { + return myAllowContainsSearches; + } + + /** + * If enabled, the server will support the use of :contains searches, + * which are helpful but can have adverse effects on performance. + * + * Default is <code>true</code> + */ + public void setAllowContainsSearches(boolean theAllowContainsSearches) { + this.myAllowContainsSearches = theAllowContainsSearches; + } + /** * If set to <code>true</code> (default is <code>false</code>) the server will allow * resources to have references to external servers. For example if this server is @@ -1099,16 +1123,6 @@ public class DaoConfig { } - public boolean allowContainsSearches() { - - return myAllowContainsSearches; - } - - public void setAllowContainsSearches(boolean myAllowContainsSearches) { - - this.myAllowContainsSearches = myAllowContainsSearches; - } - public enum IndexEnabledEnum { ENABLED, DISABLED diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 293514954fa..7f9a004a4c9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,8 +28,6 @@ import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.jpa.util.BaseIterator; -import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; -import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; @@ -45,7 +43,9 @@ import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; +import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.UrlUtil; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; @@ -1091,10 +1091,10 @@ public class SearchBuilder implements ISearchBuilder { } else if (theParameter instanceof StringParam) { StringParam id = (StringParam) theParameter; rawSearchTerm = id.getValue(); - if ((id.isContains()) && - (!myCallingDao.getConfig().allowContainsSearches())) - { - throw new MethodNotAllowedException(":contains modifier is disabled on this server"); + if (id.isContains()) { + if (!myCallingDao.getConfig().isAllowContainsSearches()) { + throw new MethodNotAllowedException(":contains modifier is disabled on this server"); + } } } else if (theParameter instanceof IPrimitiveDatatype<?>) { IPrimitiveDatatype<?> id = (IPrimitiveDatatype<?>) theParameter; @@ -1109,18 +1109,11 @@ public class SearchBuilder implements ISearchBuilder { } String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm); - if (myCallingDao.getConfig().allowContainsSearches()) { - if (theParameter instanceof StringParam) { - if (((StringParam) theParameter).isContains()) { - likeExpression = createLeftAndRightMatchLikeExpression(likeExpression); - } else { - likeExpression = createLeftMatchLikeExpression(likeExpression); - } - } else { - likeExpression = createLeftMatchLikeExpression(likeExpression); - } - } - else { + if (theParameter instanceof StringParam && + ((StringParam) theParameter).isContains() && + myCallingDao.getConfig().isAllowContainsSearches()) { + likeExpression = createLeftAndRightMatchLikeExpression(likeExpression); + } else { likeExpression = createLeftMatchLikeExpression(likeExpression); } @@ -2020,14 +2013,14 @@ public class SearchBuilder implements ISearchBuilder { return lastUpdatedPredicates; } - private static String createLeftMatchLikeExpression(String likeExpression) { - return likeExpression.replace("%", "[%]") + "%"; - } - private static String createLeftAndRightMatchLikeExpression(String likeExpression) { return "%" + likeExpression.replace("%", "[%]") + "%"; } + private static String createLeftMatchLikeExpression(String likeExpression) { + return likeExpression.replace("%", "[%]") + "%"; + } + private static Predicate createResourceLinkPathPredicate(IDao theCallingDao, FhirContext theContext, String theParamName, From<?, ? extends ResourceLink> theFrom, String theResourceType) { RuntimeResourceDefinition resourceDef = theContext.getResourceDefinition(theResourceType); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java index 05185a32150..514a71d2b5a 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.util.TestUtil; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -54,6 +55,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { public void afterResetSearchSize() { myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis()); myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum()); + myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches()); } @Before @@ -1404,43 +1406,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } - /** - * See #819 - */ - @Test - public void testSearchTokenWithNotModifier() { - String male, female; - { - Patient patient = new Patient(); - patient.addIdentifier().setSystem("urn:system").setValue("001"); - patient.addName().setFamily("Tester").addGiven("Joe"); - patient.setGender(AdministrativeGender.MALE); - male = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); - } - { - Patient patient = new Patient(); - patient.addIdentifier().setSystem("urn:system").setValue("002"); - patient.addName().setFamily("Tester").addGiven("Jane"); - patient.setGender(AdministrativeGender.FEMALE); - female = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); - } - - List<String> patients; - SearchParameterMap params; - - params = new SearchParameterMap(); - params.add(Patient.SP_GENDER, new TokenParam(null, "male")); - params.setLoadSynchronous(true); - patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); - assertThat(patients, contains(male)); - - params = new SearchParameterMap(); - params.add(Patient.SP_GENDER, new TokenParam(null, "male").setModifier(TokenParamModifier.NOT)); - params.setLoadSynchronous(true); - patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); - assertThat(patients, contains(female)); - } - @Test public void testSearchNumberParam() { ImmunizationRecommendation e1 = new ImmunizationRecommendation(); @@ -2122,6 +2087,43 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } } + /** + * See #819 + */ + @Test + public void testSearchTokenWithNotModifier() { + String male, female; + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("001"); + patient.addName().setFamily("Tester").addGiven("Joe"); + patient.setGender(AdministrativeGender.MALE); + male = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); + } + { + Patient patient = new Patient(); + patient.addIdentifier().setSystem("urn:system").setValue("002"); + patient.addName().setFamily("Tester").addGiven("Jane"); + patient.setGender(AdministrativeGender.FEMALE); + female = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue(); + } + + List<String> patients; + SearchParameterMap params; + + params = new SearchParameterMap(); + params.add(Patient.SP_GENDER, new TokenParam(null, "male")); + params.setLoadSynchronous(true); + patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); + assertThat(patients, contains(male)); + + params = new SearchParameterMap(); + params.add(Patient.SP_GENDER, new TokenParam(null, "male").setModifier(TokenParamModifier.NOT)); + params.setLoadSynchronous(true); + patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params)); + assertThat(patients, contains(female)); + } + @Test public void testSearchTokenWrongParam() { Patient p1 = new Patient(); @@ -2257,6 +2259,67 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } + @Test + public void testSearchWithContains() { + + Patient pt1 = new Patient(); + pt1.addName().setFamily("ABCDEFGHIJK"); + String pt1id = myPatientDao.create(pt1).getId().toUnqualifiedVersionless().getValue(); + + Patient pt2 = new Patient(); + pt2.addName().setFamily("FGHIJK"); + String pt2id = myPatientDao.create(pt2).getId().toUnqualifiedVersionless().getValue(); + + Patient pt3 = new Patient(); + pt3.addName().setFamily("ZZZZZ"); + myPatientDao.create(pt3).getId().toUnqualifiedVersionless().getValue(); + + + List<String> ids; + SearchParameterMap map; + IBundleProvider results; + + // Contains = true + map = new SearchParameterMap(); + map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(true)); + map.setLoadSynchronous(true); + results = myPatientDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, containsInAnyOrder(pt1id, pt2id)); + + // Contains = false + map = new SearchParameterMap(); + map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(false)); + map.setLoadSynchronous(true); + results = myPatientDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, containsInAnyOrder(pt2id)); + + // No contains + map = new SearchParameterMap(); + map.add(Patient.SP_NAME, new StringParam("FGHIJK")); + map.setLoadSynchronous(true); + results = myPatientDao.search(map); + ids = toUnqualifiedVersionlessIdValues(results); + assertThat(ids, containsInAnyOrder(pt2id)); + } + + @Test + public void testSearchWithContainsDisabled() { + myDaoConfig.setAllowContainsSearches(false); + + SearchParameterMap map = new SearchParameterMap(); + map.setLoadSynchronous(true); + map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(true)); + + try { + myPatientDao.search(map); + fail(); + } catch (MethodNotAllowedException e) { + assertEquals(":contains modifier is disabled on this server", e.getMessage()); + } + } + @Test public void testSearchWithDate() { IIdType orgId = myOrganizationDao.create(new Organization(), mySrd).getId(); From fa28d505f3cab08f1117c38e927f087a79bf5d4e Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Tue, 27 Mar 2018 06:13:44 -0400 Subject: [PATCH 25/31] Credit for #871 --- pom.xml | 5 +++++ src/changes/changes.xml | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pom.xml b/pom.xml index 184566b162b..b2ca293e722 100644 --- a/pom.xml +++ b/pom.xml @@ -411,6 +411,11 @@ <id>anthonys123</id> <name>Anthony Sute</name> </developer> + <developer> + <id>johnpoth</id> + <name>John Poth</name> + <organization>Red Hat</organization> + </developer> </developers> <licenses> diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 77cb09770e0..c81de4b20f3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -41,6 +41,28 @@ </ul> ]]> </action> + <action tyoe="add" issue="871"> + A number of HAPI FHIR modules have been converted so that they now work + as OSGi modules. Unlike the previous OSGi module, which was a mega-JAR + with all of HAPI FHIR in it, this is simply the appropriate + OSGi manifest inside the existing JARs. Thanks to John Poth + for the Pull Request! + <![CDATA[ + <br/><br/> + Note that this does not cover all modules in the project. Current support includes: + <ul> + <li>HAPI-FHIR structures DSTU2, HL7ORGDSTU2, DSTU2.1, DSTU3, R4</li> + <li>HAPI-FHIR Resource validation DSTU2, HL7ORGDSTU2, DSTU2.1, DSTU3, R4</li> + <li>Apache Karaf features for all the above</li> + <li> Integration Tests</li> + </ul> + Remaining work includes: + <ul> + <li>HAPI-FHIR Server support</li> + <li> HAPI-FHIR narrative support. This might be tricky as Thymeleaf doesn't support OSGi.</li> + </ul> + ]]> + </action> <action type="fix"> Fix a crash in the JSON parser when parsing extensions on repeatable elements (e.g. Patient.address.line) where there is an extension on the From 3e3d6e26ffcb2a8d157a167e9eec5fa92528af60 Mon Sep 17 00:00:00 2001 From: jpoth <poth.john@gmail.com> Date: Tue, 27 Mar 2018 13:38:31 +0200 Subject: [PATCH 26/31] Fix OSGI tests --- .../integration/karaf/PaxExamOptions.java | 10 ++ .../karaf/client/FhirClientTest.java | 93 +++++-------------- 2 files changed, 31 insertions(+), 72 deletions(-) diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java index 5ddc2de9cf7..fd73eb00156 100644 --- a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java @@ -39,6 +39,16 @@ public enum PaxExamOptions { .versionAsInProject(), "wrap") ), + HAPI_FHIR_CLIENT( + features( + maven() + .groupId("ca.uhn.hapi.fhir.karaf") + .artifactId("hapi-fhir") + .type("xml") + .classifier("features") + .versionAsInProject(), + "hapi-fhir-client") + ), HAPI_FHIR_HL7ORG_DSTU2( features( maven() diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java index 1ae2468018f..55e3a507524 100644 --- a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java +++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java @@ -1,18 +1,12 @@ -package ca.uhn.fhir.tests.integration.karaf.r4; +package ca.uhn.fhir.tests.integration.karaf.client; import java.io.IOException; -import java.util.List; import ca.uhn.fhir.context.FhirContext; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport; -import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext; -import org.hl7.fhir.r4.model.Base; -import org.hl7.fhir.r4.model.BooleanType; -import org.hl7.fhir.r4.model.Observation; -import org.hl7.fhir.r4.model.Patient; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.StructureDefinition; -import org.hl7.fhir.r4.utils.FHIRPathEngine; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.PreferReturnEnum; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import org.hl7.fhir.dstu3.model.Patient; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -21,12 +15,10 @@ import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; -import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_R4; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_CLIENT; +import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; import static org.ops4j.pax.exam.CoreOptions.when; @@ -37,17 +29,19 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConf */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) -public class FhirInstanceValidatorR4Test { +@Ignore(value = "Relies on external service being up and running") +public class FhirClientTest { - private FhirContext ourCtx = FhirContext.forR4(); - private FHIRPathEngine ourEngine = new FHIRPathEngine(new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport())); - private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorR4Test.class); + private FhirContext fhirContext = FhirContext.forDstu3(); + private IGenericClient client = fhirContext.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu3"); + private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirClientTest.class); @Configuration public Option[] config() throws IOException { return options( KARAF.option(), - HAPI_FHIR_VALIDATION_R4.option(), + HAPI_FHIR_CLIENT.option(), + HAPI_FHIR_DSTU3.option(), mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(), WRAP.option(), when(false) @@ -57,58 +51,13 @@ public class FhirInstanceValidatorR4Test { } @Test - public void testAs() throws Exception { - Observation obs = new Observation(); - obs.setValue(new StringType("FOO")); - - List<Base> value = ourEngine.evaluate(obs, "Observation.value.as(String)"); - assertEquals(1, value.size()); - assertEquals("FOO", ((StringType)value.get(0)).getValue()); - } - - @Test - public void testExistsWithNoValue() throws FHIRException { + public void createPatient() throws Exception { Patient patient = new Patient(); - patient.setDeceased(new BooleanType()); - List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); - ourLog.info(eval.toString()); - assertFalse(((BooleanType)eval.get(0)).getValue()); - } - - @Test - public void testExistsWithValue() throws FHIRException { - Patient patient = new Patient(); - patient.setDeceased(new BooleanType(false)); - List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()"); - ourLog.info(eval.toString()); - assertTrue(((BooleanType)eval.get(0)).getValue()); - } - - @Test - public void testConcatenation() throws FHIRException { - String exp = "Patient.name.family & '.'"; - - Patient p = new Patient(); - p.addName().setFamily("TEST"); - String result = ourEngine.evaluateToString(p, exp); - assertEquals("TEST.", result); - } - - @Test - public void testConcatenationFunction() throws FHIRException { - String exp = "element.first().path.startsWith(%resource.type) and element.tail().all(path.startsWith(%resource.type&'.'))"; - - StructureDefinition sd = new StructureDefinition(); - StructureDefinition.StructureDefinitionDifferentialComponent diff = sd.getDifferential(); - - diff.addElement().setPath("Patient.name"); - - - Patient p = new Patient(); - p.addName().setFamily("TEST"); - List<Base> result = ourEngine.evaluate(null, p, diff, exp); - ourLog.info(result.toString()); -// assertEquals("TEST.", result); + patient.setId("PATIENTID"); + patient.getMeta().addProfile("http://BAR"); + patient.addName().addGiven("GIVEN"); + MethodOutcome execute = client.create().resource(patient).prefer(PreferReturnEnum.REPRESENTATION).execute(); + ourLog.info(execute.toString()); } } From d9c167455e88d4807e12b53d07394d3b488e3253 Mon Sep 17 00:00:00 2001 From: James Agnew <jamesagnew@gmail.com> Date: Tue, 27 Mar 2018 15:20:22 -0400 Subject: [PATCH 27/31] Make sure we correctly clean up resources --- .../DefaultProfileValidationSupport.java | 47 +- .../ctx/DefaultProfileValidationSupport.java | 43 +- .../DefaultProfileValidationSupport.java | 406 +++++++++--------- .../DefaultProfileValidationSupport.java | 51 ++- src/changes/changes.xml | 7 + 5 files changed, 295 insertions(+), 259 deletions(-) diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java index ebbfbc2a0dd..fa98150221c 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java @@ -2,6 +2,7 @@ package org.hl7.fhir.dstu2016may.hapi.validation; import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; import org.hl7.fhir.dstu2016may.model.*; import org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent; @@ -68,8 +69,8 @@ public class DefaultProfileValidationSupport implements IValidationSupport { Map<String, CodeSystem> codeSystems = myCodeSystems; Map<String, ValueSet> valueSets = myValueSets; if (codeSystems == null) { - codeSystems = new HashMap<String, CodeSystem>(); - valueSets = new HashMap<String, ValueSet>(); + codeSystems = new HashMap<>(); + valueSets = new HashMap<>(); loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu2016may/model/valueset/valuesets.xml"); loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu2016may/model/valueset/v2-tables.xml"); @@ -155,27 +156,33 @@ public class DefaultProfileValidationSupport implements IValidationSupport { private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) { ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath); - InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); - if (valuesetText != null) { - InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8); + InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); + InputStreamReader reader = null; + if (inputStream != null) { + try { + reader = new InputStreamReader(inputStream, Charsets.UTF_8); - Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); - for (BundleEntryComponent next : bundle.getEntry()) { - if (next.getResource() instanceof CodeSystem) { - CodeSystem nextValueSet = (CodeSystem) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theCodeSystems.put(system, nextValueSet); - } - } else if (next.getResource() instanceof ValueSet) { - ValueSet nextValueSet = (ValueSet) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theValueSets.put(system, nextValueSet); + Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); + for (BundleEntryComponent next : bundle.getEntry()) { + if (next.getResource() instanceof CodeSystem) { + CodeSystem nextValueSet = (CodeSystem) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theCodeSystems.put(system, nextValueSet); + } + } else if (next.getResource() instanceof ValueSet) { + ValueSet nextValueSet = (ValueSet) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theValueSets.put(system, nextValueSet); + } } } + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(inputStream); } } else { ourLog.warn("Unable to load resource: {}", theClasspath); diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java index 120e25e8567..9e9637ca980 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java @@ -2,6 +2,7 @@ package org.hl7.fhir.r4.hapi.ctx; import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -141,27 +142,33 @@ public class DefaultProfileValidationSupport implements IValidationSupport { private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) { ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath); - InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); - if (valuesetText != null) { - InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8); + InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); + InputStreamReader reader = null; + if (inputStream != null) { + try { + reader = new InputStreamReader(inputStream, Charsets.UTF_8); - Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); - for (BundleEntryComponent next : bundle.getEntry()) { - if (next.getResource() instanceof CodeSystem) { - CodeSystem nextValueSet = (CodeSystem) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theCodeSystems.put(system, nextValueSet); - } - } else if (next.getResource() instanceof ValueSet) { - ValueSet nextValueSet = (ValueSet) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theValueSets.put(system, nextValueSet); + Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); + for (BundleEntryComponent next : bundle.getEntry()) { + if (next.getResource() instanceof CodeSystem) { + CodeSystem nextValueSet = (CodeSystem) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theCodeSystems.put(system, nextValueSet); + } + } else if (next.getResource() instanceof ValueSet) { + ValueSet nextValueSet = (ValueSet) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theValueSets.put(system, nextValueSet); + } } } + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(inputStream); } } else { ourLog.warn("Unable to load resource: {}", theClasspath); diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java index 70ff35e57b1..8bcc81dde0e 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java @@ -2,7 +2,7 @@ package org.hl7.fhir.dstu3.hapi.validation; import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; -import org.apache.commons.lang.WordUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport; @@ -24,243 +24,249 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; public class DefaultProfileValidationSupport implements IValidationSupport { - private static final String URL_PREFIX_VALUE_SET = "http://hl7.org/fhir/ValueSet/"; - private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/"; - private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/"; + private static final String URL_PREFIX_VALUE_SET = "http://hl7.org/fhir/ValueSet/"; + private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/"; + private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/"; - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class); - private Map<String, CodeSystem> myCodeSystems; - private Map<String, StructureDefinition> myStructureDefinitions; - private Map<String, ValueSet> myValueSets; + private Map<String, CodeSystem> myCodeSystems; + private Map<String, StructureDefinition> myStructureDefinitions; + private Map<String, ValueSet> myValueSets; - @Override - public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) { - ValueSetExpansionComponent retVal = new ValueSetExpansionComponent(); + @Override + public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) { + ValueSetExpansionComponent retVal = new ValueSetExpansionComponent(); - Set<String> wantCodes = new HashSet<String>(); - for (ConceptReferenceComponent next : theInclude.getConcept()) { - wantCodes.add(next.getCode()); - } + Set<String> wantCodes = new HashSet<>(); + for (ConceptReferenceComponent next : theInclude.getConcept()) { + wantCodes.add(next.getCode()); + } - CodeSystem system = fetchCodeSystem(theContext, theInclude.getSystem()); - for (ConceptDefinitionComponent next : system.getConcept()) { - if (wantCodes.isEmpty() || wantCodes.contains(next.getCode())) { - retVal.addContains().setSystem(theInclude.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); - } - } + CodeSystem system = fetchCodeSystem(theContext, theInclude.getSystem()); + for (ConceptDefinitionComponent next : system.getConcept()) { + if (wantCodes.isEmpty() || wantCodes.contains(next.getCode())) { + retVal.addContains().setSystem(theInclude.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); + } + } - return retVal; - } + return retVal; + } - @Override - public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) { - ArrayList<IBaseResource> retVal = new ArrayList<>(); - retVal.addAll(myCodeSystems.values()); - retVal.addAll(myStructureDefinitions.values()); - retVal.addAll(myValueSets.values()); - return retVal; - } + @Override + public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) { + ArrayList<IBaseResource> retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } - @Override - public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) { - return new ArrayList<StructureDefinition>(provideStructureDefinitionMap(theContext).values()); - } + @Override + public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) { + return new ArrayList<StructureDefinition>(provideStructureDefinitionMap(theContext).values()); + } - @Override - public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { - return (CodeSystem) fetchCodeSystemOrValueSet(theContext, theSystem, true); - } + @Override + public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { + return (CodeSystem) fetchCodeSystemOrValueSet(theContext, theSystem, true); + } - private DomainResource fetchCodeSystemOrValueSet(FhirContext theContext, String theSystem, boolean codeSystem) { - synchronized (this) { - Map<String, CodeSystem> codeSystems = myCodeSystems; - Map<String, ValueSet> valueSets = myValueSets; - if (codeSystems == null || valueSets == null) { - codeSystems = new HashMap<String, CodeSystem>(); - valueSets = new HashMap<String, ValueSet>(); + private DomainResource fetchCodeSystemOrValueSet(FhirContext theContext, String theSystem, boolean codeSystem) { + synchronized (this) { + Map<String, CodeSystem> codeSystems = myCodeSystems; + Map<String, ValueSet> valueSets = myValueSets; + if (codeSystems == null || valueSets == null) { + codeSystems = new HashMap<String, CodeSystem>(); + valueSets = new HashMap<String, ValueSet>(); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/valuesets.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/valuesets.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml"); - myCodeSystems = codeSystems; - myValueSets = valueSets; - } + myCodeSystems = codeSystems; + myValueSets = valueSets; + } - if (codeSystem) { - return codeSystems.get(theSystem); - } else { - return valueSets.get(theSystem); - } - } - } + if (codeSystem) { + return codeSystems.get(theSystem); + } else { + return valueSets.get(theSystem); + } + } + } - @SuppressWarnings("unchecked") - @Override - public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) { - Validate.notBlank(theUri, "theUri must not be null or blank"); + @SuppressWarnings("unchecked") + @Override + public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) { + Validate.notBlank(theUri, "theUri must not be null or blank"); - if (theClass.equals(StructureDefinition.class)) { - return (T) fetchStructureDefinition(theContext, theUri); - } + if (theClass.equals(StructureDefinition.class)) { + return (T) fetchStructureDefinition(theContext, theUri); + } - if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) { - return (T) fetchValueSet(theContext, theUri); - } + if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) { + return (T) fetchValueSet(theContext, theUri); + } - return null; - } + return null; + } - @Override - public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) { - String url = theUrl; - if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) { - // no change - } else if (url.indexOf('/') == -1) { - url = URL_PREFIX_STRUCTURE_DEFINITION + url; - } else if (StringUtils.countMatches(url, '/') == 1) { - url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url; - } - Map<String, StructureDefinition> map = provideStructureDefinitionMap(theContext); - StructureDefinition retVal = map.get(url); + @Override + public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) { + String url = theUrl; + if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) { + // no change + } else if (url.indexOf('/') == -1) { + url = URL_PREFIX_STRUCTURE_DEFINITION + url; + } else if (StringUtils.countMatches(url, '/') == 1) { + url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url; + } + Map<String, StructureDefinition> map = provideStructureDefinitionMap(theContext); + StructureDefinition retVal = map.get(url); - if (retVal == null && url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) { - String tryUrl = URL_PREFIX_STRUCTURE_DEFINITION + StringUtils.capitalize(url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length())); - retVal = map.get(tryUrl); - } + if (retVal == null && url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) { + String tryUrl = URL_PREFIX_STRUCTURE_DEFINITION + StringUtils.capitalize(url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length())); + retVal = map.get(tryUrl); + } - return retVal; - } + return retVal; + } - ValueSet fetchValueSet(FhirContext theContext, String theSystem) { - return (ValueSet) fetchCodeSystemOrValueSet(theContext, theSystem, false); - } + ValueSet fetchValueSet(FhirContext theContext, String theSystem) { + return (ValueSet) fetchCodeSystemOrValueSet(theContext, theSystem, false); + } - public void flush() { - myCodeSystems = null; - myStructureDefinitions = null; - } + public void flush() { + myCodeSystems = null; + myStructureDefinitions = null; + } - @Override - public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) { - CodeSystem cs = fetchCodeSystem(theContext, theSystem); - return cs != null && cs.getContent() != CodeSystemContentMode.NOTPRESENT; - } + @Override + public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) { + CodeSystem cs = fetchCodeSystem(theContext, theSystem); + return cs != null && cs.getContent() != CodeSystemContentMode.NOTPRESENT; + } - private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) { - ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath); - InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); - if (valuesetText != null) { - InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8); + private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) { + ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath); + InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); + InputStreamReader reader = null; + if (inputStream != null) { + try { + reader = new InputStreamReader(inputStream, Charsets.UTF_8); - Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); - for (BundleEntryComponent next : bundle.getEntry()) { - if (next.getResource() instanceof CodeSystem) { - CodeSystem nextValueSet = (CodeSystem) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theCodeSystems.put(system, nextValueSet); - } - } else if (next.getResource() instanceof ValueSet) { - ValueSet nextValueSet = (ValueSet) next.getResource(); - nextValueSet.getText().setDivAsString(""); - String system = nextValueSet.getUrl(); - if (isNotBlank(system)) { - theValueSets.put(system, nextValueSet); - } - } - } - } else { - ourLog.warn("Unable to load resource: {}", theClasspath); - } - } + Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); + for (BundleEntryComponent next : bundle.getEntry()) { + if (next.getResource() instanceof CodeSystem) { + CodeSystem nextValueSet = (CodeSystem) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theCodeSystems.put(system, nextValueSet); + } + } else if (next.getResource() instanceof ValueSet) { + ValueSet nextValueSet = (ValueSet) next.getResource(); + nextValueSet.getText().setDivAsString(""); + String system = nextValueSet.getUrl(); + if (isNotBlank(system)) { + theValueSets.put(system, nextValueSet); + } + } + } + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(inputStream); + } + } else { + ourLog.warn("Unable to load resource: {}", theClasspath); + } + } - private void loadStructureDefinitions(FhirContext theContext, Map<String, StructureDefinition> theCodeSystems, String theClasspath) { - ourLog.info("Loading structure definitions from classpath: {}", theClasspath); - InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); - if (valuesetText != null) { - InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8); + private void loadStructureDefinitions(FhirContext theContext, Map<String, StructureDefinition> theCodeSystems, String theClasspath) { + ourLog.info("Loading structure definitions from classpath: {}", theClasspath); + InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath); + if (valuesetText != null) { + InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8); - Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); - for (BundleEntryComponent next : bundle.getEntry()) { - if (next.getResource() instanceof StructureDefinition) { - StructureDefinition nextSd = (StructureDefinition) next.getResource(); - nextSd.getText().setDivAsString(""); - String system = nextSd.getUrl(); - if (isNotBlank(system)) { - theCodeSystems.put(system, nextSd); - } - } - } - } else { - ourLog.warn("Unable to load resource: {}", theClasspath); - } - } + Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader); + for (BundleEntryComponent next : bundle.getEntry()) { + if (next.getResource() instanceof StructureDefinition) { + StructureDefinition nextSd = (StructureDefinition) next.getResource(); + nextSd.getText().setDivAsString(""); + String system = nextSd.getUrl(); + if (isNotBlank(system)) { + theCodeSystems.put(system, nextSd); + } + } + } + } else { + ourLog.warn("Unable to load resource: {}", theClasspath); + } + } - private Map<String, StructureDefinition> provideStructureDefinitionMap(FhirContext theContext) { - Map<String, StructureDefinition> structureDefinitions = myStructureDefinitions; - if (structureDefinitions == null) { - structureDefinitions = new HashMap<String, StructureDefinition>(); + private Map<String, StructureDefinition> provideStructureDefinitionMap(FhirContext theContext) { + Map<String, StructureDefinition> structureDefinitions = myStructureDefinitions; + if (structureDefinitions == null) { + structureDefinitions = new HashMap<String, StructureDefinition>(); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-types.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-others.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-types.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-others.xml"); - myStructureDefinitions = structureDefinitions; - } - return structureDefinitions; - } + myStructureDefinitions = structureDefinitions; + } + return structureDefinitions; + } - private CodeValidationResult testIfConceptIsInList(String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) { - String code = theCode; - if (theCaseSensitive == false) { - code = code.toUpperCase(); - } + private CodeValidationResult testIfConceptIsInList(String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) { + String code = theCode; + if (theCaseSensitive == false) { + code = code.toUpperCase(); + } - return testIfConceptIsInListInner(conceptList, theCaseSensitive, code); - } + return testIfConceptIsInListInner(conceptList, theCaseSensitive, code); + } - private CodeValidationResult testIfConceptIsInListInner(List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) { - CodeValidationResult retVal = null; - for (ConceptDefinitionComponent next : conceptList) { - String nextCandidate = next.getCode(); - if (theCaseSensitive == false) { - nextCandidate = nextCandidate.toUpperCase(); - } - if (nextCandidate.equals(code)) { - retVal = new CodeValidationResult(next); - break; - } + private CodeValidationResult testIfConceptIsInListInner(List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) { + CodeValidationResult retVal = null; + for (ConceptDefinitionComponent next : conceptList) { + String nextCandidate = next.getCode(); + if (theCaseSensitive == false) { + nextCandidate = nextCandidate.toUpperCase(); + } + if (nextCandidate.equals(code)) { + retVal = new CodeValidationResult(next); + break; + } - // recurse - retVal = testIfConceptIsInList(code, next.getConcept(), theCaseSensitive); - if (retVal != null) { - break; - } - } + // recurse + retVal = testIfConceptIsInList(code, next.getConcept(), theCaseSensitive); + if (retVal != null) { + break; + } + } - return retVal; - } + return retVal; + } - @Override - public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { - CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); - if (cs != null) { - boolean caseSensitive = true; - if (cs.hasCaseSensitive()) { - caseSensitive = cs.getCaseSensitive(); - } + @Override + public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { + CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); + if (cs != null) { + boolean caseSensitive = true; + if (cs.hasCaseSensitive()) { + caseSensitive = cs.getCaseSensitive(); + } - CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); + CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); - if (retVal != null) { - return retVal; - } - } + if (retVal != null) { + return retVal; + } + } - return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); - } + return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); + } } diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/DefaultProfileValidationSupport.java index 24dcf7945a1..0523b22963c 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/DefaultProfileValidationSupport.java @@ -2,6 +2,7 @@ package org.hl7.fhir.instance.hapi.validation; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.Bundle; import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent; import org.hl7.fhir.instance.model.CodeType; @@ -44,9 +45,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (valueSets == null) { valueSets = new HashMap<String, ValueSet>(); - loadCodeSystems(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/valuesets.xml"); - loadCodeSystems(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/v2-tables.xml"); - loadCodeSystems(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"); + loadValueSets(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/valuesets.xml"); + loadValueSets(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/v2-tables.xml"); + loadValueSets(theContext, valueSets, "/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"); myCodeSystems = valueSets; } @@ -108,26 +109,34 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return false; } - private void loadCodeSystems(FhirContext theContext, Map<String, ValueSet> codeSystems, String file) { - InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(file); - if (valuesetText != null) { - InputStreamReader reader; - try { - reader = new InputStreamReader(valuesetText, "UTF-8"); - } catch (UnsupportedEncodingException e) { - // Shouldn't happen! - throw new InternalErrorException("UTF-8 encoding not supported on this platform", e); - } + private void loadValueSets(FhirContext theContext, Map<String, ValueSet> theValueSets, String theFile) { + InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theFile); + try { + if (valuesetText != null) { + InputStreamReader reader = null; + try { + reader = new InputStreamReader(valuesetText, "UTF-8"); - FhirContext ctx = FhirInstanceValidator.getHl7OrgDstu2Ctx(theContext); - Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, reader); - for (BundleEntryComponent next : bundle.getEntry()) { - ValueSet nextValueSet = (ValueSet) next.getResource(); - String system = nextValueSet.getCodeSystem().getSystem(); - if (isNotBlank(system)) { - codeSystems.put(system, nextValueSet); + FhirContext ctx = FhirInstanceValidator.getHl7OrgDstu2Ctx(theContext); + Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, reader); + for (BundleEntryComponent next : bundle.getEntry()) { + ValueSet nextValueSet = (ValueSet) next.getResource(); + String system = nextValueSet.getCodeSystem().getSystem(); + if (isNotBlank(system)) { + theValueSets.put(system, nextValueSet); + } + } + + } catch (UnsupportedEncodingException e) { + // Shouldn't happen! + throw new InternalErrorException("UTF-8 encoding not supported on this platform", e); + } finally { + IOUtils.closeQuietly(reader); } + } + } finally { + IOUtils.closeQuietly(valuesetText); } } @@ -136,7 +145,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { ValueSet vs = fetchCodeSystem(theContext, theCodeSystem); if (vs != null) { for (ValueSet.ConceptDefinitionComponent nextConcept : vs.getCodeSystem().getConcept()) { - if (nextConcept.getCode().equals(theCode)){ + if (nextConcept.getCode().equals(theCode)) { ValueSet.ConceptDefinitionComponent component = new ValueSet.ConceptDefinitionComponent(new CodeType(theCode)); return new CodeValidationResult(component); } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c81de4b20f3..deb332e5c0a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -297,6 +297,13 @@ Suport for the :contains string search parameter modifier has been added to the JPA server. Thanks to Anthony Sute for the pull request! </action> + <action type="fix"> + All instances of DefaultProfileValidationSupport (i.e. one for + each version of FHIR) have been fixed so that they explicitly + close any InputStreams they open in order to read the built-in + profile resources. Leaving these open caused resource starvation + in some cases under heavy load. + </action> </release> <release version="3.2.0" date="2018-01-13"> <action type="add"> From bcfd5370a2e7f45ff104066323e0ce8ff7a08490 Mon Sep 17 00:00:00 2001 From: patrick-werner <pa.f.werner@gmail.com> Date: Wed, 28 Mar 2018 12:02:40 +0200 Subject: [PATCH 28/31] moved OWASP check to a profile --- pom.xml | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index b2ca293e722..b28ceed042e 100644 --- a/pom.xml +++ b/pom.xml @@ -1821,21 +1821,6 @@ </execution> </executions> </plugin> - <plugin> - <groupId>org.owasp</groupId> - <artifactId>dependency-check-maven</artifactId> - <version>3.1.1</version> - <configuration> - <failBuildOnCVSS>8</failBuildOnCVSS> - </configuration> - <executions> - <execution> - <goals> - <goal>check</goal> - </goals> - </execution> - </executions> - </plugin> </plugins> </build> @@ -2096,6 +2081,28 @@ </plugins> </build> </profile> + <profile> + <id>OWASP</id> + <build> + <plugins> + <plugin> + <groupId>org.owasp</groupId> + <artifactId>dependency-check-maven</artifactId> + <version>3.1.1</version> + <configuration> + <failBuildOnCVSS>8</failBuildOnCVSS> + </configuration> + <executions> + <execution> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> </profiles> </project> From 4ba56d5021121af7a30ee7271b54ad3e4804c77f Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Wed, 28 Mar 2018 06:15:28 -0400 Subject: [PATCH 29/31] Reorganize the OSGI projects a bit --- .../hapi-fhir-jpaserver-cds-example/pom.xml | 14 +- .../ca/uhn/fhir/jpa/dao/ISearchBuilder.java | 31 ++-- .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 10 ++ .../jpa/search/SearchCoordinatorSvcImpl.java | 14 +- .../jpa/util/StatelessSessionFactoryBean.java | 157 ++++++++++++++++++ .../uhn/fhirtest/config/TestDstu2Config.java | 1 + .../uhn/fhirtest/config/TestDstu3Config.java | 1 + .../ca/uhn/fhirtest/config/TestR4Config.java | 1 + .../hapi-fhir-karaf-features}/pom.xml | 2 +- .../src/main/resources/features.xml | 0 .../pom.xml | 2 +- .../integration/karaf/PaxExamOptions.java | 0 .../karaf/client/FhirClientTest.java | 0 .../Dstu2ResourceValidatorDstu2Test.java | 0 .../karaf/dstu2/PatientProfileDstu2.java | 0 .../karaf/dstu21/JsonParserDstu2_1Test.java | 0 .../PatientWithExtendedContactDstu3.java | 0 .../karaf/dstu21/XmlParserDstu2_1Test.java | 0 .../FhirInstanceValidatorTest.java | 0 .../JsonParserHl7OrgDstu2Test.java | 0 .../MyObservationWithExtensions.java | 0 .../dstu2hl7org/MyOrganizationDstu2.java | 0 .../karaf/dstu2hl7org/MyPatientHl7Org.java | 0 ...ntWithOneDeclaredEnumerationExtension.java | 0 .../dstu2hl7org/ResourceWithExtensionsA.java | 0 .../dstu2hl7org/XmlParserHl7OrgDstu2Test.java | 0 .../karaf/dstu3/CustomDiagnosticReport.java | 0 .../karaf/dstu3/CustomObservation.java | 0 .../karaf/dstu3/CustomPatientDstu3.java | 0 .../karaf/dstu3/Dstu3JsonParserTest.java | 0 .../karaf/dstu3/Dstu3XmlParserTest.java | 0 .../karaf/dstu3/FooMessageHeader.java | 0 .../FooMessageHeaderWithExplicitField.java | 0 .../MyPatientWithCustomUrlExtension.java | 0 ...hOneDeclaredEnumerationExtensionDstu3.java | 0 .../karaf/dstu3/PatientProfileDstu3.java | 0 .../PatientWithCustomCompositeExtension.java | 0 .../ResourceValidatorDstu3FeatureTest.java | 0 .../karaf/r4/FhirInstanceValidatorR4Test.java | 0 .../karaf/r4/R4JsonParserTest.java | 0 .../integration/karaf/r4/R4XmlParserTest.java | 0 .../src/test/resources/bundle-example.json | 0 .../src/test/resources/bundle_orion.xml | 0 .../test/resources/bundle_ref_by_uuid_544.xml | 0 .../bundle_with_contained_with_no_id.xml | 0 .../bundle_with_invalid_contained_ref.xml | 0 .../test/resources/bundle_with_woven_obs.xml | 0 .../src/test/resources/conformance.json.gz | Bin .../resources/dstu3/myconsent-resource.json | 0 .../example-patient-general-hl7orgdstu2.json | 0 .../example-patient-general-hl7orgdstu2.xml | 0 .../src/test/resources/extension-on-line.txt | 0 .../test/resources/patient-example-dicom.json | 0 .../src/test/resources/q_jon.json | 0 .../src/test/resources/qr_jon.xml | 0 .../resources/r4/bundle-with-no-type.json | 0 ...iagnosticreport-example-gingival-mass.json | 0 .../src/test/resources/sample-document.xml | 0 .../src/test/resources/testscript-search.json | 0 pom.xml | 86 ++++++---- 60 files changed, 255 insertions(+), 64 deletions(-) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java rename {hapi-fhir-karaf-features => osgi/hapi-fhir-karaf-features}/pom.xml (99%) rename {hapi-fhir-karaf-features => osgi/hapi-fhir-karaf-features}/src/main/resources/features.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/pom.xml (98%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle-example.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle_orion.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle_ref_by_uuid_544.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle_with_contained_with_no_id.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle_with_invalid_contained_ref.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/bundle_with_woven_obs.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/conformance.json.gz (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/dstu3/myconsent-resource.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/example-patient-general-hl7orgdstu2.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/example-patient-general-hl7orgdstu2.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/extension-on-line.txt (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/patient-example-dicom.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/q_jon.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/qr_jon.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/r4/bundle-with-no-type.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/r4/diagnosticreport-example-gingival-mass.json (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/sample-document.xml (100%) rename {hapi-fhir-karaf-integration-tests => osgi/hapi-fhir-karaf-integration-tests}/src/test/resources/testscript-search.json (100%) diff --git a/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml b/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml index 4d600fe1ba8..ff31307337e 100644 --- a/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml +++ b/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml @@ -224,13 +224,17 @@ </pluginManagement> <plugins> - <!-- Tell Maven which Java source version you want to use --> + + <!-- + The CQF-Ruler project has some OWASP dependency security failures which we don't want + to cause the whole build to fail. TODO: investigate these + --> <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> + <groupId>org.owasp</groupId> + <artifactId>dependency-check-maven</artifactId> <configuration> - <source>1.7</source> - <target>1.7</target> + <failBuildOnCVSS>99</failBuildOnCVSS> + <failOnError>false</failOnError> </configuration> </plugin> diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java index b9a5dfa18cb..9299fe2428e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,29 +20,32 @@ package ca.uhn.fhir.jpa.dao; * #L% */ +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Include; +import ca.uhn.fhir.rest.param.DateRangeParam; +import org.hl7.fhir.instance.model.api.IBaseResource; + +import javax.persistence.EntityManager; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; -import javax.persistence.EntityManager; - -import org.hl7.fhir.instance.model.api.IBaseResource; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.model.api.Include; -import ca.uhn.fhir.rest.param.DateRangeParam; - public interface ISearchBuilder { Iterator<Long> createQuery(SearchParameterMap theParams, String theSearchUuid); - void setType(Class<? extends IBaseResource> theResourceType, String theResourceName); - void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResource> theResourceListToPopulate, Set<Long> theRevIncludedPids, boolean theForHistoryOperation, EntityManager theEntityManager, - FhirContext theContext, IDao theDao); + FhirContext theContext, IDao theDao); Set<Long> loadReverseIncludes(IDao theCallingDao, FhirContext theContext, EntityManager theEntityManager, Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, - DateRangeParam theLastUpdated); + DateRangeParam theLastUpdated); + + /** + * How many results may be fetched at once + */ + void setFetchSize(int theFetchSize); + + void setType(Class<? extends IBaseResource> theResourceType, String theResourceName); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 7f9a004a4c9..fc35027209a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -59,6 +59,9 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.tuple.Pair; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; +import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.PersistenceContext; +import org.hibernate.internal.SessionImpl; import org.hibernate.query.Query; import org.hl7.fhir.dstu3.model.BaseResource; import org.hl7.fhir.instance.model.api.IAnyResource; @@ -104,6 +107,7 @@ public class SearchBuilder implements ISearchBuilder { private ISearchParamRegistry mySearchParamRegistry; private String mySearchUuid; private IHapiTerminologySvc myTerminologySvc; + private int myFetchSize; /** * Constructor @@ -1926,6 +1930,11 @@ public class SearchBuilder implements ISearchBuilder { } } + @Override + public void setFetchSize(int theFetchSize) { + myFetchSize = theFetchSize; + } + @Override public void setType(Class<? extends IBaseResource> theResourceType, String theResourceName) { myResourceType = theResourceType; @@ -2181,6 +2190,7 @@ public class SearchBuilder implements ISearchBuilder { final TypedQuery<Long> query = createQuery(mySort, maximumResults); Query<Long> hibernateQuery = (Query<Long>) query; + hibernateQuery.setFetchSize(myFetchSize); ScrollableResults scroll = hibernateQuery.scroll(ScrollMode.FORWARD_ONLY); myResultsIterator = new ScrollableResultsIterator(scroll); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java index 8ffef936f9f..c7a959763e6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java @@ -206,6 +206,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { Class<? extends IBaseResource> resourceTypeClass = myContext.getResourceDefinition(theResourceType).getImplementingClass(); final ISearchBuilder sb = theCallingDao.newSearchBuilder(); sb.setType(resourceTypeClass, theResourceType); + sb.setFetchSize(mySyncSize); final Integer loadSynchronousUpTo; if (theCacheControlDirective != null && theCacheControlDirective.isNoStore()) { @@ -233,7 +234,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { public SimpleBundleProvider doInTransaction(TransactionStatus theStatus) { // Load the results synchronously - final List<Long> pids = new ArrayList<Long>(); + final List<Long> pids = new ArrayList<>(); Iterator<Long> resultIter = sb.createQuery(theParams, searchUuid); while (resultIter.hasNext()) { @@ -458,8 +459,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { private final SearchParameterMap myParams; private final String myResourceType; private final Search mySearch; - private final ArrayList<Long> mySyncedPids = new ArrayList<Long>(); - private final ArrayList<Long> myUnsyncedPids = new ArrayList<Long>(); + private final ArrayList<Long> mySyncedPids = new ArrayList<>(); + private final ArrayList<Long> myUnsyncedPids = new ArrayList<>(); private boolean myAbortRequested; private int myCountSaved = 0; private String mySearchUuid; @@ -503,7 +504,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { * It is called automatically by the thread pool. */ @Override - public Void call() throws Exception { + public Void call() { StopWatch sw = new StopWatch(); try { @@ -631,10 +632,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { boolean keepWaiting; do { synchronized (mySyncedPids) { - keepWaiting = false; - if (mySyncedPids.size() < theToIndex && mySearch.getStatus() == SearchStatusEnum.LOADING) { - keepWaiting = true; - } + keepWaiting = mySyncedPids.size() < theToIndex && mySearch.getStatus() == SearchStatusEnum.LOADING; } if (keepWaiting) { ourLog.info("Waiting, as we only have {} results", mySyncedPids.size()); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java new file mode 100644 index 00000000000..6dcf062e73b --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java @@ -0,0 +1,157 @@ +package ca.uhn.fhir.jpa.util; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.hibernate.engine.spi.SessionImplementor; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.orm.jpa.EntityManagerFactoryUtils; +import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; +import org.springframework.transaction.support.ResourceHolderSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationAdapter; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import java.sql.Connection; + +import static org.springframework.orm.jpa.EntityManagerFactoryUtils.ENTITY_MANAGER_SYNCHRONIZATION_ORDER; +import static org.springframework.util.ReflectionUtils.invokeMethod; + +/** + * Hibernate's {@link StatelessSession} factory which will be bound to the + * current transaction. This factory returns a Proxy which delegates method + * calls to the underlying {@link StatelessSession} bound to transaction. At the + * end of the transaction the session is automatically closed. This class + * borrows idea's from {@link DataSourceUtils}, + * {@link EntityManagerFactoryUtils}, {@link ResourceHolderSynchronization} and + * {@link LocalEntityManagerFactoryBean}. + */ +public class StatelessSessionFactoryBean implements FactoryBean<StatelessSession> { + + private SessionFactory sessionFactory; + + @Autowired + public StatelessSessionFactoryBean(SessionFactory theSessionFactory) { + this.sessionFactory = theSessionFactory; + } + + @Override + public StatelessSession getObject() throws Exception { + StatelessSessionInterceptor statelessSessionInterceptor = new StatelessSessionInterceptor( + sessionFactory); + return ProxyFactory.getProxy(StatelessSession.class, statelessSessionInterceptor); + } + + @Override + public Class<?> getObjectType() { + return StatelessSession.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + /** + * Use this to override the {@link SessionFactory} obtained from the + * {@link EntityManagerFactory}. Please note that the connection will still + * be used from the {@link EntityManager}. + */ + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + private static class StatelessSessionInterceptor implements MethodInterceptor { + + private final SessionFactory sessionFactory; + + public StatelessSessionInterceptor( + SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + private void bindWithTransaction(StatelessSession statelessSession) { + TransactionSynchronizationManager + .registerSynchronization(new StatelessSessionSynchronization(sessionFactory, + statelessSession)); + TransactionSynchronizationManager.bindResource(sessionFactory, statelessSession); + } + + private StatelessSession getCurrentSession() { + if (!TransactionSynchronizationManager.isActualTransactionActive()) { + throw new IllegalStateException( + "There should be an active transaction for the current thread."); + } + StatelessSession statelessSession = (StatelessSession) TransactionSynchronizationManager + .getResource(sessionFactory); + if (statelessSession == null) { + statelessSession = openNewStatelessSession(); + bindWithTransaction(statelessSession); + } + return statelessSession; + } + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + StatelessSession statelessSession = getCurrentSession(); + return invokeMethod(invocation.getMethod(), statelessSession, invocation.getArguments()); + } + + /** + * It is important we obtain the physical (real) connection otherwise it + * will be double proxied and there will be problems releasing the + * connection. + */ + private Connection obtainPhysicalConnection() { + EntityManager entityManager = EntityManagerFactoryUtils + .getTransactionalEntityManager(sessionFactory); + SessionImplementor sessionImplementor = (SessionImplementor) entityManager + .getDelegate(); +// return sessionImplementor.getTransactionCoordinator().getJdbcCoordinator() +// .getLogicalConnection().getConnection(); + return null; + } + + private StatelessSession openNewStatelessSession() { + Connection connection = obtainPhysicalConnection(); + return sessionFactory.openStatelessSession(connection); + } + } + + private static class StatelessSessionSynchronization extends TransactionSynchronizationAdapter { + + private final SessionFactory sessionFactory; + private final StatelessSession statelessSession; + + public StatelessSessionSynchronization(SessionFactory sessionFactory, + StatelessSession statelessSession) { + this.sessionFactory = sessionFactory; + this.statelessSession = statelessSession; + } + + @Override + public void beforeCommit(boolean readOnly) { + if (!readOnly) { +// ((TransactionContext) statelessSession).flu + } + } + + @Override + public void beforeCompletion() { + TransactionSynchronizationManager.unbindResource(sessionFactory); + statelessSession.close(); + } + + @Override + public int getOrder() { + return ENTITY_MANAGER_SYNCHRONIZATION_ORDER - 100; + } + + } + +} diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java index 0ba5259d270..d84ad94ec41 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java @@ -68,6 +68,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 { retVal.getTreatBaseUrlsAsLocal().add("https://fhirtest.uhn.ca/baseDstu2"); retVal.setCountSearchResultsUpTo(TestR4Config.COUNT_SEARCH_RESULTS_UP_TO); retVal.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED); + retVal.setFetchSizeDefaultMaximum(10000); return retVal; } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java index 845433ba7bd..7c3f868a25b 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java @@ -57,6 +57,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 { retVal.getTreatBaseUrlsAsLocal().add("https://fhirtest.uhn.ca/baseDstu3"); retVal.setCountSearchResultsUpTo(TestR4Config.COUNT_SEARCH_RESULTS_UP_TO); retVal.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED); + retVal.setFetchSizeDefaultMaximum(10000); return retVal; } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestR4Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestR4Config.java index 6a96849ea0a..1953d6d945f 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestR4Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestR4Config.java @@ -58,6 +58,7 @@ public class TestR4Config extends BaseJavaConfigR4 { retVal.getTreatBaseUrlsAsLocal().add("https://fhirtest.uhn.ca/baseR4"); retVal.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED); retVal.setCountSearchResultsUpTo(TestR4Config.COUNT_SEARCH_RESULTS_UP_TO); + retVal.setFetchSizeDefaultMaximum(10000); return retVal; } diff --git a/hapi-fhir-karaf-features/pom.xml b/osgi/hapi-fhir-karaf-features/pom.xml similarity index 99% rename from hapi-fhir-karaf-features/pom.xml rename to osgi/hapi-fhir-karaf-features/pom.xml index 6a15b39b115..9f3ead87c96 100644 --- a/hapi-fhir-karaf-features/pom.xml +++ b/osgi/hapi-fhir-karaf-features/pom.xml @@ -7,7 +7,7 @@ <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> <version>3.3.0-SNAPSHOT</version> - <relativePath>../hapi-deployable-pom/pom.xml</relativePath> + <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> <groupId>ca.uhn.hapi.fhir.karaf</groupId> diff --git a/hapi-fhir-karaf-features/src/main/resources/features.xml b/osgi/hapi-fhir-karaf-features/src/main/resources/features.xml similarity index 100% rename from hapi-fhir-karaf-features/src/main/resources/features.xml rename to osgi/hapi-fhir-karaf-features/src/main/resources/features.xml diff --git a/hapi-fhir-karaf-integration-tests/pom.xml b/osgi/hapi-fhir-karaf-integration-tests/pom.xml similarity index 98% rename from hapi-fhir-karaf-integration-tests/pom.xml rename to osgi/hapi-fhir-karaf-integration-tests/pom.xml index a8369d685d7..22cab824417 100644 --- a/hapi-fhir-karaf-integration-tests/pom.xml +++ b/osgi/hapi-fhir-karaf-integration-tests/pom.xml @@ -21,7 +21,7 @@ <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> <version>3.3.0-SNAPSHOT</version> - <relativePath>../hapi-deployable-pom/pom.xml</relativePath> + <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> <artifactId>hapi-fhir-karaf-integration-tests</artifactId> diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/PaxExamOptions.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/client/FhirClientTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/PatientProfileDstu2.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/PatientWithExtendedContactDstu3.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java rename to osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/dstu3/myconsent-resource.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/example-patient-general-hl7orgdstu2.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/extension-on-line.txt diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/patient-example-dicom.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/q_jon.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/qr_jon.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/r4/bundle-with-no-type.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/r4/diagnosticreport-example-gingival-mass.json diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/sample-document.xml diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json b/osgi/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json similarity index 100% rename from hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json rename to osgi/hapi-fhir-karaf-integration-tests/src/test/resources/testscript-search.json diff --git a/pom.xml b/pom.xml index b2ca293e722..dff5917e1ca 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <parent> <groupId>org.sonatype.oss</groupId> @@ -609,7 +610,7 @@ <groupId>es.nitaur.markdown</groupId> <artifactId>txtmark</artifactId> <version>0.16</version> - </dependency> + </dependency> <dependency> <groupId>javax.ejb</groupId> <artifactId>ejb-api</artifactId> @@ -676,9 +677,9 @@ <version>2.0.1</version> </dependency> <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.12</version> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> </dependency> <dependency> <groupId>lt.velykis.maven.skins</groupId> @@ -1320,7 +1321,8 @@ <plugin> <groupId>org.jacoco</groupId> <artifactId> - jacoco-maven-plugin</artifactId> + jacoco-maven-plugin + </artifactId> <version>0.7.9</version> </plugin> <plugin> @@ -1568,7 +1570,9 @@ </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> - <replacetoken>http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css</replacetoken> + <replacetoken> + http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css + </replacetoken> <replacevalue>./css/bootstrap-responsive.min.css</replacevalue> </replace> <replace dir="target/site" summary="true"> @@ -1578,8 +1582,10 @@ </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> - <replacetoken>http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css</replacetoken> - <replacevalue>https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css</replacevalue> + <replacetoken>http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css + </replacetoken> + <replacevalue>https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css + </replacevalue> </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> @@ -1623,28 +1629,35 @@ <echo>Adding Fontawesome</echo> <replace dir="target/site" summary="true"> <include name="*.html"/> - <replacetoken><![CDATA[<a href="download.html" title="Download">Download</a>]]></replacetoken> - <replacevalue><![CDATA[<a href="download.html" title="Download"><i class="fa fa-download"></i> Download</a>]]></replacevalue> + <replacetoken> + <![CDATA[<a href="download.html" title="Download">Download</a>]]></replacetoken> + <replacevalue> + <![CDATA[<a href="download.html" title="Download"><i class="fa fa-download"></i> Download</a>]]></replacevalue> </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> - <replacetoken><![CDATA[<a href="https://github.com/jamesagnew/hapi-fhir/" title="GitHub Project" class="externalLink">GitHub Project</a>]]></replacetoken> - <replacevalue><![CDATA[<a href="https://github.com/jamesagnew/hapi-fhir/" title="GitHub Project" class="externalLink"><i class="fa fa-github"></i> GitHub Project</a>]]></replacevalue> + <replacetoken> + <![CDATA[<a href="https://github.com/jamesagnew/hapi-fhir/" title="GitHub Project" class="externalLink">GitHub Project</a>]]></replacetoken> + <replacevalue> + <![CDATA[<a href="https://github.com/jamesagnew/hapi-fhir/" title="GitHub Project" class="externalLink"><i class="fa fa-github"></i> GitHub Project</a>]]></replacevalue> </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> <replacetoken><![CDATA[data-toggle="dropdown">Test Servers <]]></replacetoken> - <replacevalue><![CDATA[data-toggle="dropdown"><i class="fa fa-fire"></i> Test Servers <]]></replacevalue> + <replacevalue> + <![CDATA[data-toggle="dropdown"><i class="fa fa-fire"></i> Test Servers <]]></replacevalue> </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> <replacetoken><![CDATA[data-toggle="dropdown">Documentation <]]></replacetoken> - <replacevalue><![CDATA[data-toggle="dropdown"><i class="fa fa-book"></i> Documentation <]]></replacevalue> + <replacevalue> + <![CDATA[data-toggle="dropdown"><i class="fa fa-book"></i> Documentation <]]></replacevalue> </replace> <replace dir="target/site" summary="true"> <include name="*.html"/> <replacetoken><![CDATA[data-toggle="dropdown">Get Help <]]></replacetoken> - <replacevalue><![CDATA[data-toggle="dropdown"><i class="fa fa-support"></i> Get Help <]]></replacevalue> + <replacevalue> + <![CDATA[data-toggle="dropdown"><i class="fa fa-support"></i> Get Help <]]></replacevalue> </replace> <echo>Changing Breadcrumbs</echo> <replace dir="target/site" summary="true"> @@ -1822,20 +1835,20 @@ </executions> </plugin> <plugin> - <groupId>org.owasp</groupId> - <artifactId>dependency-check-maven</artifactId> - <version>3.1.1</version> - <configuration> - <failBuildOnCVSS>8</failBuildOnCVSS> - </configuration> - <executions> - <execution> - <goals> - <goal>check</goal> - </goals> - </execution> - </executions> - </plugin> + <groupId>org.owasp</groupId> + <artifactId>dependency-check-maven</artifactId> + <version>3.1.1</version> + <configuration> + <failBuildOnCVSS>8</failBuildOnCVSS> + </configuration> + <executions> + <execution> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> @@ -1875,9 +1888,12 @@ <configuration> <reportsDirectories> <reportDirectory>${project.basedir}/hapi-fhir-base/target/surefire-reports/</reportDirectory> - <reportDirectory>${project.basedir}/hapi-fhir-structures-dstu/target/surefire-reports/</reportDirectory> - <reportDirectory>${project.basedir}/hapi-fhir-structures-dstu2/target/surefire-reports/</reportDirectory> - <reportDirectory>${project.basedir}/hapi-fhir-jpaserver-base/target/surefire-reports/</reportDirectory> + <reportDirectory>${project.basedir}/hapi-fhir-structures-dstu/target/surefire-reports/ + </reportDirectory> + <reportDirectory>${project.basedir}/hapi-fhir-structures-dstu2/target/surefire-reports/ + </reportDirectory> + <reportDirectory>${project.basedir}/hapi-fhir-jpaserver-base/target/surefire-reports/ + </reportDirectory> </reportsDirectories> </configuration> </plugin> @@ -1992,8 +2008,6 @@ <module>hapi-tinder-plugin</module> <module>hapi-tinder-test</module> <module>hapi-fhir-client</module> - <module>hapi-fhir-karaf-features</module> - <module>hapi-fhir-karaf-integration-tests</module> <module>hapi-fhir-server</module> <module>hapi-fhir-validation</module> <!--<module>hapi-fhir-narrativegenerator</module>--> @@ -2021,6 +2035,8 @@ <module>hapi-fhir-cli</module> <module>hapi-fhir-dist</module> <module>examples</module> + <module>osgi/hapi-fhir-karaf-features</module> + <module>osgi/hapi-fhir-karaf-integration-tests</module> <module>example-projects/hapi-fhir-base-example-embedded-ws</module> <module>example-projects/hapi-fhir-standalone-overlay-example</module> <module>example-projects/hapi-fhir-jpaserver-cds-example</module> From 94b880fd4d3f1947b05c1f94f964daf3f29a1b8a Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Wed, 28 Mar 2018 10:13:51 -0400 Subject: [PATCH 30/31] Remove accidentally committed useless file --- .../main/java/ca/uhn/fhir/util/StopWatch.java | 4 +- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 4 +- .../ca/uhn/fhir/jpa/dao/ISearchBuilder.java | 4 +- .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 4 +- .../jpa/util/StatelessSessionFactoryBean.java | 157 ------------------ 5 files changed, 8 insertions(+), 165 deletions(-) delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/StopWatch.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/StopWatch.java index 63c9fe115a2..9ad4acc1908 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/StopWatch.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/StopWatch.java @@ -20,9 +20,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 4a9fb531754..b804e2fa6cb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -17,9 +17,9 @@ import java.util.*; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java index 9299fe2428e..f78f8617f90 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchBuilder.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index fc35027209a..2469110cda2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java deleted file mode 100644 index 6dcf062e73b..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StatelessSessionFactoryBean.java +++ /dev/null @@ -1,157 +0,0 @@ -package ca.uhn.fhir.jpa.util; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.hibernate.SessionFactory; -import org.hibernate.StatelessSession; -import org.hibernate.engine.spi.SessionImplementor; -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.orm.jpa.EntityManagerFactoryUtils; -import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; -import org.springframework.transaction.support.ResourceHolderSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationAdapter; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import java.sql.Connection; - -import static org.springframework.orm.jpa.EntityManagerFactoryUtils.ENTITY_MANAGER_SYNCHRONIZATION_ORDER; -import static org.springframework.util.ReflectionUtils.invokeMethod; - -/** - * Hibernate's {@link StatelessSession} factory which will be bound to the - * current transaction. This factory returns a Proxy which delegates method - * calls to the underlying {@link StatelessSession} bound to transaction. At the - * end of the transaction the session is automatically closed. This class - * borrows idea's from {@link DataSourceUtils}, - * {@link EntityManagerFactoryUtils}, {@link ResourceHolderSynchronization} and - * {@link LocalEntityManagerFactoryBean}. - */ -public class StatelessSessionFactoryBean implements FactoryBean<StatelessSession> { - - private SessionFactory sessionFactory; - - @Autowired - public StatelessSessionFactoryBean(SessionFactory theSessionFactory) { - this.sessionFactory = theSessionFactory; - } - - @Override - public StatelessSession getObject() throws Exception { - StatelessSessionInterceptor statelessSessionInterceptor = new StatelessSessionInterceptor( - sessionFactory); - return ProxyFactory.getProxy(StatelessSession.class, statelessSessionInterceptor); - } - - @Override - public Class<?> getObjectType() { - return StatelessSession.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - /** - * Use this to override the {@link SessionFactory} obtained from the - * {@link EntityManagerFactory}. Please note that the connection will still - * be used from the {@link EntityManager}. - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - private static class StatelessSessionInterceptor implements MethodInterceptor { - - private final SessionFactory sessionFactory; - - public StatelessSessionInterceptor( - SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - private void bindWithTransaction(StatelessSession statelessSession) { - TransactionSynchronizationManager - .registerSynchronization(new StatelessSessionSynchronization(sessionFactory, - statelessSession)); - TransactionSynchronizationManager.bindResource(sessionFactory, statelessSession); - } - - private StatelessSession getCurrentSession() { - if (!TransactionSynchronizationManager.isActualTransactionActive()) { - throw new IllegalStateException( - "There should be an active transaction for the current thread."); - } - StatelessSession statelessSession = (StatelessSession) TransactionSynchronizationManager - .getResource(sessionFactory); - if (statelessSession == null) { - statelessSession = openNewStatelessSession(); - bindWithTransaction(statelessSession); - } - return statelessSession; - } - - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - StatelessSession statelessSession = getCurrentSession(); - return invokeMethod(invocation.getMethod(), statelessSession, invocation.getArguments()); - } - - /** - * It is important we obtain the physical (real) connection otherwise it - * will be double proxied and there will be problems releasing the - * connection. - */ - private Connection obtainPhysicalConnection() { - EntityManager entityManager = EntityManagerFactoryUtils - .getTransactionalEntityManager(sessionFactory); - SessionImplementor sessionImplementor = (SessionImplementor) entityManager - .getDelegate(); -// return sessionImplementor.getTransactionCoordinator().getJdbcCoordinator() -// .getLogicalConnection().getConnection(); - return null; - } - - private StatelessSession openNewStatelessSession() { - Connection connection = obtainPhysicalConnection(); - return sessionFactory.openStatelessSession(connection); - } - } - - private static class StatelessSessionSynchronization extends TransactionSynchronizationAdapter { - - private final SessionFactory sessionFactory; - private final StatelessSession statelessSession; - - public StatelessSessionSynchronization(SessionFactory sessionFactory, - StatelessSession statelessSession) { - this.sessionFactory = sessionFactory; - this.statelessSession = statelessSession; - } - - @Override - public void beforeCommit(boolean readOnly) { - if (!readOnly) { -// ((TransactionContext) statelessSession).flu - } - } - - @Override - public void beforeCompletion() { - TransactionSynchronizationManager.unbindResource(sessionFactory); - statelessSession.close(); - } - - @Override - public int getOrder() { - return ENTITY_MANAGER_SYNCHRONIZATION_ORDER - 100; - } - - } - -} From 418e82032ff371544cacf2145f6ae39023923d50 Mon Sep 17 00:00:00 2001 From: jamesagnew <jamesagnew@gmail.com> Date: Thu, 29 Mar 2018 05:48:13 -0400 Subject: [PATCH 31/31] Prep for 3.3.0 --- .../pom.xml | 2 +- .../hapi-fhir-jpaserver-cds-example/pom.xml | 2 +- .../hapi-fhir-jpaserver-dynamic/pom.xml | 2 +- .../pom.xml | 2 +- examples/pom.xml | 2 +- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 20 +++++++++---------- hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-igpacks/pom.xml | 2 +- hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jaxrsserver-example/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- hapi-fhir-jpaserver-elasticsearch/pom.xml | 2 +- hapi-fhir-jpaserver-example/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 4 ++-- hapi-fhir-server/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- hapi-fhir-utilities/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 2 +- hapi-tinder-test/pom.xml | 2 +- osgi/hapi-fhir-karaf-features/pom.xml | 2 +- .../hapi-fhir-karaf-integration-tests/pom.xml | 2 +- pom.xml | 2 +- restful-server-example-test/pom.xml | 2 +- restful-server-example/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 53 files changed, 63 insertions(+), 63 deletions(-) diff --git a/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml b/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml index a7a2d9a7059..c3051b68366 100644 --- a/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml +++ b/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml b/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml index ff31307337e..9aa98c60577 100644 --- a/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml +++ b/example-projects/hapi-fhir-jpaserver-cds-example/pom.xml @@ -10,7 +10,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/example-projects/hapi-fhir-jpaserver-dynamic/pom.xml b/example-projects/hapi-fhir-jpaserver-dynamic/pom.xml index 18a3ef434ff..f82202218c4 100644 --- a/example-projects/hapi-fhir-jpaserver-dynamic/pom.xml +++ b/example-projects/hapi-fhir-jpaserver-dynamic/pom.xml @@ -10,7 +10,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.2.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/example-projects/hapi-fhir-standalone-overlay-example/pom.xml b/example-projects/hapi-fhir-standalone-overlay-example/pom.xml index 8bf39c78555..2e53603229d 100644 --- a/example-projects/hapi-fhir-standalone-overlay-example/pom.xml +++ b/example-projects/hapi-fhir-standalone-overlay-example/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> <artifactId>hapi-fhir-standalone-overlay-example</artifactId> diff --git a/examples/pom.xml b/examples/pom.xml index 4f9465d50e1..f152cec2663 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index e913374edaf..26a68e2581e 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index d5be37347bf..5e3d157cb8d 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index f9559a6362a..8c198da8651 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index 10348db39f7..c21ca47c67c 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-cli</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index 795f5dac0f7..0159333a05d 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-cli</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index e7d08b54703..a03a9e03b76 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index d4abc418f02..aab6f1bacdb 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index 00d03f7a02b..cb5879cf839 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 465c0dc121f..ae7d1a8b7c2 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> @@ -16,14 +16,14 @@ <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-base</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </dependency> <!-- Server --> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-server</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> @@ -35,43 +35,43 @@ <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu2</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu2.1</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu3</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-r4</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-validation-resources-dstu2</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-validation-resources-dstu3</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <optional>true</optional> </dependency> diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index f29a54fca8f..ba7aea92acc 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-igpacks/pom.xml b/hapi-fhir-igpacks/pom.xml index 50ac7fec227..2c7785f4ee2 100644 --- a/hapi-fhir-igpacks/pom.xml +++ b/hapi-fhir-igpacks/pom.xml @@ -5,7 +5,7 @@ <parent> <artifactId>hapi-deployable-pom</artifactId> <groupId>ca.uhn.hapi.fhir</groupId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index 29a8ba1a86f..5c86340da26 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index 5f3a1282871..ac6a4c527bd 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jaxrsserver-example/pom.xml b/hapi-fhir-jaxrsserver-example/pom.xml index 805549388fe..c50e005ebea 100644 --- a/hapi-fhir-jaxrsserver-example/pom.xml +++ b/hapi-fhir-jaxrsserver-example/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 7fdfe61324c..7a40b05c6fb 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jpaserver-elasticsearch/pom.xml b/hapi-fhir-jpaserver-elasticsearch/pom.xml index 8b966ec6188..1b320506887 100644 --- a/hapi-fhir-jpaserver-elasticsearch/pom.xml +++ b/hapi-fhir-jpaserver-elasticsearch/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jpaserver-example/pom.xml b/hapi-fhir-jpaserver-example/pom.xml index eb08b41f12f..7524324fc8d 100644 --- a/hapi-fhir-jpaserver-example/pom.xml +++ b/hapi-fhir-jpaserver-example/pom.xml @@ -10,7 +10,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 2dfc1ec5008..58ca963d3f8 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> @@ -158,7 +158,7 @@ <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-converter</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </dependency> </dependencies> diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index af543ba6bd1..aaba211bae9 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index b4e85bf2590..f4c3119292e 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index 028c8e25227..3bf4582dcb7 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-spring-boot-samples</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </parent> <artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index b0bc006ce2b..384a64bb5f1 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-spring-boot-samples</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </parent> <artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index 00c738e74c1..f347c3577c7 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-spring-boot-samples</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </parent> <artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml index 8c277cdd8a9..4cf4af953dc 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-spring-boot-samples</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </parent> <artifactId>hapi-fhir-spring-boot-sample-server-jpa</artifactId> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index b597d8f9038..d92927886b1 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-spring-boot</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> </parent> <artifactId>hapi-fhir-spring-boot-samples</artifactId> diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 2875a42825e..9fa665b4660 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 8407b4b47e5..865dfc8183f 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index edbd2da2f22..5c66a51ab8c 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 67b81dd56b7..03c524b66c5 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 16fa0e46660..f8e8dc1f2e0 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index 75bd63e6a43..0cabe89bcf4 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index 93a32d9067c..84600c89860 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index e68dabc0498..45fbc05714f 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-fhir-utilities/pom.xml b/hapi-fhir-utilities/pom.xml index c800404caba..30f4e8876ad 100644 --- a/hapi-fhir-utilities/pom.xml +++ b/hapi-fhir-utilities/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index 2778252ee29..9b7ef659288 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 2ffcd1a5102..ab55396bd91 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index a313bad15e5..539a0354cdc 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index d6c899f1941..daff0945380 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 2f3b937bc2d..85f350e036f 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index ecf5f33d031..41dd65a5d69 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 993991ef87e..c1ac0e18b8c 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/osgi/hapi-fhir-karaf-features/pom.xml b/osgi/hapi-fhir-karaf-features/pom.xml index 9f3ead87c96..4dddd23355a 100644 --- a/osgi/hapi-fhir-karaf-features/pom.xml +++ b/osgi/hapi-fhir-karaf-features/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/osgi/hapi-fhir-karaf-integration-tests/pom.xml b/osgi/hapi-fhir-karaf-integration-tests/pom.xml index 22cab824417..5cd8280c978 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/pom.xml +++ b/osgi/hapi-fhir-karaf-integration-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-deployable-pom</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath> </parent> diff --git a/pom.xml b/pom.xml index 45d6cb347c4..a70aceb375f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> <packaging>pom</packaging> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <name>HAPI-FHIR</name> <url>https://hapifhir.io</url> diff --git a/restful-server-example-test/pom.xml b/restful-server-example-test/pom.xml index 0b71a189c0f..f0cce113aad 100644 --- a/restful-server-example-test/pom.xml +++ b/restful-server-example-test/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/restful-server-example/pom.xml b/restful-server-example/pom.xml index f01574706d8..5e347d80730 100644 --- a/restful-server-example/pom.xml +++ b/restful-server-example/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index 1df31b9ed08..88302a9689c 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index 77214e67bf0..dd977c544fb 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir</artifactId> - <version>3.3.0-SNAPSHOT</version> + <version>3.3.0</version> <relativePath>../../pom.xml</relativePath> </parent>