[jboss-svn-commits] JBoss Common SVN: r3767 - jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Nov 22 04:57:46 EST 2009


Author: alex.loubyansky at jboss.com
Date: 2009-11-22 04:57:46 -0500 (Sun, 22 Nov 2009)
New Revision: 3767

Modified:
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/AllBinding.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ChoiceBinding.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ModelGroupBinding.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SequenceBinding.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/TypeBinding.java
   jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/UnorderedSequenceBinding.java
Log:
refactoring ModelGroupBinding.Cursor into SundayContentHandler.StackItem, create Cursor only after the next particle has been actually found instead of creating one for each try during the search, renamed StackItem to Position

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/AllBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/AllBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/AllBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -75,45 +75,53 @@
 
    public Collection<ParticleBinding> getParticles()
    {
-      return Collections.unmodifiableCollection(elements.values());
+      return elements.values();
    }
 
-   public Cursor newCursor(ParticleBinding particle)
+   public ModelGroupPosition newPosition(QName qName, Attributes attrs, ParticleBinding allParticle)
    {
-      return new Cursor(particle)
+      ParticleBinding particle = elements.get(qName);
+      if(particle != null)
       {
-         protected ModelGroupBinding.Cursor startElement(QName qName, Attributes atts, Set<ModelGroupBinding> passedGroups, boolean required)
-         {
-            if(currentParticle != null && repeatTerm(qName, atts))
-               throw new IllegalStateException("maxOccurs in all model group can only be 1: " + qName);
+         return new AllPosition(qName, allParticle, particle);
+      }               
 
-            ParticleBinding particle = elements.get(qName);
-            if(particle != null)
-            {
-               currentParticle = particle;
-               occurence = 1;
-               return this;
-            }               
-
-            return null;
-         }
-
-         protected ElementBinding getElement(QName qName, Attributes atts, Set<ModelGroupBinding.Cursor> passedGroups, boolean ignoreWildcards)
-         {
-            ParticleBinding particle = elements.get(qName);
-            return particle == null ? null : (ElementBinding)particle.getTerm();
-         }
-      };
+      return null;
    }
 
-   protected boolean mayStartWith(QName qName, Set<ModelGroupBinding> set)
-   {
-      return elements.containsKey(qName);
-   }
-
    @Override
    public String getGroupType()
    {
       return "all";
    }
+   
+   private final class AllPosition extends ModelGroupPosition
+   {
+      private AllPosition(QName name, ParticleBinding particle, ParticleBinding currentParticle)
+      {
+         super(name, particle, currentParticle);
+      }
+
+      protected ModelGroupBinding.ModelGroupPosition startElement(QName qName, Attributes atts, boolean required)
+      {
+         if(currentParticle != null && repeatTerm(qName, atts))
+            throw new IllegalStateException("maxOccurs in all model group can only be 1: " + qName);
+
+         ParticleBinding particle = elements.get(qName);
+         if(particle != null)
+         {
+            currentParticle = particle;
+            occurrence = 1;
+            return this;
+         }               
+
+         return null;
+      }
+
+      protected ElementBinding getElement(QName qName, Attributes atts, Set<ModelGroupBinding.ModelGroupPosition> passedGroups, boolean ignoreWildcards)
+      {
+         ParticleBinding particle = elements.get(qName);
+         return particle == null ? null : (ElementBinding)particle.getTerm();
+      }
+   }
 }

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ChoiceBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ChoiceBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ChoiceBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -22,13 +22,10 @@
 package org.jboss.xb.binding.sunday.unmarshalling;
 
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Collection;
 import javax.xml.namespace.QName;
-import org.jboss.xb.binding.JBossXBRuntimeException;
 import org.xml.sax.Attributes;
 
 
@@ -72,131 +69,35 @@
       return choices;
    }
 
-   public Cursor newCursor(ParticleBinding particle)
+   public ModelGroupPosition newPosition(QName qName, Attributes attrs, ParticleBinding choiceParticle)
    {
-      return new Cursor(particle)
-      {         
-         protected ModelGroupBinding.Cursor startElement(QName qName, Attributes atts, Set<ModelGroupBinding> passedGroups, boolean required)
-         {
-            if(trace)
-            {
-               StringBuffer sb = new StringBuffer();
-               sb.append("startElement ").append(qName).append(" in ").append(ChoiceBinding.this.toString());
-               log.trace(sb.toString());
-            }
-
-            next = null;
-            
-            if(currentParticle != null)
-            {
-               if(repeatTerm(qName, atts))
-                  return this;
-               else
-                  return null;
-            }
-            
-            for(int i = 0; i < choices.size(); ++i)
-            {
-               boolean found = false;
-               ParticleBinding particle = (ParticleBinding)choices.get(i);
-               TermBinding item = particle.getTerm();
-               if(item.isElement())
-               {
-                  ElementBinding element = (ElementBinding)item;
-                  if(qName.equals(element.getQName()))
-                     found = true;
-               }
-               else if(item.isModelGroup())
-               {
-                  ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-                  if(!passedGroups.contains(modelGroup))
-                  {
-                     switch(passedGroups.size())
-                     {
-                        case 0:
-                           passedGroups = Collections.singleton((ModelGroupBinding)ChoiceBinding.this);
-                           break;
-                        case 1:
-                           passedGroups = new HashSet<ModelGroupBinding>(passedGroups);
-                        default:
-                           passedGroups.add(ChoiceBinding.this);
-                     }
-
-                     boolean isRequired = occurence == 0 ? false : particle.isRequired(occurence);
-                     next = modelGroup.newCursor(particle).startElement(qName, atts, passedGroups, isRequired);
-                     found = next != null;
-                  }
-               }
-               else if(item.isWildcard())
-               {
-                  WildcardBinding wildcard = (WildcardBinding)item;
-                  wildcardContent = wildcard.getElement(qName, atts);
-                  if(wildcardContent != null)
-                     found = true;
-               }
-               
-               if(found)
-               {
-                  occurence = 1;
-                  currentParticle = particle;
-                  if(trace)
-                     log.trace("found " + qName + " in " + ChoiceBinding.this + ", term=" + currentParticle.getTerm());
-                  return this;
-               }
-            }
-
-            return null;
-         }
-      };
-   }
-
-   protected boolean mayStartWith(QName qName, Set<ModelGroupBinding> set)
-   {
-      boolean result = false;
       for(int i = 0; i < choices.size(); ++i)
       {
-         ParticleBinding particle = choices.get(i);
+         ParticleBinding particle = (ParticleBinding)choices.get(i);
          TermBinding item = particle.getTerm();
          if(item.isElement())
          {
             ElementBinding element = (ElementBinding)item;
             if(qName.equals(element.getQName()))
-            {
-               result = true;
-               break;
-            }
+               return new ChoicePosition(qName, choiceParticle, particle);
          }
          else if(item.isModelGroup())
          {
             ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-            if(!set.contains(modelGroup))
-            {
-               switch(set.size())
-               {
-                  case 0:
-                     set = Collections.singleton((ModelGroupBinding)this);
-                     break;
-                  case 1:
-                     set = new HashSet<ModelGroupBinding>(set);
-                  default:
-                     set.add(this);
-               }
-
-               result = modelGroup.mayStartWith(qName, set);
-
-               if(result)
-               {
-                  break;
-               }
-            }
+            ModelGroupPosition next = modelGroup.newPosition(qName, attrs, particle);
+            if(next != null)
+               return new ChoicePosition(qName, choiceParticle, particle, next);
          }
-         else
+         else if(item.isWildcard())
          {
-            throw new JBossXBRuntimeException("Unexpected item type in model group: " + item);
+            WildcardBinding wildcard = (WildcardBinding)item;
+            ElementBinding wildcardContent = wildcard.getElement(qName, attrs);
+            if(wildcardContent != null)
+               return new ChoicePosition(qName, choiceParticle, particle, wildcardContent);
          }
       }
 
-      return result;
+      return null;
    }
 
    @Override
@@ -204,4 +105,79 @@
    {
       return "choice";
    }
+   
+   private final class ChoicePosition extends ModelGroupPosition
+   {
+      private ChoicePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle)
+      {
+         super(name, particle, currentParticle);
+      }
+
+      private ChoicePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ModelGroupPosition next)
+      {
+         super(name, particle, currentParticle, next);
+      }
+
+      private ChoicePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ElementBinding wildcardContent)
+      {
+         super(name, particle, currentParticle, wildcardContent);
+      }
+
+      protected ModelGroupBinding.ModelGroupPosition startElement(QName qName, Attributes atts, boolean required)
+      {
+         if(trace)
+         {
+            StringBuffer sb = new StringBuffer();
+            sb.append("startElement ").append(qName).append(" in ").append(ChoiceBinding.this.toString());
+            log.trace(sb.toString());
+         }
+
+         next = null;
+         
+         if(currentParticle != null)
+         {
+            if(repeatTerm(qName, atts))
+               return this;
+            else
+               return null;
+         }
+         
+         for(int i = 0; i < choices.size(); ++i)
+         {
+            boolean found = false;
+            ParticleBinding particle = (ParticleBinding)choices.get(i);
+            TermBinding item = particle.getTerm();
+            if(item.isElement())
+            {
+               ElementBinding element = (ElementBinding)item;
+               if(qName.equals(element.getQName()))
+                  found = true;
+            }
+            else if(item.isModelGroup())
+            {
+               ModelGroupBinding modelGroup = (ModelGroupBinding)item;
+               next = modelGroup.newPosition(qName, atts, particle);
+               found = next != null;
+            }
+            else if(item.isWildcard())
+            {
+               WildcardBinding wildcard = (WildcardBinding)item;
+               wildcardContent = wildcard.getElement(qName, atts);
+               if(wildcardContent != null)
+                  found = true;
+            }
+            
+            if(found)
+            {
+               occurrence = 1;
+               currentParticle = particle;
+               if(trace)
+                  log.trace("found " + qName + " in " + ChoiceBinding.this + ", term=" + currentParticle.getTerm());
+               return this;
+            }
+         }
+
+         return null;
+      }
+   }
 }

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ModelGroupBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ModelGroupBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/ModelGroupBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -22,14 +22,10 @@
 package org.jboss.xb.binding.sunday.unmarshalling;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
 
 import javax.xml.namespace.QName;
 
 import org.jboss.logging.Logger;
-import org.jboss.xb.binding.JBossXBRuntimeException;
 import org.xml.sax.Attributes;
 
 /**
@@ -38,7 +34,6 @@
  */
 public abstract class ModelGroupBinding
    extends TermBinding
-   implements Cloneable
 {
    protected final Logger log = Logger.getLogger(getClass());
 
@@ -109,23 +104,37 @@
       return requiredParticle;
    }
 
-   /**
-    * This method is not actually used during parsing. It's here only for internal tests.
-    *
-    * @param qName an element name
-    * @return true if the model group may start with the specified element
-    */
-   public boolean mayStartWith(QName qName)
+   public abstract ModelGroupPosition newPosition(QName qName, Attributes attrs, ParticleBinding particle);
+
+   public ElementBinding getElement(QName qName, Attributes attrs, boolean ignoreWildcards)
    {
-      return mayStartWith(qName, Collections.<ModelGroupBinding>emptySet());
+      ElementBinding element = null;
+      for (ParticleBinding nextParticle : getParticles())
+      {
+         TermBinding item = nextParticle.getTerm();
+         if (item.isElement())
+         {
+            ElementBinding choice = (ElementBinding)item;
+            if (qName.equals(choice.getQName()))
+               element = choice;
+         }
+         else if (item.isModelGroup())
+         {
+            ModelGroupBinding modelGroup = (ModelGroupBinding) item;
+            element = modelGroup.getElement(qName, attrs, ignoreWildcards);
+         }
+         else if (!ignoreWildcards)
+         {
+            WildcardBinding wildcard = (WildcardBinding)item;
+            element = wildcard.getElement(qName, attrs);
+         }
+         
+         if (element != null)
+            break;
+      }
+      return element;
    }
 
-   public abstract Cursor newCursor(ParticleBinding particle);
-
-   // Protected
-
-   protected abstract boolean mayStartWith(QName qName, Set<ModelGroupBinding> set);
-
    public boolean isSkip()
    {
       return skip == null || skip;
@@ -181,30 +190,64 @@
    public abstract String getGroupType();
 
    // Inner
-   public abstract class Cursor
+   public abstract class ModelGroupPosition extends SundayContentHandler.Position
    {
       protected final boolean trace = log.isTraceEnabled();
-      protected final ParticleBinding particle;
-      protected int occurence;
+      protected int occurrence;
 
       protected ParticleBinding currentParticle;
       protected ElementBinding wildcardContent;
 
-      protected Cursor next;
+      protected ModelGroupPosition next;
       
-      protected Cursor(ParticleBinding particle)
+      protected ModelGroupPosition(QName qName, ParticleBinding particle)
       {
+         super(qName, particle);
+         this.cursor = this;
          if(particle.getTerm() != ModelGroupBinding.this)
             throw new IllegalStateException("Particle term " + particle.getTerm() + " is not the model group " + ModelGroupBinding.this);
          this.particle = particle;
       }
 
+      protected ModelGroupPosition(QName name, ParticleBinding particle, ParticleBinding currentParticle)
+      {
+         this(name, particle);
+         this.currentParticle = currentParticle;
+         occurrence = 1; 
+      }
+
+      protected ModelGroupPosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ModelGroupPosition next)
+      {
+         this(name, particle);
+         this.currentParticle = currentParticle;
+         this.next = next;
+         occurrence = 1;
+      }
+
+      protected ModelGroupPosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ElementBinding wildcardContent)
+      {
+         this(name, particle);
+         this.currentParticle = currentParticle;
+         this.wildcardContent = wildcardContent;
+         occurrence = 1;
+      }
+
+      protected boolean isElement()
+      {
+         return false;
+      }
+      
+      protected boolean isModelGroup()
+      {
+         return true;
+      }
+
       public ParticleBinding getParticle()
       {
          return particle;
       }
 
-      public Cursor getNext()
+      public ModelGroupPosition getNext()
       {
          return next;
       }
@@ -224,32 +267,11 @@
          return wildcardContent;
       }
 
-      public ModelGroupBinding.Cursor startElement(QName qName, Attributes attrs)
+      public ModelGroupBinding.ModelGroupPosition startElement(QName qName, Attributes attrs)
       {
-         return startElement(qName, attrs, Collections.<ModelGroupBinding>emptySet(), true);
+         return startElement(qName, attrs, true);
       }
 
-      public ElementBinding getElement(QName qName, Attributes attrs, boolean ignoreWildcards)
-      {
-         return getElement(qName, attrs, Collections.<Cursor>emptySet(), ignoreWildcards);
-      }
-
-/*      public void endElement(QName qName)
-      {
-         TermBinding term = getCurrentParticle().getTerm();
-         ElementBinding element = term.isWildcard() ? getWildcardContent() : (ElementBinding) term;
-         if(element == null || !element.getQName().equals(qName))
-         {
-            throw new JBossXBRuntimeException("Failed to process endElement for " + qName +
-               " since the current element is " + (element == null ? "null" : element.getQName().toString())
-            );
-         }
-
-         if(trace)
-            log.trace("endElement " + qName + " in " + ModelGroupBinding.this);
-      }
-*/
-
       public boolean repeatTerm(QName qName, Attributes atts)
       {
          if(currentParticle == null)
@@ -257,8 +279,8 @@
          
          boolean repeated = false;
          if(currentParticle.getMaxOccursUnbounded() ||
-            occurence < currentParticle.getMinOccurs() ||
-            occurence < currentParticle.getMaxOccurs())
+            occurrence < currentParticle.getMinOccurs() ||
+            occurrence < currentParticle.getMaxOccurs())
          {
             TermBinding item = currentParticle.getTerm();
             if(item.isElement())
@@ -269,8 +291,7 @@
             else if(item.isModelGroup())
             {
                ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-               boolean isRequired = occurence == 0 ? false : currentParticle.isRequired(occurence);
-               next = modelGroup.newCursor(currentParticle).startElement(qName, atts, Collections.<ModelGroupBinding>emptySet(), isRequired);
+               next = modelGroup.newPosition(qName, atts, currentParticle);
                repeated = next != null;
             }
             else if(item.isWildcard())
@@ -283,90 +304,20 @@
 
          if(repeated)
          {
-            ++occurence;
+            ++occurrence;
             if(trace)
-               log.trace("repeated " + qName + " in " + ModelGroupBinding.this + ", occurence=" + occurence + ", term=" + currentParticle.getTerm());
+               log.trace("repeated " + qName + " in " + ModelGroupBinding.this + ", occurence=" + occurrence + ", term=" + currentParticle.getTerm());
          }
          else
          {
             wildcardContent = null;
             currentParticle = null;
-            occurence = 0;
+            occurrence = 0;
          }
 
          return repeated;
       }
 
-      // Protected
-
-      protected abstract ModelGroupBinding.Cursor startElement(QName qName,
-            Attributes atts,
-            Set<ModelGroupBinding> passedGroups,
-            boolean required);
-
-      protected ElementBinding getElement(QName qName, Attributes atts, Set<ModelGroupBinding.Cursor> passedGroups, boolean ignoreWildcards)
-      {
-         ElementBinding element = null;
-         for (ParticleBinding nextParticle : getParticles())
-         {
-            TermBinding item = nextParticle.getTerm();
-            if (item.isElement())
-            {
-               ElementBinding choice = (ElementBinding)item;
-               if (qName.equals(choice.getQName()))
-               {
-                  element = choice;
-                  break;
-               }
-            }
-            else if (item.isModelGroup())
-            {
-               ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-               if (passedGroups.contains(modelGroup) == false) // FIX-ME ... weird set usage
-               {
-                  switch (passedGroups.size())
-                  {
-                     case 0:
-                        passedGroups = Collections.singleton(this);
-                        break;
-                     case 1:
-                        passedGroups = new HashSet<Cursor>(passedGroups);
-                     default:
-                        passedGroups.add(this);
-                  }
-
-                  ElementBinding e = modelGroup.newCursor(nextParticle).getElement(qName, atts, passedGroups, ignoreWildcards);
-                  if (e != null)
-                  {
-                     element = e;
-                     if (!qName.equals(e.getQName()))
-                     {
-                        throw new JBossXBRuntimeException(
-                              "There is a bug in ModelGroupBinding.Cursor.getElement(QName,Attributes) impl"
-                        );
-                     }
-                     break;
-                  }
-               }
-            }
-            else if (!ignoreWildcards)
-            {
-               WildcardBinding wildcard = (WildcardBinding)item;
-               ElementBinding e = wildcard.getElement(qName, atts);
-               if (e != null)
-               {
-                  element = e;
-                  if (!qName.equals(e.getQName()))
-                  {
-                     throw new JBossXBRuntimeException(
-                           "There is a bug in ModelGroupBinding.Cursor.getElement(QName,Attributes) impl"
-                     );
-                  }
-                  break;
-               }
-            }
-         }
-         return element;
-      }
+      protected abstract ModelGroupBinding.ModelGroupPosition startElement(QName qName, Attributes atts, boolean required);
    }
 }

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SequenceBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SequenceBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SequenceBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -23,9 +23,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.Collection;
 import javax.xml.namespace.QName;
 import org.jboss.xb.binding.JBossXBRuntimeException;
@@ -81,215 +79,184 @@
       return sequence;
    }
 
-   public Cursor newCursor(ParticleBinding particle)
+   public ModelGroupPosition newPosition(QName qName, Attributes attrs, ParticleBinding seqParticle)
    {
-      return new Cursor(particle)
+      for(int i = 0; i < sequence.size(); ++i)
       {
-         private int pos = -1;
+         ParticleBinding particle = sequence.get(i);
+         TermBinding term = particle.getTerm();
+         if(term.isElement())
+         {
+            ElementBinding element = (ElementBinding)term;
+            if(qName.equals(element.getQName()))
+               return new SequencePosition(qName, seqParticle, i, particle);
+         }
+         else if(term.isModelGroup())
+         {
+            ModelGroupBinding modelGroup = (ModelGroupBinding)term;
+            ModelGroupPosition next = modelGroup.newPosition(qName, attrs, particle);
+            if(next != null)
+               return new SequencePosition(qName, seqParticle, i, particle, next);
+         }
+         else if(term.isWildcard())
+         {
+            WildcardBinding wildcard = (WildcardBinding)term;
+            ElementBinding wildcardContent = wildcard.getElement(qName, attrs);
+            if(wildcardContent != null)
+               return new SequencePosition(qName, seqParticle, i, particle, wildcardContent);
+         }
+         
+         if(particle.isRequired())
+         {
+/*            StringBuffer sb = new StringBuffer(250);
+            sb.append(qName).append(" cannot appear in this position in group ")
+            .append(SequenceBinding.this.toString());
+            throw new JBossXBRuntimeException(sb.toString());
+*/            break;
+         }
+      }
+      
+      return null;
+   }
 
-         protected ModelGroupBinding.Cursor startElement(QName qName, Attributes atts, Set<ModelGroupBinding> passedGroups, boolean required)
+   @Override
+   public String getGroupType()
+   {
+      return "sequence";
+   }
+   
+   private final class SequencePosition extends ModelGroupPosition
+   {
+      private int pos = -1;
+
+      protected SequencePosition(QName qName, ParticleBinding particle, int pos, ParticleBinding currentParticle)
+      {
+         super(qName, particle, currentParticle);
+         this.pos = pos;
+      }
+
+      protected SequencePosition(QName qName, ParticleBinding particle, int pos, ParticleBinding currentParticle, ModelGroupPosition next)
+      {
+         super(qName, particle, currentParticle, next);
+         this.pos = pos;
+      }
+
+      protected SequencePosition(QName qName, ParticleBinding particle, int pos, ParticleBinding currentParticle, ElementBinding wildcardContent)
+      {
+         super(qName, particle, currentParticle, wildcardContent);
+         this.pos = pos;
+      }
+
+      protected ModelGroupBinding.ModelGroupPosition startElement(QName qName, Attributes atts, boolean required)
+      {
+         if(trace)
          {
-            if(trace)
-            {
-               StringBuffer sb = new StringBuffer();
-               sb.append("startElement ").append(qName).append(" in ").append(SequenceBinding.this.toString());
-               log.trace(sb.toString());
-            }
+            StringBuffer sb = new StringBuffer();
+            sb.append("startElement ").append(qName).append(" in ").append(SequenceBinding.this.toString());
+            log.trace(sb.toString());
+         }
 
-            next = null;
+         next = null;
 
-            // if positioned try repeating
-            if(currentParticle != null && repeatTerm(qName, atts))
-               return this;
-            
-            // this will be the first occurence
-            
-            // i update pos only if the element has been found, though it seems to be irrelevant
-            // since the cursor is going to be thrown away in case the element has not been found
-            int i = pos;
-            while(i < sequence.size() - 1)
+         // if positioned try repeating
+         if(currentParticle != null && repeatTerm(qName, atts))
+            return this;
+         
+         // this will be the first occurrence
+         
+         int i = pos;
+         while(i < sequence.size() - 1)
+         {
+            ParticleBinding particle = sequence.get(++i);
+            TermBinding item = particle.getTerm();
+            if(item.isElement())
             {
-               ParticleBinding particle = sequence.get(++i);
-               TermBinding item = particle.getTerm();
-               if(item.isElement())
+               ElementBinding element = (ElementBinding)item;
+               if(qName.equals(element.getQName()))
                {
-                  ElementBinding element = (ElementBinding)item;
-                  if(qName.equals(element.getQName()))
-                  {
-                     pos = i;
-                     occurence = 1;
-                     currentParticle = particle;
+                  pos = i;
+                  occurrence = 1;
+                  currentParticle = particle;
 
-                     if(trace)
-                        log.trace("found " + qName + " in " + SequenceBinding.this);
-                     return this;
-                  }
-
-                  if(particle.getMinOccurs() > 0)
-                  {
-                     if(required)
-                     {
-                        StringBuffer sb = new StringBuffer(250);
-                        sb.append(qName).append(" cannot appear in this position in group ")
-                        .append(SequenceBinding.this.toString());
-                        throw new JBossXBRuntimeException(sb.toString());
-                     }
-                     else
-                     {
-                        break;
-                     }
-                  }
+                  if(trace)
+                     log.trace("found " + qName + " in " + SequenceBinding.this);
+                  return this;
                }
-               else if(item.isModelGroup())
+
+               if(particle.getMinOccurs() > 0)
                {
-                  ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-                  if(!passedGroups.contains(modelGroup))
+                  if(required)
                   {
-                     switch(passedGroups.size())
-                     {
-                        case 0:
-                           passedGroups = Collections.singleton((ModelGroupBinding)SequenceBinding.this);
-                           break;
-                        case 1:
-                           passedGroups = new HashSet<ModelGroupBinding>(passedGroups);
-                        default:
-                           passedGroups.add(SequenceBinding.this);
-                     }
-
-                     next = modelGroup.newCursor(particle).startElement(
-                        qName, atts, passedGroups, particle.isRequired(occurence)
-                     );
-
-                     if(next != null)
-                     {
-                        pos = i;
-                        occurence = 1;
-                        currentParticle = particle;
-                        return this;
-                     }
-
-                     if(particle.isRequired())
-                     {
-                        if(required)
-                        {
-                           throw new JBossXBRuntimeException("Requested element " + qName +
-                              " is not allowed in this position in the sequence. A model group with minOccurs=" +
-                              particle.getMinOccurs() + " that doesn't contain this element must follow."
-                           );
-                        }
-                        else
-                        {
-                           break;
-                        }
-                     }
+                     StringBuffer sb = new StringBuffer(250);
+                     sb.append(qName).append(" cannot appear in this position in group ")
+                     .append(SequenceBinding.this.toString());
+                     throw new JBossXBRuntimeException(sb.toString());
                   }
-                  else if(particle.isRequired())
+                  else
                   {
-                     if(required)
-                     {
-                        throw new JBossXBRuntimeException("Requested element " + qName +
-                           " is not allowed in this position in the sequence. A model group with minOccurs=" +
-                           particle.getMinOccurs() + " that doesn't contain this element must follow."
-                        );
-                     }
-                     else
-                     {
-                        break;
-                     }
+                     break;
                   }
                }
-               else if(item.isWildcard())
+            }
+            else if(item.isModelGroup())
+            {
+               ModelGroupBinding modelGroup = (ModelGroupBinding) item;
+               next = modelGroup.newPosition(qName, atts, particle);
+
+               if (next != null)
                {
-                  WildcardBinding wildcard = (WildcardBinding)item;
-                  wildcardContent = wildcard.getElement(qName, atts);
-                  if(wildcardContent != null)
+                  pos = i;
+                  occurrence = 1;
+                  currentParticle = particle;
+                  return this;
+               }
+
+               if (particle.isRequired())
+               {
+                  if (required)
                   {
-                     pos = i;
-                     occurence = 1;
-                     currentParticle = particle;
-                     return this;
+                     throw new JBossXBRuntimeException("Requested element " + qName
+                           + " is not allowed in this position in the sequence. A model group with minOccurs="
+                           + particle.getMinOccurs() + " that doesn't contain this element must follow.");
                   }
-
-                  if(particle.getMinOccurs() > 0)
+                  else
                   {
-                     if(required)
-                     {
-                        throw new JBossXBRuntimeException("Requested element " + qName +
-                           " is not allowed in this position in the sequence."
-                        );
-                     }
-                     else
-                     {
-                        break;
-                     }
+                     break;
                   }
                }
             }
-
-            if(trace && i == sequence.size())
-               log.trace(qName + " not found in " + SequenceBinding.this);
-
-            return null;
-         }
-      };
-   }
-
-   protected boolean mayStartWith(QName qName, Set<ModelGroupBinding> set)
-   {
-      boolean result = false;
-      for(int i = 0; i < sequence.size(); ++i)
-      {
-         ParticleBinding particle = (ParticleBinding)sequence.get(i);
-         Object item = particle.getTerm();
-         if(item instanceof ElementBinding)
-         {
-            ElementBinding element = (ElementBinding)item;
-            if(qName.equals(element.getQName()))
+            else if(item.isWildcard())
             {
-               result = true;
-               break;
-            }
-
-            if(particle.getMinOccurs() > 0)
-            {
-               break;
-            }
-         }
-         else if(item instanceof ModelGroupBinding)
-         {
-            ModelGroupBinding modelGroup = (ModelGroupBinding)item;
-            if(!set.contains(modelGroup))
-            {
-               switch(set.size())
+               WildcardBinding wildcard = (WildcardBinding)item;
+               wildcardContent = wildcard.getElement(qName, atts);
+               if(wildcardContent != null)
                {
-                  case 0:
-                     set = Collections.singleton((ModelGroupBinding)this);
-                     break;
-                  case 1:
-                     set = new HashSet<ModelGroupBinding>(set);
-                  default:
-                     set.add(this);
+                  pos = i;
+                  occurrence = 1;
+                  currentParticle = particle;
+                  return this;
                }
 
-               result = modelGroup.mayStartWith(qName, set);
-
-               if(result || particle.getMinOccurs() > 0)
+               if(particle.getMinOccurs() > 0)
                {
-                  break;
+                  if(required)
+                  {
+                     throw new JBossXBRuntimeException("Requested element " + qName +
+                        " is not allowed in this position in the sequence."
+                     );
+                  }
+                  else
+                  {
+                     break;
+                  }
                }
             }
-            else if(particle.getMinOccurs() > 0)
-            {
-               break;
-            }
          }
+
+         if(trace && i == sequence.size())
+            log.trace(qName + " not found in " + SequenceBinding.this);
+
+         return null;
       }
-      return result;
    }
-
-   @Override
-   public String getGroupType()
-   {
-      return "sequence";
-   }
 }

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-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -102,44 +102,42 @@
 
    public void characters(char[] ch, int start, int length)
    {
-      StackItem stackItem = stack.peek();
-      if(stackItem.cursor != null)
-      {
+      Position position = stack.peek();
+      if(position.isModelGroup())
          return;
-      }
       
-      ElementBinding e = (ElementBinding) stackItem.particle.getTerm();
+      ElementBinding e = (ElementBinding) position.particle.getTerm();
       // if current is ended the characters belong to its parent
-      if(stackItem.ended)
+      if(position.ended)
       {
-         stackItem = stack.peek1();
-         if(stackItem.cursor != null)
+         position = stack.peek1();
+         if(position.isModelGroup())
          {
             for(int i = stack.size() - 3; i >= 0; --i)
             {
-               stackItem = stack.peek(i);
-               if(stackItem.cursor == null)
+               position = stack.peek(i);
+               if(position.isElement())
                   break;
             }
          }
-         e = (ElementBinding) stackItem.particle.getTerm();
+         e = (ElementBinding) position.particle.getTerm();
       }
 
       // collect characters only if they are allowed content
       if(e.getType().isTextContentAllowed())
       {
-         if(stackItem.indentation != Boolean.FALSE)
+         if(position.indentation != Boolean.FALSE)
          {
             if(e.getType().isSimple())
             {
                // simple content is not analyzed
-               stackItem.indentation = Boolean.FALSE;
-               stackItem.ignorableCharacters = false;
+               position.indentation = Boolean.FALSE;
+               position.ignorableCharacters = false;
             }
             else if(e.getSchema() != null && !e.getSchema().isIgnoreWhitespacesInMixedContent())
             {
-               stackItem.indentation = Boolean.FALSE;
-               stackItem.ignorableCharacters = false;
+               position.indentation = Boolean.FALSE;
+               position.ignorableCharacters = false;
             }
             else
             {
@@ -149,23 +147,23 @@
                {
                   if(ch[i] == 0x0a)
                   {
-                     stackItem.indentation = Boolean.TRUE;
+                     position.indentation = Boolean.TRUE;
                   }
                   else if (!Character.isWhitespace(ch[i]))
                   {
-                     stackItem.indentation = Boolean.FALSE;
-                     stackItem.ignorableCharacters = false;
+                     position.indentation = Boolean.FALSE;
+                     position.ignorableCharacters = false;
                      break;
                   }
                }
             }
          }
          
-         if (stackItem.textContent == null)
+         if (position.textContent == null)
          {
-            stackItem.textContent = new StringBuffer();
+            position.textContent = new StringBuffer();
          }
-         stackItem.textContent.append(ch, start, length);
+         position.textContent.append(ch, start, length);
       }
    }
 
@@ -173,53 +171,53 @@
    {
       ElementBinding elementBinding = null;
       QName endName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
-      StackItem item;
+      Position position;
       while(true)
       {
-         item = stack.peek();
-         if(item.cursor == null)
+         position = stack.peek();
+         if(position.isElement())
          {
-            if(item.ended)
+            if(position.ended)
             {
                pop();
-               if(item.particle.isRepeatable())
+               if(position.particle.isRepeatable())
                {
-                  StackItem parentItem = stack.peek();
-                  if(parentItem.repeatableParticleValue != null)
+                  Position parentPosition = stack.peek();
+                  if(parentPosition.repeatableParticleValue != null)
                   {
                      // TODO this has to be done for every endRepeatableParticle
-                     StackItem notSkippedParent = parentItem;
-                     if(parentItem.particle.getTerm().isSkip())
+                     Position notSkippedParent = parentPosition;
+                     if(parentPosition.particle.getTerm().isSkip())
                         notSkippedParent = stack.peek1();
                      int i = stack.size() - 2;
                      while(notSkippedParent.particle.getTerm().isSkip() && i >= 0)
                         notSkippedParent = stack.peek(i--);
-                     endRepeatableParticle(parentItem, item.qName, item.particle, notSkippedParent.particle);
+                     endRepeatableParticle(parentPosition, position.qName, position.particle, notSkippedParent.particle);
                   }
                }
             }
             else
             {
-               elementBinding = (ElementBinding)item.particle.getTerm();
-               item.ended = true;
+               elementBinding = (ElementBinding)position.particle.getTerm();
+               position.ended = true;
                break;
             }
          }
          else
          {
-            if(!item.ended) // could be ended if it's a choice
-               endParticle(item, stack.peek1());
+            if(!position.ended) // could be ended if it's a choice
+               endParticle(position, stack.peek1());
 
-            ParticleBinding currentParticle = item.cursor.getCurrentParticle();
-            if(item.repeatableParticleValue != null && currentParticle.getTerm().isWildcard())
-               endRepeatableParticle(item, item.qName, currentParticle, item.particle);
+            ParticleBinding currentParticle = position.cursor.getCurrentParticle();
+            if(position.repeatableParticleValue != null && currentParticle.getTerm().isWildcard())
+               endRepeatableParticle(position, position.qName, currentParticle, position.particle);
 
             pop();
-            if(item.particle.isRepeatable())
+            if(position.particle.isRepeatable())
             {
-               StackItem parentItem = stack.peek();
-               if(parentItem.repeatableParticleValue != null)
-                  endRepeatableParticle(parentItem, item.qName, item.particle, parentItem.particle);
+               Position parentPosition = stack.peek();
+               if(parentPosition.repeatableParticleValue != null)
+                  endRepeatableParticle(parentPosition, position.qName, position.particle, parentPosition.particle);
             }
          }
       }
@@ -250,8 +248,8 @@
       TypeBinding parentType = null;
       boolean repeated = false;
       boolean repeatedParticle = false;
-      StackItem item = null;
-      ModelGroupBinding.Cursor cursor = null; // used only when particle is a wildcard
+      Position position = null;
+      ModelGroupBinding.ModelGroupPosition groupPosition = null; // used only when particle is a wildcard
       SchemaBinding schemaBinding = schema;
 
       atts = preprocessAttributes(atts);
@@ -291,38 +289,38 @@
       {
          while(!stack.isEmpty())
          {
-            item = stack.peek();
-            if(item.cursor == null)
+            position = stack.peek();
+            if(position.isElement())
             {
-               TermBinding term = item.particle.getTerm();
+               TermBinding term = position.particle.getTerm();
                ElementBinding element = (ElementBinding)term;
-               if(item.ended)
+               if(position.ended)
                {
                   if(element.getQName().equals(startName))
                   {
-                     if(item.particle.isRepeatable())
+                     if(position.particle.isRepeatable())
                      {
-                        StackItem parentItem = stack.peek1();
-                        if(parentItem.cursor.repeatTerm(startName, atts))
+                        Position parentPosition = stack.peek1();
+                        if(parentPosition.cursor.repeatTerm(startName, atts))
                         {
-                           item.reset();
-                           particle = item.particle;
-                           parentType = item.parentType;
+                           position.reset();
+                           particle = position.particle;
+                           parentType = position.parentType;
                            repeated = true;
                         }
                         else
                         {
                            pop();
-                           if(parentItem.repeatableParticleValue != null)
-                              endRepeatableParticle(parentItem, item.qName, item.particle, parentItem.particle);
+                           if(parentPosition.repeatableParticleValue != null)
+                              endRepeatableParticle(parentPosition, position.qName, position.particle, parentPosition.particle);
                            continue;
                         }
                      }
                      else
                      {
-                        item.reset();
-                        particle = item.particle;
-                        parentType = item.parentType;
+                        position.reset();
+                        particle = position.particle;
+                        parentType = position.parentType;
                         repeated = true;
 
                         endRepeatableParent(startName);
@@ -331,12 +329,12 @@
                   else
                   {
                      pop();                     
-                     if(item.particle.isRepeatable())
+                     if(position.particle.isRepeatable())
                      {
-                        StackItem parentItem = stack.peek();
-                        if(parentItem.repeatableParticleValue != null)
+                        Position parentPosition = stack.peek();
+                        if(parentPosition.repeatableParticleValue != null)
                         {
-                           endRepeatableParticle(parentItem, item.qName, item.particle, parentItem.particle);
+                           endRepeatableParticle(parentPosition, position.qName, position.particle, parentPosition.particle);
                         }
                      }
                      continue;
@@ -366,13 +364,13 @@
 
                         particle = new ParticleBinding(xopInclude);
                         
-                        ElementBinding parentElement = (ElementBinding) item.particle.getTerm();
+                        ElementBinding parentElement = (ElementBinding) position.particle.getTerm();
                         parentElement.setXopUnmarshaller(schema.getXopUnmarshaller());
 
                         flushIgnorableCharacters();
-                        item.handler = DefaultHandlers.XOP_HANDLER;
-                        item.ignoreCharacters = true;
-                        item.o = item.handler.startParticle(stack.peek().o, startName, stack.peek().particle, null, nsRegistry);
+                        position.handler = DefaultHandlers.XOP_HANDLER;
+                        position.ignoreCharacters = true;
+                        position.o = position.handler.startParticle(stack.peek().o, startName, stack.peek().particle, null, nsRegistry);
                         break;
                      }
 
@@ -384,9 +382,8 @@
                      );
                   }
 
-                  cursor = modelGroup.newCursor(typeParticle);
-                  ModelGroupBinding.Cursor newCursor = cursor.startElement(startName, atts);
-                  if(newCursor == null)
+                  ModelGroupBinding.ModelGroupPosition newPosition = modelGroup.newPosition(startName, atts, typeParticle);
+                  if(newPosition == null)
                   {
                      throw new JBossXBRuntimeException(startName +
                         " not found as a child of " +
@@ -397,42 +394,42 @@
                   {
                      flushIgnorableCharacters();
 
-                     Object o = item.o;
-                     while(newCursor != null)
+                     Object o = position.o;
+                     while(newPosition != null)
                      {
-                        cursor = newCursor;
-                        ParticleBinding modelGroupParticle = cursor.getParticle();
+                        groupPosition = newPosition;
+                        ParticleBinding modelGroupParticle = groupPosition.getParticle();
                         if(modelGroupParticle.isRepeatable())
                            startRepeatableParticle(stack.peek(), o, startName, modelGroupParticle);
 
                         handler = getHandler(modelGroupParticle);
                         o = handler.startParticle(o, startName, modelGroupParticle, atts, nsRegistry);
-                        push(startName, cursor, o, handler, parentType);
+                        push(groupPosition, o, handler, parentType);
                         
-                        newCursor = newCursor.getNext();
+                        newPosition = newPosition.getNext();
                      }
-                     particle = cursor.getCurrentParticle();
+                     particle = groupPosition.getCurrentParticle();
                   }                  
                }
                break;
             }
             else
             {
-               cursor = item.cursor;
-               if(cursor == null)
+               groupPosition = position.cursor;
+               if(groupPosition == null)
                   throw new JBossXBRuntimeException("No cursor for " + startName);
 
-               ParticleBinding prevParticle = cursor.getCurrentParticle();
-               ModelGroupBinding.Cursor newCursor = cursor.startElement(startName, atts);               
-               if(newCursor == null)
+               ParticleBinding prevParticle = groupPosition.getCurrentParticle();
+               ModelGroupBinding.ModelGroupPosition newPosition = groupPosition.startElement(startName, atts);               
+               if(newPosition == null)
                {
-                  if(!item.ended)
-                     endParticle(item, stack.peek1());
+                  if(!position.ended)
+                     endParticle(position, stack.peek1());
                                     
-                  StackItem poped = pop();
-                  if(!poped.particle.isRepeatable() && stack.peek().cursor == null)
+                  Position poped = pop();
+                  if(!poped.particle.isRepeatable() && stack.peek().isElement())
                   {
-                     TermBinding t = cursor.getParticle().getTerm();
+                     TermBinding t = groupPosition.getParticle().getTerm();
                      StringBuffer sb = new StringBuffer(250);
                      sb.append(startName).append(" cannot appear in this position. Expected content of ")
                      .append(((ElementBinding)stack.peek().particle.getTerm()).getQName())
@@ -442,26 +439,26 @@
                }
                else
                {
-                  if(item.ended) // for repeatable choices
+                  if(position.ended) // for repeatable choices
                   {
-                     if(!item.particle.isRepeatable())
-                        throw new JBossXBRuntimeException("The particle expected to be repeatable but it's not: " + item.particle.getTerm());
+                     if(!position.particle.isRepeatable())
+                        throw new JBossXBRuntimeException("The particle expected to be repeatable but it's not: " + position.particle.getTerm());
                      
-                     item.reset();                     
-                     handler = getHandler(item.particle);
-                     item.o = handler.startParticle(stack.peek1().o, startName, item.particle, atts, nsRegistry);
+                     position.reset();                     
+                     handler = getHandler(position.particle);
+                     position.o = handler.startParticle(stack.peek1().o, startName, position.particle, atts, nsRegistry);
                   }
                   
-                  ParticleBinding curParticle = cursor.getCurrentParticle();
+                  ParticleBinding curParticle = groupPosition.getCurrentParticle();
                   if(curParticle != prevParticle)
                   {
-                     if(item.repeatableParticleValue != null &&
+                     if(position.repeatableParticleValue != null &&
                            prevParticle != null && prevParticle.isRepeatable() && prevParticle.getTerm().isModelGroup())
                      {
-                        endRepeatableParticle(item, item.qName, prevParticle, item.particle);
+                        endRepeatableParticle(position, position.qName, prevParticle, position.particle);
                      }
 
-                     if(newCursor.getNext() != null && curParticle.isRepeatable())
+                     if(newPosition.getNext() != null && curParticle.isRepeatable())
                      {
                         startRepeatableParticle(stack.peek1(), stack.peek1().o, startName, curParticle);
                      }
@@ -472,21 +469,21 @@
                   }
 
                   // push all except the last one
-                  parentType = item.parentType;
-                  Object o = item.o;
-                  cursor = newCursor;
-                  newCursor = newCursor.getNext();
-                  while(newCursor != null)
+                  parentType = position.parentType;
+                  Object o = position.o;
+                  groupPosition = newPosition;
+                  newPosition = newPosition.getNext();
+                  while(newPosition != null)
                   {
-                     cursor = newCursor;
-                     ParticleBinding modelGroupParticle = cursor.getParticle();
+                     groupPosition = newPosition;
+                     ParticleBinding modelGroupParticle = groupPosition.getParticle();
                      handler = getHandler(modelGroupParticle);
                      o = handler.startParticle(o, startName, modelGroupParticle, atts, nsRegistry);
-                     push(startName, cursor, o, handler, parentType);
+                     push(groupPosition, o, handler, parentType);
                      
-                     newCursor = newCursor.getNext();
+                     newPosition = newPosition.getNext();
                   }
-                  particle = cursor.getCurrentParticle();
+                  particle = groupPosition.getCurrentParticle();
                   break;
                }
             }
@@ -500,7 +497,7 @@
             (repeated ? stack.peek1().o : stack.peek().o);
          if(particle.getTerm().isWildcard())
          {
-            ElementBinding element = cursor.getWildcardContent();
+            ElementBinding element = groupPosition.getWildcardContent();
             if(element == null)
                throw new JBossXBRuntimeException("Failed to resolve element " + startName + " for wildcard.");
 
@@ -519,8 +516,8 @@
             if(trace)
                log.trace(element.getQName() + " uses xsi:type " + xsiType);
 
-            if(item != null && item.nonXsiParticle == null)
-               item.nonXsiParticle = particle;
+            if(position != null && position.nonXsiParticle == null)
+               position.nonXsiParticle = particle;
             
             String xsiTypePrefix;
             String xsiTypeLocal;
@@ -601,7 +598,7 @@
             if (repeated)
             {
                // to have correct endRepeatableParticle calls
-               stack.push(item);
+               stack.push(position);
             }
          }
 
@@ -640,9 +637,9 @@
 
       if(repeated)
       {
-         item.o = o;
+         position.o = o;
          // in case of collection of abstract types
-         item.particle = particle;
+         position.particle = particle;
       }
       else
       {
@@ -659,42 +656,42 @@
    private void endRepeatableParent(QName startName)
    {
       int stackIndex = stack.size() - 2;
-      StackItem item;
-      StackItem parentItem = stack.peek1();
+      Position position;
+      Position parentPosition = stack.peek1();
       ParticleBinding parentParticle = null;
       while(true)
       {
-         if(parentItem.cursor == null)
+         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)parentItem.particle.getTerm()).getQName()
+               ((ElementBinding)parentPosition.particle.getTerm()).getQName()
             );
          }
 
-         item = parentItem;
+         position = parentPosition;
 
-         parentParticle = parentItem.particle;
+         parentParticle = parentPosition.particle;
          if(parentParticle.isRepeatable())
          {
-            parentItem = stack.peek(stackIndex - 1);
-            endParticle(item, parentItem);
+            parentPosition = stack.peek(stackIndex - 1);
+            endParticle(position, parentPosition);
 
-            ParticleHandler handler = getHandler(item.particle);
-            item.reset();
-            item.o = handler.startParticle(parentItem.o, item.qName, item.particle, null, nsRegistry);
+            ParticleHandler handler = getHandler(position.particle);
+            position.reset();
+            position.o = handler.startParticle(parentPosition.o, position.qName, position.particle, null, nsRegistry);
 
             break;
          }
 
          // wildcards are not on the stack
-         ParticleBinding currentParticle = parentItem.cursor.getCurrentParticle();
+         ParticleBinding currentParticle = parentPosition.cursor.getCurrentParticle();
          if(currentParticle.getTerm().isWildcard() && currentParticle.isRepeatable())
             break;
          
-         parentItem = stack.peek(--stackIndex);
-         endParticle(item, parentItem);
+         parentPosition = stack.peek(--stackIndex);
+         endParticle(position, parentPosition);
       }
 
 /*      if(!parentParticle.isRepeatable())
@@ -747,15 +744,15 @@
 */
       while(++stackIndex < stack.size() - 1)
       {
-         parentItem = item;
-         item = stack.peek(stackIndex);
-         ParticleHandler handler = getHandler(item.particle);
-         item.reset();
-         item.o = handler.startParticle(parentItem.o, item.qName, item.particle, null, nsRegistry);
+         parentPosition = position;
+         position = stack.peek(stackIndex);
+         ParticleHandler handler = getHandler(position.particle);
+         position.reset();
+         position.o = handler.startParticle(parentPosition.o, position.qName, position.particle, null, nsRegistry);
       }
    }
 
-   private void startRepeatableParticle(StackItem parentItem, Object parent, QName startName, ParticleBinding particle)
+   private void startRepeatableParticle(Position parentPosition, Object parent, QName startName, ParticleBinding particle)
    {
       if(trace)
          log.trace(" start repeatable (" + stack.size() + "): " + particle.getTerm());
@@ -764,45 +761,45 @@
       Object repeatableContainer = repeatableHandler.startRepeatableParticle(parent, startName, particle);
       if(repeatableContainer != null)
       {
-         parentItem.repeatableParticleValue = repeatableContainer;
-         parentItem.repeatableHandler = repeatableHandler;
+         parentPosition.repeatableParticleValue = repeatableContainer;
+         parentPosition.repeatableHandler = repeatableHandler;
       }
    }
 
-   private void endRepeatableParticle(StackItem parentItem, QName elementName, ParticleBinding particle, ParticleBinding parentParticle)
+   private void endRepeatableParticle(Position parentPosition, QName elementName, ParticleBinding particle, ParticleBinding parentParticle)
    {
       if (trace)
          log.trace(" end repeatable (" + stack.size() + "): " + particle.getTerm());
-      RepeatableParticleHandler repeatableHandler = parentItem.repeatableHandler;
+      RepeatableParticleHandler repeatableHandler = parentPosition.repeatableHandler;
       // the way it is now it's never null
-      repeatableHandler.endRepeatableParticle(parentItem.o, parentItem.repeatableParticleValue, elementName, particle, parentParticle);
-      parentItem.repeatableParticleValue = null;
-      parentItem.repeatableHandler = null;
+      repeatableHandler.endRepeatableParticle(parentPosition.o, parentPosition.repeatableParticleValue, elementName, particle, parentParticle);
+      parentPosition.repeatableParticleValue = null;
+      parentPosition.repeatableHandler = null;
    }
 
-   private void endParticle(StackItem item, StackItem parentItem)
+   private void endParticle(Position position, Position parentPosition)
    {
-      if(item.ended)
+      if(position.ended)
       {
-         throw new JBossXBRuntimeException(item.particle.getTerm() + " has already been ended.");
+         throw new JBossXBRuntimeException(position.particle.getTerm() + " has already been ended.");
       }
 
-      ParticleHandler handler = item.handler;
-      Object o = handler.endParticle(item.o, item.qName, item.particle);
+      ParticleHandler handler = position.handler;
+      Object o = handler.endParticle(position.o, position.qName, position.particle);
 
-      item.ended = true;
+      position.ended = true;
 
       // model group should always have parent particle
-      if(parentItem.o != null)
+      if(parentPosition.o != null)
       {
          ParticleBinding parentParticle = getNotSkippedParent().particle;//item.particle;
          if(parentParticle == null)
-            parentParticle = parentItem.particle;
+            parentParticle = parentPosition.particle;
          
-         if(parentItem.repeatableParticleValue == null)
-            setParent(handler, parentItem.o, o, item.qName, item.particle, parentParticle);
+         if(parentPosition.repeatableParticleValue == null)
+            setParent(handler, parentPosition.o, o, position.qName, position.particle, parentParticle);
          else
-            parentItem.repeatableHandler.addTermValue(parentItem.repeatableParticleValue, o, item.qName, item.particle, parentParticle, handler);
+            parentPosition.repeatableHandler.addTermValue(parentPosition.repeatableParticleValue, o, position.qName, position.particle, parentParticle, handler);
       }
    }
 
@@ -868,55 +865,53 @@
    
    private void flushIgnorableCharacters()
    {
-      StackItem stackItem = stack.peek();
-      if(stackItem.cursor != null || stackItem.textContent == null)
-      {
+      Position position = stack.peek();
+      if(position.isModelGroup() || position.textContent == null)
          return;
-      }
 
-      if(stackItem.indentation == Boolean.TRUE || stackItem.ignorableCharacters)
+      if(position.indentation == Boolean.TRUE || position.ignorableCharacters)
       {
-         if(log.isTraceEnabled())
+         if(trace)
          {
-            log.trace("ignored characters: " + ((ElementBinding) stackItem.particle.getTerm()).getQName() + " '"
-               + stackItem.textContent + "'");
+            log.trace("ignored characters: " + ((ElementBinding) position.particle.getTerm()).getQName() + " '"
+               + position.textContent + "'");
          }
-         stackItem.textContent = null;
-         stackItem.indentation = null;
+         position.textContent = null;
+         position.indentation = null;
       }
    }
    
-   private StackItem getNotSkippedParent()
+   private Position getNotSkippedParent()
    {
-      StackItem item = stack.peek1();
-      if(item == null)
+      Position position = stack.peek1();
+      if(position == null)
          return null;
       
-      ParticleBinding particle = item.particle;
-      if(!particle.getTerm().isSkip() || item.repeatableParticleValue != null)
-         return item;
+      ParticleBinding particle = position.particle;
+      if(!particle.getTerm().isSkip() || position.repeatableParticleValue != null)
+         return position;
       
       for(int i = stack.size() - 3; i >= 0; --i)
       {
-         item = stack.peek(i);
-         particle = item.particle;
-         if(!particle.getTerm().isSkip() || item.repeatableParticleValue != null)
-            return item;
+         position = stack.peek(i);
+         particle = position.particle;
+         if(!particle.getTerm().isSkip() || position.repeatableParticleValue != null)
+            return position;
       }
       return null;
    }
    
    private void endElement()
    {
-      StackItem item = stack.peek();
-      Object o = item.o;
-      ParticleBinding particle = item.particle;
+      Position position = stack.peek();
+      Object o = position.o;
+      ParticleBinding particle = position.particle;
       
       ElementBinding element = (ElementBinding)particle.getTerm();
       QName endName = element.getQName();
       TypeBinding type = element.getType();
       List<ElementInterceptor> interceptors = element.getInterceptors();
-      List<ElementInterceptor> localInterceptors = item.parentType == null ? Collections.EMPTY_LIST : item.parentType.getInterceptors(endName);
+      List<ElementInterceptor> localInterceptors = position.parentType == null ? Collections.EMPTY_LIST : position.parentType.getInterceptors(endName);
       int allInterceptors = interceptors.size() + localInterceptors.size();
 
       if(o != NIL)
@@ -933,7 +928,7 @@
             charType = type;
          }
 
-         CharactersHandler charHandler = item.ignoreCharacters ? null : charType.getCharactersHandler();
+         CharactersHandler charHandler = position.ignoreCharacters ? null : charType.getCharactersHandler();
 
          /**
           * If there is text content then unmarshal it and set.
@@ -943,7 +938,7 @@
           * 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 = item.textContent == null ? "" : item.textContent.toString();
+         String textContent = position.textContent == null ? "" : position.textContent.toString();
          if(textContent.length() > 0 || charHandler != null && !type.isIgnoreEmptyString())
          {
             String dataContent;
@@ -1050,8 +1045,8 @@
       // endElement
       //
 
-      StackItem parentItem = stack.size() == 1 ? null : stack.peek1();
-      Object parent = parentItem == null ? null : parentItem.o;
+      Position parentPosition = stack.size() == 1 ? null : stack.peek1();
+      Object parent = parentPosition == null ? null : parentPosition.o;
       ParticleHandler handler = stack.peek().handler;
       
       o = handler.endParticle(o, endName, particle);
@@ -1072,10 +1067,10 @@
 
       if(allInterceptors == 0)
       {
-         StackItem notSkippedParentItem = getNotSkippedParent();
-         if(notSkippedParentItem != null)
+         Position notSkippedParent = getNotSkippedParent();
+         if(notSkippedParent != null)
          {
-         ParticleBinding parentParticle = notSkippedParentItem.particle;
+         ParticleBinding parentParticle = notSkippedParent.particle;
          boolean hasWildcard = false;
          if (parentParticle != null && parentParticle.getTerm().isElement())
          {
@@ -1083,7 +1078,7 @@
             if (wildcard != null)
             {
                hasWildcard = true;
-               if(parentItem.cursor.isWildcardContent())
+               if(parentPosition.cursor.isWildcardContent())
                {
                   ParticleHandler wh = wildcard.getWildcardHandler();
                   if(wh != null)
@@ -1094,19 +1089,19 @@
 
          if(parent != null)
          {
-            if(notSkippedParentItem.repeatableParticleValue == null)
+            if(notSkippedParent.repeatableParticleValue == null)
                setParent(handler, parent, o, endName, particle, parentParticle);
             else
-               notSkippedParentItem.repeatableHandler.addTermValue(notSkippedParentItem.repeatableParticleValue, o, endName, particle, parentParticle, handler);
+               notSkippedParent.repeatableHandler.addTermValue(notSkippedParent.repeatableParticleValue, o, endName, particle, parentParticle, handler);
          }
          else if(parentParticle != null && hasWildcard && stack.size() > 1)
          {
             // the parent has anyType, so it gets the value of its child
             for(int i = stack.size() - 2; i >= 0; --i)
             {
-               StackItem peeked = stack.peek(i);
+               Position peeked = stack.peek(i);
                peeked.o = o;
-               if(peeked.cursor == null)
+               if(peeked.isElement())
                   break;
             }
 
@@ -1117,7 +1112,7 @@
       }
       else
       {
-         StackItem popped = pop();
+         Position popped = pop();
 
          for(int i = interceptors.size() - 1; i >= 0; --i)
          {
@@ -1186,11 +1181,11 @@
 
    private void push(QName qName, ParticleBinding particle, Object o, ParticleHandler handler, TypeBinding parentType)
    {
-      StackItem item = new StackItem(qName, particle);
-      item.o = o;
-      item.handler = handler;
-      item.parentType = parentType;      
-      stack.push(item);
+      Position position = new Position(qName, particle);
+      position.o = o;
+      position.handler = handler;
+      position.parentType = parentType;      
+      stack.push(position);
       if(trace)
       {
          if(particle != null)
@@ -1200,36 +1195,32 @@
       }
    }
 
-   private void push(QName qName, ModelGroupBinding.Cursor cursor, Object o, ParticleHandler handler, TypeBinding parentType)
+   private void push(ModelGroupBinding.ModelGroupPosition position, Object o, ParticleHandler handler, TypeBinding parentType)
    {
-      StackItem item = new StackItem(qName, cursor);
-      item.o = o;
-      item.handler = handler;
-      item.parentType = parentType;
-      stack.push(item);
+      //StackItem item = new StackItem(qName, cursor);
+      //ElementPosition position = cursor;
+      position.o = o;
+      position.handler = handler;
+      position.parentType = parentType;
+      stack.push(position);
       if(trace)
-         log.trace("pushed cursor " + cursor + ", o=" + o);
+         log.trace("pushed position " + position + ", o=" + o);
    }
 
-   private StackItem pop()
+   private Position pop()
    {
-      StackItem item = stack.pop();
+      Position position = stack.pop();
       if(trace)
-      {
-         if(item.cursor == null)
-            log.trace("poped " + ((ElementBinding)item.particle.getTerm()).getQName() + "=" + item.particle);
-         else
-            log.trace("poped " + item.cursor.getParticle().getTerm());
-      }
-      return item;
+         log.trace("poped " + position.particle.getTerm());
+      return position;
    }
 
    // Inner
 
-   private static class StackItem
+   public static class Position
    {
       final QName qName;
-      final ModelGroupBinding.Cursor cursor;
+      ModelGroupBinding.ModelGroupPosition cursor;
       ParticleBinding particle;
       ParticleBinding nonXsiParticle;
       ParticleHandler handler;
@@ -1243,7 +1234,7 @@
       boolean ignorableCharacters = true;
       boolean ended;
 
-      public StackItem(QName qName, ModelGroupBinding.Cursor cursor)
+/*      public StackItem(QName qName, ModelGroupBinding.Cursor cursor)
       {
          if (cursor == null)
             throw new IllegalArgumentException("Null cursor");
@@ -1256,13 +1247,11 @@
          
          this.particle = cursor.getParticle();
       }
-
-      public StackItem(QName qName, ParticleBinding particle)
+*/
+      public Position(QName qName, ParticleBinding particle)
       {
          if (particle == null)
             throw new IllegalArgumentException("Null particle");
-         // this is element particle
-         this.cursor = null;
          
          if(qName == null)
             throw new IllegalArgumentException("Null qName");
@@ -1271,6 +1260,16 @@
          this.particle = particle;
       }
 
+      protected boolean isElement()
+      {
+         return true;
+      }
+
+      protected boolean isModelGroup()
+      {
+         return false;
+      }
+      
       void reset()
       {
          if(!ended)
@@ -1295,9 +1294,9 @@
 
    static class StackImpl
    {
-      private List<StackItem> list = new ArrayList<StackItem>();
-      private StackItem head;
-      private StackItem peek1;
+      private List<Position> list = new ArrayList<Position>();
+      private Position head;
+      private Position peek1;
 
       public void clear()
       {
@@ -1306,14 +1305,14 @@
          peek1 = null;
       }
 
-      public void push(StackItem o)
+      public void push(Position o)
       {
          list.add(o);
          peek1 = head;
          head = o;
       }
 
-      public StackItem pop()
+      public Position pop()
       {
          head = peek1;
          int index = list.size() - 1;
@@ -1321,17 +1320,17 @@
          return list.remove(index);
       }
 
-      public StackItem peek()
+      public Position peek()
       {
          return head;
       }
 
-      public StackItem peek1()
+      public Position peek1()
       {
          return peek1;
       }
 
-      public StackItem peek(int i)
+      public Position peek(int i)
       {
          return list.get(i);
       }

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/TypeBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/TypeBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/TypeBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -151,7 +151,7 @@
       if(particle != null)
       {
          ModelGroupBinding modelGroup = (ModelGroupBinding)particle.getTerm();
-         element = modelGroup.newCursor(particle).getElement(name, null, ignoreWildcards);
+         element = modelGroup.getElement(name, null, ignoreWildcards);
       }
 
       if(element == null && !ignoreWildcards && wildcard != null)

Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/UnorderedSequenceBinding.java
===================================================================
--- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/UnorderedSequenceBinding.java	2009-11-20 11:23:55 UTC (rev 3766)
+++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/UnorderedSequenceBinding.java	2009-11-22 09:57:46 UTC (rev 3767)
@@ -25,10 +25,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import javax.xml.namespace.QName;
 
@@ -97,93 +95,107 @@
          allParticles.addAll(elementParticles.values());
          allParticles.addAll(groupParticles);
          allParticles.addAll(wildcardParticles);
-         allParticles = Collections.unmodifiableList(allParticles);
       }
       return allParticles;
    }
 
-   @Override
-   protected boolean mayStartWith(QName name, Set<ModelGroupBinding> set)
+   public ModelGroupPosition newPosition(QName qName, Attributes attrs, ParticleBinding seqParticle)
    {
-      throw new UnsupportedOperationException();
+      ParticleBinding currentParticle = elementParticles.get(qName);
+      if (currentParticle != null)
+         return new UnorderedSequencePosition(qName, seqParticle, currentParticle);
+
+      for (ParticleBinding particle : groupParticles)
+      {
+         ModelGroupBinding modelGroup = (ModelGroupBinding) particle.getTerm();
+         ModelGroupPosition next = modelGroup.newPosition(qName, attrs, particle);
+         if (next != null)
+            return new UnorderedSequencePosition(qName, seqParticle, particle, next);
+      }
+
+      for (ParticleBinding particle : wildcardParticles)
+      {
+         WildcardBinding wildcard = (WildcardBinding) particle.getTerm();
+         ElementBinding wildcardContent = wildcard.getElement(qName, attrs);
+         if (wildcardContent != null)
+            return new UnorderedSequencePosition(qName, seqParticle, particle, wildcardContent);
+      }
+      return null;
    }
-
+   
    @Override
-   public Cursor newCursor(ParticleBinding particle)
+   public String getGroupType()
    {
-      return new Cursor(particle)
+      return "unordered_sequence";
+   }
+   
+   private final class UnorderedSequencePosition extends ModelGroupPosition
+   {
+      private UnorderedSequencePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle)
       {
-         @Override
-         protected Cursor startElement(QName qName, Attributes atts, Set<ModelGroupBinding> passedGroups, boolean required)
+         super(name, particle, currentParticle);
+      }
+
+      private UnorderedSequencePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ModelGroupPosition next)
+      {
+         super(name, particle, currentParticle, next);
+      }
+
+      private UnorderedSequencePosition(QName name, ParticleBinding particle, ParticleBinding currentParticle, ElementBinding wildcardContent)
+      {
+         super(name, particle, currentParticle, wildcardContent);
+      }
+
+      @Override
+      protected ModelGroupPosition startElement(QName qName, Attributes atts, boolean required)
+      {
+         if(trace)
          {
-            if(trace)
-            {
-               StringBuffer sb = new StringBuffer();
-               sb.append("startElement ").append(qName).append(" in ").append(UnorderedSequenceBinding.this.toString());
-               log.trace(sb.toString());
-            }
+            StringBuffer sb = new StringBuffer();
+            sb.append("startElement ").append(qName).append(" in ").append(UnorderedSequenceBinding.this.toString());
+            log.trace(sb.toString());
+         }
 
-            next = null;
-            
-            if(currentParticle != null && repeatTerm(qName, atts))
-               return this;               
+         next = null;
+         
+         if(currentParticle != null && repeatTerm(qName, atts))
+            return this;               
 
-            currentParticle = elementParticles.get(qName);
-            if (currentParticle != null)
+         currentParticle = elementParticles.get(qName);
+         if (currentParticle != null)
+         {
+            occurrence = 1;
+            if (trace)
+               log.trace("found " + qName + " in " + UnorderedSequenceBinding.this);
+            return this;
+         }
+
+         for (ParticleBinding particle : groupParticles)
+         {
+            ModelGroupBinding modelGroup = (ModelGroupBinding) particle.getTerm();
+            next = modelGroup.newPosition(qName, atts, particle);
+
+            if (next != null)
             {
-               occurence = 1;
-               if (trace)
-                  log.trace("found " + qName + " in " + UnorderedSequenceBinding.this);
+               occurrence = 1;
+               currentParticle = particle;
                return this;
             }
+         }
 
-            for (ParticleBinding particle : groupParticles)
+         for (ParticleBinding particle : wildcardParticles)
+         {
+            WildcardBinding wildcard = (WildcardBinding) particle.getTerm();
+            wildcardContent = wildcard.getElement(qName, atts);
+            if (wildcardContent != null)
             {
-               ModelGroupBinding modelGroup = (ModelGroupBinding) particle.getTerm();
-               if (!passedGroups.contains(modelGroup))
-               {
-                  switch (passedGroups.size())
-                  {
-                     case 0 :
-                        passedGroups = Collections.singleton((ModelGroupBinding) UnorderedSequenceBinding.this);
-                        break;
-                     case 1 :
-                        passedGroups = new HashSet<ModelGroupBinding>(passedGroups);
-                     default :
-                        passedGroups.add(UnorderedSequenceBinding.this);
-                  }
-
-                  next = modelGroup.newCursor(particle).startElement(qName, atts, passedGroups, particle.isRequired(occurence));
-
-                  if (next != null)
-                  {
-                     occurence = 1;
-                     currentParticle = particle;
-                     return this;
-                  }
-               }
+               occurrence = 1;
+               currentParticle = particle;
+               return this;
             }
-
-            for (ParticleBinding particle : wildcardParticles)
-            {
-               WildcardBinding wildcard = (WildcardBinding) particle.getTerm();
-               wildcardContent = wildcard.getElement(qName, atts);
-               if (wildcardContent != null)
-               {
-                  occurence = 1;
-                  currentParticle = particle;
-                  return this;
-               }
-            }
-            
-            return null;
          }
-      };
+         
+         return null;
+      }
    }
-
-   @Override
-   public String getGroupType()
-   {
-      return "unordered_sequence";
-   }
 }



More information about the jboss-svn-commits mailing list