A few cleanups to allow example resources to commit cleanly
This commit is contained in:
parent
70a26c6d2d
commit
d20b7e2c94
|
@ -87,7 +87,6 @@ public abstract class BaseParser implements IParser {
|
|||
}
|
||||
|
||||
private void containResourcesForEncoding(ContainedResources theContained, IBaseResource theResource, IBaseResource theTarget) {
|
||||
|
||||
Set<String> allIds = new HashSet<String>();
|
||||
Map<String, IBaseResource> existingIdToContainedResource = null;
|
||||
|
||||
|
@ -131,6 +130,10 @@ public abstract class BaseParser implements IParser {
|
|||
IBaseResource resource = next.getResource();
|
||||
if (resource != null) {
|
||||
if (resource.getIdElement().isEmpty() || resource.getIdElement().isLocal()) {
|
||||
if (theContained.getResourceId(resource) != null) {
|
||||
// Prevent infinite recursion if there are circular loops in the contained resources
|
||||
continue;
|
||||
}
|
||||
theContained.addContained(resource);
|
||||
} else {
|
||||
continue;
|
||||
|
|
|
@ -1684,7 +1684,7 @@ class ParserState<T> {
|
|||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
if (myExtension.getValue() != null && myExtension.getExtension().size() > 0) {
|
||||
throw new DataFormatException("Extension must not have both a value and other contained extensions");
|
||||
throw new DataFormatException("Extension (URL='" + myExtension.getUrl() + "') must not have both a value and other contained extensions");
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.util;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
@ -68,29 +69,26 @@ public class FhirTerser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are
|
||||
* either of the exact type specified, or are a subclass of that type.
|
||||
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are either of the exact type specified, or are a subclass of that type.
|
||||
* <p>
|
||||
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within the
|
||||
* message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained
|
||||
* resources.
|
||||
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within the message. Specifying a type of {@link IResource} would return the resource itself, as
|
||||
* well as any contained resources.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
|
||||
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
|
||||
* resources (e.g. Bundle.entry.resource)
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g.
|
||||
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource)
|
||||
* </p>
|
||||
*
|
||||
* @param theResource
|
||||
* The resource instance to search. Must not be null.
|
||||
* The resource instance to search. Must not be null.
|
||||
* @param theType
|
||||
* The type to search for. Must not be null.
|
||||
* The type to search for. Must not be null.
|
||||
* @return Returns a list of all matching elements
|
||||
*/
|
||||
public <T extends IBase> List<T> getAllPopulatedChildElementsOfType(IBaseResource theResource, final Class<T> theType) {
|
||||
final ArrayList<T> retVal = new ArrayList<T>();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
visit(theResource, null, null, def, new IModelVisitor() {
|
||||
visit(new IdentityHashMap<Object, Object>(), theResource, null, null, def, new IModelVisitor() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void acceptElement(IBase theElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
|
||||
|
@ -105,8 +103,8 @@ public class FhirTerser {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition,
|
||||
ExtensionDt theNextExt) {
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
|
||||
BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
|
||||
if (theType.isAssignableFrom(theNextExt.getClass())) {
|
||||
retVal.add((T) theNextExt);
|
||||
}
|
||||
|
@ -118,32 +116,32 @@ public class FhirTerser {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
|
||||
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
visit(theResource, null, null, def, new IModelVisitor() {
|
||||
@Override
|
||||
public void acceptElement(IBase theElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
|
||||
if (theElement == null || theElement.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (IBaseReference.class.isAssignableFrom(theElement.getClass())) {
|
||||
retVal.add(new ResourceReferenceInfo(myContext, theResource, thePathToElement, (IBaseReference)theElement));
|
||||
}
|
||||
}
|
||||
public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
|
||||
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
visit(new IdentityHashMap<Object, Object>(),theResource, null, null, def, new IModelVisitor() {
|
||||
@Override
|
||||
public void acceptElement(IBase theElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition) {
|
||||
if (theElement == null || theElement.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (IBaseReference.class.isAssignableFrom(theElement.getClass())) {
|
||||
retVal.add(new ResourceReferenceInfo(myContext, theResource, thePathToElement, (IBaseReference) theElement));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition,
|
||||
ExtensionDt theNextExt) {
|
||||
if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) {
|
||||
retVal.add(new ResourceReferenceInfo(myContext, theResource, thePathToElement, (BaseResourceReferenceDt)theNextExt.getValue()));
|
||||
}
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
}
|
||||
@Override
|
||||
public void acceptUndeclaredExtension(ISupportsUndeclaredExtensions theContainingElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
|
||||
BaseRuntimeElementDefinition<?> theDefinition, ExtensionDt theNextExt) {
|
||||
if (theNextExt.getValue() != null && BaseResourceReferenceDt.class.isAssignableFrom(theNextExt.getValue().getClass())) {
|
||||
retVal.add(new ResourceReferenceInfo(myContext, theResource, thePathToElement, (BaseResourceReferenceDt) theNextExt.getValue()));
|
||||
}
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
|
||||
private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
|
||||
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));
|
||||
|
||||
if (theSubList.size() == 1) {
|
||||
|
@ -214,7 +212,7 @@ public class FhirTerser {
|
|||
|
||||
public List<Object> getValues(IBaseResource theResource, String thePath) {
|
||||
Class<Object> wantedClass = Object.class;
|
||||
|
||||
|
||||
return getValues(theResource, thePath, wantedClass);
|
||||
|
||||
}
|
||||
|
@ -233,24 +231,30 @@ public class FhirTerser {
|
|||
return getValues(currentDef, currentObj, subList, theWantedClass);
|
||||
}
|
||||
|
||||
private List<String> addNameToList(List<String> theCurrentList, BaseRuntimeChildDefinition theChildDefinition) {
|
||||
if (theChildDefinition == null)
|
||||
return null;
|
||||
if (theCurrentList== null || theCurrentList.isEmpty())
|
||||
return new ArrayList<String>(Arrays.asList(theChildDefinition.getElementName()));
|
||||
List<String> newList = new ArrayList<String>(theCurrentList);
|
||||
newList.add(theChildDefinition.getElementName());
|
||||
return newList;
|
||||
}
|
||||
private List<String> addNameToList(List<String> theCurrentList, BaseRuntimeChildDefinition theChildDefinition) {
|
||||
if (theChildDefinition == null)
|
||||
return null;
|
||||
if (theCurrentList == null || theCurrentList.isEmpty())
|
||||
return new ArrayList<String>(Arrays.asList(theChildDefinition.getElementName()));
|
||||
List<String> newList = new ArrayList<String>(theCurrentList);
|
||||
newList.add(theChildDefinition.getElementName());
|
||||
return newList;
|
||||
}
|
||||
|
||||
private void visit(IBase theElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
|
||||
List<String> pathToElement = addNameToList(thePathToElement, theChildDefinition);
|
||||
private void visit(IdentityHashMap<Object, Object> theStack, IBase theElement, List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
|
||||
BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
|
||||
List<String> pathToElement = addNameToList(thePathToElement, theChildDefinition);
|
||||
|
||||
if (theStack.put(theElement, theElement) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
theCallback.acceptElement(theElement, pathToElement, theChildDefinition, theDefinition);
|
||||
addUndeclaredExtensions(theElement, theDefinition, theChildDefinition, theCallback);
|
||||
|
||||
// if (theElement.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
if (theElement.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (theDefinition.getChildType()) {
|
||||
case ID_DATATYPE:
|
||||
|
@ -265,7 +269,7 @@ public class FhirTerser {
|
|||
IBaseResource theResource = resRefDt.getResource();
|
||||
if (theResource.getIdElement() == null || theResource.getIdElement().isEmpty() || theResource.getIdElement().isLocal()) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
visit(theResource, pathToElement, null, def, theCallback);
|
||||
visit(theStack, theResource, pathToElement, null, def, theCallback);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -287,14 +291,14 @@ public class FhirTerser {
|
|||
childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
|
||||
|
||||
if (childElementDef == null) {
|
||||
childElementDef = myContext.getElementDefinition(nextValue.getClass());
|
||||
childElementDef = myContext.getElementDefinition(nextValue.getClass());
|
||||
}
|
||||
|
||||
if (nextChild instanceof RuntimeChildDirectResource) {
|
||||
// Don't descend into embedded resources
|
||||
theCallback.acceptElement(nextValue, null, nextChild, childElementDef);
|
||||
} else {
|
||||
visit(nextValue, pathToElement, nextChild, childElementDef, theCallback);
|
||||
visit(theStack, nextValue, pathToElement, nextChild, childElementDef, theCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +309,7 @@ public class FhirTerser {
|
|||
BaseContainedDt value = (BaseContainedDt) theElement;
|
||||
for (IResource next : value.getContainedResources()) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next);
|
||||
visit(next, pathToElement, null, def, theCallback);
|
||||
visit(theStack, next, pathToElement, null, def, theCallback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -316,21 +320,25 @@ public class FhirTerser {
|
|||
case CONTAINED_RESOURCE_LIST:
|
||||
if (theElement != null) {
|
||||
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theElement.getClass());
|
||||
visit(theElement, pathToElement, null, def, theCallback);
|
||||
visit(theStack, theElement, pathToElement, null, def, theCallback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
theStack.remove(theElement);
|
||||
|
||||
}
|
||||
|
||||
private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor2 theCallback, List<IBase> theContainingElementPath, List<BaseRuntimeChildDefinition> theChildDefinitionPath,
|
||||
List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath) {
|
||||
private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor2 theCallback, List<IBase> theContainingElementPath,
|
||||
List<BaseRuntimeChildDefinition> theChildDefinitionPath, List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath) {
|
||||
if (theChildDefinition != null) {
|
||||
theChildDefinitionPath.add(theChildDefinition);
|
||||
}
|
||||
theContainingElementPath.add(theElement);
|
||||
theElementDefinitionPath.add(theDefinition);
|
||||
|
||||
theCallback.acceptElement(theElement, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), Collections.unmodifiableList(theElementDefinitionPath));
|
||||
theCallback.acceptElement(theElement, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath),
|
||||
Collections.unmodifiableList(theElementDefinitionPath));
|
||||
|
||||
/*
|
||||
* Visit undeclared extensions
|
||||
|
@ -405,7 +413,8 @@ public class FhirTerser {
|
|||
theContainingElementPath.add(nextValue);
|
||||
theChildDefinitionPath.add(nextChild);
|
||||
theElementDefinitionPath.add(myContext.getElementDefinition(nextValue.getClass()));
|
||||
theCallback.acceptElement(nextValue, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), Collections.unmodifiableList(theElementDefinitionPath));
|
||||
theCallback.acceptElement(nextValue, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath),
|
||||
Collections.unmodifiableList(theElementDefinitionPath));
|
||||
theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1);
|
||||
theContainingElementPath.remove(theContainingElementPath.size() - 1);
|
||||
theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1);
|
||||
|
@ -449,19 +458,18 @@ public class FhirTerser {
|
|||
* Visit all elements in a given resource
|
||||
*
|
||||
* <p>
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
|
||||
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
|
||||
* resources (e.g. Bundle.entry.resource)
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g.
|
||||
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource)
|
||||
* </p>
|
||||
*
|
||||
* @param theResource
|
||||
* The resource to visit
|
||||
* The resource to visit
|
||||
* @param theVisitor
|
||||
* The visitor
|
||||
* The visitor
|
||||
*/
|
||||
public void visit(IBaseResource theResource, IModelVisitor theVisitor) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
visit(theResource, null, null, def, theVisitor);
|
||||
visit(new IdentityHashMap<Object, Object>(), theResource, null, null, def, theVisitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -470,15 +478,14 @@ public class FhirTerser {
|
|||
* THIS ALTERNATE METHOD IS STILL EXPERIMENTAL
|
||||
*
|
||||
* <p>
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well,
|
||||
* but will not descend into linked resources (e.g. {@link BaseResourceReferenceDt#getResource()}) or embedded
|
||||
* resources (e.g. Bundle.entry.resource)
|
||||
* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g.
|
||||
* {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource)
|
||||
* </p>
|
||||
*
|
||||
* @param theResource
|
||||
* The resource to visit
|
||||
* The resource to visit
|
||||
* @param theVisitor
|
||||
* The visitor
|
||||
* The visitor
|
||||
*/
|
||||
void visit(IBaseResource theResource, IModelVisitor2 theVisitor) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
|
@ -487,7 +494,7 @@ public class FhirTerser {
|
|||
|
||||
public Object getSingleValueOrNull(IBase theTarget, String thePath) {
|
||||
Class<Object> wantedType = Object.class;
|
||||
|
||||
|
||||
return getSingleValueOrNull(theTarget, thePath, wantedType);
|
||||
}
|
||||
|
||||
|
@ -512,5 +519,4 @@ public class FhirTerser {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -87,6 +87,9 @@ public interface IIdType {
|
|||
|
||||
IIdType withServerBase(String theServerBase, String theResourceName);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this ID contains an absolute URL (in other words, a URL starting with "http://" or "https://"
|
||||
*/
|
||||
boolean isAbsolute();
|
||||
|
||||
boolean isIdPartValidLong();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build/
|
|
@ -0,0 +1,128 @@
|
|||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!--
|
||||
Note: HAPI projects use the "hapi-fhir" POM as their base to provide
|
||||
easy management.
|
||||
|
||||
You do not need to use this in your own projects, so the
|
||||
"parent" tag and it's contents below may be removed if you
|
||||
are using this file as a basis for your own project.
|
||||
-->
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>ca.uhn.hapi.example</groupId>
|
||||
<artifactId>hapi-fhir-examples-uploader</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR - Examples Uploader</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- This dependency includes the core HAPI-FHIR classes -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<!--
|
||||
Tells Maven to name the generated WAR file as
|
||||
hapi-fhir-jpaserver-example.war
|
||||
-->
|
||||
<finalName>hapi-fhir-jpaserver-example</finalName>
|
||||
|
||||
<!--
|
||||
The following is not required for the application to build, but
|
||||
allows you to test it by issuing "mvn jetty:run" from the command
|
||||
line.
|
||||
-->
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.1.1.v20140108</version>
|
||||
<configuration>
|
||||
<webApp>
|
||||
<contextPath>/hapi-fhir-jpaserver-example</contextPath>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<!--
|
||||
Tell Maven which Java source version you want to use
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
The configuration here tells the WAR plugin to include the FHIR Tester
|
||||
overlay. You can omit it if you are not using that feature.
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
</overlay>
|
||||
</overlays>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
This plugin is just a part of the HAPI internal build process, you do not
|
||||
need to incude it in your own projects
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,149 @@
|
|||
package ca.uhn.fhir.exampleuploader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryTransaction;
|
||||
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||
|
||||
public class Uploader {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Uploader.class);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ourLog.info("Starting...");
|
||||
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
|
||||
HttpGet get = new HttpGet("http://hl7.org/fhir/2015May/examples-json.zip");
|
||||
CloseableHttpClient client = HttpClientBuilder.create().build();
|
||||
CloseableHttpResponse result = client.execute(get);
|
||||
byte[] bytes = IOUtils.toByteArray(result.getEntity().getContent());
|
||||
IOUtils.closeQuietly(result.getEntity().getContent());
|
||||
|
||||
ourLog.info("Loaded examples ({} bytes)", bytes.length);
|
||||
|
||||
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
|
||||
byte[] buffer = new byte[2048];
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
while (true) {
|
||||
ZipEntry nextEntry = zis.getNextEntry();
|
||||
if (nextEntry == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
byte[] exampleBytes = bos.toByteArray();
|
||||
String exampleString = new String(exampleBytes, "UTF-8");
|
||||
|
||||
IBaseResource parsed;
|
||||
try {
|
||||
parsed = ctx.newJsonParser().parseResource(exampleString);
|
||||
} catch (DataFormatException e) {
|
||||
ourLog.info("FAILED to parse example {}", nextEntry.getName(), e);
|
||||
continue;
|
||||
}
|
||||
ourLog.info("Found example {} - {} - {} chars", nextEntry.getName(), parsed.getClass().getSimpleName(), exampleString.length());
|
||||
|
||||
if (parsed instanceof Bundle) {
|
||||
Bundle b = (Bundle) parsed;
|
||||
for (Entry nextEntry1 : b.getEntry()) {
|
||||
if (nextEntry1.getResource() == null) {
|
||||
continue;
|
||||
}
|
||||
if (nextEntry1.getResource() instanceof Bundle) {
|
||||
continue;
|
||||
}
|
||||
if (nextEntry1.getResource() instanceof SearchParameter) {
|
||||
continue;
|
||||
}
|
||||
bundle.addEntry().setTransaction(new EntryTransaction().setMethod(HTTPVerbEnum.POST)).setResource(nextEntry1.getResource());
|
||||
}
|
||||
} else {
|
||||
if (parsed instanceof SearchParameter) {
|
||||
continue;
|
||||
}
|
||||
bundle.addEntry().setTransaction(new EntryTransaction().setMethod(HTTPVerbEnum.POST)).setResource((IResource) parsed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Set<String> ids = new HashSet<String>();
|
||||
for (int i = 0; i < bundle.getEntry().size(); i++) {
|
||||
Entry next = bundle.getEntry().get(i);
|
||||
if (next.getResource().getId().getIdPart() != null) {
|
||||
String nextId = next.getResource().getResourceName() + '/' + next.getResource().getId().getIdPart();
|
||||
if (!ids.add(nextId)) {
|
||||
ourLog.info("Discarding duplicate resource with ID: " + nextId);
|
||||
bundle.getEntry().remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int goodRefs = 0;
|
||||
for (Entry next : bundle.getEntry()) {
|
||||
List<ResourceReferenceInfo> refs = ctx.newTerser().getAllResourceReferences(next.getResource());
|
||||
for (ResourceReferenceInfo nextRef : refs) {
|
||||
// if (nextRef.getResourceReference().getReferenceElement().isAbsolute()) {
|
||||
// ourLog.info("Discarding absolute reference: {}", nextRef.getResourceReference().getReferenceElement().getValue());
|
||||
// nextRef.getResourceReference().getReferenceElement().setValue(null);
|
||||
// }
|
||||
nextRef.getResourceReference().getReferenceElement().setValue(nextRef.getResourceReference().getReferenceElement().toUnqualifiedVersionless().getValue());
|
||||
String value = nextRef.getResourceReference().getReferenceElement().toUnqualifiedVersionless().getValue();
|
||||
if (!ids.contains(value) && !nextRef.getResourceReference().getReferenceElement().isLocal()) {
|
||||
ourLog.info("Discarding unknown reference: {}", value);
|
||||
nextRef.getResourceReference().getReferenceElement().setValue(null);
|
||||
} else {
|
||||
goodRefs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for (Entry next : bundle.getEntry()) {
|
||||
// if (next.getResource().getId().hasIdPart() && Character.isLetter(next.getResource().getId().getIdPart().charAt(0))) {
|
||||
// next.getTransaction().setUrl(next.getResource().getResourceName() + '/' + next.getResource().getId().getIdPart());
|
||||
// next.getTransaction().setMethod(HTTPVerbEnum.PUT);
|
||||
// }
|
||||
// }
|
||||
|
||||
ourLog.info("{} good references", goodRefs);
|
||||
|
||||
String encoded = ctx.newJsonParser().encodeResourceToString(bundle);
|
||||
ourLog.info("Final bundle: {} entries", bundle.getEntry().size());
|
||||
ourLog.info("Final bundle: {} chars", encoded.length());
|
||||
|
||||
IGenericClient fhirClient = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2");
|
||||
fhirClient.transaction().withBundle(bundle).execute();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.eclipse" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="org.apache" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="org.thymeleaf" additivity="false" level="warn">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<!--
|
||||
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="trace">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
-->
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.base.composite.BaseHumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.AddressDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.BoundCodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ContactPointDt;
|
||||
|
@ -58,9 +59,11 @@ import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
|||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient.Communication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.RestfulSecurityServiceEnum;
|
||||
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
@ -469,28 +472,21 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
|
|||
} else if (nextObject instanceof CodeableConceptDt) {
|
||||
CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
|
||||
if (!nextCC.getTextElement().isEmpty()) {
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseFhirDao.normalizeString(nextCC.getTextElement().getValue()), nextCC.getTextElement().getValue());
|
||||
String value = nextCC.getTextElement().getValue();
|
||||
if (value.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
|
||||
value = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseFhirDao.normalizeString(value), value);
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
|
||||
for (CodingDt nextCoding : nextCC.getCoding()) {
|
||||
if (nextCoding.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextSystem = nextCoding.getSystemElement().getValueAsString();
|
||||
String nextCode = nextCoding.getCodeElement().getValue();
|
||||
if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
|
||||
systems.add(nextSystem);
|
||||
codes.add(nextCode);
|
||||
}
|
||||
|
||||
if (!nextCoding.getDisplayElement().isEmpty()) {
|
||||
systems.add(null);
|
||||
codes.add(nextCoding.getDisplayElement().getValue());
|
||||
}
|
||||
|
||||
extractTokensFromCodeableConcept(systems, codes, nextCC);
|
||||
} else if (nextObject instanceof RestSecurity) {
|
||||
// Conformance.security search param points to something kind of useless right now - This should probably be fixed.
|
||||
RestSecurity sec = (RestSecurity)nextObject;
|
||||
for (BoundCodeableConceptDt<RestfulSecurityServiceEnum> nextCC : sec.getService()) {
|
||||
extractTokensFromCodeableConcept(systems, codes, nextCC);
|
||||
}
|
||||
} else {
|
||||
if (!multiType) {
|
||||
|
@ -538,4 +534,25 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void extractTokensFromCodeableConcept(List<String> systems, List<String> codes, CodeableConceptDt nextCC) {
|
||||
for (CodingDt nextCoding : nextCC.getCoding()) {
|
||||
if (nextCoding.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextSystem = nextCoding.getSystemElement().getValueAsString();
|
||||
String nextCode = nextCoding.getCodeElement().getValue();
|
||||
if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
|
||||
systems.add(nextSystem);
|
||||
codes.add(nextCode);
|
||||
}
|
||||
|
||||
if (!nextCoding.getDisplayElement().isEmpty()) {
|
||||
systems.add(null);
|
||||
codes.add(nextCoding.getDisplayElement().getValue());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -37,6 +38,8 @@ import org.junit.Test;
|
|||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.jmx.access.InvalidInvocationException;
|
||||
|
||||
import com.ctc.wstx.util.StringUtil;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
|
@ -1715,6 +1718,37 @@ public class FhirResourceDaoDstu2Test extends BaseJpaTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchStringParamReallyLong() {
|
||||
String methodName = "testSearchStringParamReallyLong";
|
||||
String value = StringUtils.rightPad(methodName, 200, 'a');
|
||||
|
||||
IIdType longId;
|
||||
IIdType shortId;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily(value);
|
||||
longId = (IdDt) ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
shortId = (IdDt) ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
String substring = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
|
||||
params.put(Patient.SP_FAMILY, new StringParam(substring));
|
||||
IBundleProvider found = ourPatientDao.search(params);
|
||||
assertEquals(1, toList(found).size());
|
||||
assertThat(toUnqualifiedVersionlessIds(found), contains(longId));
|
||||
assertThat(toUnqualifiedVersionlessIds(found), not(contains(shortId)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchStringParamWithNonNormalized() {
|
||||
{
|
||||
|
|
|
@ -25,11 +25,12 @@ public class UhnFhirTestApp {
|
|||
|
||||
int myPort = 8888;
|
||||
String base = "http://localhost:" + myPort + "/base";
|
||||
|
||||
|
||||
// new File("target/testdb").mkdirs();
|
||||
System.setProperty("fhir.db.location", "./target/testdb");
|
||||
System.setProperty("fhir.db.location.dstu2", "./target/testdb_dstu2");
|
||||
System.setProperty("fhir.baseurl", base);
|
||||
System.setProperty("fhir.baseurl.dstu1", base + "Dstu1");
|
||||
System.setProperty("fhir.baseurl.dstu2", base + "Dstu1");
|
||||
|
||||
Server server = new Server(myPort);
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
|
||||
public class Perf {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Perf.class);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
FhirContext ctx = FhirContext.forDstu1();
|
||||
|
||||
String str = IOUtils.toString(Perf.class.getResourceAsStream("/contained-diagnosticreport-singlecontainedelement.xml"));
|
||||
DiagnosticReport rept = ctx.newXmlParser().parseResource(DiagnosticReport.class, str);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
if (i % 10 == 0) {
|
||||
ourLog.info("Rep: " + i);
|
||||
}
|
||||
ctx.newTerser().getAllPopulatedChildElementsOfType(rept, BaseResourceReferenceDt.class);
|
||||
}
|
||||
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
ourLog.info("Took: {} ms", delay);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ public class IdDtTest {
|
|||
|
||||
id = new IdDt("#123");
|
||||
assertEquals("#123", id.getValue());
|
||||
assertEquals("#123", id.toUnqualifiedVersionless().getValue());
|
||||
assertTrue(id.isLocal());
|
||||
|
||||
id = new IdDt("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
||||
|
|
|
@ -500,6 +500,28 @@ public class XmlParserTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeContainedWithSelfReference() {
|
||||
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
|
||||
// Create an organization, note that the organization does not have an ID
|
||||
Organization org = new Organization();
|
||||
org.getName().setValue("Contained Test Organization");
|
||||
org.setPartOf(new ResourceReferenceDt(org));
|
||||
|
||||
// Create a patient
|
||||
Patient patient = new Patient();
|
||||
patient.getManagingOrganization().setResource(org);
|
||||
|
||||
String encoded = xmlParser.encodeResourceToString(patient);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("<contained>"));
|
||||
assertThat(encoded, containsString("<reference value=\"#1\"/>"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeContained() {
|
||||
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
|
|
|
@ -146,6 +146,10 @@
|
|||
e.g. "Location.partof.partof.organization". Thanks to Ismael Sarmento Jr for
|
||||
reporting!
|
||||
</action>
|
||||
<action type="fix">
|
||||
Prevent crash when encoding resources with contained resources
|
||||
if the contained resources contained a circular reference to each other
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.0" date="2015-May-8">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue