Add server interceptor layer as well as starting work on property file for versions
This commit is contained in:
parent
8d462f3cda
commit
d01f43e4b3
|
@ -1,4 +1,10 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
|
||||
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
|
||||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
|
@ -7,7 +13,88 @@ org.eclipse.jdt.core.compiler.compliance=1.6
|
|||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deadCode=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
|
||||
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
|
|
@ -100,6 +100,9 @@
|
|||
<action type="fix">
|
||||
Server setUseBrowserFriendlyContentType setting also respected for errors (e.g. OperationOutcome with 4xx/5xx status)
|
||||
</action>
|
||||
<action type="fix">
|
||||
Fix performance issue in date/time datatypes where pattern matchers were not static
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.5" date="2014-Jul-30">
|
||||
<action type="add">
|
||||
|
|
|
@ -45,14 +45,20 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
|
||||
public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||
|
||||
private static final Pattern ourYearDashMonthDashDayPattern = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
|
||||
private static final Pattern ourYearDashMonthPattern = Pattern.compile("[0-9]{4}-[0-9]{2}");
|
||||
private static final FastDateFormat ourYearFormat = FastDateFormat.getInstance("yyyy");
|
||||
private static final FastDateFormat ourYearMonthDayFormat = FastDateFormat.getInstance("yyyy-MM-dd");
|
||||
private static final FastDateFormat ourYearMonthDayNoDashesFormat = FastDateFormat.getInstance("yyyyMMdd");
|
||||
private static final Pattern ourYearMonthDayPattern = Pattern.compile("[0-9]{4}[0-9]{2}[0-9]{2}");
|
||||
private static final FastDateFormat ourYearMonthDayTimeFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
|
||||
private static final FastDateFormat ourYearMonthDayTimeMilliFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||
private static final FastDateFormat ourYearMonthDayTimeMilliZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
|
||||
private static final FastDateFormat ourYearMonthDayTimeZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
|
||||
private static final FastDateFormat ourYearMonthFormat = FastDateFormat.getInstance("yyyy-MM");
|
||||
private static final FastDateFormat ourYearMonthNoDashesFormat = FastDateFormat.getInstance("yyyyMM");
|
||||
private static final Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
|
||||
private static final Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
|
||||
|
||||
private TemporalPrecisionEnum myPrecision = TemporalPrecisionEnum.SECOND;
|
||||
private TimeZone myTimeZone;
|
||||
|
@ -60,9 +66,8 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
private Date myValue;
|
||||
|
||||
/**
|
||||
* Gets the precision for this datatype using field values from
|
||||
* {@link Calendar}, such as {@link Calendar#MONTH}. Default is
|
||||
* {@link Calendar#DAY_OF_MONTH}
|
||||
* Gets the precision for this datatype using field values from {@link Calendar}, such as {@link Calendar#MONTH}.
|
||||
* Default is {@link Calendar#DAY_OF_MONTH}
|
||||
*
|
||||
* @see #setPrecision(int)
|
||||
*/
|
||||
|
@ -127,7 +132,8 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
/**
|
||||
* Returns <code>true</code> if this object represents a date that is today's date
|
||||
*
|
||||
* @throws NullPointerException if {@link #getValue()} returns <code>null</code>
|
||||
* @throws NullPointerException
|
||||
* if {@link #getValue()} returns <code>null</code>
|
||||
*/
|
||||
public boolean isToday() {
|
||||
Validate.notNull(myValue, getClass().getSimpleName() + " contains null value");
|
||||
|
@ -135,8 +141,7 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the precision for this datatype using field values from
|
||||
* {@link Calendar}. Valid values are:
|
||||
* Sets the precision for this datatype using field values from {@link Calendar}. Valid values are:
|
||||
* <ul>
|
||||
* <li>{@link Calendar#SECOND}
|
||||
* <li>{@link Calendar#DAY_OF_MONTH}
|
||||
|
@ -166,12 +171,6 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
private Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
|
||||
private Pattern ourYearDashMonthPattern = Pattern.compile("[0-9]{4}-[0-9]{2}");
|
||||
private Pattern ourYearDashMonthDashDayPattern = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
|
||||
private Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
|
||||
private Pattern ourYearMonthDayPattern = Pattern.compile("[0-9]{4}[0-9]{2}[0-9]{2}");
|
||||
|
||||
@Override
|
||||
public void setValueAsString(String theValue) throws DataFormatException {
|
||||
try {
|
||||
|
@ -186,6 +185,15 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
} else {
|
||||
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support YEAR precision): " + theValue);
|
||||
}
|
||||
} else if (theValue.length() == 6 && ourYearMonthPattern.matcher(theValue).matches()) {
|
||||
// Eg. 198401 (allow this just to be lenient)
|
||||
if (isPrecisionAllowed(MONTH)) {
|
||||
setValue((ourYearMonthNoDashesFormat).parse(theValue));
|
||||
setPrecision(MONTH);
|
||||
clearTimeZone();
|
||||
} else {
|
||||
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support DAY precision): " + theValue);
|
||||
}
|
||||
} else if (theValue.length() == 7 && ourYearDashMonthPattern.matcher(theValue).matches()) {
|
||||
// E.g. 1984-01 (this is valid according to the spec)
|
||||
if (isPrecisionAllowed(MONTH)) {
|
||||
|
@ -196,7 +204,7 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support MONTH precision): " + theValue);
|
||||
}
|
||||
} else if (theValue.length() == 8 && ourYearMonthDayPattern.matcher(theValue).matches()) {
|
||||
//Eg. 19840101 (allow this just to be lenient)
|
||||
// Eg. 19840101 (allow this just to be lenient)
|
||||
if (isPrecisionAllowed(DAY)) {
|
||||
setValue((ourYearMonthDayNoDashesFormat).parse(theValue));
|
||||
setPrecision(DAY);
|
||||
|
@ -255,9 +263,8 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
}
|
||||
|
||||
/**
|
||||
* To be implemented by subclasses to indicate whether the given precision
|
||||
* is allowed by this type
|
||||
* To be implemented by subclasses to indicate whether the given precision is allowed by this type
|
||||
*/
|
||||
abstract boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.apache.http.client.methods.HttpRequestBase;
|
|||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
|
||||
/**
|
||||
* Client interceptor which simply captures request and response objects and stored them so that they can be inspected after a client
|
||||
* Client interceptor which simply captures request and response objects and stores them so that they can be inspected after a client
|
||||
* call has returned
|
||||
*/
|
||||
public class CapturingInterceptor implements IClientInterceptor {
|
||||
|
|
|
@ -48,6 +48,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {
|
||||
|
||||
|
@ -156,7 +157,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
Object[] params = createParametersForServerRequest(theRequest, null);
|
||||
|
||||
params[myIdParamIndex] = theRequest.getId();
|
||||
|
@ -175,15 +176,23 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
}
|
||||
invokeServerMethod(params);
|
||||
|
||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
|
||||
|
||||
theResponse.setContentType(responseEncoding.getResourceContentType());
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
theResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
response.setContentType(responseEncoding.getResourceContentType());
|
||||
response.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
response.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theResponse);
|
||||
theServer.addHeadersToResponse(response);
|
||||
|
||||
PrintWriter writer = theResponse.getWriter();
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -33,8 +33,6 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
|
@ -136,7 +134,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
|
||||
public abstract BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException;
|
||||
|
||||
public abstract void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException;
|
||||
public abstract void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException;
|
||||
|
||||
/** For unit tests only */
|
||||
public void setParameters(List<IParameter> theParameters) {
|
||||
|
|
|
@ -38,7 +38,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
|||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||
|
@ -106,7 +107,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
IResource resource;
|
||||
if (requestContainsResource()) {
|
||||
resource = parseIncomingServerResource(theRequest);
|
||||
|
@ -125,18 +126,19 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
Object[] params = createParametersForServerRequest(theRequest, resource);
|
||||
addParametersForServerRequest(theRequest, params);
|
||||
|
||||
HttpServletResponse servletResponse = theRequest.getServletResponse();
|
||||
MethodOutcome response;
|
||||
try {
|
||||
response = (MethodOutcome) invokeServerMethod(params);
|
||||
} catch (InternalErrorException e) {
|
||||
ourLog.error("Internal error during method invocation", e);
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
|
||||
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
|
||||
streamOperationOutcome(e, theServer, encoding, servletResponse, theRequest);
|
||||
return;
|
||||
} catch (BaseServerResponseException e) {
|
||||
ourLog.info("Exception during method invocation: " + e.getMessage());
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
|
||||
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
|
||||
streamOperationOutcome(e, theServer, encoding, servletResponse, theRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -145,7 +147,15 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
throw new InternalErrorException("Server method returned invalid resource ID: " + response.getId().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OperationOutcome outcome = response != null ? response.getOperationOutcome():null;
|
||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, outcome, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (getResourceOperationType()) {
|
||||
case CREATE:
|
||||
if (response == null) {
|
||||
|
@ -153,20 +163,20 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
+ " returned null, which is not allowed for create operation");
|
||||
}
|
||||
if (response.getCreated() == null || response.getCreated() == Boolean.TRUE) {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
} else {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
}
|
||||
addLocationHeader(theRequest, theResponse, response);
|
||||
addLocationHeader(theRequest, servletResponse, response);
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
if (response.getCreated() == null || response.getCreated() == Boolean.FALSE) {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
} else {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
|
||||
}
|
||||
addLocationHeader(theRequest, theResponse, response);
|
||||
addLocationHeader(theRequest, servletResponse, response);
|
||||
break;
|
||||
|
||||
case VALIDATE:
|
||||
|
@ -176,27 +186,23 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
if (isReturnVoid() == false) {
|
||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
|
||||
}
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
|
||||
} else {
|
||||
if (response.getOperationOutcome() == null) {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
|
||||
} else {
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
servletResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
}
|
||||
if (getResourceOperationType() == RestfulOperationTypeEnum.UPDATE) {
|
||||
addLocationHeader(theRequest, theResponse, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
theServer.addHeadersToResponse(theResponse);
|
||||
theServer.addHeadersToResponse(servletResponse);
|
||||
|
||||
if (response != null && response.getOperationOutcome() != null) {
|
||||
if (outcome != null) {
|
||||
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
|
||||
theResponse.setContentType(encoding.getResourceContentType());
|
||||
Writer writer = theResponse.getWriter();
|
||||
servletResponse.setContentType(encoding.getResourceContentType());
|
||||
Writer writer = servletResponse.getWriter();
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
parser.setPrettyPrint(RestfulServer.prettyPrintResponse(theRequest));
|
||||
try {
|
||||
|
@ -205,8 +211,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
|||
writer.close();
|
||||
}
|
||||
} else {
|
||||
theResponse.setContentType(Constants.CT_TEXT);
|
||||
Writer writer = theResponse.getWriter();
|
||||
servletResponse.setContentType(Constants.CT_TEXT);
|
||||
Writer writer = servletResponse.getWriter();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
||||
|
@ -78,8 +79,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
Class<?> collectionType = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
|
||||
if (collectionType != null) {
|
||||
if (!Object.class.equals(collectionType) && !IResource.class.isAssignableFrom(collectionType)) {
|
||||
throw new ConfigurationException("Method " + theMethod.getDeclaringClass().getSimpleName() + "#" + theMethod.getName() + " returns an invalid collection generic type: "
|
||||
+ collectionType);
|
||||
throw new ConfigurationException("Method " + theMethod.getDeclaringClass().getSimpleName() + "#" + theMethod.getName() + " returns an invalid collection generic type: " + collectionType);
|
||||
}
|
||||
}
|
||||
myResourceListCollectionType = collectionType;
|
||||
|
@ -91,8 +91,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
} else if (IBundleProvider.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE_PROVIDER;
|
||||
} else {
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: "
|
||||
+ theMethod.getDeclaringClass().getCanonicalName());
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
||||
if (theReturnResourceType != null) {
|
||||
|
@ -192,7 +191,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
public abstract IBundleProvider invokeServer(RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
|
||||
// Pretty print
|
||||
boolean prettyPrint = RestfulServer.prettyPrintResponse(theRequest);
|
||||
|
@ -225,11 +224,21 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
|
||||
boolean respondGzip = theRequest.isRespondGzip();
|
||||
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
IBundleProvider result = invokeServer(theRequest, params);
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE:
|
||||
RestfulServer.streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser,
|
||||
narrativeMode, 0, count, null, respondGzip);
|
||||
|
||||
Bundle bundle = RestfulServer.createBundleFromBundleProvider(theServer, response, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, 0, count, null);
|
||||
|
||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RestfulServer.streamResponseAsBundle(theServer, response, bundle, responseEncoding, theRequest.getFhirServerBase(), prettyPrint, narrativeMode, respondGzip);
|
||||
break;
|
||||
case RESOURCE:
|
||||
if (result.size() == 0) {
|
||||
|
@ -237,8 +246,17 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
} else if (result.size() > 1) {
|
||||
throw new InternalErrorException("Method returned multiple resources");
|
||||
}
|
||||
RestfulServer.streamResponseAsResource(theServer, theResponse, result.getResources(0, 1).get(0), responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip,
|
||||
theRequest.getFhirServerBase());
|
||||
|
||||
IResource resource = result.getResources(0, 1).get(0);
|
||||
|
||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RestfulServer.streamResponseAsResource(theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip, theRequest.getFhirServerBase());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -246,6 +264,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
/**
|
||||
* Subclasses may override
|
||||
*
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @throws IOException
|
||||
* Subclasses may throw this in the event of an IO exception
|
||||
*/
|
||||
|
|
|
@ -47,6 +47,7 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
|||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
||||
|
||||
|
@ -143,7 +144,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException {
|
||||
Object[] params = createParametersForServerRequest(theRequest, null);
|
||||
|
||||
if (myIdParamIndex != null) {
|
||||
|
@ -155,17 +156,25 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
|
||||
TagList resp = (TagList) invokeServerMethod(params);
|
||||
|
||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, resp, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
|
||||
|
||||
theResponse.setContentType(responseEncoding.getResourceContentType());
|
||||
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
theResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
response.setContentType(responseEncoding.getResourceContentType());
|
||||
response.setStatus(Constants.STATUS_HTTP_200_OK);
|
||||
response.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theResponse);
|
||||
theServer.addHeadersToResponse(response);
|
||||
|
||||
IParser parser = responseEncoding.newParser(getContext());
|
||||
parser.setPrettyPrint(RestfulServer.prettyPrintResponse(theRequest));
|
||||
PrintWriter writer = theResponse.getWriter();
|
||||
PrintWriter writer = response.getWriter();
|
||||
try {
|
||||
parser.encodeTagListToWriter(resp, writer);
|
||||
} finally {
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.net.URLEncoder;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -85,12 +86,12 @@ import ca.uhn.fhir.util.VersionUtil;
|
|||
public class RestfulServer extends HttpServlet {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AddProfileTagEnum myAddProfileTag;
|
||||
private FhirContext myFhirContext;
|
||||
private String myImplementationDescription;
|
||||
private List<IServerInterceptor> myInterceptors = new ArrayList<IServerInterceptor>();
|
||||
private ResourceBinding myNullResourceBinding = new ResourceBinding();
|
||||
private IPagingProvider myPagingProvider;
|
||||
private Collection<Object> myPlainProviders;
|
||||
|
@ -150,6 +151,13 @@ public class RestfulServer extends HttpServlet {
|
|||
return myImplementationDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ist of all registered server interceptors
|
||||
*/
|
||||
public List<IServerInterceptor> getInterceptors() {
|
||||
return Collections.unmodifiableList(myInterceptors);
|
||||
}
|
||||
|
||||
public IPagingProvider getPagingProvider() {
|
||||
return myPagingProvider;
|
||||
}
|
||||
|
@ -305,6 +313,19 @@ public class RestfulServer extends HttpServlet {
|
|||
myImplementationDescription = theImplementationDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets (or clears) the list of interceptors
|
||||
*
|
||||
* @param theList
|
||||
* The list of interceptors (may be null)
|
||||
*/
|
||||
public void setInterceptors(List<IServerInterceptor> theList) {
|
||||
myInterceptors.clear();
|
||||
if (theList != null) {
|
||||
myInterceptors.addAll(theList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the paging provider to use, or <code>null</code> to use no paging (which is the default)
|
||||
*/
|
||||
|
@ -419,6 +440,23 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Sets the {@link INarrativeGenerator Narrative Generator} to use when
|
||||
// serializing responses from this server, or <code>null</code> (which is
|
||||
// the default) to disable narrative generation.
|
||||
// * Note that this method can only be called before the server is
|
||||
// initialized.
|
||||
// *
|
||||
// * @throws IllegalStateException
|
||||
// * Note that this method can only be called prior to {@link #init()
|
||||
// initialization} and will throw an {@link IllegalStateException} if called
|
||||
// after that.
|
||||
// */
|
||||
// public void setNarrativeGenerator(INarrativeGenerator
|
||||
// theNarrativeGenerator) {
|
||||
// myNarrativeGenerator = theNarrativeGenerator;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Count length of URL string, but treating unescaped sequences (e.g. ' ') as their unescaped equivalent (%20)
|
||||
*/
|
||||
|
@ -452,23 +490,6 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Sets the {@link INarrativeGenerator Narrative Generator} to use when
|
||||
// serializing responses from this server, or <code>null</code> (which is
|
||||
// the default) to disable narrative generation.
|
||||
// * Note that this method can only be called before the server is
|
||||
// initialized.
|
||||
// *
|
||||
// * @throws IllegalStateException
|
||||
// * Note that this method can only be called prior to {@link #init()
|
||||
// initialization} and will throw an {@link IllegalStateException} if called
|
||||
// after that.
|
||||
// */
|
||||
// public void setNarrativeGenerator(INarrativeGenerator
|
||||
// theNarrativeGenerator) {
|
||||
// myNarrativeGenerator = theNarrativeGenerator;
|
||||
// }
|
||||
|
||||
private int findResourceMethods(Object theProvider, Class<?> clazz) throws ConfigurationException {
|
||||
int count = 0;
|
||||
|
||||
|
@ -574,7 +595,17 @@ public class RestfulServer extends HttpServlet {
|
|||
boolean requestIsBrowser = requestIsBrowser(theRequest.getServletRequest());
|
||||
NarrativeModeEnum narrativeMode = determineNarrativeMode(theRequest);
|
||||
boolean respondGzip = theRequest.isRespondGzip();
|
||||
streamResponseAsBundle(this, theResponse, resultList, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, start, count, thePagingAction, respondGzip);
|
||||
|
||||
Bundle bundle = createBundleFromBundleProvider(this, theResponse, resultList, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, start, count, thePagingAction);
|
||||
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
streamResponseAsBundle(this, theResponse, bundle, responseEncoding, theRequest.getFhirServerBase(), prettyPrint, narrativeMode, respondGzip);
|
||||
|
||||
}
|
||||
|
||||
|
@ -607,23 +638,19 @@ public class RestfulServer extends HttpServlet {
|
|||
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
handleRequest(SearchMethodBinding.RequestType.PUT, request, response);
|
||||
}
|
||||
|
||||
|
||||
private List<IServerInterceptor> myInterceptors = new ArrayList<IServerInterceptor>();
|
||||
|
||||
|
||||
protected void handleRequest(SearchMethodBinding.RequestType theRequestType, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
||||
for(IServerInterceptor next : myInterceptors) {
|
||||
for (IServerInterceptor next : myInterceptors) {
|
||||
boolean continueProcessing = next.incomingRequest(theRequest, theResponse);
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String fhirServerBase = null;
|
||||
boolean requestIsBrowser = requestIsBrowser(theRequest);
|
||||
try {
|
||||
|
||||
|
||||
if (null != mySecurityManager) {
|
||||
mySecurityManager.authenticate(theRequest);
|
||||
}
|
||||
|
@ -786,15 +813,15 @@ public class RestfulServer extends HttpServlet {
|
|||
RequestDetails requestDetails = r;
|
||||
requestDetails.setResourceOperationType(resourceMethod.getResourceOperationType());
|
||||
requestDetails.setSystemOperationType(resourceMethod.getSystemOperationType());
|
||||
|
||||
|
||||
for (IServerInterceptor next : myInterceptors) {
|
||||
boolean continueProcessing = next.incomingRequest(requestDetails, theRequest, theResponse);
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
resourceMethod.invokeServer(this, r, theResponse);
|
||||
|
||||
resourceMethod.invokeServer(this, r);
|
||||
|
||||
} catch (AuthenticationException e) {
|
||||
if (requestIsBrowser) {
|
||||
|
@ -855,6 +882,89 @@ public class RestfulServer extends HttpServlet {
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
public static Bundle createBundleFromBundleProvider(RestfulServer theServer, HttpServletResponse theHttpResponse, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser,
|
||||
NarrativeModeEnum theNarrativeMode, int theOffset, Integer theLimit, String theSearchId) {
|
||||
theHttpResponse.setStatus(200);
|
||||
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else if (theNarrativeMode == NarrativeModeEnum.ONLY) {
|
||||
theHttpResponse.setContentType(Constants.CT_HTML);
|
||||
} else {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBundleContentType());
|
||||
}
|
||||
|
||||
theHttpResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theHttpResponse);
|
||||
|
||||
int numToReturn;
|
||||
String searchId = null;
|
||||
List<IResource> resourceList;
|
||||
if (theServer.getPagingProvider() == null) {
|
||||
numToReturn = theResult.size();
|
||||
resourceList = theResult.getResources(0, numToReturn);
|
||||
} else {
|
||||
IPagingProvider pagingProvider = theServer.getPagingProvider();
|
||||
if (theLimit == null) {
|
||||
numToReturn = pagingProvider.getDefaultPageSize();
|
||||
} else {
|
||||
numToReturn = Math.min(pagingProvider.getMaximumPageSize(), theLimit);
|
||||
}
|
||||
|
||||
numToReturn = Math.min(numToReturn, theResult.size() - theOffset);
|
||||
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
|
||||
|
||||
if (theSearchId != null) {
|
||||
searchId = theSearchId;
|
||||
} else {
|
||||
if (theResult.size() > numToReturn) {
|
||||
searchId = pagingProvider.storeResultList(theResult);
|
||||
Validate.notNull(searchId, "Paging provider returned null searchId");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (IResource next : resourceList) {
|
||||
if (next.getId() == null || next.getId().isEmpty()) {
|
||||
if (!(next instanceof OperationOutcome)) {
|
||||
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
||||
for (int i = 0; i < resourceList.size(); i++) {
|
||||
IResource nextRes = resourceList.get(i);
|
||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
||||
addProfileToBundleEntry(theServer.getFhirContext(), nextRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bundle bundle = createBundleFromResourceList(theServer.getFhirContext(), theServer.getServerName(), resourceList, theServerBase, theCompleteUrl, theResult.size());
|
||||
|
||||
bundle.setPublished(theResult.getPublished());
|
||||
|
||||
if (theServer.getPagingProvider() != null) {
|
||||
int limit;
|
||||
limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize();
|
||||
limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize());
|
||||
|
||||
if (searchId != null) {
|
||||
if (theOffset + numToReturn < theResult.size()) {
|
||||
bundle.getLinkNext().setValue(createPagingLink(theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint));
|
||||
}
|
||||
if (theOffset > 0) {
|
||||
int start = Math.max(0, theOffset - limit);
|
||||
bundle.getLinkPrevious().setValue(createPagingLink(theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint));
|
||||
}
|
||||
}
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public static Bundle createBundleFromResourceList(FhirContext theContext, String theAuthor, List<IResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.getAuthorName().setValue(theAuthor);
|
||||
|
@ -1079,93 +1189,14 @@ public class RestfulServer extends HttpServlet {
|
|||
return prettyPrint;
|
||||
}
|
||||
|
||||
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser,
|
||||
NarrativeModeEnum theNarrativeMode, int theOffset, Integer theLimit, String theSearchId, boolean theRespondGzip) throws IOException {
|
||||
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, EncodingEnum theResponseEncoding, String theServerBase, boolean thePrettyPrint, NarrativeModeEnum theNarrativeMode, boolean theRespondGzip)
|
||||
throws IOException {
|
||||
assert !theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
|
||||
} else if (theNarrativeMode == NarrativeModeEnum.ONLY) {
|
||||
theHttpResponse.setContentType(Constants.CT_HTML);
|
||||
} else {
|
||||
theHttpResponse.setContentType(theResponseEncoding.getBundleContentType());
|
||||
}
|
||||
|
||||
theHttpResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
|
||||
|
||||
theServer.addHeadersToResponse(theHttpResponse);
|
||||
|
||||
int numToReturn;
|
||||
String searchId = null;
|
||||
List<IResource> resourceList;
|
||||
if (theServer.getPagingProvider() == null) {
|
||||
numToReturn = theResult.size();
|
||||
resourceList = theResult.getResources(0, numToReturn);
|
||||
} else {
|
||||
IPagingProvider pagingProvider = theServer.getPagingProvider();
|
||||
if (theLimit == null) {
|
||||
numToReturn = pagingProvider.getDefaultPageSize();
|
||||
} else {
|
||||
numToReturn = Math.min(pagingProvider.getMaximumPageSize(), theLimit);
|
||||
}
|
||||
|
||||
numToReturn = Math.min(numToReturn, theResult.size() - theOffset);
|
||||
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
|
||||
|
||||
if (theSearchId != null) {
|
||||
searchId = theSearchId;
|
||||
} else {
|
||||
if (theResult.size() > numToReturn) {
|
||||
searchId = pagingProvider.storeResultList(theResult);
|
||||
Validate.notNull(searchId, "Paging provider returned null searchId");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (IResource next : resourceList) {
|
||||
if (next.getId() == null || next.getId().isEmpty()) {
|
||||
if (!(next instanceof OperationOutcome)) {
|
||||
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
|
||||
for (int i = 0; i < resourceList.size(); i++) {
|
||||
IResource nextRes = resourceList.get(i);
|
||||
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
|
||||
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardProfile()) {
|
||||
addProfileToBundleEntry(theServer.getFhirContext(), nextRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bundle bundle = createBundleFromResourceList(theServer.getFhirContext(), theServer.getServerName(), resourceList, theServerBase, theCompleteUrl, theResult.size());
|
||||
|
||||
bundle.setPublished(theResult.getPublished());
|
||||
|
||||
if (theServer.getPagingProvider() != null) {
|
||||
int limit;
|
||||
limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize();
|
||||
limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize());
|
||||
|
||||
if (searchId != null) {
|
||||
if (theOffset + numToReturn < theResult.size()) {
|
||||
bundle.getLinkNext().setValue(createPagingLink(theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint));
|
||||
}
|
||||
if (theOffset > 0) {
|
||||
int start = Math.max(0, theOffset - limit);
|
||||
bundle.getLinkPrevious().setValue(createPagingLink(theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Writer writer = getWriter(theHttpResponse, theRespondGzip);
|
||||
try {
|
||||
if (theNarrativeMode == NarrativeModeEnum.ONLY) {
|
||||
for (IResource next : resourceList) {
|
||||
for (IResource next : bundle.toListOfResources()) {
|
||||
writer.append(next.getText().getDiv().getValueAsString());
|
||||
writer.append("<hr/>");
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@ package ca.uhn.fhir.rest.server.interceptor;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
|
||||
|
@ -32,8 +36,8 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
|||
public interface IServerInterceptor {
|
||||
|
||||
/**
|
||||
* This method is called before any other processing takes place for each incoming request. It may be used to provide alternate handling for some requests, or to screen requests before they are
|
||||
* handled, etc.
|
||||
* This method is called before any other processing takes place for each incoming request. It may be used to
|
||||
* provide alternate handling for some requests, or to screen requests before they are handled, etc.
|
||||
* <p>
|
||||
* Note that any exceptions thrown by this method will not be trapped by HAPI (they will be passed up to the server)
|
||||
* </p>
|
||||
|
@ -41,10 +45,12 @@ public interface IServerInterceptor {
|
|||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
*/
|
||||
public boolean incomingRequest(HttpServletRequest theRequest, HttpServletResponse theResponse);
|
||||
|
||||
|
@ -56,13 +62,109 @@ public interface IServerInterceptor {
|
|||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
|
||||
* <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
|
||||
* response normally, you must return <code>false</code>. In this case, no further processing will occur and no further interceptors will be called.
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt
|
||||
*/
|
||||
public boolean incomingRequest(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream
|
||||
* the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt
|
||||
*/
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream
|
||||
* the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt
|
||||
*/
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream
|
||||
* the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt
|
||||
*/
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* This method is called after the server implementation method has been called, but before any attempt to stream
|
||||
* the response back to the client
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* A bean containing details about the request that is about to be processed, including
|
||||
* @param theResponseObject
|
||||
* The actual object which is being streamed to the client as a response
|
||||
* @param theRequest
|
||||
* The incoming request
|
||||
* @param theResponse
|
||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||
* interceptors will be called.
|
||||
* @throws AuthenticationException
|
||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||
* attempt
|
||||
*/
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
||||
* of all methods, always returning <code>true</code>
|
||||
*/
|
||||
public class InterceptorAdapter implements IServerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean incomingRequest(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingRequest(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.text.StrLookup;
|
||||
import org.apache.commons.lang3.text.StrSubstitutor;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Server interceptor which logs each request using a defined format
|
||||
* <p>
|
||||
* The following substitution variables are supported:
|
||||
* </p>
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>${operationType}</td>
|
||||
* <td>A code indicating the operation type for this request, e.g. "read", "history-instance", etc.)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>${id}</td>
|
||||
* <td>The resource ID associated with this request (or "" if none)</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
*/
|
||||
public class LoggingInterceptor extends InterceptorAdapter {
|
||||
|
||||
private String myMessageFormat = "${operationType} - ${id}";
|
||||
private Logger myLogger = ourLog;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LoggingInterceptor.class);
|
||||
|
||||
@Override
|
||||
public boolean incomingRequest(final RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||
StrLookup<?> lookup = new StrLookup<String>() {
|
||||
@Override
|
||||
public String lookup(String theKey) {
|
||||
if ("operationType".equals(theKey)) {
|
||||
if (theRequestDetails.getResourceOperationType() != null) {
|
||||
return theRequestDetails.getResourceOperationType().getCode();
|
||||
}
|
||||
if (theRequestDetails.getSystemOperationType() != null) {
|
||||
return theRequestDetails.getSystemOperationType().getCode();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
if ("id".equals(theKey)) {
|
||||
if (theRequestDetails.getId() != null) {
|
||||
return theRequestDetails.getId().getValue();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return "!VAL!";
|
||||
}
|
||||
};
|
||||
StrSubstitutor subs = new StrSubstitutor(lookup, "${", "}", '\\');
|
||||
|
||||
String line = subs.replace(myMessageFormat);
|
||||
myLogger.info(line);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
|
|
@ -52,6 +52,18 @@ public class BaseDateTimeDtTest {
|
|||
assertEquals(TemporalPrecisionEnum.MONTH, dt.getPrecision());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseMonthNoDashes() throws DataFormatException {
|
||||
DateTimeDt dt = new DateTimeDt();
|
||||
dt.setValueAsString("201302");
|
||||
|
||||
assertEquals("2013-02", myDateInstantParser.format(dt.getValue()).substring(0, 7));
|
||||
assertEquals("2013-02", dt.getValueAsString());
|
||||
assertEquals(false, dt.isTimeZoneZulu());
|
||||
assertNull(dt.getTimeZone());
|
||||
assertEquals(TemporalPrecisionEnum.MONTH, dt.getPrecision());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseDay() throws DataFormatException {
|
||||
DateTimeDt dt = new DateTimeDt();
|
||||
|
|
|
@ -41,6 +41,7 @@ import ca.uhn.fhir.model.dstu.resource.Binary;
|
|||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||
import ca.uhn.fhir.model.dstu.resource.ListResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
|
@ -606,6 +607,19 @@ public class XmlParserTest {
|
|||
ourLog.info(result);
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void testParseFeedWithListResource() throws ConfigurationException, DataFormatException, IOException {
|
||||
|
||||
// Use new context here to ensure List isn't already loaded
|
||||
IParser p = new FhirContext().newXmlParser();
|
||||
|
||||
String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/feed-with-list.xml"));
|
||||
Bundle bundle = p.parseBundle(string);
|
||||
|
||||
ListResource res = (ListResource) bundle.toListOfResources().get(2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoadPatient() throws ConfigurationException, DataFormatException, IOException {
|
||||
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
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.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class InterceptorTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static RestfulServer servlet;
|
||||
private IServerInterceptor myInterceptor;
|
||||
|
||||
@Test
|
||||
public void testInterceptorFires() throws Exception {
|
||||
when(myInterceptor.incomingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||
when(myInterceptor.incomingRequest(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||
when(myInterceptor.outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
verify(myInterceptor, times(1)).incomingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
verify(myInterceptor, times(1)).incomingRequest(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
verify(myInterceptor, times(1)).outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
verifyNoMoreInteractions(myInterceptor);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoggingInterceptor() throws Exception {
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||
servlet.setInterceptors(Collections.singletonList((IServerInterceptor)interceptor));
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myInterceptor = mock(IServerInterceptor.class);
|
||||
servlet.setInterceptors(Collections.singletonList(myInterceptor));
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
servlet = new RestfulServer();
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
public Map<String, Patient> getIdToPatient() {
|
||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
||||
{
|
||||
Patient patient = createPatient1();
|
||||
idToPatient.put("1", patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.getIdentifier().add(new IdentifierDt());
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00002");
|
||||
patient.getName().add(new HumanNameDt());
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientTwo");
|
||||
patient.getGender().setText("F");
|
||||
patient.getId().setValue("2");
|
||||
idToPatient.put("2", patient);
|
||||
}
|
||||
return idToPatient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the resource by its identifier
|
||||
*
|
||||
* @param theId
|
||||
* The resource identity
|
||||
* @return The resource
|
||||
*/
|
||||
@Read()
|
||||
public Patient getResourceById(@IdParam IdDt theId) {
|
||||
String key = theId.getIdPart();
|
||||
Patient retVal = getIdToPatient().get(key);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@Search(queryName="searchWithWildcardRetVal")
|
||||
public List<? extends IResource> searchWithWildcardRetVal() {
|
||||
Patient p = new Patient();
|
||||
p.setId("1234");
|
||||
p.addName().addFamily("searchWithWildcardRetVal");
|
||||
return Collections.singletonList(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the resource by its identifier
|
||||
*
|
||||
* @param theId
|
||||
* The resource identity
|
||||
* @return The resource
|
||||
*/
|
||||
@Search()
|
||||
public List<Patient> getResourceById(@RequiredParam(name = "_id") String theId) {
|
||||
Patient patient = getIdToPatient().get(theId);
|
||||
if (patient != null) {
|
||||
return Collections.singletonList(patient);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
private Patient createPatient1() {
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier();
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00001");
|
||||
patient.addName();
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
patient.getId().setValue("1");
|
||||
return patient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
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.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class ServerSecurityTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerSecurityTest.class);
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourCtx = new FhirContext(Patient.class);
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextWithSpace() throws Exception {
|
||||
if (true) return;
|
||||
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
Server server = new Server(port);
|
||||
|
||||
RestfulServer restServer = new RestfulServer();
|
||||
restServer.setFhirContext(ourCtx);
|
||||
restServer.setResourceProviders(new DummyPatientResourceProvider());
|
||||
|
||||
// ServletHandler proxyHandler = new ServletHandler();
|
||||
ServletHolder servletHolder = new ServletHolder(restServer);
|
||||
|
||||
WebAppContext wac = new WebAppContext();
|
||||
wac.setWar("src/test/resources/securitytest_war");
|
||||
|
||||
// wac.addServlet(servletHolder, "/fhir/*");
|
||||
|
||||
|
||||
ServletContextHandler ch = new ServletContextHandler();
|
||||
ch.setContextPath("/");
|
||||
ch.addServlet(servletHolder, "/fhir/*");
|
||||
// ch.add
|
||||
// ch.addFilter(org.springframework.web.filter.DelegatingFilterProxy.class, "/*", null);
|
||||
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(wac);
|
||||
|
||||
// server.setHandler(ch);
|
||||
server.start();
|
||||
try {
|
||||
|
||||
String baseUri = "http://localhost:" + port + "/fhir";
|
||||
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
httpGet.addHeader("Authorization", "Basic eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MDY4MzU3MjMsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvdWhudmVzYjAxZC51aG4ub24uY2E6MjUxODBcL3Vobi1vcGVuaWQtY29ubmVjdC1zZXJ2ZXJcLyIsImp0aSI6IjEwZTYwYWY1LTEyZmUtNDFhYy05MWQyLTliNWY0NzBiNGM5OSIsImlhdCI6MTQwNjgzMjEyM30.LaCAOmoM0ikkaalKBfccU_YE8NBXvT5M7L9ITfR86vEp5-3_kVeSrYHI4CjVUSDafyVwQF4x5eJVSZdtQxtEk9F1L6be_JQI84crqff53EKA10z7m9Lkc5jJFs6sd9cnlayhlBgxL7BNdSf0Bjs7aS6YMEcn9IY3RNSeQj7kjhs");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
|
||||
|
||||
assertEquals(1, bundle.getEntries().size());
|
||||
|
||||
} finally {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
public Map<String, Patient> getIdToPatient() {
|
||||
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.setId("1");
|
||||
patient.addIdentifier();
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00001");
|
||||
patient.addName();
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.getGender().setText("M");
|
||||
idToPatient.put("1", patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.setId("2");
|
||||
patient.getIdentifier().add(new IdentifierDt());
|
||||
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
|
||||
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
|
||||
patient.getIdentifier().get(0).setValue("00002");
|
||||
patient.getName().add(new HumanNameDt());
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientTwo");
|
||||
patient.getGender().setText("F");
|
||||
idToPatient.put("2", patient);
|
||||
}
|
||||
return idToPatient;
|
||||
}
|
||||
|
||||
@Search()
|
||||
public Patient getPatient(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||
for (Patient next : getIdToPatient().values()) {
|
||||
for (IdentifierDt nextId : next.getIdentifier()) {
|
||||
if (nextId.matchesSystemAndValue(theIdentifier)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the resource by its identifier
|
||||
*
|
||||
* @param theId
|
||||
* The resource identity
|
||||
* @return The resource
|
||||
*/
|
||||
@Read()
|
||||
public Patient getResourceById(@IdParam IdDt theId) {
|
||||
return getIdToPatient().get(theId.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import ca.uhn.fhir.rest.server.ServerSecurityTest.DummyPatientResourceProvider;
|
||||
|
||||
public class ServerSecurityTestRestfulServlet extends RestfulServer
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
setResourceProviders(new DummyPatientResourceProvider());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.w3.org/2005/Atom ../../Blogs/fhir-all-xsd/fhir-atom.xsd"
|
||||
xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Glucosemeter data from suresense</title>
|
||||
<id>urn:uuid:500bee81-d973-4afe-b592-d39fe71e38</id>
|
||||
<updated>2014-05-28T22:12:21Z</updated>
|
||||
<author>
|
||||
<name>Aaron Jackson</name>
|
||||
</author>
|
||||
|
||||
<category scheme="http://hl7.org/fhir/tag/profile" term="http://localhost/Profile/medman" label="Medman Profile" />
|
||||
|
||||
<entry>
|
||||
<title>Patient details</title>
|
||||
<id>cid:patient@bundle</id>
|
||||
<updated>2014-05-28T22:12:21Z</updated>
|
||||
<link href="http://localhost/Patient?identifier=PRP1660" rel="search"/>
|
||||
<content type="text/xml">
|
||||
<Patient xmlns="http://hl7.org/fhir">
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">Joe Bloggs</div>
|
||||
</text>
|
||||
<identifier>
|
||||
<system value="urn:oid:2.16.840.1.113883.2.18.2"/>
|
||||
<value value="PRP1660"/>
|
||||
</identifier>
|
||||
<name>
|
||||
<text value="Joe Bloggs"/>
|
||||
</name>
|
||||
</Patient>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>Practitioner</title>
|
||||
<id>cid:practioner@bundle</id>
|
||||
<updated>2014-05-28T22:12:21Z</updated>
|
||||
<link href="http://localhost/Device?udi=abc123456" rel="search"/>
|
||||
<content type="text/xml">
|
||||
<Practitioner xmlns="http://hl7.org/fhir">
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"/>
|
||||
</text>
|
||||
</Practitioner>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
|
||||
<entry>
|
||||
<title>Medication List</title>
|
||||
<id>cid:list1</id>
|
||||
<updated>2013-05-28T22:12:21Z</updated>
|
||||
|
||||
<content type="text/xml">
|
||||
<List xmlns="http://hl7.org/fhir">
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org"/>
|
||||
<code value="= 18605-6"/>
|
||||
</coding>
|
||||
</code>
|
||||
<subject>
|
||||
<reference value="cid:patient@bundle"/>
|
||||
</subject>
|
||||
<source>
|
||||
<reference value="cid:practioner@bundle"/>
|
||||
</source>
|
||||
<mode value="snapshot"/>
|
||||
<entry>
|
||||
<item>
|
||||
<reference value="#med1"/>
|
||||
</item>
|
||||
</entry>
|
||||
<entry>
|
||||
<item>
|
||||
<reference value="#med2"/>
|
||||
</item>
|
||||
</entry>
|
||||
<entry>
|
||||
<deleted value="true"/>
|
||||
<item>
|
||||
<reference value="#med3"/>
|
||||
</item>
|
||||
</entry>
|
||||
</List>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>Medication 1</title>
|
||||
<id>cid:med1</id>
|
||||
<updated>2013-05-29T22:12:21Z</updated>
|
||||
|
||||
<content type="text/xml">
|
||||
<MedicationStatement xmlns="http://hl7.org/fhir">
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">Atenolol 50mg 1 mane</div>
|
||||
</text>
|
||||
<contained>
|
||||
<Medication id="med1">
|
||||
<code>
|
||||
<coding>
|
||||
<system value="mySys"/>
|
||||
<code value="med1"/>
|
||||
</coding>
|
||||
<text value="Atenolol 50mg"/>
|
||||
</code>
|
||||
</Medication>
|
||||
</contained>
|
||||
<patient>
|
||||
<reference value="cid:patient@bundle"/>
|
||||
</patient>
|
||||
<dosage>
|
||||
<!-- Once a day -->
|
||||
<timing>
|
||||
<repeat>
|
||||
<frequency value="1"/>
|
||||
<when value="ACM"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</timing>
|
||||
<quantity>
|
||||
<value value="1"/>
|
||||
</quantity>
|
||||
</dosage>
|
||||
|
||||
</MedicationStatement>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>Medication 2</title>
|
||||
<id>cid:med2</id>
|
||||
<updated>2013-05-29T22:12:21Z</updated>
|
||||
|
||||
<content type="text/xml">
|
||||
<MedicationStatement xmlns="http://hl7.org/fhir">
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">Voltaren 25mg 3 times a day</div>
|
||||
</text>
|
||||
<contained>
|
||||
<Medication id="med1">
|
||||
<code>
|
||||
<coding>
|
||||
<system value="mySys"/>
|
||||
<code value="volt25"/>
|
||||
</coding>
|
||||
<text value="Voltaren 50mg"/>
|
||||
</code>
|
||||
</Medication>
|
||||
</contained>
|
||||
<patient>
|
||||
<reference value="cid:patient@bundle"/>
|
||||
</patient>
|
||||
<dosage>
|
||||
<!-- Three times a day -->
|
||||
<timing>
|
||||
<repeat>
|
||||
<frequency value="3"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</timing>
|
||||
<quantity>
|
||||
<value value="2"/>
|
||||
</quantity>
|
||||
</dosage>
|
||||
|
||||
</MedicationStatement>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>Medication 3</title>
|
||||
<id>cid:med2</id>
|
||||
<updated>2013-05-29T22:12:21Z</updated>
|
||||
|
||||
<content type="text/xml">
|
||||
<MedicationStatement xmlns="http://hl7.org/fhir">
|
||||
<text>
|
||||
<status value="generated"/>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">Voltaren 25mg 3 times a day</div>
|
||||
</text>
|
||||
<contained>
|
||||
<Medication id="med1">
|
||||
<code>
|
||||
<coding>
|
||||
<system value="mySys"/>
|
||||
<code value="volt25"/>
|
||||
</coding>
|
||||
<text value="Voltaren 100mg SR"/>
|
||||
</code>
|
||||
</Medication>
|
||||
</contained>
|
||||
<patient>
|
||||
<reference value="cid:patient@bundle"/>
|
||||
</patient>
|
||||
<dosage>
|
||||
<!-- once a day -->
|
||||
<timing>
|
||||
<repeat>
|
||||
<frequency value="1"/>
|
||||
<duration value="1"/>
|
||||
<units value="d"/>
|
||||
</repeat>
|
||||
</timing>
|
||||
<quantity>
|
||||
<value value="2"/>
|
||||
</quantity>
|
||||
</dosage>
|
||||
|
||||
</MedicationStatement>
|
||||
</content>
|
||||
</entry>
|
||||
|
||||
|
||||
</feed>
|
|
@ -33,6 +33,11 @@
|
|||
<version>2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>17.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- General -->
|
||||
<dependency>
|
||||
|
|
|
@ -122,7 +122,7 @@ public class TinderClientMojo extends AbstractMojo {
|
|||
File resourceDir = new File(myDirectoryBase, "resource");
|
||||
resourceDir.mkdirs();
|
||||
pp.markResourcesForImports();
|
||||
pp.writeAll(resourceDir, myPackageBase);
|
||||
pp.writeAll(resourceDir, null,myPackageBase);
|
||||
|
||||
try {
|
||||
write();
|
||||
|
|
|
@ -59,7 +59,7 @@ public class TinderJpaRestServerMojo extends AbstractMojo {
|
|||
|
||||
gen.setFilenameSuffix("ResourceProvider");
|
||||
gen.setTemplate("/vm/jpa_resource_provider.vm");
|
||||
gen.writeAll(directoryBase, packageBase);
|
||||
gen.writeAll(directoryBase, null,packageBase);
|
||||
|
||||
// gen.setFilenameSuffix("ResourceTable");
|
||||
// gen.setTemplate("/vm/jpa_resource_table.vm");
|
||||
|
|
|
@ -28,7 +28,7 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
@Parameter(required = false)
|
||||
private List<String> baseResourceNames;
|
||||
|
||||
@Parameter(required = false, defaultValue="false")
|
||||
@Parameter(required = false, defaultValue = "false")
|
||||
private boolean buildDatatypes;
|
||||
|
||||
@Component
|
||||
|
@ -46,6 +46,9 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
|
||||
private String targetDirectory;
|
||||
|
||||
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-resources/tinder")
|
||||
private String targetResourceDirectory;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
if (StringUtils.isBlank(packageName)) {
|
||||
|
@ -58,9 +61,14 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
ourLog.info("Beginning HAPI-FHIR Tinder Code Generation...");
|
||||
|
||||
ourLog.info(" * Output Package: " + packageName);
|
||||
|
||||
File resDirectoryBase = new File(new File(targetResourceDirectory), packageName.replace('.', File.separatorChar));
|
||||
resDirectoryBase.mkdirs();
|
||||
ourLog.info(" * Output Resource Directory: " + resDirectoryBase.getAbsolutePath());
|
||||
|
||||
File directoryBase = new File(new File(targetDirectory), packageName.replace('.', File.separatorChar));
|
||||
directoryBase.mkdirs();
|
||||
ourLog.info(" * Output Directory: " + directoryBase.getAbsolutePath());
|
||||
ourLog.info(" * Output Source Directory: " + directoryBase.getAbsolutePath());
|
||||
|
||||
ValueSetGenerator vsp = new ValueSetGenerator();
|
||||
vsp.setResourceValueSetFiles(resourceValueSetFiles);
|
||||
|
@ -73,9 +81,8 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
ourLog.info("Loading Datatypes...");
|
||||
|
||||
Map<String, String> datatypeLocalImports = new HashMap<String, String>();
|
||||
DatatypeGeneratorUsingSpreadsheet dtp = null;
|
||||
DatatypeGeneratorUsingSpreadsheet dtp = new DatatypeGeneratorUsingSpreadsheet();
|
||||
if (buildDatatypes) {
|
||||
dtp = new DatatypeGeneratorUsingSpreadsheet();
|
||||
try {
|
||||
dtp.parse();
|
||||
dtp.markResourcesForImports();
|
||||
|
@ -83,13 +90,13 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
throw new MojoFailureException("Failed to load datatypes", e);
|
||||
}
|
||||
dtp.bindValueSets(vsp);
|
||||
|
||||
|
||||
datatypeLocalImports = dtp.getLocalImports();
|
||||
}
|
||||
|
||||
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
|
||||
if (baseResourceNames != null && baseResourceNames.size() > 0) {
|
||||
ourLog.info("Loading Resources...");
|
||||
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
|
||||
try {
|
||||
rp.setBaseResourceNames(baseResourceNames);
|
||||
rp.parse();
|
||||
|
@ -97,36 +104,44 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
} catch (Exception e) {
|
||||
throw new MojoFailureException("Failed to load resources", e);
|
||||
}
|
||||
|
||||
|
||||
rp.bindValueSets(vsp);
|
||||
rp.getLocalImports().putAll(datatypeLocalImports);
|
||||
datatypeLocalImports.putAll(rp.getLocalImports());
|
||||
|
||||
|
||||
ourLog.info("Writing Resources...");
|
||||
rp.writeAll(new File(directoryBase, "resource"), packageName);
|
||||
File resSubDirectoryBase = new File(directoryBase, "resource");
|
||||
rp.combineContentMaps(dtp);
|
||||
rp.writeAll(resSubDirectoryBase, resDirectoryBase, packageName);
|
||||
}
|
||||
|
||||
ProfileParser pp = new ProfileParser();
|
||||
if (resourceProfileFiles != null) {
|
||||
ourLog.info("Loading profiles...");
|
||||
ProfileParser pp = new ProfileParser();
|
||||
for (ProfileFileDefinition next : resourceProfileFiles) {
|
||||
ourLog.info("Parsing file: {}", next.profileFile);
|
||||
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl);
|
||||
}
|
||||
|
||||
|
||||
pp.bindValueSets(vsp);
|
||||
pp.markResourcesForImports();
|
||||
pp.getLocalImports().putAll(datatypeLocalImports);
|
||||
datatypeLocalImports.putAll(pp.getLocalImports());
|
||||
|
||||
pp.writeAll(new File(directoryBase, "resource"), packageName);
|
||||
|
||||
pp.combineContentMaps(rp);
|
||||
pp.combineContentMaps(dtp);
|
||||
pp.writeAll(new File(directoryBase, "resource"), null, packageName);
|
||||
}
|
||||
|
||||
|
||||
if (dtp != null) {
|
||||
ourLog.info("Writing Composite Datatypes...");
|
||||
dtp.writeAll(new File(directoryBase, "composite"), packageName);
|
||||
|
||||
dtp.combineContentMaps(pp);
|
||||
dtp.combineContentMaps(rp);
|
||||
dtp.writeAll(new File(directoryBase, "composite"), null, packageName);
|
||||
}
|
||||
|
||||
|
||||
ourLog.info("Writing ValueSet Enums...");
|
||||
vsp.writeMarkedValueSets(new File(directoryBase, "valueset"), packageName);
|
||||
|
||||
|
@ -184,44 +199,44 @@ public class TinderStructuresMojo extends AbstractMojo {
|
|||
public static void main(String[] args) throws Exception {
|
||||
|
||||
ProfileParser pp = new ProfileParser();
|
||||
pp.parseSingleProfile(new File("../hapi-tinder-test/src/test/resources/profile/patient.xml"), "http://foo");
|
||||
pp.parseSingleProfile(new File("../hapi-tinder-test/src/test/resources/profile/patient.xml"), "http://foo");
|
||||
|
||||
ValueSetGenerator vsp = new ValueSetGenerator();
|
||||
// vsp.setDirectory("src/test/resources/vs/");
|
||||
vsp.parse();
|
||||
|
||||
DatatypeGeneratorUsingSpreadsheet dtp = new DatatypeGeneratorUsingSpreadsheet();
|
||||
dtp.parse();
|
||||
dtp.bindValueSets(vsp);
|
||||
|
||||
String dtOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/composite";
|
||||
dtp.writeAll(new File(dtOutputDir), null, "ca.uhn.fhir.model.dstu");
|
||||
|
||||
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
|
||||
rp.setBaseResourceNames(Arrays.asList("patient"));
|
||||
rp.parse();
|
||||
|
||||
// rp.bindValueSets(vsp);
|
||||
|
||||
String rpOutputDir = "target/generated-sources/valuesets/ca/uhn/fhir/model/dstu/resource";
|
||||
String rpSOutputDir = "target/generated-resources/valuesets/ca/uhn/fhir/model/dstu";
|
||||
|
||||
ValueSetGenerator vsp = new ValueSetGenerator();
|
||||
// vsp.setDirectory("src/test/resources/vs/");
|
||||
vsp.parse();
|
||||
|
||||
DatatypeGeneratorUsingSpreadsheet dtp = new DatatypeGeneratorUsingSpreadsheet();
|
||||
dtp.parse();
|
||||
dtp.bindValueSets(vsp);
|
||||
|
||||
String dtOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/composite";
|
||||
dtp.writeAll(new File(dtOutputDir), "ca.uhn.fhir.model.dstu");
|
||||
|
||||
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet();
|
||||
rp.setBaseResourceNames(Arrays.asList("patient"));
|
||||
rp.parse();
|
||||
|
||||
// rp.bindValueSets(vsp);
|
||||
|
||||
String rpOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/resource";
|
||||
rp.writeAll(new File(rpOutputDir), "ca.uhn.fhir.model.dstu");
|
||||
//
|
||||
// String vsOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/valueset";
|
||||
// vsp.writeMarkedValueSets(vsOutputDir);
|
||||
rp.combineContentMaps(dtp);
|
||||
rp.writeAll(new File(rpOutputDir), new File(rpSOutputDir), "ca.uhn.fhir.model.dstu");
|
||||
//
|
||||
// String vsOutputDir = "target/generated/valuesets/ca/uhn/fhir/model/dstu/valueset";
|
||||
// vsp.writeMarkedValueSets(vsOutputDir);
|
||||
}
|
||||
|
||||
public static class ProfileFileDefinition
|
||||
{
|
||||
public static class ProfileFileDefinition {
|
||||
@Parameter(required = true)
|
||||
private String profileFile;
|
||||
|
||||
|
||||
@Parameter(required = true)
|
||||
private String profileSourceUrl;
|
||||
}
|
||||
|
||||
public static class ValueSetFileDefinition
|
||||
{
|
||||
public static class ValueSetFileDefinition {
|
||||
@Parameter(required = true)
|
||||
private String valueSetFile;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
@ -51,7 +52,20 @@ public abstract class BaseStructureParser {
|
|||
private Map<String, String> myLocallyDefinedClassNames = new HashMap<String, String>();
|
||||
private List<BaseRootType> myResources = new ArrayList<BaseRootType>();
|
||||
private boolean myImportsResolved;
|
||||
private TreeMap<String, String> myNameToResourceClass = new TreeMap<String, String>();
|
||||
private TreeMap<String, String> myNameToDatatypeClass = new TreeMap<String, String>();
|
||||
|
||||
public TreeMap<String, String> getNameToDatatypeClass() {
|
||||
return myNameToDatatypeClass;
|
||||
}
|
||||
|
||||
public void combineContentMaps(BaseStructureParser theStructureParser) {
|
||||
myNameToResourceClass.putAll(theStructureParser.myNameToResourceClass);
|
||||
myNameToDatatypeClass.putAll(theStructureParser.myNameToDatatypeClass);
|
||||
theStructureParser.myNameToResourceClass.putAll(myNameToResourceClass);
|
||||
theStructureParser.myNameToDatatypeClass.putAll(myNameToDatatypeClass);
|
||||
}
|
||||
|
||||
public void addResource(BaseRootType theResource) {
|
||||
myResources.add(theResource);
|
||||
}
|
||||
|
@ -84,8 +98,7 @@ public abstract class BaseStructureParser {
|
|||
}
|
||||
}
|
||||
|
||||
private ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter findAnnotation(Class<?> theBase, Annotation[] theAnnotations,
|
||||
Class<ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter> theClass) {
|
||||
private ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter findAnnotation(Class<?> theBase, Annotation[] theAnnotations, Class<ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter> theClass) {
|
||||
for (Annotation next : theAnnotations) {
|
||||
if (theClass.equals(next.annotationType())) {
|
||||
return (ca.uhn.fhir.model.api.annotation.SimpleSetter.Parameter) next;
|
||||
|
@ -316,13 +329,21 @@ public abstract class BaseStructureParser {
|
|||
}
|
||||
}
|
||||
|
||||
public void writeAll(File theOutputDirectory, String thePackageBase) throws MojoFailureException {
|
||||
public void writeAll(File theOutputDirectory, File theResourceOutputDirectory, String thePackageBase) throws MojoFailureException {
|
||||
if (!theOutputDirectory.exists()) {
|
||||
theOutputDirectory.mkdirs();
|
||||
}
|
||||
if (!theOutputDirectory.isDirectory()) {
|
||||
throw new MojoFailureException(theOutputDirectory + " is not a directory");
|
||||
}
|
||||
if (theResourceOutputDirectory != null) {
|
||||
if (!theResourceOutputDirectory.exists()) {
|
||||
theResourceOutputDirectory.mkdirs();
|
||||
}
|
||||
if (!theResourceOutputDirectory.isDirectory()) {
|
||||
throw new MojoFailureException(theResourceOutputDirectory + " is not a directory");
|
||||
}
|
||||
}
|
||||
|
||||
if (!myImportsResolved) {
|
||||
for (BaseRootType next : myResources) {
|
||||
|
@ -348,6 +369,40 @@ public abstract class BaseStructureParser {
|
|||
} catch (IOException e) {
|
||||
throw new MojoFailureException("Failed to write structure", e);
|
||||
}
|
||||
|
||||
if (next instanceof Resource) {
|
||||
myNameToResourceClass.put(next.getElementName(), thePackageBase + '.' + elementName);
|
||||
} else if (next instanceof Composite) {
|
||||
myNameToDatatypeClass.put(next.getElementName(), thePackageBase + '.' + elementName);
|
||||
} else {
|
||||
throw new IllegalStateException(next.getClass().toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (theResourceOutputDirectory != null) {
|
||||
try {
|
||||
File versionFile = new File(theResourceOutputDirectory, "fhirversion.properties");
|
||||
FileWriter w = new FileWriter(versionFile, false);
|
||||
|
||||
ourLog.info("Writing file: {}", versionFile.getAbsolutePath());
|
||||
|
||||
VelocityContext ctx = new VelocityContext();
|
||||
ctx.put("nameToResourceClass", myNameToResourceClass);
|
||||
ctx.put("nameToDatatypeClass", myNameToDatatypeClass);
|
||||
|
||||
VelocityEngine v = new VelocityEngine();
|
||||
v.setProperty("resource.loader", "cp");
|
||||
v.setProperty("cp.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||
v.setProperty("runtime.references.strict", Boolean.TRUE);
|
||||
|
||||
InputStream templateIs = ResourceGeneratorUsingSpreadsheet.class.getResourceAsStream("/vm/fhirversion_properties.vm");
|
||||
InputStreamReader templateReader = new InputStreamReader(templateIs);
|
||||
v.evaluate(ctx, w, "", templateReader);
|
||||
|
||||
w.close();
|
||||
} catch (IOException e) {
|
||||
throw new MojoFailureException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,8 +426,8 @@ public abstract class BaseStructureParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Example: Encounter has an internal block class named "Location", but it also has a reference to the Location resource type, so we need to use the fully qualified name for that resource
|
||||
* reference
|
||||
* Example: Encounter has an internal block class named "Location", but it also has a reference to the Location
|
||||
* resource type, so we need to use the fully qualified name for that resource reference
|
||||
*/
|
||||
private void fixResourceReferenceClassNames(BaseElement theNext, String thePackageBase) {
|
||||
for (BaseElement next : theNext.getChildren()) {
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
package ca.uhn.fhir.tinder.parser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
|
||||
import ch.qos.logback.classic.ClassicConstants;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import com.google.common.reflect.ClassPath.ClassInfo;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.tinder.model.BaseRootType;
|
||||
import ca.uhn.fhir.tinder.model.Composite;
|
||||
|
||||
|
@ -31,6 +44,27 @@ public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAll(File theOutputDirectory, File theResourceOutputDirectory, String thePackageBase) throws MojoFailureException {
|
||||
|
||||
try {
|
||||
ImmutableSet<ClassInfo> tlc = ClassPath.from(getClass().getClassLoader()).getTopLevelClasses(StringDt.class.getPackage().getName());
|
||||
for (ClassInfo classInfo : tlc) {
|
||||
DatatypeDef def = Class.forName(classInfo.getName()).getAnnotation(DatatypeDef.class);
|
||||
if (def!=null) {
|
||||
getNameToDatatypeClass().put(def.name(), classInfo.getName());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new MojoFailureException(e.getMessage(),e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MojoFailureException(e.getMessage(),e);
|
||||
}
|
||||
|
||||
|
||||
super.writeAll(theOutputDirectory, theResourceOutputDirectory, thePackageBase);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseRootType createRootType() {
|
||||
return new Composite();
|
||||
|
|
|
@ -315,7 +315,7 @@ public class ProfileParser extends BaseStructureParser {
|
|||
pp.parseSingleProfile(prof, "http://foo");
|
||||
|
||||
pp.markResourcesForImports();
|
||||
pp.writeAll(new File("target/gen/test/resource"), "test");
|
||||
pp.writeAll(new File("target/gen/test/resource"), null,"test");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ public class ResourceGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
|
|||
p.setBaseResourceNames(names);
|
||||
p.parse();
|
||||
p.markResourcesForImports();
|
||||
p.writeAll(new File("target/gen/ca/uhn/fhir/model/dstu/resource"), "ca.uhn.fhir.model.dstu");
|
||||
p.writeAll(new File("target/gen/ca/uhn/fhir/model/dstu/resource"), null,"ca.uhn.fhir.model.dstu");
|
||||
//
|
||||
// // TODO: this needs to be properly populated
|
||||
// p.getAllDatatypes().add("String");
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# This file contains version definitions
|
||||
|
||||
#foreach ( $next in ${nameToResourceClass.entrySet()} )
|
||||
resource.${next.key}=${next.value}
|
||||
#end
|
||||
|
||||
#foreach ( $next in ${nameToDatatypeClass.entrySet()} )
|
||||
datatype.${next.key}=${next.value}
|
||||
#end
|
Loading…
Reference in New Issue