[jboss-svn-commits] JBoss Common SVN: r3838 - in jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling: position and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Dec 8 18:45:17 EST 2009
Author: alex.loubyansky at jboss.com
Date: 2009-12-08 18:45:16 -0500 (Tue, 08 Dec 2009)
New Revision: 3838
Modified:
jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java
jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/AbstractPosition.java
jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/ElementPosition.java
jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/NonElementPosition.java
jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/Position.java
Log:
break up start/end particle handling by position type and move the logic into the corresponding position impl.
Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java 2009-12-07 04:08:39 UTC (rev 3837)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java 2009-12-08 23:45:16 UTC (rev 3838)
@@ -29,21 +29,17 @@
import javax.xml.namespace.QName;
import org.apache.xerces.xs.XSTypeDefinition;
import org.jboss.logging.Logger;
-import org.jboss.util.StringPropertyReplacer;
import org.jboss.xb.binding.AttributesImpl;
import org.jboss.xb.binding.Constants;
import org.jboss.xb.binding.JBossXBRuntimeException;
import org.jboss.xb.binding.NamespaceRegistry;
import org.jboss.xb.binding.Util;
import org.jboss.xb.binding.introspection.FieldInfo;
-import org.jboss.xb.binding.metadata.CharactersMetaData;
import org.jboss.xb.binding.metadata.PropertyMetaData;
-import org.jboss.xb.binding.metadata.ValueMetaData;
import org.jboss.xb.binding.parser.JBossXBParser;
import org.jboss.xb.binding.resolver.MutableSchemaResolver;
import org.jboss.xb.binding.sunday.unmarshalling.position.ElementPosition;
import org.jboss.xb.binding.sunday.unmarshalling.position.Position;
-import org.jboss.xb.binding.sunday.xop.XOPIncludeHandler;
import org.xml.sax.Attributes;
/**
@@ -57,17 +53,14 @@
{
final static Logger log = Logger.getLogger(SundayContentHandler.class);
- private final static Object NIL = new Object();
+ public final static Object NIL = new Object();
- private final SchemaBinding schema;
private final SchemaBindingResolver schemaResolver;
private final StackImpl stack = new StackImpl();
private Object root;
- private NamespaceRegistry nsRegistry = new NamespaceRegistry();
- private UnmarshallingContextImpl ctx = new UnmarshallingContextImpl();
// DTD information frm startDTD
private String dtdRootName;
private String dtdPublicId;
@@ -78,14 +71,14 @@
public SundayContentHandler(SchemaBinding schema)
{
- this.schema = schema;
+ this.stack.schema = schema;
this.schemaResolver = null;
}
public SundayContentHandler(SchemaBindingResolver schemaResolver)
{
this.schemaResolver = schemaResolver;
- this.schema = null;
+ this.stack.schema = null;
}
@@ -127,9 +120,10 @@
public void endElement(String namespaceURI, String localName, String qName)
{
ElementBinding elementBinding = null;
+ Position position = null;
while(elementBinding == null && !stack.isEmpty())
{
- Position position = stack.peek();
+ position = stack.peek();
if(position.isElement())
{
if(position.isEnded())
@@ -138,26 +132,35 @@
{
Position parentPosition = stack.peek1();
if(parentPosition.getRepeatableParticleValue() != null)
- endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
+ stack.endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
}
stack.pop();
}
else
{
elementBinding = (ElementBinding)position.getParticle().getTerm();
- position.setEnded(true);
+
+ QName endName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
+ if(!elementBinding.getQName().equals(endName))
+ {
+ throw new JBossXBRuntimeException("Failed to end element " +
+ new QName(namespaceURI, localName) +
+ ": element on the stack is " + elementBinding.getQName()
+ );
+ }
+
+ position.endParticle();
}
}
else
{
- if(!position.isEnded()) // could be ended if it's a choice
- endParticle(position);
+ position.endParticle();
if(position.getParticle().isRepeatable())
{
Position parentPosition = stack.peek1();
if(parentPosition.getRepeatableParticleValue() != null)
- endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
+ stack.endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
}
stack.pop();
}
@@ -166,16 +169,28 @@
if(elementBinding == null)
throw new JBossXBRuntimeException("Failed to endElement " + qName + ": binding not found");
- QName endName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
- if(!elementBinding.getQName().equals(endName))
+ if(stack.size() == 1)
{
- throw new JBossXBRuntimeException("Failed to end element " +
- new QName(namespaceURI, localName) +
- ": element on the stack is " + elementBinding.getQName()
- );
+ root = elementBinding.getType().getValueAdapter().cast(position.getValue(), Object.class);
+ stack.clear();
+
+ if(sawDTD)
+ {
+ // Probably should be integrated into schema binding?
+ try
+ {
+ // setDTD(String root, String publicId, String systemId)
+ Class[] sig = {String.class, String.class, String.class};
+ Method setDTD = root.getClass().getMethod("setDTD", sig);
+ Object[] args = {dtdRootName, dtdPublicId, dtdSystemId};
+ setDTD.invoke(root, args);
+ }
+ catch(Exception e)
+ {
+ log.debug("No setDTD found on root: " + root);
+ }
+ }
}
-
- endElement();
}
public void startElement(String namespaceURI,
@@ -187,7 +202,7 @@
QName startName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
boolean repeated = false;
Position position = null;
- SchemaBinding schemaBinding = schema;
+ SchemaBinding schemaBinding = stack.schema;
atts = preprocessAttributes(atts);
@@ -234,177 +249,16 @@
{
while(!stack.isEmpty())
{
- position = stack.peek();
- if(position.isElement())
+ Position peek = stack.peek();
+ position = peek.startParticle(startName, atts);
+ if(position.isEnded())
{
- TermBinding term = position.getParticle().getTerm();
- ElementBinding element = (ElementBinding)term;
- if(position.isEnded())
- {
- if(element.getQName().equals(startName))
- {
- if(position.getParticle().isRepeatable())
- {
- Position parentPosition = stack.peek1();
- if(parentPosition.repeatTerm(startName, atts))
- {
- position.reset();
- repeated = true;
- }
- else
- {
- stack.pop();
- if(parentPosition.getRepeatableParticleValue() != null)
- endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
- continue;
- }
- }
- else
- {
- position.reset();
- repeated = true;
- endRepeatableParent(startName);
- }
- }
- else
- {
- if(position.getParticle().isRepeatable())
- {
- Position parentPosition = stack.peek1();
- if(parentPosition.getRepeatableParticleValue() != null)
- endRepeatableParticle(parentPosition, position.getQName(), position.getParticle(), parentPosition.getParticle());
- }
- stack.pop();
- continue;
- }
- }
- else
- {
- TypeBinding parentType = element.getType();
- ParticleBinding typeParticle = parentType.getParticle();
- ModelGroupBinding modelGroup = typeParticle == null ? null : (ModelGroupBinding)typeParticle.getTerm();
- if(modelGroup == null)
- {
- if(startName.equals(Constants.QNAME_XOP_INCLUDE))
- {
- TypeBinding anyUriType = schema.getType(Constants.QNAME_ANYURI);
- if(anyUriType == null)
- log.warn("Type " + Constants.QNAME_ANYURI + " not bound.");
-
- ElementBinding parentElement = (ElementBinding) position.getParticle().getTerm();
- parentElement.setXopUnmarshaller(schema.getXopUnmarshaller());
-
- ElementPosition ep = (ElementPosition) position;
- ep.flushIgnorableCharacters();
- ep.setHandler(DefaultHandlers.XOP_HANDLER);
- ep.setIgnoreCharacters(true);
- position.startParticle(position.getValue(), null, nsRegistry);
-
- TypeBinding xopIncludeType = new TypeBinding(new QName(Constants.NS_XOP_INCLUDE, "Include"));
- xopIncludeType.setSchemaBinding(schema);
- xopIncludeType.addAttribute(new QName("href"), anyUriType, DefaultHandlers.ATTRIBUTE_HANDLER);
- xopIncludeType.setHandler(new XOPIncludeHandler(parentType, schema.getXopUnmarshaller()));
-
- ElementBinding xopInclude = new ElementBinding(schema, Constants.QNAME_XOP_INCLUDE, xopIncludeType);
- position = new ElementPosition(startName, new ParticleBinding(xopInclude));
- break;
- }
-
- QName typeName = parentType.getQName();
- throw new JBossXBRuntimeException((typeName == null ? "Anonymous" : typeName.toString()) +
- " type of element " +
- element.getQName() +
- " should be complex and contain " + startName + " as a child element."
- );
- }
-
- Position newPosition = modelGroup.newPosition(startName, atts, typeParticle);
- if(newPosition == null)
- {
- throw new JBossXBRuntimeException(startName +
- " not found as a child of " +
- ((ElementBinding)term).getQName() + " in " + modelGroup
- );
- }
- else
- {
- position.flushIgnorableCharacters();
-
- Object o = position.getValue();
- while(newPosition.getNext() != null)
- {
- if(newPosition.getParticle().isRepeatable())
- startRepeatableParticle(stack.peek(), o, startName, newPosition.getParticle());
-
- o = newPosition.startParticle(o, atts, nsRegistry);
- newPosition.setParentType(parentType);
- stack.push(newPosition);
- newPosition = newPosition.getNext();
- }
-
- position = newPosition;
- position.setParentType(parentType);
- if(!position.isElement())
- throw new IllegalStateException();
- }
- }
- break;
+ stack.pop();
}
else
{
- ParticleBinding prevParticle = position.getCurrentParticle();
- Position newPosition = position.startElement(startName, atts);
- if(newPosition == null)
- {
- if(!position.isEnded())
- endParticle(position);
-
- stack.pop();
- if(!position.getParticle().isRepeatable() && stack.peek().isElement())
- {
- TermBinding t = position.getParticle().getTerm();
- StringBuffer sb = new StringBuffer(250);
- sb.append(startName).append(" cannot appear in this position. Expected content of ")
- .append(((ElementBinding)stack.peek().getParticle().getTerm()).getQName())
- .append(" is ").append(t);
- throw new JBossXBRuntimeException(sb.toString());
- }
- }
- else
- {
- ParticleBinding curParticle = position.getCurrentParticle();
- if(curParticle != prevParticle)
- {
- if(position.getRepeatableParticleValue() != null &&
- prevParticle != null && prevParticle.isRepeatable() && prevParticle.getTerm().isModelGroup())
- {
- endRepeatableParticle(position, position.getQName(), prevParticle, position.getParticle());
- }
-
- if(newPosition.getNext() != null && curParticle.isRepeatable() && !curParticle.getTerm().isElement())
- {
- startRepeatableParticle(position, position.getValue(), startName, curParticle);
- }
- }
-
- // push all except the last one
- Object o = position.getValue();
- newPosition = newPosition.getNext();
- while (newPosition.getNext() != null)
- {
- o = newPosition.startParticle(o, atts, nsRegistry);
- newPosition.setParentType(position.getParentType());
- stack.push(newPosition);
- newPosition = newPosition.getNext();
- }
-
- newPosition.setParentType(position.getParentType());
- position = newPosition;
- if(!position.isElement())
- throw new IllegalStateException();
-
- break;
- }
+ repeated = position == peek;
+ break;
}
}
}
@@ -436,7 +290,7 @@
xsiTypeLocal = xsiType.substring(colon + 1);
}
- String xsiTypeNs = nsRegistry.getNamespaceURI(xsiTypePrefix);
+ String xsiTypeNs = stack.nsRegistry.getNamespaceURI(xsiTypePrefix);
QName xsiTypeQName = new QName(xsiTypeNs, xsiTypeLocal);
TypeBinding xsiTypeBinding = schemaBinding.getType(xsiTypeQName);
@@ -456,7 +310,7 @@
Object parent = stack.isEmpty() ? null : (repeated ? stack.peek1().getValue() : stack.peek().getValue());
if (!repeated && position.getParticle().isRepeatable())
- startRepeatableParticle(stack.peek(), parent, startName, position.getParticle());
+ stack.startRepeatableParticle(stack.peek(), parent, startName, position.getParticle());
TypeBinding type = element.getType();
if (type == null)
@@ -481,7 +335,7 @@
ElementInterceptor interceptor = localInterceptors.get(i);
parent = interceptor.startElement(parent, startName, type);
push(startName, position.getParticle(), parent, position.getHandler(), position.getParentType());
- interceptor.attributes(parent, startName, type, atts, nsRegistry);
+ interceptor.attributes(parent, startName, type, atts, stack.nsRegistry);
}
for (int i = 0; i < interceptors.size(); ++i)
@@ -489,7 +343,7 @@
ElementInterceptor interceptor = interceptors.get(i);
parent = interceptor.startElement(parent, startName, type);
push(startName, position.getParticle(), parent, position.getHandler(), position.getParentType());
- interceptor.attributes(parent, startName, type, atts, nsRegistry);
+ interceptor.attributes(parent, startName, type, atts, stack.nsRegistry);
}
if (repeated)
@@ -499,165 +353,24 @@
}
}
+ if (!repeated)
+ stack.push(position);
+
String nil = atts.getValue(Constants.NS_XML_SCHEMA_INSTANCE, "nil");
if (nil == null || !("1".equals(nil) || "true".equals(nil)))
- position.startParticle(parent, atts, nsRegistry);
+ position.initValue(parent, atts);
else
position.setValue(NIL);
-
- if (!repeated)
- stack.push(position);
}
- private void endRepeatableParent(QName startName)
- {
- int stackIndex = stack.size() - 2;
- Position position;
- Position parentPosition = stack.peek1();
- while(true)
- {
- if(parentPosition.isElement())
- {
- throw new JBossXBRuntimeException(
- "Failed to start " + startName +
- ": the element is not repeatable, repeatable parent expected to be a model group but got element " +
- ((ElementBinding)parentPosition.getParticle().getTerm()).getQName()
- );
- }
-
- position = parentPosition;
- if(position.getParticle().isRepeatable())
- {
- endParticle(position, stackIndex - 1);
- parentPosition = stack.peek(stackIndex - 1);
- position.reset();
- position.startParticle(parentPosition.getValue(), null, nsRegistry);
- break;
- }
-
- parentPosition = stack.peek(--stackIndex);
- endParticle(position, stackIndex);
- }
-
-/* if(!parentParticle.isRepeatable())
- {
- StringBuffer msg = new StringBuffer();
-
- item = stack.peek();
- ParticleBinding currentParticle = item.particle;
- msg.append("Failed to start ").append(startName).append(": ")
- .append(currentParticle.getTerm())
- .append(" is not repeatable.")
- .append(" Its parent ")
- .append(parentParticle.getTerm())
- .append(" expected to be repeatable!")
- .append("\ncurrent stack: ");
-
- for(int i = 0; i < stack.size() - 1; ++i)
- {
- item = stack.peek(i);
- ParticleBinding particle = item.particle;
- TermBinding term = particle.getTerm();
- if(term.isModelGroup())
- {
- if(term instanceof SequenceBinding)
- {
- msg.append("sequence");
- }
- else if(term instanceof ChoiceBinding)
- {
- msg.append("choice");
- }
- else
- {
- msg.append("all");
- }
- }
- else if(term.isWildcard())
- {
- msg.append("wildcard");
- }
- else
- {
- msg.append(((ElementBinding)term).getQName());
- }
- msg.append("\\");
- }
-
- throw new JBossXBRuntimeException(msg.toString());
- }
-*/
- while(++stackIndex < stack.size() - 1)
- {
- parentPosition = position;
- position = stack.peek(stackIndex);
- position.reset();
- position.startParticle(parentPosition.getValue(), null, nsRegistry);
- }
- }
-
- private void startRepeatableParticle(Position parentPosition, Object parent, QName startName, ParticleBinding particle)
- {
- if(trace)
- log.trace(" start repeatable (" + stack.size() + "): " + particle.getTerm());
-
- RepeatableParticleHandler repeatableHandler = particle.getTerm().getRepeatableHandler();
- // the way it is now it's never null
- Object repeatableContainer = repeatableHandler.startRepeatableParticle(parent, startName, particle);
- if(repeatableContainer != null)
- {
- if(parentPosition.getRepeatableParticleValue() != null)
- throw new IllegalStateException("Previous repeatable particle hasn't been ended yet!");
- parentPosition.setRepeatableParticleValue(repeatableContainer);
- parentPosition.setRepeatableHandler(repeatableHandler);
- }
- }
-
- private void endRepeatableParticle(Position parentPosition, QName elementName, ParticleBinding particle, ParticleBinding parentParticle)
- {
- if (trace)
- log.trace(" end repeatable (" + stack.size() + "): " + particle.getTerm());
- RepeatableParticleHandler repeatableHandler = parentPosition.getRepeatableHandler();
- // the way it is now it's never null
- repeatableHandler.endRepeatableParticle(parentPosition.getValue(), parentPosition.getRepeatableParticleValue(), elementName, particle, parentParticle);
- parentPosition.setRepeatableParticleValue(null);
- parentPosition.setRepeatableHandler(null);
- }
-
- private void endParticle(Position position)
- {
- if(position.isEnded())
- throw new JBossXBRuntimeException(position.getParticle().getTerm() + " has already been ended.");
-
- position.endParticle();
-
- // model group should always have parent particle
- Position parentPosition = stack.peek1();
- if(parentPosition.getValue() != null)
- setParent(position.getHandler(), parentPosition, position);
- }
-
- private void endParticle(Position position, int parentIdex)
- {
- if(position.isEnded())
- throw new JBossXBRuntimeException(position.getParticle().getTerm() + " has already been ended.");
-
- position.endParticle();
-
- // model group should always have parent particle
- Position parentPosition = getNotSkippedParent(parentIdex);
- if(parentPosition.getValue() != null)
- setParent(position.getHandler(), parentPosition, position);
- }
-
public void startPrefixMapping(String prefix, String uri)
{
- nsRegistry.addPrefixMapping(prefix, uri);
+ stack.nsRegistry.addPrefixMapping(prefix, uri);
}
public void endPrefixMapping(String prefix)
{
- nsRegistry.removePrefixMapping(prefix);
+ stack.nsRegistry.removePrefixMapping(prefix);
}
public void processingInstruction(String target, String data)
@@ -673,7 +386,7 @@
private Attributes preprocessAttributes(Attributes attrs)
{
- SchemaBindingResolver resolver = schemaResolver == null ? schema.getSchemaResolver() : schemaResolver;
+ SchemaBindingResolver resolver = schemaResolver == null ? stack.schema.getSchemaResolver() : schemaResolver;
if(resolver == null || !(resolver instanceof MutableSchemaResolver))
return attrs;
@@ -710,308 +423,6 @@
return attrs;
}
- private Position getNotSkippedParent()
- {
- Position position = stack.peek1();
- if(position == null)
- return null;
-
- ParticleBinding particle = position.getParticle();
- if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
- return position;
-
- Position wildcardPosition = null;
- if(particle.getTerm().isWildcard())
- wildcardPosition = position;
-
- for(int i = stack.size() - 3; i >= 0; --i)
- {
- position = stack.peek(i);
- particle = position.getParticle();
- if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
- return position;
- else if(wildcardPosition != null)
- return wildcardPosition;
-
- if(particle.getTerm().isWildcard())
- wildcardPosition = position;
- }
- return wildcardPosition;
- }
-
- private Position getNotSkippedParent(int i)
- {
- Position position = null;
- while(i >= 0)
- {
- position = stack.peek(i--);
- ParticleBinding particle = position.getParticle();
- if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
- return position;
- }
- return null;
- }
-
- private void endElement()
- {
- ElementPosition position = (ElementPosition) stack.peek();
-
- ElementBinding element = (ElementBinding)position.getParticle().getTerm();
- QName endName = element.getQName();
- TypeBinding type = element.getType();
- List<ElementInterceptor> interceptors = element.getInterceptors();
- List<ElementInterceptor> localInterceptors = position.getParentType() == null ? Collections.EMPTY_LIST : position.getParentType().getInterceptors(endName);
- int allInterceptors = interceptors.size() + localInterceptors.size();
-
- if(position.getValue() != NIL)
- {
- //
- // characters
- //
-
- position.flushIgnorableCharacters();
-
- TypeBinding charType = type.getSimpleType();
- if(charType == null)
- charType = type;
-
- CharactersHandler charHandler = position.isIgnoreCharacters() ? null : charType.getCharactersHandler();
-
- /**
- * If there is text content then unmarshal it and set.
- * If there is no text content and the type is simple and
- * its characters handler is not null then unmarshal and set.
- * If the type is complex and there is no text data then the unmarshalled value
- * of the empty text content is assumed to be null
- * (in case of simple types that's not always true and depends on nillable attribute).
- */
- String textContent = position.getTextContent() == null ? "" : position.getTextContent().toString();
- if(textContent.length() > 0 || charHandler != null && !type.isIgnoreEmptyString())
- {
- String dataContent;
- SchemaBinding schema = element.getSchema();
- if(textContent.length() == 0)
- {
- dataContent = null;
- }
- else
- {
- dataContent = textContent.toString();
- if(schema != null && schema.isReplacePropertyRefs())
- dataContent = StringPropertyReplacer.replaceProperties(dataContent);
-
- if(element.isNormalizeSpace())
- dataContent = dataContent.trim();
- }
-
- Object unmarshalled;
-
- if(charHandler == null)
- {
- if(!type.isSimple() &&
- schema != null &&
- schema.isStrictSchema()
- // todo this isSkip() doesn't look nice here
- && !element.isSkip())
- {
- throw new JBossXBRuntimeException("Element " +
- endName +
- " with type binding " +
- type.getQName() +
- " does not include text content binding: " + dataContent
- );
- }
- unmarshalled = dataContent;
- }
- else
- {
- ValueMetaData valueMetaData = element.getValueMetaData();
- if(valueMetaData == null)
- {
- CharactersMetaData charactersMetaData = type.getCharactersMetaData();
- if(charactersMetaData != null)
- {
- valueMetaData = charactersMetaData.getValue();
- }
- }
-
- // todo valueMetaData is available from type
- unmarshalled = dataContent == null ?
- charHandler.unmarshalEmpty(endName, charType, nsRegistry, valueMetaData) :
- charHandler.unmarshal(endName, charType, nsRegistry, valueMetaData, dataContent);
- }
-
- if(unmarshalled != null)
- {
- // if startElement returned null, we use characters as the object for this element
- if(position.getValue() == null)
- {
- position.setValue(unmarshalled);
- }
- else if(charHandler != null)
- {
- TermBeforeSetParentCallback beforeSetParent = charType.getBeforeSetParentCallback();
- if(beforeSetParent != null)
- {
- ctx.parent = position.getValue();
- ctx.particle = position.getParticle();
- ctx.parentParticle = getNotSkippedParent().getParticle();
- unmarshalled = beforeSetParent.beforeSetParent(unmarshalled, ctx);
- ctx.clear();
- }
-
- charHandler.setValue(endName, element, position.getValue(), unmarshalled);
- }
- }
-
- if(allInterceptors > 0)
- {
- int interceptorIndex = stack.size() - 1 - allInterceptors;
- for (int i = interceptors.size() - 1; i >= 0; --i)
- {
- ElementInterceptor interceptor = interceptors.get(i);
- interceptor.characters(stack.peek(interceptorIndex++).getValue(), endName, type, nsRegistry, dataContent);
- }
-
- for (int i = localInterceptors.size() - 1; i >= 0; --i)
- {
- ElementInterceptor interceptor = localInterceptors.get(i);
- interceptor.characters(stack.peek(interceptorIndex++).getValue(), endName, type, nsRegistry, dataContent);
- }
- }
- }
- }
- else
- {
- position.setValue(null);
- }
-
- //
- // endElement
- //
-
- position.endParticle();
-
- if(!interceptors.isEmpty())
- {
- int interceptorIndex = stack.size() - 1 - interceptors.size();
- for (int i = interceptors.size() - 1; i >= 0; --i)
- {
- ElementInterceptor interceptor = interceptors.get(i);
- interceptor.endElement(stack.peek(interceptorIndex++).getValue(), endName, type);
- }
- }
-
- //
- // setParent
- //
-
- if(allInterceptors == 0)
- {
- Position notSkippedParent = getNotSkippedParent();
- if (notSkippedParent != null)
- {
- ParticleBinding parentParticle = notSkippedParent.getParticle();
- TermBinding parentTerm = parentParticle.getTerm();
-
- if (notSkippedParent.getValue() != null)
- {
- ParticleHandler handler = position.getHandler();
- if (parentTerm.isWildcard())
- {
- ParticleHandler wh = ((WildcardBinding) parentTerm).getWildcardHandler();
- if (wh != null)
- handler = wh;
- }
- setParent(handler, notSkippedParent, position);
- }
- else if (parentTerm.isWildcard() && stack.size() > 1)
- {
- // the parent has anyType, so it gets the value of its child
- for (int i = stack.size() - 2; i >= 0; --i)
- {
- Position peeked = stack.peek(i);
- peeked.setValue(position.getValue());
- if (peeked.isElement())
- break;
- }
-
- if (trace)
- log.trace("Value of " + endName + " " + position.getValue() + " is promoted as the value of its parent element.");
- }
- }
- }
- else
- {
- Position popped = stack.pop();
-
- for(int i = interceptors.size() - 1; i >= 0; --i)
- {
- ElementInterceptor interceptor = interceptors.get(i);
- Object parent = stack.pop().getValue();
- interceptor.add(parent, position.getValue(), endName);
- position.setValue(parent);
- }
-
- for(int i = localInterceptors.size() - 1; i >= 0; --i)
- {
- ElementInterceptor interceptor = localInterceptors.get(i);
- Object parent = stack.pop().getValue();
- interceptor.add(parent, position.getValue(), endName);
- position.setValue(parent);
- }
-
- // need to push it back to have correct endRepeatableParticle events
- stack.push(popped);
- }
-
- if(stack.size() == 1)
- {
- root = type.getValueAdapter().cast(position.getValue(), Object.class);
- stack.clear();
-
- if(sawDTD)
- {
- // Probably should be integrated into schema binding?
- try
- {
- // setDTD(String root, String publicId, String systemId)
- Class[] sig = {String.class, String.class, String.class};
- Method setDTD = root.getClass().getMethod("setDTD", sig);
- Object[] args = {dtdRootName, dtdPublicId, dtdSystemId};
- setDTD.invoke(root, args);
- }
- catch(Exception e)
- {
- log.debug("No setDTD found on root: " + root);
- }
- }
- }
- }
-
- private void setParent(ParticleHandler handler, Position parentPosition, Position position)
- {
- if(parentPosition.getRepeatableParticleValue() == null)
- {
- TermBeforeSetParentCallback beforeSetParent = position.getParticle().getTerm().getBeforeSetParentCallback();
- if(beforeSetParent != null)
- {
- ctx.parent = parentPosition.getValue();
- ctx.particle = position.getParticle();
- ctx.parentParticle = getNotSkippedParent().getParticle();
- position.setValue(beforeSetParent.beforeSetParent(position.getValue(), ctx));
- ctx.clear();
- }
-
- handler.setParent(parentPosition.getValue(), position.getValue(), position.getQName(), position.getParticle(), parentPosition.getParticle());
- }
- else
- parentPosition.getRepeatableHandler().addTermValue(
- parentPosition.getRepeatableParticleValue(),
- position.getValue(), position.getQName(), position.getParticle(),
- parentPosition.getParticle(), handler);
- }
-
private void push(QName qName, ParticleBinding particle, Object o, ParticleHandler handler, TypeBinding parentType)
{
ElementPosition position = new ElementPosition(qName, particle);
@@ -1025,12 +436,18 @@
// Inner
- static class StackImpl
+ public static class StackImpl
{
+ protected boolean trace = log.isTraceEnabled();
+
private List<Position> list = new ArrayList<Position>();
private Position head;
private Position peek1;
+ public SchemaBinding schema;
+ public UnmarshallingContextImpl ctx = new UnmarshallingContextImpl();
+ public NamespaceRegistry nsRegistry = new NamespaceRegistry();
+
public void clear()
{
list.clear();
@@ -1043,6 +460,7 @@
list.add(o);
peek1 = head;
head = o;
+ o.setStack(this);
}
public Position pop()
@@ -1077,13 +495,83 @@
{
return list.size();
}
+
+ public Position getNotSkippedParent()
+ {
+ Position position = peek1;
+ if(position == null)
+ return null;
+
+ ParticleBinding particle = position.getParticle();
+ if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
+ return position;
+
+ Position wildcardPosition = null;
+ if(particle.getTerm().isWildcard())
+ wildcardPosition = position;
+
+ for(int i = list.size() - 3; i >= 0; --i)
+ {
+ position = list.get(i);
+ particle = position.getParticle();
+ if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
+ return position;
+ else if(wildcardPosition != null)
+ return wildcardPosition;
+
+ if(particle.getTerm().isWildcard())
+ wildcardPosition = position;
+ }
+ return wildcardPosition;
+ }
+
+ public Position getNotSkippedParent(int i)
+ {
+ Position position = null;
+ while(i >= 0)
+ {
+ position = list.get(i--);
+ ParticleBinding particle = position.getParticle();
+ if(!particle.getTerm().isSkip() || position.getRepeatableParticleValue() != null)
+ return position;
+ }
+ return null;
+ }
+
+ public void startRepeatableParticle(Position parentPosition, Object parent, QName startName, ParticleBinding particle)
+ {
+ if(trace)
+ log.trace(" start repeatable (" + size() + "): " + particle.getTerm());
+
+ RepeatableParticleHandler repeatableHandler = particle.getTerm().getRepeatableHandler();
+ // the way it is now it's never null
+ Object repeatableContainer = repeatableHandler.startRepeatableParticle(parent, startName, particle);
+ if(repeatableContainer != null)
+ {
+ if(parentPosition.getRepeatableParticleValue() != null)
+ throw new IllegalStateException("Previous repeatable particle hasn't been ended yet!");
+ parentPosition.setRepeatableParticleValue(repeatableContainer);
+ parentPosition.setRepeatableHandler(repeatableHandler);
+ }
+ }
+
+ public void endRepeatableParticle(Position parentPosition, QName elementName, ParticleBinding particle, ParticleBinding parentParticle)
+ {
+ if (trace)
+ log.trace(" end repeatable (" + size() + "): " + particle.getTerm());
+ RepeatableParticleHandler repeatableHandler = parentPosition.getRepeatableHandler();
+ // the way it is now it's never null
+ repeatableHandler.endRepeatableParticle(parentPosition.getValue(), parentPosition.getRepeatableParticleValue(), elementName, particle, parentParticle);
+ parentPosition.setRepeatableParticleValue(null);
+ parentPosition.setRepeatableHandler(null);
+ }
}
- private class UnmarshallingContextImpl implements UnmarshallingContext
+ public static class UnmarshallingContextImpl implements UnmarshallingContext
{
- Object parent;
- ParticleBinding particle;
- ParticleBinding parentParticle;
+ public Object parent;
+ public ParticleBinding particle;
+ public ParticleBinding parentParticle;
public Object getParentValue()
{
@@ -1141,11 +629,11 @@
// private
- void clear()
+ public void clear()
{
- ctx.parent = null;
- ctx.particle = null;
- ctx.parentParticle = null;
+ parent = null;
+ particle = null;
+ parentParticle = null;
}
}
}
Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/AbstractPosition.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/AbstractPosition.java 2009-12-07 04:08:39 UTC (rev 3837)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/AbstractPosition.java 2009-12-08 23:45:16 UTC (rev 3838)
@@ -25,7 +25,6 @@
import org.jboss.logging.Logger;
import org.jboss.xb.binding.JBossXBRuntimeException;
-import org.jboss.xb.binding.NamespaceRegistry;
import org.jboss.xb.binding.sunday.unmarshalling.DefaultHandlers;
import org.jboss.xb.binding.sunday.unmarshalling.ElementBinding;
import org.jboss.xb.binding.sunday.unmarshalling.ModelGroupBinding;
@@ -35,6 +34,7 @@
import org.jboss.xb.binding.sunday.unmarshalling.RepeatableParticleHandler;
import org.jboss.xb.binding.sunday.unmarshalling.TermBinding;
import org.jboss.xb.binding.sunday.unmarshalling.TypeBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.StackImpl;
import org.xml.sax.Attributes;
/**
@@ -47,7 +47,8 @@
{
protected final Logger log = Logger.getLogger(getClass());
protected boolean trace;
-
+
+ protected StackImpl stack;
protected final QName qName;
protected ParticleBinding particle;
protected ParticleHandler handler;
@@ -73,6 +74,11 @@
this.occurrence = 1;
}
+ public void setStack(StackImpl stack)
+ {
+ this.stack = stack;
+ }
+
public QName getQName()
{
return qName;
@@ -215,7 +221,7 @@
return repeated;
}
- public Position startElement(QName qName, Attributes attrs)
+ public Position nextPosition(QName qName, Attributes attrs)
{
return startElement(qName, attrs, true);
}
@@ -225,20 +231,14 @@
throw new UnsupportedOperationException();
}
- public Object startParticle(Object parent, Attributes atts, NamespaceRegistry nsRegistry)
+ public Object initValue(Object parent, Attributes atts)
{
if(handler == null)
handler = getHandler(particle.getTerm());
- o = handler.startParticle(parent, qName, particle, atts, nsRegistry);
+ o = handler.startParticle(parent, qName, particle, atts, stack.nsRegistry);
return o;
}
-
- public void endParticle()
- {
- o = handler.endParticle(o, qName, particle);
- ended = true;
- }
-
+
public void reset()
{
if(!ended)
Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/ElementPosition.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/ElementPosition.java 2009-12-07 04:08:39 UTC (rev 3837)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/ElementPosition.java 2009-12-08 23:45:16 UTC (rev 3838)
@@ -21,10 +21,31 @@
*/
package org.jboss.xb.binding.sunday.unmarshalling.position;
+import java.util.Collections;
+import java.util.List;
+
import javax.xml.namespace.QName;
+import org.jboss.util.StringPropertyReplacer;
+import org.jboss.xb.binding.Constants;
+import org.jboss.xb.binding.JBossXBRuntimeException;
+import org.jboss.xb.binding.metadata.CharactersMetaData;
+import org.jboss.xb.binding.metadata.ValueMetaData;
+import org.jboss.xb.binding.sunday.unmarshalling.CharactersHandler;
+import org.jboss.xb.binding.sunday.unmarshalling.DefaultHandlers;
import org.jboss.xb.binding.sunday.unmarshalling.ElementBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.ElementInterceptor;
+import org.jboss.xb.binding.sunday.unmarshalling.ModelGroupBinding;
import org.jboss.xb.binding.sunday.unmarshalling.ParticleBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.ParticleHandler;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler;
+import org.jboss.xb.binding.sunday.unmarshalling.TermBeforeSetParentCallback;
+import org.jboss.xb.binding.sunday.unmarshalling.TermBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.TypeBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.WildcardBinding;
+import org.jboss.xb.binding.sunday.xop.XOPIncludeHandler;
+import org.xml.sax.Attributes;
/**
* A ElementPosition.
@@ -148,4 +169,424 @@
textContent.append(ch, start, length);
}
}
+
+ public void endParticle()
+ {
+ ElementBinding element = (ElementBinding) particle.getTerm();
+ TypeBinding type = element.getType();
+ List<ElementInterceptor> interceptors = element.getInterceptors();
+ List<ElementInterceptor> localInterceptors = parentType == null ? Collections.<ElementInterceptor>emptyList() : parentType.getInterceptors(qName);
+ int allInterceptors = interceptors.size() + localInterceptors.size();
+
+ if(o != SundayContentHandler.NIL)
+ {
+ //
+ // characters
+ //
+
+ flushIgnorableCharacters();
+
+ TypeBinding charType = type.getSimpleType();
+ if(charType == null)
+ charType = type;
+
+ CharactersHandler charHandler = ignoreCharacters ? null : charType.getCharactersHandler();
+
+ /**
+ * If there is text content then unmarshal it and set.
+ * If there is no text content and the type is simple and
+ * its characters handler is not null then unmarshal and set.
+ * If the type is complex and there is no text data then the unmarshalled value
+ * of the empty text content is assumed to be null
+ * (in case of simple types that's not always true and depends on nillable attribute).
+ */
+ String textContent = this.textContent == null ? "" : this.textContent.toString();
+ if(textContent.length() > 0 || charHandler != null && !type.isIgnoreEmptyString())
+ {
+ String dataContent;
+ SchemaBinding schema = element.getSchema();
+ if(textContent.length() == 0)
+ {
+ dataContent = null;
+ }
+ else
+ {
+ dataContent = textContent.toString();
+ if(schema != null && schema.isReplacePropertyRefs())
+ dataContent = StringPropertyReplacer.replaceProperties(dataContent);
+
+ if(element.isNormalizeSpace())
+ dataContent = dataContent.trim();
+ }
+
+ Object unmarshalled;
+
+ if(charHandler == null)
+ {
+ if(!type.isSimple() &&
+ schema != null &&
+ schema.isStrictSchema()
+ // todo this isSkip() doesn't look nice here
+ && !element.isSkip())
+ {
+ throw new JBossXBRuntimeException("Element " +
+ qName +
+ " with type binding " +
+ type.getQName() +
+ " does not include text content binding: " + dataContent
+ );
+ }
+ unmarshalled = dataContent;
+ }
+ else
+ {
+ ValueMetaData valueMetaData = element.getValueMetaData();
+ if(valueMetaData == null)
+ {
+ CharactersMetaData charactersMetaData = type.getCharactersMetaData();
+ if(charactersMetaData != null)
+ {
+ valueMetaData = charactersMetaData.getValue();
+ }
+ }
+
+ // todo valueMetaData is available from type
+ unmarshalled = dataContent == null ?
+ charHandler.unmarshalEmpty(qName, charType, stack.nsRegistry, valueMetaData) :
+ charHandler.unmarshal(qName, charType, stack.nsRegistry, valueMetaData, dataContent);
+ }
+
+ if(unmarshalled != null)
+ {
+ // if startElement returned null, we use characters as the object for this element
+ if(o == null)
+ {
+ o = unmarshalled;
+ }
+ else if(charHandler != null)
+ {
+ TermBeforeSetParentCallback beforeSetParent = charType.getBeforeSetParentCallback();
+ if(beforeSetParent != null)
+ {
+ stack.ctx.parent = o;
+ stack.ctx.particle = particle;
+ stack.ctx.parentParticle = stack.getNotSkippedParent().getParticle();
+ unmarshalled = beforeSetParent.beforeSetParent(unmarshalled, stack.ctx);
+ stack.ctx.clear();
+ }
+
+ charHandler.setValue(qName, element, o, unmarshalled);
+ }
+ }
+
+ if(allInterceptors > 0)
+ {
+ int interceptorIndex = stack.size() - 1 - allInterceptors;
+ for (int i = interceptors.size() - 1; i >= 0; --i)
+ {
+ ElementInterceptor interceptor = interceptors.get(i);
+ interceptor.characters(stack.peek(interceptorIndex++).getValue(), qName, type, stack.nsRegistry, dataContent);
+ }
+
+ for (int i = localInterceptors.size() - 1; i >= 0; --i)
+ {
+ ElementInterceptor interceptor = localInterceptors.get(i);
+ interceptor.characters(stack.peek(interceptorIndex++).getValue(), qName, type, stack.nsRegistry, dataContent);
+ }
+ }
+ }
+ }
+ else
+ {
+ o = null;
+ }
+
+ //
+ // endElement
+ //
+
+ o = handler.endParticle(o, qName, particle);
+
+ if(!interceptors.isEmpty())
+ {
+ int interceptorIndex = stack.size() - 1 - interceptors.size();
+ for (int i = interceptors.size() - 1; i >= 0; --i)
+ {
+ ElementInterceptor interceptor = interceptors.get(i);
+ interceptor.endElement(stack.peek(interceptorIndex++).getValue(), qName, type);
+ }
+ }
+
+ //
+ // setParent
+ //
+
+ if(allInterceptors == 0)
+ {
+ Position notSkippedParent = stack.getNotSkippedParent();
+ if (notSkippedParent != null)
+ {
+ ParticleBinding parentParticle = notSkippedParent.getParticle();
+ TermBinding parentTerm = parentParticle.getTerm();
+
+ if (notSkippedParent.getValue() != null)
+ {
+ ParticleHandler handler = this.handler;
+ if (parentTerm.isWildcard())
+ {
+ ParticleHandler wh = ((WildcardBinding) parentTerm).getWildcardHandler();
+ if (wh != null)
+ handler = wh;
+ }
+
+ if(notSkippedParent.getRepeatableParticleValue() == null)
+ {
+ TermBeforeSetParentCallback beforeSetParent = particle.getTerm().getBeforeSetParentCallback();
+ if(beforeSetParent != null)
+ {
+ stack.ctx.parent = notSkippedParent.getValue();
+ stack.ctx.particle = particle;
+ stack.ctx.parentParticle = stack.getNotSkippedParent().getParticle();
+ o = beforeSetParent.beforeSetParent(o, stack.ctx);
+ stack.ctx.clear();
+ }
+
+ handler.setParent(notSkippedParent.getValue(), o, qName, particle, notSkippedParent.getParticle());
+ }
+ else
+ {
+ notSkippedParent.getRepeatableHandler().addTermValue(
+ notSkippedParent.getRepeatableParticleValue(),
+ o, qName, particle,
+ notSkippedParent.getParticle(), handler);
+ }
+
+ //setParent(handler, notSkippedParent, this);
+ }
+ else if (parentTerm.isWildcard() && stack.size() > 1)
+ {
+ // the parent has anyType, so it gets the value of its child
+ for (int i = stack.size() - 2; i >= 0; --i)
+ {
+ Position peeked = stack.peek(i);
+ peeked.setValue(o);
+ if (peeked.isElement())
+ break;
+ }
+
+ if (trace)
+ log.trace("Value of " + qName + " " + o + " is promoted as the value of its parent element.");
+ }
+ }
+ }
+ else
+ {
+ Position popped = stack.pop();
+
+ for(int i = interceptors.size() - 1; i >= 0; --i)
+ {
+ ElementInterceptor interceptor = interceptors.get(i);
+ Object parent = stack.pop().getValue();
+ interceptor.add(parent, o, qName);
+ o = parent;
+ }
+
+ for(int i = localInterceptors.size() - 1; i >= 0; --i)
+ {
+ ElementInterceptor interceptor = localInterceptors.get(i);
+ Object parent = stack.pop().getValue();
+ interceptor.add(parent, o, qName);
+ o = parent;
+ }
+
+ // need to push it back to have correct endRepeatableParticle events
+ stack.push(popped);
+ }
+
+ ended = true;
+ }
+
+ public Position startParticle(QName startName, Attributes atts)
+ {
+ Position position = this;
+ if(ended)
+ {
+ if(qName.equals(startName))
+ {
+ if(particle.isRepeatable())
+ {
+ Position parentPosition = stack.peek1();
+ if(parentPosition.repeatTerm(startName, atts))
+ reset();
+ else if(parentPosition.getRepeatableParticleValue() != null)
+ stack.endRepeatableParticle(parentPosition, qName, particle, parentPosition.getParticle());
+ }
+ else
+ {
+ reset();
+ endRepeatableParent();
+ }
+ }
+ else if(particle.isRepeatable())
+ {
+ Position parentPosition = stack.peek1();
+ if(parentPosition.getRepeatableParticleValue() != null)
+ stack.endRepeatableParticle(parentPosition, qName, particle, parentPosition.getParticle());
+ }
+ }
+ else
+ {
+ ElementBinding element = (ElementBinding)particle.getTerm();
+ TypeBinding parentType = element.getType();
+ ParticleBinding typeParticle = parentType.getParticle();
+ ModelGroupBinding modelGroup = typeParticle == null ? null : (ModelGroupBinding)typeParticle.getTerm();
+ if(modelGroup == null)
+ {
+ if(startName.equals(Constants.QNAME_XOP_INCLUDE))
+ {
+ TypeBinding anyUriType = stack.schema.getType(Constants.QNAME_ANYURI);
+ if(anyUriType == null)
+ log.warn("Type " + Constants.QNAME_ANYURI + " not bound.");
+
+ ElementBinding parentElement = (ElementBinding) particle.getTerm();
+ parentElement.setXopUnmarshaller(stack.schema.getXopUnmarshaller());
+
+ flushIgnorableCharacters();
+ handler = DefaultHandlers.XOP_HANDLER;
+ ignoreCharacters = true;
+ initValue(o, null);
+
+ TypeBinding xopIncludeType = new TypeBinding(new QName(Constants.NS_XOP_INCLUDE, "Include"));
+ xopIncludeType.setSchemaBinding(stack.schema);
+ xopIncludeType.addAttribute(new QName("href"), anyUriType, DefaultHandlers.ATTRIBUTE_HANDLER);
+ xopIncludeType.setHandler(new XOPIncludeHandler(parentType, stack.schema.getXopUnmarshaller()));
+
+ ElementBinding xopInclude = new ElementBinding(stack.schema, Constants.QNAME_XOP_INCLUDE, xopIncludeType);
+ position = new ElementPosition(startName, new ParticleBinding(xopInclude));
+ return position;
+ }
+
+ QName typeName = parentType.getQName();
+ throw new JBossXBRuntimeException((typeName == null ? "Anonymous" : typeName.toString()) +
+ " type of element " + qName +
+ " should be complex and contain " + startName + " as a child element."
+ );
+ }
+
+ Position newPosition = modelGroup.newPosition(startName, atts, typeParticle);
+ if(newPosition == null)
+ {
+ throw new JBossXBRuntimeException(startName + " not found as a child of " + qName + " in " + modelGroup);
+ }
+ else
+ {
+ flushIgnorableCharacters();
+
+ Object value = o;
+ while(newPosition.getNext() != null)
+ {
+ if(newPosition.getParticle().isRepeatable())
+ stack.startRepeatableParticle(stack.peek(), value, startName, newPosition.getParticle());
+
+ stack.push(newPosition);
+ value = newPosition.initValue(o, atts);
+ newPosition.setParentType(parentType);
+ newPosition = newPosition.getNext();
+ }
+
+ position = newPosition;
+ position.setParentType(parentType);
+ if(!position.isElement())
+ throw new IllegalStateException();
+ }
+ }
+ return position;
+ }
+
+ private void endRepeatableParent()
+ {
+ int stackIndex = stack.size() - 2;
+ Position position;
+ Position parentPosition = stack.peek1();
+ while(true)
+ {
+ if(parentPosition.isElement())
+ {
+ throw new JBossXBRuntimeException(
+ "Failed to start " + qName +
+ ": the element is not repeatable, repeatable parent expected to be a model group but got element " +
+ ((ElementBinding)parentPosition.getParticle().getTerm()).getQName()
+ );
+ }
+
+ position = parentPosition;
+ if(position.getParticle().isRepeatable())
+ {
+ ((NonElementPosition)position).endParticle(stackIndex - 1);
+ parentPosition = stack.peek(stackIndex - 1);
+ position.reset();
+ position.initValue(parentPosition.getValue(), null);
+ break;
+ }
+
+ parentPosition = stack.peek(--stackIndex);
+ ((NonElementPosition)position).endParticle(stackIndex);
+ }
+
+/* if(!parentParticle.isRepeatable())
+ {
+ StringBuffer msg = new StringBuffer();
+
+ item = stack.peek();
+ ParticleBinding currentParticle = item.particle;
+ msg.append("Failed to start ").append(startName).append(": ")
+ .append(currentParticle.getTerm())
+ .append(" is not repeatable.")
+ .append(" Its parent ")
+ .append(parentParticle.getTerm())
+ .append(" expected to be repeatable!")
+ .append("\ncurrent stack: ");
+
+ for(int i = 0; i < stack.size() - 1; ++i)
+ {
+ item = stack.peek(i);
+ ParticleBinding particle = item.particle;
+ TermBinding term = particle.getTerm();
+ if(term.isModelGroup())
+ {
+ if(term instanceof SequenceBinding)
+ {
+ msg.append("sequence");
+ }
+ else if(term instanceof ChoiceBinding)
+ {
+ msg.append("choice");
+ }
+ else
+ {
+ msg.append("all");
+ }
+ }
+ else if(term.isWildcard())
+ {
+ msg.append("wildcard");
+ }
+ else
+ {
+ msg.append(((ElementBinding)term).getQName());
+ }
+ msg.append("\\");
+ }
+
+ throw new JBossXBRuntimeException(msg.toString());
+ }
+*/
+ while(++stackIndex < stack.size() - 1)
+ {
+ parentPosition = position;
+ position = stack.peek(stackIndex);
+ position.reset();
+ position.initValue(parentPosition.getValue(), null);
+ }
+ }
}
\ No newline at end of file
Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/NonElementPosition.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/NonElementPosition.java 2009-12-07 04:08:39 UTC (rev 3837)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/NonElementPosition.java 2009-12-08 23:45:16 UTC (rev 3838)
@@ -23,7 +23,12 @@
import javax.xml.namespace.QName;
+import org.jboss.xb.binding.JBossXBRuntimeException;
+import org.jboss.xb.binding.sunday.unmarshalling.ElementBinding;
import org.jboss.xb.binding.sunday.unmarshalling.ParticleBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.TermBeforeSetParentCallback;
+import org.jboss.xb.binding.sunday.unmarshalling.TermBinding;
+import org.xml.sax.Attributes;
/**
* @author <a href="alex at jboss.com">Alexey Loubyansky</a>
@@ -70,4 +75,111 @@
public void characters(char[] ch, int start, int length)
{
}
+
+ public void endParticle()
+ {
+ if(ended)
+ throw new JBossXBRuntimeException("The position has already been ended!");
+
+ o = handler.endParticle(o, qName, particle);
+ ended = true;
+
+ // model group should always have parent particle
+ Position parentPosition = stack.peek1();
+ if(parentPosition.getValue() != null)
+ setParent(parentPosition);
+ }
+
+ public void endParticle(int parentIdex)
+ {
+ if(ended)
+ throw new JBossXBRuntimeException("The position has already been ended!");
+
+ o = handler.endParticle(o, qName, particle);
+ ended = true;
+
+ // model group should always have parent particle
+ Position parentPosition = stack.getNotSkippedParent(parentIdex);
+ if(parentPosition.getValue() != null)
+ setParent(parentPosition);
+ }
+
+ private void setParent(Position parentPosition)
+ {
+ if(parentPosition.getRepeatableParticleValue() == null)
+ {
+ TermBeforeSetParentCallback beforeSetParent = particle.getTerm().getBeforeSetParentCallback();
+ if(beforeSetParent != null)
+ {
+ stack.ctx.parent = parentPosition.getValue();
+ stack.ctx.particle = particle;
+ stack.ctx.parentParticle = stack.getNotSkippedParent().getParticle();
+ o = beforeSetParent.beforeSetParent(o, stack.ctx);
+ stack.ctx.clear();
+ }
+
+ handler.setParent(parentPosition.getValue(), o, qName, particle, parentPosition.getParticle());
+ }
+ else
+ parentPosition.getRepeatableHandler().addTermValue(
+ parentPosition.getRepeatableParticleValue(),
+ o, qName, particle,
+ parentPosition.getParticle(), handler);
+ }
+
+ public Position startParticle(QName startName, Attributes atts)
+ {
+ ParticleBinding prevParticle = currentParticle;
+ Position newPosition = nextPosition(startName, atts);
+ if(newPosition == null)
+ {
+ if(!ended)
+ {
+ endParticle();
+
+ if(!particle.isRepeatable() && stack.peek1().isElement())
+ {
+ TermBinding t = particle.getTerm();
+ StringBuffer sb = new StringBuffer(250);
+ sb.append(startName).append(" cannot appear in this position. Expected content of ")
+ .append(((ElementBinding)stack.peek1().getParticle().getTerm()).getQName())
+ .append(" is ").append(t);
+ throw new JBossXBRuntimeException(sb.toString());
+ }
+ }
+ return this;
+ }
+ else
+ {
+ if(currentParticle != prevParticle)
+ {
+ if(getRepeatableParticleValue() != null &&
+ prevParticle != null && prevParticle.isRepeatable() && prevParticle.getTerm().isModelGroup())
+ {
+ stack.endRepeatableParticle(this, qName, prevParticle, particle);
+ }
+
+ if(newPosition.getNext() != null && currentParticle.isRepeatable() && !currentParticle.getTerm().isElement())
+ {
+ stack.startRepeatableParticle(this, o, startName, currentParticle);
+ }
+ }
+
+ // push all except the last one
+ Object value = o;
+ newPosition = newPosition.getNext();
+ while (newPosition.getNext() != null)
+ {
+ stack.push(newPosition);
+ value = newPosition.initValue(value, atts);
+ newPosition.setParentType(parentType);
+ newPosition = newPosition.getNext();
+ }
+
+ newPosition.setParentType(parentType);
+ if(!newPosition.isElement())
+ throw new IllegalStateException();
+ return newPosition;
+ }
+ }
}
\ No newline at end of file
Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/Position.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/Position.java 2009-12-07 04:08:39 UTC (rev 3837)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/position/Position.java 2009-12-08 23:45:16 UTC (rev 3838)
@@ -23,11 +23,11 @@
import javax.xml.namespace.QName;
-import org.jboss.xb.binding.NamespaceRegistry;
import org.jboss.xb.binding.sunday.unmarshalling.ParticleBinding;
import org.jboss.xb.binding.sunday.unmarshalling.ParticleHandler;
import org.jboss.xb.binding.sunday.unmarshalling.RepeatableParticleHandler;
import org.jboss.xb.binding.sunday.unmarshalling.TypeBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.StackImpl;
import org.xml.sax.Attributes;
/**
@@ -38,6 +38,8 @@
*/
public interface Position
{
+ void setStack(StackImpl stack);
+
QName getQName();
ParticleBinding getParticle();
@@ -78,12 +80,8 @@
void reset();
- Position startElement(QName qName, Attributes attrs);
+ Position nextPosition(QName qName, Attributes attrs);
- Object startParticle(Object parent, Attributes atts, NamespaceRegistry nsRegistry);
-
- void endParticle();
-
boolean repeatTerm(QName qName, Attributes atts);
ParticleBinding getCurrentParticle();
@@ -93,4 +91,10 @@
void flushIgnorableCharacters();
void characters(char[] ch, int start, int length);
+
+ Object initValue(Object parent, Attributes atts);
+
+ Position startParticle(QName startName, Attributes atts);
+
+ void endParticle();
}
More information about the jboss-svn-commits
mailing list