Implement DSTU2 transaction semantics in JPA
This commit is contained in:
parent
1f958221a7
commit
5600ba6763
|
@ -41,7 +41,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
@ -210,9 +211,14 @@ public class Bundle extends BaseBundle /* implements IElement */{
|
|||
entry.getLinkAlternate().setValue(linkSearch);
|
||||
}
|
||||
|
||||
BundleEntryStatusEnum entryStatus = ResourceMetadataKeyEnum.ENTRY_STATUS.get(theResource);
|
||||
BundleEntrySearchModeEnum entryStatus = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(theResource);
|
||||
if (entryStatus != null) {
|
||||
entry.getStatus().setValueAsEnum(entryStatus);
|
||||
entry.getSearchMode().setValueAsEnum(entryStatus);
|
||||
}
|
||||
|
||||
BundleEntryTransactionOperationEnum entryTransactionOperation = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(theResource);
|
||||
if (entryTransactionOperation != null) {
|
||||
entry.getTransactionOperation().setValueAsEnum(entryTransactionOperation);
|
||||
}
|
||||
|
||||
DecimalDt entryScore = ResourceMetadataKeyEnum.ENTRY_SCORE.get(theResource);
|
||||
|
|
|
@ -31,7 +31,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
|
||||
public class BundleEntry extends BaseBundle {
|
||||
|
@ -56,7 +57,8 @@ public class BundleEntry extends BaseBundle {
|
|||
private InstantDt myPublished;
|
||||
private IResource myResource;
|
||||
private DecimalDt myScore;
|
||||
private BoundCodeDt<BundleEntryStatusEnum> myStatus;
|
||||
private BoundCodeDt<BundleEntrySearchModeEnum> mySearchMode;
|
||||
private BoundCodeDt<BundleEntryTransactionOperationEnum> myTransactionOperation;
|
||||
private XhtmlDt mySummary;
|
||||
private StringDt myTitle;
|
||||
private InstantDt myUpdated;
|
||||
|
@ -197,12 +199,6 @@ public class BundleEntry extends BaseBundle {
|
|||
return myScore;
|
||||
}
|
||||
|
||||
public BoundCodeDt<BundleEntryStatusEnum> getStatus() {
|
||||
if (myStatus == null) {
|
||||
myStatus = new BoundCodeDt<BundleEntryStatusEnum>(BundleEntryStatusEnum.VALUESET_BINDER);
|
||||
}
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
public XhtmlDt getSummary() {
|
||||
if (mySummary == null) {
|
||||
|
@ -243,7 +239,7 @@ public class BundleEntry extends BaseBundle {
|
|||
return super.isEmpty() &&
|
||||
ElementUtil.isEmpty(
|
||||
myDeletedResourceId, myDeletedResourceType, myDeletedResourceVersion, myDeletedAt,
|
||||
myScore, myStatus, myCategories,
|
||||
myScore, mySearchMode, myTransactionOperation, myCategories,
|
||||
myLinkAlternate, myLinkSelf, myPublished, myResource, mySummary,
|
||||
myTitle, myUpdated, myDeletedByEmail, myDeletedByName, myDeletedComment);
|
||||
//@formatter:on
|
||||
|
@ -326,9 +322,6 @@ public class BundleEntry extends BaseBundle {
|
|||
myScore = theScore;
|
||||
}
|
||||
|
||||
public void setStatus(BoundCodeDt<BundleEntryStatusEnum> theStatus) {
|
||||
myStatus = theStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated <b>DSTU2 Note:</b> As of DSTU2, bundle entries no longer have an updated time (this bit of metadata
|
||||
|
@ -353,4 +346,29 @@ public class BundleEntry extends BaseBundle {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
public BoundCodeDt<BundleEntrySearchModeEnum> getSearchMode() {
|
||||
if (mySearchMode == null) {
|
||||
mySearchMode = new BoundCodeDt<BundleEntrySearchModeEnum>(BundleEntrySearchModeEnum.VALUESET_BINDER);
|
||||
}
|
||||
return mySearchMode;
|
||||
}
|
||||
|
||||
public void setSearchMode(BoundCodeDt<BundleEntrySearchModeEnum> theSearchMode) {
|
||||
mySearchMode = theSearchMode;
|
||||
}
|
||||
|
||||
public BoundCodeDt<BundleEntryTransactionOperationEnum> getTransactionOperation() {
|
||||
if (myTransactionOperation == null) {
|
||||
myTransactionOperation = new BoundCodeDt<BundleEntryTransactionOperationEnum>(BundleEntryTransactionOperationEnum.VALUESET_BINDER);
|
||||
}
|
||||
return myTransactionOperation;
|
||||
}
|
||||
|
||||
public void setTransactionOperation(BoundCodeDt<BundleEntryTransactionOperationEnum> theTransactionOperation) {
|
||||
myTransactionOperation = theTransactionOperation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ import ca.uhn.fhir.model.primitive.DecimalDt;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
/**
|
||||
|
@ -294,26 +294,55 @@ public abstract class ResourceMetadataKeyEnum<T> {
|
|||
};
|
||||
|
||||
/**
|
||||
* If present and populated with a {@link BundleEntryStatusEnum}, contains the "bundle entry status",
|
||||
* which is the value of the status field in the Bundle.entry containing this resource. This value can be
|
||||
* If present and populated with a {@link BundleEntrySearchModeEnum}, contains the "bundle entry search mode",
|
||||
* which is the value of the status field in the Bundle entry containing this resource. The value for this key
|
||||
* corresponds to field <code>Bundle.entry.search.mode</code>.
|
||||
* This value can be
|
||||
* set to provide a status value of "include" for included resources being returned by a server, or to
|
||||
* set the value on a transaction, etc.
|
||||
* "match" to indicate that the resource was returned because it matched the given search criteria.
|
||||
* <p>
|
||||
* Note that status is only used in FHIR DSTU2 and later.
|
||||
* </p>
|
||||
* <p>
|
||||
* Values for this key are of type <b>{@link BundleEntryStatusEnum}</b>
|
||||
* Values for this key are of type <b>{@link BundleEntrySearchModeEnum}</b>
|
||||
* </p>
|
||||
*/
|
||||
public static final ResourceMetadataKeyEnum<BundleEntryStatusEnum> ENTRY_STATUS = new ResourceMetadataKeyEnum<BundleEntryStatusEnum>("ENTRY_STATUS") {
|
||||
public static final ResourceMetadataKeyEnum<BundleEntrySearchModeEnum> ENTRY_SEARCH_MODE = new ResourceMetadataKeyEnum<BundleEntrySearchModeEnum>("ENTRY_SEARCH_MODE") {
|
||||
@Override
|
||||
public BundleEntryStatusEnum get(IResource theResource) {
|
||||
return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_STATUS, BundleEntryStatusEnum.class, BundleEntryStatusEnum.VALUESET_BINDER);
|
||||
public BundleEntrySearchModeEnum get(IResource theResource) {
|
||||
return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_SEARCH_MODE, BundleEntrySearchModeEnum.class, BundleEntrySearchModeEnum.VALUESET_BINDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(IResource theResource, BundleEntryStatusEnum theObject) {
|
||||
theResource.getResourceMetadata().put(ENTRY_STATUS, theObject);
|
||||
public void put(IResource theResource, BundleEntrySearchModeEnum theObject) {
|
||||
theResource.getResourceMetadata().put(ENTRY_SEARCH_MODE, theObject);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If present and populated with a {@link BundleEntryTransactionOperationEnum}, contains the "bundle entry transaction operation",
|
||||
* which is the value of the status field in the Bundle entry containing this resource. The value for this key
|
||||
* corresponds to field <code>Bundle.entry.transaction.operation</code>.
|
||||
* This value can be
|
||||
* set in resources being transmitted to a server to provide a status value of "create" or "update" to indicate behaviour the
|
||||
* server should observe. It may also be set to similar values (or to "noop") in resources being returned by
|
||||
* a server as a result of a transaction to indicate to the client what operation was actually performed.
|
||||
* <p>
|
||||
* Note that status is only used in FHIR DSTU2 and later.
|
||||
* </p>
|
||||
* <p>
|
||||
* Values for this key are of type <b>{@link BundleEntryTransactionOperationEnum}</b>
|
||||
* </p>
|
||||
*/
|
||||
public static final ResourceMetadataKeyEnum<BundleEntryTransactionOperationEnum> ENTRY_TRANSACTION_OPERATION = new ResourceMetadataKeyEnum<BundleEntryTransactionOperationEnum>("ENTRY_TRANSACTION_OPERATION") {
|
||||
@Override
|
||||
public BundleEntryTransactionOperationEnum get(IResource theResource) {
|
||||
return getEnumFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ENTRY_TRANSACTION_OPERATION, BundleEntryTransactionOperationEnum.class, BundleEntryTransactionOperationEnum.VALUESET_BINDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(IResource theResource, BundleEntryTransactionOperationEnum theObject) {
|
||||
theResource.getResourceMetadata().put(ENTRY_TRANSACTION_OPERATION, theObject);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -26,12 +26,10 @@ import java.util.Map;
|
|||
|
||||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
|
||||
public enum BundleEntryStatusEnum {
|
||||
public enum BundleEntrySearchModeEnum {
|
||||
|
||||
CREATE("create", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
UPDATE("update", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
MATCH("match", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
INCLUDE("include", "http://hl7.org/fhir/bundle-entry-status"),
|
||||
MATCH("match", "http://hl7.org/fhir/search-entry-mode"),
|
||||
INCLUDE("include", "http://hl7.org/fhir/search-entry-mode"),
|
||||
|
||||
;
|
||||
|
||||
|
@ -47,18 +45,18 @@ public enum BundleEntryStatusEnum {
|
|||
*/
|
||||
public static final String VALUESET_NAME = "BundleEntryStatus";
|
||||
|
||||
private static Map<String, BundleEntryStatusEnum> CODE_TO_ENUM = new HashMap<String, BundleEntryStatusEnum>();
|
||||
private static Map<String, Map<String, BundleEntryStatusEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, BundleEntryStatusEnum>>();
|
||||
private static Map<String, BundleEntrySearchModeEnum> CODE_TO_ENUM = new HashMap<String, BundleEntrySearchModeEnum>();
|
||||
private static Map<String, Map<String, BundleEntrySearchModeEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, BundleEntrySearchModeEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (BundleEntryStatusEnum next : BundleEntryStatusEnum.values()) {
|
||||
for (BundleEntrySearchModeEnum next : BundleEntrySearchModeEnum.values()) {
|
||||
CODE_TO_ENUM.put(next.getCode(), next);
|
||||
|
||||
if (!SYSTEM_TO_CODE_TO_ENUM.containsKey(next.getSystem())) {
|
||||
SYSTEM_TO_CODE_TO_ENUM.put(next.getSystem(), new HashMap<String, BundleEntryStatusEnum>());
|
||||
SYSTEM_TO_CODE_TO_ENUM.put(next.getSystem(), new HashMap<String, BundleEntrySearchModeEnum>());
|
||||
}
|
||||
SYSTEM_TO_CODE_TO_ENUM.get(next.getSystem()).put(next.getCode(), next);
|
||||
}
|
||||
|
@ -81,33 +79,33 @@ public enum BundleEntryStatusEnum {
|
|||
/**
|
||||
* Returns the enumerated value associated with this code
|
||||
*/
|
||||
public BundleEntryStatusEnum forCode(String theCode) {
|
||||
BundleEntryStatusEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
public BundleEntrySearchModeEnum forCode(String theCode) {
|
||||
BundleEntrySearchModeEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<BundleEntryStatusEnum> VALUESET_BINDER = new IValueSetEnumBinder<BundleEntryStatusEnum>() {
|
||||
public static final IValueSetEnumBinder<BundleEntrySearchModeEnum> VALUESET_BINDER = new IValueSetEnumBinder<BundleEntrySearchModeEnum>() {
|
||||
@Override
|
||||
public String toCodeString(BundleEntryStatusEnum theEnum) {
|
||||
public String toCodeString(BundleEntrySearchModeEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(BundleEntryStatusEnum theEnum) {
|
||||
public String toSystemString(BundleEntrySearchModeEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryStatusEnum fromCodeString(String theCodeString) {
|
||||
public BundleEntrySearchModeEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryStatusEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, BundleEntryStatusEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
public BundleEntrySearchModeEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, BundleEntrySearchModeEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -119,7 +117,7 @@ public enum BundleEntryStatusEnum {
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
BundleEntryStatusEnum(String theCode, String theSystem) {
|
||||
BundleEntrySearchModeEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
package ca.uhn.fhir.model.valueset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
|
||||
|
||||
public enum BundleEntryTransactionOperationEnum {
|
||||
|
||||
CREATE("create", "http://hl7.org/fhir/restful-interaction"),
|
||||
UPDATE("update", "http://hl7.org/fhir/restful-interaction"),
|
||||
DELETE("delete", "http://hl7.org/fhir/restful-interaction"),
|
||||
NOOP("noop", "http://hl7.org/fhir/transaction-operation"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Identifier for this Value Set:
|
||||
* http://hl7.org/fhir/vs/address-use
|
||||
*/
|
||||
public static final String VALUESET_IDENTIFIER = "http://hl7.org/fhir/bundle-entry-status";
|
||||
|
||||
/**
|
||||
* Name for this Value Set:
|
||||
* AddressUse
|
||||
*/
|
||||
public static final String VALUESET_NAME = "BundleEntryStatus";
|
||||
|
||||
private static Map<String, BundleEntryTransactionOperationEnum> CODE_TO_ENUM = new HashMap<String, BundleEntryTransactionOperationEnum>();
|
||||
private static Map<String, Map<String, BundleEntryTransactionOperationEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, BundleEntryTransactionOperationEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (BundleEntryTransactionOperationEnum next : BundleEntryTransactionOperationEnum.values()) {
|
||||
CODE_TO_ENUM.put(next.getCode(), next);
|
||||
|
||||
if (!SYSTEM_TO_CODE_TO_ENUM.containsKey(next.getSystem())) {
|
||||
SYSTEM_TO_CODE_TO_ENUM.put(next.getSystem(), new HashMap<String, BundleEntryTransactionOperationEnum>());
|
||||
}
|
||||
SYSTEM_TO_CODE_TO_ENUM.get(next.getSystem()).put(next.getCode(), next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code associated with this enumerated value
|
||||
*/
|
||||
public String getCode() {
|
||||
return myCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code system associated with this enumerated value
|
||||
*/
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enumerated value associated with this code
|
||||
*/
|
||||
public BundleEntryTransactionOperationEnum forCode(String theCode) {
|
||||
BundleEntryTransactionOperationEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<BundleEntryTransactionOperationEnum> VALUESET_BINDER = new IValueSetEnumBinder<BundleEntryTransactionOperationEnum>() {
|
||||
@Override
|
||||
public String toCodeString(BundleEntryTransactionOperationEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(BundleEntryTransactionOperationEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryTransactionOperationEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BundleEntryTransactionOperationEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, BundleEntryTransactionOperationEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(theCodeString);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
BundleEntryTransactionOperationEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -273,9 +273,21 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeStartObject();
|
||||
|
||||
writeOptionalTagWithTextNode(theEventWriter, "base", determineResourceBaseUrl(theBundle.getLinkBase().getValue(), nextEntry));
|
||||
writeOptionalTagWithTextNode(theEventWriter, "status", nextEntry.getStatus());
|
||||
writeOptionalTagWithTextNode(theEventWriter, "search", nextEntry.getLinkSearch());
|
||||
writeOptionalTagWithDecimalNode(theEventWriter, "score", nextEntry.getScore());
|
||||
|
||||
if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
|
||||
theEventWriter.writeStartObject("search");
|
||||
writeOptionalTagWithTextNode(theEventWriter, "mode", nextEntry.getSearchMode().getValueAsString());
|
||||
writeOptionalTagWithDecimalNode(theEventWriter, "score", nextEntry.getScore());
|
||||
theEventWriter.writeEnd();
|
||||
// IResource nextResource = nextEntry.getResource();
|
||||
}
|
||||
|
||||
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
||||
theEventWriter.writeStartObject("transaction");
|
||||
writeOptionalTagWithTextNode(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue());
|
||||
writeOptionalTagWithTextNode(theEventWriter, "match", nextEntry.getLinkSearch().getValue());
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
boolean deleted = nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false;
|
||||
if (deleted) {
|
||||
|
|
|
@ -950,10 +950,10 @@ class ParserState<T> {
|
|||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("base".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getLinkBase()));
|
||||
} else if ("status".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getStatus()));
|
||||
} else if ("transaction".equals(theLocalPart)) {
|
||||
push(new BundleEntryTransactionState(myEntry));
|
||||
} else if ("search".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getLinkSearch()));
|
||||
push(new BundleEntrySearchState(myEntry));
|
||||
} else if ("score".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getScore()));
|
||||
} else if ("resource".equals(theLocalPart)) {
|
||||
|
@ -1013,16 +1013,74 @@ class ParserState<T> {
|
|||
if (!myEntry.getLinkSearch().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(myEntry.getResource(), myEntry.getLinkSearch().getValue());
|
||||
}
|
||||
if (!myEntry.getStatus().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.ENTRY_STATUS.put(myEntry.getResource(), myEntry.getStatus().getValueAsEnum());
|
||||
if (!myEntry.getSearchMode().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(myEntry.getResource(), myEntry.getSearchMode().getValueAsEnum());
|
||||
}
|
||||
if (!myEntry.getStatus().isEmpty()) {
|
||||
if (!myEntry.getTransactionOperation().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(myEntry.getResource(), myEntry.getTransactionOperation().getValueAsEnum());
|
||||
}
|
||||
if (!myEntry.getScore().isEmpty()) {
|
||||
ResourceMetadataKeyEnum.ENTRY_SCORE.put(myEntry.getResource(), myEntry.getScore());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class BundleEntrySearchState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
||||
public BundleEntrySearchState(BundleEntry theEntry) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("mode".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getSearchMode()));
|
||||
} else if ("score".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getScore()));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element in Bundle.entry.search: " + theLocalPart);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class BundleEntryTransactionState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
||||
public BundleEntryTransactionState(BundleEntry theEntry) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() throws DataFormatException {
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("operation".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getTransactionOperation()));
|
||||
} else if ("match".equals(theLocalPart)) {
|
||||
push(new PrimitiveState(getPreResourceState(), myEntry.getLinkSearch()));
|
||||
} else {
|
||||
throw new DataFormatException("Unexpected element in Bundle.entry.search: " + theLocalPart);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class BundleLinkState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
|
|
|
@ -86,12 +86,12 @@ import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
|||
import ca.uhn.fhir.util.XmlUtil;
|
||||
|
||||
public class XmlParser extends BaseParser implements IParser {
|
||||
static final String RESREF_DISPLAY = "display";
|
||||
static final String RESREF_REFERENCE = "reference";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
|
||||
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
||||
static final String FHIR_NS = "http://hl7.org/fhir";
|
||||
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParser.class);
|
||||
static final String RESREF_DISPLAY = "display";
|
||||
static final String RESREF_REFERENCE = "reference";
|
||||
static final String TOMBSTONES_NS = "http://purl.org/atompub/tombstones/1.0";
|
||||
static final String XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
|
@ -109,6 +109,109 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
private XMLEventReader createStreamReader(Reader theReader) {
|
||||
try {
|
||||
return XmlUtil.createXmlReader(theReader);
|
||||
} catch (FactoryConfigurationError e1) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e1);
|
||||
} catch (XMLStreamException e1) {
|
||||
throw new DataFormatException(e1);
|
||||
}
|
||||
|
||||
// XMLEventReader streamReader;
|
||||
// try {
|
||||
// streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||
// } catch (XMLStreamException e) {
|
||||
// throw new DataFormatException(e);
|
||||
// } catch (FactoryConfigurationError e) {
|
||||
// throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
// }
|
||||
// return streamReader;
|
||||
}
|
||||
|
||||
private XMLStreamWriter createXmlWriter(Writer theWriter) throws XMLStreamException {
|
||||
XMLStreamWriter eventWriter;
|
||||
eventWriter = XmlUtil.createXmlStreamWriter(theWriter);
|
||||
eventWriter = decorateStreamWriter(eventWriter);
|
||||
return eventWriter;
|
||||
}
|
||||
|
||||
private XMLStreamWriter decorateStreamWriter(XMLStreamWriter eventWriter) {
|
||||
if (myPrettyPrint) {
|
||||
PrettyPrintWriterWrapper retVal = new PrettyPrintWriterWrapper(eventWriter);
|
||||
return retVal;
|
||||
} else {
|
||||
NonPrettyPrintWriterWrapper retVal = new NonPrettyPrintWriterWrapper(eventWriter);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState) {
|
||||
ourLog.trace("Entering XML parsing loop with state: {}", parserState);
|
||||
|
||||
try {
|
||||
while (streamReader.hasNext()) {
|
||||
XMLEvent nextEvent = streamReader.nextEvent();
|
||||
try {
|
||||
if (nextEvent.isStartElement()) {
|
||||
StartElement elem = nextEvent.asStartElement();
|
||||
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
|
||||
if ("extension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), false);
|
||||
} else if ("modifierExtension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), true);
|
||||
|
||||
} else {
|
||||
|
||||
String elementName = elem.getName().getLocalPart();
|
||||
parserState.enteringNewElement(namespaceURI, elementName);
|
||||
|
||||
}
|
||||
|
||||
for (@SuppressWarnings("unchecked")
|
||||
Iterator<Attribute> iter = elem.getAttributes(); iter.hasNext();) {
|
||||
Attribute next = iter.next();
|
||||
// if
|
||||
// (next.getName().getLocalPart().equals("value")) {
|
||||
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
||||
// }
|
||||
}
|
||||
|
||||
} else if (nextEvent.isAttribute()) {
|
||||
Attribute elem = (Attribute) nextEvent;
|
||||
String name = (elem.getName().getLocalPart());
|
||||
parserState.attributeValue(name, elem.getValue());
|
||||
} else if (nextEvent.isEndElement()) {
|
||||
parserState.endingElement();
|
||||
if (parserState.isComplete()) {
|
||||
return parserState.getObject();
|
||||
}
|
||||
} else if (nextEvent.isCharacters()) {
|
||||
parserState.string(nextEvent.asCharacters().getData());
|
||||
}
|
||||
|
||||
parserState.xmlEvent(nextEvent);
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new DataFormatException("DataFormatException at [" + nextEvent.getLocation().toString() + "]: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
|
@ -122,16 +225,16 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
try {
|
||||
XMLStreamWriter eventWriter = createXmlWriter(theWriter);
|
||||
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
encodeBundleToWriterUsingBundleResource(theBundle, eventWriter);
|
||||
encodeBundleToWriterDstu2(theBundle, eventWriter);
|
||||
} else {
|
||||
encodeBundleToWriterUsingAtom(theBundle, eventWriter);
|
||||
encodeBundleToWriterDstu1(theBundle, eventWriter);
|
||||
}
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeBundleToWriterUsingAtom(Bundle theBundle, XMLStreamWriter eventWriter) throws XMLStreamException {
|
||||
private void encodeBundleToWriterDstu1(Bundle theBundle, XMLStreamWriter eventWriter) throws XMLStreamException {
|
||||
eventWriter.writeStartElement("feed");
|
||||
eventWriter.writeDefaultNamespace(ATOM_NS);
|
||||
|
||||
|
@ -250,13 +353,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
eventWriter.close();
|
||||
}
|
||||
|
||||
private void writeOptionalAttribute(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theValue)) {
|
||||
theEventWriter.writeAttribute(theName, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeBundleToWriterUsingBundleResource(Bundle theBundle, XMLStreamWriter theEventWriter) throws XMLStreamException {
|
||||
private void encodeBundleToWriterDstu2(Bundle theBundle, XMLStreamWriter theEventWriter) throws XMLStreamException {
|
||||
theEventWriter.writeStartElement("Bundle");
|
||||
theEventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
|
@ -288,12 +385,22 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
theEventWriter.writeStartElement("entry");
|
||||
|
||||
IResource nextResource = nextEntry.getResource();
|
||||
writeOptionalTagWithValue(theEventWriter, "base", determineResourceBaseUrl(bundleBaseUrl, nextEntry));
|
||||
|
||||
writeOptionalTagWithValue(theEventWriter, "status", nextEntry.getStatus().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "search", nextEntry.getLinkSearch().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "score", nextEntry.getScore().getValueAsString());
|
||||
if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
|
||||
theEventWriter.writeStartElement("search");
|
||||
writeOptionalTagWithValue(theEventWriter, "mode", nextEntry.getSearchMode().getValueAsString());
|
||||
writeOptionalTagWithValue(theEventWriter, "score", nextEntry.getScore().getValueAsString());
|
||||
theEventWriter.writeEndElement();
|
||||
// IResource nextResource = nextEntry.getResource();
|
||||
}
|
||||
|
||||
if (nextEntry.getTransactionOperation().isEmpty() == false || nextEntry.getLinkSearch().isEmpty() == false) {
|
||||
theEventWriter.writeStartElement("transaction");
|
||||
writeOptionalTagWithValue(theEventWriter, "operation", nextEntry.getTransactionOperation().getValue());
|
||||
writeOptionalTagWithValue(theEventWriter, "match", nextEntry.getLinkSearch().getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
boolean deleted = false;
|
||||
if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
|
||||
|
@ -322,225 +429,6 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.close();
|
||||
}
|
||||
|
||||
private void writeBundleResourceLink(XMLStreamWriter theEventWriter, String theRel, StringDt theUrl) throws XMLStreamException {
|
||||
if (theUrl.isEmpty() == false) {
|
||||
theEventWriter.writeStartElement("link");
|
||||
theEventWriter.writeStartElement("relation");
|
||||
theEventWriter.writeAttribute("value", theRel);
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeStartElement("url");
|
||||
theEventWriter.writeAttribute("value", theUrl.getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithValue(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theValue)) {
|
||||
theEventWriter.writeStartElement(theName);
|
||||
theEventWriter.writeAttribute("value", theValue);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
|
||||
if (categories != null) {
|
||||
for (Tag next : categories) {
|
||||
eventWriter.writeStartElement("category");
|
||||
eventWriter.writeAttribute("term", defaultString(next.getTerm()));
|
||||
eventWriter.writeAttribute("label", defaultString(next.getLabel()));
|
||||
eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeResourceToString(IBaseResource theResource) throws DataFormatException {
|
||||
if (theResource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
Writer stringWriter = new StringWriter();
|
||||
encodeResourceToWriter(theResource, stringWriter);
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws DataFormatException {
|
||||
XMLStreamWriter eventWriter;
|
||||
try {
|
||||
eventWriter = createXmlWriter(theWriter);
|
||||
|
||||
encodeResourceToXmlStreamWriter(theResource, eventWriter, false);
|
||||
eventWriter.flush();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
private XMLStreamWriter createXmlWriter(Writer theWriter) throws XMLStreamException {
|
||||
XMLStreamWriter eventWriter;
|
||||
eventWriter = XmlUtil.createXmlStreamWriter(theWriter);
|
||||
eventWriter = decorateStreamWriter(eventWriter);
|
||||
return eventWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException {
|
||||
try {
|
||||
XMLStreamWriter eventWriter = createXmlWriter(theWriter);
|
||||
|
||||
eventWriter.writeStartElement(TagList.ELEMENT_NAME_LC);
|
||||
eventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
for (Tag next : theTagList) {
|
||||
eventWriter.writeStartElement(TagList.ATTR_CATEGORY);
|
||||
|
||||
if (isNotBlank(next.getTerm())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_TERM, next.getTerm());
|
||||
}
|
||||
if (isNotBlank(next.getLabel())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_LABEL, next.getLabel());
|
||||
}
|
||||
if (isNotBlank(next.getScheme())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_SCHEME, next.getScheme());
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
eventWriter.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
return parseBundle(streamReader, theResourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
return parseResource(theResourceType, streamReader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagList parseTagList(Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
ParserState<TagList> parserState = ParserState.getPreTagListInstance(myContext, false);
|
||||
return doXmlLoop(streamReader, parserState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
return this;
|
||||
}
|
||||
|
||||
private XMLEventReader createStreamReader(Reader theReader) {
|
||||
try {
|
||||
return XmlUtil.createXmlReader(theReader);
|
||||
} catch (FactoryConfigurationError e1) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e1);
|
||||
} catch (XMLStreamException e1) {
|
||||
throw new DataFormatException(e1);
|
||||
}
|
||||
|
||||
// XMLEventReader streamReader;
|
||||
// try {
|
||||
// streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||
// } catch (XMLStreamException e) {
|
||||
// throw new DataFormatException(e);
|
||||
// } catch (FactoryConfigurationError e) {
|
||||
// throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
// }
|
||||
// return streamReader;
|
||||
}
|
||||
|
||||
private XMLStreamWriter decorateStreamWriter(XMLStreamWriter eventWriter) {
|
||||
if (myPrettyPrint) {
|
||||
PrettyPrintWriterWrapper retVal = new PrettyPrintWriterWrapper(eventWriter);
|
||||
return retVal;
|
||||
} else {
|
||||
NonPrettyPrintWriterWrapper retVal = new NonPrettyPrintWriterWrapper(eventWriter);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState) {
|
||||
ourLog.trace("Entering XML parsing loop with state: {}", parserState);
|
||||
|
||||
try {
|
||||
while (streamReader.hasNext()) {
|
||||
XMLEvent nextEvent = streamReader.nextEvent();
|
||||
try {
|
||||
if (nextEvent.isStartElement()) {
|
||||
StartElement elem = nextEvent.asStartElement();
|
||||
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
|
||||
if ("extension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), false);
|
||||
} else if ("modifierExtension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue(), true);
|
||||
|
||||
} else {
|
||||
|
||||
String elementName = elem.getName().getLocalPart();
|
||||
parserState.enteringNewElement(namespaceURI, elementName);
|
||||
|
||||
}
|
||||
|
||||
for (@SuppressWarnings("unchecked")
|
||||
Iterator<Attribute> iter = elem.getAttributes(); iter.hasNext();) {
|
||||
Attribute next = iter.next();
|
||||
// if
|
||||
// (next.getName().getLocalPart().equals("value")) {
|
||||
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
||||
// }
|
||||
}
|
||||
|
||||
} else if (nextEvent.isAttribute()) {
|
||||
Attribute elem = (Attribute) nextEvent;
|
||||
String name = (elem.getName().getLocalPart());
|
||||
parserState.attributeValue(name, elem.getValue());
|
||||
} else if (nextEvent.isEndElement()) {
|
||||
parserState.endingElement();
|
||||
if (parserState.isComplete()) {
|
||||
return parserState.getObject();
|
||||
}
|
||||
} else if (nextEvent.isCharacters()) {
|
||||
parserState.string(nextEvent.asCharacters().getData());
|
||||
}
|
||||
|
||||
parserState.xmlEvent(nextEvent);
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new DataFormatException("DataFormatException at [" + nextEvent.getLocation().toString() + "]: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theEventWriter, IBase nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl, boolean theIncludedResource)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
if (nextValue.isEmpty()) {
|
||||
|
@ -586,16 +474,11 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
case CONTAINED_RESOURCES: {
|
||||
ContainedDt value = (ContainedDt) nextValue;
|
||||
/*
|
||||
* Disable per #103
|
||||
for (IResource next : value.getContainedResources()) {
|
||||
if (getContainedResources().getResourceId(next) != null) {
|
||||
continue;
|
||||
}
|
||||
theEventWriter.writeStartElement("contained");
|
||||
encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(next.getId().getValue()));
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
*/
|
||||
* Disable per #103 for (IResource next : value.getContainedResources()) { if
|
||||
* (getContainedResources().getResourceId(next) != null) { continue; }
|
||||
* theEventWriter.writeStartElement("contained"); encodeResourceToXmlStreamWriter(next, theEventWriter,
|
||||
* true, fixContainedResourceId(next.getId().getValue())); theEventWriter.writeEndElement(); }
|
||||
*/
|
||||
for (IBaseResource next : getContainedResources().getContainedResources()) {
|
||||
IdDt resourceId = getContainedResources().getResourceId(next);
|
||||
theEventWriter.writeStartElement("contained");
|
||||
|
@ -697,6 +580,35 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(), theIncludedResource);
|
||||
}
|
||||
|
||||
private void encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredExtensions(), "extension", theIncludedResource);
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension", theIncludedResource);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, ResourceReferenceDt theRef) throws XMLStreamException {
|
||||
String reference = determineReferenceText(theRef);
|
||||
|
||||
if (StringUtils.isNotBlank(reference)) {
|
||||
theEventWriter.writeStartElement(RESREF_REFERENCE);
|
||||
theEventWriter.writeAttribute("value", reference);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
if (!(theRef.getDisplay().isEmpty())) {
|
||||
theEventWriter.writeStartElement(RESREF_DISPLAY);
|
||||
theEventWriter.writeAttribute("value", theRef.getDisplay().getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeResourceToStreamWriterInDstu2Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
/*
|
||||
* DSTU2 requires extensions to come in a specific spot within the encoded content - This is a bit of a messy
|
||||
|
@ -724,32 +636,27 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
encodeExtensionsIfPresent(theResDef, theResource, theEventWriter, theElement, theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions(), theIncludedResource);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren(), theIncludedResource);
|
||||
@Override
|
||||
public String encodeResourceToString(IBaseResource theResource) throws DataFormatException {
|
||||
if (theResource == null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
Writer stringWriter = new StringWriter();
|
||||
encodeResourceToWriter(theResource, stringWriter);
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
private void encodeExtensionsIfPresent(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, IBase theElement, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions res = (ISupportsUndeclaredExtensions) theElement;
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredExtensions(), "extension", theIncludedResource);
|
||||
encodeUndeclaredExtensions(theResDef, theResource, theWriter, res.getUndeclaredModifierExtensions(), "modifierExtension", theIncludedResource);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws DataFormatException {
|
||||
XMLStreamWriter eventWriter;
|
||||
try {
|
||||
eventWriter = createXmlWriter(theWriter);
|
||||
|
||||
private void encodeResourceReferenceToStreamWriter(XMLStreamWriter theEventWriter, ResourceReferenceDt theRef) throws XMLStreamException {
|
||||
String reference = determineReferenceText(theRef);
|
||||
|
||||
if (StringUtils.isNotBlank(reference)) {
|
||||
theEventWriter.writeStartElement(RESREF_REFERENCE);
|
||||
theEventWriter.writeAttribute("value", reference);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
if (!(theRef.getDisplay().isEmpty())) {
|
||||
theEventWriter.writeStartElement(RESREF_DISPLAY);
|
||||
theEventWriter.writeAttribute("value", theRef.getDisplay().getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
encodeResourceToXmlStreamWriter(theResource, eventWriter, false);
|
||||
eventWriter.flush();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,6 +743,37 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException {
|
||||
try {
|
||||
XMLStreamWriter eventWriter = createXmlWriter(theWriter);
|
||||
|
||||
eventWriter.writeStartElement(TagList.ELEMENT_NAME_LC);
|
||||
eventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
||||
for (Tag next : theTagList) {
|
||||
eventWriter.writeStartElement(TagList.ATTR_CATEGORY);
|
||||
|
||||
if (isNotBlank(next.getTerm())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_TERM, next.getTerm());
|
||||
}
|
||||
if (isNotBlank(next.getLabel())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_LABEL, next.getLabel());
|
||||
}
|
||||
if (isNotBlank(next.getScheme())) {
|
||||
eventWriter.writeAttribute(Tag.ATTR_SCHEME, next.getScheme());
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
eventWriter.writeEndElement();
|
||||
eventWriter.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeUndeclaredExtensions(RuntimeResourceDefinition theResDef, IBaseResource theResource, XMLStreamWriter theWriter, List<ExtensionDt> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (ExtensionDt next : theExtensions) {
|
||||
theWriter.writeStartElement(tagName);
|
||||
|
@ -970,16 +908,44 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
return parseBundle(streamReader, theResourceType);
|
||||
}
|
||||
|
||||
private Bundle parseBundle(XMLEventReader theStreamReader, Class<? extends IBaseResource> theResourceType) {
|
||||
ParserState<Bundle> parserState = ParserState.getPreAtomInstance(myContext, theResourceType, false);
|
||||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
return parseResource(theResourceType, streamReader);
|
||||
}
|
||||
|
||||
private <T extends IBaseResource> T parseResource(Class<T> theResourceType, XMLEventReader theStreamReader) {
|
||||
ParserState<T> parserState = ParserState.getPreResourceInstance(theResourceType, myContext, false);
|
||||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagList parseTagList(Reader theReader) {
|
||||
XMLEventReader streamReader = createStreamReader(theReader);
|
||||
|
||||
ParserState<TagList> parserState = ParserState.getPreTagListInstance(myContext, false);
|
||||
return doXmlLoop(streamReader, parserState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void writeAtomLink(XMLStreamWriter theEventWriter, String theRel, StringDt theStringDt) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
theEventWriter.writeStartElement("link");
|
||||
|
@ -989,6 +955,37 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeBundleResourceLink(XMLStreamWriter theEventWriter, String theRel, StringDt theUrl) throws XMLStreamException {
|
||||
if (theUrl.isEmpty() == false) {
|
||||
theEventWriter.writeStartElement("link");
|
||||
theEventWriter.writeStartElement("relation");
|
||||
theEventWriter.writeAttribute("value", theRel);
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeStartElement("url");
|
||||
theEventWriter.writeAttribute("value", theUrl.getValue());
|
||||
theEventWriter.writeEndElement();
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCategories(XMLStreamWriter eventWriter, TagList categories) throws XMLStreamException {
|
||||
if (categories != null) {
|
||||
for (Tag next : categories) {
|
||||
eventWriter.writeStartElement("category");
|
||||
eventWriter.writeAttribute("term", defaultString(next.getTerm()));
|
||||
eventWriter.writeAttribute("label", defaultString(next.getLabel()));
|
||||
eventWriter.writeAttribute("scheme", defaultString(next.getScheme()));
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalAttribute(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theValue)) {
|
||||
theEventWriter.writeAttribute(theName, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithTextNode(XMLStreamWriter theEventWriter, String theTagName, InstantDt theInstantDt) throws XMLStreamException {
|
||||
if (theInstantDt.getValue() != null) {
|
||||
theEventWriter.writeStartElement(theTagName);
|
||||
|
@ -1005,6 +1002,14 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithValue(XMLStreamWriter theEventWriter, String theName, String theValue) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theValue)) {
|
||||
theEventWriter.writeStartElement(theName);
|
||||
theEventWriter.writeAttribute("value", theValue);
|
||||
theEventWriter.writeEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(XMLStreamWriter theEventWriter, String theElementName, IdDt theIdDt) throws XMLStreamException {
|
||||
theEventWriter.writeStartElement(theElementName);
|
||||
if (StringUtils.isNotBlank(theIdDt.getValue())) {
|
||||
|
|
|
@ -27,10 +27,10 @@ import ca.uhn.fhir.model.api.IQueryParameterOr;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
interface IParamBinder {
|
||||
interface IParamBinder<T> {
|
||||
|
||||
List<IQueryParameterOr<?>> encode(FhirContext theContext, Object theString) throws InternalErrorException;
|
||||
|
||||
Object parse(String theName, List<QualifiedParamList> theList) throws InternalErrorException, InvalidRequestException;
|
||||
T parse(String theName, List<QualifiedParamList> theList) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -58,7 +60,13 @@ import ca.uhn.fhir.rest.annotation.VersionIdParam;
|
|||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.CollectionBinder;
|
||||
import ca.uhn.fhir.rest.param.DateAndListParam;
|
||||
import ca.uhn.fhir.rest.param.NumberAndListParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityAndListParam;
|
||||
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||
|
@ -455,6 +463,38 @@ public class MethodUtil {
|
|||
return MethodUtil.findParamAnnotationIndex(theMethod, TagListParam.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method intended provided to help the JPA module.
|
||||
*/
|
||||
public static IQueryParameterAnd<?> parseQueryParams(RuntimeSearchParam theParamDef, String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
|
||||
QueryParameterAndBinder binder = null;
|
||||
switch (theParamDef.getParamType()) {
|
||||
case COMPOSITE:
|
||||
throw new UnsupportedOperationException();
|
||||
case DATE:
|
||||
binder = new QueryParameterAndBinder(DateAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case NUMBER:
|
||||
binder = new QueryParameterAndBinder(NumberAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case QUANTITY:
|
||||
binder = new QueryParameterAndBinder(QuantityAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case REFERENCE:
|
||||
binder = new QueryParameterAndBinder(ReferenceAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case STRING:
|
||||
binder = new QueryParameterAndBinder(StringAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
case TOKEN:
|
||||
binder = new QueryParameterAndBinder(TokenAndListParam.class, Collections.<Class<? extends IQueryParameterType>>emptyList());
|
||||
break;
|
||||
}
|
||||
|
||||
return binder.parse(theUnqualifiedParamName, theParameters);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(Method theMethod, Object theProvider) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
|
|
|
@ -29,7 +29,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterAndBinder extends BaseBinder<IQueryParameterAnd<?>> implements IParamBinder {
|
||||
final class QueryParameterAndBinder extends BaseBinder<IQueryParameterAnd<?>> implements IParamBinder<IQueryParameterAnd<?>> {
|
||||
|
||||
QueryParameterAndBinder(Class<? extends IQueryParameterAnd<?>> theType, List<Class<? extends IQueryParameterType>> theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
|
@ -43,7 +43,7 @@ final class QueryParameterAndBinder extends BaseBinder<IQueryParameterAnd<?>> im
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String theName, List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public IQueryParameterAnd<?> parse(String theName, List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterAnd<?> dt;
|
||||
try {
|
||||
dt = newInstance();
|
||||
|
|
|
@ -29,7 +29,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterOrBinder extends BaseBinder<IQueryParameterOr<?>> implements IParamBinder {
|
||||
final class QueryParameterOrBinder extends BaseBinder<IQueryParameterOr<?>> implements IParamBinder<IQueryParameterOr<?>> {
|
||||
|
||||
QueryParameterOrBinder(Class<? extends IQueryParameterOr<?>> theType, List<Class<? extends IQueryParameterType>> theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
|
@ -44,7 +44,7 @@ final class QueryParameterOrBinder extends BaseBinder<IQueryParameterOr<?>> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String theName, List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public IQueryParameterOr<?> parse(String theName, List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterOr<?> dt;
|
||||
try {
|
||||
dt = newInstance();
|
||||
|
|
|
@ -31,7 +31,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class QueryParameterTypeBinder extends BaseBinder<IQueryParameterType> implements IParamBinder {
|
||||
final class QueryParameterTypeBinder extends BaseBinder<IQueryParameterType> implements IParamBinder<IQueryParameterType> {
|
||||
|
||||
QueryParameterTypeBinder(Class<? extends IQueryParameterType> theType, List<Class<? extends IQueryParameterType>> theCompositeTypes) {
|
||||
super(theType, theCompositeTypes);
|
||||
|
@ -46,7 +46,7 @@ final class QueryParameterTypeBinder extends BaseBinder<IQueryParameterType> imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String theName, List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
|
||||
public IQueryParameterType parse(String theName, List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
|
||||
String value = theParams.get(0).get(0);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return null;
|
||||
|
|
|
@ -29,7 +29,7 @@ import ca.uhn.fhir.rest.param.StringParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
final class StringBinder implements IParamBinder {
|
||||
final class StringBinder implements IParamBinder<String> {
|
||||
StringBinder() {
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ final class StringBinder implements IParamBinder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String theName, List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
|
||||
public String parse(String theName, List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
|
||||
if (theParams.size() == 0 || theParams.get(0).size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -20,43 +20,7 @@ package ca.uhn.fhir.rest.server;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.ProvidedResourceScanner;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Destroy;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.method.*;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
@ -67,10 +31,67 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.ProvidedResourceScanner;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.Destroy;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.OtherOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
public class RestfulServer extends HttpServlet {
|
||||
|
||||
|
@ -1202,8 +1223,8 @@ public class RestfulServer extends HttpServlet {
|
|||
for (IResource next : includedResources) {
|
||||
BundleEntry entry = bundle.addResource(next, theContext, theServerBase);
|
||||
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
|
||||
if (entry.getStatus().isEmpty()) {
|
||||
entry.getStatus().setValueAsEnum(BundleEntryStatusEnum.INCLUDE);
|
||||
if (entry.getSearchMode().isEmpty()) {
|
||||
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,17 +63,11 @@ public class XmlUtil {
|
|||
private static volatile boolean ourHaveLoggedStaxImplementation;
|
||||
private static final Map<String, Integer> VALID_ENTITY_NAMES;
|
||||
private static final ExtendedEntityReplacingXmlResolver XML_RESOLVER = new ExtendedEntityReplacingXmlResolver();
|
||||
|
||||
private static final Attributes.Name IMPLEMENTATION_TITLE = new Attributes.Name("Implementation-Title");
|
||||
|
||||
private static final Attributes.Name IMPLEMENTATION_VENDOR = new Attributes.Name("Implementation-Vendor");
|
||||
|
||||
private static final Attributes.Name IMPLEMENTATION_VERSION = new Attributes.Name("Implementation-Version");
|
||||
|
||||
private static final Attributes.Name BUNDLE_SYMBOLIC_NAME = new Attributes.Name("Bundle-SymbolicName");
|
||||
|
||||
private static final Attributes.Name BUNDLE_VENDOR = new Attributes.Name("Bundle-Vendor");
|
||||
|
||||
private static final Attributes.Name BUNDLE_VERSION = new Attributes.Name("Bundle-Version");
|
||||
|
||||
static {
|
||||
|
@ -211,7 +205,7 @@ public class XmlUtil {
|
|||
* being used (e.g. glassfish) so we don't set them there.
|
||||
*/
|
||||
try {
|
||||
Class.forName("com.ctc.wstx.stax.WstxOutputFactory");
|
||||
Class.forName("com.ctc.wstx.stax.WstxInputFactory");
|
||||
if (inputFactory instanceof com.ctc.wstx.stax.WstxInputFactory) {
|
||||
// inputFactory.setProperty(WstxInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
|
||||
inputFactory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, XML_RESOLVER);
|
||||
|
@ -366,6 +360,7 @@ public class XmlUtil {
|
|||
case '"':
|
||||
case '&':
|
||||
hasEscapable = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -57,11 +57,13 @@ public class ValidationResult {
|
|||
|
||||
private String toDescription() {
|
||||
StringBuilder b = new StringBuilder(100);
|
||||
if (myOperationOutcome != null) {
|
||||
if (myOperationOutcome != null && myOperationOutcome.getIssue().size() > 0) {
|
||||
BaseOperationOutcome.BaseIssue issueFirstRep = myOperationOutcome.getIssueFirstRep();
|
||||
b.append(issueFirstRep.getDetailsElement().getValue());
|
||||
b.append(" - ");
|
||||
b.append(issueFirstRep.getLocationFirstRep().getValue());
|
||||
}else {
|
||||
b.append("No issues");
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
# Core Library Messages
|
||||
|
||||
ca.uhn.fhir.context.FhirContext.noStructures=Could not find any HAPI-FHIR structure JARs on the classpath. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath (or project pom.xml if you are using Maven)
|
||||
ca.uhn.fhir.context.FhirContext.noStructuresForSpecifiedVersion=Could not find the HAPI-FHIR structure JAR on the classpath for version {0}. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath (or project pom.xml if you are using Maven)
|
||||
|
||||
|
@ -10,7 +12,7 @@ ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable
|
|||
ca.uhn.fhir.rest.client.RestfulClientFactory.failedToRetrieveConformance=Failed to retrieve the server's metadata statement during client initialization. URL used was: {0}
|
||||
ca.uhn.fhir.rest.client.RestfulClientFactory.wrongVersionInConformance=The server at base URL "{0}" returned a conformance statement indicating that it supports FHIR version "{1}" which corresponds to {2}, but this client is configured to use {3} (via the FhirContext).
|
||||
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid _include parameter value: '{0}'. Valid values are: {1}
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.invalidIncludeNameInRequest=Invalid _include parameter value: "{0}". Valid values are: {1}
|
||||
ca.uhn.fhir.rest.method.IncludeParameter.orIncludeInRequest='OR' query parameters (values containing ',') are not supported in _include parameters
|
||||
|
||||
ca.uhn.fhir.rest.method.SearchMethodBinding.invalidSpecialParamName=Method [{0}] in provider [{1}] contains search parameter annotated to use name [{2}] - This name is reserved according to the FHIR specification and can not be used as a search parameter name.
|
||||
|
@ -19,3 +21,10 @@ ca.uhn.fhir.rest.method.SearchMethodBinding.idNullForCompartmentSearch=ID parame
|
|||
|
||||
ca.uhn.fhir.validation.FhirValidator.noPhlocWarningOnStartup=Phloc-schematron library not found on classpath, will not attempt to perform schematron validation
|
||||
ca.uhn.fhir.validation.FhirValidator.noPhlocError=Phloc-schematron library not found on classpath, can not enable perform schematron validation
|
||||
|
||||
# JPA Messages
|
||||
|
||||
ca.uhn.fhir.jpa.dao.FhirSystemDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request.
|
||||
ca.uhn.fhir.jpa.dao.FhirSystemDao.transactionOperationWithMultipleMatchFailure=Failed to {0} resource with match URL "{1}" because this search matched {2} resources
|
||||
ca.uhn.fhir.jpa.dao.FhirSystemDao.transactionOperationFailedNoId=Failed to {0} resource in transaction because no ID was provided
|
||||
ca.uhn.fhir.jpa.dao.FhirSystemDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
|
|
|
@ -7,9 +7,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
|
|||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
|
@ -97,4 +97,4 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
|||
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
|
|
|
@ -20,8 +20,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
@ -96,7 +95,7 @@ import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
|||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
|
@ -372,6 +371,15 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
@Override
|
||||
public BaseHasResource readEntity(IdDt theId) {
|
||||
boolean checkForForcedId = true;
|
||||
|
||||
BaseHasResource entity = readEntity(theId, checkForForcedId);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId) {
|
||||
validateResourceTypeAndThrowIllegalArgumentException(theId);
|
||||
|
||||
Long pid = translateForcedIdToPid(theId);
|
||||
|
@ -396,10 +404,12 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
}
|
||||
}
|
||||
|
||||
validateGivenIdIsAppropriateToRetrieveResource(theId, entity);
|
||||
|
||||
validateResourceType(entity);
|
||||
|
||||
if (theCheckForForcedId) {
|
||||
validateGivenIdIsAppropriateToRetrieveResource(theId, entity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -508,7 +518,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
// Execute the query and make sure we return distinct results
|
||||
List<IResource> retVal = new ArrayList<IResource>();
|
||||
loadResourcesByPid(pidsSubList, retVal, BundleEntryStatusEnum.MATCH);
|
||||
loadResourcesByPid(pidsSubList, retVal, BundleEntrySearchModeEnum.MATCH);
|
||||
|
||||
// Load _include resources
|
||||
if (theParams.getIncludes() != null && theParams.getIncludes().isEmpty() == false) {
|
||||
|
@ -561,7 +571,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
ourLog.info("Loading {} included resources", includePids.size());
|
||||
resources = loadResourcesById(includePids);
|
||||
for (IResource next : resources) {
|
||||
ResourceMetadataKeyEnum.ENTRY_STATUS.put(next, BundleEntryStatusEnum.INCLUDE);
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(next, BundleEntrySearchModeEnum.INCLUDE);
|
||||
}
|
||||
retVal.addAll(resources);
|
||||
}
|
||||
|
@ -1441,7 +1451,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
}
|
||||
|
||||
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IResource> theResourceListToPopulate, BundleEntryStatusEnum theBundleEntryStatus) {
|
||||
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IResource> theResourceListToPopulate, BundleEntrySearchModeEnum theBundleEntryStatus) {
|
||||
if (theIncludePids.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1469,7 +1479,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
continue;
|
||||
}
|
||||
|
||||
ResourceMetadataKeyEnum.ENTRY_STATUS.put(resource, theBundleEntryStatus);
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(resource, theBundleEntryStatus);
|
||||
|
||||
theResourceListToPopulate.set(index, resource);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
@ -36,11 +38,19 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
|
@ -49,11 +59,16 @@ import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
|||
import ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
|
||||
public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDao.class);
|
||||
|
||||
|
@ -68,15 +83,14 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
|||
|
||||
Set<IdDt> allIds = new HashSet<IdDt>();
|
||||
|
||||
for (int i =0; i <theResources.size();i++) {
|
||||
for (int i = 0; i < theResources.size(); i++) {
|
||||
IResource res = theResources.get(i);
|
||||
if(res.getId().hasIdPart() && !res.getId().hasResourceType()) {
|
||||
if (res.getId().hasIdPart() && !res.getId().hasResourceType()) {
|
||||
res.setId(new IdDt(toResourceName(res.getClass()), res.getId().getIdPart()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the bundle doesn't have any duplicates, since this causes all
|
||||
* kinds of weirdness
|
||||
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
|
||||
*/
|
||||
if (res.getId().hasResourceType() && res.getId().hasIdPart()) {
|
||||
IdDt nextId = res.getId().toUnqualifiedVersionless();
|
||||
|
@ -95,30 +109,89 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
|||
|
||||
List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();
|
||||
|
||||
for (IResource nextResource : theResources) {
|
||||
List<IResource> retVal = new ArrayList<IResource>();
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
retVal.add(oo);
|
||||
|
||||
for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
|
||||
IResource nextResource = theResources.get(resourceIdx);
|
||||
|
||||
IdDt nextId = nextResource.getId();
|
||||
if (nextId == null) {
|
||||
nextId = new IdDt();
|
||||
}
|
||||
|
||||
String resourceName = toResourceName(nextResource);
|
||||
|
||||
ResourceTable entity;
|
||||
if (nextId.isEmpty()) {
|
||||
entity = null;
|
||||
} else {
|
||||
try {
|
||||
Long pid = translateForcedIdToPid(nextId);
|
||||
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
entity = null;
|
||||
}
|
||||
BundleEntryTransactionOperationEnum nextResouceOperationIn = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(nextResource);
|
||||
if (nextResouceOperationIn == null && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
|
||||
nextResouceOperationIn = BundleEntryTransactionOperationEnum.DELETE;
|
||||
}
|
||||
|
||||
String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
|
||||
Set<Long> candidateMatches = null;
|
||||
if (StringUtils.isNotBlank(matchUrl)) {
|
||||
candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
|
||||
}
|
||||
|
||||
ResourceTable entity;
|
||||
if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
entity = null;
|
||||
} else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE || nextResouceOperationIn == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
if (candidateMatches == null || candidateMatches.size() == 0) {
|
||||
if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDao.class, "transactionOperationFailedNoId", nextResouceOperationIn.name()));
|
||||
}
|
||||
entity = tryToLoadEntity(nextId);
|
||||
if (entity == null) {
|
||||
if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.UPDATE) {
|
||||
ourLog.debug("Attempting to UPDATE resource with unknown ID '{}', will CREATE instead", nextId);
|
||||
} else if (candidateMatches == null) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDao.class, "transactionOperationFailedUnknownId", nextResouceOperationIn.name(), nextId));
|
||||
} else {
|
||||
ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, BundleEntryTransactionOperationEnum.NOOP);
|
||||
persistedResources.add(null);
|
||||
retVal.add(nextResource);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (candidateMatches.size() == 1) {
|
||||
entity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
} else {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDao.class, "transactionOperationWithMultipleMatchFailure", nextResouceOperationIn.name(), matchUrl, candidateMatches.size()));
|
||||
}
|
||||
} else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.NOOP) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDao.class, "incomingNoopInTransaction"));
|
||||
} else if (nextId.isEmpty()) {
|
||||
entity = null;
|
||||
} else {
|
||||
entity = tryToLoadEntity(nextId);
|
||||
}
|
||||
|
||||
BundleEntryTransactionOperationEnum nextResouceOperationOut;
|
||||
if (entity == null) {
|
||||
nextResouceOperationOut = BundleEntryTransactionOperationEnum.CREATE;
|
||||
entity = toEntity(nextResource);
|
||||
if (!nextId.isEmpty() && nextId.getIdPart().startsWith("cid:")) {
|
||||
if (nextId.isEmpty() == false && nextId.getIdPart().startsWith("cid:")) {
|
||||
ourLog.debug("Resource in transaction has ID[{}], will replace with server assigned ID", nextId.getIdPart());
|
||||
} else if (nextResouceOperationIn == BundleEntryTransactionOperationEnum.CREATE) {
|
||||
if (nextId.isEmpty() == false) {
|
||||
ourLog.debug("Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID", nextId.getIdPart());
|
||||
}
|
||||
if (candidateMatches != null) {
|
||||
if (candidateMatches.size() == 1) {
|
||||
ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
|
||||
BaseHasResource existingEntity = loadFirstEntityFromCandidateMatches(candidateMatches);
|
||||
IResource existing = (IResource) toResource(existingEntity);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(existing, BundleEntryTransactionOperationEnum.NOOP);
|
||||
persistedResources.add(null);
|
||||
retVal.add(existing);
|
||||
continue;
|
||||
}
|
||||
if (candidateMatches.size() > 1) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(FhirSystemDao.class, "transactionOperationWithMultipleMatchFailure", BundleEntryTransactionOperationEnum.CREATE.name(), matchUrl, candidateMatches.size()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
createForcedIdIfNeeded(entity, nextId);
|
||||
}
|
||||
|
@ -126,16 +199,20 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
|||
if (entity.getForcedId() != null) {
|
||||
myEntityManager.persist(entity.getForcedId());
|
||||
}
|
||||
// myEntityManager.flush();
|
||||
creations++;
|
||||
ourLog.info("Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
|
||||
} else {
|
||||
nextResouceOperationOut = nextResouceOperationIn;
|
||||
if (nextResouceOperationOut == null) {
|
||||
nextResouceOperationOut = BundleEntryTransactionOperationEnum.UPDATE;
|
||||
}
|
||||
updates++;
|
||||
ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
|
||||
}
|
||||
|
||||
persistedResources.add(entity);
|
||||
|
||||
retVal.add(nextResource);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(nextResource, nextResouceOperationOut);
|
||||
}
|
||||
|
||||
ourLog.info("Flushing transaction to database");
|
||||
|
@ -143,14 +220,22 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
|||
|
||||
for (int i = 0; i < persistedResources.size(); i++) {
|
||||
ResourceTable entity = persistedResources.get(i);
|
||||
|
||||
String resourceName = toResourceName(theResources.get(i));
|
||||
IdDt nextId = theResources.get(i).getId();
|
||||
|
||||
IdDt newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
IdDt newId;
|
||||
|
||||
if (entity == null) {
|
||||
newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
|
||||
} else {
|
||||
newId = entity.getIdDt().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
if (nextId == null || nextId.isEmpty()) {
|
||||
ourLog.info("Transaction resource (with no preexisting ID) has been assigned new ID[{}]", nextId, newId);
|
||||
} else {
|
||||
if (nextId.toUnqualifiedVersionless().equals(entity.getIdDt().toUnqualifiedVersionless())) {
|
||||
if (nextId.toUnqualifiedVersionless().equals(newId)) {
|
||||
ourLog.info("Transaction resource ID[{}] is being updated", newId);
|
||||
} else {
|
||||
if (!nextId.getIdPart().startsWith("#")) {
|
||||
|
@ -182,26 +267,96 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
|||
for (int i = 0; i < theResources.size(); i++) {
|
||||
IResource resource = theResources.get(i);
|
||||
ResourceTable table = persistedResources.get(i);
|
||||
if (table == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
|
||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||
if (deletedInstantOrNull == null && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(resource) == BundleEntryTransactionOperationEnum.DELETE) {
|
||||
deletedTimestampOrNull = new Date();
|
||||
ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
|
||||
}
|
||||
|
||||
updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull);
|
||||
}
|
||||
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
ourLog.info("Transaction completed in {}ms with {} creations and {} updates", new Object[] { delay, creations, updates });
|
||||
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in "+delay+"ms with "+creations+" creations and "+updates+" updates");
|
||||
|
||||
ArrayList<IResource> retVal = new ArrayList<IResource>();
|
||||
retVal.add(oo);
|
||||
retVal.addAll(theResources);
|
||||
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Transaction completed in " + delay + "ms with " + creations + " creations and " + updates + " updates");
|
||||
|
||||
notifyWriteCompleted();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private boolean hasValue(InstantDt theInstantDt) {
|
||||
return theInstantDt != null && theInstantDt.isEmpty() == false;
|
||||
}
|
||||
|
||||
private ResourceTable tryToLoadEntity(IdDt nextId) {
|
||||
ResourceTable entity;
|
||||
try {
|
||||
Long pid = translateForcedIdToPid(nextId);
|
||||
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
entity = null;
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private ResourceTable loadFirstEntityFromCandidateMatches(Set<Long> candidateMatches) {
|
||||
return myEntityManager.find(ResourceTable.class, candidateMatches.iterator().next());
|
||||
}
|
||||
|
||||
private Set<Long> processMatchUrl(String theMatchUrl, Class<? extends IBaseResource> theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType);
|
||||
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
try {
|
||||
parameters = URLEncodedUtils.parse(new URI(theMatchUrl), "UTF-8");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString());
|
||||
}
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
String paramName = next.getName();
|
||||
String qualifier = null;
|
||||
for (int i = 0; i < paramMap.size(); i++) {
|
||||
switch (paramName.charAt(i)) {
|
||||
case '.':
|
||||
case ':':
|
||||
qualifier = paramName.substring(i);
|
||||
paramName = paramName.substring(0, i);
|
||||
i = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, next.getValue());
|
||||
nameToParamLists.put(paramName, paramList);
|
||||
}
|
||||
|
||||
for (String nextParamName : nameToParamLists.keySet()) {
|
||||
RuntimeSearchParam paramDef = resourceDef.getSearchParam(nextParamName);
|
||||
if (paramDef == null) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName);
|
||||
}
|
||||
|
||||
List<QualifiedParamList> paramList = nameToParamLists.get(nextParamName);
|
||||
IQueryParameterAnd<?> param = MethodUtil.parseQueryParams(paramDef, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
}
|
||||
|
||||
IFhirResourceDao<? extends IResource> dao = getDao(theResourceType);
|
||||
Set<Long> ids = dao.searchForIdsWithAndOr(paramMap);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBundleProvider history(Date theSince) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
|
|
@ -79,4 +79,11 @@ public interface IFhirResourceDao<T extends IResource> extends IDao {
|
|||
|
||||
Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams);
|
||||
|
||||
/**
|
||||
* @param theCheckForForcedId If true, this method should fail if the requested ID contains
|
||||
* a numeric PID which exists, but is obscured by a "forced ID" so should not exist as
|
||||
* far as the outside world is concerned.
|
||||
*/
|
||||
BaseHasResource readEntity(IdDt theId, boolean theCheckForForcedId);
|
||||
|
||||
}
|
||||
|
|
|
@ -641,6 +641,7 @@ public class FhirResourceDaoTest {
|
|||
assertTrue(patients.size() >= 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHistoryByForcedId() {
|
||||
IdDt idv1;
|
||||
|
@ -661,6 +662,7 @@ public class FhirResourceDaoTest {
|
|||
// Newest first
|
||||
assertEquals("Patient/testHistoryByForcedId/_history/2", patients.get(0).getId().toUnqualified().getValue());
|
||||
assertEquals("Patient/testHistoryByForcedId/_history/1", patients.get(1).getId().toUnqualified().getValue());
|
||||
assertNotEquals(idv1, idv2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
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.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.instrument.UnmodifiableClassException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
@ -33,31 +25,53 @@ import ca.uhn.fhir.model.api.TagList;
|
|||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Device;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionOperationEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public class FhirSystemDaoTest {
|
||||
|
||||
private static ClassPathXmlApplicationContext ourCtx;
|
||||
private static FhirContext ourFhirContext;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoTest.class);
|
||||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirResourceDao<Device> ourDeviceDao;
|
||||
private static IFhirResourceDao<DiagnosticReport> ourDiagnosticReportDao;
|
||||
private static IFhirResourceDao<Organization> ourOrganizationDao;
|
||||
private static IFhirResourceDao<Location> ourLocationDao;
|
||||
private static Date ourTestStarted;
|
||||
private static IFhirSystemDao ourSystemDao;
|
||||
private static FhirContext ourFhirContext;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
|
@ -65,7 +79,7 @@ public class FhirSystemDaoTest {
|
|||
Thread.sleep(10);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testHistory");
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testHistory");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
|
||||
|
||||
|
@ -105,6 +119,84 @@ public class FhirSystemDaoTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0, 1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagOperationss() throws Exception {
|
||||
|
||||
|
@ -179,7 +271,465 @@ public class FhirSystemDaoTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithUpdate() throws Exception {
|
||||
public void testTransactionCreateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.NOOP, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id, p.getId());
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionCreateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateNoMatchUrl() {
|
||||
String methodName = "testTransactionCreateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.CREATE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
p = (Patient) resp.get(1);
|
||||
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().getIdPart(), not(containsString("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
ourPatientDao.read(new IdDt("Patient/" + methodName));
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionDeleteMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName + "ZZZ");
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id2 = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), (containsString("test")));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
assertEquals(id2.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id2, p.getId());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id2.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
Patient found = ourPatientDao.read(id);
|
||||
assertEquals(id, found.getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionDeleteNoMatchUrl() {
|
||||
String methodName = "testTransactionDeleteNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.DELETE);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p));
|
||||
assertEquals(2, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.DELETE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get(p).getValue());
|
||||
|
||||
try {
|
||||
ourPatientDao.read(id.toVersionless());
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoTest.class.getResourceAsStream("/bundle.json");
|
||||
Bundle bundle = ourFhirContext.newJsonParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(containsString("5556918")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithOneMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithOneMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithTwoMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithTwoMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatch() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatch";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("Hello");
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId(id);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference(id);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting() {
|
||||
String methodName = "testTransactionUpdateMatchUrlWithZeroMatchAndNotPreExisting";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertThat(p.getId().toString(), endsWith("/_history/1"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(p.getId().toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoMatchUrl() {
|
||||
String methodName = "testTransactionUpdateNoMatchUrl";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.setId("Patient/" + methodName);
|
||||
IdDt id = ourPatientDao.create(p).getId();
|
||||
ourLog.info("Created patient, got it: {}", id);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
p.addName().addFamily("Hello");
|
||||
p.setId("Patient/" + methodName);
|
||||
ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.put(p, BundleEntryTransactionOperationEnum.UPDATE);
|
||||
|
||||
Observation o = new Observation();
|
||||
o.getName().setText("Some Observation");
|
||||
o.getSubject().setReference("Patient/" + methodName);
|
||||
|
||||
List<IResource> resp = ourSystemDao.transaction(Arrays.asList((IResource) p, o));
|
||||
assertEquals(3, resp.size());
|
||||
|
||||
p = (Patient) resp.get(1);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(p));
|
||||
assertThat(p.getId().toVersionless().toString(), containsString("test"));
|
||||
assertEquals(id.toVersionless(), p.getId().toVersionless());
|
||||
assertNotEquals(id, p.getId());
|
||||
assertThat(p.getId().toString(), endsWith("/_history/2"));
|
||||
|
||||
o = (Observation) resp.get(2);
|
||||
assertEquals(BundleEntryTransactionOperationEnum.CREATE, ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(o));
|
||||
assertEquals(id.toVersionless(), o.getSubject().getReference());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionUpdateNoOperationSpecified() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
|
@ -196,8 +746,10 @@ public class FhirSystemDaoTest {
|
|||
ourSystemDao.transaction(res);
|
||||
|
||||
assertFalse(p1.getId().isEmpty());
|
||||
assertNotEquals("testTransactionWithUpdateXXX01", p1.getId().getVersionIdPart());
|
||||
assertFalse(p2.getId().isEmpty());
|
||||
assertEquals("testTransactionWithUpdateXXX01", p1.getId().getIdPart());
|
||||
assertEquals("testTransactionWithUpdateXXX02", p2.getId().getIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX01", p1.getId().getVersionIdPart());
|
||||
assertNotEquals("testTransactionWithUpdateXXX02", p2.getId().getVersionIdPart());
|
||||
assertEquals(p1.getId().toUnqualified().toVersionless(), p2.getSubject().getReference());
|
||||
|
||||
|
@ -206,18 +758,66 @@ public class FhirSystemDaoTest {
|
|||
IdDt p2id = p2.getId().toUnqualified().toVersionless();
|
||||
IdDt p2idWithVer = p2.getId().toUnqualified();
|
||||
|
||||
p1.addName().addFamily("Name1");
|
||||
p1.setId(p1.getId().toUnqualified().toVersionless());
|
||||
/*
|
||||
* Make some changes
|
||||
*/
|
||||
|
||||
res = new ArrayList<IResource>();
|
||||
|
||||
p1 = new Patient();
|
||||
p1.getId().setValue("testTransactionWithUpdateXXX01");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithUpdate01");
|
||||
p1.addName().addFamily("Name1");
|
||||
res.add(p1);
|
||||
|
||||
p2 = new Observation();
|
||||
p2.getId().setValue("testTransactionWithUpdateXXX02");
|
||||
p2.getIdentifier().setSystem("system").setValue("testTransactionWithUpdate02");
|
||||
p2.setSubject(new ResourceReferenceDt("Patient/testTransactionWithUpdateXXX01"));
|
||||
p2.addReferenceRange().setHigh(new QuantityDt(123L));
|
||||
p2.setId(p2.getId().toUnqualified().toVersionless());
|
||||
res.add(p2);
|
||||
|
||||
List<IResource> results = ourSystemDao.transaction(res);
|
||||
|
||||
assertEquals(p1id, results.get(1).getId().toUnqualified().toVersionless());
|
||||
assertEquals(p2id, results.get(2).getId().toUnqualified().toVersionless());
|
||||
assertNotEquals(p1idWithVer, results.get(1).getId().toUnqualified());
|
||||
assertNotEquals(p2idWithVer, results.get(2).getId().toUnqualified());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertEquals(p1id, p1.getId().toUnqualified().toVersionless());
|
||||
assertEquals(p2id, p2.getId().toUnqualified().toVersionless());
|
||||
assertNotEquals(p1idWithVer, p1.getId().toUnqualified());
|
||||
assertNotEquals(p2idWithVer, p2.getId().toUnqualified());
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
|
@ -282,175 +882,6 @@ public class FhirSystemDaoTest {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #55
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithCidIds() throws Exception {
|
||||
List<IResource> res = new ArrayList<IResource>();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.setId("cid:patient1");
|
||||
p1.addIdentifier().setSystem("system").setValue("testTransactionWithCidIds01");
|
||||
res.add(p1);
|
||||
|
||||
Observation o1 = new Observation();
|
||||
o1.setId("cid:observation1");
|
||||
o1.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds02");
|
||||
o1.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o1);
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.setId("cid:observation2");
|
||||
o2.getIdentifier().setSystem("system").setValue("testTransactionWithCidIds03");
|
||||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
||||
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle() throws Exception {
|
||||
|
||||
InputStream bundleRes = FhirSystemDaoTest.class.getResourceAsStream("/bundle.json");
|
||||
Bundle bundle = ourFhirContext.newJsonParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
ourLog.info("ID: {}", id);
|
||||
assertThat(id, not(containsString("5556918")));
|
||||
assertThat(id, not(equalToIgnoringCase("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithSimpleLink() {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String patientVersion = (patient.getId().getVersionIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
String obsVersion = (obs.getId().getVersionIdPart());
|
||||
|
||||
// assertThat(patientId, greaterThan(0L));
|
||||
// assertEquals(patientVersion, 1L);
|
||||
// assertThat(obsId, greaterThan(patientId));
|
||||
// assertEquals(obsVersion, 1L);
|
||||
|
||||
// Try to search
|
||||
|
||||
IBundleProvider obsResults = ourObservationDao.search(Observation.SP_NAME, new IdentifierDt("urn:system", "testPersistWithSimpleLinkO01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IBundleProvider patResults = ourPatientDao.search(Patient.SP_IDENTIFIER, new IdentifierDt("urn:system", "testPersistWithSimpleLinkP01"));
|
||||
assertEquals(1, obsResults.size());
|
||||
|
||||
IdDt foundPatientId = patResults.getResources(0, 1).get(0).getId();
|
||||
ResourceReferenceDt subject = obs.getSubject();
|
||||
assertEquals(foundPatientId.getIdPart(), subject.getReference().getIdPart());
|
||||
|
||||
// Update
|
||||
|
||||
patient = (Patient) patResults.getResources(0,1).get(0);
|
||||
obs = (Observation) obsResults.getResources(0, 1).get(0);
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
String obsId2 = (obs.getId().getIdPart());
|
||||
String obsVersion2 = (obs.getId().getVersionIdPart());
|
||||
|
||||
assertEquals(patientId, patientId2);
|
||||
assertEquals(patientVersion2, "2");
|
||||
assertEquals(obsId, obsId2);
|
||||
assertEquals(obsVersion2, "2");
|
||||
|
||||
}
|
||||
|
||||
@Test(expected=InvalidRequestException.class)
|
||||
public void testTransactionFailsWithDuplicateIds() {
|
||||
Patient patient1 = new Patient();
|
||||
patient1.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient1.addIdentifier().setSystem("urn:system").setValue( "testPersistWithSimpleLinkP01");
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue( "testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testGetResourceCountsO01");
|
||||
ourObservationDao.create(obs);
|
||||
|
||||
Map<String, Long> oldCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue( "testGetResourceCountsP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
ourPatientDao.create(patient);
|
||||
|
||||
Map<String, Long> newCounts = ourSystemDao.getResourceCounts();
|
||||
|
||||
if (oldCounts.containsKey("Patient")) {
|
||||
assertEquals(oldCounts.get("Patient") + 1, (long) newCounts.get("Patient"));
|
||||
} else {
|
||||
assertEquals(1L, (long) newCounts.get("Patient"));
|
||||
}
|
||||
|
||||
assertEquals((long) oldCounts.get("Observation"), (long) newCounts.get("Observation"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
|
@ -459,14 +890,10 @@ public class FhirSystemDaoTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourTestStarted = new Date();
|
||||
ourCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml");
|
||||
ourFhirContext = ourCtx.getBean(FhirContext.class);
|
||||
ourPatientDao = ourCtx.getBean("myPatientDao", IFhirResourceDao.class);
|
||||
ourObservationDao = ourCtx.getBean("myObservationDao", IFhirResourceDao.class);
|
||||
ourDiagnosticReportDao = ourCtx.getBean("myDiagnosticReportDao", IFhirResourceDao.class);
|
||||
ourDeviceDao = ourCtx.getBean("myDeviceDao", IFhirResourceDao.class);
|
||||
ourOrganizationDao = ourCtx.getBean("myOrganizationDao", IFhirResourceDao.class);
|
||||
ourLocationDao = ourCtx.getBean("myLocationDao", IFhirResourceDao.class);
|
||||
ourSystemDao = ourCtx.getBean("mySystemDao", IFhirSystemDao.class);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProvider;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -39,7 +38,6 @@ import ca.uhn.fhir.model.dstu.valueset.EncounterClassEnum;
|
|||
import ca.uhn.fhir.model.dstu.valueset.EncounterStateEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
|
@ -115,11 +113,11 @@ public class ResourceProviderDstu1Test {
|
|||
|
||||
assertEquals(2, found.size());
|
||||
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
||||
assertEquals(null, found.getEntries().get(0).getStatus().getValueAsEnum());
|
||||
assertEquals(null, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_STATUS));
|
||||
assertEquals(null, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||
assertEquals(null, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
|
||||
assertEquals(null, found.getEntries().get(1).getStatus().getValueAsEnum());
|
||||
assertEquals(null, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_STATUS));
|
||||
assertEquals(null, found.getEntries().get(1).getSearchMode().getValueAsEnum());
|
||||
assertEquals(null, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,13 +20,13 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProvider;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
|
||||
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
|
||||
|
@ -37,9 +37,8 @@ import ca.uhn.fhir.model.dstu2.resource.Organization;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
@ -143,11 +142,11 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
assertEquals(2, found.size());
|
||||
assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass());
|
||||
assertEquals(BundleEntryStatusEnum.MATCH, found.getEntries().get(0).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntryStatusEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_STATUS));
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
assertEquals(Organization.class, found.getEntries().get(1).getResource().getClass());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, found.getEntries().get(1).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_STATUS));
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
|
||||
|
||||
|
@ -398,7 +397,7 @@ public class ResourceProviderDstu2Test {
|
|||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01")).encodedJson().prettyPrint().execute();
|
||||
assertEquals(1, actual.size());
|
||||
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
||||
assertEquals(BundleEntryStatusEnum.MATCH, actual.getEntries().get(0).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.MATCH, actual.getEntries().get(0).getSearchMode().getValueAsEnum());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -27,7 +27,10 @@ public class JpaServerDemo extends RestfulServer {
|
|||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
|
||||
// We want to support FHIR DSTU2 format
|
||||
/*
|
||||
* We want to support FHIR DSTU2 format. This means that the server
|
||||
* will use the DSTU2 bundle format and other DSTU2 encoding changes.
|
||||
*/
|
||||
setFhirContext(FhirContext.forDstu2());
|
||||
|
||||
// Get the spring context from the web container (it's declared in web.xml)
|
||||
|
@ -38,14 +41,14 @@ public class JpaServerDemo extends RestfulServer {
|
|||
* file which is automatically generated as a part of hapi-fhir-jpaserver-base and
|
||||
* contains bean definitions for a resource provider for each resource type
|
||||
*/
|
||||
List<IResourceProvider> beans = myAppCtx.getBean("myResourceProvidersDev", List.class);
|
||||
List<IResourceProvider> beans = myAppCtx.getBean("myResourceProvidersDstu2", List.class);
|
||||
setResourceProviders(beans);
|
||||
|
||||
/*
|
||||
* The system provider implements non-resource-type methods, such as
|
||||
* transaction, and global history.
|
||||
*/
|
||||
JpaSystemProvider systemProvider = myAppCtx.getBean("mySystemProviderDev", JpaSystemProvider.class);
|
||||
JpaSystemProvider systemProvider = myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProvider.class);
|
||||
setPlainProviders(systemProvider);
|
||||
|
||||
/*
|
||||
|
@ -59,13 +62,17 @@ public class JpaServerDemo extends RestfulServer {
|
|||
FhirContext ctx = getFhirContext();
|
||||
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||
|
||||
|
||||
/*
|
||||
* This tells the server to use "incorrect" MIME types if it detects
|
||||
* that the request is coming from a browser in the hopes that the
|
||||
* This tells the server to use "browser friendly" MIME types if it
|
||||
* detects that the request is coming from a browser, in the hopes that the
|
||||
* browser won't just treat the content as a binary payload and try
|
||||
* to download it (which is what generally happens if you load a
|
||||
* FHIR URL in a browser)
|
||||
* FHIR URL in a browser).
|
||||
*
|
||||
* This means that the server isn't technically complying with the
|
||||
* FHIR specification for direct browser requests, but this mode
|
||||
* is very helpful for testing and troubleshooting since it means
|
||||
* you can look at FHIR URLs directly in a browser.
|
||||
*/
|
||||
setUseBrowserFriendlyContentTypes(true);
|
||||
|
||||
|
@ -78,8 +85,8 @@ public class JpaServerDemo extends RestfulServer {
|
|||
* Do some fancy logging to create a nice access log that has details about each incoming request.
|
||||
*/
|
||||
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
|
||||
loggingInterceptor.setLoggerName("fhirtest.access");
|
||||
loggingInterceptor.setMessageFormat("Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]");
|
||||
loggingInterceptor.setLoggerName("fhir.access");
|
||||
loggingInterceptor.setMessageFormat("Path[${servletPath}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]");
|
||||
this.registerInterceptor(loggingInterceptor);
|
||||
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="target/generated-resources/tinder"/>
|
||||
<classpathentry kind="src" path="target/generated-sources/tinder"/>
|
||||
<classpathentry including="**/*.java" kind="src" path="target/generated-resources/tinder"/>
|
||||
<classpathentry including="**/*.java" kind="src" path="target/generated-sources/tinder"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
|
@ -24,16 +24,16 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<attributes>
|
||||
<attribute name="owner.project.facets" value="java"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
|
|
|
@ -26,7 +26,7 @@ Copyright (c) 2011+, HL7, Inc
|
|||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Generated on Thu, Dec 18, 2014 17:00+0000 for FHIR v0.4.0
|
||||
Generated on Sat, Feb 7, 2015 18:18+0000 for FHIR v0.4.0
|
||||
-->
|
||||
<xs:schema xmlns="http://hl7.org/fhir" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://hl7.org/fhir" elementFormDefault="qualified" version="0.4.0">
|
||||
<xs:include schemaLocation="alert.xsd"/>
|
||||
|
@ -35,6 +35,7 @@ Copyright (c) 2011+, HL7, Inc
|
|||
<xs:include schemaLocation="appointmentresponse.xsd"/>
|
||||
<xs:include schemaLocation="basic.xsd"/>
|
||||
<xs:include schemaLocation="binary.xsd"/>
|
||||
<xs:include schemaLocation="bodysite.xsd"/>
|
||||
<xs:include schemaLocation="bundle.xsd"/>
|
||||
<xs:include schemaLocation="careplan.xsd"/>
|
||||
<xs:include schemaLocation="careplan2.xsd"/>
|
||||
|
|
|
@ -26,7 +26,7 @@ Copyright (c) 2011+, HL7, Inc
|
|||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Generated on Thu, Dec 18, 2014 17:00+0000 for FHIR v0.4.0
|
||||
Generated on Thu, Jan 8, 2015 07:22-0500 for FHIR v0.4.0
|
||||
-->
|
||||
<xs:schema xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:os="http://a9.com/-/spec/opensearch/1.1/" xmlns:osr="http://a9.com/-/opensearch/extensions/relevance/1.0/"
|
||||
xmlns:fhir="http://hl7.org/fhir" xmlns:at="http://purl.org/atompub/tombstones/1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://www.w3.org/2005/Atom" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@ Copyright (c) 2011+, HL7, Inc
|
|||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Generated on Thu, Dec 18, 2014 17:00+0000 for FHIR v0.4.0
|
||||
Generated on Thu, Jan 8, 2015 07:22-0500 for FHIR v0.4.0
|
||||
-->
|
||||
<xs:schema xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:os="http://a9.com/-/spec/opensearch/1.1/" xmlns:osr="http://a9.com/-/opensearch/extensions/relevance/1.0/"
|
||||
xmlns:fhir="http://hl7.org/fhir" xmlns:at="http://purl.org/atompub/tombstones/1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://www.w3.org/2005/Atom" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -94,9 +94,14 @@ public class JsonParserTest {
|
|||
" }],\n" +
|
||||
" \"entry\" : [{\n" +
|
||||
" \"base\" : \"http://foo/fhirBase2\",\n" +
|
||||
" \"status\" : \"match\",\n" +
|
||||
" \"search\" : \"http://foo/Patient?identifier=value\",\n" +
|
||||
" \"score\" : 0.123,\n" +
|
||||
" \"search\" : {\n" +
|
||||
" \"mode\" : \"match\",\n" +
|
||||
" \"score\" : 0.123\n" +
|
||||
" },\n" +
|
||||
" \"transaction\" : {\n" +
|
||||
" \"operation\" : \"create\",\n" +
|
||||
" \"match\" : \"http://foo/Patient?identifier=value\"\n" +
|
||||
" },\n" +
|
||||
" \"resource\" : {\n" +
|
||||
" \"resourceType\" : \"Patient\",\n" +
|
||||
" \"id\" : \"1\",\n" +
|
||||
|
@ -117,7 +122,8 @@ public class JsonParserTest {
|
|||
assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getId().getValue());
|
||||
assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString());
|
||||
assertEquals("0.123", ResourceMetadataKeyEnum.ENTRY_SCORE.get(pt).getValueAsString());
|
||||
assertEquals("match", ResourceMetadataKeyEnum.ENTRY_STATUS.get(pt).getCode());
|
||||
assertEquals("match", ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(pt).getCode());
|
||||
assertEquals("create", ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(pt).getCode());
|
||||
assertEquals("http://foo/Patient?identifier=value", ResourceMetadataKeyEnum.LINK_SEARCH.get(pt));
|
||||
assertEquals("2001-02-22T11:22:33-05:00", ResourceMetadataKeyEnum.UPDATED.get(pt).getValueAsString());
|
||||
|
||||
|
@ -165,17 +171,16 @@ public class JsonParserTest {
|
|||
assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
|
||||
assertEquals("1", parsed.getId().getVersionIdPart());
|
||||
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
assertEquals("transaction", parsed.getType().getValue());
|
||||
assertEquals("searchset", parsed.getType().getValue());
|
||||
assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
assertEquals("http://example.com/base", parsed.getLinkBase().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2", parsed.getLinkNext().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347", parsed.getLinkSelf().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&_include=MedicationPrescription.medication", parsed.getLinkSelf().getValue());
|
||||
|
||||
assertEquals(1, parsed.getEntries().size());
|
||||
assertEquals("update", parsed.getEntries().get(0).getStatus().getValue());
|
||||
assertEquals(2, parsed.getEntries().size());
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
assertEquals("Patient/example", p.getPatient().getReference().getValue());
|
||||
assertEquals("Patient/347", p.getPatient().getReference().getValue());
|
||||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.emptyOrNullString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
|
@ -28,7 +23,6 @@ import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
|
||||
public class XmlParserTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class);
|
||||
|
@ -62,26 +56,24 @@ public class XmlParserTest {
|
|||
|
||||
@Test
|
||||
public void testParseAndEncodeBundle() throws Exception {
|
||||
String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/bundle-example(example).xml"));
|
||||
String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/bundle-example.xml"));
|
||||
|
||||
Bundle parsed = ourCtx.newXmlParser().parseBundle(content);
|
||||
assertEquals("http://example.com/base/Bundle/example/_history/1", parsed.getId().getValue());
|
||||
assertEquals("1", parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION));
|
||||
assertEquals("1", parsed.getId().getVersionIdPart());
|
||||
assertEquals(new InstantDt("2014-08-18T01:43:30Z"), parsed.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
|
||||
assertEquals("transaction", parsed.getType().getValue());
|
||||
assertEquals("searchset", parsed.getType().getValue());
|
||||
assertEquals(3, parsed.getTotalResults().getValue().intValue());
|
||||
assertEquals("http://example.com/base", parsed.getLinkBase().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2", parsed.getLinkNext().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347", parsed.getLinkSelf().getValue());
|
||||
assertEquals("https://example.com/base/MedicationPrescription?patient=347&_include=MedicationPrescription.medication", parsed.getLinkSelf().getValue());
|
||||
|
||||
assertEquals(1, parsed.getEntries().size());
|
||||
assertEquals("update", parsed.getEntries().get(0).getStatus().getValue());
|
||||
assertEquals(BundleEntryStatusEnum.UPDATE, ResourceMetadataKeyEnum.ENTRY_STATUS.get(parsed.getEntries().get(0).getResource()));
|
||||
assertEquals(2, parsed.getEntries().size());
|
||||
assertEquals("http://foo?search", parsed.getEntries().get(0).getLinkSearch().getValue());
|
||||
|
||||
MedicationPrescription p = (MedicationPrescription) parsed.getEntries().get(0).getResource();
|
||||
assertEquals("Patient/example", p.getPatient().getReference().getValue());
|
||||
assertEquals("Patient/347", p.getPatient().getReference().getValue());
|
||||
assertEquals("2014-08-16T05:31:17Z", ResourceMetadataKeyEnum.UPDATED.get(p).getValueAsString());
|
||||
assertEquals("http://example.com/base/MedicationPrescription/3123/_history/1", p.getId().getValue());
|
||||
|
||||
|
@ -152,9 +144,14 @@ public class XmlParserTest {
|
|||
" </link>\n" +
|
||||
" <entry>\n" +
|
||||
" <base value=\"http://foo/fhirBase2\"/>\n" +
|
||||
" <status value=\"match\"/>\n" +
|
||||
" <search value=\"http://foo/Patient?identifier=value\"/>\n" +
|
||||
" <score value=\"0.123\"/>\n" +
|
||||
" <search>\n" +
|
||||
" <mode value=\"match\"/>\n" +
|
||||
" <score value=\"0.123\"/>\n" +
|
||||
" </search>\n" +
|
||||
" <transaction>\n" +
|
||||
" <operation value=\"create\"/>\n" +
|
||||
" <match value=\"http://foo/Patient?identifier=value\"/>\n" +
|
||||
" </transaction>\n" +
|
||||
" <resource>\n" +
|
||||
" <Patient xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
" <id value=\"1\"/>\n" +
|
||||
|
@ -176,7 +173,8 @@ public class XmlParserTest {
|
|||
assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getId().getValue());
|
||||
assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString());
|
||||
assertEquals("0.123", ResourceMetadataKeyEnum.ENTRY_SCORE.get(pt).getValueAsString());
|
||||
assertEquals("match", ResourceMetadataKeyEnum.ENTRY_STATUS.get(pt).getCode());
|
||||
assertEquals("match", ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(pt).getCode());
|
||||
assertEquals("create", ResourceMetadataKeyEnum.ENTRY_TRANSACTION_OPERATION.get(pt).getCode());
|
||||
assertEquals("http://foo/Patient?identifier=value", ResourceMetadataKeyEnum.LINK_SEARCH.get(pt));
|
||||
assertEquals("2001-02-22T11:22:33-05:00", ResourceMetadataKeyEnum.UPDATED.get(pt).getValueAsString());
|
||||
|
||||
|
|
|
@ -29,8 +29,9 @@ import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
|||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class ClientServerValidationTestDev {
|
||||
public class ClientServerValidationTestDstu2 {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationTestDstu2.class);
|
||||
private FhirContext myCtx;
|
||||
private HttpClient myHttpClient;
|
||||
private HttpResponse myHttpResponse;
|
||||
|
@ -40,12 +41,12 @@ public class ClientServerValidationTestDev {
|
|||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
|
||||
myCtx = FhirContext.forDstu1();
|
||||
myCtx = FhirContext.forDstu2();
|
||||
myCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsAppropriateVersionDev() throws Exception {
|
||||
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.4.0");
|
||||
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
@ -66,9 +67,9 @@ public class ClientServerValidationTestDev {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testServerReturnsWrongVersionDev() throws Exception {
|
||||
public void testServerReturnsWrongVersionForDstu2() throws Exception {
|
||||
Conformance conf = new Conformance();
|
||||
conf.setFhirVersion("0.8.0");
|
||||
conf.setFhirVersion("0.80");
|
||||
String msg = myCtx.newXmlParser().encodeResourceToString(conf);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -84,7 +85,11 @@ public class ClientServerValidationTestDev {
|
|||
myCtx.newRestfulGenericClient("http://foo");
|
||||
fail();
|
||||
} catch (FhirClientConnectionException e) {
|
||||
assertThat(e.toString(), containsString("The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.4\" which corresponds to DSTU2, but this client is configured to use DSTU1 (at FhirContext creation time)"));
|
||||
String out = e.toString();
|
||||
String want = "The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"0.80\" which corresponds to DSTU1, but this client is configured to use DSTU2 (via the FhirContext)";
|
||||
ourLog.info(out);
|
||||
ourLog.info(want);
|
||||
assertThat(out, containsString(want));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -40,7 +39,7 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryStatusEnum;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
|
@ -144,7 +143,7 @@ public class IncludeTest {
|
|||
assertEquals(new IdDt("Patient/p1"), bundle.toListOfResources().get(0).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Patient/p2"), bundle.toListOfResources().get(1).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Organization/o1"), bundle.toListOfResources().get(2).getId().toUnqualifiedVersionless());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, bundle.getEntries().get(2).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, bundle.getEntries().get(2).getSearchMode().getValueAsEnum());
|
||||
|
||||
Patient p1 = (Patient) bundle.toListOfResources().get(0);
|
||||
assertEquals(0, p1.getContained().getContainedResources().size());
|
||||
|
@ -170,7 +169,7 @@ public class IncludeTest {
|
|||
assertEquals(new IdDt("Patient/p1"), bundle.toListOfResources().get(0).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Patient/p2"), bundle.toListOfResources().get(1).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Organization/o1"), bundle.toListOfResources().get(2).getId().toUnqualifiedVersionless());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, bundle.getEntries().get(2).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, bundle.getEntries().get(2).getSearchMode().getValueAsEnum());
|
||||
|
||||
Patient p1 = (Patient) bundle.toListOfResources().get(0);
|
||||
assertEquals(0, p1.getContained().getContainedResources().size());
|
||||
|
@ -196,7 +195,7 @@ public class IncludeTest {
|
|||
assertEquals(new IdDt("Patient/p1"), bundle.toListOfResources().get(0).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Patient/p2"), bundle.toListOfResources().get(1).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Organization/o1"), bundle.toListOfResources().get(2).getId().toUnqualifiedVersionless());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, bundle.getEntries().get(2).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, bundle.getEntries().get(2).getSearchMode().getValueAsEnum());
|
||||
|
||||
Patient p1 = (Patient) bundle.toListOfResources().get(0);
|
||||
assertEquals(0, p1.getContained().getContainedResources().size());
|
||||
|
@ -223,8 +222,8 @@ public class IncludeTest {
|
|||
assertEquals(new IdDt("Patient/p2"), bundle.toListOfResources().get(1).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Organization/o1"), bundle.toListOfResources().get(2).getId().toUnqualifiedVersionless());
|
||||
assertEquals(new IdDt("Organization/o2"), bundle.toListOfResources().get(3).getId().toUnqualifiedVersionless());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, bundle.getEntries().get(2).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntryStatusEnum.INCLUDE, bundle.getEntries().get(3).getStatus().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, bundle.getEntries().get(2).getSearchMode().getValueAsEnum());
|
||||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, bundle.getEntries().get(3).getSearchMode().getValueAsEnum());
|
||||
|
||||
Patient p1 = (Patient) bundle.toListOfResources().get(0);
|
||||
assertEquals(0, p1.getContained().getContainedResources().size());
|
||||
|
|
|
@ -136,14 +136,15 @@ public class ResourceValidatorTest {
|
|||
String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("bundle-example.json"));
|
||||
Bundle b = ourCtx.newJsonParser().parseBundle(res);
|
||||
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b));
|
||||
|
||||
FhirValidator val = createFhirValidator();
|
||||
|
||||
ValidationResult result = val.validateWithResult(b);
|
||||
|
||||
OperationOutcome operationOutcome = (OperationOutcome) result.getOperationOutcome();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
|
||||
|
||||
|
||||
assertTrue(result.isSuccessful());
|
||||
assertTrue(result.toString(), result.isSuccessful());
|
||||
assertNotNull(operationOutcome);
|
||||
assertEquals(0, operationOutcome.getIssue().size());
|
||||
}
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="example"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-18T01:43:30Z"/>
|
||||
</meta>
|
||||
<type value="transaction"/>
|
||||
<base value="http://example.com/base"/>
|
||||
<total value="3"/>
|
||||
<link>
|
||||
<relation value="next"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2"/>
|
||||
</link>
|
||||
<link>
|
||||
<relation value="self"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347"/>
|
||||
</link>
|
||||
<entry>
|
||||
<status value="update"/>
|
||||
<search value="http://foo?search"/>
|
||||
<resource>
|
||||
<MedicationPrescription>
|
||||
<id value="3123"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-16T05:31:17Z"/>
|
||||
</meta>
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Penicillin VK 5ml suspension to be administered by oral route</p>
|
||||
<p>ONE 5ml spoonful to be taken THREE times a day</p>
|
||||
<p>100ml bottle</p>
|
||||
<p>to patient ref: a23</p>
|
||||
<p>by doctor X</p>
|
||||
</div>
|
||||
</text>
|
||||
<status value="active"/>
|
||||
<patient>
|
||||
<reference value="Patient/example"/>
|
||||
</patient>
|
||||
<prescriber>
|
||||
<reference value="Practitioner/example"/>
|
||||
</prescriber>
|
||||
|
||||
<medication>
|
||||
<reference value="Medication/example"/>
|
||||
</medication>
|
||||
|
||||
<dosageInstruction>
|
||||
<scheduledTiming>
|
||||
<repeat>
|
||||
<frequency value="3"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</scheduledTiming>
|
||||
<route>
|
||||
<coding>
|
||||
<system value="http://snomed.info/sct"/>
|
||||
<code value="394899003"/>
|
||||
<display value="oral administration of treatment"/>
|
||||
</coding>
|
||||
</route>
|
||||
<doseQuantity>
|
||||
<value value="5"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</doseQuantity>
|
||||
</dosageInstruction>
|
||||
|
||||
<dispense>
|
||||
<quantity>
|
||||
<value value="100"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</quantity>
|
||||
</dispense>
|
||||
|
||||
</MedicationPrescription>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -5,7 +5,7 @@
|
|||
"versionId": "1",
|
||||
"lastUpdated": "2014-08-18T01:43:30Z"
|
||||
},
|
||||
"type": "transaction",
|
||||
"type": "searchset",
|
||||
"base": "http://example.com/base",
|
||||
"total": 3,
|
||||
"link": [
|
||||
|
@ -15,68 +15,38 @@
|
|||
},
|
||||
{
|
||||
"relation": "self",
|
||||
"url": "https://example.com/base/MedicationPrescription?patient=347"
|
||||
"url": "https://example.com/base/MedicationPrescription?patient=347&_include=MedicationPrescription.medication"
|
||||
}
|
||||
],
|
||||
"entry": [
|
||||
{
|
||||
"status": "update",
|
||||
"search": {
|
||||
"mode": "match",
|
||||
"score": 1
|
||||
},
|
||||
"resource": {
|
||||
"resourceType": "MedicationPrescription",
|
||||
"id": "3123",
|
||||
"meta": {
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2014-08-16T05:31:17Z"
|
||||
"meta" : {
|
||||
"versionId" : "1",
|
||||
"lastUpdated" : "2014-08-16T05:31:17Z"
|
||||
},
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div>\n <p>Penicillin VK 5ml suspension to be administered by oral route</p>\n <p>ONE 5ml spoonful to be taken THREE times a day</p>\n <p>100ml bottle</p>\n <p>to patient ref: a23</p>\n <p>by doctor X</p>\n </div>"
|
||||
},
|
||||
"status": "active",
|
||||
"patient": {
|
||||
"reference": "Patient/example"
|
||||
},
|
||||
"prescriber": {
|
||||
"reference": "Practitioner/example"
|
||||
"reference": "Patient/347"
|
||||
},
|
||||
"medication": {
|
||||
"reference": "Medication/example"
|
||||
},
|
||||
"dosageInstruction": [
|
||||
{
|
||||
"scheduledTiming": {
|
||||
"repeat": {
|
||||
"frequency": 3,
|
||||
"duration": 1,
|
||||
"units": "d"
|
||||
}
|
||||
},
|
||||
"route": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://snomed.info/sct",
|
||||
"code": "394899003",
|
||||
"display": "oral administration of treatment"
|
||||
}
|
||||
]
|
||||
},
|
||||
"doseQuantity": {
|
||||
"value": 5,
|
||||
"units": "ml",
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "ml"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dispense": {
|
||||
"quantity": {
|
||||
"value": 100,
|
||||
"units": "ml",
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "ml"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"search": {
|
||||
"mode": "include"
|
||||
},
|
||||
"resource": {
|
||||
"resourceType": "Medication",
|
||||
"id": "example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="example"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-18T01:43:30Z"/>
|
||||
</meta>
|
||||
<type value="transaction"/>
|
||||
<type value="searchset"/>
|
||||
<base value="http://example.com/base"/>
|
||||
<total value="3"/>
|
||||
<link>
|
||||
|
@ -14,72 +13,40 @@
|
|||
</link>
|
||||
<link>
|
||||
<relation value="self"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347"/>
|
||||
<url value="https://example.com/base/MedicationPrescription?patient=347&_include=MedicationPrescription.medication"/>
|
||||
</link>
|
||||
<entry>
|
||||
<status value="update"/>
|
||||
<search>
|
||||
<mode value="match"/>
|
||||
<score value="1"/>
|
||||
</search>
|
||||
<transaction>
|
||||
<match value="http://foo?search"/>
|
||||
</transaction>
|
||||
<resource>
|
||||
<MedicationPrescription>
|
||||
<id value="3123"/>
|
||||
<meta>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-16T05:31:17Z"/>
|
||||
<versionId value="1"/>
|
||||
<lastUpdated value="2014-08-16T05:31:17Z"/>
|
||||
</meta>
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Penicillin VK 5ml suspension to be administered by oral route</p>
|
||||
<p>ONE 5ml spoonful to be taken THREE times a day</p>
|
||||
<p>100ml bottle</p>
|
||||
<p>to patient ref: a23</p>
|
||||
<p>by doctor X</p>
|
||||
</div>
|
||||
</text>
|
||||
<status value="active"/>
|
||||
<patient>
|
||||
<reference value="Patient/example"/>
|
||||
<reference value="Patient/347"/>
|
||||
</patient>
|
||||
<prescriber>
|
||||
<reference value="Practitioner/example"/>
|
||||
</prescriber>
|
||||
|
||||
<medication>
|
||||
<reference value="Medication/example"/>
|
||||
</medication>
|
||||
|
||||
<dosageInstruction>
|
||||
<scheduledTiming>
|
||||
<repeat>
|
||||
<frequency value="3"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</scheduledTiming>
|
||||
<route>
|
||||
<coding>
|
||||
<system value="http://snomed.info/sct"/>
|
||||
<code value="394899003"/>
|
||||
<display value="oral administration of treatment"/>
|
||||
</coding>
|
||||
</route>
|
||||
<doseQuantity>
|
||||
<value value="5"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</doseQuantity>
|
||||
</dosageInstruction>
|
||||
|
||||
<dispense>
|
||||
<quantity>
|
||||
<value value="100"/>
|
||||
<units value="ml"/>
|
||||
<system value="http://unitsofmeasure.org"/>
|
||||
<code value="ml"/>
|
||||
</quantity>
|
||||
</dispense>
|
||||
|
||||
</MedicationPrescription>
|
||||
</resource>
|
||||
</entry>
|
||||
<entry>
|
||||
<search>
|
||||
<mode value="include"/>
|
||||
</search>
|
||||
<resource>
|
||||
<Medication>
|
||||
<id value="example"/>
|
||||
</Medication>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
35
pom.xml
35
pom.xml
|
@ -601,22 +601,6 @@
|
|||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<classFilesDirectory>./hapi-fhir-base/target/classes</classFilesDirectory>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>findbugs</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
|
||||
<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-linkcheck-plugin</artifactId>
|
||||
<version>1.1</version> </plugin> -->
|
||||
</plugins>
|
||||
|
@ -687,6 +671,25 @@
|
|||
<module>hapi-fhir-jpaserver-base</module>
|
||||
<module>examples</module>
|
||||
</modules>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<classFilesDirectory>./hapi-fhir-base/target/classes</classFilesDirectory>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>findbugs</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>ALLMODULES</id>
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project xmlns="http://maven.apache.org/DECORATION/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.1.0 http://maven.apache.org/xsd/decoration-1.1.0.xsd" name="HAPI">
|
||||
|
||||
<bannerLeft>
|
||||
<name>HAPI</name>
|
||||
<src>images/hapi_fhir_banner.png</src>
|
||||
<href>http://jamesagnew.github.io/hapi-fhir/</href>
|
||||
</bannerLeft>
|
||||
|
||||
<bannerRight>
|
||||
<name>FHIR</name>
|
||||
<src>images/hapi_fhir_banner_right.png</src>
|
||||
<href>http://jamesagnew.github.io/hapi-fhir/</href>
|
||||
</bannerRight>
|
||||
|
||||
<poweredBy>
|
||||
<logo name="Hosted on GitHub" href="https://github.com/jamesagnew/hapi-fhir" img="./images/github-logo-mini.png"/>
|
||||
<logo name="Built with Maven 3" href="http://maven.apache.org" img="./images/maven-logo-mini.png" />
|
||||
</poweredBy>
|
||||
|
||||
<version position="left" />
|
||||
|
||||
<body>
|
||||
<head>
|
||||
<!-- Syntax Highlighter -->
|
||||
<script type="text/javascript" src="syntaxhighlighter/shCore.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushJScript.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushJava.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushBash.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushXml.js"></script>
|
||||
<link href="syntaxhighlighter/shCore.css" rel="stylesheet" type="text/css" />
|
||||
<link href="syntaxhighlighter/shThemeDefault.css" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!--
|
||||
HAPI stylesheet comes after because it overwrites the Syntax Highlighter
|
||||
font size
|
||||
-->
|
||||
<link rel="shortcut icon" href="https://github.com/jamesagnew/hapi-fhir/images/favicon.png" />
|
||||
<link rel="stylesheet" type="text/css" href="hapi.css" />
|
||||
</head>
|
||||
|
||||
<links>
|
||||
<item name="GitHub Page" href="https://github.com/jamesagnew/hapi-fhir/" />
|
||||
<item name="hl7.org" href="http://hl7.org/" />
|
||||
<item name="University Health Network" href="http://www.uhn.ca/" />
|
||||
</links>
|
||||
|
||||
<menu name="Welcome">
|
||||
<item name="Welcome" href="index.html" />
|
||||
<item name="Download" href="./download.html" />
|
||||
<item name="Upgrade Guide" href="./doc_upgrading.html" />
|
||||
<item name="Changelog" href="./changes-report.html" />
|
||||
</menu>
|
||||
|
||||
<menu name="Test Server">
|
||||
<item name="Public Test Server" href="http://fhirtest.uhn.ca"/>
|
||||
<item name="Vagrant (Private) Test Server" href="doc_vagrant.html"/>
|
||||
</menu>
|
||||
|
||||
<menu name="Documentation">
|
||||
<item name="Introduction" href="./doc_intro.html" />
|
||||
<item name="The Data Model" href="./doc_fhirobjects.html">
|
||||
<item name="Profiles & Extensions" href="./doc_extensions.html" />
|
||||
<item name="Resource References" href="./doc_resource_references.html" />
|
||||
<item name="Tags" href="./doc_tags.html" />
|
||||
<item name="Validation" href="./doc_validation.html" />
|
||||
</item>
|
||||
<item name="RESTful Client" href="./doc_rest_client.html" >
|
||||
<item name="Interceptors (client)" href="./doc_rest_client_interceptor.html"/>
|
||||
</item>
|
||||
<item name="RESTful Server" href="./doc_rest_server.html" >
|
||||
<item name="RESTful Operations" href="./doc_rest_operations.html" />
|
||||
<item name="Narrative Generator" href="./doc_narrative.html" />
|
||||
<item name="CORS Support" href="./doc_cors.html" />
|
||||
<item name="Interceptors (server)" href="./doc_rest_server_interceptor.html" />
|
||||
<item name="Web Testing UI" href="./doc_server_tester.html" />
|
||||
</item>
|
||||
<item name="Logging" href="./doc_logging.html" />
|
||||
<item name="Tinder Plugin" href="./doc_tinder.html" />
|
||||
</menu>
|
||||
|
||||
<menu name="Community">
|
||||
<item name="Google Group" href="https://groups.google.com/d/forum/hapi-fhir" />
|
||||
<item name="Issue Tracker" href="https://github.com/jamesagnew/hapi-fhir/issues" />
|
||||
</menu>
|
||||
|
||||
<menu name="JavaDocs">
|
||||
<<<<<<< HEAD:src/site/site.xml
|
||||
<item name="API (Core)" href="./apidocs/index.html" />
|
||||
<item name="API (DSTU Model)" href="./apidocs-dstu/index.html" />
|
||||
<item name="API (DEV Model)" href="./apidocs-dev/index.html" />
|
||||
=======
|
||||
<item name="Core API" href="./apidocs/index.html" />
|
||||
<item name="Model API (DSTU1)" href="./apidocs-dstu/index.html" />
|
||||
<item name="Model API (DEV)" href="./apidocs-dev/index.html" />
|
||||
>>>>>>> d22a35788f57e9f7ce64bc8afc2ee7eaf29d94f2:src/site/site.xml
|
||||
<item name="Source Code" href=".https://github.com/jamesagnew/hapi-fhir" />
|
||||
</menu>
|
||||
|
||||
<menu name="Reports">
|
||||
<item name="Developers" href="team-list.html" />
|
||||
<item name="Unit Test Report" href="surefire-report.html" />
|
||||
<item name="FindBugs" href="findbugs.html" />
|
||||
<item name="License" href="license.html" />
|
||||
<item name="Source Code" href="https://github.com/jamesagnew/hapi-fhir" />
|
||||
</menu>
|
||||
|
||||
</body>
|
||||
|
||||
<skin>
|
||||
<groupId>org.apache.maven.skins</groupId>
|
||||
<artifactId>maven-fluido-skin</artifactId>
|
||||
<version>1.3.1</version>
|
||||
</skin>
|
||||
|
||||
<custom>
|
||||
<fluidoSkin>
|
||||
<googleSearch />
|
||||
<!-- <sourceLineNumbersEnabled>true</sourceLineNumbersEnabled> -->
|
||||
</fluidoSkin>
|
||||
</custom>
|
||||
|
||||
</project>
|
||||
|
Loading…
Reference in New Issue