1 22 package org.jboss.xb.binding.sunday.unmarshalling; 23 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.HashSet ; 27 import java.util.List ; 28 import java.util.Set ; 29 import java.util.Collection ; 30 import javax.xml.namespace.QName ; 31 import org.jboss.xb.binding.JBossXBRuntimeException; 32 import org.xml.sax.Attributes ; 33 34 35 39 public class SequenceBinding 40 extends ModelGroupBinding 41 { 42 private List 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 (sequence); 72 arrayItem = null; 73 default: 74 sequence.add(particle); 75 } 76 super.addParticle(particle); 77 } 78 79 public Collection 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 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 startElement(QName qName, Attributes atts, Set passedGroups, List groupStack, boolean required) 140 { 141 if(trace) 142 { 143 StringBuffer sb = new StringBuffer (); 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 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 while(i < sequence.size() - 1) 188 { 189 ParticleBinding particle = (ParticleBinding)sequence.get(++i); 190 Object 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 (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 qName, Attributes atts, Set passedGroups, boolean ignoreWildcards) 341 { 342 return getElement(sequence, qName, atts, passedGroups, ignoreWildcards); 343 } 344 }; 345 } 346 347 protected boolean mayStartWith(QName qName, Set 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 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 (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 |