KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xb > binding > sunday > unmarshalling > SequenceBinding


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.xb.binding.sunday.unmarshalling;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.Collection JavaDoc;
30 import javax.xml.namespace.QName JavaDoc;
31 import org.jboss.xb.binding.JBossXBRuntimeException;
32 import org.xml.sax.Attributes JavaDoc;
33
34
35 /**
36  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
37  * @version <tt>$Revision: 2139 $</tt>
38  */

39 public class SequenceBinding
40    extends ModelGroupBinding
41 {
42    private List JavaDoc sequence = Collections.EMPTY_LIST;
43    private ElementBinding arrayItem;
44
45    public SequenceBinding(SchemaBinding schema)
46    {
47       super(schema);
48    }
49
50    public ElementBinding getArrayItem()
51    {
52       return arrayItem;
53    }
54
55    public void addParticle(ParticleBinding particle)
56    {
57       switch(sequence.size())
58       {
59          case 0:
60             sequence = Collections.singletonList(particle);
61             if(particle.isRepeatable() && particle.getTerm().isElement())
62             {
63                ElementBinding element = (ElementBinding)particle.getTerm();
64                if(particle.isRepeatable())
65                {
66                   arrayItem = element;
67                }
68             }
69             break;
70          case 1:
71             sequence = new ArrayList JavaDoc(sequence);
72             arrayItem = null;
73          default:
74             sequence.add(particle);
75       }
76       super.addParticle(particle);
77    }
78
79    public Collection JavaDoc getParticles()
80    {
81       return Collections.unmodifiableCollection(sequence);
82    }
83
84    public Cursor newCursor(ParticleBinding particle)
85    {
86       return new Cursor(particle)
87       {
88          private int pos = -1;
89          private ElementBinding element;
90          private int occurence;
91
92          public ParticleBinding getCurrentParticle()
93          {
94             if(pos < 0)
95             {
96                throw new JBossXBRuntimeException(
97                   "The cursor has not been positioned yet! startElement should be called."
98                );
99             }
100             return (ParticleBinding)sequence.get(pos);
101          }
102
103          public ElementBinding getElement()
104          {
105             if(pos < 0)
106             {
107                throw new JBossXBRuntimeException(
108                   "The cursor has not been positioned yet! startElement should be called."
109                );
110             }
111             return element;
112          }
113
114          public boolean isPositioned()
115          {
116             return pos != -1;
117          }
118
119          public void endElement(QName JavaDoc qName)
120          {
121             if(element == null || !element.getQName().equals(qName))
122             {
123                throw new JBossXBRuntimeException("Failed to process endElement for " + qName +
124                   " since the current element is " + (element == null ? "null" : element.getQName().toString())
125                );
126             }
127
128             if(trace)
129             {
130                log.trace("endElement " + qName + " in " + getModelGroup());
131             }
132          }
133
134          public int getOccurence()
135          {
136             return occurence;
137          }
138
139          protected List JavaDoc startElement(QName JavaDoc qName, Attributes JavaDoc atts, Set JavaDoc passedGroups, List JavaDoc groupStack, boolean required)
140          {
141             if(trace)
142             {
143                StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
144                sb.append("startElement " + qName + " in " + getModelGroup() + ", " + sequence.size() + ": ");
145
146                for(int i = 0; i < sequence.size(); ++i)
147                {
148                   ParticleBinding particle = (ParticleBinding)sequence.get(i);
149                   Object JavaDoc o = particle.getTerm();
150                   if(o instanceof ElementBinding)
151                   {
152                      sb.append(((ElementBinding)o).getQName());
153                   }
154                   else if(o instanceof SequenceBinding)
155                   {
156                      sb.append("sequence");
157                   }
158                   else if(o instanceof ChoiceBinding)
159                   {
160                      sb.append("choice");
161                   }
162                   else if(o instanceof AllBinding)
163                   {
164                      sb.append("all");
165                   }
166
167                   sb.append(" ");
168                }
169                sb.append("]");
170                log.trace(sb.toString());
171             }
172
173             int i = pos;
174             if(pos >= 0)
175             {
176                ParticleBinding particle = getCurrentParticle();
177                if(particle.getMaxOccursUnbounded() ||
178                   occurence < particle.getMinOccurs() ||
179                   occurence < particle.getMaxOccurs())
180                {
181                   --i;
182                }
183             }
184
185             // i update pos only if the element has been found, though it seems to be irrelevant
186
// since the cursor is going to be thrown away in case the element has not been found
187
while(i < sequence.size() - 1)
188             {
189                ParticleBinding particle = (ParticleBinding)sequence.get(++i);
190                Object JavaDoc item = particle.getTerm();
191                if(item instanceof ElementBinding)
192                {
193                   ElementBinding element = (ElementBinding)item;
194                   if(qName.equals(element.getQName()))
195                   {
196                      if(pos == i)
197                      {
198                         ++occurence;
199                      }
200                      else
201                      {
202                         pos = i;
203                         occurence = 1;
204                      }
205                      groupStack = addItem(groupStack, this);
206                      this.element = element;
207
208                      if(trace)
209                      {
210                         log.trace("found " + qName + " in " + getModelGroup());
211                      }
212                      break;
213                   }
214
215                   if(i != pos && particle.getMinOccurs() > 0)
216                   {
217                      if(required)
218                      {
219                         throw new JBossXBRuntimeException("Requested element " + qName +
220                            " is not allowed in this position in the sequence. The next element should be " +
221                            element.getQName()
222                         );
223                      }
224                      else
225                      {
226                         break;
227                      }
228                   }
229                }
230                else if(item instanceof ModelGroupBinding)
231                {
232                   ModelGroupBinding modelGroup = (ModelGroupBinding)item;
233                   if(!passedGroups.contains(modelGroup))
234                   {
235                      switch(passedGroups.size())
236                      {
237                         case 0:
238                            passedGroups = Collections.singleton(this);
239                            break;
240                         case 1:
241                            passedGroups = new HashSet JavaDoc(passedGroups);
242                         default:
243                            passedGroups.add(this);
244                      }
245
246                      int groupStackSize = groupStack.size();
247                      groupStack = modelGroup.newCursor(particle).startElement(
248                         qName, atts, passedGroups, groupStack, particle.isRequired(occurence)
249                      );
250
251                      if(groupStackSize != groupStack.size())
252                      {
253                         if(pos != i)
254                         {
255                            pos = i;
256                            occurence = 1;
257                         }
258                         else
259                         {
260                            ++occurence;
261                         }
262                         groupStack = addItem(groupStack, this);
263                         element = null;
264                         break;
265                      }
266
267                      if(i != pos && particle.isRequired())
268                      {
269                         if(required)
270                         {
271                            throw new JBossXBRuntimeException("Requested element " + qName +
272                               " is not allowed in this position in the sequence. A model group with minOccurs=" +
273                               particle.getMinOccurs() + " that doesn't contain this element must follow."
274                            );
275                         }
276                         else
277                         {
278                            break;
279                         }
280                      }
281                   }
282                   else if(i != pos && particle.isRequired())
283                   {
284                      if(required)
285                      {
286                         throw new JBossXBRuntimeException("Requested element " + qName +
287                            " is not allowed in this position in the sequence. A model group with minOccurs=" +
288                            particle.getMinOccurs() + " that doesn't contain this element must follow."
289                         );
290                      }
291                      else
292                      {
293                         break;
294                      }
295                   }
296                }
297                else if(item instanceof WildcardBinding)
298                {
299                   WildcardBinding wildcard = (WildcardBinding)item;
300                   element = wildcard.getElement(qName, atts);
301                   if(element != null)
302                   {
303                      if(pos != i)
304                      {
305                         pos = i;
306                         occurence = 1;
307                      }
308                      else
309                      {
310                         ++occurence;
311                      }
312                      groupStack = addItem(groupStack, this);
313                      break;
314                   }
315
316                   if(i != pos && particle.getMinOccurs() > 0)
317                   {
318                      if(required)
319                      {
320                         throw new JBossXBRuntimeException("Requested element " + qName +
321                            " is not allowed in this position in the sequence."
322                         );
323                      }
324                      else
325                      {
326                         break;
327                      }
328                   }
329                }
330             }
331
332             if(trace && i == sequence.size())
333             {
334                log.trace(qName + " not found in " + getModelGroup());
335             }
336
337             return groupStack;
338          }
339
340          protected ElementBinding getElement(QName JavaDoc qName, Attributes JavaDoc atts, Set JavaDoc passedGroups, boolean ignoreWildcards)
341          {
342             return getElement(sequence, qName, atts, passedGroups, ignoreWildcards);
343          }
344       };
345    }
346
347    protected boolean mayStartWith(QName JavaDoc qName, Set JavaDoc set)
348    {
349       boolean result = false;
350       for(int i = 0; i < sequence.size(); ++i)
351       {
352          ParticleBinding particle = (ParticleBinding)sequence.get(i);
353          Object JavaDoc item = particle.getTerm();
354          if(item instanceof ElementBinding)
355          {
356             ElementBinding element = (ElementBinding)item;
357             if(qName.equals(element.getQName()))
358             {
359                result = true;
360                break;
361             }
362
363             if(particle.getMinOccurs() > 0)
364             {
365                break;
366             }
367          }
368          else if(item instanceof ModelGroupBinding)
369          {
370             ModelGroupBinding modelGroup = (ModelGroupBinding)item;
371             if(!set.contains(modelGroup))
372             {
373                switch(set.size())
374                {
375                   case 0:
376                      set = Collections.singleton(this);
377                      break;
378                   case 1:
379                      set = new HashSet JavaDoc(set);
380                   default:
381                      set.add(this);
382                }
383
384                result = modelGroup.mayStartWith(qName, set);
385
386                if(result || particle.getMinOccurs() > 0)
387                {
388                   break;
389                }
390             }
391             else if(particle.getMinOccurs() > 0)
392             {
393                break;
394             }
395          }
396       }
397       return result;
398    }
399 }
400
Popular Tags