Merge branch 'master' into fulltext
This commit is contained in:
commit
588016e406
|
@ -1,43 +1,17 @@
|
||||||
package ca.uhn.fhir.context;
|
package ca.uhn.fhir.context;
|
||||||
|
|
||||||
/*
|
|
||||||
* #%L
|
|
||||||
* HAPI FHIR - Core Library
|
|
||||||
* %%
|
|
||||||
* Copyright (C) 2014 - 2015 University Health Network
|
|
||||||
* %%
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* #L%
|
|
||||||
*/
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.text.WordUtils;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.util.BeanUtils;
|
|
||||||
|
|
||||||
public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChildDefinition {
|
public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChildDefinition {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseRuntimeDeclaredChildDefinition.class);
|
|
||||||
private final IAccessor myAccessor;
|
private final IAccessor myAccessor;
|
||||||
private final String myElementName;
|
private final String myElementName;
|
||||||
private final Field myField;
|
private final Field myField;
|
||||||
|
@ -48,22 +22,13 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
private final IMutator myMutator;
|
private final IMutator myMutator;
|
||||||
private final String myShortDefinition;
|
private final String myShortDefinition;
|
||||||
private boolean mySummary;
|
private boolean mySummary;
|
||||||
private Boolean ourUseMethodAccessors;
|
|
||||||
|
|
||||||
BaseRuntimeDeclaredChildDefinition(Field theField, Child theChildAnnotation, Description theDescriptionAnnotation, String theElementName) throws ConfigurationException {
|
BaseRuntimeDeclaredChildDefinition(Field theField, Child theChildAnnotation, Description theDescriptionAnnotation, String theElementName) throws ConfigurationException {
|
||||||
super();
|
super();
|
||||||
if (theField == null) {
|
Validate.notNull(theField, "No field speficied");
|
||||||
throw new IllegalArgumentException("No field speficied");
|
Validate.inclusiveBetween(0, Integer.MAX_VALUE, theChildAnnotation.min(), "Min must be >= 0");
|
||||||
}
|
Validate.isTrue(theChildAnnotation.max() == -1 || theChildAnnotation.max() >= theChildAnnotation.min(), "Max must be >= Min (unless it is -1 / unlimited)");
|
||||||
if (theChildAnnotation.min() < 0) {
|
Validate.notBlank(theElementName, "Element name must not be blank");
|
||||||
throw new ConfigurationException("Min must be >= 0");
|
|
||||||
}
|
|
||||||
if (theChildAnnotation.max() != -1 && theChildAnnotation.max() < theChildAnnotation.min()) {
|
|
||||||
throw new ConfigurationException("Max must be >= Min (unless it is -1 / unlimited)");
|
|
||||||
}
|
|
||||||
if (isBlank(theElementName)) {
|
|
||||||
throw new ConfigurationException("Element name must not be blank");
|
|
||||||
}
|
|
||||||
|
|
||||||
myField = theField;
|
myField = theField;
|
||||||
myMin = theChildAnnotation.min();
|
myMin = theChildAnnotation.min();
|
||||||
|
@ -79,69 +44,14 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
myFormalDefinition = null;
|
myFormalDefinition = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle lists (max>0), and maybe max=0?
|
myField.setAccessible(true);
|
||||||
|
if (List.class.equals(myField.getType())) {
|
||||||
// TODO: finish implementing field level accessors/mutators
|
// TODO: verify that generic type is IElement
|
||||||
if (ourUseMethodAccessors == null) {
|
myAccessor = new FieldListAccessor();
|
||||||
try {
|
myMutator = new FieldListMutator();
|
||||||
myField.setAccessible(true);
|
|
||||||
ourUseMethodAccessors = false;
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
ourLog.info("Can not use field accessors/mutators, going to use methods instead");
|
|
||||||
ourUseMethodAccessors = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ourUseMethodAccessors == false) {
|
|
||||||
if (List.class.equals(myField.getType())) {
|
|
||||||
// TODO: verify that generic type is IElement
|
|
||||||
myAccessor = new FieldListAccessor();
|
|
||||||
myMutator = new FieldListMutator();
|
|
||||||
} else {
|
|
||||||
myAccessor = new FieldPlainAccessor();
|
|
||||||
myMutator = new FieldPlainMutator();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Class<?> declaringClass = myField.getDeclaringClass();
|
myAccessor = new FieldPlainAccessor();
|
||||||
final Class<?> targetReturnType = myField.getType();
|
myMutator = new FieldPlainMutator();
|
||||||
try {
|
|
||||||
String elementName = myElementName;
|
|
||||||
if ("class".equals(elementName.toLowerCase())) {
|
|
||||||
elementName = "classElement"; // because getClass() is reserved
|
|
||||||
}
|
|
||||||
final Method accessor = BeanUtils.findAccessor(declaringClass, targetReturnType, elementName);
|
|
||||||
if (accessor == null) {
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
b.append("Could not find bean accessor/getter for property ");
|
|
||||||
b.append(elementName);
|
|
||||||
b.append(" on class ");
|
|
||||||
b.append(declaringClass.getCanonicalName());
|
|
||||||
throw new ConfigurationException(b.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
final Method mutator = findMutator(declaringClass, targetReturnType, elementName);
|
|
||||||
if (mutator == null) {
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
b.append("Could not find bean mutator/setter for property ");
|
|
||||||
b.append(elementName);
|
|
||||||
b.append(" on class ");
|
|
||||||
b.append(declaringClass.getCanonicalName());
|
|
||||||
b.append(" (expected return type ");
|
|
||||||
b.append(targetReturnType.getCanonicalName());
|
|
||||||
b.append(")");
|
|
||||||
throw new ConfigurationException(b.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (List.class.isAssignableFrom(targetReturnType)) {
|
|
||||||
myAccessor = new ListAccessor(accessor);
|
|
||||||
myMutator = new ListMutator(mutator);
|
|
||||||
} else {
|
|
||||||
myAccessor = new PlainAccessor(accessor);
|
|
||||||
myMutator = new PlainMutator(targetReturnType, mutator);
|
|
||||||
}
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
throw new ConfigurationException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -198,17 +108,6 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
return mySummary;
|
return mySummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Method findMutator(Class<?> theDeclaringClass, Class<?> theTargetReturnType, String theElementName) {
|
|
||||||
String methodName = "set" + WordUtils.capitalize(theElementName);
|
|
||||||
try {
|
|
||||||
return theDeclaringClass.getMethod(methodName, theTargetReturnType);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
return null;
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
throw new ConfigurationException("Failed to scan class '" + theDeclaringClass + "' because of a security exception", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class FieldListAccessor implements IAccessor {
|
private final class FieldListAccessor implements IAccessor {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
|
@ -216,11 +115,10 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
List<IBase> retVal;
|
List<IBase> retVal;
|
||||||
try {
|
try {
|
||||||
retVal = (List<IBase>) myField.get(theTarget);
|
retVal = (List<IBase>) myField.get(theTarget);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (Exception e) {
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
throw new ConfigurationException("Failed to get value", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retVal == null) {
|
if (retVal == null) {
|
||||||
retVal = Collections.emptyList();
|
retVal = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -246,9 +144,7 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
existingList.clear();
|
existingList.clear();
|
||||||
}
|
}
|
||||||
existingList.add(theValue);
|
existingList.add(theValue);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (Exception e) {
|
||||||
throw new ConfigurationException("Failed to set value", e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to set value", e);
|
throw new ConfigurationException("Failed to set value", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,11 +163,9 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<IBase> retVal = Collections.singletonList((IBase)values);
|
List<IBase> retVal = Collections.singletonList((IBase) values);
|
||||||
return retVal;
|
return retVal;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (Exception e) {
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
throw new ConfigurationException("Failed to get value", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,125 +176,8 @@ public abstract class BaseRuntimeDeclaredChildDefinition extends BaseRuntimeChil
|
||||||
public void addValue(Object theTarget, IBase theValue) {
|
public void addValue(Object theTarget, IBase theValue) {
|
||||||
try {
|
try {
|
||||||
myField.set(theTarget, theValue);
|
myField.set(theTarget, theValue);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (Exception e) {
|
||||||
throw new ConfigurationException("Failed to set value", e);
|
throw new ConfigurationException("Failed to set value", e);
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to set value", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(Object theTarget, IBase theValue) {
|
|
||||||
addValue(theTarget, theValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ListAccessor implements IAccessor {
|
|
||||||
private final Method myAccessorMethod;
|
|
||||||
|
|
||||||
private ListAccessor(Method theAccessor) {
|
|
||||||
myAccessorMethod = theAccessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public List<IBase> getValues(Object theTarget) {
|
|
||||||
try {
|
|
||||||
return (List<IBase>) myAccessorMethod.invoke(theTarget);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class ListMutator implements IMutator {
|
|
||||||
private final Method myMutatorMethod;
|
|
||||||
|
|
||||||
private ListMutator(Method theMutator) {
|
|
||||||
myMutatorMethod = theMutator;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addValue(Object theTarget, boolean theClear, IBase theValue) {
|
|
||||||
List<IBase> existingList = myAccessor.getValues(theTarget);
|
|
||||||
if (existingList == null) {
|
|
||||||
existingList = new ArrayList<IBase>();
|
|
||||||
try {
|
|
||||||
myMutatorMethod.invoke(theTarget, existingList);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (theClear) {
|
|
||||||
existingList.clear();
|
|
||||||
}
|
|
||||||
existingList.add(theValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addValue(Object theTarget, IBase theValue) {
|
|
||||||
addValue(theTarget, false, theValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(Object theTarget, IBase theValue) {
|
|
||||||
addValue(theTarget, true, theValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class PlainAccessor implements IAccessor {
|
|
||||||
private final Method myAccessorMethod;
|
|
||||||
|
|
||||||
private PlainAccessor(Method theAccessor) {
|
|
||||||
myAccessorMethod = theAccessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<IBase> getValues(Object theTarget) {
|
|
||||||
try {
|
|
||||||
return Collections.singletonList((IBase)myAccessorMethod.invoke(theTarget));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class PlainMutator implements IMutator {
|
|
||||||
private final Method myMutatorMethod;
|
|
||||||
private final Class<?> myTargetReturnType;
|
|
||||||
|
|
||||||
private PlainMutator(Class<?> theTargetReturnType, Method theMutator) {
|
|
||||||
assert theTargetReturnType != null;
|
|
||||||
assert theMutator != null;
|
|
||||||
|
|
||||||
myTargetReturnType = theTargetReturnType;
|
|
||||||
myMutatorMethod = theMutator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addValue(Object theTarget, IBase theValue) {
|
|
||||||
try {
|
|
||||||
if (theValue != null && !myTargetReturnType.isAssignableFrom(theValue.getClass())) {
|
|
||||||
throw new ConfigurationException("Value for field " + myElementName + " expects type " + myTargetReturnType + " but got " + theValue.getClass());
|
|
||||||
}
|
|
||||||
myMutatorMethod.invoke(theTarget, theValue);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new ConfigurationException("Failed to get value", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div>
|
||||||
|
<th:block th:if="${not resource.valueElement.empty}" th:text="${resource.valueElement.valueAsString}"/>
|
||||||
|
<th:block th:if="${not resource.unitsElement.empty}" th:text="${resource.unitsElement.value}"/>
|
||||||
|
</div>
|
|
@ -39,6 +39,9 @@ period.narrative=classpath:ca/uhn/fhir/narrative/datatype/PeriodDt.html
|
||||||
quantity.class=ca.uhn.fhir.model.dstu.composite.QuantityDt
|
quantity.class=ca.uhn.fhir.model.dstu.composite.QuantityDt
|
||||||
quantity.narrative=classpath:ca/uhn/fhir/narrative/datatype/QuantityDt.html
|
quantity.narrative=classpath:ca/uhn/fhir/narrative/datatype/QuantityDt.html
|
||||||
|
|
||||||
|
simplequantity.class=ca.uhn.fhir.model.dstu.composite.SimpleQuantityDt
|
||||||
|
simplequantity.narrative=classpath:ca/uhn/fhir/narrative/datatype/SimpleQuantityDt.html
|
||||||
|
|
||||||
################################################
|
################################################
|
||||||
# Resources
|
# Resources
|
||||||
################################################
|
################################################
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class App {
|
||||||
ourCommands.add(new RunServerCommand());
|
ourCommands.add(new RunServerCommand());
|
||||||
ourCommands.add(new ExampleDataUploader());
|
ourCommands.add(new ExampleDataUploader());
|
||||||
ourCommands.add(new ValidateCommand());
|
ourCommands.add(new ValidateCommand());
|
||||||
|
ourCommands.add(new ValidationDataUploader());
|
||||||
|
|
||||||
Collections.sort(ourCommands);
|
Collections.sort(ourCommands);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ public class RunServerCommand extends BaseCommand {
|
||||||
public void run(CommandLine theCommandLine) throws ParseException {
|
public void run(CommandLine theCommandLine) throws ParseException {
|
||||||
myPort = parseOptionInteger(theCommandLine, OPTION_P, DEFAULT_PORT);
|
myPort = parseOptionInteger(theCommandLine, OPTION_P, DEFAULT_PORT);
|
||||||
|
|
||||||
|
// ((ch.qos.logback.classic.Logger)LoggerFactory.getLogger("/")).setLevel(Level.ERROR);
|
||||||
|
|
||||||
ourLog.info("Preparing HAPI FHIR JPA server");
|
ourLog.info("Preparing HAPI FHIR JPA server");
|
||||||
File tempWarFile;
|
File tempWarFile;
|
||||||
try {
|
try {
|
||||||
|
@ -81,6 +83,8 @@ public class RunServerCommand extends BaseCommand {
|
||||||
ourLog.info("Server started on port {}", myPort);
|
ourLog.info("Server started on port {}", myPort);
|
||||||
ourLog.info("Web Testing UI : http://localhost:{}/", myPort);
|
ourLog.info("Web Testing UI : http://localhost:{}/", myPort);
|
||||||
ourLog.info("Server Base URL: http://localhost:{}/baseDstu2/", myPort);
|
ourLog.info("Server Base URL: http://localhost:{}/baseDstu2/", myPort);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(String[] theArgs) {
|
public void run(String[] theArgs) {
|
||||||
|
|
|
@ -1,134 +1,157 @@
|
||||||
package ca.uhn.fhir.cli;
|
package ca.uhn.fhir.cli;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.hl7.fhir.instance.model.Bundle;
|
|
||||||
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
|
|
||||||
import org.hl7.fhir.instance.model.StructureDefinition;
|
|
||||||
import org.hl7.fhir.instance.model.ValueSet;
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
|
|
||||||
public class ValidationDataUploader extends BaseCommand {
|
public class ValidationDataUploader extends BaseCommand {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationDataUploader.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationDataUploader.class);
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
@Override
|
||||||
new ValidationDataUploader().execute();
|
public String getCommandDescription() {
|
||||||
|
return "Uploads the conformance resources (StructureDefinition and ValueSet) from the official FHIR definitions.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void execute() throws IOException, ClientProtocolException, UnsupportedEncodingException {
|
@Override
|
||||||
ourLog.info("Starting...");
|
public String getCommandName() {
|
||||||
|
return "upload-definitions";
|
||||||
|
}
|
||||||
|
|
||||||
FhirContext ctx = FhirContext.forDstu2Hl7Org();
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
Options options = new Options();
|
||||||
|
Option opt;
|
||||||
|
|
||||||
IGenericClient client = newClient(ctx,"");
|
opt = new Option("t", "target", true, "Base URL for the target server (e.g. \"http://example.com/fhir\")");
|
||||||
|
opt.setRequired(true);
|
||||||
|
options.addOption(opt);
|
||||||
|
|
||||||
int total;
|
return options;
|
||||||
int count;
|
}
|
||||||
|
|
||||||
// String vsContents =
|
|
||||||
// IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/valuesets.xml"),
|
|
||||||
// "UTF-8");
|
|
||||||
// Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
|
||||||
//
|
|
||||||
// int total = bundle.getEntry().size();
|
|
||||||
// int count = 1;
|
|
||||||
// for (BundleEntryComponent i : bundle.getEntry()) {
|
|
||||||
// ValueSet next = (ValueSet) i.getResource();
|
|
||||||
// next.setId(next.getIdElement().toUnqualifiedVersionless());
|
|
||||||
//
|
|
||||||
// ourLog.info("Uploading ValueSet {}/{} : {}", new Object[] {count,total,next.getIdElement().getValue()});
|
|
||||||
// client.update().resource(next).execute();
|
|
||||||
//
|
|
||||||
// count++;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ourLog.info("Finished uploading ValueSets");
|
|
||||||
|
|
||||||
// String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
|
@Override
|
||||||
// Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
public void run(CommandLine theCommandLine) throws ParseException {
|
||||||
// total = bundle.getEntry().size();
|
String targetServer = theCommandLine.getOptionValue("t");
|
||||||
// count = 1;
|
if (isBlank(targetServer)) {
|
||||||
// for (BundleEntryComponent i : bundle.getEntry()) {
|
throw new ParseException("No target server (-t) specified");
|
||||||
// ValueSet next = (ValueSet) i.getResource();
|
} else if (targetServer.startsWith("http") == false) {
|
||||||
// next.setId(next.getIdElement().toUnqualifiedVersionless());
|
throw new ParseException("Invalid target server specified, must begin with 'http'");
|
||||||
//
|
}
|
||||||
// ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
|
||||||
// client.update().resource(next).execute();
|
|
||||||
//
|
|
||||||
// count++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
FhirContext ctx = FhirContext.forDstu2();
|
||||||
String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v2-tables.xml"), "UTF-8");
|
ourLog.info("Uploading definitions to server: " + targetServer);
|
||||||
|
|
||||||
|
IGenericClient client = newClient(ctx, targetServer);
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String vsContents;
|
||||||
|
try {
|
||||||
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/valuesets.xml"), "UTF-8");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CommandFailureException(e.toString());
|
||||||
|
}
|
||||||
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||||
|
|
||||||
|
int total = bundle.getEntry().size();
|
||||||
|
int count = 1;
|
||||||
|
for (Entry i : bundle.getEntry()) {
|
||||||
|
ValueSet next = (ValueSet) i.getResource();
|
||||||
|
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||||
|
|
||||||
|
ourLog.info("Uploading ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||||
|
client.update().resource(next).execute();
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CommandFailureException(e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||||
total = bundle.getEntry().size();
|
total = bundle.getEntry().size();
|
||||||
count = 1;
|
count = 1;
|
||||||
for (BundleEntryComponent i : bundle.getEntry()) {
|
for (Entry i : bundle.getEntry()) {
|
||||||
if (count > 1900) {
|
ValueSet next = (ValueSet) i.getResource();
|
||||||
|
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||||
|
|
||||||
|
ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||||
|
client.update().resource(next).execute();
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v2-tables.xml"), "UTF-8");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CommandFailureException(e.toString());
|
||||||
|
}
|
||||||
|
bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
|
||||||
|
total = bundle.getEntry().size();
|
||||||
|
count = 1;
|
||||||
|
for (Entry i : bundle.getEntry()) {
|
||||||
ValueSet next = (ValueSet) i.getResource();
|
ValueSet next = (ValueSet) i.getResource();
|
||||||
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||||
|
|
||||||
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||||
client.update().resource(next).execute();
|
client.update().resource(next).execute();
|
||||||
}
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Finished uploading ValueSets");
|
ourLog.info("Finished uploading ValueSets");
|
||||||
|
|
||||||
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
||||||
Resource[] mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/*.profile.xml");
|
Resource[] mappingLocations;
|
||||||
|
try {
|
||||||
|
mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/*.profile.xml");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CommandFailureException(e.toString());
|
||||||
|
}
|
||||||
total = mappingLocations.length;
|
total = mappingLocations.length;
|
||||||
count = 1;
|
count = 1;
|
||||||
for (Resource i : mappingLocations) {
|
for (Resource i : mappingLocations) {
|
||||||
if (count > 140) {
|
StructureDefinition next;
|
||||||
StructureDefinition next = ctx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(i.getInputStream(), "UTF-8"));
|
try {
|
||||||
|
next = ctx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(i.getInputStream(), "UTF-8"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CommandFailureException(e.toString());
|
||||||
|
}
|
||||||
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
next.setId(next.getIdElement().toUnqualifiedVersionless());
|
||||||
|
|
||||||
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
|
||||||
client.update().resource(next).execute();
|
try {
|
||||||
|
client.update().resource(next).execute();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ourLog.warn("Failed to upload {} - {}", next.getIdElement().getValue(), e.getMessage());
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Finished uploading ValueSets");
|
ourLog.info("Finished uploading ValueSets");
|
||||||
|
|
||||||
}
|
long delay = System.currentTimeMillis() - start;
|
||||||
|
|
||||||
@Override
|
ourLog.info("Finished uploading definitions to server (took {} ms)", delay);
|
||||||
public String getCommandDescription() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCommandName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Options getOptions() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(CommandLine theCommandLine) throws ParseException {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,38 +8,11 @@
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<logger name="java.sql" additivity="false" level="warn">
|
<logger name="ca.uhn.fhir.cli" additivity="false" level="info">
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="ca.uhn.fhir.jpa" additivity="false" level="info">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="ca.uhn.fhir.rest" additivity="false" level="warn">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="org.eclipse" additivity="false" level="warn">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="org.springframework" additivity="false" level="warn">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="org.apache" additivity="false" level="info">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="org.thymeleaf" additivity="false" level="warn">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
<logger name="org.hibernate" additivity="false" level="warn">
|
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</logger>
|
</logger>
|
||||||
|
|
||||||
<!--
|
<root level="warn">
|
||||||
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="trace">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</logger>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<root level="info">
|
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.6.0</version>
|
<version>${slf4j_target_version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
|
|
@ -106,16 +106,13 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
||||||
|
|
||||||
// SubscriptionCandidateResource
|
// SubscriptionCandidateResource
|
||||||
|
|
||||||
TypedQuery<SubscriptionTable> q = myEntityManager.createNamedQuery("Q_HFJ_SUBSCRIPTION_NEXT_CHECK", SubscriptionTable.class);
|
Collection<Long> subscriptions = mySubscriptionTableDao.finsSubscriptionsWhichNeedToBeChecked(SubscriptionStatusEnum.ACTIVE, new Date());
|
||||||
q.setParameter("next_check", new Date());
|
|
||||||
q.setParameter("status", SubscriptionStatusEnum.ACTIVE);
|
|
||||||
List<SubscriptionTable> subscriptions = q.getResultList();
|
|
||||||
|
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||||
|
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
for (final SubscriptionTable nextSubscriptionTable : subscriptions) {
|
for (final Long nextSubscriptionTablePid : subscriptions) {
|
||||||
retVal += txTemplate.execute(new TransactionCallback<Integer>() {
|
retVal += txTemplate.execute(new TransactionCallback<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public Integer doInTransaction(TransactionStatus theStatus) {
|
public Integer doInTransaction(TransactionStatus theStatus) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
|
||||||
|
|
||||||
public interface ISubscriptionTableDao extends JpaRepository<SubscriptionTable, Long> {
|
public interface ISubscriptionTableDao extends JpaRepository<SubscriptionTable, Long> {
|
||||||
|
|
||||||
|
@ -46,4 +47,6 @@ public interface ISubscriptionTableDao extends JpaRepository<SubscriptionTable,
|
||||||
@Query("SELECT t FROM SubscriptionTable t WHERE t.myLastClientPoll < :cutoff OR (t.myLastClientPoll IS NULL AND t.myCreated < :cutoff)")
|
@Query("SELECT t FROM SubscriptionTable t WHERE t.myLastClientPoll < :cutoff OR (t.myLastClientPoll IS NULL AND t.myCreated < :cutoff)")
|
||||||
public Collection<SubscriptionTable> findInactiveBeforeCutoff(@Param("cutoff") Date theCutoff);
|
public Collection<SubscriptionTable> findInactiveBeforeCutoff(@Param("cutoff") Date theCutoff);
|
||||||
|
|
||||||
|
@Query("SELECT t.myId FROM SubscriptionTable t WHERE t.myStatus = :status AND t.myNextCheck <= :next_check")
|
||||||
|
public Collection<Long> finsSubscriptionsWhichNeedToBeChecked(@Param("status") SubscriptionStatusEnum theStatus, @Param("next_check") Date theNextCheck);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
|
||||||
})
|
})
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name="Q_HFJ_SUBSCRIPTION_SET_STATUS", query="UPDATE SubscriptionTable t SET t.myStatus = :status WHERE t.myResId = :res_id"),
|
@NamedQuery(name="Q_HFJ_SUBSCRIPTION_SET_STATUS", query="UPDATE SubscriptionTable t SET t.myStatus = :status WHERE t.myResId = :res_id"),
|
||||||
@NamedQuery(name="Q_HFJ_SUBSCRIPTION_NEXT_CHECK", query="SELECT t FROM SubscriptionTable t WHERE t.myStatus = :status AND t.myNextCheck <= :next_check"),
|
|
||||||
@NamedQuery(name="Q_HFJ_SUBSCRIPTION_GET_BY_RES", query="SELECT t FROM SubscriptionTable t WHERE t.myResId = :res_id")
|
@NamedQuery(name="Q_HFJ_SUBSCRIPTION_GET_BY_RES", query="SELECT t FROM SubscriptionTable t WHERE t.myResId = :res_id")
|
||||||
})
|
})
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
|
@ -6,6 +6,7 @@ import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
|
@ -19,6 +20,7 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptor;
|
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptor;
|
||||||
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
||||||
|
@ -250,6 +252,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
mySubscriptionDao.read(new IdDt("Subscription", socket.mySubsId));
|
mySubscriptionDao.read(new IdDt("Subscription", socket.mySubsId));
|
||||||
|
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
|
ResourceMetadataKeyEnum.PROFILES.put(obs, Collections.singletonList(new IdDt("http://foo")));
|
||||||
obs.getSubject().setReference(pId);
|
obs.getSubject().setReference(pId);
|
||||||
obs.setStatus(ObservationStatusEnum.FINAL);
|
obs.setStatus(ObservationStatusEnum.FINAL);
|
||||||
IIdType afterId1 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
IIdType afterId1 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||||
|
@ -301,6 +304,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
IIdType pId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
IIdType pId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
Subscription subs = new Subscription();
|
Subscription subs = new Subscription();
|
||||||
|
ResourceMetadataKeyEnum.PROFILES.put(subs, Collections.singletonList(new IdDt("http://foo")));
|
||||||
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
|
subs.getChannel().setType(SubscriptionChannelTypeEnum.WEBSOCKET);
|
||||||
subs.setCriteria("Observation?subject=Patient/" + pId.getIdPart());
|
subs.setCriteria("Observation?subject=Patient/" + pId.getIdPart());
|
||||||
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
|
subs.setStatus(SubscriptionStatusEnum.ACTIVE);
|
||||||
|
|
|
@ -41,6 +41,14 @@
|
||||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||||
<version>1.3-SNAPSHOT</version>
|
<version>1.3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Don't force OSGi users to use a newer version of SLF4j than we need -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j_target_version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class NarrativeDt extends BaseNarrativeDt<NarrativeStatusEnum> {
|
||||||
return ca.uhn.fhir.util.ElementUtil.allPopulatedChildElements( theType, myStatus, myDiv );
|
return ca.uhn.fhir.util.ElementUtil.allPopulatedChildElements( theType, myStatus, myDiv );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value(s) for <b>status</b> (generated | extensions | additional).
|
* Gets the value(s) for <b>status</b> (generated | extensions | additional).
|
||||||
* creating it if it does
|
* creating it if it does
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class BearerTokenAuthInterceptorTest {
|
||||||
public void before() {
|
public void before() {
|
||||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||||
ourCtx.getRestfulClientFactory().setServerValidationModeEnum(ServerValidationModeEnum.NEVER);
|
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||||
|
|
||||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,20 @@ public class NarrativeDt extends BaseNarrativeDt {
|
||||||
* <p>
|
* <p>
|
||||||
* <b>Definition:</b>
|
* <b>Definition:</b>
|
||||||
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
|
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public BoundCodeDt<NarrativeStatusEnum> getStatusElement() {
|
||||||
|
return getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value(s) for <b>status</b> (generated | extensions | additional).
|
||||||
|
* creating it if it does
|
||||||
|
* not exist. Will not return <code>null</code>.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Definition:</b>
|
||||||
|
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public BoundCodeDt<NarrativeStatusEnum> getStatus() {
|
public BoundCodeDt<NarrativeStatusEnum> getStatus() {
|
||||||
|
@ -132,6 +146,20 @@ public class NarrativeDt extends BaseNarrativeDt {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value(s) for <b>div</b> (Limited xhtml content).
|
||||||
|
* creating it if it does
|
||||||
|
* not exist. Will not return <code>null</code>.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Definition:</b>
|
||||||
|
* The actual narrative content, a stripped down version of XHTML
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public XhtmlDt getDivElement() {
|
||||||
|
return getDiv();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value(s) for <b>div</b> (Limited xhtml content).
|
* Gets the value(s) for <b>div</b> (Limited xhtml content).
|
||||||
* creating it if it does
|
* creating it if it does
|
||||||
|
|
|
@ -8,9 +8,12 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.*;
|
||||||
|
import ca.uhn.fhir.model.dstu2.valueset.*;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
@ -26,20 +29,7 @@ import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Binary;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Medication;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.IdentifierUseEnum;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum;
|
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.ObservationStatusEnum;
|
|
||||||
import ca.uhn.fhir.model.primitive.DateDt;
|
import ca.uhn.fhir.model.primitive.DateDt;
|
||||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
@ -1012,4 +1002,19 @@ public class JsonParserDstu2Test {
|
||||||
Assert.assertThat(message, containsString("contained"));
|
Assert.assertThat(message, containsString("contained"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// see #241
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testEncodeThenParseShouldNotAddSpuriousId() throws Exception {
|
||||||
|
Condition condition = new Condition().setVerificationStatus(ConditionVerificationStatusEnum.CONFIRMED);
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
|
ca.uhn.fhir.model.dstu2.resource.Bundle.Entry entry = new ca.uhn.fhir.model.dstu2.resource.Bundle.Entry();
|
||||||
|
entry.setFullUrl(IdDt.newRandomUuid());
|
||||||
|
entry.setResource(condition);
|
||||||
|
bundle.getEntry().add(entry);
|
||||||
|
IParser parser = ourCtx.newJsonParser();
|
||||||
|
String json = parser.encodeResourceToString(bundle);
|
||||||
|
bundle = (ca.uhn.fhir.model.dstu2.resource.Bundle) parser.parseResource(json);
|
||||||
|
assertTrue(bundle.getEntry().get(0).getResource().getIdElement().isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
@ -163,7 +164,20 @@ public class SearchDstu2Test {
|
||||||
assertEquals("2002", ourLastDateAndList.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(1).getValueAsString());
|
assertEquals("2002", ourLastDateAndList.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(1).getValueAsString());
|
||||||
assertThat(responseContent, containsString("SYSTEM"));
|
assertThat(responseContent, containsString("SYSTEM"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchByPut() throws Exception {
|
||||||
|
HttpPut httpGet = new HttpPut("http://localhost:" + ourPort + "/Patient/_search");
|
||||||
|
StringEntity entity = new StringEntity("searchDateAndList=2001,2002&searchDateAndList=2003,2004", ContentType.APPLICATION_FORM_URLENCODED);
|
||||||
|
httpGet.setEntity(entity);
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchByPostWithBodyAndUrlParams() throws Exception {
|
public void testSearchByPostWithBodyAndUrlParams() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -282,7 +287,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
assertEquals("1", opDef.getParameter().get(2).getMinElement().getValueAsString());
|
assertEquals("1", opDef.getParameter().get(2).getMinElement().getValueAsString());
|
||||||
assertEquals("2", opDef.getParameter().get(2).getMaxElement().getValueAsString());
|
assertEquals("2", opDef.getParameter().get(2).getMaxElement().getValueAsString());
|
||||||
assertEquals("string", opDef.getParameter().get(2).getTypeElement().getValueAsString());
|
assertEquals("string", opDef.getParameter().get(2).getTypeElement().getValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderWithRequiredAndOptional() throws Exception {
|
public void testProviderWithRequiredAndOptional() throws Exception {
|
||||||
|
@ -451,7 +456,7 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
public MethodOutcome delete(@IdParam IdDt theId, @ConditionalUrlParam(supportsMultiple=true) String theConditionalUrl) {
|
public MethodOutcome delete(@IdParam IdDt theId, @ConditionalUrlParam(supportsMultiple = true) String theConditionalUrl) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +491,8 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
public static class MultiOptionalProvider {
|
public static class MultiOptionalProvider {
|
||||||
|
|
||||||
@Search(type = Patient.class)
|
@Search(type = Patient.class)
|
||||||
public Patient findPatient(@Description(shortDefinition = "The patient's identifier") @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier, @Description(shortDefinition = "The patient's name") @OptionalParam(name = Patient.SP_NAME) StringDt theName) {
|
public Patient findPatient(@Description(shortDefinition = "The patient's identifier") @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier,
|
||||||
|
@Description(shortDefinition = "The patient's name") @OptionalParam(name = Patient.SP_NAME) StringDt theName) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,10 +524,9 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
|
|
||||||
public static class PlainProviderWithExtendedOperationOnNoType {
|
public static class PlainProviderWithExtendedOperationOnNoType {
|
||||||
|
|
||||||
@Operation(name = "plain", idempotent = true, returnParameters= {
|
@Operation(name = "plain", idempotent = true, returnParameters = { @OperationParam(min = 1, max = 2, name = "out1", type = StringDt.class) })
|
||||||
@OperationParam(min=1, max=2, name="out1", type=StringDt.class)
|
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId,
|
||||||
})
|
@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||||
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +535,8 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
public static class ProviderWithExtendedOperationReturningBundle implements IResourceProvider {
|
public static class ProviderWithExtendedOperationReturningBundle implements IResourceProvider {
|
||||||
|
|
||||||
@Operation(name = "everything", idempotent = true)
|
@Operation(name = "everything", idempotent = true)
|
||||||
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId,
|
||||||
|
@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,8 +551,9 @@ public class ServerConformanceProviderDstu2Test {
|
||||||
|
|
||||||
@Description(shortDefinition = "This is a search for stuff!")
|
@Description(shortDefinition = "This is a search for stuff!")
|
||||||
@Search
|
@Search
|
||||||
public List<DiagnosticReport> findDiagnosticReportsByPatient(@RequiredParam(name = DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId, @OptionalParam(name = DiagnosticReport.SP_CODE) TokenOrListParam theNames,
|
public List<DiagnosticReport> findDiagnosticReportsByPatient(@RequiredParam(name = DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId,
|
||||||
@OptionalParam(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange, @IncludeParam(allow = { "DiagnosticReport.result" }) Set<Include> theIncludes) throws Exception {
|
@OptionalParam(name = DiagnosticReport.SP_CODE) TokenOrListParam theNames, @OptionalParam(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange,
|
||||||
|
@IncludeParam(allow = { "DiagnosticReport.result" }) Set<Include> theIncludes) throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,13 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
||||||
throw new IllegalArgumentException("Unknown encoding: " + theEncoding);
|
throw new IllegalArgumentException("Unknown encoding: " + theEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < messages.size(); i++) {
|
||||||
|
ValidationMessage next = messages.get(i);
|
||||||
|
if ("Binding has no source, so can't be checked".equals(next.getMessage())) {
|
||||||
|
messages.remove(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,7 @@ public class FhirInstanceValidatorTest {
|
||||||
.toString(FhirInstanceValidator.class.getResourceAsStream("/medicationstatement_invalidelement.xml"));
|
.toString(FhirInstanceValidator.class.getResourceAsStream("/medicationstatement_invalidelement.xml"));
|
||||||
ValidationResult output = myVal.validateWithResult(input);
|
ValidationResult output = myVal.validateWithResult(input);
|
||||||
|
|
||||||
List<SingleValidationMessage> res = logResultsAndReturnNonInformationalOnes(output);
|
List<SingleValidationMessage> res = logResultsAndReturnAll(output);
|
||||||
ourLog.info(res.toString());
|
ourLog.info(res.toString());
|
||||||
|
|
||||||
for (SingleValidationMessage nextMessage : res) {
|
for (SingleValidationMessage nextMessage : res) {
|
||||||
|
|
8
pom.xml
8
pom.xml
|
@ -237,6 +237,14 @@
|
||||||
<thymeleaf-version>2.1.4.RELEASE</thymeleaf-version>
|
<thymeleaf-version>2.1.4.RELEASE</thymeleaf-version>
|
||||||
<ebay_cors_filter_version>1.0.1</ebay_cors_filter_version>
|
<ebay_cors_filter_version>1.0.1</ebay_cors_filter_version>
|
||||||
<xmlunit_version>1.6</xmlunit_version>
|
<xmlunit_version>1.6</xmlunit_version>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
We are aiming to still work on a very old version of SLF4j even though
|
||||||
|
we depend on the newest, just to be nice to users of the API. This version
|
||||||
|
is tested in the hapi-fhir-cobertura.
|
||||||
|
-->
|
||||||
|
<slf4j_target_version>1.6.0</slf4j_target_version>
|
||||||
|
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue