Bump to 3.6.0-SNAPSHOT

This commit is contained in:
James Agnew 2018-09-19 10:24:48 -04:00
parent 6e0a1dddd4
commit 706e004b9d
64 changed files with 298 additions and 214 deletions

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -10,7 +10,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -10,7 +10,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -10,7 +10,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-standalone-overlay-example</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.context;
* 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,15 +20,10 @@ package ca.uhn.fhir.context;
* #L%
*/
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import ca.uhn.fhir.parser.IParser;
import java.util.*;
/**
* This object supplies default configuration to all {@link IParser parser} instances
* created by a given {@link FhirContext}. It is accessed using {@link FhirContext#getParserOptions()}
@ -42,7 +37,7 @@ public class ParserOptions {
private boolean myStripVersionsFromReferences = true;
private Set<String> myDontStripVersionsFromReferencesAtPaths = Collections.emptySet();
private boolean myOverrideResourceIdWithBundleEntryFullUrl = true;
/**
* If supplied value(s), any resource references at the specified paths will have their
* resource versions encoded instead of being automatically stripped during the encoding
@ -53,13 +48,12 @@ public class ParserOptions {
* has been set to <code>true</code> (which is the default)
* </p>
*
* @param thePaths
* A collection of paths for which the resource versions will not be removed automatically
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
* only resource name and field names with dots separating is allowed here (no repetition
* indicators, FluentPath expressions, etc.)
* @see #setStripVersionsFromReferences(boolean)
* @param thePaths A collection of paths for which the resource versions will not be removed automatically
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
* only resource name and field names with dots separating is allowed here (no repetition
* indicators, FluentPath expressions, etc.)
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
* @see #setStripVersionsFromReferences(boolean)
*/
public ParserOptions setDontStripVersionsFromReferencesAtPaths(String... thePaths) {
if (thePaths == null) {
@ -69,19 +63,19 @@ public class ParserOptions {
}
return this;
}
/**
* If set to <code>true<code> (which is the default), resource references containing a version
* will have the version removed when the resource is encoded. This is generally good behaviour because
* in most situations, references from one resource to another should be to the resource by ID, not
* by ID and version. In some cases though, it may be desirable to preserve the version in resource
* links. In that case, this value should be set to <code>false</code>.
*
*
* @return Returns the parser instance's configuration setting for stripping versions from resource references when
* encoding. Default is <code>true</code>.
* encoding. Default is <code>true</code>.
*/
public boolean isStripVersionsFromReferences() {
return myStripVersionsFromReferences ;
return myStripVersionsFromReferences;
}
/**
@ -94,9 +88,9 @@ public class ParserOptions {
* This method provides the ability to globally disable reference encoding. If finer-grained
* control is needed, use {@link #setDontStripVersionsFromReferencesAtPaths(String...)}
* </p>
* @param theStripVersionsFromReferences
* Set this to <code>false<code> to prevent the parser from removing
* resource versions from references.
*
* @param theStripVersionsFromReferences Set this to <code>false<code> to prevent the parser from removing
* resource versions from references.
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
*/
@ -105,6 +99,16 @@ public class ParserOptions {
return this;
}
/**
* Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
*
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
* @see #setStripVersionsFromReferences(boolean)
*/
public Set<String> getDontStripVersionsFromReferencesAtPaths() {
return myDontStripVersionsFromReferencesAtPaths;
}
/**
* If supplied value(s), any resource references at the specified paths will have their
* resource versions encoded instead of being automatically stripped during the encoding
@ -115,36 +119,25 @@ public class ParserOptions {
* has been set to <code>true</code> (which is the default)
* </p>
*
* @param thePaths
* A collection of paths for which the resource versions will not be removed automatically
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
* only resource name and field names with dots separating is allowed here (no repetition
* indicators, FluentPath expressions, etc.)
* @see #setStripVersionsFromReferences(boolean)
* @param thePaths A collection of paths for which the resource versions will not be removed automatically
* when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
* only resource name and field names with dots separating is allowed here (no repetition
* indicators, FluentPath expressions, etc.)
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
* @see #setStripVersionsFromReferences(boolean)
*/
@SuppressWarnings("unchecked")
public ParserOptions setDontStripVersionsFromReferencesAtPaths(Collection<String> thePaths) {
if (thePaths == null) {
myDontStripVersionsFromReferencesAtPaths = Collections.emptySet();
} else if (thePaths instanceof HashSet) {
myDontStripVersionsFromReferencesAtPaths = (Set<String>) ((HashSet<String>)thePaths).clone();
myDontStripVersionsFromReferencesAtPaths = (Set<String>) ((HashSet<String>) thePaths).clone();
} else {
myDontStripVersionsFromReferencesAtPaths = new HashSet<String>(thePaths);
}
return this;
}
/**
* Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
*
* @see #setDontStripVersionsFromReferencesAtPaths(String...)
* @see #setStripVersionsFromReferences(boolean)
*/
public Set<String> getDontStripVersionsFromReferencesAtPaths() {
return myDontStripVersionsFromReferencesAtPaths;
}
/**
* If set to <code>true</code> (which is the default), the Bundle.entry.fullUrl will override the Bundle.entry.resource's
* resource id if the fullUrl is defined. This behavior happens when parsing the source data into a Bundle object. Set this
@ -152,7 +145,7 @@ public class ParserOptions {
* validation checks between the fullUrl and the resource id).
*
* @return Returns the parser instance's configuration setting for overriding resource ids with Bundle.entry.fullUrl when
* parsing the source data into a Bundle object. Default is <code>true</code>.
* parsing the source data into a Bundle object. Default is <code>true</code>.
*/
public boolean isOverrideResourceIdWithBundleEntryFullUrl() {
return myOverrideResourceIdWithBundleEntryFullUrl;
@ -164,14 +157,13 @@ public class ParserOptions {
* to <code>false</code> if this is not the desired behavior (e.g. the client code wishes to perform additional
* validation checks between the fullUrl and the resource id).
*
* @param theOverrideResourceIdWithBundleEntryFullUrl
* Set this to <code>false</code> to prevent the parser from overriding resource ids with the
* Bundle.entry.fullUrl
*
* @param theOverrideResourceIdWithBundleEntryFullUrl Set this to <code>false</code> to prevent the parser from overriding resource ids with the
* Bundle.entry.fullUrl
* @return Returns a reference to <code>this</code> parser so that method calls can be chained together
*/
public ParserOptions setOverrideResourceIdWithBundleEntryFullUrl(boolean theOverrideResourceIdWithBundleEntryFullUrl) {
myOverrideResourceIdWithBundleEntryFullUrl = theOverrideResourceIdWithBundleEntryFullUrl;
return this;
}
}

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.parser;
* 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.
@ -157,7 +157,6 @@ public abstract class BaseParser implements IParser {
}
private void containResourcesForEncoding(ContainedResources theContained, IBaseResource theResource, IBaseResource theTarget) {
Map<String, IBaseResource> existingIdToContainedResource = null;
if (theTarget instanceof IResource) {
List<? extends IResource> containedResources = ((IResource) theTarget).getContained().getContainedResources();
@ -167,10 +166,7 @@ public abstract class BaseParser implements IParser {
if (!nextId.startsWith("#")) {
nextId = '#' + nextId;
}
if (existingIdToContainedResource == null) {
existingIdToContainedResource = new HashMap<>();
}
existingIdToContainedResource.put(nextId, next);
theContained.getExistingIdToContainedResource().put(nextId, next);
}
}
} else if (theTarget instanceof IDomainResource) {
@ -181,56 +177,46 @@ public abstract class BaseParser implements IParser {
if (!nextId.startsWith("#")) {
nextId = '#' + nextId;
}
if (existingIdToContainedResource == null) {
existingIdToContainedResource = new HashMap<>();
}
existingIdToContainedResource.put(nextId, next);
theContained.getExistingIdToContainedResource().put(nextId, next);
}
}
} else {
// no resources to contain
}
// Make sure we don't reuse local IDs
if (existingIdToContainedResource != null) {
theContained.addPreExistingLocalIds(existingIdToContainedResource.keySet());
List<IBaseReference> allReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
for (IBaseReference next : allReferences) {
IBaseResource resource = next.getResource();
if (resource == null && next.getReferenceElement().isLocal()) {
if (theContained.hasExistingIdToContainedResource()) {
IBaseResource potentialTarget = theContained.getExistingIdToContainedResource().remove(next.getReferenceElement().getValue());
if (potentialTarget != null) {
theContained.addContained(next.getReferenceElement(), potentialTarget);
containResourcesForEncoding(theContained, potentialTarget, theTarget);
}
}
}
}
{
List<IBaseReference> allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
for (IBaseReference next : allElements) {
IBaseResource resource = next.getResource();
if (resource == null && next.getReferenceElement().isLocal()) {
if (existingIdToContainedResource != null) {
IBaseResource potentialTarget = existingIdToContainedResource.remove(next.getReferenceElement().getValue());
if (potentialTarget != null) {
theContained.addContained(next.getReferenceElement(), potentialTarget);
containResourcesForEncoding(theContained, potentialTarget, theTarget);
}
}
}
}
for (IBaseReference next : allElements) {
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);
if (resource.getIdElement().isLocal() && existingIdToContainedResource != null) {
existingIdToContainedResource.remove(resource.getIdElement().getValue());
}
} else {
for (IBaseReference next : allReferences) {
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;
}
containResourcesForEncoding(theContained, resource, theTarget);
theContained.addContained(resource);
if (resource.getIdElement().isLocal() && theContained.hasExistingIdToContainedResource()) {
theContained.getExistingIdToContainedResource().remove(resource.getIdElement().getValue());
}
} else {
continue;
}
containResourcesForEncoding(theContained, resource, theTarget);
}
}
}
@ -238,7 +224,9 @@ public abstract class BaseParser implements IParser {
protected void containResourcesForEncoding(IBaseResource theResource) {
ContainedResources contained = new ContainedResources();
containResourcesForEncoding(contained, theResource, theResource);
contained.assignIdsToContainedResources();
myContainedResources = contained;
}
private String determineReferenceText(IBaseReference theRef, CompositeChildElement theCompositeChildElement) {
@ -940,36 +928,6 @@ public abstract class BaseParser implements IParser {
throw new DataFormatException(nextChild + " has no child of type " + theType);
}
protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
List<? extends T> securityLabels = key.get(resource);
if (securityLabels == null) {
securityLabels = Collections.emptyList();
}
return new ArrayList<T>(securityLabels);
}
static boolean hasExtensions(IBase theElement) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
if (res.getUndeclaredExtensions().size() > 0 || res.getUndeclaredModifierExtensions().size() > 0) {
return true;
}
}
if (theElement instanceof IBaseHasExtensions) {
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
if (res.hasExtension()) {
return true;
}
}
if (theElement instanceof IBaseHasModifierExtensions) {
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
if (res.hasModifierExtension()) {
return true;
}
}
return false;
}
class ChildNameAndDef {
private final BaseRuntimeElementDefinition<?> myChildDef;
@ -1182,7 +1140,14 @@ public abstract class BaseParser implements IParser {
private List<IBaseResource> myResources;
private IdentityHashMap<IBaseResource, IIdType> myResourceToId;
private Set<String> myPreExistingLocalIds;
private Map<String, IBaseResource> myExistingIdToContainedResource;
public Map<String, IBaseResource> getExistingIdToContainedResource() {
if (myExistingIdToContainedResource == null) {
myExistingIdToContainedResource = new HashMap<>();
}
return myExistingIdToContainedResource;
}
public void addContained(IBaseResource theResource) {
initializeMapsIfNeeded();
@ -1194,26 +1159,7 @@ public abstract class BaseParser implements IParser {
if (theResource.getIdElement().isLocal()) {
newId = theResource.getIdElement();
} else {
// TODO: make this configurable between the two below (and something else?)
// newId = new IdDt(UUID.randomUUID().toString());
// Generally we won't even go into this loop once since
// our next ID shouldn't already exist, but there is
// always a chance that it does if someone is mixing
// manually assigned local IDs with HAPI assigned ones
// See JsonParser#testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalFirst
// and JsonParser#testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalLast
// for examples of where this is needed...
while (true) {
String nextCandidate = "#" + myNextContainedId;
if (myPreExistingLocalIds.add(nextCandidate)) {
break;
}
myNextContainedId++;
}
newId = new IdDt(myNextContainedId);
myNextContainedId++;
newId = null;
}
myResourceToId.put(theResource, newId);
@ -1228,11 +1174,6 @@ public abstract class BaseParser implements IParser {
}
}
public void addPreExistingLocalIds(Set<String> theIds) {
initializeMapsIfNeeded();
myPreExistingLocalIds.addAll(theIds);
}
public List<IBaseResource> getContainedResources() {
if (myResources == null) {
return Collections.emptyList();
@ -1251,7 +1192,6 @@ public abstract class BaseParser implements IParser {
if (myResources == null) {
myResources = new ArrayList<>();
myResourceToId = new IdentityHashMap<>();
myPreExistingLocalIds = new HashSet<>();
}
}
@ -1262,6 +1202,83 @@ public abstract class BaseParser implements IParser {
return myResourceToId.isEmpty();
}
public boolean hasExistingIdToContainedResource() {
return myExistingIdToContainedResource != null;
}
public void assignIdsToContainedResources() {
if (myResources != null) {
/*
* The idea with the code block below:
*
* We want to preserve any IDs that were user-assigned, so that if it's really
* important to someone that their contained resource have the ID of #FOO
* or #1 we will keep that.
*
* For any contained resources where no ID was assigned by the user, we
* want to manually create an ID but make sure we don't reuse an existing ID.
*/
Set<String> ids = new HashSet<>();
// Gather any user assigned IDs
for (IBaseResource nextResource : myResources) {
if (myResourceToId.get(nextResource) != null) {
ids.add(myResourceToId.get(nextResource).getValue());
continue;
}
}
// Automatically assign IDs to the rest
for (IBaseResource nextResource : myResources) {
while (myResourceToId.get(nextResource) == null) {
String nextCandidate = "#" + myNextContainedId;
myNextContainedId++;
if (!ids.add(nextCandidate)) {
continue;
}
myResourceToId.put(nextResource, new IdDt(nextCandidate));
}
}
}
}
}
protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
List<? extends T> securityLabels = key.get(resource);
if (securityLabels == null) {
securityLabels = Collections.emptyList();
}
return new ArrayList<>(securityLabels);
}
static boolean hasExtensions(IBase theElement) {
if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
if (res.getUndeclaredExtensions().size() > 0 || res.getUndeclaredModifierExtensions().size() > 0) {
return true;
}
}
if (theElement instanceof IBaseHasExtensions) {
IBaseHasExtensions res = (IBaseHasExtensions) theElement;
if (res.hasExtension()) {
return true;
}
}
if (theElement instanceof IBaseHasModifierExtensions) {
IBaseHasModifierExtensions res = (IBaseHasModifierExtensions) theElement;
if (res.hasModifierExtension()) {
return true;
}
}
return false;
}
}

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.util;
public enum VersionEnum {
V3_4_0,
V3_5_0
V3_5_0,
V3_6_0
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</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.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</dependency>
<!-- Server -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-server</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</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.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2.1</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-r4</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>hapi-deployable-pom</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -11,7 +11,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -10,7 +10,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
* #L%
*/
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.ColumnMapRowMapper;
@ -29,6 +31,7 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
public class ArbitrarySqlTask extends BaseTask<ArbitrarySqlTask> {
@ -37,6 +40,7 @@ public class ArbitrarySqlTask extends BaseTask<ArbitrarySqlTask> {
private final String myDescription;
private List<Task> myTask = new ArrayList<>();
private int myBatchSize = 1000;
private String myExecuteOnlyIfTableExists;
public ArbitrarySqlTask(String theDescription) {
myDescription = theDescription;
@ -55,6 +59,14 @@ public class ArbitrarySqlTask extends BaseTask<ArbitrarySqlTask> {
public void execute() throws SQLException {
ourLog.info("Starting: {}", myDescription);
if (StringUtils.isNotBlank(myExecuteOnlyIfTableExists)) {
Set<String> tableNames = JdbcUtils.getTableNames(getConnectionProperties());
if (!tableNames.contains(myExecuteOnlyIfTableExists.toUpperCase())) {
ourLog.info("Table {} does not exist - No action performed", myExecuteOnlyIfTableExists);
return;
}
}
for (Task next : myTask) {
next.execute();
}
@ -65,6 +77,10 @@ public class ArbitrarySqlTask extends BaseTask<ArbitrarySqlTask> {
myBatchSize = theBatchSize;
}
public void setExecuteOnlyIfTableExists(String theExecuteOnlyIfTableExists) {
myExecuteOnlyIfTableExists = theExecuteOnlyIfTableExists;
}
public enum QueryModeEnum {
BATCH_UNTIL_NO_MORE
}

View File

@ -255,8 +255,11 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
.addIndex("IDX_RESPARMPRESENT_HASHPRES")
.unique(false)
.withColumns("HASH_PRESENCE");
ArbitrarySqlTask consolidateSearchParamPresenceIndexesTask = new ArbitrarySqlTask("Consolidate search parameter presence indexes");
consolidateSearchParamPresenceIndexesTask.setExecuteOnlyIfTableExists("HFJ_SEARCH_PARM");
consolidateSearchParamPresenceIndexesTask.setBatchSize(1);
String sql = "SELECT " +
"HFJ_SEARCH_PARM.RES_TYPE RES_TYPE, HFJ_SEARCH_PARM.PARAM_NAME PARAM_NAME, " +
"HFJ_RES_PARAM_PRESENT.PID PID, HFJ_RES_PARAM_PRESENT.SP_ID SP_ID, HFJ_RES_PARAM_PRESENT.SP_PRESENT SP_PRESENT, HFJ_RES_PARAM_PRESENT.HASH_PRESENCE HASH_PRESENCE " +

View File

@ -8,7 +8,7 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
public class ArbitrarySqlTest extends BaseTest {
public class ArbitrarySqlTaskTest extends BaseTest {
@Test
public void test350MigrateSearchParams() {
@ -20,6 +20,7 @@ public class ArbitrarySqlTest extends BaseTest {
executeSql("insert into HFJ_RES_PARAM_PRESENT (PID, SP_ID, SP_PRESENT, HASH_PRESENT) values (101, 2, true, null)");
ArbitrarySqlTask task = new ArbitrarySqlTask("Consolidate search parameter presence indexes");
task.setExecuteOnlyIfTableExists("hfj_search_parm");
task.setBatchSize(1);
String sql = "SELECT " +
"HFJ_SEARCH_PARM.RES_TYPE RES_TYPE, HFJ_SEARCH_PARM.PARAM_NAME PARAM_NAME, " +
@ -50,4 +51,19 @@ public class ArbitrarySqlTest extends BaseTest {
}
@Test
public void testExecuteOnlyIfTableExists() {
ArbitrarySqlTask task = new ArbitrarySqlTask("Consolidate search parameter presence indexes");
task.setBatchSize(1);
String sql = "SELECT * FROM HFJ_SEARCH_PARM";
task.addQuery(sql, ArbitrarySqlTask.QueryModeEnum.BATCH_UNTIL_NO_MORE, t -> {
task.executeSql("update HFJ_RES_PARAM_PRESENT set FOOFOOOFOO = null");
});
task.setExecuteOnlyIfTableExists("hfj_search_parm");
// No action should be performed
getMigrator().addTask(task);
getMigrator().migrate();
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -158,7 +158,7 @@
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-converter</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</dependency>
</dependencies>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-server-jpa</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -18,6 +18,7 @@ import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder;
import static org.junit.Assert.*;
@SuppressWarnings("Duplicates")
public class XmlParserR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(XmlParserR4Test.class);
private static FhirContext ourCtx = FhirContext.forR4();
@ -162,6 +163,31 @@ public class XmlParserR4Test {
}
@Test
public void testEncodeContainedIdsAreRenumbered() {
DiagnosticReport dr = new DiagnosticReport();
// Put a contained that isn't referenced anywhere
dr.getContained().add(new Specimen().setId("#1"));
// Add a specimen that is actually referenced
Specimen spec = new Specimen();
spec.addNote().setAuthor(new StringType("FOO"));
dr.addSpecimen().setResource(spec);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(dr);
ourLog.info(encoded);
assertThat(encoded, stringContainsInOrder(
"<contained>",
"<id value=\"1\"/>",
"</contained>",
"<reference value=\"#1\"/>"
));
}
/**
* See #11
*/

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -20,7 +20,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<packaging>pom</packaging>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<name>HAPI-FHIR</name>
<description>An open-source implementation of the FHIR specification in Java.</description>
<url>https://hapifhir.io</url>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -8,7 +8,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -6,6 +6,19 @@
<title>HAPI FHIR Changelog</title>
</properties>
<body>
<release version="3.6.0" date="TBD">
<action type="fix">
A bug in the JPA migration tasks from 3.4.0 to 3.5.0 caused a failure if the HFJ_SEARCH_PARM
table did not exist. This table existed in previous versions of HAPI FHIR but was dropped
in 3.5.0, meaning that migrations would fail if the database was created using a snapshot
version of 3.5.0.
</action>
<action type="fix">
Automatic ID generation for contained resources (in cases where the user hasn't manually specified an ID)
has been streamlined to generate more predictable IDs in some cases.
</action>
</release>
<release version="3.5.0" date="2018-09-17">
<action type="add">
HAPI FHIR now supports JDK 9 and JDK 10, both for building HAPI FHIR

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.5.0</version>
<version>3.6.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>