mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-07 05:28:21 +00:00
Merge branch 'master' of github.com:jamesagnew/hapi-fhir
This commit is contained in:
commit
89f3df80a4
@ -354,11 +354,6 @@ public abstract class BaseRuntimeElementCompositeDefinition<T extends IBase> ext
|
||||
RuntimeChildChoiceDefinition def = new RuntimeChildChoiceDefinition(next, elementName, childAnnotation, descriptionAnnotation, choiceTypes);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (next.getType().equals(ExtensionDt.class)) {
|
||||
|
||||
RuntimeChildExtensionDt def = new RuntimeChildExtensionDt(next, elementName, childAnnotation, descriptionAnnotation);
|
||||
orderMap.put(order, def);
|
||||
|
||||
} else if (extensionAttr != null) {
|
||||
/*
|
||||
* Child is an extension
|
||||
@ -427,8 +422,6 @@ public abstract class BaseRuntimeElementCompositeDefinition<T extends IBase> ext
|
||||
} else {
|
||||
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
|
||||
}
|
||||
} else if (IBaseXhtml.class.isAssignableFrom(nextElementType)) {
|
||||
def = new RuntimeChildXhtmlDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
|
||||
} else {
|
||||
if (IBoundCodeableConcept.class.isAssignableFrom(nextElementType)) {
|
||||
IValueSetEnumBinder<Enum<?>> binder = ModelScanner.getBoundCodeBinder(next);
|
||||
|
@ -44,6 +44,7 @@ import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
|
||||
@ -574,6 +575,8 @@ class ModelScanner {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException("Failed to load model property file from classpath: " + "/ca/uhn/fhir/model/dstu/model.properties");
|
||||
} finally {
|
||||
IOUtils.closeQuietly(str);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
@ -1,40 +0,0 @@
|
||||
package ca.uhn.fhir.context;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.lang.reflect.Field;
|
||||
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
||||
public class RuntimeChildExtensionDt extends RuntimeChildAny {
|
||||
|
||||
public RuntimeChildExtensionDt(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation) {
|
||||
super(theField, theElementName, theChildAnnotation, theDescriptionAnnotation);
|
||||
}
|
||||
|
||||
public IElement newInstance() {
|
||||
return new ExtensionDt();
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package ca.uhn.fhir.context;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.lang.reflect.Field;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
|
||||
/**
|
||||
* HL7org XHTML type
|
||||
*/
|
||||
public class RuntimeChildXhtmlDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
|
||||
|
||||
public RuntimeChildXhtmlDatatypeDefinition(Field theField, String theElementName, Description theDescriptionAnnotation, Child theChildAnnotation, Class<? extends IBase> theDatatype) {
|
||||
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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%
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Represents a FHIR resource path specification, e.g.
|
||||
* <code>Patient.gender.coding</code>
|
||||
* <p>
|
||||
* Note on equality: This class uses the {@link PathSpecification#setValue(String) value}
|
||||
* as the single item used to provide {@link #hashCode()} and {@link #equals(Object)}.
|
||||
* </p>
|
||||
*
|
||||
* @deprecated {@link Include} should be used instead
|
||||
*/
|
||||
@CoverageIgnore
|
||||
@Deprecated
|
||||
public class PathSpecification extends Include {
|
||||
|
||||
public PathSpecification(String theInclude) {
|
||||
super(theInclude);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
|
||||
package ca.uhn.fhir.model.dstu.valueset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
@CoverageIgnore
|
||||
public enum SecurityEventObjectSensitivityEnum {
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Identifier for this Value Set:
|
||||
* http://hl7.org/fhir/vs/security-event-sensitivity
|
||||
*/
|
||||
public static final String VALUESET_IDENTIFIER = "http://hl7.org/fhir/vs/security-event-sensitivity";
|
||||
|
||||
/**
|
||||
* Name for this Value Set:
|
||||
* Security Event Object Sensitivity
|
||||
*/
|
||||
public static final String VALUESET_NAME = "Security Event Object Sensitivity";
|
||||
|
||||
private static Map<String, SecurityEventObjectSensitivityEnum> CODE_TO_ENUM = new HashMap<String, SecurityEventObjectSensitivityEnum>();
|
||||
private static Map<String, Map<String, SecurityEventObjectSensitivityEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, SecurityEventObjectSensitivityEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (SecurityEventObjectSensitivityEnum next : SecurityEventObjectSensitivityEnum.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, SecurityEventObjectSensitivityEnum>());
|
||||
}
|
||||
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 SecurityEventObjectSensitivityEnum forCode(String theCode) {
|
||||
SecurityEventObjectSensitivityEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<SecurityEventObjectSensitivityEnum> VALUESET_BINDER = new IValueSetEnumBinder<SecurityEventObjectSensitivityEnum>() {
|
||||
@Override
|
||||
public String toCodeString(SecurityEventObjectSensitivityEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(SecurityEventObjectSensitivityEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityEventObjectSensitivityEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityEventObjectSensitivityEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, SecurityEventObjectSensitivityEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(theCodeString);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
SecurityEventObjectSensitivityEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
|
||||
package ca.uhn.fhir.model.dstu.valueset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
@CoverageIgnore
|
||||
public enum SecurityEventObjectTypeEnum {
|
||||
|
||||
/**
|
||||
* Code Value: <b>1</b>
|
||||
*
|
||||
* Person.
|
||||
*/
|
||||
PERSON("1", "http://hl7.org/fhir/object-type"),
|
||||
|
||||
/**
|
||||
* Code Value: <b>2</b>
|
||||
*
|
||||
* System Object.
|
||||
*/
|
||||
SYSTEM_OBJECT("2", "http://hl7.org/fhir/object-type"),
|
||||
|
||||
/**
|
||||
* Code Value: <b>3</b>
|
||||
*
|
||||
* Organization.
|
||||
*/
|
||||
ORGANIZATION("3", "http://hl7.org/fhir/object-type"),
|
||||
|
||||
/**
|
||||
* Code Value: <b>4</b>
|
||||
*
|
||||
* Other.
|
||||
*/
|
||||
OTHER("4", "http://hl7.org/fhir/object-type"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Identifier for this Value Set:
|
||||
* http://hl7.org/fhir/vs/object-type
|
||||
*/
|
||||
public static final String VALUESET_IDENTIFIER = "http://hl7.org/fhir/vs/object-type";
|
||||
|
||||
/**
|
||||
* Name for this Value Set:
|
||||
* SecurityEventObjectType
|
||||
*/
|
||||
public static final String VALUESET_NAME = "SecurityEventObjectType";
|
||||
|
||||
private static Map<String, SecurityEventObjectTypeEnum> CODE_TO_ENUM = new HashMap<String, SecurityEventObjectTypeEnum>();
|
||||
private static Map<String, Map<String, SecurityEventObjectTypeEnum>> SYSTEM_TO_CODE_TO_ENUM = new HashMap<String, Map<String, SecurityEventObjectTypeEnum>>();
|
||||
|
||||
private final String myCode;
|
||||
private final String mySystem;
|
||||
|
||||
static {
|
||||
for (SecurityEventObjectTypeEnum next : SecurityEventObjectTypeEnum.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, SecurityEventObjectTypeEnum>());
|
||||
}
|
||||
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 SecurityEventObjectTypeEnum forCode(String theCode) {
|
||||
SecurityEventObjectTypeEnum retVal = CODE_TO_ENUM.get(theCode);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codes to their respective enumerated values
|
||||
*/
|
||||
public static final IValueSetEnumBinder<SecurityEventObjectTypeEnum> VALUESET_BINDER = new IValueSetEnumBinder<SecurityEventObjectTypeEnum>() {
|
||||
@Override
|
||||
public String toCodeString(SecurityEventObjectTypeEnum theEnum) {
|
||||
return theEnum.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSystemString(SecurityEventObjectTypeEnum theEnum) {
|
||||
return theEnum.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityEventObjectTypeEnum fromCodeString(String theCodeString) {
|
||||
return CODE_TO_ENUM.get(theCodeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityEventObjectTypeEnum fromCodeString(String theCodeString, String theSystemString) {
|
||||
Map<String, SecurityEventObjectTypeEnum> map = SYSTEM_TO_CODE_TO_ENUM.get(theSystemString);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(theCodeString);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
SecurityEventObjectTypeEnum(String theCode, String theSystem) {
|
||||
myCode = theCode;
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -52,6 +52,7 @@ public class TimeDt extends StringDt implements IQueryParameterType {
|
||||
*/
|
||||
@SimpleSetter
|
||||
public TimeDt(@SimpleSetter.Parameter(name = "theString") String theValue) {
|
||||
this();
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
package ca.uhn.fhir.narrative;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.thymeleaf.TemplateProcessingParameters;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolution;
|
||||
|
||||
public class ThymeleafResolver implements ITemplateResolver {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ThymeleafResolver.class);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateResolution resolveTemplate(TemplateProcessingParameters theTemplateProcessingParameters) {
|
||||
|
||||
String templateName = theTemplateProcessingParameters.getTemplateName();
|
||||
ourLog.info("Resolving template: {}", templateName);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -314,21 +314,6 @@ public abstract class BaseParser implements IParser {
|
||||
}
|
||||
}
|
||||
|
||||
protected String determineResourceBaseUrl(String bundleBaseUrl, BundleEntry theEntry) {
|
||||
IResource resource = theEntry.getResource();
|
||||
if (resource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String resourceBaseUrl = null;
|
||||
if (resource.getId() != null && resource.getId().hasBaseUrl()) {
|
||||
if (!resource.getId().getBaseUrl().equals(bundleBaseUrl)) {
|
||||
resourceBaseUrl = resource.getId().getBaseUrl();
|
||||
}
|
||||
}
|
||||
return resourceBaseUrl;
|
||||
}
|
||||
|
||||
protected abstract void doEncodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException, DataFormatException;
|
||||
|
||||
protected abstract void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
|
||||
|
@ -70,6 +70,13 @@ import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
|
||||
public abstract class BaseClient implements IRestfulClient {
|
||||
|
||||
/**
|
||||
* This property is used by unit tests - do not rely on it in production code
|
||||
* as it may change at any time. If you want to capture responses in a reliable
|
||||
* way in your own code, just use client interceptors
|
||||
*/
|
||||
static final String HAPI_CLIENT_KEEPRESPONSES = "hapi.client.keepresponses";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseClient.class);
|
||||
|
||||
private final IHttpClient myClient;
|
||||
@ -89,6 +96,15 @@ public abstract class BaseClient implements IRestfulClient {
|
||||
myClient = theClient;
|
||||
myUrlBase = theUrlBase;
|
||||
myFactory = theFactory;
|
||||
|
||||
/*
|
||||
* This property is used by unit tests - do not rely on it in production code
|
||||
* as it may change at any time. If you want to capture responses in a reliable
|
||||
* way in your own code, just use client interceptors
|
||||
*/
|
||||
if ("true".equals(System.getProperty(HAPI_CLIENT_KEEPRESPONSES))) {
|
||||
setKeepResponses(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, List<String>> createExtraParams() {
|
||||
@ -193,7 +209,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||
|
||||
// TODO: handle non 2xx status codes by throwing the correct exception,
|
||||
// and ensure it's passed upwards
|
||||
IHttpRequest httpRequest;
|
||||
IHttpRequest httpRequest = null;
|
||||
IHttpResponse response = null;
|
||||
try {
|
||||
Map<String, List<String>> params = createExtraParams();
|
||||
@ -339,11 +355,13 @@ public abstract class BaseClient implements IRestfulClient {
|
||||
}
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
String msg = getFhirContext().getLocalizer().getMessage(BaseClient.class, "failedToParseResponse", httpRequest.getHttpVerbName(), httpRequest.getUri(), e.toString());
|
||||
throw new FhirClientConnectionException(msg, e);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} catch (IOException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
String msg = getFhirContext().getLocalizer().getMessage(BaseClient.class, "ioExceptionDuringOperation", httpRequest.getHttpVerbName(), httpRequest.getUri(), e.toString());
|
||||
throw new FhirClientConnectionException(msg, e);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
@ -76,6 +76,7 @@ import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.gclient.IClientExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateTyped;
|
||||
@ -136,7 +137,7 @@ import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
import ca.uhn.fhir.rest.method.SortParameter;
|
||||
import ca.uhn.fhir.rest.method.TransactionMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu1;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu2;
|
||||
import ca.uhn.fhir.rest.method.ValidateMethodBindingDstu2Plus;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
@ -174,8 +175,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
|
||||
@Override
|
||||
public IBaseConformance conformance() {
|
||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
|
||||
throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/DSTU3+ structures");
|
||||
if (myContext.getVersion().getVersion().isRi()) {
|
||||
throw new IllegalArgumentException("Must call fetchConformance() instead of conformance() for RI/STU3+ structures");
|
||||
}
|
||||
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation(getFhirContext());
|
||||
@ -376,7 +377,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
|
||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_CANNOT_DETEMINE_RESOURCE_TYPE, theUrl.getValueAsString()));
|
||||
|
||||
}
|
||||
|
||||
@ -385,6 +386,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
// return doReadOrVRead(theType, theId, false, null, null);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link LoggingInterceptor} as a client interceptor registered to your
|
||||
* client instead, as this provides much more fine-grained control over what is logged. This
|
||||
* method will be removed at some point (deprecated in HAPI 1.6 - 2016-06-16)
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isLogRequestAndResponse() {
|
||||
return myLogRequestAndResponse;
|
||||
}
|
||||
@ -549,7 +556,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
invocation = ValidateMethodBindingDstu1.createValidateInvocation(theResource, null, myContext);
|
||||
} else {
|
||||
invocation = ValidateMethodBindingDstu2.createValidateInvocation(myContext, theResource);
|
||||
invocation = ValidateMethodBindingDstu2Plus.createValidateInvocation(myContext, theResource);
|
||||
}
|
||||
|
||||
if (isKeepResponses()) {
|
||||
@ -714,7 +721,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
protected IBaseResource parseResourceBody(String theResourceBody) {
|
||||
EncodingEnum encoding = MethodUtil.detectEncodingNoDefault(theResourceBody);
|
||||
if (encoding == null) {
|
||||
throw new InvalidRequestException("FHIR client can't determine resource encoding");
|
||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "cantDetermineRequestType"));
|
||||
}
|
||||
return encoding.newParser(myContext).parseResource(theResourceBody);
|
||||
}
|
||||
@ -2213,7 +2220,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
myRawBundle = theBundle;
|
||||
myRawBundleEncoding = MethodUtil.detectEncodingNoDefault(myRawBundle);
|
||||
if (myRawBundleEncoding == null) {
|
||||
throw new IllegalArgumentException("Can not determine encoding of raw resource body");
|
||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "cantDetermineRequestType"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2402,7 +2409,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
|
||||
@Override
|
||||
public MethodOutcome execute() {
|
||||
BaseHttpClientInvocation invocation = ValidateMethodBindingDstu2.createValidateInvocation(myContext, myResource);
|
||||
BaseHttpClientInvocation invocation = ValidateMethodBindingDstu2Plus.createValidateInvocation(myContext, myResource);
|
||||
ResourceResponseHandler<BaseOperationOutcome> handler = new ResourceResponseHandler<BaseOperationOutcome>(null, null);
|
||||
IBaseOperationOutcome outcome = invoke(null, handler, invocation);
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
@ -2424,7 +2431,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||
|
||||
EncodingEnum enc = MethodUtil.detectEncodingNoDefault(theResourceRaw);
|
||||
if (enc == null) {
|
||||
throw new IllegalArgumentException("Could not detect encoding (XML/JSON) in string. Is this a valid FHIR resource?");
|
||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(GenericClient.class, "cantDetermineRequestType"));
|
||||
}
|
||||
switch (enc) {
|
||||
case XML:
|
||||
|
@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
import ca.uhn.fhir.rest.gclient.IDelete;
|
||||
import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
|
||||
@ -288,7 +289,11 @@ public interface IGenericClient extends IRestfulClient {
|
||||
*
|
||||
* @param theLogRequestAndResponse
|
||||
* Should requests and responses be logged
|
||||
* @deprecated Use {@link LoggingInterceptor} as a client interceptor registered to your
|
||||
* client instead, as this provides much more fine-grained control over what is logged. This
|
||||
* method will be removed at some point (deprecated in HAPI 1.6 - 2016-06-16)
|
||||
*/
|
||||
@Deprecated
|
||||
void setLogRequestAndResponse(boolean theLogRequestAndResponse);
|
||||
|
||||
/**
|
||||
|
@ -194,7 +194,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, IHttpClient theHttpClient, BaseClient theClient) {
|
||||
String serverBase = normalizeBaseUrlForMap(theServerBase);
|
||||
|
||||
switch (myServerValidationMode) {
|
||||
switch (getServerValidationMode()) {
|
||||
case NEVER:
|
||||
break;
|
||||
case ONCE:
|
||||
@ -267,22 +267,6 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||
myPoolMaxPerRoute = thePoolMaxPerRoute;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new client invocation handler
|
||||
* @param theClient
|
||||
* the client which will invoke the call
|
||||
* @param theUrlBase
|
||||
* the url base
|
||||
* @param theMethodToReturnValue
|
||||
* @param theBindings
|
||||
* @param theMethodToLambda
|
||||
* @return a newly created client invocation handler
|
||||
*/
|
||||
ClientInvocationHandler newInvocationHandler(IHttpClient theClient, String theUrlBase, Map<Method, Object> theMethodToReturnValue, Map<Method, BaseMethodBinding<?>> theBindings, Map<Method, ClientInvocationHandlerFactory.ILambda> theMethodToLambda) {
|
||||
return new ClientInvocationHandler(theClient, getFhirContext(), theUrlBase.toString(), theMethodToReturnValue,
|
||||
theBindings, theMethodToLambda, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@ -300,7 +284,8 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||
Class implementingClass = myContext.getResourceDefinition("Conformance").getImplementingClass();
|
||||
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
|
||||
} catch (FhirClientConnectionException e) {
|
||||
throw new FhirClientConnectionException(myContext.getLocalizer().getMessage(RestfulClientFactory.class, "failedToRetrieveConformance", theServerBase + Constants.URL_TOKEN_METADATA), e);
|
||||
String msg = myContext.getLocalizer().getMessage(RestfulClientFactory.class, "failedToRetrieveConformance", theServerBase + Constants.URL_TOKEN_METADATA);
|
||||
throw new FhirClientConnectionException(msg, e);
|
||||
}
|
||||
|
||||
FhirTerser t = myContext.newTerser();
|
||||
|
@ -44,8 +44,8 @@ import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
*/
|
||||
public class ApacheHttpRequest implements IHttpRequest {
|
||||
|
||||
private HttpRequestBase myRequest;
|
||||
private HttpClient myClient;
|
||||
private HttpRequestBase myRequest;
|
||||
|
||||
public ApacheHttpRequest(HttpClient theClient, HttpRequestBase theApacheRequest) {
|
||||
this.myClient = theClient;
|
||||
@ -57,14 +57,6 @@ public class ApacheHttpRequest implements IHttpRequest {
|
||||
myRequest.addHeader(theName, theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ApacheRequest
|
||||
* @return the ApacheRequest
|
||||
*/
|
||||
public HttpRequestBase getApacheRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpResponse execute() throws IOException {
|
||||
return new ApacheHttpResponse(myClient.execute(myRequest));
|
||||
@ -82,9 +74,17 @@ public class ApacheHttpRequest implements IHttpRequest {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ApacheRequest
|
||||
* @return the ApacheRequest
|
||||
*/
|
||||
public HttpRequestBase getApacheRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myRequest.toString();
|
||||
public String getHttpVerbName() {
|
||||
return myRequest.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -98,4 +98,14 @@ public class ApacheHttpRequest implements IHttpRequest {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUri() {
|
||||
return myRequest.getURI().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myRequest.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ public class ApacheRestfulClientFactory extends RestfulClientFactory {
|
||||
* Constructor
|
||||
*/
|
||||
public ApacheRestfulClientFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,4 +56,14 @@ public interface IHttpRequest {
|
||||
*/
|
||||
public String getRequestBodyFromStream() throws IOException;
|
||||
|
||||
/**
|
||||
* Return the request URI, or null
|
||||
*/
|
||||
public String getUri();
|
||||
|
||||
/**
|
||||
* Return the HTTP verb (e.g. "GET")
|
||||
*/
|
||||
public String getHttpVerbName();
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
@ -200,9 +201,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
||||
if (myParams != null) {
|
||||
return httpClient.createParamRequest(getContext(), myParams, encoding);
|
||||
} else {
|
||||
if (encoding == null) {
|
||||
encoding = EncodingEnum.XML;
|
||||
}
|
||||
encoding = ObjectUtils.defaultIfNull(encoding, EncodingEnum.XML);
|
||||
String contents = encodeContents(thePrettyPrint, encoding);
|
||||
String contentType = getContentType(encoding);
|
||||
return httpClient.createByteRequest(getContext(), contents, contentType, encoding);
|
||||
|
@ -516,7 +516,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
||||
if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
||||
return new ValidateMethodBindingDstu1(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
return new ValidateMethodBindingDstu2(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
|
||||
return new ValidateMethodBindingDstu2Plus(returnType, returnTypeFromRp, theMethod, theContext, theProvider, validate);
|
||||
}
|
||||
} else if (getTags != null) {
|
||||
return new GetTagsMethodBinding(theMethod, theContext, theProvider, getTags);
|
||||
|
@ -253,7 +253,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
Set<SummaryEnum> summaryMode = Collections.emptySet();
|
||||
|
||||
return restfulResponse.streamResponseAsResource(outcome, prettyPrint, summaryMode, operationStatus, theRequest.isRespondGzip(), true);
|
||||
return restfulResponse.streamResponseAsResource(outcome, prettyPrint, summaryMode, operationStatus, null, theRequest.isRespondGzip(), true);
|
||||
// return theRequest.getResponse().returnResponse(ParseAction.create(outcome), operationStatus, allowPrefer, response, getResourceName());
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
@ -45,7 +46,6 @@ import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
@ -232,7 +232,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
||||
return resource;
|
||||
case METHOD_OUTCOME:
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
retVal.setOperationOutcome((BaseOperationOutcome) resource);
|
||||
retVal.setOperationOutcome((IBaseOperationOutcome) resource);
|
||||
return retVal;
|
||||
}
|
||||
break;
|
||||
@ -260,8 +260,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
||||
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
|
||||
return theRequest.getResponse().streamResponseAsResource(responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(),
|
||||
isAddContentLocationHeader());
|
||||
return theRequest.getResponse().streamResponseAsResource(responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, null,
|
||||
theRequest.isRespondGzip(), isAddContentLocationHeader());
|
||||
|
||||
} else {
|
||||
// Is this request coming from a browser
|
||||
|
@ -31,7 +31,6 @@ import java.util.TreeSet;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.param.BaseQueryParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
@ -60,7 +59,7 @@ class IncludeParameter extends BaseQueryParameter {
|
||||
}
|
||||
|
||||
mySpecType = theSpecType;
|
||||
if (mySpecType != Include.class && mySpecType != PathSpecification.class && mySpecType != String.class) {
|
||||
if (mySpecType != Include.class && mySpecType != String.class) {
|
||||
throw new ConfigurationException("Invalid @" + IncludeParam.class.getSimpleName() + " parameter type: " + mySpecType);
|
||||
}
|
||||
|
||||
@ -72,7 +71,7 @@ class IncludeParameter extends BaseQueryParameter {
|
||||
ArrayList<QualifiedParamList> retVal = new ArrayList<QualifiedParamList>();
|
||||
|
||||
if (myInstantiableCollectionType == null) {
|
||||
if (mySpecType == Include.class || mySpecType == PathSpecification.class) {
|
||||
if (mySpecType == Include.class) {
|
||||
convertAndAddIncludeToList(retVal, (Include) theObject);
|
||||
} else {
|
||||
retVal.add(QualifiedParamList.singleton(((String) theObject)));
|
||||
|
@ -6,10 +6,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -23,6 +21,7 @@ import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
@ -40,14 +39,12 @@ import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
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.api.annotation.Description;
|
||||
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.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.At;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
@ -90,7 +87,9 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.SearchParameterMap;
|
||||
import ca.uhn.fhir.util.DateUtils;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
@ -114,6 +113,12 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MethodUtil {
|
||||
|
||||
/** Non instantiable */
|
||||
private MethodUtil() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
private static final String LABEL = "label=\"";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MethodUtil.class);
|
||||
|
||||
@ -133,19 +138,14 @@ public class MethodUtil {
|
||||
}
|
||||
|
||||
|
||||
public static IIdType convertIdToType(IIdType value, Class<? extends IIdType> idParamType) {
|
||||
if (value != null && !idParamType.isAssignableFrom(value.getClass())) {
|
||||
try {
|
||||
IIdType newValue = idParamType.newInstance();
|
||||
newValue.setValue(value.getValue());
|
||||
value = newValue;
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigurationException("Failed to instantiate " + idParamType, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ConfigurationException("Failed to instantiate " + idParamType, e);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends IIdType> T convertIdToType(IIdType value, Class<T> theIdParamType) {
|
||||
if (value != null && !theIdParamType.isAssignableFrom(value.getClass())) {
|
||||
IIdType newValue = ReflectionUtil.newInstance(theIdParamType);
|
||||
newValue.setValue(value.getValue());
|
||||
value = newValue;
|
||||
}
|
||||
return value;
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation(FhirContext theContext) {
|
||||
@ -213,13 +213,9 @@ public class MethodUtil {
|
||||
for (String nextValue : nextEntry.getValue()) {
|
||||
b.append(haveQuestionMark ? '&' : '?');
|
||||
haveQuestionMark = true;
|
||||
try {
|
||||
b.append(URLEncoder.encode(nextEntry.getKey(), "UTF-8"));
|
||||
b.append('=');
|
||||
b.append(URLEncoder.encode(nextValue, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ConfigurationException("UTF-8 not supported on this platform");
|
||||
}
|
||||
b.append(UrlUtil.escape(nextEntry.getKey()));
|
||||
b.append('=');
|
||||
b.append(UrlUtil.escape(nextValue));
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,9 +284,7 @@ public class MethodUtil {
|
||||
|
||||
public static EncodingEnum detectEncoding(String theBody) {
|
||||
EncodingEnum retVal = detectEncodingNoDefault(theBody);
|
||||
if (retVal == null) {
|
||||
retVal = EncodingEnum.XML;
|
||||
}
|
||||
retVal = ObjectUtils.defaultIfNull(retVal, EncodingEnum.XML);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -322,10 +316,6 @@ public class MethodUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer findConditionalOperationParameterIndex(Method theMethod) {
|
||||
return MethodUtil.findParamAnnotationIndex(theMethod, ConditionalUrlParam.class);
|
||||
}
|
||||
|
||||
public static Integer findIdParameterIndex(Method theMethod, FhirContext theContext) {
|
||||
Integer index = MethodUtil.findParamAnnotationIndex(theMethod, IdParam.class);
|
||||
if (index != null) {
|
||||
@ -366,7 +356,7 @@ public class MethodUtil {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(FhirContext theContext, Method theMethod, Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
|
||||
public static List<IParameter> getResourceParameters(final FhirContext theContext, Method theMethod, Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
|
||||
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
||||
@ -442,7 +432,7 @@ public class MethodUtil {
|
||||
if (parameterType == String.class) {
|
||||
instantiableCollectionType = null;
|
||||
specType = String.class;
|
||||
} else if ((parameterType != Include.class && parameterType != PathSpecification.class) || innerCollectionType == null || outerCollectionType != null) {
|
||||
} else if ((parameterType != Include.class) || innerCollectionType == null || outerCollectionType != null) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<" + Include.class.getSimpleName() + ">");
|
||||
} else {
|
||||
instantiableCollectionType = (Class<? extends Collection<Include>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + theMethod.getName() + "'");
|
||||
@ -515,7 +505,7 @@ public class MethodUtil {
|
||||
|
||||
@Override
|
||||
public Object outgoingClient(Object theObject) {
|
||||
return new StringDt(((ValidationModeEnum)theObject).getCode());
|
||||
return ParametersUtil.createString(theContext, ((ValidationModeEnum)theObject).getCode());
|
||||
}
|
||||
});
|
||||
} else if (nextAnnotation instanceof Validate.Profile) {
|
||||
@ -530,7 +520,7 @@ public class MethodUtil {
|
||||
|
||||
@Override
|
||||
public Object outgoingClient(Object theObject) {
|
||||
return new StringDt(theObject.toString());
|
||||
return ParametersUtil.createString(theContext, theObject.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -59,7 +59,6 @@ import ca.uhn.fhir.rest.param.HasParam;
|
||||
import ca.uhn.fhir.rest.param.NumberAndListParam;
|
||||
import ca.uhn.fhir.rest.param.NumberOrListParam;
|
||||
import ca.uhn.fhir.rest.param.NumberParam;
|
||||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityAndListParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityOrListParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
@ -81,7 +80,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.CollectionUtil;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SearchParameter extends BaseQueryParameter {
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
@ -341,8 +339,6 @@ public class SearchParameter extends BaseQueryParameter {
|
||||
// ok
|
||||
} else if (StringDt.class.isAssignableFrom(type)) {
|
||||
myParamType = RestSearchParameterTypeEnum.STRING;
|
||||
} else if (QualifiedDateParam.class.isAssignableFrom(type)) {
|
||||
myParamType = RestSearchParameterTypeEnum.DATE;
|
||||
} else if (BaseIdentifierDt.class.isAssignableFrom(type)) {
|
||||
myParamType = RestSearchParameterTypeEnum.TOKEN;
|
||||
} else if (BaseQuantityDt.class.isAssignableFrom(type)) {
|
||||
|
@ -1,54 +0,0 @@
|
||||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
class Util {
|
||||
// public static Integer findCountParameterIndex(Method theMethod) {
|
||||
// return findParamIndex(theMethod, Count.class);
|
||||
// }
|
||||
|
||||
|
||||
public static Map<String, String> getQueryParams(String query) {
|
||||
try {
|
||||
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
for (String param : query.split("&")) {
|
||||
String[] pair = param.split("=");
|
||||
String key = URLDecoder.decode(pair[0], "UTF-8");
|
||||
String value = URLDecoder.decode(pair[1], "UTF-8");
|
||||
|
||||
params.put(key, value);
|
||||
}
|
||||
return params;
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -37,9 +37,9 @@ import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
|
||||
public class ValidateMethodBindingDstu2 extends OperationMethodBinding {
|
||||
public class ValidateMethodBindingDstu2Plus extends OperationMethodBinding {
|
||||
|
||||
public ValidateMethodBindingDstu2(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
public ValidateMethodBindingDstu2Plus(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Validate theAnnotation) {
|
||||
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION);
|
||||
|
@ -1,84 +0,0 @@
|
||||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
|
||||
public class ValidateMethodBindingDstu3 extends OperationMethodBinding {
|
||||
|
||||
public ValidateMethodBindingDstu3(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Validate theAnnotation) {
|
||||
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION);
|
||||
|
||||
List<IParameter> newParams = new ArrayList<IParameter>();
|
||||
int idx = 0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof ResourceParameter) {
|
||||
if (IBaseResource.class.isAssignableFrom(((ResourceParameter) next).getResourceType())) {
|
||||
Class<?> parameterType = theMethod.getParameterTypes()[idx];
|
||||
if (String.class.equals(parameterType) || EncodingEnum.class.equals(parameterType)) {
|
||||
newParams.add(next);
|
||||
} else {
|
||||
OperationParameter parameter = new OperationParameter(theContext, Constants.EXTOP_VALIDATE, Constants.EXTOP_VALIDATE_RESOURCE, 0, 1);
|
||||
parameter.initializeTypes(theMethod, null, null, parameterType);
|
||||
newParams.add(parameter);
|
||||
}
|
||||
} else {
|
||||
newParams.add(next);
|
||||
}
|
||||
} else {
|
||||
newParams.add(next);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
setParameters(newParams);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static BaseHttpClientInvocation createValidateInvocation(FhirContext theContext, IBaseResource theResource) {
|
||||
IBaseParameters parameters = (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||
ParametersUtil.addParameterToParameters(theContext, parameters, theResource, "resource");
|
||||
|
||||
String resourceName = theContext.getResourceDefinition(theResource).getName();
|
||||
String resourceId = theResource.getIdElement().getIdPart();
|
||||
|
||||
BaseHttpClientInvocation retVal = createOperationInvocation(theContext, resourceName, resourceId, Constants.EXTOP_VALIDATE, parameters, false);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.Date;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link DateParam} instead (this class is identical, but was renamed to be less confusing)
|
||||
*/
|
||||
@Deprecated
|
||||
@CoverageIgnore
|
||||
public class QualifiedDateParam extends DateParam {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public QualifiedDateParam() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public QualifiedDateParam(QuantityCompararatorEnum theComparator, Date theDate) {
|
||||
setComparator(theComparator);
|
||||
setValue(theDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public QualifiedDateParam(QuantityCompararatorEnum theComparator, String theDate) {
|
||||
setComparator(theComparator);
|
||||
setValueAsString(theDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which takes a complete [qualifier]{date} string.
|
||||
*
|
||||
* @param theString The string
|
||||
*/
|
||||
public QualifiedDateParam(String theString) {
|
||||
setValueAsQueryToken(null, theString);
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,7 @@ import ca.uhn.fhir.rest.method.ParseAction;
|
||||
|
||||
public interface IRestfulResponse {
|
||||
|
||||
Object streamResponseAsResource(IBaseResource theActualResourceToReturn, boolean prettyPrint, Set<SummaryEnum> summaryMode, int operationStatus, boolean respondGzip, boolean addContentLocationHeader) throws IOException;
|
||||
Object streamResponseAsResource(IBaseResource theActualResourceToReturn, boolean thePrettyPrint, Set<SummaryEnum> theSummaryMode, int theStatusCode, String theStatusMessage, boolean theRespondGzip, boolean theAddContentLocation) throws IOException;
|
||||
|
||||
Object streamResponseAsBundle(Bundle bundle, Set<SummaryEnum> summaryMode, boolean respondGzip, boolean requestIsBrowser) throws IOException;
|
||||
|
||||
@ -48,7 +48,7 @@ public interface IRestfulResponse {
|
||||
*/
|
||||
Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException;
|
||||
|
||||
Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip) throws UnsupportedEncodingException, IOException;
|
||||
Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException;
|
||||
|
||||
Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException;
|
||||
|
||||
|
@ -90,10 +90,10 @@ public abstract class RestfulResponse<T extends RequestDetails> implements IRest
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set<SummaryEnum> summaryMode,
|
||||
int statusCode, boolean respondGzip, boolean addContentLocationHeader)
|
||||
public final Object streamResponseAsResource(IBaseResource theResource, boolean thePrettyPrint, Set<SummaryEnum> theSummaryMode,
|
||||
int theStatusCode, String theStatusMessage, boolean theRespondGzip, boolean theAddContentLocation)
|
||||
throws IOException {
|
||||
return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), resource, summaryMode, statusCode, addContentLocationHeader, respondGzip, getRequestDetails(), myOperationResourceId, myOperationResourceLastUpdated);
|
||||
return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), theResource, theSummaryMode, theStatusCode, theStatusMessage, theAddContentLocation, theRespondGzip, getRequestDetails(), myOperationResourceId, myOperationResourceLastUpdated);
|
||||
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ public class RestfulServerUtils {
|
||||
String contentType = responseEncoding.getBundleContentType();
|
||||
|
||||
String charset = Constants.CHARSET_NAME_UTF8;
|
||||
Writer writer = theRequestDetails.getResponse().getResponseWriter(status, contentType, charset, respondGzip);
|
||||
Writer writer = theRequestDetails.getResponse().getResponseWriter(status, null, contentType, charset, respondGzip);
|
||||
|
||||
try {
|
||||
IParser parser = RestfulServerUtils.getNewParser(theServer.getFhirContext(), theRequestDetails);
|
||||
@ -552,11 +552,11 @@ public class RestfulServerUtils {
|
||||
}
|
||||
|
||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int stausCode, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails) throws IOException {
|
||||
return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null);
|
||||
return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, null, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null);
|
||||
}
|
||||
|
||||
|
||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int stausCode, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated) throws IOException {
|
||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int theStausCode, String theStatusMessage, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated) throws IOException {
|
||||
IRestfulResponse restUtil = theRequestDetails.getResponse();
|
||||
|
||||
// Determine response encoding
|
||||
@ -596,7 +596,7 @@ public class RestfulServerUtils {
|
||||
// malicious images or HTML blocks being served up as content.
|
||||
restUtil.addHeader(Constants.HEADER_CONTENT_DISPOSITION, "Attachment;");
|
||||
|
||||
return restUtil.sendAttachmentResponse(bin, stausCode, contentType);
|
||||
return restUtil.sendAttachmentResponse(bin, theStausCode, contentType);
|
||||
}
|
||||
|
||||
// Ok, we're not serving a binary resource, so apply default encoding
|
||||
@ -656,7 +656,7 @@ public class RestfulServerUtils {
|
||||
}
|
||||
String charset = Constants.CHARSET_NAME_UTF8;
|
||||
|
||||
Writer writer = restUtil.getResponseWriter(stausCode, contentType, charset, respondGzip);
|
||||
Writer writer = restUtil.getResponseWriter(theStausCode, theStatusMessage, contentType, charset, respondGzip);
|
||||
if (theResource == null) {
|
||||
// No response is being returned
|
||||
} else if (encodingDomainResourceAsText && theResource instanceof IResource) {
|
||||
@ -666,7 +666,7 @@ public class RestfulServerUtils {
|
||||
parser.encodeResourceToWriter(theResource, writer);
|
||||
}
|
||||
|
||||
return restUtil.sendWriterResponse(stausCode, contentType, charset, writer);
|
||||
return restUtil.sendWriterResponse(theStausCode, contentType, charset, writer);
|
||||
}
|
||||
|
||||
public static IIdType fullyQualifyResourceIdOrReturnNull(IRestfulServerDefaults theServer, IBaseResource theResource, String theServerBase, IIdType theResourceId) {
|
||||
|
@ -39,6 +39,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.IRestfulResponse;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
|
||||
public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
||||
@ -79,7 +80,15 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, false, false);
|
||||
String statusMessage = null;
|
||||
if (theException instanceof UnclassifiedServerFailureException) {
|
||||
String sm = theException.getMessage();
|
||||
if (isNotBlank(sm) && sm.indexOf('\n') == -1) {
|
||||
statusMessage = sm;
|
||||
}
|
||||
}
|
||||
|
||||
return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, statusMessage, false, false);
|
||||
// theResponse.setStatus(statusCode);
|
||||
// theRequestDetails.getServer().addHeadersToResponse(theResponse);
|
||||
// theResponse.setContentType("text/plain");
|
||||
|
@ -340,19 +340,21 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
||||
|
||||
b.append("<p>");
|
||||
b.append("This result is being rendered in HTML for easy viewing. ");
|
||||
b.append("You may view this content as ");
|
||||
b.append("You may access this content as ");
|
||||
|
||||
b.append("<a href=\"");
|
||||
b.append(createLinkHref(parameters, Constants.FORMAT_JSON));
|
||||
b.append("\">Raw JSON</a>, ");
|
||||
b.append("\">Raw JSON</a> or ");
|
||||
|
||||
b.append("<a href=\"");
|
||||
b.append(createLinkHref(parameters, Constants.FORMAT_XML));
|
||||
b.append("\">Raw XML</a>, ");
|
||||
|
||||
b.append(" or view this content in ");
|
||||
|
||||
b.append("<a href=\"");
|
||||
b.append(createLinkHref(parameters, Constants.FORMATS_HTML_JSON));
|
||||
b.append("\">HTML JSON</a>, ");
|
||||
b.append("\">HTML JSON</a> ");
|
||||
|
||||
b.append("or ");
|
||||
b.append("<a href=\"");
|
||||
|
@ -0,0 +1,30 @@
|
||||
package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
|
||||
|
||||
abstract class BaseRule implements IAuthRule {
|
||||
private String myName;
|
||||
private PolicyEnum myMode;
|
||||
|
||||
BaseRule(String theRuleName) {
|
||||
myName = theRuleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public void setMode(PolicyEnum theRuleMode) {
|
||||
myMode = theRuleMode;
|
||||
}
|
||||
|
||||
Verdict newVerdict() {
|
||||
return new Verdict(myMode, this);
|
||||
}
|
||||
|
||||
public PolicyEnum getMode() {
|
||||
return myMode;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
|
||||
public interface IAuthRuleBuilderOperation {
|
||||
|
||||
/**
|
||||
* This rule applies to the operation with the given name
|
||||
*
|
||||
* @param The operation name, e.g. "validate" or "$validate" (either form may be used here)
|
||||
*/
|
||||
IAuthRuleBuilderOperationNamed named(String theOperationName);
|
||||
|
||||
/**
|
||||
* This rule applies to any operation
|
||||
*/
|
||||
IAuthRuleBuilderOperationNamed withAnyName();
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
public interface IAuthRuleBuilderOperationNamed {
|
||||
|
||||
/**
|
||||
* Rule applies to invocations of this operation at the <code>server</code> level
|
||||
*/
|
||||
IAuthRuleBuilderRuleOpClassifierFinished onServer();
|
||||
|
||||
/**
|
||||
* Rule applies to invocations of this operation at the <code>type</code> level
|
||||
*/
|
||||
IAuthRuleBuilderRuleOpClassifierFinished onType(Class<? extends IBaseResource> theType);
|
||||
|
||||
/**
|
||||
* Rule applies to invocations of this operation at the <code>instance</code> level
|
||||
*/
|
||||
IAuthRuleBuilderRuleOpClassifierFinished onInstance(IIdType theInstanceId);
|
||||
|
||||
}
|
@ -55,4 +55,9 @@ public interface IAuthRuleBuilderRule {
|
||||
*/
|
||||
IAuthRuleBuilderRuleOp write();
|
||||
|
||||
/**
|
||||
* This rule applies to a FHIR operation (e.g. <code>$validate</code>)
|
||||
*/
|
||||
IAuthRuleBuilderOperation operation();
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
|
||||
|
||||
class OperationRule extends BaseRule implements IAuthRule {
|
||||
|
||||
public OperationRule(String theRuleName) {
|
||||
super(theRuleName);
|
||||
}
|
||||
|
||||
private String myOperationName;
|
||||
private boolean myAppliesToServer;
|
||||
private HashSet<Class<? extends IBaseResource>> myAppliesToTypes;
|
||||
private List<IIdType> myAppliesToIds;
|
||||
|
||||
/**
|
||||
* Must include the leading $
|
||||
*/
|
||||
public void setOperationName(String theOperationName) {
|
||||
myOperationName = theOperationName;
|
||||
}
|
||||
|
||||
public String getOperationName() {
|
||||
return myOperationName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IBaseResource theOutputResource, IRuleApplier theRuleApplier) {
|
||||
FhirContext ctx = theRequestDetails.getServer().getFhirContext();
|
||||
|
||||
boolean applies = false;
|
||||
switch (theOperation) {
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
if (myAppliesToServer) {
|
||||
applies = true;
|
||||
}
|
||||
break;
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
if (myAppliesToTypes != null) {
|
||||
for (Class<? extends IBaseResource> next : myAppliesToTypes) {
|
||||
String resName = ctx.getResourceDefinition(theRequestDetails.getResourceName()).getName();
|
||||
if (resName.equals(theRequestDetails.getResourceName())) {
|
||||
applies = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
if (myAppliesToIds != null) {
|
||||
String instanceId = theRequestDetails.getId().toUnqualifiedVersionless().getValue();
|
||||
for (IIdType next : myAppliesToIds) {
|
||||
if (next.toUnqualifiedVersionless().getValue().equals(instanceId)) {
|
||||
applies = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!applies) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (myOperationName != null && !myOperationName.equals(theRequestDetails.getOperation())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return newVerdict();
|
||||
}
|
||||
|
||||
public void appliesToServer() {
|
||||
myAppliesToServer = true;
|
||||
}
|
||||
|
||||
public void appliesToTypes(HashSet<Class<? extends IBaseResource>> theAppliesToTypes) {
|
||||
myAppliesToTypes = theAppliesToTypes;
|
||||
}
|
||||
|
||||
public void appliesToInstances(List<IIdType> theAppliesToIds) {
|
||||
myAppliesToIds = theAppliesToIds;
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
@ -40,20 +39,18 @@ import ca.uhn.fhir.util.BundleUtil;
|
||||
import ca.uhn.fhir.util.BundleUtil.BundleEntryParts;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
class Rule implements IAuthRule {
|
||||
class Rule extends BaseRule implements IAuthRule {
|
||||
|
||||
private AppliesTypeEnum myAppliesTo;
|
||||
private Set<?> myAppliesToTypes;
|
||||
private String myClassifierCompartmentName;
|
||||
private Collection<? extends IIdType> myClassifierCompartmentOwners;
|
||||
private ClassifierTypeEnum myClassifierType;
|
||||
private PolicyEnum myMode;
|
||||
private String myName;
|
||||
private RuleOpEnum myOp;
|
||||
private TransactionAppliesToEnum myTransactionAppliesToOp;
|
||||
|
||||
public Rule(String theRuleName) {
|
||||
myName = theRuleName;
|
||||
super(theRuleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,7 +74,7 @@ class Rule implements IAuthRule {
|
||||
case DELETE:
|
||||
if (theOperation == RestOperationTypeEnum.DELETE) {
|
||||
if (theInputResource == null) {
|
||||
return new Verdict(myMode, this);
|
||||
return newVerdict();
|
||||
} else {
|
||||
appliesTo = theInputResource;
|
||||
}
|
||||
@ -88,13 +85,13 @@ class Rule implements IAuthRule {
|
||||
case BATCH:
|
||||
case TRANSACTION:
|
||||
if (theInputResource != null && requestAppliesToTransaction(ctx, myOp, theInputResource)) {
|
||||
if (myMode == PolicyEnum.DENY) {
|
||||
if (getMode() == PolicyEnum.DENY) {
|
||||
return new Verdict(PolicyEnum.DENY, this);
|
||||
} else {
|
||||
} else {
|
||||
List<BundleEntryParts> inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource);
|
||||
Verdict verdict = null;
|
||||
for (BundleEntryParts nextPart : inputResources) {
|
||||
|
||||
|
||||
IBaseResource inputResource = nextPart.getResource();
|
||||
RestOperationTypeEnum operation = null;
|
||||
if (nextPart.getRequestType() == RequestTypeEnum.GET) {
|
||||
@ -111,13 +108,13 @@ class Rule implements IAuthRule {
|
||||
/*
|
||||
* This is basically just being conservative - Be careful of transactions containing
|
||||
* nested operations and nested transactions. We block the by default. At some point
|
||||
* it would be nice to be more nuanced here.
|
||||
* it would be nice to be more nuanced here.
|
||||
*/
|
||||
RuntimeResourceDefinition resourceDef = ctx.getResourceDefinition(nextPart.getResource());
|
||||
if ("Parameters".equals(resourceDef.getName()) || "Bundle".equals(resourceDef.getName())) {
|
||||
throw new InvalidRequestException("Can not handle transaction with nested resource of type " + resourceDef.getName());
|
||||
throw new InvalidRequestException("Can not handle transaction with nested resource of type " + resourceDef.getName());
|
||||
}
|
||||
|
||||
|
||||
Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(operation, theRequestDetails, inputResource, null);
|
||||
if (newVerdict == null) {
|
||||
continue;
|
||||
@ -155,7 +152,7 @@ class Rule implements IAuthRule {
|
||||
return new Verdict(PolicyEnum.DENY, this);
|
||||
case METADATA:
|
||||
if (theOperation == RestOperationTypeEnum.METADATA) {
|
||||
return new Verdict(myMode, this);
|
||||
return newVerdict();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -196,14 +193,15 @@ class Rule implements IAuthRule {
|
||||
throw new IllegalStateException("Unable to apply security to event of applies to type " + myAppliesTo);
|
||||
}
|
||||
|
||||
return new Verdict(myMode, this);
|
||||
return newVerdict();
|
||||
}
|
||||
|
||||
|
||||
private boolean requestAppliesToTransaction(FhirContext theContext, RuleOpEnum theOp, IBaseResource theInputResource) {
|
||||
if (!"Bundle".equals(theContext.getResourceDefinition(theInputResource).getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
IBaseBundle request = (IBaseBundle) theInputResource;
|
||||
String bundleType = BundleUtil.getBundleType(theContext, request);
|
||||
switch (theOp) {
|
||||
@ -216,11 +214,6 @@ class Rule implements IAuthRule {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public TransactionAppliesToEnum getTransactionAppliesToOp() {
|
||||
return myTransactionAppliesToOp;
|
||||
}
|
||||
@ -245,9 +238,6 @@ class Rule implements IAuthRule {
|
||||
myClassifierType = theClassifierType;
|
||||
}
|
||||
|
||||
public void setMode(PolicyEnum theRuleMode) {
|
||||
myMode = theRuleMode;
|
||||
}
|
||||
|
||||
public Rule setOp(RuleOpEnum theRuleOp) {
|
||||
myOp = theRuleOp;
|
||||
@ -257,4 +247,5 @@ class Rule implements IAuthRule {
|
||||
public void setTransactionAppliesToOp(TransactionAppliesToEnum theOp) {
|
||||
myTransactionAppliesToOp = theOp;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -243,6 +244,80 @@ public class RuleBuilder implements IAuthRuleBuilder {
|
||||
|
||||
}
|
||||
|
||||
private class RuleBuilderRuleOperation implements IAuthRuleBuilderOperation {
|
||||
|
||||
private class RuleBuilderRuleOperationNamed implements IAuthRuleBuilderOperationNamed {
|
||||
|
||||
private String myOperationName;
|
||||
|
||||
public RuleBuilderRuleOperationNamed(String theOperationName) {
|
||||
if (theOperationName != null && !theOperationName.startsWith("$")) {
|
||||
myOperationName = '$' + theOperationName;
|
||||
} else {
|
||||
myOperationName = theOperationName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderRuleOpClassifierFinished onServer() {
|
||||
OperationRule rule = createRule();
|
||||
rule.appliesToServer();
|
||||
myRules.add(rule);
|
||||
return new RuleBuilderFinished();
|
||||
}
|
||||
|
||||
private OperationRule createRule() {
|
||||
OperationRule rule = new OperationRule(myRuleName);
|
||||
rule.setOperationName(myOperationName);
|
||||
rule.setMode(myRuleMode);
|
||||
return rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderRuleOpClassifierFinished onType(Class<? extends IBaseResource> theType) {
|
||||
Validate.notNull(theType, "theType must not be null");
|
||||
|
||||
OperationRule rule = createRule();
|
||||
HashSet<Class<? extends IBaseResource>> appliesToTypes = new HashSet<Class<? extends IBaseResource>>();
|
||||
appliesToTypes.add(theType);
|
||||
rule.appliesToTypes(appliesToTypes);
|
||||
myRules.add(rule);
|
||||
return new RuleBuilderFinished();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderRuleOpClassifierFinished onInstance(IIdType theInstanceId) {
|
||||
Validate.notNull(theInstanceId, "theInstanceId must not be null");
|
||||
Validate.notBlank(theInstanceId.getResourceType(), "theInstanceId does not have a resource type");
|
||||
Validate.notBlank(theInstanceId.getIdPart(), "theInstanceId does not have an ID part");
|
||||
|
||||
OperationRule rule = createRule();
|
||||
ArrayList<IIdType> ids = new ArrayList<IIdType>();
|
||||
ids.add(theInstanceId);
|
||||
rule.appliesToInstances(ids);
|
||||
myRules.add(rule);
|
||||
return new RuleBuilderFinished();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderOperationNamed named(String theOperationName) {
|
||||
Validate.notBlank(theOperationName, "theOperationName must not be null or empty");
|
||||
return new RuleBuilderRuleOperationNamed(theOperationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderOperationNamed withAnyName() {
|
||||
return new RuleBuilderRuleOperationNamed(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAuthRuleBuilderOperation operation() {
|
||||
return new RuleBuilderRuleOperation();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,5 +28,6 @@ enum RuleOpEnum {
|
||||
TRANSACTION,
|
||||
METADATA,
|
||||
BATCH,
|
||||
DELETE
|
||||
DELETE,
|
||||
OPERATION
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package ca.uhn.fhir.rest.server.servlet;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
@ -61,12 +63,12 @@ public class ServletRestfulResponse extends RestfulResponse<ServletRequestDetail
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
public Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
|
||||
addHeaders();
|
||||
HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
|
||||
theHttpResponse.setCharacterEncoding(charset);
|
||||
theHttpResponse.setStatus(statusCode);
|
||||
theHttpResponse.setContentType(contentType);
|
||||
theHttpResponse.setCharacterEncoding(theCharset);
|
||||
theHttpResponse.setStatus(theStatusCode);
|
||||
theHttpResponse.setContentType(theContentType);
|
||||
if (theRespondGzip) {
|
||||
theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
|
||||
return new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), Constants.CHARSET_NAME_UTF8);
|
||||
|
@ -1656,10 +1656,6 @@ public class XmlUtil {
|
||||
ourHaveLoggedStaxImplementation = true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws FactoryConfigurationError, XMLStreamException {
|
||||
createXmlWriter(new StringWriter());
|
||||
}
|
||||
|
||||
private static final class ExtendedEntityReplacingXmlResolver implements XMLResolver {
|
||||
@Override
|
||||
public Object resolveEntity(String thePublicID, String theSystemID, String theBaseURI, String theNamespace) throws XMLStreamException {
|
||||
|
@ -7,11 +7,15 @@ ca.uhn.fhir.context.FhirContext.noStructuresForSpecifiedVersion=Could not find t
|
||||
|
||||
ca.uhn.fhir.context.RuntimeResourceDefinition.nonInstantiableType=Resource type "{0}" can not be instantiated. Check that this class has a no-argument constructor, and that it is static if it is a nested type. Error is: {1}
|
||||
|
||||
ca.uhn.fhir.rest.client.BaseClient.ioExceptionDuringOperation=Encountered IOException when performing {0} to URL {1} - {2}
|
||||
ca.uhn.fhir.rest.client.BaseClient.failedToParseResponse=Failed to parse response from server when performing {0} to URL {1} - {2}
|
||||
|
||||
ca.uhn.fhir.rest.client.GenericClient.cantDetermineRequestType=Unable to determing encoding of request (body does not appear to be valid XML or JSON)
|
||||
ca.uhn.fhir.rest.client.GenericClient.noPagingLinkFoundInBundle=Can not perform paging operation because no link was found in Bundle with relation "{0}"
|
||||
ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread=No version specified in URL for 'vread' operation: {0}
|
||||
ca.uhn.fhir.rest.client.GenericClient.incompleteUriForRead=The given URI is not an absolute URL and is not usable for this operation: {0}
|
||||
ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable to determine the resource type from the given URI: {0}
|
||||
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.failedToRetrieveConformance=Failed to retrieve the server 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.BaseOutcomeReturningMethodBindingWithResourceParam.incorrectIdForUpdate=Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of "{0}" does not match URL ID of "{1}"
|
||||
|
@ -26,7 +26,7 @@ public class FhirDbConfig {
|
||||
extraProperties.put("hibernate.search.default.directory_provider", "filesystem");
|
||||
extraProperties.put("hibernate.search.default.indexBase", "target/lucenefiles");
|
||||
extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT");
|
||||
// extraProperties.put("hibernate.search.default.worker.execution", "async");
|
||||
extraProperties.put("hibernate.search.default.worker.execution", "async");
|
||||
|
||||
if (System.getProperty("lowmem") != null) {
|
||||
extraProperties.put("hibernate.search.autoregister_listeners", "false");
|
||||
|
@ -103,4 +103,14 @@ public class JaxRsHttpRequest implements IHttpRequest {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUri() {
|
||||
return ""; // TODO: can we get this from somewhere?
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHttpVerbName() {
|
||||
return myRequestType.name();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
|
||||
|
||||
if (conformance != null) {
|
||||
Set<SummaryEnum> summaryMode = Collections.emptySet();
|
||||
return (Response) response.streamResponseAsResource(conformance, false, summaryMode, Constants.STATUS_HTTP_200_OK, true, false);
|
||||
return (Response) response.streamResponseAsResource(conformance, false, summaryMode, Constants.STATUS_HTTP_200_OK, null, true, false);
|
||||
}
|
||||
return (Response) response.returnResponse(null, Constants.STATUS_HTTP_500_INTERNAL_ERROR, true, null, getResourceType().getSimpleName());
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class JaxRsResponse extends RestfulResponse<JaxRsRequest> {
|
||||
* by the server.
|
||||
*/
|
||||
@Override
|
||||
public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean respondGzip)
|
||||
public Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
return new StringWriter();
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseClient;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
@ -94,6 +95,7 @@ public class GenericJaxRsClientDstu3Test {
|
||||
|
||||
ourCtx.setRestfulClientFactory(clientFactory);
|
||||
ourResponseCount = 0;
|
||||
System.setProperty("hapi.client.keepresponses", "true");
|
||||
}
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
@ -211,7 +213,6 @@ public class GenericJaxRsClientDstu3Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testConformance() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
@ -228,7 +229,7 @@ public class GenericJaxRsClientDstu3Test {
|
||||
|
||||
|
||||
//@formatter:off
|
||||
Conformance resp = (Conformance)client.conformance();
|
||||
Conformance resp = (Conformance)client.fetchConformance().ofType(Conformance.class).execute();
|
||||
|
||||
//@formatter:on
|
||||
assertEquals("http://localhost:" + ourPort + "/fhir/metadata", ourRequestUri);
|
||||
|
@ -51,8 +51,13 @@ public class DaoConfig {
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private int myDeferIndexingForCodesystemsOfSize = 2000;
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
|
||||
private int myHardSearchLimit = 1000;
|
||||
|
||||
private int myHardTagListLimit = 1000;
|
||||
|
||||
private int myIncludeLimit = 2000;
|
||||
@ -61,24 +66,36 @@ public class DaoConfig {
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private boolean myIndexContainedResources = true;
|
||||
|
||||
|
||||
private List<IServerInterceptor> myInterceptors;
|
||||
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private int myMaximumExpansionSize = 5000;
|
||||
|
||||
|
||||
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
||||
|
||||
private boolean mySchedulingDisabled;
|
||||
|
||||
private boolean mySubscriptionEnabled;
|
||||
|
||||
private long mySubscriptionPollDelay = 1000;
|
||||
|
||||
private Long mySubscriptionPurgeInactiveAfterMillis;
|
||||
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<String>();
|
||||
private boolean mySubscriptionEnabled;
|
||||
|
||||
private long mySubscriptionPollDelay = 1000;
|
||||
|
||||
private Long mySubscriptionPurgeInactiveAfterMillis;
|
||||
|
||||
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* When a code system is added that contains more than this number of codes,
|
||||
* the code system will be indexed later in an incremental process in order to
|
||||
* avoid overwhelming Lucene with a huge number of codes in a single operation.
|
||||
* <p>
|
||||
* Defaults to 2000
|
||||
* </p>
|
||||
*/
|
||||
public int getDeferIndexingForCodesystemsOfSize() {
|
||||
return myDeferIndexingForCodesystemsOfSize;
|
||||
}
|
||||
/**
|
||||
* Sets the number of milliseconds that search results for a given client search
|
||||
* should be preserved before being purged from the database.
|
||||
@ -117,6 +134,7 @@ public class DaoConfig {
|
||||
}
|
||||
return myInterceptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #setMaximumExpansionSize(int)}
|
||||
*/
|
||||
@ -180,7 +198,6 @@ public class DaoConfig {
|
||||
public boolean isAllowInlineMatchUrlReferences() {
|
||||
return myAllowInlineMatchUrlReferences;
|
||||
}
|
||||
|
||||
public boolean isAllowMultipleDelete() {
|
||||
return myAllowMultipleDelete;
|
||||
}
|
||||
@ -251,6 +268,18 @@ public class DaoConfig {
|
||||
myAllowMultipleDelete = theAllowMultipleDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a code system is added that contains more than this number of codes,
|
||||
* the code system will be indexed later in an incremental process in order to
|
||||
* avoid overwhelming Lucene with a huge number of codes in a single operation.
|
||||
* <p>
|
||||
* Defaults to 2000
|
||||
* </p>
|
||||
*/
|
||||
public void setDeferIndexingForCodesystemsOfSize(int theDeferIndexingForCodesystemsOfSize) {
|
||||
myDeferIndexingForCodesystemsOfSize = theDeferIndexingForCodesystemsOfSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of milliseconds that search results for a given client search
|
||||
* should be preserved before being purged from the database.
|
||||
|
@ -1,79 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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.Date;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
class HistoryTuple implements Comparable<HistoryTuple> {
|
||||
|
||||
private Long myId;
|
||||
private boolean myIsHistory;
|
||||
private Date myUpdated;
|
||||
|
||||
public HistoryTuple(boolean theIsHistory, Date theUpdated, Long theId) {
|
||||
super();
|
||||
myIsHistory = theIsHistory;
|
||||
myUpdated = theUpdated;
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(HistoryTuple theO) {
|
||||
return myUpdated.compareTo(theO.myUpdated);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public boolean isHistory() {
|
||||
return myIsHistory;
|
||||
}
|
||||
|
||||
public Date getUpdated() {
|
||||
return myUpdated;
|
||||
}
|
||||
|
||||
public void setId(Long theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
public void setIsHistory(boolean theIsHistory) {
|
||||
myIsHistory = theIsHistory;
|
||||
}
|
||||
|
||||
public void setUpdated(Date theUpdated) {
|
||||
myUpdated = theUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
b.append("id", myId);
|
||||
b.append("history", myIsHistory);
|
||||
b.append("updated", myUpdated);
|
||||
return b.build();
|
||||
}
|
||||
|
||||
}
|
@ -55,14 +55,12 @@ import org.hibernate.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Fields;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
import org.hibernate.search.annotations.Store;
|
||||
import org.hibernate.search.indexes.interceptor.DontInterceptEntityInterceptor;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Indexed(interceptor=DeferConceptIndexingInterceptor.class)
|
||||
@Indexed()
|
||||
@Table(name="TRM_CONCEPT", uniqueConstraints= {
|
||||
@UniqueConstraint(name="IDX_CONCEPT_CS_CODE", columnNames= {"CODESYSTEM_PID", "CODE"})
|
||||
}, indexes= {
|
||||
@ -71,12 +69,11 @@ import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
|
||||
//@formatter:on
|
||||
public class TermConcept implements Serializable {
|
||||
private static final int MAX_DESC_LENGTH = 400;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@OneToMany(fetch=FetchType.LAZY, mappedBy="myParent")
|
||||
private Collection<TermConceptParentChildLink> myChildren;
|
||||
|
||||
|
||||
@Column(name="CODE", length=100, nullable=false)
|
||||
@Fields({
|
||||
@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),
|
||||
@ -86,7 +83,7 @@ public class TermConcept implements Serializable {
|
||||
@ManyToOne()
|
||||
@JoinColumn(name="CODESYSTEM_PID", referencedColumnName="PID", foreignKey=@ForeignKey(name="FK_CONCEPT_PID_CS_PID"))
|
||||
private TermCodeSystemVersion myCodeSystem;
|
||||
|
||||
|
||||
@Column(name="CODESYSTEM_PID", insertable=false, updatable=false)
|
||||
@Fields({
|
||||
@Field(name="myCodeSystemVersionPid")
|
||||
@ -103,7 +100,7 @@ public class TermConcept implements Serializable {
|
||||
})
|
||||
private String myDisplay;
|
||||
//@formatter:on
|
||||
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name="SEQ_CONCEPT_PID", sequenceName="SEQ_CONCEPT_PID")
|
||||
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CONCEPT_PID")
|
||||
@ -189,6 +186,10 @@ public class TermConcept implements Serializable {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public Long getIndexStatus() {
|
||||
return myIndexStatus;
|
||||
}
|
||||
|
||||
public Collection<TermConceptParentChildLink> getParents() {
|
||||
if (myParents == null) {
|
||||
myParents = new ArrayList<TermConceptParentChildLink>();
|
||||
|
@ -66,6 +66,10 @@ public class TermConceptParentChildLink implements Serializable {
|
||||
return myChild;
|
||||
}
|
||||
|
||||
public RelationshipTypeEnum getRelationshipType() {
|
||||
return myRelationshipType;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion getCodeSystem() {
|
||||
return myCodeSystem;
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
|
||||
public class BaseJpaPlainProvider extends BaseJpaProvider {
|
||||
|
||||
private IFhirSystemDao<?,?> myDao;
|
||||
|
||||
public BaseJpaPlainProvider() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setDao(IFhirSystemDao<?,?> theDao) {
|
||||
myDao = theDao;
|
||||
}
|
||||
|
||||
public IFhirSystemDao<?,?> getDao() {
|
||||
return myDao;
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
|
||||
|
||||
public class BaseJpaResourceProviderQuestionnaireResponseDstu2 extends JpaResourceProviderDstu2<QuestionnaireResponse> {
|
||||
|
||||
// nothing yet
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 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%
|
||||
*/
|
||||
|
||||
public class BaseJpaResourceProviderQuestionnaireResponseDstu3 extends JpaResourceProviderDstu3<QuestionnaireResponse> {
|
||||
|
||||
// nothing yet
|
||||
|
||||
}
|
@ -26,7 +26,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -85,7 +84,9 @@ public class TerminologyUploaderProviderDstu3 extends BaseJpaProvider {
|
||||
} else if (thePackage == null || thePackage.getData() == null || thePackage.getData().length == 0) {
|
||||
throw new InvalidRequestException("No 'localfile' or 'package' parameter, or package had no data");
|
||||
} else {
|
||||
data = Arrays.asList(thePackage.getData());
|
||||
data = new ArrayList<byte[]>();
|
||||
data.add(thePackage.getData());
|
||||
thePackage.setData(null);
|
||||
}
|
||||
|
||||
String url = theUrl != null ? theUrl.getValueAsString() : null;
|
||||
|
@ -1,9 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.search;
|
||||
|
||||
import org.hibernate.search.indexes.interceptor.DontInterceptEntityInterceptor;
|
||||
|
||||
public class DeferConceptIndexingInterceptor extends DontInterceptEntityInterceptor
|
||||
//implements EntityIndexingInterceptor<TermConcept>
|
||||
{
|
||||
// nothing for now
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class SubscriptionWebsocketHandlerFactoryDstu2 implements FactoryBean<ISubscriptionWebsocketHandler> {
|
||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu2.class);
|
||||
|
||||
@Override
|
||||
public ISubscriptionWebsocketHandler getObject() throws Exception {
|
||||
return new SubscriptionWebsocketHandlerDstu2();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ISubscriptionWebsocketHandler> getObjectType() {
|
||||
return ISubscriptionWebsocketHandler.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.subscription;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
public class SubscriptionWebsocketHandlerFactoryDstu3 implements FactoryBean<ISubscriptionWebsocketHandler> {
|
||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu3.class);
|
||||
|
||||
@Override
|
||||
public ISubscriptionWebsocketHandler getObject() throws Exception {
|
||||
return new SubscriptionWebsocketHandlerDstu3();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ISubscriptionWebsocketHandler> getObjectType() {
|
||||
return ISubscriptionWebsocketHandler.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -67,9 +68,13 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
@Autowired
|
||||
protected ITermConceptDao myConceptDao;
|
||||
|
||||
private List<TermConceptParentChildLink> myConceptLinksToSaveLater = new ArrayList<TermConceptParentChildLink>();
|
||||
|
||||
@Autowired
|
||||
private ITermConceptParentChildLinkDao myConceptParentChildLinkDao;
|
||||
|
||||
private List<TermConcept> myConceptsToSaveLater = new ArrayList<TermConcept>();
|
||||
|
||||
@Autowired
|
||||
protected FhirContext myContext;
|
||||
|
||||
@ -78,6 +83,8 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
|
||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
|
||||
private boolean myProcessDeferred = true;
|
||||
|
||||
private boolean addToSet(Set<TermConcept> theSetToPopulate, TermConcept theConcept) {
|
||||
boolean retVal = theSetToPopulate.add(theConcept);
|
||||
@ -197,35 +204,101 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
TermCodeSystemVersion csv = cs.getCurrentVersion();
|
||||
return csv;
|
||||
}
|
||||
|
||||
private TermCodeSystem getCodeSystem(String theSystem) {
|
||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(theSystem);
|
||||
return cs;
|
||||
}
|
||||
|
||||
private void parentPids(TermConcept theNextConcept, Set<Long> theParentPids) {
|
||||
for (TermConceptParentChildLink nextParentLink : theNextConcept.getParents()){
|
||||
TermConcept parent = nextParentLink.getParent();
|
||||
if (parent != null && theParentPids.add(parent.getId())) {
|
||||
parentPids(parent, theParentPids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void persistChildren(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, IdentityHashMap<TermConcept, Object> theConceptsStack, int theTotalConcepts) {
|
||||
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (theConceptsStack.size() % 1000 == 0) {
|
||||
if (theConceptsStack.size() == 1 || theConceptsStack.size() % 10000 == 0) {
|
||||
float pct = (float) theConceptsStack.size() / (float) theTotalConcepts;
|
||||
ourLog.info("Have saved {}/{} concepts ({}%), flushing", theConceptsStack.size(), theTotalConcepts, (int)( pct*100.0f));
|
||||
myConceptDao.flush();
|
||||
myConceptParentChildLinkDao.flush();
|
||||
ourLog.info("Have processed {}/{} concepts ({}%)", theConceptsStack.size(), theTotalConcepts, (int)( pct*100.0f));
|
||||
}
|
||||
|
||||
theConcept.setCodeSystem(theCodeSystem);
|
||||
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||
|
||||
myConceptDao.save(theConcept);
|
||||
Set<Long> parentPids = new HashSet<Long>();
|
||||
parentPids(theConcept, parentPids);
|
||||
theConcept.setParentPids(parentPids);
|
||||
|
||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||
myConceptDao.save(theConcept);
|
||||
} else {
|
||||
myConceptsToSaveLater.add(theConcept);
|
||||
}
|
||||
|
||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||
persistChildren(next.getChild(), theCodeSystem, theConceptsStack, theTotalConcepts);
|
||||
}
|
||||
|
||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
} else {
|
||||
myConceptLinksToSaveLater.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
if (theNext.getCodeSystem() != null) {
|
||||
return;
|
||||
}
|
||||
theNext.setCodeSystem(theCodeSystemVersion);
|
||||
for (TermConceptParentChildLink next : theNext.getChildren()) {
|
||||
populateVersion(next.getChild(), theCodeSystemVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate=5000)
|
||||
@Transactional(propagation=Propagation.REQUIRED)
|
||||
@Override
|
||||
public synchronized void saveDeferred() {
|
||||
if (!myProcessDeferred || ((myConceptsToSaveLater.isEmpty() && myConceptLinksToSaveLater.isEmpty()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
int codeCount = 0, relCount = 0;
|
||||
|
||||
int count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptsToSaveLater.size());
|
||||
ourLog.info("Saving {} deferred concepts...", count);
|
||||
while (codeCount < count && myConceptsToSaveLater.size() > 0) {
|
||||
TermConcept next = myConceptsToSaveLater.remove(0);
|
||||
myConceptDao.save(next);
|
||||
codeCount++;
|
||||
}
|
||||
|
||||
if (codeCount == 0) {
|
||||
count = Math.min(myDaoConfig.getDeferIndexingForCodesystemsOfSize(), myConceptLinksToSaveLater.size());
|
||||
ourLog.info("Saving {} deferred concept relationships...", count);
|
||||
while (relCount < count && myConceptLinksToSaveLater.size() > 0) {
|
||||
TermConceptParentChildLink next = myConceptLinksToSaveLater.remove(0);
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
relCount++;
|
||||
}
|
||||
}
|
||||
|
||||
ourLog.info("Saved {} deferred concepts ({} remain) and {} deferred relationships ({} remain)", new Object[] {codeCount, myConceptsToSaveLater.size(), relCount, myConceptLinksToSaveLater.size()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProcessDeferred(boolean theProcessDeferred) {
|
||||
myProcessDeferred = theProcessDeferred;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -263,7 +336,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
ourLog.info("Validating all codes in CodeSystem for storage (this can take some time for large sets)");
|
||||
|
||||
// Validate the code system
|
||||
IdentityHashMap<TermConcept, Object> conceptsStack = new IdentityHashMap<TermConcept, Object>();
|
||||
ArrayList<String> conceptsStack = new ArrayList<String>();
|
||||
IdentityHashMap<TermConcept, Object> allConcepts = new IdentityHashMap<TermConcept, Object>();
|
||||
int totalCodeCount = 0;
|
||||
for (TermConcept next : theCodeSystemVersion.getConcepts()) {
|
||||
@ -279,11 +352,17 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
codeSystem.setCurrentVersion(theCodeSystemVersion);
|
||||
codeSystem = myCodeSystemDao.saveAndFlush(codeSystem);
|
||||
|
||||
ourLog.info("Saving {} concepts...", totalCodeCount);
|
||||
ourLog.info("Setting codesystemversion on {} concepts...", totalCodeCount);
|
||||
|
||||
conceptsStack = new IdentityHashMap<TermConcept, Object>();
|
||||
for (TermConcept next : theCodeSystemVersion.getConcepts()) {
|
||||
persistChildren(next, codeSystemVersion, conceptsStack, totalCodeCount);
|
||||
populateVersion(next, codeSystemVersion);
|
||||
}
|
||||
|
||||
ourLog.info("Saving {} concepts...", totalCodeCount);
|
||||
|
||||
IdentityHashMap<TermConcept, Object> conceptsStack2 = new IdentityHashMap<TermConcept, Object>();
|
||||
for (TermConcept next : theCodeSystemVersion.getConcepts()) {
|
||||
persistChildren(next, codeSystemVersion, conceptsStack2, totalCodeCount);
|
||||
}
|
||||
|
||||
ourLog.info("Done saving concepts, flushing to database");
|
||||
@ -291,27 +370,6 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
myConceptDao.flush();
|
||||
myConceptParentChildLinkDao.flush();
|
||||
|
||||
ourLog.info("Building multi-axial hierarchy...");
|
||||
|
||||
int index = 0;
|
||||
int totalParents = 0;
|
||||
for (TermConcept nextConcept : conceptsStack.keySet()) {
|
||||
|
||||
if (index++ % 1000 == 0) {
|
||||
float pct = (float) index / (float) totalCodeCount;
|
||||
ourLog.info("Have built hierarchy for {}/{} concepts - {}%", index, totalCodeCount, (int)( pct*100.0f));
|
||||
}
|
||||
|
||||
Set<Long> parentPids = new HashSet<Long>();
|
||||
parentPids(nextConcept, parentPids);
|
||||
nextConcept.setParentPids(parentPids);
|
||||
totalParents += parentPids.size();
|
||||
|
||||
myConceptDao.save(nextConcept);
|
||||
}
|
||||
|
||||
ourLog.info("Done building hierarchy, found {} parents", totalParents);
|
||||
|
||||
/*
|
||||
* For now we always delete old versions.. At some point it would be nice to allow configuration to keep old versions
|
||||
*/
|
||||
@ -324,17 +382,12 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
}
|
||||
|
||||
ourLog.info("Done deleting old code system versions");
|
||||
}
|
||||
|
||||
private void parentPids(TermConcept theNextConcept, Set<Long> theParentPids) {
|
||||
for (TermConceptParentChildLink nextParentLink : theNextConcept.getParents()){
|
||||
TermConcept parent = nextParentLink.getParent();
|
||||
if (parent != null && theParentPids.add(parent.getId())) {
|
||||
parentPids(parent, theParentPids);
|
||||
}
|
||||
|
||||
if (myConceptsToSaveLater.size() > 0 || myConceptLinksToSaveLater.size() > 0) {
|
||||
ourLog.info("Note that some concept saving was deferred - still have {} concepts and {} relationships", myConceptsToSaveLater.size(), myConceptLinksToSaveLater.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsSystem(String theSystem) {
|
||||
TermCodeSystem cs = getCodeSystem(theSystem);
|
||||
@ -349,16 +402,17 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, IdentityHashMap<TermConcept, Object> theConceptsStack,
|
||||
private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, ArrayList<String> theConceptsStack,
|
||||
IdentityHashMap<TermConcept, Object> theAllConcepts) {
|
||||
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystem() != null, "CodesystemValue is null");
|
||||
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystem() == theCodeSystem, "CodeSystems are not equal");
|
||||
ValidateUtil.isNotBlankOrThrowInvalidRequest(theConcept.getCode(), "Codesystem contains a code with no code value");
|
||||
|
||||
if (theConceptsStack.put(theConcept, PLACEHOLDER_OBJECT) != null) {
|
||||
if (theConceptsStack.contains(theConcept.getCode())) {
|
||||
throw new InvalidRequestException("CodeSystem contains circular reference around code " + theConcept.getCode());
|
||||
}
|
||||
|
||||
theConceptsStack.add(theConcept.getCode());
|
||||
|
||||
int retVal = 0;
|
||||
if (theAllConcepts.put(theConcept, theAllConcepts) == null) {
|
||||
if (theAllConcepts.size() % 1000 == 0) {
|
||||
@ -372,7 +426,7 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
||||
retVal += validateConceptForStorage(next.getChild(), theCodeSystem, theConceptsStack, theAllConcepts);
|
||||
}
|
||||
|
||||
theConceptsStack.remove(theConcept);
|
||||
theConceptsStack.remove(theConceptsStack.size() - 1);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
|
||||
} else if (nextFilter.getOp() == FilterOperator.ISA) {
|
||||
if (isNotBlank(nextFilter.getValue())) {
|
||||
TermConcept code = super.findCode(system, nextFilter.getValue());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching(code.getId()).createQuery());
|
||||
bool.must(qb.keyword().onField("myParentPids").matching("" + code.getId()).createQuery());
|
||||
}
|
||||
} else {
|
||||
throw new InvalidRequestException("Unknown filter property[" + nextFilter + "] + op[" + nextFilter.getOpElement().getValueAsString() + "]");
|
||||
|
@ -48,4 +48,12 @@ public interface IHapiTerminologySvc {
|
||||
|
||||
List<TermConcept> findCodes(String theSystem);
|
||||
|
||||
void saveDeferred();
|
||||
|
||||
/**
|
||||
* This is mostly for unit tests - we can disable processing of deferred concepts
|
||||
* by changing this flag
|
||||
*/
|
||||
void setProcessDeferred(boolean theProcessDeferred);
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
@ -24,20 +23,19 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -56,18 +54,20 @@ import org.apache.commons.lang3.Validate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvc.LoincHierarchyHandler;
|
||||
import ca.uhn.fhir.jpa.util.Counter;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
private static final int LOG_INCREMENT = 100000;
|
||||
|
||||
public static final String LOINC_FILE = "loinc.csv";
|
||||
|
||||
public static final String LOINC_HIERARCHY_FILE = "MULTI-AXIAL_HIERARCHY.CSV";
|
||||
@ -79,15 +79,8 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTermSvc;
|
||||
|
||||
private void cleanUpTemporaryFiles(Map<String, File> filenameToFile) {
|
||||
ourLog.info("Finished terminology file import, cleaning up temporary files");
|
||||
for (File nextFile : filenameToFile.values()) {
|
||||
nextFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void dropCircularRefs(TermConcept theConcept, LinkedHashSet<String> theChain, Map<String, TermConcept> theCode2concept) {
|
||||
|
||||
private void dropCircularRefs(TermConcept theConcept, ArrayList<String> theChain, Map<String, TermConcept> theCode2concept, Counter theCircularCounter) {
|
||||
|
||||
theChain.add(theConcept.getCode());
|
||||
for (Iterator<TermConceptParentChildLink> childIter = theConcept.getChildren().iterator(); childIter.hasNext();) {
|
||||
TermConceptParentChildLink next = childIter.next();
|
||||
@ -110,46 +103,25 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
ourLog.info(b.toString(), theConcept.getCode());
|
||||
childIter.remove();
|
||||
} else {
|
||||
dropCircularRefs(nextChild, theChain, theCode2concept);
|
||||
dropCircularRefs(nextChild, theChain, theCode2concept, theCircularCounter);
|
||||
}
|
||||
}
|
||||
theChain.remove(theConcept.getCode());
|
||||
theChain.remove(theChain.size() - 1);
|
||||
|
||||
}
|
||||
|
||||
private Map<String, File> extractFiles(List<byte[]> theZipBytes, List<String> theExpectedFilenameFragments) {
|
||||
Map<String, File> filenameToFile = new HashMap<String, File>();
|
||||
private void extractFiles(List<byte[]> theZipBytes, List<String> theExpectedFilenameFragments) {
|
||||
Set<String> foundFragments = new HashSet<String>();
|
||||
|
||||
for (byte[] nextZipBytes : theZipBytes) {
|
||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new ByteArrayInputStream(nextZipBytes)));
|
||||
try {
|
||||
for (ZipEntry nextEntry; (nextEntry = zis.getNextEntry()) != null;) {
|
||||
ZippedFileInputStream inputStream = new ZippedFileInputStream(zis);
|
||||
|
||||
boolean want = false;
|
||||
for (String next : theExpectedFilenameFragments) {
|
||||
if (nextEntry.getName().contains(next)) {
|
||||
want = true;
|
||||
foundFragments.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
if (!want) {
|
||||
ourLog.info("Ignoring zip entry: {}", nextEntry.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
ourLog.info("Streaming ZIP entry {} into temporary file", nextEntry.getName());
|
||||
|
||||
File nextOutFile = File.createTempFile("hapi_fhir", ".csv");
|
||||
nextOutFile.deleteOnExit();
|
||||
OutputStream outputStream = new SinkOutputStream(new FileOutputStream(nextOutFile, false), nextEntry.getName());
|
||||
try {
|
||||
IOUtils.copyLarge(inputStream, outputStream);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
|
||||
filenameToFile.put(nextEntry.getName(), nextOutFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InternalErrorException(e);
|
||||
@ -158,10 +130,12 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
}
|
||||
}
|
||||
|
||||
if (filenameToFile.size() != theExpectedFilenameFragments.size()) {
|
||||
throw new InvalidRequestException("Invalid input zip file, expected zip to contain the following name fragments: " + theExpectedFilenameFragments + " but found: " + filenameToFile.keySet());
|
||||
for (String next : theExpectedFilenameFragments) {
|
||||
if (!foundFragments.contains(next)) {
|
||||
throw new InvalidRequestException("Invalid input zip file, expected zip to contain the following name fragments: " + theExpectedFilenameFragments + " but found: " + foundFragments);
|
||||
}
|
||||
}
|
||||
return filenameToFile;
|
||||
|
||||
}
|
||||
|
||||
public String firstNonBlank(String... theStrings) {
|
||||
@ -185,49 +159,54 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
return concept;
|
||||
}
|
||||
|
||||
private void iterateOverZipFile(Map<String, File> theFilenameToFile, String fileNamePart, IRecordHandler handler, char theDelimiter, QuoteMode theQuoteMode) {
|
||||
private void iterateOverZipFile(List<byte[]> theZipBytes, String fileNamePart, IRecordHandler handler, char theDelimiter, QuoteMode theQuoteMode) {
|
||||
boolean found = false;
|
||||
for (Entry<String, File> nextEntry : new HashMap<String, File>(theFilenameToFile).entrySet()) {
|
||||
|
||||
if (nextEntry.getKey().contains(fileNamePart)) {
|
||||
ourLog.info("Processing file {}", nextEntry.getKey());
|
||||
found = true;
|
||||
for (byte[] nextZipBytes : theZipBytes) {
|
||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new ByteArrayInputStream(nextZipBytes)));
|
||||
try {
|
||||
for (ZipEntry nextEntry; (nextEntry = zis.getNextEntry()) != null;) {
|
||||
ZippedFileInputStream inputStream = new ZippedFileInputStream(zis);
|
||||
|
||||
Reader reader = null;
|
||||
CSVParser parsed = null;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(nextEntry.getValue()));
|
||||
CSVFormat format = CSVFormat.newFormat(theDelimiter).withFirstRecordAsHeader();
|
||||
if (theQuoteMode != null) {
|
||||
format = format.withQuote('"').withQuoteMode(theQuoteMode);
|
||||
}
|
||||
parsed = new CSVParser(reader, format);
|
||||
Iterator<CSVRecord> iter = parsed.iterator();
|
||||
ourLog.debug("Header map: {}", parsed.getHeaderMap());
|
||||
String nextFilename = nextEntry.getName();
|
||||
if (nextFilename.contains(fileNamePart)) {
|
||||
ourLog.info("Processing file {}", nextFilename);
|
||||
found = true;
|
||||
|
||||
int count = 0;
|
||||
int logIncrement = 100000;
|
||||
int nextLoggedCount = logIncrement;
|
||||
while (iter.hasNext()) {
|
||||
CSVRecord nextRecord = iter.next();
|
||||
handler.accept(nextRecord);
|
||||
count++;
|
||||
if (count >= nextLoggedCount) {
|
||||
ourLog.info(" * Processed {} records in {}", count, fileNamePart);
|
||||
nextLoggedCount += logIncrement;
|
||||
Reader reader = null;
|
||||
CSVParser parsed = null;
|
||||
try {
|
||||
reader = new InputStreamReader(zis, Charsets.UTF_8);
|
||||
CSVFormat format = CSVFormat.newFormat(theDelimiter).withFirstRecordAsHeader();
|
||||
if (theQuoteMode != null) {
|
||||
format = format.withQuote('"').withQuoteMode(theQuoteMode);
|
||||
}
|
||||
parsed = new CSVParser(reader, format);
|
||||
Iterator<CSVRecord> iter = parsed.iterator();
|
||||
ourLog.debug("Header map: {}", parsed.getHeaderMap());
|
||||
|
||||
int count = 0;
|
||||
int logIncrement = LOG_INCREMENT;
|
||||
int nextLoggedCount = 0;
|
||||
while (iter.hasNext()) {
|
||||
CSVRecord nextRecord = iter.next();
|
||||
handler.accept(nextRecord);
|
||||
count++;
|
||||
if (count >= nextLoggedCount) {
|
||||
ourLog.info(" * Processed {} records in {}", count, nextFilename);
|
||||
nextLoggedCount += logIncrement;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
}
|
||||
|
||||
ourLog.info("Deleting temporary file: {}", nextEntry.getValue());
|
||||
nextEntry.getValue().delete();
|
||||
theFilenameToFile.remove(nextEntry.getKey());
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(parsed);
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(zis);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,42 +218,36 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
public UploadStatistics loadLoinc(List<byte[]> theZipBytes, RequestDetails theRequestDetails) {
|
||||
List<String> expectedFilenameFragments = Arrays.asList(LOINC_FILE, LOINC_HIERARCHY_FILE);
|
||||
|
||||
Map<String, File> filenameToFile = extractFiles(theZipBytes, expectedFilenameFragments);
|
||||
extractFiles(theZipBytes, expectedFilenameFragments);
|
||||
|
||||
ourLog.info("Beginning LOINC processing");
|
||||
|
||||
try {
|
||||
return processLoincFiles(filenameToFile, theRequestDetails);
|
||||
} finally {
|
||||
cleanUpTemporaryFiles(filenameToFile);
|
||||
}
|
||||
return processLoincFiles(theZipBytes, theRequestDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UploadStatistics loadSnomedCt(List<byte[]> theZipBytes, RequestDetails theRequestDetails) {
|
||||
List<String> expectedFilenameFragments = Arrays.asList(SCT_FILE_DESCRIPTION, SCT_FILE_RELATIONSHIP, SCT_FILE_CONCEPT);
|
||||
|
||||
Map<String, File> filenameToFile = extractFiles(theZipBytes, expectedFilenameFragments);
|
||||
extractFiles(theZipBytes, expectedFilenameFragments);
|
||||
|
||||
ourLog.info("Beginning SNOMED CT processing");
|
||||
|
||||
try {
|
||||
return processSnomedCtFiles(filenameToFile, theRequestDetails);
|
||||
} finally {
|
||||
cleanUpTemporaryFiles(filenameToFile);
|
||||
}
|
||||
return processSnomedCtFiles(theZipBytes, theRequestDetails);
|
||||
}
|
||||
|
||||
UploadStatistics processLoincFiles(Map<String, File> filenameToFile, RequestDetails theRequestDetails) {
|
||||
UploadStatistics processLoincFiles(List<byte[]> theZipBytes, RequestDetails theRequestDetails) {
|
||||
final TermCodeSystemVersion codeSystemVersion = new TermCodeSystemVersion();
|
||||
final Map<String, TermConcept> code2concept = new HashMap<String, TermConcept>();
|
||||
|
||||
IRecordHandler handler = new LoincHandler(codeSystemVersion, code2concept);
|
||||
iterateOverZipFile(filenameToFile, LOINC_FILE, handler, ',', QuoteMode.NON_NUMERIC);
|
||||
iterateOverZipFile(theZipBytes, LOINC_FILE, handler, ',', QuoteMode.NON_NUMERIC);
|
||||
|
||||
handler = new LoincHierarchyHandler(codeSystemVersion, code2concept);
|
||||
iterateOverZipFile(filenameToFile, LOINC_HIERARCHY_FILE, handler, ',', QuoteMode.NON_NUMERIC);
|
||||
iterateOverZipFile(theZipBytes, LOINC_HIERARCHY_FILE, handler, ',', QuoteMode.NON_NUMERIC);
|
||||
|
||||
theZipBytes.clear();
|
||||
|
||||
for (Iterator<Entry<String, TermConcept>> iter = code2concept.entrySet().iterator(); iter.hasNext();) {
|
||||
Entry<String, TermConcept> next = iter.next();
|
||||
// if (isBlank(next.getKey())) {
|
||||
@ -290,39 +263,60 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
|
||||
ourLog.info("Have {} total concepts, {} root concepts", code2concept.size(), codeSystemVersion.getConcepts().size());
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(LOINC_URL, codeSystemVersion, theRequestDetails);
|
||||
String url = LOINC_URL;
|
||||
storeCodeSystem(theRequestDetails, codeSystemVersion, url);
|
||||
|
||||
return new UploadStatistics(code2concept.size());
|
||||
}
|
||||
|
||||
UploadStatistics processSnomedCtFiles(Map<String, File> filenameToFile, RequestDetails theRequestDetails) {
|
||||
private void storeCodeSystem(RequestDetails theRequestDetails, final TermCodeSystemVersion codeSystemVersion, String url) {
|
||||
myTermSvc.setProcessDeferred(false);
|
||||
myTermSvc.storeNewCodeSystemVersion(url, codeSystemVersion, theRequestDetails);
|
||||
myTermSvc.setProcessDeferred(true);
|
||||
}
|
||||
|
||||
UploadStatistics processSnomedCtFiles(List<byte[]> theZipBytes, RequestDetails theRequestDetails) {
|
||||
final TermCodeSystemVersion codeSystemVersion = new TermCodeSystemVersion();
|
||||
final Map<String, TermConcept> id2concept = new HashMap<String, TermConcept>();
|
||||
final Map<String, TermConcept> code2concept = new HashMap<String, TermConcept>();
|
||||
final Set<String> validConceptIds = new HashSet<String>();
|
||||
|
||||
IRecordHandler handler = new SctHandlerConcept(validConceptIds);
|
||||
iterateOverZipFile(filenameToFile, SCT_FILE_CONCEPT, handler, '\t', null);
|
||||
iterateOverZipFile(theZipBytes, SCT_FILE_CONCEPT, handler, '\t', null);
|
||||
|
||||
ourLog.info("Have {} valid concept IDs", validConceptIds.size());
|
||||
|
||||
handler = new SctHandlerDescription(validConceptIds, code2concept, id2concept, codeSystemVersion);
|
||||
iterateOverZipFile(filenameToFile, SCT_FILE_DESCRIPTION, handler, '\t', null);
|
||||
iterateOverZipFile(theZipBytes, SCT_FILE_DESCRIPTION, handler, '\t', null);
|
||||
|
||||
ourLog.info("Got {} concepts, cloning map", code2concept.size());
|
||||
final HashMap<String, TermConcept> rootConcepts = new HashMap<String, TermConcept>(code2concept);
|
||||
|
||||
handler = new SctHandlerRelationship(codeSystemVersion, rootConcepts, code2concept);
|
||||
iterateOverZipFile(filenameToFile, SCT_FILE_RELATIONSHIP, handler, '\t', null);
|
||||
iterateOverZipFile(theZipBytes, SCT_FILE_RELATIONSHIP, handler, '\t', null);
|
||||
|
||||
theZipBytes.clear();
|
||||
|
||||
ourLog.info("Looking for root codes");
|
||||
for (Iterator<Entry<String, TermConcept>> iter = rootConcepts.entrySet().iterator(); iter.hasNext(); ) {
|
||||
if (iter.next().getValue().getParents().isEmpty() == false) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
ourLog.info("Done loading SNOMED CT files - {} root codes, {} total codes", rootConcepts.size(), code2concept.size());
|
||||
|
||||
Counter circularCounter = new Counter();
|
||||
for (TermConcept next : rootConcepts.values()) {
|
||||
dropCircularRefs(next, new LinkedHashSet<String>(), code2concept);
|
||||
long count = circularCounter.getThenAdd();
|
||||
float pct = ((float)count / rootConcepts.size()) * 100.0f;
|
||||
ourLog.info(" * Scanning for circular refs - have scanned {} / {} codes ({}%)", count, rootConcepts.size(), pct);
|
||||
dropCircularRefs(next, new ArrayList<String>(), code2concept, circularCounter);
|
||||
}
|
||||
|
||||
codeSystemVersion.getConcepts().addAll(rootConcepts.values());
|
||||
myTermSvc.storeNewCodeSystemVersion(SCT_URL, codeSystemVersion, theRequestDetails);
|
||||
String url = SCT_URL;
|
||||
storeCodeSystem(theRequestDetails, codeSystemVersion, url);
|
||||
|
||||
return new UploadStatistics(code2concept.size());
|
||||
}
|
||||
@ -332,20 +326,6 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
myTermSvc = theTermSvc;
|
||||
}
|
||||
|
||||
@CoverageIgnore
|
||||
public static void main(String[] args) throws Exception {
|
||||
TerminologyLoaderSvc svc = new TerminologyLoaderSvc();
|
||||
|
||||
// byte[] bytes = IOUtils.toByteArray(new FileInputStream("/Users/james/Downloads/SnomedCT_Release_INT_20160131_Full.zip"));
|
||||
// svc.loadSnomedCt(bytes);
|
||||
|
||||
Map<String, File> files = new HashMap<String, File>();
|
||||
files.put(SCT_FILE_CONCEPT, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Concept_Full_INT_20160131.txt"));
|
||||
files.put(SCT_FILE_DESCRIPTION, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Description_Full-en_INT_20160131.txt"));
|
||||
files.put(SCT_FILE_RELATIONSHIP, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Relationship_Full_INT_20160131.txt"));
|
||||
svc.processSnomedCtFiles(files, null);
|
||||
}
|
||||
|
||||
private interface IRecordHandler {
|
||||
void accept(CSVRecord theRecord);
|
||||
}
|
||||
@ -506,23 +486,33 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
String destinationId = theRecord.get("destinationId");
|
||||
String typeId = theRecord.get("typeId");
|
||||
boolean active = "1".equals(theRecord.get("active"));
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
|
||||
TermConcept typeConcept = myCode2concept.get(typeId);
|
||||
TermConcept sourceConcept = myCode2concept.get(sourceId);
|
||||
TermConcept targetConcept = myCode2concept.get(destinationId);
|
||||
if (sourceConcept != null && targetConcept != null && typeConcept != null) {
|
||||
if (typeConcept.getDisplay().equals("Is a (attribute)")) {
|
||||
RelationshipTypeEnum relationshipType = RelationshipTypeEnum.ISA;
|
||||
if (!sourceId.equals(destinationId)) {
|
||||
TermConceptParentChildLink link = new TermConceptParentChildLink();
|
||||
link.setChild(sourceConcept);
|
||||
link.setParent(targetConcept);
|
||||
link.setRelationshipType(TermConceptParentChildLink.RelationshipTypeEnum.ISA);
|
||||
link.setCodeSystem(myCodeSystemVersion);
|
||||
myRootConcepts.remove(link.getChild().getCode());
|
||||
|
||||
targetConcept.addChild(sourceConcept, RelationshipTypeEnum.ISA);
|
||||
if (active) {
|
||||
TermConceptParentChildLink link = new TermConceptParentChildLink();
|
||||
link.setChild(sourceConcept);
|
||||
link.setParent(targetConcept);
|
||||
link.setRelationshipType(relationshipType);
|
||||
link.setCodeSystem(myCodeSystemVersion);
|
||||
|
||||
targetConcept.addChild(sourceConcept, relationshipType);
|
||||
} else {
|
||||
// not active, so we're removing any existing links
|
||||
for (TermConceptParentChildLink next : new ArrayList<TermConceptParentChildLink>(targetConcept.getChildren())) {
|
||||
if (next.getRelationshipType() == relationshipType) {
|
||||
if (next.getChild().getCode().equals(sourceConcept.getCode())) {
|
||||
next.getParent().getChildren().remove(next);
|
||||
next.getChild().getParents().remove(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ignoredTypes.contains(typeConcept.getDisplay())) {
|
||||
// ignore
|
||||
@ -534,57 +524,6 @@ public class TerminologyLoaderSvc implements IHapiTerminologyLoaderSvc {
|
||||
|
||||
}
|
||||
|
||||
private static class SinkOutputStream extends OutputStream {
|
||||
|
||||
private static final long LOG_INCREMENT = 10 * FileUtils.ONE_MB;
|
||||
private int myBytes;
|
||||
private String myFilename;
|
||||
private long myNextLogCount = LOG_INCREMENT;
|
||||
private FileOutputStream myWrap;
|
||||
|
||||
public SinkOutputStream(FileOutputStream theWrap, String theFilename) {
|
||||
myWrap = theWrap;
|
||||
myFilename = theFilename;
|
||||
}
|
||||
|
||||
private void addCount(int theCount) {
|
||||
myBytes += theCount;
|
||||
if (myBytes > myNextLogCount) {
|
||||
ourLog.info(" * Wrote {} of {}", FileUtils.byteCountToDisplaySize(myBytes), myFilename);
|
||||
myNextLogCount = myBytes + LOG_INCREMENT;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
myWrap.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
myWrap.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] theB) throws IOException {
|
||||
myWrap.write(theB);
|
||||
addCount(theB.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] theB, int theOff, int theLen) throws IOException {
|
||||
myWrap.write(theB, theOff, theLen);
|
||||
addCount(theLen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int theB) throws IOException {
|
||||
myWrap.write(theB);
|
||||
addCount(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ZippedFileInputStream extends InputStream {
|
||||
|
||||
private ZipInputStream is;
|
||||
|
@ -0,0 +1,11 @@
|
||||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
public class Counter {
|
||||
|
||||
private long myCount;
|
||||
|
||||
public long getThenAdd() {
|
||||
return myCount++;
|
||||
}
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.hibernate.cfg.ImprovedNamingStrategy;
|
||||
|
||||
public class CustomNamingStrategy extends ImprovedNamingStrategy {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PREFIX = "FR_";
|
||||
|
||||
// @Override
|
||||
// public String classToTableName(final String className) {
|
||||
// return this.addPrefix(super.classToTableName(className));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String collectionTableName(final String ownerEntity,
|
||||
// final String ownerEntityTable, final String associatedEntity,
|
||||
// final String associatedEntityTable, final String propertyName) {
|
||||
// return this.addPrefix(super.collectionTableName(ownerEntity,
|
||||
// ownerEntityTable, associatedEntity, associatedEntityTable,
|
||||
// propertyName));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String foreignKeyColumnName(String thePropertyName, String thePropertyEntityName, String thePropertyTableName, String theReferencedColumnName) {
|
||||
// String foreignKeyColumnName = super.foreignKeyColumnName(thePropertyName, thePropertyEntityName, thePropertyTableName, theReferencedColumnName);
|
||||
// return foreignKeyColumnName;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String logicalCollectionTableName(final String tableName,
|
||||
// final String ownerEntityTable, final String associatedEntityTable,
|
||||
// final String propertyName) {
|
||||
// return this.addPrefix(super.logicalCollectionTableName(tableName,
|
||||
// ownerEntityTable, associatedEntityTable, propertyName));
|
||||
// }
|
||||
//
|
||||
// private String addPrefix(final String composedTableName) {
|
||||
//
|
||||
// return PREFIX
|
||||
// + composedTableName.toUpperCase().replace("_", "");
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.hibernate.dialect.DerbyTenSevenDialect;
|
||||
|
||||
/**
|
||||
* As of Hibernate 5.0.1, DerbyTenSevenDialect doesn't seem to work when updating
|
||||
* the schema, as it tries to create a duplicate schema
|
||||
*/
|
||||
public class HapiDerbyTenSevenDialect extends DerbyTenSevenDialect {
|
||||
|
||||
@Override
|
||||
public String getQuerySequencesString() {
|
||||
return "select SEQUENCENAME from sys.syssequences";
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import static org.junit.Assert.fail;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.AuditEvent;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
@ -22,11 +21,13 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
@ -339,6 +340,42 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||
assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexingIsDeferredForLargeCodeSystems() {
|
||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(1);
|
||||
|
||||
myTermSvc.setProcessDeferred(false);
|
||||
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
||||
include.addFilter().setProperty("display").setOp(FilterOperator.ISA).setValue("ParentA");
|
||||
|
||||
ValueSet result = myValueSetDao.expand(vs, null);
|
||||
String encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||
ourLog.info(encoded);
|
||||
|
||||
assertEquals(0, result.getExpansion().getContains().size());
|
||||
|
||||
myTermSvc.setProcessDeferred(true);
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
myTermSvc.saveDeferred();
|
||||
|
||||
result = myValueSetDao.expand(vs, null);
|
||||
encoded = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result);
|
||||
ourLog.info(encoded);
|
||||
assertEquals(4, result.getExpansion().getContains().size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandWithExcludeInExternalValueSet() {
|
||||
createExternalCsAndLocalVs();
|
||||
@ -486,6 +523,11 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
||||
public void before() {
|
||||
myDaoConfig.setMaximumExpansionSize(5000);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchCodeBelowLocalCodesystem() {
|
||||
|
@ -185,22 +185,22 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
||||
List<String> idValues;
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + id.getIdPart() + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
|
||||
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
|
||||
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
|
||||
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0)));
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt2060");
|
||||
assertThat(idValues, empty());
|
||||
assertThat(idValues.toString(), idValues, empty());
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=" + InstantDt.withCurrentTime().getYear());
|
||||
assertThat(idValues, hasSize(10)); // 10 is the page size
|
||||
assertThat(idValues.toString(), idValues, hasSize(10)); // 10 is the page size
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=ge" + InstantDt.withCurrentTime().getYear());
|
||||
assertThat(idValues, hasSize(10));
|
||||
assertThat(idValues.toString(), idValues, hasSize(10));
|
||||
|
||||
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + InstantDt.withCurrentTime().getYear());
|
||||
assertThat(idValues, hasSize(0));
|
||||
|
@ -34,7 +34,7 @@ public class TerminologyLoaderSvcIntegrationTest extends BaseJpaDstu3Test {
|
||||
files.put(TerminologyLoaderSvc.SCT_FILE_CONCEPT, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Concept_Full_INT_20160131.txt"));
|
||||
files.put(TerminologyLoaderSvc.SCT_FILE_DESCRIPTION, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Description_Full-en_INT_20160131.txt"));
|
||||
files.put(TerminologyLoaderSvc.SCT_FILE_RELATIONSHIP, new File("/Users/james/tmp/sct/SnomedCT_Release_INT_20160131_Full/Terminology/sct2_Relationship_Full_INT_20160131.txt"));
|
||||
myLoader.processSnomedCtFiles(files, mySrd);
|
||||
// myLoader.processSnomedCtFiles(files, mySrd);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@ -12,8 +13,10 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@ -40,19 +43,19 @@ import ca.uhn.fhir.util.TestUtil;
|
||||
public class TerminologyLoaderSvcTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TerminologyLoaderSvcTest.class);
|
||||
private TerminologyLoaderSvc mySvc;
|
||||
|
||||
|
||||
@Mock
|
||||
private IHapiTerminologySvc myTermSvc;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<TermCodeSystemVersion> myCsvCaptor;
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
mySvc = new TerminologyLoaderSvc();
|
||||
mySvc.setTermSvcForUnitTests(myTermSvc);
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
@ -62,18 +65,18 @@ public class TerminologyLoaderSvcTest {
|
||||
public void testLoadLoinc() throws Exception {
|
||||
ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
|
||||
ZipOutputStream zos1 = new ZipOutputStream(bos1);
|
||||
addEntry(zos1,"/loinc/", "loinc.csv");
|
||||
addEntry(zos1, "/loinc/", "loinc.csv");
|
||||
zos1.close();
|
||||
ourLog.info("ZIP file has {} bytes", bos1.toByteArray().length);
|
||||
|
||||
|
||||
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
|
||||
ZipOutputStream zos2 = new ZipOutputStream(bos2);
|
||||
addEntry(zos2,"/loinc/", "LOINC_2.54_MULTI-AXIAL_HIERARCHY.CSV");
|
||||
addEntry(zos2, "/loinc/", "LOINC_2.54_MULTI-AXIAL_HIERARCHY.CSV");
|
||||
zos2.close();
|
||||
ourLog.info("ZIP file has {} bytes", bos2.toByteArray().length);
|
||||
|
||||
|
||||
RequestDetails details = mock(RequestDetails.class);
|
||||
mySvc.loadLoinc(Arrays.asList(bos1.toByteArray(), bos2.toByteArray()), details);
|
||||
mySvc.loadLoinc(list(bos1.toByteArray(), bos2.toByteArray()), details);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -84,38 +87,48 @@ public class TerminologyLoaderSvcTest {
|
||||
addEntry(zos, "/sct/", "sct2_Concept_Full-en_INT_20160131.txt");
|
||||
addEntry(zos, "/sct/", "sct2_Description_Full-en_INT_20160131.txt");
|
||||
addEntry(zos, "/sct/", "sct2_Identifier_Full_INT_20160131.txt");
|
||||
addEntry(zos,"/sct/", "sct2_Relationship_Full_INT_20160131.txt");
|
||||
addEntry(zos,"/sct/", "sct2_StatedRelationship_Full_INT_20160131.txt");
|
||||
addEntry(zos, "/sct/", "sct2_Relationship_Full_INT_20160131.txt");
|
||||
addEntry(zos, "/sct/", "sct2_StatedRelationship_Full_INT_20160131.txt");
|
||||
addEntry(zos, "/sct/", "sct2_TextDefinition_Full-en_INT_20160131.txt");
|
||||
zos.close();
|
||||
|
||||
|
||||
ourLog.info("ZIP file has {} bytes", bos.toByteArray().length);
|
||||
|
||||
|
||||
RequestDetails details = mock(RequestDetails.class);
|
||||
mySvc.loadSnomedCt(Collections.singletonList(bos.toByteArray()), details);
|
||||
|
||||
mySvc.loadSnomedCt(list(bos.toByteArray()), details);
|
||||
|
||||
verify(myTermSvc).storeNewCodeSystemVersion(any(String.class), myCsvCaptor.capture(), any(RequestDetails.class));
|
||||
|
||||
|
||||
TermCodeSystemVersion csv = myCsvCaptor.getValue();
|
||||
TreeSet<String> allCodes = toCodes(csv);
|
||||
TreeSet<String> allCodes = toCodes(csv, true);
|
||||
ourLog.info(allCodes.toString());
|
||||
|
||||
|
||||
assertThat(allCodes, containsInRelativeOrder("116680003"));
|
||||
assertThat(allCodes, not(containsInRelativeOrder("207527008")));
|
||||
|
||||
allCodes = toCodes(csv, false);
|
||||
ourLog.info(allCodes.toString());
|
||||
assertThat(allCodes, hasItem("126816002"));
|
||||
}
|
||||
|
||||
private TreeSet<String> toCodes(TermCodeSystemVersion theCsv) {
|
||||
private List<byte[]> list(byte[]... theByteArray) {
|
||||
return new ArrayList<byte[]>(Arrays.asList(theByteArray));
|
||||
}
|
||||
|
||||
private TreeSet<String> toCodes(TermCodeSystemVersion theCsv, boolean theAddChildren) {
|
||||
TreeSet<String> retVal = new TreeSet<String>();
|
||||
for (TermConcept next : theCsv.getConcepts()) {
|
||||
toCodes(retVal, next);
|
||||
toCodes(retVal, next, theAddChildren);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void toCodes(TreeSet<String> theCodes, TermConcept theConcept) {
|
||||
private void toCodes(TreeSet<String> theCodes, TermConcept theConcept, boolean theAddChildren) {
|
||||
theCodes.add(theConcept.getCode());
|
||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||
toCodes(theCodes, next.getChild());
|
||||
if (theAddChildren) {
|
||||
for (TermConceptParentChildLink next : theConcept.getChildren()) {
|
||||
toCodes(theCodes, next.getChild(), theAddChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,9 +138,9 @@ public class TerminologyLoaderSvcTest {
|
||||
ZipOutputStream zos = new ZipOutputStream(bos);
|
||||
addEntry(zos, "/sct/", "sct2_StatedRelationship_Full_INT_20160131.txt");
|
||||
zos.close();
|
||||
|
||||
|
||||
ourLog.info("ZIP file has {} bytes", bos.toByteArray().length);
|
||||
|
||||
|
||||
RequestDetails details = mock(RequestDetails.class);
|
||||
try {
|
||||
mySvc.loadSnomedCt(Collections.singletonList(bos.toByteArray()), details);
|
||||
@ -145,6 +158,5 @@ public class TerminologyLoaderSvcTest {
|
||||
zos.write(byteArray);
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ id effectiveTime active moduleId definitionStatusId
|
||||
126813005 20020131 1 900000000000207008 900000000000074008
|
||||
126813006 20020131 1 900000000000207008 900000000000074008
|
||||
126817006 20020131 1 900000000000207008 900000000000074008
|
||||
126816002 20020131 1 900000000000207008 900000000000074008
|
||||
207527008 20020131 1 900000000000207008 900000000000074008
|
||||
207527008 20040731 1 900000000000207008 900000000000073002
|
||||
207527008 20090731 0 900000000000207008 900000000000074008
|
||||
|
@ -1,5 +1,6 @@
|
||||
id effectiveTime active moduleId sourceId destinationId relationshipGroup typeId characteristicTypeId modifierId
|
||||
100022 20020131 1 900000000000207008 126815003 126813005 0 116680003 900000000000011006 900000000000451002
|
||||
100022 20090731 0 900000000000207008 126816002 126813005 0 116680003 900000000000011006 900000000000451002
|
||||
100025 20020131 1 900000000000207008 126816002 126813005 0 116680003 900000000000011006 900000000000451002
|
||||
100025 20090731 0 900000000000207008 126816002 126813005 0 116680003 900000000000011006 900000000000451002
|
||||
101021 20020131 1 900000000000207008 126817006 126815003 0 116680003 900000000000011006 900000000000451002
|
||||
101021 20020131 1 900000000000207008 126815003 126817006 0 116680003 900000000000011006 900000000000451002
|
||||
|
@ -44,6 +44,7 @@ import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.AllergyIntolerance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu.resource.CarePlan;
|
||||
import ca.uhn.fhir.model.dstu.resource.Composition;
|
||||
import ca.uhn.fhir.model.dstu.resource.Condition;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
@ -67,6 +68,7 @@ import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.IdrefDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
@ -95,6 +97,21 @@ public class XmlParserTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeAndParseIdref() {
|
||||
CarePlan cp = new CarePlan();
|
||||
cp.addGoal().setNotes("Goal Notes").setElementSpecificId("goalId0");
|
||||
|
||||
IdrefDt idref = new IdrefDt();
|
||||
idref.setValue("#goalId0");
|
||||
idref.setTarget(cp);
|
||||
idref.getTarget();
|
||||
cp.addActivity().getGoal().add(idref);
|
||||
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(cp);
|
||||
ourLog.info(encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for #82 - Not yet enabled because the test won't pass
|
||||
*/
|
||||
|
@ -32,7 +32,7 @@ import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerExcept
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ClientServerValidationTestDstu {
|
||||
public class ClientServerValidationDstu1Test {
|
||||
|
||||
private FhirContext myCtx;
|
||||
private HttpClient myHttpClient;
|
@ -15,7 +15,9 @@ import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
@ -33,6 +35,7 @@ import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@ -82,6 +85,8 @@ public class GenericClientTest {
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
|
||||
System.setProperty(BaseClient.HAPI_CLIENT_KEEPRESPONSES, "true");
|
||||
}
|
||||
|
||||
private String extractBody(ArgumentCaptor<HttpUriRequest> capt, int count) throws IOException {
|
||||
@ -89,6 +94,24 @@ public class GenericClientTest {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidCalls() {
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
try {
|
||||
client.meta();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals("Can not call $meta operations on a DSTU1 client", e.getMessage());
|
||||
}
|
||||
try {
|
||||
client.operation();
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals("Operations are only supported in FHIR DSTU2 and later. This client was created using a context configured for DSTU1", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
String msg = "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" +
|
||||
@ -155,6 +178,9 @@ public class GenericClientTest {
|
||||
resp = client.create().resource(ourCtx.newXmlParser().encodeResourceToString(p1)).execute();
|
||||
assertNull(resp.getCreated());
|
||||
|
||||
ourLog.info("lastRequest: {}", ((GenericClient)client).getLastRequest());
|
||||
ourLog.info("lastResponse: {}", ((GenericClient)client).getLastResponse());
|
||||
ourLog.info("lastResponseBody: {}", ((GenericClient)client).getLastResponseBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1471,6 +1497,25 @@ public class GenericClientTest {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testTransactionOldStyle() throws Exception {
|
||||
String bundleStr = IOUtils.toString(getClass().getResourceAsStream("/bundle.json"));
|
||||
Bundle bundle = ourCtx.newJsonParser().parseBundle(bundleStr);
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(bundleStr), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
List<IBaseResource> input = new ArrayList<IBaseResource>();
|
||||
input.addAll(bundle.toListOfResources());
|
||||
client.transaction(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionJson() throws Exception {
|
||||
String bundleStr = IOUtils.toString(getClass().getResourceAsStream("/bundle.json"));
|
||||
|
@ -10,11 +10,25 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import com.google.common.reflect.ClassPath.ClassInfo;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ExceptionPropertiesTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionPropertiesTest.class);
|
||||
|
||||
@Test
|
||||
public void testConstructors() {
|
||||
new FhirClientConnectionException("");
|
||||
new FhirClientConnectionException("", new Exception());
|
||||
new FhirClientConnectionException(new Exception());
|
||||
new NotImplementedOperationException("");
|
||||
new NotImplementedOperationException(null, new OperationOutcome());
|
||||
new FhirClientInappropriateForServerException(new Exception());
|
||||
new FhirClientInappropriateForServerException("", new Exception());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testExceptionsAreGood() throws Exception {
|
||||
|
@ -11,6 +11,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirContextDstu2Test {
|
||||
@ -23,6 +24,12 @@ public class FhirContextDstu2Test {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Test(expected=DataFormatException.class)
|
||||
public void testScanInvalid() {
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
ctx.getResourceDefinition("InvalidResource");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testQueryBoundCode() {
|
||||
|
@ -0,0 +1,15 @@
|
||||
package ca.uhn.fhir.model.primitive;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TimeDtTest {
|
||||
|
||||
@Test
|
||||
public void testEncode() {
|
||||
TimeDt dt = new TimeDt("11:33:01.123");
|
||||
assertEquals("11:33:01.123", dt.getValue());
|
||||
}
|
||||
|
||||
}
|
@ -37,9 +37,9 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||
public class DefaultThymeleafNarrativeGeneratorDstu2Test {
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultThymeleafNarrativeGeneratorTestDstu2.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultThymeleafNarrativeGeneratorDstu2Test.class);
|
||||
private DefaultThymeleafNarrativeGenerator myGen;
|
||||
|
||||
@AfterClass
|
@ -1,7 +1,12 @@
|
||||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@ -32,16 +37,15 @@ import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||
import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ClientServerValidationTestDstu2 {
|
||||
public class ClientServerValidationDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationTestDstu2.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ClientServerValidationDstu2Test.class);
|
||||
private FhirContext myCtx;
|
||||
private boolean myFirstResponse;
|
||||
private HttpClient myHttpClient;
|
@ -19,6 +19,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@ -45,18 +46,20 @@ import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Link;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Encounter;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
@ -68,15 +71,19 @@ 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.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.parser.XmlParserDstu2Test;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
@ -84,28 +91,29 @@ import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class GenericClientDstu2Test {
|
||||
private static FhirContext ourCtx;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GenericClientDstu2Test.class);
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GenericClientDstu2Test.class);
|
||||
private HttpClient myHttpClient;
|
||||
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
private int myResponseCount = 0;
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.setRestfulClientFactory(new ApacheRestfulClientFactory(ourCtx));
|
||||
ourCtx.getRestfulClientFactory().setConnectionRequestTimeout(10000);
|
||||
ourCtx.getRestfulClientFactory().setConnectTimeout(10000);
|
||||
ourCtx.getRestfulClientFactory().setPoolMaxPerRoute(100);
|
||||
ourCtx.getRestfulClientFactory().setPoolMaxTotal(100);
|
||||
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
myResponseCount = 0;
|
||||
|
||||
System.setProperty(BaseClient.HAPI_CLIENT_KEEPRESPONSES, "true");
|
||||
}
|
||||
|
||||
private String extractBody(ArgumentCaptor<HttpUriRequest> capt, int count) throws IOException {
|
||||
@ -113,7 +121,6 @@ public class GenericClientDstu2Test {
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
@ -134,7 +141,7 @@ public class GenericClientDstu2Test {
|
||||
//@formatter:on
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAcceptHeaderFetchConformance() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
@ -177,70 +184,6 @@ public class GenericClientDstu2Test {
|
||||
idx++;
|
||||
}
|
||||
|
||||
/**
|
||||
* See #322
|
||||
*/
|
||||
@Test
|
||||
public void testFetchConformanceWithSmartExtensions() throws Exception {
|
||||
final String respString = IOUtils.toString(GenericClientDstu2Test.class.getResourceAsStream("/conformance_322.json"));
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir");
|
||||
Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
|
||||
Rest rest = conf.getRest().get(0);
|
||||
RestSecurity security = rest.getSecurity();
|
||||
|
||||
List<ExtensionDt> ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
|
||||
List<ExtensionDt> tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token");
|
||||
ExtensionDt tokenExt = tokenExts.get(0);
|
||||
UriDt value = (UriDt) tokenExt.getValue();
|
||||
assertEquals("https://my-server.org/token", value.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* See #322
|
||||
*/
|
||||
@Test
|
||||
public void testFetchConformanceWithSmartExtensionsAltCase() throws Exception {
|
||||
final String respString = IOUtils.toString(GenericClientDstu2Test.class.getResourceAsStream("/conformance_322.json")).replace("valueuri", "valueUri");
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir");
|
||||
Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
|
||||
Rest rest = conf.getRest().get(0);
|
||||
RestSecurity security = rest.getSecurity();
|
||||
|
||||
List<ExtensionDt> ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
|
||||
List<ExtensionDt> tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token");
|
||||
ExtensionDt tokenExt = tokenExts.get(0);
|
||||
UriDt value = (UriDt) tokenExt.getValue();
|
||||
assertEquals("https://my-server.org/token", value.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptHeaderPreflightConformance() throws Exception {
|
||||
String methodName = "testAcceptHeaderPreflightConformance";
|
||||
@ -540,6 +483,30 @@ public class GenericClientDstu2Test {
|
||||
assertEquals("Patient/123", output.getResource().getIdElement().toUnqualifiedVersionless().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteByResource() throws Exception {
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, ""));
|
||||
when(myHttpResponse.getEntity().getContent()).then(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.setId("Patient/123");
|
||||
|
||||
client.delete().resource(pat).execute();
|
||||
assertEquals("DELETE", capt.getAllValues().get(idx).getMethod());
|
||||
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteConditional() throws Exception {
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
@ -575,6 +542,49 @@ public class GenericClientDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteInvalidRequest() throws Exception {
|
||||
Patient pat = new Patient();
|
||||
pat.setId("123");
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
try {
|
||||
client.delete().resource(pat).execute();
|
||||
fail();
|
||||
} catch (IllegalArgumentException e){
|
||||
assertEquals("theResource.getId() must contain a resource type and logical ID at a minimum (e.g. Patient/1234), found: 123", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
client.delete().resourceById(new IdDt("123")).execute();
|
||||
fail();
|
||||
} catch (IllegalArgumentException e){
|
||||
assertEquals("theId must contain a resource type and logical ID at a minimum (e.g. Patient/1234)found: 123", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
client.delete().resourceById("", "123").execute();
|
||||
fail();
|
||||
} catch (IllegalArgumentException e){
|
||||
assertEquals("theResourceType can not be blank/null", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
client.delete().resourceById("Patient", "").execute();
|
||||
fail();
|
||||
} catch (IllegalArgumentException e){
|
||||
assertEquals("theLogicalId can not be blank/null", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
client.delete().resourceConditionalByType("InvalidType");
|
||||
fail();
|
||||
} catch (DataFormatException e){
|
||||
assertEquals("Unknown resource name \"InvalidType\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testDeleteNonFluent() throws Exception {
|
||||
@ -604,6 +614,68 @@ public class GenericClientDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #322
|
||||
*/
|
||||
@Test
|
||||
public void testFetchConformanceWithSmartExtensions() throws Exception {
|
||||
final String respString = IOUtils.toString(GenericClientDstu2Test.class.getResourceAsStream("/conformance_322.json"));
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir");
|
||||
Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
|
||||
Rest rest = conf.getRest().get(0);
|
||||
RestSecurity security = rest.getSecurity();
|
||||
|
||||
List<ExtensionDt> ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
|
||||
List<ExtensionDt> tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token");
|
||||
ExtensionDt tokenExt = tokenExts.get(0);
|
||||
UriDt value = (UriDt) tokenExt.getValue();
|
||||
assertEquals("https://my-server.org/token", value.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #322
|
||||
*/
|
||||
@Test
|
||||
public void testFetchConformanceWithSmartExtensionsAltCase() throws Exception {
|
||||
final String respString = IOUtils.toString(GenericClientDstu2Test.class.getResourceAsStream("/conformance_322.json")).replace("valueuri", "valueUri");
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:8080/fhir");
|
||||
Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
|
||||
Rest rest = conf.getRest().get(0);
|
||||
RestSecurity security = rest.getSecurity();
|
||||
|
||||
List<ExtensionDt> ext = security.getUndeclaredExtensionsByUrl("http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
|
||||
List<ExtensionDt> tokenExts = ext.get(0).getUndeclaredExtensionsByUrl("token");
|
||||
ExtensionDt tokenExt = tokenExts.get(0);
|
||||
UriDt value = (UriDt) tokenExt.getValue();
|
||||
assertEquals("https://my-server.org/token", value.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
|
||||
@ -709,6 +781,16 @@ public class GenericClientDstu2Test {
|
||||
idx++;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidClient() {
|
||||
try {
|
||||
ourCtx.getRestfulClientFactory().newClient(RestfulClientInstance.class, "http://foo");
|
||||
fail();
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("ca.uhn.fhir.context.ConfigurationException: ca.uhn.fhir.rest.client.GenericClientDstu2Test.RestfulClientInstance is not an interface", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaAdd() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
@ -1504,10 +1586,10 @@ public class GenericClientDstu2Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderWhereWeForgotToSetTheContext() throws Exception {
|
||||
public void testProviderWhereWeForgotToSetTheContext() throws Exception {
|
||||
ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory(); // no ctx
|
||||
clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
|
||||
|
||||
ourCtx.setRestfulClientFactory(clientFactory);
|
||||
|
||||
try {
|
||||
@ -1576,6 +1658,24 @@ public class GenericClientDstu2Test {
|
||||
assertEquals("FAM", response.getName().get(0).getFamily().get(0).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadForUnknownType() throws Exception {
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
try {
|
||||
client.read(new UriDt("1"));
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("The given URI is not an absolute URL and is not usable for this operation: 1", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
client.read(new UriDt("http://example.com/InvalidResource/1"));
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Unknown resource name \"InvalidResource\" (this name is not known in FHIR version \"DSTU2\")", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadUpdatedHeaderDoesntOverwriteResourceValue() throws Exception {
|
||||
|
||||
@ -1699,112 +1799,6 @@ public class GenericClientDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPost() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/_search?_elements=identifier%2Cname", capt.getValue().getURI().toString());
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
assertThat(capt.getValue().getFirstHeader("user-agent").getValue(), not(emptyString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPostUseJson() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.encodedJson()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient/_search?"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_elements=identifier%2Cname"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_format=json"));
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.CT_FHIR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByString() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString());
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByNumber() throws Exception {
|
||||
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
@ -1817,11 +1811,12 @@ public class GenericClientDstu2Test {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}});
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
int idx = 0;
|
||||
|
||||
|
||||
//@formatter:off
|
||||
client.search()
|
||||
.forResource("Encounter")
|
||||
@ -1874,6 +1869,112 @@ public class GenericClientDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPost() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/_search?_elements=identifier%2Cname", capt.getValue().getURI().toString());
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
assertThat(capt.getValue().getFirstHeader("user-agent").getValue(), not(emptyString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPostUseJson() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.encodedJson()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient/_search?"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_elements=identifier%2Cname"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_format=json"));
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.CT_FHIR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByString() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString());
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByUrl() throws Exception {
|
||||
|
||||
@ -2035,6 +2136,27 @@ public class GenericClientDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMap() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
HashMap<String, List<IQueryParameterType>> params = new HashMap<String, List<IQueryParameterType>>();
|
||||
params.put("foo", Arrays.asList((IQueryParameterType)new DateParam("2001")));
|
||||
Bundle response = client.search(Patient.class, params);
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient?foo=2001", capt.getValue().getURI().toString());
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithProfileAndSecurity() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
@ -2521,9 +2643,61 @@ public class GenericClientDstu2Test {
|
||||
return (OperationOutcome) theOperationOutcome;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
}
|
||||
|
||||
public final static class RestfulClientInstance implements IRestfulClient {
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerBase() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInterceptor(IClientInterceptor theInterceptor) {
|
||||
//nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEncoding(EncodingEnum theEncoding) {
|
||||
//nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrettyPrint(Boolean thePrettyPrint) {
|
||||
//nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSummary(SummaryEnum theSummary) {
|
||||
//nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInterceptor(IClientInterceptor theInterceptor) {
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.client.BaseClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
|
||||
public class ApacheRestfulClientFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testSetContext() {
|
||||
ApacheRestfulClientFactory factory = new ApacheRestfulClientFactory();
|
||||
factory.getServerValidationModeEnum();
|
||||
factory.setFhirContext(FhirContext.forDstu2());
|
||||
try {
|
||||
factory.setFhirContext(FhirContext.forDstu2());
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals("java.lang.IllegalStateException: RestfulClientFactory instance is already associated with one FhirContext. RestfulClientFactory instances can not be shared.", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidatateBase() {
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
ApacheRestfulClientFactory factory = new ApacheRestfulClientFactory();
|
||||
factory.setFhirContext(ctx);
|
||||
factory.setConnectTimeout(1);
|
||||
try {
|
||||
factory.validateServerBase("http://127.0.0.1:22225", factory.getHttpClient("http://foo"), (BaseClient) ctx.newRestfulGenericClient("http://foo"));
|
||||
fail();
|
||||
} catch (FhirClientConnectionException e) {
|
||||
assertEquals("Failed to retrieve the server metadata statement during client initialization. URL used was http://127.0.0.1:22225metadata", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
@ -62,6 +63,51 @@ public class ServerInvalidDefinitionDstu2Test {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongResourceType() {
|
||||
RestfulServer srv = new RestfulServer(ourCtx);
|
||||
srv.setFhirContext(ourCtx);
|
||||
srv.setResourceProviders(new UpdateWithWrongResourceType());
|
||||
|
||||
try {
|
||||
srv.init();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("Method 'update' is annotated with @ResourceParam but has a type that is not an implemtation of org.hl7.fhir.instance.model.api.IBaseResource or String or byte[]"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongValidateModeType() {
|
||||
RestfulServer srv = new RestfulServer(ourCtx);
|
||||
srv.setFhirContext(ourCtx);
|
||||
srv.setResourceProviders(new ValidateWithWrongModeType());
|
||||
|
||||
try {
|
||||
srv.init();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("Parameter annotated with @Validate.Mode must be of type ca.uhn.fhir.rest.api.ValidationModeEnum"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongValidateProfileType() {
|
||||
RestfulServer srv = new RestfulServer(ourCtx);
|
||||
srv.setFhirContext(ourCtx);
|
||||
srv.setResourceProviders(new ValidateWithWrongProfileType());
|
||||
|
||||
try {
|
||||
srv.init();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("Parameter annotated with @Validate.Profile must be of type java.lang.String"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class OperationReturningOldBundleProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
@ -90,4 +136,46 @@ public class ServerInvalidDefinitionDstu2Test {
|
||||
|
||||
}
|
||||
|
||||
public static class UpdateWithWrongResourceType implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Update
|
||||
public MethodOutcome update(@ResourceParam Integer theParam2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ValidateWithWrongModeType implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Validate
|
||||
public MethodOutcome update(@ResourceParam Patient thePatient, @Validate.Mode Integer theParam2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ValidateWithWrongProfileType implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Validate
|
||||
public MethodOutcome update(@ResourceParam Patient thePatient, @Validate.Profile Integer theParam2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
@ -47,6 +48,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
@ -158,6 +160,215 @@ public class AuthorizationInterceptorDstu2Test {
|
||||
assertTrue(ourHitMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationServerLevel() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("RULE 1").operation().named("opName").onServer().andThen()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
HttpGet httpGet;
|
||||
HttpResponse status;
|
||||
String response;
|
||||
|
||||
// Server
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
extractResponseAndClose(status);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertTrue(ourHitMethod);
|
||||
|
||||
// Type
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Instance
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationInstanceLevel() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("RULE 1").operation().named("opName").onInstance(new IdDt("http://example.com/Patient/1/_history/2")).andThen()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
HttpGet httpGet;
|
||||
HttpResponse status;
|
||||
String response;
|
||||
|
||||
// Server
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Type
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Instance
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertTrue(ourHitMethod);
|
||||
|
||||
// Wrong instance
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationAnyName() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("RULE 1").operation().withAnyName().onServer().andThen()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
HttpGet httpGet;
|
||||
HttpResponse status;
|
||||
String response;
|
||||
|
||||
// Server
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertTrue(ourHitMethod);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationTypeLevel() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
//@formatter:off
|
||||
return new RuleBuilder()
|
||||
.allow("RULE 1").operation().named("opName").onType(Patient.class).andThen()
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
});
|
||||
|
||||
HttpGet httpGet;
|
||||
HttpResponse status;
|
||||
String response;
|
||||
|
||||
// Server
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Type
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertTrue(ourHitMethod);
|
||||
|
||||
// Wrong type
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/1/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Wrong name
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName2");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
// Instance
|
||||
ourHitMethod = false;
|
||||
ourReturn = Arrays.asList(createPatient(2));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
|
||||
status = ourClient.execute(httpGet);
|
||||
response = extractResponseAndClose(status);
|
||||
ourLog.info(response);
|
||||
assertThat(response, containsString("Access denied by default policy"));
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
assertFalse(ourHitMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDenyAll() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@ -762,6 +973,17 @@ public class AuthorizationInterceptorDstu2Test {
|
||||
retVal.setResource(theResource);
|
||||
return retVal;
|
||||
}
|
||||
@Operation(name="opName", idempotent=true)
|
||||
public Parameters operation() {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
@Operation(name="opName", idempotent=true)
|
||||
public Parameters operation(@IdParam IdDt theId) {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -813,11 +1035,37 @@ public class AuthorizationInterceptorDstu2Test {
|
||||
retVal.setResource(theResource);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Operation(name="opName", idempotent=true)
|
||||
public Parameters operation() {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
@Operation(name="opName", idempotent=true)
|
||||
public Parameters operation(@IdParam IdDt theId) {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
@Operation(name="opName2", idempotent=true)
|
||||
public Parameters operation2(@IdParam IdDt theId) {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PlainProvider
|
||||
{
|
||||
|
||||
@Operation(name="opName", idempotent=true)
|
||||
public Parameters operation() {
|
||||
ourHitMethod = true;
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
|
||||
@Transaction()
|
||||
public Bundle search(@TransactionParam Bundle theInput) {
|
||||
ourHitMethod = true;
|
||||
|
@ -24,7 +24,7 @@ public class FhirContextDstu3Test {
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #344
|
||||
*/
|
||||
|
@ -1,4 +1,9 @@
|
||||
package ca.uhn.fhir.validation;
|
||||
package ca.uhn.fhir.parser;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.parser.ErrorHandlerAdapter;
|
||||
import ca.uhn.fhir.parser.IParserErrorHandler;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
@ -20,16 +25,15 @@ package ca.uhn.fhir.validation;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public class Problem {
|
||||
|
||||
private String myDescription;
|
||||
|
||||
public Problem(String theDescription) {
|
||||
myDescription=theDescription;
|
||||
/**
|
||||
* Adapter implementation with NOP implementations of all {@link IParserErrorHandler} methods.
|
||||
*/
|
||||
public class ErrorHandlerAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testMethods() {
|
||||
new ErrorHandlerAdapter().unexpectedRepeatingElement(null, null);
|
||||
new ErrorHandlerAdapter().unknownAttribute(null, null);
|
||||
new ErrorHandlerAdapter().unknownElement(null, null);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,122 @@
|
||||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class NonGenericClientDstu3Test {
|
||||
private static FhirContext ourCtx;
|
||||
private HttpClient myHttpClient;
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
|
||||
System.setProperty(BaseClient.HAPI_CLIENT_KEEPRESPONSES, "true");
|
||||
|
||||
}
|
||||
|
||||
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt, int theIdx) throws IOException {
|
||||
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(theIdx)).getEntity().getContent(), "UTF-8");
|
||||
return body;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceOnly() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
OperationOutcome conf = new OperationOutcome();
|
||||
conf.getText().setDivAsString("OK!");
|
||||
|
||||
final String respString = p.encodeResourceToString(conf);
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IClient client = ourCtx.newRestfulClient(IClient.class, "http://example.com/fhir");
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("FAM");
|
||||
|
||||
int idx = 0;
|
||||
MethodOutcome outcome = client.validate(patient, null, null);
|
||||
String resp = ourCtx.newXmlParser().encodeResourceToString(outcome.getOperationOutcome());
|
||||
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><text><div xmlns=\"http://www.w3.org/1999/xhtml\">OK!</div></text></OperationOutcome>", resp);
|
||||
assertEquals("http://example.com/fhir/$validate", capt.getAllValues().get(idx).getURI().toString());
|
||||
String request = extractBodyAsString(capt,idx);
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><family value=\"FAM\"/></name></Patient></resource></parameter></Parameters>", request);
|
||||
|
||||
idx = 1;
|
||||
outcome = client.validate(patient, ValidationModeEnum.CREATE, "http://foo");
|
||||
resp = ourCtx.newXmlParser().encodeResourceToString(outcome.getOperationOutcome());
|
||||
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><text><div xmlns=\"http://www.w3.org/1999/xhtml\">OK!</div></text></OperationOutcome>", resp);
|
||||
assertEquals("http://example.com/fhir/$validate", capt.getAllValues().get(idx).getURI().toString());
|
||||
request = extractBodyAsString(capt,idx);
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><family value=\"FAM\"/></name></Patient></resource></parameter><parameter><name value=\"mode\"/><valueString value=\"create\"/></parameter><parameter><name value=\"profile\"/><valueString value=\"http://foo\"/></parameter></Parameters>", request);
|
||||
}
|
||||
|
||||
|
||||
private interface IClient extends IRestfulClient {
|
||||
|
||||
@Validate
|
||||
MethodOutcome validate(@ResourceParam IBaseResource theResource, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile);
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourCtx = FhirContext.forDstu3();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
||||
public class MethodUtilTest {
|
||||
|
||||
@Test
|
||||
public void testConvertIdToType() {
|
||||
IdDt id = new IdDt("Patient/123");
|
||||
IdType id2 = MethodUtil.convertIdToType(id, IdType.class);
|
||||
assertEquals("Patient/123", id2.getValue());
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -8,6 +9,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -25,6 +27,7 @@ import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@ -50,7 +53,7 @@ public class InterceptorDstu3Test {
|
||||
private static final FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static RestfulServer servlet;
|
||||
private static RestfulServer ourServlet;
|
||||
private IServerInterceptor myInterceptor1;
|
||||
private IServerInterceptor myInterceptor2;
|
||||
|
||||
@ -58,7 +61,7 @@ public class InterceptorDstu3Test {
|
||||
public void before() {
|
||||
myInterceptor1 = mock(IServerInterceptor.class);
|
||||
myInterceptor2 = mock(IServerInterceptor.class);
|
||||
servlet.setInterceptors(myInterceptor1, myInterceptor2);
|
||||
ourServlet.setInterceptors(myInterceptor1, myInterceptor2);
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +124,13 @@ public class InterceptorDstu3Test {
|
||||
ourServer.stop();
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
for (IServerInterceptor next : new ArrayList<IServerInterceptor>(ourServlet.getInterceptors())) {
|
||||
ourServlet.unregisterInterceptor(next);
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
@ -130,9 +140,9 @@ public class InterceptorDstu3Test {
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
servlet = new RestfulServer(ourCtx);
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
ourServlet = new RestfulServer(ourCtx);
|
||||
ourServlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
@ -1,8 +1,6 @@
|
||||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -26,13 +24,10 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Sort;
|
||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
|
@ -21,14 +21,11 @@ import org.hl7.fhir.dstu3.model.HumanName;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
@ -55,6 +52,55 @@ public class SearchWithServerAddressStrategyDstu3Test {
|
||||
assertThat(responseContent, containsString("<fullUrl value=\"http://localhost:" + ourPort + "/Patient/1\"/>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApacheProxyAddressStrategy() throws Exception {
|
||||
|
||||
ourServlet.setServerAddressStrategy(ApacheProxyAddressStrategy.forHttp());
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<family value=\"FAMILY\""));
|
||||
assertThat(responseContent, containsString("<fullUrl value=\"http://localhost:" + ourPort + "/Patient/1\"/>"));
|
||||
|
||||
ourServlet.setServerAddressStrategy(new ApacheProxyAddressStrategy(false));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||
httpGet.addHeader("x-forwarded-host", "foo.com");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<family value=\"FAMILY\""));
|
||||
assertThat(responseContent, containsString("<fullUrl value=\"http://foo.com/Patient/1\"/>"));
|
||||
|
||||
ourServlet.setServerAddressStrategy(ApacheProxyAddressStrategy.forHttps());
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||
httpGet.addHeader("x-forwarded-host", "foo.com");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<family value=\"FAMILY\""));
|
||||
assertThat(responseContent, containsString("<fullUrl value=\"https://foo.com/Patient/1\"/>"));
|
||||
|
||||
ourServlet.setServerAddressStrategy(new ApacheProxyAddressStrategy(false));
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||
httpGet.addHeader("x-forwarded-host", "foo.com");
|
||||
httpGet.addHeader("x-forwarded-proto", "https");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("<family value=\"FAMILY\""));
|
||||
assertThat(responseContent, containsString("<fullUrl value=\"https://foo.com/Patient/1\"/>"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHardcodedAddressStrategy() throws Exception {
|
||||
ourServlet.setServerAddressStrategy(new HardcodedServerAddressStrategy("http://example.com/fhir/base"));
|
||||
|
@ -0,0 +1,110 @@
|
||||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu3.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||
import ca.uhn.fhir.util.PortUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class UnclassifiedServerExceptionDstu3Test {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UnclassifiedServerExceptionDstu3Test.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
public static UnclassifiedServerFailureException ourException;
|
||||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
|
||||
OperationOutcome operationOutcome = new OperationOutcome();
|
||||
operationOutcome.addIssue().setCode(IssueType.BUSINESSRULE);
|
||||
ourException = new UnclassifiedServerFailureException(477, "SOME MESSAGE", operationOutcome);
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||
try {
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info(status.getStatusLine().toString());
|
||||
ourLog.info(responseContent);
|
||||
assertEquals(477, status.getStatusLine().getStatusCode());
|
||||
//assertEquals("SOME MESSAGE", status.getStatusLine().getReasonPhrase());
|
||||
assertThat(responseContent, stringContainsInOrder("business-rule"));
|
||||
} finally {
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() throws Exception {
|
||||
ourServer.stop();
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||
servlet.setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Search()
|
||||
public List<Patient> search() {
|
||||
throw ourException;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -30,8 +30,6 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
@ -1,23 +1,20 @@
|
||||
package ca.uhn.fhir.validation;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class SchemaValidationTestDstu3 {
|
||||
public class SchemaValidationDstu3Test {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaValidationTestDstu3.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaValidationDstu3Test.class);
|
||||
|
||||
/**
|
||||
* See #339
|
@ -41,6 +41,16 @@
|
||||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
<action type="remove">
|
||||
Remove some clases that were deprecated over a year ago and have
|
||||
suitable replacements:
|
||||
<![CDATA[
|
||||
<ul>
|
||||
<li>QualifiedDateParam has been removed, but DateParam may be used instead</li>
|
||||
<li>PathSpecification has been removedm but Include may be used instead</li>
|
||||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
<action type="fix" issue="345">
|
||||
ResponseValidatingInterceptor threw an InternalErrorException (HTTP 500) for operations
|
||||
that do not return any content (e.g. delete). Thanks to Mohammad Jafari for reporting!
|
||||
@ -359,6 +369,18 @@
|
||||
Server now supports the _at parameter (including multiple repetitions)
|
||||
for history operation
|
||||
</action>
|
||||
<!--
|
||||
This one actually doesn't seem possible without using a deprecated servlet API
|
||||
<action type="fix">
|
||||
When throwing UnclassifiedServerException in server methods, the HTTP response
|
||||
status line contained the response code specified in the exception, but not the
|
||||
response message
|
||||
</action>
|
||||
-->
|
||||
<action type="add">
|
||||
AuthorizationInterceptor can now allow or deny requests to extended
|
||||
operations (e.g. $everything)
|
||||
</action>
|
||||
<action type="fix">
|
||||
DecimalType used BigDecimal constructor instead of valueOf method to
|
||||
create a BigDecimal from a double, resulting in weird floating point
|
||||
|
Loading…
x
Reference in New Issue
Block a user