788 lines
24 KiB
Java
Raw Normal View History

2014-02-18 08:26:49 -05:00
package ca.uhn.fhir.parser;
2014-02-22 15:33:02 -05:00
import java.util.ArrayList;
import java.util.List;
2014-02-21 21:06:11 -05:00
import javax.xml.namespace.QName;
2014-02-21 21:06:11 -05:00
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import com.ctc.wstx.sw.BaseStreamWriter;
2014-02-18 08:26:49 -05:00
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-23 18:13:59 -05:00
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
2014-02-22 15:33:02 -05:00
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition;
2014-02-20 12:13:05 -05:00
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
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-26 17:13:49 -05:00
import ca.uhn.fhir.model.api.Bundle;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.ICompositeElement;
2014-02-22 15:33:02 -05:00
import ca.uhn.fhir.model.api.IElement;
2014-02-19 11:59:12 -05:00
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
2014-02-27 07:39:36 -05:00
import ca.uhn.fhir.model.api.IResource;
2014-02-20 12:13:05 -05:00
import ca.uhn.fhir.model.api.IResourceBlock;
2014-02-26 17:13:49 -05:00
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
2014-02-19 17:33:46 -05:00
import ca.uhn.fhir.model.api.ResourceReference;
2014-02-22 15:33:02 -05:00
import ca.uhn.fhir.model.api.UndeclaredExtension;
2014-02-26 17:13:49 -05:00
import ca.uhn.fhir.model.primitive.StringDt;
2014-02-24 11:46:08 -05:00
import ca.uhn.fhir.model.primitive.XhtmlDt;
2014-02-18 08:26:49 -05:00
2014-02-27 07:39:36 -05:00
class ParserState<T extends IElement> {
2014-02-18 08:26:49 -05:00
2014-02-21 21:06:11 -05:00
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ParserState.class);
2014-02-19 17:33:46 -05:00
2014-02-21 21:06:11 -05:00
private FhirContext myContext;
2014-02-27 07:39:36 -05:00
private T myObject;
2014-02-21 21:06:11 -05:00
private BaseState myState;
2014-02-19 17:33:46 -05:00
2014-02-26 17:13:49 -05:00
private ParserState(FhirContext theContext) {
2014-02-21 21:06:11 -05:00
myContext = theContext;
}
2014-02-19 17:33:46 -05:00
2014-02-21 21:06:11 -05:00
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
myState.attributeValue(theAttribute, theValue);
2014-02-19 17:33:46 -05:00
}
2014-02-21 21:06:11 -05:00
public void endingElement(EndElement theElem) throws DataFormatException {
myState.endingElement(theElem);
}
2014-02-19 11:59:12 -05:00
2014-02-21 21:06:11 -05:00
public void enteringNewElement(StartElement theElement, String theName) throws DataFormatException {
myState.enteringNewElement(theElement, theName);
}
2014-02-18 08:26:49 -05:00
2014-02-22 15:33:02 -05:00
public void enteringNewElementExtension(StartElement theElem, String theUrlAttr) {
myState.enteringNewElementExtension(theElem, theUrlAttr);
}
2014-02-27 07:39:36 -05:00
public T getObject() {
2014-02-21 21:06:11 -05:00
return myObject;
2014-02-19 11:59:12 -05:00
}
2014-02-21 21:06:11 -05:00
public boolean isComplete() {
return myObject != null;
2014-02-19 11:59:12 -05:00
}
2014-02-22 15:33:02 -05:00
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
myState.otherEvent(theEvent);
}
2014-02-21 21:06:11 -05:00
private void pop() {
myState = myState.myStack;
2014-02-26 17:13:49 -05:00
myState.wereBack();
2014-02-19 11:59:12 -05:00
}
private void push(BaseState theState) {
theState.setStack(myState);
myState = theState;
}
2014-02-27 07:39:36 -05:00
public static ParserState<IResource> getPreResourceInstance(FhirContext theContext) throws DataFormatException {
ParserState<IResource> retVal = new ParserState<IResource>(theContext);
2014-02-26 17:13:49 -05:00
retVal.push(retVal.new PreResourceState());
return retVal;
2014-02-18 08:26:49 -05:00
}
2014-02-27 07:39:36 -05:00
public static ParserState<Bundle> getPreAtomInstance(FhirContext theContext) throws DataFormatException {
ParserState<Bundle> retVal = new ParserState<Bundle>(theContext);
retVal.push(retVal.new PreAtomState());
return retVal;
}
private class AtomPrimitiveState extends BaseState {
2014-02-26 17:13:49 -05:00
private IPrimitiveDatatype<?> myPrimitive;
private String myData;
public AtomPrimitiveState(IPrimitiveDatatype<?> thePrimitive) {
myPrimitive = thePrimitive;
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-26 17:13:49 -05:00
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
// ignore
}
2014-02-19 11:59:12 -05:00
2014-02-26 17:13:49 -05:00
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
myPrimitive.setValueAsString(myData);
pop();
}
2014-02-19 11:59:12 -05:00
2014-02-26 17:13:49 -05:00
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
throw new DataFormatException("Unexpected nested element in atom tag ");
}
@Override
protected IElement getCurrentElement() {
return null;
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
if (theEvent.isCharacters()) {
String data = theEvent.asCharacters().getData();
if (myData == null) {
myData = data;
} else {
2014-02-26 17:13:49 -05:00
// this shouldn't generally happen so it's ok that it's inefficient
myData = myData + data;
2014-02-26 17:13:49 -05:00
}
}
}
2014-02-18 08:26:49 -05:00
}
private class ExpectEndElementState extends BaseState {
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
throw new DataFormatException("Found unexpected element content");
}
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
pop();
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
throw new DataFormatException("Found unexpected element content");
}
@Override
protected IElement getCurrentElement() {
return null;
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
throw new DataFormatException("Found unexpected element content");
}
}
private static final QName ATOM_LINK_REL_ATTRIBUTE = new QName("rel");
private static final QName ATOM_LINK_HREF_ATTRIBUTE = new QName("href");
2014-02-26 17:13:49 -05:00
private class AtomState extends BaseState {
private Bundle myInstance;
public AtomState(Bundle theInstance) {
myInstance = theInstance;
}
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
// TODO Auto-generated method stub
2014-02-26 17:13:49 -05:00
}
2014-02-18 08:26:49 -05:00
2014-02-26 17:13:49 -05:00
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
pop();
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
if (theLocalPart.equals("title")) {
push(new AtomPrimitiveState(myInstance.getTitle()));
} else if ("id".equals(theLocalPart)) {
2014-02-27 07:39:36 -05:00
push(new AtomPrimitiveState(myInstance.getId()));
} else if ("link".equals(theLocalPart)) {
Attribute rel = theElement.getAttributeByName(ATOM_LINK_REL_ATTRIBUTE);
Attribute href = theElement.getAttributeByName(ATOM_LINK_HREF_ATTRIBUTE);
if (rel != null && href != null) {
if ("self".equals(rel.getValue())) {
myInstance.getLinkSelf().setValueAsString(href.getValue());
push(new ExpectEndElementState());
} else if ("first".equals(rel.getValue())) {
myInstance.getLinkFirst().setValueAsString(href.getValue());
push(new ExpectEndElementState());
} else if ("previous".equals(rel.getValue())) {
myInstance.getLinkPrevious().setValueAsString(href.getValue());
push(new ExpectEndElementState());
} else if ("next".equals(rel.getValue())) {
myInstance.getLinkNext().setValueAsString(href.getValue());
push(new ExpectEndElementState());
} else if ("last".equals(rel.getValue())) {
myInstance.getLinkLast().setValueAsString(href.getValue());
push(new ExpectEndElementState());
} else if ("fhir-base".equals(rel.getValue())) {
myInstance.getLinkBase().setValueAsString(href.getValue());
push(new ExpectEndElementState());
}
}
2014-02-26 17:13:49 -05:00
}
}
@Override
protected IElement getCurrentElement() {
return myInstance;
2014-02-26 17:13:49 -05:00
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
// ignore
2014-02-26 17:13:49 -05:00
}
2014-02-26 17:13:49 -05:00
}
2014-02-26 17:13:49 -05:00
private class PreAtomState extends BaseState {
private Bundle myInstance;
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
// ignore
}
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
// ignore
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
if (!"feed".equals(theLocalPart)) {
throw new DataFormatException("Expecting outer element called 'feed', found: " + theLocalPart);
2014-02-26 17:13:49 -05:00
}
2014-02-26 17:13:49 -05:00
myInstance = new Bundle();
push(new AtomState(myInstance));
2014-02-26 17:13:49 -05:00
}
@Override
protected IElement getCurrentElement() {
// TODO Auto-generated method stub
return null;
}
2014-02-27 07:39:36 -05:00
@SuppressWarnings("unchecked")
2014-02-26 17:13:49 -05:00
@Override
public void wereBack() {
2014-02-27 07:39:36 -05:00
myObject = (T) myInstance;
2014-02-26 17:13:49 -05:00
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
// ignore
}
2014-02-26 17:13:49 -05:00
}
2014-02-20 12:13:05 -05:00
private abstract class BaseState {
2014-02-26 17:13:49 -05:00
2014-02-20 12:13:05 -05:00
private BaseState myStack;
2014-02-18 08:26:49 -05:00
2014-02-21 21:06:11 -05:00
public abstract void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException;
public abstract void endingElement(EndElement theElem) throws DataFormatException;
2014-02-19 11:59:12 -05:00
2014-02-21 21:06:11 -05:00
public abstract void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException;
2014-02-18 08:26:49 -05:00
2014-02-23 18:13:59 -05:00
/**
* Default implementation just handles undeclared extensions
*/
2014-02-22 15:33:02 -05:00
public void enteringNewElementExtension(@SuppressWarnings("unused") StartElement theElement, String theUrlAttr) {
if (getCurrentElement() instanceof ISupportsUndeclaredExtensions) {
UndeclaredExtension newExtension = new UndeclaredExtension();
newExtension.setUrl(theUrlAttr);
2014-02-23 18:13:59 -05:00
// TODO: fail if we don't support undeclared extensions
2014-02-22 15:33:02 -05:00
((ISupportsUndeclaredExtensions) getCurrentElement()).getUndeclaredExtensions().add(newExtension);
ExtensionState newState = new ExtensionState(newExtension);
push(newState);
}
}
2014-02-26 17:13:49 -05:00
protected abstract IElement getCurrentElement();
2014-02-22 15:33:02 -05:00
public abstract void otherEvent(XMLEvent theEvent) throws DataFormatException;
2014-02-20 12:13:05 -05:00
public void setStack(BaseState theState) {
myStack = theState;
}
2014-02-26 17:13:49 -05:00
public void wereBack() {
// allow an implementor to override
}
}
private class DeclaredExtensionState extends BaseState {
private IElement myChildInstance;
private RuntimeChildDeclaredExtensionDefinition myDefinition;
private IElement myParentInstance;
public DeclaredExtensionState(RuntimeChildDeclaredExtensionDefinition theDefinition, IElement theParentInstance) {
myDefinition = theDefinition;
myParentInstance = theParentInstance;
}
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
throw new DataFormatException("'value' attribute is invalid in 'extension' element");
}
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
pop();
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
BaseRuntimeElementDefinition<?> target = myDefinition.getChildByName(theLocalPart);
if (target == null) {
throw new DataFormatException("Unknown extension element name: " + theLocalPart);
}
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance();
myDefinition.getMutator().addValue(myParentInstance, newChildInstance);
ElementCompositeState newState = new ElementCompositeState(compositeTarget, newChildInstance);
push(newState);
return;
}
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveDatatype<?> newChildInstance = primitiveTarget.newInstance();
myDefinition.getMutator().addValue(myParentInstance, newChildInstance);
PrimitiveState newState = new PrimitiveState(newChildInstance);
push(newState);
return;
}
case RESOURCE_REF: {
RuntimeResourceReferenceDefinition resourceRefTarget = (RuntimeResourceReferenceDefinition) target;
ResourceReference newChildInstance = new ResourceReference();
myDefinition.getMutator().addValue(myParentInstance, newChildInstance);
ResourceReferenceState newState = new ResourceReferenceState(resourceRefTarget, newChildInstance);
push(newState);
return;
}
case PRIMITIVE_XHTML:
case RESOURCE:
case RESOURCE_BLOCK:
case UNDECL_EXT:
case EXTENSION_DECLARED:
default:
break;
}
}
@Override
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr) {
RuntimeChildDeclaredExtensionDefinition declaredExtension = myDefinition.getChildExtensionForUrl(theUrlAttr);
if (declaredExtension != null) {
if (myChildInstance == null) {
myChildInstance = myDefinition.newInstance();
myDefinition.getMutator().addValue(myParentInstance, myChildInstance);
}
BaseState newState = new DeclaredExtensionState(declaredExtension, myChildInstance);
push(newState);
} else {
super.enteringNewElementExtension(theElement, theUrlAttr);
}
}
@Override
protected IElement getCurrentElement() {
return myParentInstance;
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
// ignore
}
2014-02-20 12:13:05 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-26 17:13:49 -05:00
private class ElementCompositeState extends BaseState {
2014-02-19 11:59:12 -05:00
private BaseRuntimeElementCompositeDefinition<?> myDefinition;
private ICompositeElement myInstance;
2014-02-18 08:26:49 -05:00
2014-02-26 17:13:49 -05:00
public ElementCompositeState(BaseRuntimeElementCompositeDefinition<?> theDef, ICompositeElement theInstance) {
2014-02-19 11:59:12 -05:00
myDefinition = theDef;
2014-02-18 08:26:49 -05:00
myInstance = theInstance;
}
2014-02-19 11:59:12 -05:00
@Override
2014-02-21 21:06:11 -05:00
public void attributeValue(Attribute theAttribute, String theValue) {
2014-02-19 11:59:12 -05:00
ourLog.debug("Ignoring attribute value: {}", theValue);
}
2014-02-27 07:39:36 -05:00
@SuppressWarnings("unchecked")
2014-02-18 08:26:49 -05:00
@Override
2014-02-21 21:06:11 -05:00
public void endingElement(EndElement theElem) {
pop();
if (myState == null) {
2014-02-27 07:39:36 -05:00
myObject = (T) myInstance;
2014-02-21 21:06:11 -05:00
}
}
@Override
public void enteringNewElement(StartElement theElement, String theChildName) throws DataFormatException {
2014-02-19 11:59:12 -05:00
BaseRuntimeChildDefinition child = myDefinition.getChildByNameOrThrowDataFormatException(theChildName);
BaseRuntimeElementDefinition<?> target = child.getChildByName(theChildName);
2014-02-26 09:03:43 -05:00
if (target == null) {
throw new DataFormatException("Found unexpected element '" + theChildName + "' in parent element '" + myDefinition.getName() + "'. Valid names are: " + child.getValidChildNames());
}
2014-02-26 17:13:49 -05:00
2014-02-19 11:59:12 -05:00
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance();
child.getMutator().addValue(myInstance, newChildInstance);
2014-02-26 17:13:49 -05:00
ElementCompositeState newState = new ElementCompositeState(compositeTarget, newChildInstance);
2014-02-19 11:59:12 -05:00
push(newState);
2014-02-20 12:13:05 -05:00
return;
2014-02-19 11:59:12 -05:00
}
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveDatatype<?> newChildInstance = primitiveTarget.newInstance();
child.getMutator().addValue(myInstance, newChildInstance);
2014-02-20 12:13:05 -05:00
PrimitiveState newState = new PrimitiveState(newChildInstance);
2014-02-19 11:59:12 -05:00
push(newState);
2014-02-20 12:13:05 -05:00
return;
2014-02-19 11:59:12 -05:00
}
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-20 12:13:05 -05:00
return;
}
case RESOURCE_BLOCK: {
RuntimeResourceBlockDefinition blockTarget = (RuntimeResourceBlockDefinition) target;
IResourceBlock newBlockInstance = blockTarget.newInstance();
child.getMutator().addValue(myInstance, newBlockInstance);
2014-02-26 17:13:49 -05:00
ElementCompositeState newState = new ElementCompositeState(blockTarget, newBlockInstance);
2014-02-20 12:13:05 -05:00
push(newState);
return;
2014-02-19 11:59:12 -05:00
}
2014-02-22 15:33:02 -05:00
case PRIMITIVE_XHTML: {
RuntimePrimitiveDatatypeNarrativeDefinition xhtmlTarget = (RuntimePrimitiveDatatypeNarrativeDefinition) target;
XhtmlDt newDt = xhtmlTarget.newInstance();
child.getMutator().addValue(myInstance, newDt);
XhtmlState state = new XhtmlState(newDt, theElement);
push(state);
return;
}
case UNDECL_EXT:
2014-02-21 21:06:11 -05:00
case RESOURCE: {
2014-02-20 12:13:05 -05:00
// Throw an exception because this shouldn't happen here
break;
2014-02-19 11:59:12 -05:00
}
2014-02-22 15:33:02 -05:00
}
throw new DataFormatException("Illegal resource position: " + target.getChildType());
}
@Override
2014-02-26 17:13:49 -05:00
public void enteringNewElementExtension(StartElement theElement, String theUrlAttr) {
RuntimeChildDeclaredExtensionDefinition declaredExtension = myDefinition.getDeclaredExtension(theUrlAttr);
if (declaredExtension != null) {
BaseState newState = new DeclaredExtensionState(declaredExtension, myInstance);
push(newState);
} else {
super.enteringNewElementExtension(theElement, theUrlAttr);
}
2014-02-22 15:33:02 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-22 15:33:02 -05:00
@Override
protected IElement getCurrentElement() {
return myInstance;
}
2014-02-26 17:13:49 -05:00
@Override
public void otherEvent(XMLEvent theEvent) {
// ignore
}
2014-02-22 15:33:02 -05:00
}
private class ExtensionState extends BaseState {
private UndeclaredExtension myExtension;
public ExtensionState(UndeclaredExtension theExtension) {
myExtension = theExtension;
}
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
throw new DataFormatException("'value' attribute is invalid in 'extension' element");
}
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
if (myExtension.getValue() != null && myExtension.getUndeclaredExtensions().size() > 0) {
throw new DataFormatException("Extension must not have both a value and other contained extensions");
2014-02-18 18:10:50 -05:00
}
2014-02-22 15:33:02 -05:00
pop();
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
BaseRuntimeElementDefinition<?> target = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(theLocalPart);
if (target == null) {
throw new DataFormatException("Unknown extension element name: " + theLocalPart);
2014-02-21 21:06:11 -05:00
}
2014-02-22 15:33:02 -05:00
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeDatatype newChildInstance = (ICompositeDatatype) compositeTarget.newInstance();
myExtension.setValue(newChildInstance);
2014-02-26 17:13:49 -05:00
ElementCompositeState newState = new ElementCompositeState(compositeTarget, newChildInstance);
2014-02-22 15:33:02 -05:00
push(newState);
return;
}
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveDatatype<?> newChildInstance = primitiveTarget.newInstance();
myExtension.setValue(newChildInstance);
PrimitiveState newState = new PrimitiveState(newChildInstance);
push(newState);
return;
}
case RESOURCE_REF: {
RuntimeResourceReferenceDefinition resourceRefTarget = (RuntimeResourceReferenceDefinition) target;
ResourceReference newChildInstance = new ResourceReference();
myExtension.setValue(newChildInstance);
ResourceReferenceState newState = new ResourceReferenceState(resourceRefTarget, newChildInstance);
push(newState);
return;
}
case PRIMITIVE_XHTML:
case RESOURCE:
case RESOURCE_BLOCK:
case UNDECL_EXT:
break;
}
}
2014-02-26 17:13:49 -05:00
@Override
protected IElement getCurrentElement() {
return myExtension;
}
2014-02-22 15:33:02 -05:00
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
// ignore
}
2014-02-26 17:13:49 -05:00
}
private class PreResourceState extends BaseState {
private ICompositeElement myInstance;
@Override
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
// ignore
}
@Override
public void endingElement(EndElement theElem) throws DataFormatException {
// ignore
}
@Override
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
BaseRuntimeElementDefinition<?> definition = myContext.getNameToResourceDefinition().get(theLocalPart);
if (!(definition instanceof RuntimeResourceDefinition)) {
throw new DataFormatException("Element '" + theLocalPart + "' is not a resource, expected a resource at this position");
}
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
myInstance = def.newInstance();
push(new ElementCompositeState(def, myInstance));
}
2014-02-22 15:33:02 -05:00
@Override
protected IElement getCurrentElement() {
2014-02-26 17:13:49 -05:00
return myInstance;
}
@Override
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
// ignore
}
2014-02-27 07:39:36 -05:00
@SuppressWarnings("unchecked")
2014-02-26 17:13:49 -05:00
@Override
public void wereBack() {
2014-02-27 07:39:36 -05:00
myObject = (T) myInstance;
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 IPrimitiveDatatype<?> myInstance;
2014-02-20 12:13:05 -05:00
public PrimitiveState(IPrimitiveDatatype<?> theInstance) {
2014-02-19 11:59:12 -05:00
super();
myInstance = theInstance;
}
@Override
2014-02-21 21:06:11 -05:00
public void attributeValue(Attribute theAttribute, String theValue) throws DataFormatException {
2014-02-19 11:59:12 -05:00
myInstance.setValueAsString(theValue);
}
@Override
2014-02-21 21:06:11 -05:00
public void endingElement(EndElement theElem) {
pop();
2014-02-19 11:59:12 -05:00
}
@Override
2014-02-21 21:06:11 -05:00
public void enteringNewElement(StartElement theElement, String theLocalPart) throws DataFormatException {
throw new Error("?? can this happen?"); // TODO: can this happen?
2014-02-19 11:59:12 -05:00
}
2014-02-22 15:33:02 -05:00
@Override
2014-02-26 17:13:49 -05:00
protected IElement getCurrentElement() {
return myInstance;
2014-02-22 15:33:02 -05:00
}
@Override
2014-02-26 17:13:49 -05:00
public void otherEvent(XMLEvent theEvent) {
// ignore
2014-02-22 15:33:02 -05:00
}
2014-02-19 11:59:12 -05:00
}
2014-02-21 21:06:11 -05:00
private class ResourceReferenceState extends BaseState {
private RuntimeResourceReferenceDefinition myDefinition;
private ResourceReference myInstance;
private ResourceReferenceSubState mySubState;
public ResourceReferenceState(RuntimeResourceReferenceDefinition theDefinition, ResourceReference theInstance) {
myDefinition = theDefinition;
myInstance = theInstance;
mySubState = ResourceReferenceSubState.INITIAL;
}
@Override
public void attributeValue(Attribute theAttribute, 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 endingElement(EndElement theElement) {
switch (mySubState) {
case INITIAL:
pop();
break;
case DISPLAY:
case REFERENCE:
mySubState = ResourceReferenceSubState.INITIAL;
}
}
@Override
public void enteringNewElement(StartElement theElem, 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;
}
//$FALL-THROUGH$
case DISPLAY:
case REFERENCE:
throw new DataFormatException("Unexpected element: " + theLocalPart);
}
}
2014-02-22 15:33:02 -05:00
@Override
2014-02-26 17:13:49 -05:00
protected IElement getCurrentElement() {
return myInstance;
2014-02-22 15:33:02 -05:00
}
@Override
2014-02-26 17:13:49 -05:00
public void otherEvent(XMLEvent theEvent) {
// ignore
2014-02-22 15:33:02 -05:00
}
2014-02-18 08:26:49 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-21 21:06:11 -05:00
private enum ResourceReferenceSubState {
DISPLAY, INITIAL, REFERENCE
2014-02-19 11:59:12 -05:00
}
2014-02-21 21:06:11 -05:00
private class XhtmlState extends BaseState {
2014-02-22 15:33:02 -05:00
private int myDepth;
private XhtmlDt myDt;
private List<XMLEvent> myEvents = new ArrayList<XMLEvent>();
private XhtmlState(XhtmlDt theXhtmlDt, StartElement theXhtmlStartElement) throws DataFormatException {
myDepth = 1;
myDt = theXhtmlDt;
myEvents.add(theXhtmlStartElement);
2014-02-21 21:06:11 -05:00
}
@Override
public void attributeValue(Attribute theAttr, String theValue) throws DataFormatException {
2014-02-22 15:33:02 -05:00
myEvents.add(theAttr);
2014-02-21 21:06:11 -05:00
}
@Override
public void endingElement(EndElement theElement) throws DataFormatException {
2014-02-22 15:33:02 -05:00
myEvents.add(theElement);
myDepth--;
if (myDepth == 0) {
myDt.setValue(myEvents);
pop();
2014-02-21 21:06:11 -05:00
}
}
@Override
public void enteringNewElement(StartElement theElem, String theLocalPart) throws DataFormatException {
2014-02-22 15:33:02 -05:00
myDepth++;
myEvents.add(theElem);
}
2014-02-21 21:06:11 -05:00
2014-02-22 15:33:02 -05:00
@Override
2014-02-26 17:13:49 -05:00
protected IElement getCurrentElement() {
return myDt;
2014-02-21 21:06:11 -05:00
}
2014-02-19 11:59:12 -05:00
2014-02-22 15:33:02 -05:00
@Override
2014-02-26 17:13:49 -05:00
public void otherEvent(XMLEvent theEvent) throws DataFormatException {
myEvents.add(theEvent);
2014-02-22 15:33:02 -05:00
}
2014-02-19 11:59:12 -05:00
}
2014-02-18 08:26:49 -05:00
}