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
2014-02-27 10:20:25 -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 ;
2014-02-27 10:20:25 -05:00
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 ;
}
2014-02-27 10:20:25 -05:00
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 ;
2014-02-27 10:20:25 -05:00
} else {
2014-02-26 17:13:49 -05:00
// this shouldn't generally happen so it's ok that it's inefficient
2014-02-27 10:20:25 -05:00
myData = myData + data ;
2014-02-26 17:13:49 -05:00
}
}
}
2014-02-27 10:20:25 -05:00
2014-02-18 08:26:49 -05:00
}
2014-02-27 10:20:25 -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-27 10:20:25 -05:00
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 ( ) ) ) ;
2014-02-27 10:20:25 -05:00
} else if ( " id " . equals ( theLocalPart ) ) {
2014-02-27 07:39:36 -05:00
push ( new AtomPrimitiveState ( myInstance . getId ( ) ) ) ;
2014-02-27 10:20:25 -05:00
} 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 ( ) {
2014-02-27 10:20:25 -05:00
return myInstance ;
2014-02-26 17:13:49 -05:00
}
@Override
public void otherEvent ( XMLEvent theEvent ) throws DataFormatException {
2014-02-27 10:20:25 -05:00
// ignore
2014-02-26 17:13:49 -05:00
}
2014-02-27 10:20:25 -05:00
2014-02-26 17:13:49 -05:00
}
2014-02-27 10:20:25 -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 ) ) {
2014-02-27 10:20:25 -05:00
throw new DataFormatException ( " Expecting outer element called 'feed', found: " + theLocalPart ) ;
2014-02-26 17:13:49 -05:00
}
2014-02-27 10:20:25 -05:00
2014-02-26 17:13:49 -05:00
myInstance = new Bundle ( ) ;
push ( new AtomState ( myInstance ) ) ;
2014-02-27 10:20:25 -05:00
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-27 10:20:25 -05:00
2014-02-26 17:13:49 -05:00
}
2014-02-27 10:20:25 -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
}