234 lines
7.0 KiB
Java
Raw Normal View History

2014-02-18 08:26:49 -05:00
package ca.uhn.fhir.parser;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
2014-02-18 08:26:49 -05:00
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
2014-02-18 08:26:49 -05:00
import ca.uhn.fhir.context.RuntimeResourceDefinition;
2014-02-19 17:33:46 -05:00
import ca.uhn.fhir.context.RuntimeResourceReferenceDefinition;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.ICompositeElement;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
2014-02-18 08:26:49 -05:00
import ca.uhn.fhir.model.api.IResource;
2014-02-19 17:33:46 -05:00
import ca.uhn.fhir.model.api.ResourceReference;
2014-02-18 08:26:49 -05:00
class ParserState {
2014-02-19 17:33:46 -05:00
private enum ResourceReferenceSubState {
INITIAL, REFERENCE, DISPLAY
}
private class ResourceReferenceState extends BaseState {
private ResourceReferenceSubState mySubState;
private RuntimeResourceReferenceDefinition myDefinition;
private ResourceReference myInstance;
public ResourceReferenceState(RuntimeResourceReferenceDefinition theDefinition, ResourceReference theInstance) {
myDefinition=theDefinition;
myInstance = theInstance;
mySubState = ResourceReferenceSubState.INITIAL;
}
@Override
public void attributeValue(String theValue) throws DataFormatException {
switch (mySubState) {
case DISPLAY:
myInstance.setDisplay(theValue);
break;
case INITIAL:
throw new DataFormatException("Unexpected attribute: "+theValue);
case REFERENCE:
myInstance.setReference(theValue);
break;
}
}
@Override
public void enteringNewElement(String theLocalPart) throws DataFormatException {
switch (mySubState) {
case INITIAL:
if ("display".equals(theLocalPart)) {
mySubState = ResourceReferenceSubState.DISPLAY;
break;
} else if ("reference".equals(theLocalPart)) {
mySubState = ResourceReferenceSubState.REFERENCE;
break;
}
// ...else fall through...
case DISPLAY:
case REFERENCE:
throw new DataFormatException("Unexpected element: "+theLocalPart);
}
}
@Override
public void endingElement(String theLocalPart) {
mySubState=ResourceReferenceSubState.INITIAL;
}
}
2014-02-19 11:59:12 -05:00
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ParserState.class);
2014-02-18 08:26:49 -05:00
private FhirContext myContext;
2014-02-19 11:59:12 -05:00
2014-02-18 08:26:49 -05:00
private BaseState myState;
2014-02-19 11:59:12 -05:00
private Object myObject;
2014-02-18 08:26:49 -05:00
public ParserState(FhirContext theContext) {
2014-02-19 11:59:12 -05:00
myContext = theContext;
}
public void attributeValue(String theValue) throws DataFormatException {
myState.attributeValue(theValue);
}
public void enteringNewElement(String theLocalPart) throws DataFormatException {
myState.enteringNewElement(theLocalPart);
}
private void push(BaseState theState) {
theState.setStack(myState);
myState = theState;
}
private void setState(BaseState theState) {
myState = theState;
2014-02-18 08:26:49 -05:00
}
public static ParserState getResourceInstance(FhirContext theContext, String theLocalPart) throws DataFormatException {
2014-02-18 18:10:50 -05:00
BaseRuntimeElementDefinition<?> definition = theContext.getNameToResourceDefinition().get(theLocalPart);
2014-02-18 08:26:49 -05:00
if (!(definition instanceof RuntimeResourceDefinition)) {
throw new DataFormatException("Element '" + theLocalPart + "' is not a resource, expected a resource at this position");
}
2014-02-19 11:59:12 -05:00
2014-02-18 08:26:49 -05:00
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
IResource instance = def.newInstance();
2014-02-19 11:59:12 -05:00
2014-02-18 08:26:49 -05:00
ParserState retVal = new ParserState(theContext);
2014-02-19 11:59:12 -05:00
retVal.setState(retVal.new ContainerState(def, instance));
2014-02-18 08:26:49 -05:00
return retVal;
}
2014-02-19 11:59:12 -05:00
private abstract class BaseState {
private BaseState myStack;
2014-02-18 08:26:49 -05:00
2014-02-19 11:59:12 -05:00
public abstract void attributeValue(String theValue) throws DataFormatException;
2014-02-18 08:26:49 -05:00
2014-02-19 11:59:12 -05:00
public abstract void enteringNewElement(String theLocalPart) throws DataFormatException;
public void setStack(BaseState theState) {
myStack = theState;
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
public abstract void endingElement(String theLocalPart);
}
private class ContainerState extends BaseState {
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
private ICompositeElement myInstance;
2014-02-18 08:26:49 -05:00
2014-02-19 11:59:12 -05:00
public ContainerState(BaseRuntimeElementCompositeDefinition<?> theDef, ICompositeElement theInstance) {
myDefinition = theDef;
2014-02-18 08:26:49 -05:00
myInstance = theInstance;
}
2014-02-19 11:59:12 -05:00
@Override
public void attributeValue(String theValue) {
ourLog.debug("Ignoring attribute value: {}", theValue);
}
2014-02-18 08:26:49 -05:00
@Override
public void enteringNewElement(String theChildName) throws DataFormatException {
2014-02-19 11:59:12 -05:00
BaseRuntimeChildDefinition child = myDefinition.getChildByNameOrThrowDataFormatException(theChildName);
BaseRuntimeElementDefinition<?> target = child.getChildByName(theChildName);
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance();
child.getMutator().addValue(myInstance, newChildInstance);
ContainerState newState = new ContainerState(compositeTarget, newChildInstance);
push(newState);
2014-02-18 18:10:50 -05:00
break;
2014-02-19 11:59:12 -05:00
}
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveDatatype<?> newChildInstance = primitiveTarget.newInstance();
child.getMutator().addValue(myInstance, newChildInstance);
PrimitiveState newState = new PrimitiveState(primitiveTarget, newChildInstance);
push(newState);
break;
}
2014-02-19 17:33:46 -05:00
case RESOURCE_REF: {
RuntimeResourceReferenceDefinition resourceRefTarget = (RuntimeResourceReferenceDefinition) target;
ResourceReference newChildInstance = new ResourceReference();
child.getMutator().addValue(myInstance, newChildInstance);
ResourceReferenceState newState = new ResourceReferenceState(resourceRefTarget, newChildInstance);
push(newState);
2014-02-18 18:10:50 -05:00
break;
2014-02-19 11:59:12 -05:00
}
2014-02-19 17:33:46 -05:00
case RESOURCE:
2014-02-18 18:10:50 -05:00
default:
2014-02-19 17:33:46 -05:00
throw new DataFormatException("Illegal resource position: " + target.getChildType());
2014-02-19 11:59:12 -05:00
}
}
@Override
public void endingElement(String theLocalPart) {
pop();
if (myState == null) {
myObject = myInstance;
2014-02-18 18:10:50 -05:00
}
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
private class PrimitiveState extends BaseState {
private RuntimePrimitiveDatatypeDefinition myDefinition;
private IPrimitiveDatatype<?> myInstance;
public PrimitiveState(RuntimePrimitiveDatatypeDefinition theDefinition, IPrimitiveDatatype<?> theInstance) {
super();
myDefinition = theDefinition;
myInstance = theInstance;
}
@Override
public void attributeValue(String theValue) throws DataFormatException {
myInstance.setValueAsString(theValue);
}
@Override
public void enteringNewElement(String theLocalPart) throws DataFormatException {
throw new Error("?? can this happen?"); // TODO: can this happen?
}
@Override
public void endingElement(String theLocalPart) {
pop();
}
}
public Object getObject() {
return myObject;
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
private void pop() {
myState = myState.myStack;
}
public boolean isComplete() {
return myObject != null;
}
public void endingElement(String theLocalPart) {
myState.endingElement(theLocalPart);
}
2014-02-18 08:26:49 -05:00
}