1 22 package org.jboss.xb.binding.sunday.unmarshalling; 23 24 import java.util.Collections ; 25 import java.util.HashSet ; 26 import java.util.Set ; 27 import java.util.List ; 28 import java.util.ArrayList ; 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 ChoiceBinding 40 extends ModelGroupBinding 41 { 42 private List choices = Collections.EMPTY_LIST; 43 44 public ChoiceBinding(SchemaBinding schema) 45 { 46 super(schema); 47 } 48 49 public ElementBinding getArrayItem() 50 { 51 return null; 52 } 53 54 public void addParticle(ParticleBinding particle) 55 { 56 switch(choices.size()) 57 { 58 case 0: 59 choices = Collections.singletonList(particle); 60 break; 61 case 1: 62 choices = new ArrayList (choices); 63 default: 64 choices.add(particle); 65 } 66 67 super.addParticle(particle); 68 } 69 70 public Collection getParticles() 71 { 72 return Collections.unmodifiableCollection(choices); 73 } 74 75 public Cursor newCursor(ParticleBinding particle) 76 { 77 return new Cursor(particle) 78 { 79 private int pos = -1; 80 private ElementBinding element; 81 private int occurence; 82 83 public ParticleBinding getCurrentParticle() 84 { 85 if(pos < 0) 86 { 87 throw new JBossXBRuntimeException( 88 "The cursor has not been positioned yet! startElement should be called." 89 ); 90 } 91 return (ParticleBinding)choices.get(pos); 92 } 93 94 public ElementBinding getElement() 95 { 96 if(pos < 0) 97 { 98 throw new JBossXBRuntimeException( 99 "The cursor has not been positioned yet! startElement should be called." 100 ); 101 } 102 return element; 103 } 104 105 public boolean isPositioned() 106 { 107 return pos != -1; 108 } 109 110 public void endElement(QName qName) 111 { 112 if(element == null || !element.getQName().equals(qName)) 113 { 114 throw new JBossXBRuntimeException("Failed to process endElement for " + qName + 115 " since the current element is " + (element == null ? "null" : element.getQName().toString()) 116 ); 117 } 118 119 if(trace) 120 { 121 log.trace("endElement " + qName + " in " + getModelGroup()); 122 } 123 } 124 125 public int getOccurence() 126 { 127 return occurence; 128 } 129 130 protected List startElement(QName qName, Attributes atts, Set passedGroups, List groupStack, boolean required) 131 { 132 if(trace) 133 { 134 StringBuffer sb = new StringBuffer (); 135 sb.append("startElement " + qName + " in " + getModelGroup() + ", " + choices.size() + ": "); 136 137 for(int i = 0; i < choices.size(); ++i) 138 { 139 ParticleBinding particle = (ParticleBinding)choices.get(i); 140 Object o = particle.getTerm(); 141 if(o instanceof ElementBinding) 142 { 143 sb.append(((ElementBinding)o).getQName()); 144 } 145 else if(o instanceof SequenceBinding) 146 { 147 sb.append("sequence"); 148 } 149 else if(o instanceof ChoiceBinding) 150 { 151 sb.append("choice"); 152 } 153 else if(o instanceof AllBinding) 154 { 155 sb.append("all"); 156 } 157 158 sb.append(" "); 159 } 160 sb.append("]"); 161 log.trace(sb.toString()); 162 } 163 164 int i = pos; 165 if(pos >= 0) 166 { 167 ParticleBinding particle = getCurrentParticle(); 168 if(particle.getMaxOccursUnbounded() || 169 occurence < particle.getMinOccurs() || 170 occurence < particle.getMaxOccurs()) 171 { 172 --i; 173 } 174 } 175 176 while(i < choices.size() - 1) 179 { 180 ParticleBinding particle = (ParticleBinding)choices.get(++i); 181 Object item = particle.getTerm(); 182 if(item instanceof ElementBinding) 183 { 184 ElementBinding element = (ElementBinding)item; 185 if(qName.equals(element.getQName())) 186 { 187 if(pos == i) 188 { 189 ++occurence; 190 } 191 else 192 { 193 pos = i; 194 occurence = 1; 195 } 196 groupStack = addItem(groupStack, this); 197 this.element = element; 198 199 if(trace) 200 { 201 log.trace("found " + qName + " in " + getModelGroup()); 202 } 203 break; 204 } 205 } 206 else if(item instanceof ModelGroupBinding) 207 { 208 ModelGroupBinding modelGroup = (ModelGroupBinding)item; 209 if(!passedGroups.contains(modelGroup)) 210 { 211 switch(passedGroups.size()) 212 { 213 case 0: 214 passedGroups = Collections.singleton(this); 215 break; 216 case 1: 217 passedGroups = new HashSet (passedGroups); 218 default: 219 passedGroups.add(this); 220 } 221 222 int groupStackSize = groupStack.size(); 223 groupStack = modelGroup.newCursor(particle).startElement( 224 qName, atts, passedGroups, groupStack, particle.isRequired(occurence) 225 ); 226 227 if(groupStackSize != groupStack.size()) 228 { 229 if(pos != i) 230 { 231 pos = i; 232 occurence = 1; 233 } 234 else 235 { 236 ++occurence; 237 } 238 groupStack = addItem(groupStack, this); 239 element = null; 240 break; 241 } 242 } 243 } 244 else if(item instanceof WildcardBinding) 245 { 246 WildcardBinding wildcard = (WildcardBinding)item; 247 element = wildcard.getElement(qName, atts); 248 if(element != null) 249 { 250 if(pos != i) 251 { 252 pos = i; 253 occurence = 1; 254 } 255 else 256 { 257 ++occurence; 258 } 259 groupStack = addItem(groupStack, this); 260 break; 261 } 262 } 263 } 264 265 if(trace) 266 { 267 if(i == choices.size()) 268 { 269 log.trace(qName + " not found in " + getModelGroup()); 270 } 271 else 272 { 273 log.trace("leaving " + getModelGroup() + " i=" + i + ", pos=" + pos); 274 } 275 } 276 277 return groupStack; 278 } 279 280 protected ElementBinding getElement(QName qName, Attributes atts, Set passedGroups, boolean ignoreWildcards) 281 { 282 return getElement(choices, qName, atts, passedGroups, ignoreWildcards); 283 } 284 }; 285 } 286 287 protected boolean mayStartWith(QName qName, Set set) 288 { 289 boolean result = false; 290 for(int i = 0; i < choices.size(); ++i) 291 { 292 ParticleBinding particle = (ParticleBinding)choices.get(i); 293 Object item = particle.getTerm(); 294 if(item instanceof ElementBinding) 295 { 296 ElementBinding element = (ElementBinding)item; 297 if(qName.equals(element.getQName())) 298 { 299 result = true; 300 break; 301 } 302 } 303 else if(item instanceof ModelGroupBinding) 304 { 305 ModelGroupBinding modelGroup = (ModelGroupBinding)item; 306 if(!set.contains(modelGroup)) 307 { 308 switch(set.size()) 309 { 310 case 0: 311 set = Collections.singleton(this); 312 break; 313 case 1: 314 set = new HashSet (set); 315 default: 316 set.add(this); 317 } 318 319 result = modelGroup.mayStartWith(qName, set); 320 321 if(result) 322 { 323 break; 324 } 325 } 326 } 327 else 328 { 329 throw new JBossXBRuntimeException("Unexpected item type in model group: " + item); 330 } 331 } 332 333 return result; 334 } 335 } 336 | Popular Tags |