Server starting to work
This commit is contained in:
parent
ce17e82f9d
commit
5828f49029
2
TODO.txt
2
TODO.txt
|
@ -1,4 +1,4 @@
|
|||
|
||||
* Implement JSON parser and encoder
|
||||
* Implement strategy for narrative generation
|
||||
|
||||
* Fix XML encoder to not encode empty elements
|
|
@ -39,6 +39,10 @@ public class FhirContext {
|
|||
return myClassToElementDefinition;
|
||||
}
|
||||
|
||||
public RuntimeResourceDefinition getResourceDefinition(Class<? extends IResource> theResourceType) {
|
||||
return (RuntimeResourceDefinition) myClassToElementDefinition.get(theResourceType);
|
||||
}
|
||||
|
||||
public RuntimeResourceDefinition getResourceDefinition(IResource theResource) {
|
||||
return (RuntimeResourceDefinition) myClassToElementDefinition.get(theResource.getClass());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
@ -60,9 +60,17 @@ class ModelScanner {
|
|||
|
||||
private RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||
|
||||
ModelScanner(Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
|
||||
ModelScanner(Class<? extends IResource> theResourceTypes) throws ConfigurationException {
|
||||
Set<Class<? extends IElement>> singleton = new HashSet<>();
|
||||
singleton.add(theResourceTypes);
|
||||
init(singleton);
|
||||
}
|
||||
|
||||
Set<Class<? extends IElement>> toScan = new HashSet<Class<? extends IElement>>(theResourceTypes);
|
||||
ModelScanner(Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
|
||||
init(new HashSet<Class<? extends IElement>>(theResourceTypes));
|
||||
}
|
||||
|
||||
private void init(Set<Class<? extends IElement>> toScan) {
|
||||
toScan.add(NarrativeDt.class);
|
||||
toScan.add(DateDt.class);
|
||||
toScan.add(CodeDt.class);
|
||||
|
@ -89,7 +97,6 @@ class ModelScanner {
|
|||
myRuntimeChildUndeclaredExtensionDefinition.sealAndInitialize(myClassToElementDefinitions);
|
||||
|
||||
ourLog.info("Done scanning FHIR library, found {} model entries", myClassToElementDefinitions.size());
|
||||
|
||||
}
|
||||
|
||||
public RuntimeChildUndeclaredExtensionDefinition getRuntimeChildUndeclaredExtensionDefinition() {
|
||||
|
|
|
@ -1,77 +1,57 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package ca.uhn.fhir.model.dstu.composite;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.api.annotation.*;
|
||||
import ca.uhn.fhir.model.primitive.*;
|
||||
import ca.uhn.fhir.model.dstu.valueset.*;
|
||||
import ca.uhn.fhir.model.dstu.resource.*;
|
||||
import ca.uhn.fhir.model.api.BaseElement;
|
||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||
import ca.uhn.fhir.model.api.ResourceReference;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ChildResource;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
||||
/**
|
||||
* HAPI/FHIR <b>Identifier</b> Datatype
|
||||
* (An identifier intended for computation)
|
||||
* HAPI/FHIR <b>Identifier</b> Datatype (An identifier intended for computation)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* A technical identifier - identifies some entity uniquely and unambiguously
|
||||
* <b>Definition:</b> A technical identifier - identifies some entity uniquely and unambiguously
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <b>Requirements:</b>
|
||||
* Need to be able to identify things with confidence and be sure that the identification is not subject to misinterpretation
|
||||
* <b>Requirements:</b> Need to be able to identify things with confidence and be sure that the identification is not subject to misinterpretation
|
||||
* </p>
|
||||
*/
|
||||
@DatatypeDef(name="Identifier")
|
||||
@DatatypeDef(name = "Identifier")
|
||||
public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
||||
|
||||
@Child(name="use", type=CodeDt.class, order=0, min=0, max=1)
|
||||
@Child(name = "use", type = CodeDt.class, order = 0, min = 0, max = 1)
|
||||
private BoundCodeDt<IdentifierUseEnum> myUse;
|
||||
|
||||
@Child(name="label", type=StringDt.class, order=1, min=0, max=1)
|
||||
@Child(name = "label", type = StringDt.class, order = 1, min = 0, max = 1)
|
||||
private StringDt myLabel;
|
||||
|
||||
@Child(name="system", type=UriDt.class, order=2, min=0, max=1)
|
||||
@Child(name = "system", type = UriDt.class, order = 2, min = 0, max = 1)
|
||||
private UriDt mySystem;
|
||||
|
||||
@Child(name="value", type=StringDt.class, order=3, min=0, max=1)
|
||||
@Child(name = "value", type = StringDt.class, order = 3, min = 0, max = 1)
|
||||
private StringDt myValue;
|
||||
|
||||
@Child(name="period", type=PeriodDt.class, order=4, min=0, max=1)
|
||||
@Child(name = "period", type = PeriodDt.class, order = 4, min = 0, max = 1)
|
||||
private PeriodDt myPeriod;
|
||||
|
||||
@Child(name="assigner", order=5, min=0, max=1)
|
||||
@ChildResource(types= {
|
||||
Organization.class,
|
||||
})
|
||||
@Child(name = "assigner", order = 5, min = 0, max = 1)
|
||||
@ChildResource(types = { Organization.class, })
|
||||
private ResourceReference myAssigner;
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>use</b> (usual | official | temp | secondary (If known)
|
||||
).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>use</b> (usual | official | temp | secondary (If known) ). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The purpose of this identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The purpose of this identifier
|
||||
* </p>
|
||||
*/
|
||||
public BoundCodeDt<IdentifierUseEnum> getUse() {
|
||||
if (myUse == null) {
|
||||
|
@ -81,41 +61,33 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>use</b> (usual | official | temp | secondary (If known)
|
||||
)
|
||||
* Sets the value(s) for <b>use</b> (usual | official | temp | secondary (If known) )
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The purpose of this identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The purpose of this identifier
|
||||
* </p>
|
||||
*/
|
||||
public void setUse(BoundCodeDt<IdentifierUseEnum> theValue) {
|
||||
myUse = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value(s) for <b>use</b> (usual | official | temp | secondary (If known)
|
||||
)
|
||||
* Sets the value(s) for <b>use</b> (usual | official | temp | secondary (If known) )
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The purpose of this identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The purpose of this identifier
|
||||
* </p>
|
||||
*/
|
||||
public void setUse(IdentifierUseEnum theValue) {
|
||||
getUse().setValueAsEnum(theValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>label</b> (Description of identifier).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>label</b> (Description of identifier). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
*/
|
||||
public StringDt getLabel() {
|
||||
if (myLabel == null) {
|
||||
|
@ -127,36 +99,31 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
/**
|
||||
* Sets the value(s) for <b>label</b> (Description of identifier)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
*/
|
||||
public void setLabel(StringDt theValue) {
|
||||
myLabel = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the value(s) for <b>label</b> (Description of identifier)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> A text string for the identifier that can be displayed to a human so they can recognize the identifier
|
||||
* </p>
|
||||
*/
|
||||
public void setLabel( String theString) {
|
||||
public void setLabel(String theString) {
|
||||
myLabel = new StringDt(theString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>system</b> (The namespace for the identifier).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>system</b> (The namespace for the identifier). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Establishes the namespace in which set of possible id values is unique.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Establishes the namespace in which set of possible id values is unique.
|
||||
* </p>
|
||||
*/
|
||||
public UriDt getSystem() {
|
||||
if (mySystem == null) {
|
||||
|
@ -168,25 +135,20 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
/**
|
||||
* Sets the value(s) for <b>system</b> (The namespace for the identifier)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Establishes the namespace in which set of possible id values is unique.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Establishes the namespace in which set of possible id values is unique.
|
||||
* </p>
|
||||
*/
|
||||
public void setSystem(UriDt theValue) {
|
||||
mySystem = theValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>value</b> (The value that is unique).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>value</b> (The value that is unique). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
*/
|
||||
public StringDt getValue() {
|
||||
if (myValue == null) {
|
||||
|
@ -198,36 +160,31 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
/**
|
||||
* Sets the value(s) for <b>value</b> (The value that is unique)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
*/
|
||||
public void setValue(StringDt theValue) {
|
||||
myValue = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the value(s) for <b>value</b> (The value that is unique)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> The portion of the identifier typically displayed to the user and which is unique within the context of the system.
|
||||
* </p>
|
||||
*/
|
||||
public void setValue( String theString) {
|
||||
public void setValue(String theString) {
|
||||
myValue = new StringDt(theString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>period</b> (Time period when id is/was valid for use).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>period</b> (Time period when id is/was valid for use). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Time period during which identifier is/was valid for use
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Time period during which identifier is/was valid for use
|
||||
* </p>
|
||||
*/
|
||||
public PeriodDt getPeriod() {
|
||||
if (myPeriod == null) {
|
||||
|
@ -239,25 +196,20 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
/**
|
||||
* Sets the value(s) for <b>period</b> (Time period when id is/was valid for use)
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Time period during which identifier is/was valid for use
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Time period during which identifier is/was valid for use
|
||||
* </p>
|
||||
*/
|
||||
public void setPeriod(PeriodDt theValue) {
|
||||
myPeriod = theValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value(s) for <b>assigner</b> (Organization that issued id (may be just text)).
|
||||
* creating it if it does
|
||||
* not exist. Will not return <code>null</code>.
|
||||
* Gets the value(s) for <b>assigner</b> (Organization that issued id (may be just text)). creating it if it does not exist. Will not return <code>null</code>.
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Organization that issued/manages the identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Organization that issued/manages the identifier
|
||||
* </p>
|
||||
*/
|
||||
public ResourceReference getAssigner() {
|
||||
if (myAssigner == null) {
|
||||
|
@ -269,16 +221,41 @@ public class IdentifierDt extends BaseElement implements ICompositeDatatype {
|
|||
/**
|
||||
* Sets the value(s) for <b>assigner</b> (Organization that issued id (may be just text))
|
||||
*
|
||||
* <p>
|
||||
* <b>Definition:</b>
|
||||
* Organization that issued/manages the identifier
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Definition:</b> Organization that issued/manages the identifier
|
||||
* </p>
|
||||
*/
|
||||
public void setAssigner(ResourceReference theValue) {
|
||||
myAssigner = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if <code>this</code> identifier has the same {@link IdentifierDt#getValue() value} and {@link IdentifierDt#getSystem() system} (as compared by simple equals comparison). Does not
|
||||
* compare other values (e.g. {@link IdentifierDt#getUse() use}) or any extensions.
|
||||
*/
|
||||
public boolean matchesSystemAndValue(IdentifierDt theIdentifier) {
|
||||
if (theIdentifier == null) {
|
||||
return false;
|
||||
}
|
||||
return getValue().equals(theIdentifier.getValue()) && getSystem().equals(theIdentifier.getSystem());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of this <code>IdentifierDt</code> using the <b>token</b> format. This
|
||||
* format is used in HTTP queries as a parameter format.
|
||||
*
|
||||
* @see See FHIR specification
|
||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search Parameter Types</a>
|
||||
* for information on the <b>token</b> format
|
||||
*/
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
int barIndex = theParameter.indexOf('|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(new UriDt(theParameter.substring(0, barIndex)));
|
||||
setValue(theParameter.substring(barIndex + 1));
|
||||
} else {
|
||||
setValue(theParameter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package ca.uhn.fhir.model.primitive;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
|
||||
|
@ -17,4 +20,14 @@ public class InstantDt extends BaseDateTimeDt {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this instant to the current time (from the system clock)
|
||||
* and the local/default timezone (as retrieved using {@link TimeZone#getDefault()}. This
|
||||
* TimeZone is generally obtained from the underlying OS.
|
||||
*/
|
||||
public void setToCurrentTimeInLocalTimeZone() {
|
||||
setValue(new Date());
|
||||
setTimeZone(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,5 +60,30 @@ public class StringDt extends BaseElement implements IPrimitiveDatatype<String>
|
|||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
StringDt other = (StringDt) obj;
|
||||
if (myValue == null) {
|
||||
if (other.myValue != null)
|
||||
return false;
|
||||
} else if (!myValue.equals(other.myValue))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.net.URISyntaxException;
|
|||
import ca.uhn.fhir.model.api.BaseElement;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
@DatatypeDef(name = "uri")
|
||||
|
@ -13,6 +14,21 @@ public class UriDt extends BaseElement implements IPrimitiveDatatype<URI> {
|
|||
|
||||
private URI myValue;
|
||||
|
||||
/**
|
||||
* Create a new String
|
||||
*/
|
||||
public UriDt() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new String
|
||||
*/
|
||||
@SimpleSetter
|
||||
public UriDt(@SimpleSetter.Parameter(name="theUri") String theValue) {
|
||||
setValueAsString(theValue);
|
||||
}
|
||||
|
||||
public URI getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
@ -43,4 +59,29 @@ public class UriDt extends BaseElement implements IPrimitiveDatatype<URI> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
UriDt other = (UriDt) obj;
|
||||
if (myValue == null) {
|
||||
if (other.myValue != null)
|
||||
return false;
|
||||
} else if (!myValue.equals(other.myValue))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -292,6 +292,8 @@ class ParserState<T extends IElement> {
|
|||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("entry".equals(theLocalPart) && verifyNamespace(XmlParser.ATOM_NS, theNamespaceURI)) {
|
||||
push(new AtomEntryState(myInstance));
|
||||
} else if (theLocalPart.equals("published")) {
|
||||
push(new AtomPrimitiveState(myInstance.getPublished()));
|
||||
} else if (theLocalPart.equals("title")) {
|
||||
push(new AtomPrimitiveState(myInstance.getTitle()));
|
||||
} else if ("id".equals(theLocalPart)) {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -71,11 +73,83 @@ public class XmlParser {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
|
||||
XMLStreamWriter eventWriter;
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
private <T extends IElement> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState) {
|
||||
try {
|
||||
eventWriter = myXmlOutputFactory.createXMLStreamWriter(stringWriter);
|
||||
while (streamReader.hasNext()) {
|
||||
XMLEvent nextEvent = streamReader.nextEvent();
|
||||
try {
|
||||
if (nextEvent.isStartElement()) {
|
||||
StartElement elem = nextEvent.asStartElement();
|
||||
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
|
||||
if ("extension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue());
|
||||
} else {
|
||||
|
||||
String elementName = elem.getName().getLocalPart();
|
||||
parserState.enteringNewElement(namespaceURI, elementName);
|
||||
|
||||
}
|
||||
|
||||
for (@SuppressWarnings("unchecked")
|
||||
Iterator<Attribute> iter = elem.getAttributes(); iter.hasNext();) {
|
||||
Attribute next = iter.next();
|
||||
// if
|
||||
// (next.getName().getLocalPart().equals("value")) {
|
||||
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
||||
// }
|
||||
}
|
||||
|
||||
} else if (nextEvent.isAttribute()) {
|
||||
Attribute elem = (Attribute) nextEvent;
|
||||
String name = (elem.getName().getLocalPart());
|
||||
parserState.attributeValue(name, elem.getValue());
|
||||
} else if (nextEvent.isEndElement()) {
|
||||
EndElement elem = nextEvent.asEndElement();
|
||||
|
||||
String name = elem.getName().getLocalPart();
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
// if (!FHIR_NS.equals(namespaceURI) &&
|
||||
// !XHTML_NS.equals(namespaceURI)) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
parserState.endingElement(elem);
|
||||
if (parserState.isComplete()) {
|
||||
return parserState.getObject();
|
||||
}
|
||||
} else if (nextEvent.isCharacters()) {
|
||||
parserState.string(nextEvent.asCharacters().getData());
|
||||
}
|
||||
|
||||
parserState.xmlEvent(nextEvent);
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new DataFormatException("DataFormatException at [" + nextEvent.getLocation().toString() + "]: "+e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
encodeBundleToWriter(theBundle, stringWriter);
|
||||
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) {
|
||||
try {
|
||||
XMLStreamWriter eventWriter;
|
||||
eventWriter = myXmlOutputFactory.createXMLStreamWriter(theWriter);
|
||||
eventWriter = decorateStreamWriter(eventWriter);
|
||||
|
||||
eventWriter.writeStartElement("feed");
|
||||
|
@ -91,10 +165,10 @@ public class XmlParser {
|
|||
writeAtomLink(eventWriter, "last", theBundle.getLinkLast());
|
||||
writeAtomLink(eventWriter, "fhir-base", theBundle.getLinkBase());
|
||||
|
||||
if (theBundle.getTotalResults() != null) {
|
||||
if (theBundle.getTotalResults().getValue() != null) {
|
||||
eventWriter.writeStartElement("os", OPENSEARCH_NS, "totalResults");
|
||||
eventWriter.writeNamespace("os", OPENSEARCH_NS);
|
||||
eventWriter.writeStartElement(OPENSEARCH_NS, "totalResults");
|
||||
eventWriter.writeCharacters(theBundle.getTotalResults().toString());
|
||||
eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
@ -105,6 +179,7 @@ public class XmlParser {
|
|||
eventWriter.writeStartElement("author");
|
||||
writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
|
||||
writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
|
||||
eventWriter.writeEndElement();
|
||||
}
|
||||
|
||||
for (BundleEntry nextEntry : theBundle.getEntries()) {
|
||||
|
@ -114,7 +189,7 @@ public class XmlParser {
|
|||
eventWriter.writeAttribute("type", "text/xml");
|
||||
|
||||
IResource resource = nextEntry.getResource();
|
||||
encodeResourceToStreamWriter(resource, eventWriter);
|
||||
encodeResourceToXmlStreamWriter(resource, eventWriter);
|
||||
|
||||
eventWriter.writeEndElement(); // content
|
||||
eventWriter.writeEndElement(); // entry
|
||||
|
@ -125,10 +200,10 @@ public class XmlParser {
|
|||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean encodeChildElementToStreamWriter(XMLStreamWriter theEventWriter, IElement nextValue, String childName, BaseRuntimeElementDefinition<?> childDef, String theExtensionUrl) throws XMLStreamException, DataFormatException {
|
||||
switch (childDef.getChildType()) {
|
||||
case PRIMITIVE_DATATYPE: {
|
||||
|
@ -261,7 +336,25 @@ public class XmlParser {
|
|||
}
|
||||
}
|
||||
|
||||
public void encodeResourceToStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException {
|
||||
public String encodeResourceToString(IResource theResource) throws DataFormatException {
|
||||
Writer stringWriter = new StringWriter();
|
||||
encodeResourceToWriter(theResource, stringWriter);
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
public void encodeResourceToWriter(IResource theResource, Writer stringWriter) {
|
||||
XMLStreamWriter eventWriter;
|
||||
try {
|
||||
eventWriter = myXmlOutputFactory.createXMLStreamWriter(stringWriter);
|
||||
eventWriter = decorateStreamWriter(eventWriter);
|
||||
|
||||
encodeResourceToXmlStreamWriter(theResource, eventWriter);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException {
|
||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||
eventWriter.writeStartElement(resDef.getName());
|
||||
eventWriter.writeDefaultNamespace(FHIR_NS);
|
||||
|
@ -272,21 +365,6 @@ public class XmlParser {
|
|||
eventWriter.close();
|
||||
}
|
||||
|
||||
public String encodeResourceToString(IResource theResource) throws DataFormatException {
|
||||
XMLStreamWriter eventWriter;
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
eventWriter = myXmlOutputFactory.createXMLStreamWriter(stringWriter);
|
||||
eventWriter = decorateStreamWriter(eventWriter);
|
||||
|
||||
encodeResourceToStreamWriter(theResource, eventWriter);
|
||||
} catch (XMLStreamException e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
private void encodeXhtml(XhtmlDt theDt, XMLStreamWriter theEventWriter) throws XMLStreamException {
|
||||
if (theDt == null || theDt.getValue() == null) {
|
||||
return;
|
||||
|
@ -359,19 +437,6 @@ public class XmlParser {
|
|||
}
|
||||
}
|
||||
|
||||
public IResource parseResource(String theXml) throws ConfigurationException, DataFormatException {
|
||||
XMLEventReader streamReader;
|
||||
try {
|
||||
streamReader = myXmlInputFactory.createXMLEventReader(new StringReader(theXml));
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
} catch (FactoryConfigurationError e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
|
||||
return parseResource(streamReader);
|
||||
}
|
||||
|
||||
public Bundle parseBundle(String theXml) throws ConfigurationException, DataFormatException {
|
||||
XMLEventReader streamReader;
|
||||
try {
|
||||
|
@ -390,77 +455,24 @@ public class XmlParser {
|
|||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
public IResource parseResource(String theXml) throws ConfigurationException, DataFormatException {
|
||||
XMLEventReader streamReader;
|
||||
try {
|
||||
streamReader = myXmlInputFactory.createXMLEventReader(new StringReader(theXml));
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
} catch (FactoryConfigurationError e) {
|
||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||
}
|
||||
|
||||
return parseResource(streamReader);
|
||||
}
|
||||
|
||||
public IResource parseResource(XMLEventReader theStreamReader) {
|
||||
ParserState<IResource> parserState = ParserState.getPreResourceInstance(myContext);
|
||||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
private <T extends IElement> T doXmlLoop(XMLEventReader streamReader, ParserState<T> parserState) {
|
||||
try {
|
||||
while (streamReader.hasNext()) {
|
||||
XMLEvent nextEvent = streamReader.nextEvent();
|
||||
try {
|
||||
if (nextEvent.isStartElement()) {
|
||||
StartElement elem = nextEvent.asStartElement();
|
||||
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
|
||||
if ("extension".equals(elem.getName().getLocalPart())) {
|
||||
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
|
||||
if (urlAttr == null || isBlank(urlAttr.getValue())) {
|
||||
throw new DataFormatException("Extension element has no 'url' attribute");
|
||||
}
|
||||
parserState.enteringNewElementExtension(elem, urlAttr.getValue());
|
||||
} else {
|
||||
|
||||
String elementName = elem.getName().getLocalPart();
|
||||
parserState.enteringNewElement(namespaceURI, elementName);
|
||||
|
||||
}
|
||||
|
||||
for (@SuppressWarnings("unchecked")
|
||||
Iterator<Attribute> iter = elem.getAttributes(); iter.hasNext();) {
|
||||
Attribute next = iter.next();
|
||||
// if
|
||||
// (next.getName().getLocalPart().equals("value")) {
|
||||
parserState.attributeValue(next.getName().getLocalPart(), next.getValue());
|
||||
// }
|
||||
}
|
||||
|
||||
} else if (nextEvent.isAttribute()) {
|
||||
Attribute elem = (Attribute) nextEvent;
|
||||
String name = (elem.getName().getLocalPart());
|
||||
parserState.attributeValue(name, elem.getValue());
|
||||
} else if (nextEvent.isEndElement()) {
|
||||
EndElement elem = nextEvent.asEndElement();
|
||||
|
||||
String name = elem.getName().getLocalPart();
|
||||
String namespaceURI = elem.getName().getNamespaceURI();
|
||||
// if (!FHIR_NS.equals(namespaceURI) &&
|
||||
// !XHTML_NS.equals(namespaceURI)) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
parserState.endingElement(elem);
|
||||
if (parserState.isComplete()) {
|
||||
return parserState.getObject();
|
||||
}
|
||||
} else if (nextEvent.isCharacters()) {
|
||||
parserState.string(nextEvent.asCharacters().getData());
|
||||
}
|
||||
|
||||
parserState.xmlEvent(nextEvent);
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new DataFormatException("DataFormatException at [" + nextEvent.getLocation().toString() + "]: "+e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (XMLStreamException e) {
|
||||
throw new DataFormatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAtomLink(XMLStreamWriter theEventWriter, String theRel, StringDt theStringDt) throws XMLStreamException {
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
theEventWriter.writeStartElement("link");
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String CT_FHIR_XML = "application/xml+fhir";
|
||||
public static final String PARAM_FORMAT = "_format";
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
public enum EncodingUtil {
|
||||
|
||||
XML, JSON
|
||||
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.ws.exceptions.InternalErrorException;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
|
@ -7,6 +11,7 @@ public class Parameter {
|
|||
private String name;
|
||||
private boolean required;
|
||||
private Class<?> type;
|
||||
private IParser parser;
|
||||
|
||||
public Parameter(){}
|
||||
|
||||
|
@ -19,8 +24,25 @@ public class Parameter {
|
|||
return type;
|
||||
}
|
||||
|
||||
public void setType(Class<?> type) {
|
||||
public void setType(final Class<?> type) {
|
||||
this.type = type;
|
||||
if (IdentifierDt.class.isAssignableFrom(type)) {
|
||||
this.parser = new IParser() {
|
||||
@Override
|
||||
public Object parse(String theString) throws InternalErrorException {
|
||||
IdentifierDt dt;
|
||||
try {
|
||||
dt = (IdentifierDt) type.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
dt.setValueAsQueryToken(theString);
|
||||
return dt;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new ConfigurationException("Unsupported data type for parameter: " + type.getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -38,4 +60,14 @@ public class Parameter {
|
|||
public void setRequired(boolean required) {
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public Object parse(String theString) throws InternalErrorException {
|
||||
return parser.parse(theString);
|
||||
}
|
||||
|
||||
private interface IParser
|
||||
{
|
||||
Object parse(String theString) throws InternalErrorException;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,18 +4,20 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class Resource {
|
||||
|
||||
private String resourceName;
|
||||
private Class resourceClass;
|
||||
private List<ResourceMethod> methods = new ArrayList<ResourceMethod>();
|
||||
private IResourceProvider<? extends IResource> resourceProvider;
|
||||
|
||||
public Resource() {}
|
||||
|
||||
public Resource(String resourceName, Class resourceClass, List<ResourceMethod> methods) {
|
||||
public Resource(String resourceName, List<ResourceMethod> methods) {
|
||||
this.resourceName = resourceName;
|
||||
this.methods = methods;
|
||||
}
|
||||
|
@ -29,13 +31,6 @@ public class Resource {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Class getResourceClass() {
|
||||
return resourceClass;
|
||||
}
|
||||
|
||||
public void setResourceClass(Class resourceClass) {
|
||||
this.resourceClass = resourceClass;
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return resourceName;
|
||||
|
@ -55,6 +50,7 @@ public class Resource {
|
|||
|
||||
public void addMethod(ResourceMethod method) {
|
||||
this.methods.add(method);
|
||||
method.setResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,4 +64,12 @@ public class Resource {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void setResourceProvider(IResourceProvider<? extends IResource> theProvider) {
|
||||
resourceProvider = theProvider;
|
||||
}
|
||||
|
||||
public IResourceProvider<? extends IResource> getResourceProvider() {
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.ws.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.ws.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.ws.exceptions.MethodNotFoundException;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
|
@ -21,9 +30,10 @@ public class ResourceMethod {
|
|||
DELETE
|
||||
}
|
||||
|
||||
RequestType requestType;
|
||||
List<Parameter> parameters;
|
||||
Method method;
|
||||
private RequestType requestType;
|
||||
private List<Parameter> parameters;
|
||||
private Method method;
|
||||
private Resource resource;
|
||||
|
||||
public ResourceMethod() {}
|
||||
|
||||
|
@ -36,7 +46,7 @@ public class ResourceMethod {
|
|||
this.resourceType = resourceType;
|
||||
}
|
||||
|
||||
public Class getResourceType() throws IllegalAccessException, InstantiationException {
|
||||
public Class getResourceType() {
|
||||
return resourceType.getClass();
|
||||
}
|
||||
|
||||
|
@ -76,19 +86,44 @@ public class ResourceMethod {
|
|||
return methodParamsTemp.containsAll(parameterNames);
|
||||
}
|
||||
|
||||
public IResource invoke(Map<String,String> parameterValues) {
|
||||
public List<IResource> invoke(IResourceProvider theResourceProvider, Map<String,String[]> parameterValues) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] params = new Object[parameters.size()];
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
Parameter param = parameters.get(i);
|
||||
String value = parameterValues.get(param.getName());
|
||||
if (null != value) {
|
||||
//TODO
|
||||
//param.getType().newInstance().getClass();
|
||||
String[] value = parameterValues.get(param.getName());
|
||||
if (value == null || value.length == 0 || StringUtils.isBlank(value[0])) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
params[i] = null;
|
||||
if (value.length > 1) {
|
||||
throw new InvalidRequestException("Multiple values specified for parameter: " + param.getName());
|
||||
}
|
||||
params[i] = param.parse(value[0]);
|
||||
}
|
||||
return null;
|
||||
|
||||
Object response;
|
||||
try {
|
||||
response = this.method.invoke(theResourceProvider, params);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
return Collections.emptyList();
|
||||
}else if (response instanceof IResource) {
|
||||
return Collections.singletonList((IResource)response);
|
||||
} else if (response instanceof Collection) {
|
||||
List<IResource> retVal = new ArrayList<>();
|
||||
for (Object next : ((Collection<?>)response)) {
|
||||
retVal.add((IResource) next);
|
||||
}
|
||||
return retVal;
|
||||
} else {
|
||||
throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setResource(Resource theResource) {
|
||||
this.resource = theResource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
public @interface ResourceName {
|
||||
String value();
|
||||
}
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.ws;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
|
@ -11,19 +12,24 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.parser.XmlParser;
|
||||
import ca.uhn.fhir.ws.exceptions.AbstractResponseException;
|
||||
import ca.uhn.fhir.ws.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.ws.exceptions.MethodNotFoundException;
|
||||
import ca.uhn.fhir.ws.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.ws.operations.DELETE;
|
||||
import ca.uhn.fhir.ws.operations.GET;
|
||||
import ca.uhn.fhir.ws.operations.POST;
|
||||
|
@ -33,46 +39,18 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
|
||||
|
||||
// map of request handler resources keyed by resource name
|
||||
private Map<String, Resource> resources = new HashMap<String, Resource>();
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
private Map<Class<? extends IResource>, IResourceProvider<?>> myTypeToProvider = new HashMap<Class<? extends IResource>, IResourceProvider<?>>();
|
||||
|
||||
public abstract Collection<IResourceProvider<?>> getResourceProviders();
|
||||
// map of request handler resources keyed by resource name
|
||||
private Map<String, Resource> resources = new HashMap<String, Resource>();
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
try {
|
||||
ourLog.info("Initializing HAPI FHIR restful server");
|
||||
private boolean addResourceMethod(Resource resource, Method method) throws Exception {
|
||||
|
||||
Collection<IResourceProvider<?>> resourceProvider = getResourceProviders();
|
||||
for (IResourceProvider<?> nextProvider : resourceProvider) {
|
||||
if (myTypeToProvider.containsKey(nextProvider.getResourceType())) {
|
||||
throw new ServletException("Multiple providers for type: " + nextProvider.getResourceType().getCanonicalName());
|
||||
}
|
||||
myTypeToProvider.put(nextProvider.getResourceType(), nextProvider);
|
||||
}
|
||||
|
||||
ourLog.info("Got {} resource providers",myTypeToProvider.size());
|
||||
|
||||
myFhirContext = new FhirContext(myTypeToProvider.keySet());
|
||||
|
||||
findResourceMethods(nextProvider.getClass());
|
||||
|
||||
|
||||
} catch (Exception ex) {
|
||||
ourLog.error("An error occurred while loading request handlers!", ex);
|
||||
throw new ServletException("Failed to initialize FHIR Restful server", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void addResourceMethod(Resource resource, Method method) throws Exception {
|
||||
|
||||
Class<?>[] params = method.getParameterTypes();
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
rm.setResourceType(method.getReturnType());
|
||||
|
||||
// each operation name must have a request type annotation and be unique
|
||||
if (null != method.getAnnotation(GET.class)) {
|
||||
|
@ -83,27 +61,23 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
rm.setRequestType(ResourceMethod.RequestType.POST);
|
||||
} else if (null != method.getAnnotation(DELETE.class)) {
|
||||
rm.setRequestType(ResourceMethod.RequestType.DELETE);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
rm.setMethod(method);
|
||||
rm.setResourceType(method.getReturnType());
|
||||
rm.setParameters(Util.getResourceParameters(method));
|
||||
|
||||
resource.addMethod(rm);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void findResourceMethods(Class<? extends IResourceProvider> theClass1) throws Exception {
|
||||
for (Method m : theClass1.getDeclaredMethods()) {
|
||||
if (Modifier.isPublic(m.getModifiers())) {
|
||||
|
||||
String resourceName = Util.getResourceName(m);
|
||||
Resource r = resources.get(resourceName);
|
||||
if (null == r) {
|
||||
r = new Resource();
|
||||
r.setResourceName(resourceName);
|
||||
resources.put(resourceName, r);
|
||||
}
|
||||
addResourceMethod(r, m);
|
||||
|
||||
ourLog.debug("found handler: " + m.getName());
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
private EncodingUtil determineResponseEncoding(Map<String, String[]> theParams) {
|
||||
String[] format = theParams.remove(Constants.PARAM_FORMAT);
|
||||
// TODO: handle this once we support JSON
|
||||
return EncodingUtil.XML;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,27 +100,155 @@ public abstract class RestfulServer extends HttpServlet {
|
|||
handleRequest(ResourceMethod.RequestType.PUT, request, response);
|
||||
}
|
||||
|
||||
protected void handleRequest(ResourceMethod.RequestType requestType, HttpServletRequest request, HttpServletResponse response) {
|
||||
try {
|
||||
private void findResourceMethods(IResourceProvider<? extends IResource> theProvider) throws Exception {
|
||||
|
||||
response.setContentType(request.getHeader("Accept"));
|
||||
String resourceName = request.getRequestURI();
|
||||
Map<String, String> params = Util.getQueryParams(request.getQueryString());
|
||||
Class<? extends IResource> resourceType = theProvider.getResourceType();
|
||||
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(resourceType);
|
||||
|
||||
Resource resource = resources.get(resourceName);
|
||||
if (null == resource)
|
||||
throw new MethodNotFoundException("No resource available for " + resourceName);
|
||||
Resource r = new Resource();
|
||||
r.setResourceProvider(theProvider);
|
||||
r.setResourceName(definition.getName());
|
||||
resources.put(definition.getName(), r);
|
||||
|
||||
ResourceMethod resourceMethod = resource.getMethod(params.keySet());
|
||||
if (null == resourceMethod)
|
||||
throw new MethodNotFoundException("No resource method available for the supplied parameters " + params);
|
||||
Class<?> clazz = theProvider.getClass();
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (Modifier.isPublic(m.getModifiers())) {
|
||||
|
||||
FhirContext ctx = new FhirContext(resourceMethod.getResourceType());
|
||||
XmlParser p = new XmlParser(ctx);
|
||||
response.getWriter().write(p.encodeResourceToString(resourceMethod.invoke(params)));
|
||||
} catch (Throwable t) {
|
||||
// TODO: handle errors
|
||||
boolean foundMethod = addResourceMethod(r, m);
|
||||
if (foundMethod) {
|
||||
ourLog.debug("found handler: " + m.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Collection<IResourceProvider<?>> getResourceProviders();
|
||||
|
||||
protected void handleRequest(ResourceMethod.RequestType requestType, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
try {
|
||||
String resourceName = null;
|
||||
Long identity = null;
|
||||
|
||||
Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
|
||||
EncodingUtil responseEncoding = determineResponseEncoding(params);
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(request.getRequestURI(), "/");
|
||||
if (!tok.hasMoreTokens()) {
|
||||
throw new MethodNotFoundException("No resource name specified");
|
||||
}
|
||||
resourceName = tok.nextToken();
|
||||
|
||||
Resource resourceBinding = resources.get(resourceName);
|
||||
if (resourceBinding == null) {
|
||||
throw new MethodNotFoundException("Unknown resource type: " + resourceBinding);
|
||||
}
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String identityString = tok.nextToken();
|
||||
try {
|
||||
identity = Long.parseLong(identityString);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new NumberFormatException("Invalid identity token: " + identity);
|
||||
}
|
||||
}
|
||||
|
||||
if (identity != null && !tok.hasMoreTokens()) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
IResource resource = resourceBinding.getResourceProvider().getResourceById(identity);
|
||||
if (resource == null) {
|
||||
throw new ResourceNotFoundException(identity);
|
||||
}
|
||||
streamResponseAsResource(response, resource, resourceBinding, responseEncoding);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceMethod resourceMethod = resourceBinding.getMethod(params.keySet());
|
||||
if (null == resourceMethod) {
|
||||
throw new MethodNotFoundException("No resource method available for the supplied parameters " + params);
|
||||
}
|
||||
|
||||
List<IResource> result = resourceMethod.invoke(resourceBinding.getResourceProvider(), params);
|
||||
streamResponseAsBundle(response, result, responseEncoding);
|
||||
// resourceMethod.get
|
||||
|
||||
} catch (AbstractResponseException e) {
|
||||
|
||||
response.setStatus(e.getStatusCode());
|
||||
response.setContentType("text/plain");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.getWriter().append(e.getMessage());
|
||||
response.getWriter().close();
|
||||
|
||||
} catch (Throwable t) {
|
||||
// TODO: handle this better
|
||||
ourLog.error("Failed to process invocation", t);
|
||||
throw new ServletException(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
try {
|
||||
ourLog.info("Initializing HAPI FHIR restful server");
|
||||
|
||||
Collection<IResourceProvider<?>> resourceProvider = getResourceProviders();
|
||||
for (IResourceProvider<?> nextProvider : resourceProvider) {
|
||||
if (myTypeToProvider.containsKey(nextProvider.getResourceType())) {
|
||||
throw new ServletException("Multiple providers for type: " + nextProvider.getResourceType().getCanonicalName());
|
||||
}
|
||||
myTypeToProvider.put(nextProvider.getResourceType(), nextProvider);
|
||||
}
|
||||
|
||||
ourLog.info("Got {} resource providers",myTypeToProvider.size());
|
||||
|
||||
myFhirContext = new FhirContext(myTypeToProvider.keySet());
|
||||
|
||||
for (IResourceProvider<?> provider : myTypeToProvider.values()) {
|
||||
findResourceMethods(provider);
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception ex) {
|
||||
ourLog.error("An error occurred while loading request handlers!", ex);
|
||||
throw new ServletException("Failed to initialize FHIR Restful server", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void streamResponseAsBundle(HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding) throws IOException {
|
||||
theHttpResponse.setStatus(200);
|
||||
theHttpResponse.setContentType(Constants.CT_FHIR_XML);
|
||||
theHttpResponse.setCharacterEncoding("UTF-8");
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.getAuthorName().setValue(getClass().getCanonicalName());
|
||||
bundle.getId().setValue(UUID.randomUUID().toString());
|
||||
bundle.getPublished().setToCurrentTimeInLocalTimeZone();
|
||||
|
||||
for (IResource next : theResult) {
|
||||
BundleEntry entry = new BundleEntry();
|
||||
bundle.getEntries().add(entry);
|
||||
|
||||
entry.setResource(next);
|
||||
}
|
||||
|
||||
bundle.getTotalResults().setValue(theResult.size());
|
||||
|
||||
PrintWriter writer = theHttpResponse.getWriter();
|
||||
myFhirContext.newXmlParser().encodeBundleToWriter(bundle, writer);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private void streamResponseAsResource(HttpServletResponse theHttpResponse, IResource theResource, Resource theResourceBinding, EncodingUtil theResponseEncoding) throws IOException {
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
theHttpResponse.setContentType(Constants.CT_FHIR_XML);
|
||||
theHttpResponse.setCharacterEncoding("UTF-8");
|
||||
|
||||
PrintWriter writer = theHttpResponse.getWriter();
|
||||
myFhirContext.newXmlParser().encodeResourceToWriter(theResource, writer);
|
||||
writer.close();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ public class Util {
|
|||
public static Map<String, String> getQueryParams(String query) throws UnsupportedEncodingException {
|
||||
try {
|
||||
|
||||
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
for (String param : query.split("&")) {
|
||||
String[] pair = param.split("=");
|
||||
|
@ -33,13 +34,6 @@ public class Util {
|
|||
}
|
||||
}
|
||||
|
||||
public static String getResourceName(Method method) {
|
||||
ResourceName resourceNameAnnotation = method.getAnnotation(ResourceName.class);
|
||||
if (null != resourceNameAnnotation) {
|
||||
return resourceNameAnnotation.value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Parameter> getResourceParameters(Method method) {
|
||||
List<Parameter> parameters = new ArrayList<Parameter>();
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package ca.uhn.fhir.ws.exceptions;
|
||||
|
||||
public abstract class AbstractResponseException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int myStatusCode;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theStatusCode
|
||||
* The HTTP status code corresponding to this problem
|
||||
* @param theMessage
|
||||
* The message
|
||||
*/
|
||||
public AbstractResponseException(int theStatusCode, String theMessage) {
|
||||
super(theMessage);
|
||||
myStatusCode = theStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theStatusCode
|
||||
* The HTTP status code corresponding to this problem
|
||||
* @param theCause
|
||||
* The underlying cause exception
|
||||
*/
|
||||
public AbstractResponseException(int theStatusCode, Throwable theCause) {
|
||||
super(theCause.toString(), theCause);
|
||||
myStatusCode = theStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP status code corresponding to this problem
|
||||
*/
|
||||
public int getStatusCode() {
|
||||
return myStatusCode;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ca.uhn.fhir.ws.exceptions;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
public class ConfigurationException extends ServletException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package ca.uhn.fhir.ws.exceptions;
|
||||
|
||||
public class InternalErrorException extends AbstractResponseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InternalErrorException(String theMessage) {
|
||||
super(500, theMessage);
|
||||
}
|
||||
|
||||
public InternalErrorException(Throwable theCause) {
|
||||
super(500, theCause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.ws.exceptions;
|
||||
|
||||
public class InvalidRequestException extends AbstractResponseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidRequestException(String theMessage) {
|
||||
super(400, theMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,10 @@ package ca.uhn.fhir.ws.exceptions;
|
|||
/**
|
||||
* Created by dsotnikov on 2/27/2014.
|
||||
*/
|
||||
public class MethodNotFoundException extends Exception {
|
||||
public MethodNotFoundException(String error) { super(error); }
|
||||
public class MethodNotFoundException extends AbstractResponseException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MethodNotFoundException(String error) {
|
||||
super(404, error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.ws.exceptions;
|
||||
|
||||
public class ResourceNotFoundException extends AbstractResponseException {
|
||||
|
||||
public ResourceNotFoundException(long theId) {
|
||||
super(404, "Resource " + theId + " is not known");
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -2,8 +2,12 @@ package ca.uhn.fhir.context;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
public class ModelScannerTest {
|
||||
|
@ -11,7 +15,6 @@ public class ModelScannerTest {
|
|||
@Test
|
||||
public void testScanExtensionTypes() throws DataFormatException {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ModelScanner scanner = new ModelScanner(ResourceWithExtensionsA.class);
|
||||
RuntimeResourceDefinition def = (RuntimeResourceDefinition) scanner.getClassToElementDefinitions().get(ResourceWithExtensionsA.class);
|
||||
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
|
||||
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.UriDt;
|
||||
import ca.uhn.fhir.ws.operations.GET;
|
||||
import ca.uhn.fhir.ws.parameters.Required;
|
||||
|
||||
|
@ -9,11 +17,48 @@ import ca.uhn.fhir.ws.parameters.Required;
|
|||
*/
|
||||
public class DummyPatientResourceProvider implements IResourceProvider<Patient> {
|
||||
|
||||
@GET
|
||||
@ResourceName(value="Patient")
|
||||
public Patient getPatient(@Required(name="mrn") String mrn) {
|
||||
return null;
|
||||
}
|
||||
private Map<Long, Patient> myIdToPatient = new HashMap<>();
|
||||
|
||||
public DummyPatientResourceProvider() {
|
||||
{
|
||||
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("00001");
|
||||
patient.getName().add(new HumanNameDt());
|
||||
patient.getName().get(0).addFamily("Test");
|
||||
patient.getName().get(0).addGiven("PatientOne");
|
||||
patient.setGender(new CodeableConceptDt());
|
||||
patient.getGender().setText("M");
|
||||
myIdToPatient.put(1L, 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.setGender(new CodeableConceptDt());
|
||||
patient.getGender().setText("F");
|
||||
myIdToPatient.put(2L, patient);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
public Patient getPatient(@Required(name = "identifier") IdentifierDt theIdentifier) {
|
||||
for (Patient next : myIdToPatient.values()) {
|
||||
for (IdentifierDt nextId : next.getIdentifier()) {
|
||||
if (nextId.matchesSystemAndValue(theIdentifier)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
|
@ -22,6 +67,6 @@ public class DummyPatientResourceProvider implements IResourceProvider<Patient>
|
|||
|
||||
@Override
|
||||
public Patient getResourceById(long theId) {
|
||||
return null;
|
||||
return myIdToPatient.get(theId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
|
@ -21,153 +16,115 @@ import org.apache.http.impl.conn.SchemeRegistryFactory;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.Before;
|
||||
import org.junit.AfterClass;
|
||||
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.resource.Patient;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class ResfulServerTest extends TestCase {
|
||||
public class ResfulServerTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResfulServerTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static DefaultHttpClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
/*
|
||||
* System.setProperty("java.naming.factory.initial",
|
||||
* "org.apache.naming.java.javaURLContextFactory");
|
||||
* System.setProperty("java.naming.factory.url.pkgs",
|
||||
* "org.apache.naming"); InitialContext context = new InitialContext();
|
||||
* //context.bind("java:comp", "env");
|
||||
* context.bind(context.composeName("java:comp", "env"),
|
||||
* "ca.uhn.rest.handlers");
|
||||
*
|
||||
* //Context subcontext = context.createSubcontext("java:comp/env");
|
||||
* //context.bind("java:comp/env/ca.uhn.rest.handlers", "ca.uhn.test");
|
||||
*
|
||||
* Context env = (Context) new InitialContext().lookup("java:comp/env");
|
||||
*
|
||||
* //System.out.println((String) env.lookup("ca.uhn.rest.handlers"));
|
||||
*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServlet() throws Exception {
|
||||
int port = RandomServerPortProvider.findFreePort();
|
||||
Server server = new Server(port);
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ServletHolder servletHolder = new ServletHolder(new DummyRestfulServer(patientProvider));
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/");
|
||||
server.setHandler(proxyHandler);
|
||||
server.start();
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(SchemeRegistryFactory.createDefault(), 5000, TimeUnit.MILLISECONDS);
|
||||
HttpClient client = new DefaultHttpClient(connectionManager);
|
||||
ourClient = new DefaultHttpClient(connectionManager);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + port + "/foo/bar?bar=123&more=params");
|
||||
httpPost.setEntity(new StringEntity("test", ContentType.create("application/json", "UTF-8")));
|
||||
HttpResponse status = client.execute(httpPost);
|
||||
ourCtx = new FhirContext(Patient.class);
|
||||
|
||||
ourLog.info("Response was: {}", status);
|
||||
}
|
||||
|
||||
// server.join();
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiredParamsMissing() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
public void testSearchByParamIdentifier() throws Exception {
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=urn:hapitest:mrns%7C00001");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
String responseContent = IOUtils.toString(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());
|
||||
|
||||
Patient patient = (Patient)bundle.getEntries().get(0).getResource();
|
||||
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
|
||||
assertEquals(false, rm.matches(inputParams)); // False
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiredParamsOnly() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
public void testGetById() throws Exception {
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
// HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/1");
|
||||
// httpPost.setEntity(new StringEntity("test", ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.debug("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Patient patient = (Patient) ourCtx.newXmlParser().parseResource(responseContent);
|
||||
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
|
||||
|
||||
/*
|
||||
* Different ID
|
||||
*/
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
|
||||
status = ourClient.execute(httpGet);
|
||||
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.debug("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
patient = (Patient) ourCtx.newXmlParser().parseResource(responseContent);
|
||||
assertEquals("PatientTwo", patient.getName().get(0).getGiven().get(0).getValue());
|
||||
|
||||
/*
|
||||
* Bad ID
|
||||
*/
|
||||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/9999999");
|
||||
status = ourClient.execute(httpGet);
|
||||
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.debug("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("mrn");
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedParams() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParams() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParamsWithExtra() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
inputParams.add("mrn");
|
||||
inputParams.add("foo");
|
||||
|
||||
assertEquals(false, rm.matches(inputParams)); // False
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
package ca.uhn.fhir.ws;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ResourceMethodTest {
|
||||
|
||||
@Test
|
||||
public void testRequiredParamsMissing() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
|
||||
assertEquals(false, rm.matches(inputParams)); // False
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiredParamsOnly() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("mrn");
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedParams() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParams() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
inputParams.add("mrn");
|
||||
|
||||
assertEquals(true, rm.matches(inputParams)); // True
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllParamsWithExtra() {
|
||||
ResourceMethod rm = new ResourceMethod();
|
||||
List<Parameter> methodParams = new ArrayList<Parameter>();
|
||||
|
||||
methodParams.add(new Parameter("firstName", false));
|
||||
methodParams.add(new Parameter("lastName", false));
|
||||
methodParams.add(new Parameter("mrn", true));
|
||||
|
||||
rm.setParameters(methodParams);
|
||||
|
||||
Set<String> inputParams = new HashSet<String>();
|
||||
inputParams.add("firstName");
|
||||
inputParams.add("lastName");
|
||||
inputParams.add("mrn");
|
||||
inputParams.add("foo");
|
||||
|
||||
assertEquals(false, rm.matches(inputParams)); // False
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.eclipse" additivity="false">
|
||||
</logger>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,54 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-test</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR Structures - DSTU (FHIR 0.80)</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<package>ca.uhn.fhir.model.dstu</package>
|
||||
<baseResourceNames>
|
||||
<baseResourceName>patient</baseResourceName>
|
||||
<baseResourceName>valueset</baseResourceName>
|
||||
<baseResourceName>organization</baseResourceName>
|
||||
<baseResourceName>device</baseResourceName>
|
||||
<baseResourceName>location</baseResourceName>
|
||||
<baseResourceName>practitioner</baseResourceName>
|
||||
</baseResourceNames>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -31,6 +31,41 @@ public class ${className}Dt extends BaseElement implements ICompositeDatatype {
|
|||
#childAccessors( $children )
|
||||
#childResourceBlocks($resourceBlockChildren)
|
||||
|
||||
#########################
|
||||
### Type-specific methods
|
||||
#########################
|
||||
#if ( ${className} == "Identifier" )
|
||||
/**
|
||||
* Returns true if <code>this</code> identifier has the same {@link IdentifierDt#getValue() value}
|
||||
* and {@link IdentifierDt#getSystem() system} (as compared by simple equals comparison).
|
||||
* Does not compare other values (e.g. {@link IdentifierDt#getUse() use}) or any extensions.
|
||||
*/
|
||||
public boolean matchesSystemAndValue(IdentifierDt theIdentifier) {
|
||||
if (theIdentifier == null) {
|
||||
return false;
|
||||
}
|
||||
return getValue().equals(theIdentifier.getValue()) && getSystem().equals(theIdentifier.getSystem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this <code>IdentifierDt</code> using the <b>token</b> format. This
|
||||
* format is used in HTTP queries as a parameter format.
|
||||
*
|
||||
* @see See FHIR specification
|
||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search Parameter Types</a>
|
||||
* for information on the <b>token</b> format
|
||||
*/
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
int barIndex = theParameter.indexOf('|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(new UriDt(theParameter.substring(0, barIndex)));
|
||||
setValue(theParameter.substring(barIndex + 1));
|
||||
} else {
|
||||
setValue(theParameter);
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
#childExtensionTypes( $childExtensionTypes )
|
||||
|
||||
}
|
Loading…
Reference in New Issue