1 16 17 package org.apache.xerces.impl.xs; 18 19 import org.apache.xerces.xs.XSConstants; 20 import org.apache.xerces.xs.XSTypeDefinition; 21 import org.apache.xerces.xni.QName; 22 import java.util.Hashtable ; 23 import java.util.Vector ; 24 25 34 public class SubstitutionGroupHandler { 35 36 private static final XSElementDecl[] EMPTY_GROUP = new XSElementDecl[0]; 37 38 XSGrammarBucket fGrammarBucket; 40 41 44 public SubstitutionGroupHandler(XSGrammarBucket grammarBucket) { 45 fGrammarBucket = grammarBucket; 46 } 47 48 public XSElementDecl getMatchingElemDecl(QName element, XSElementDecl exemplar) { 51 if (element.localpart == exemplar.fName && 52 element.uri == exemplar.fTargetNamespace) { 53 return exemplar; 54 } 55 56 if (exemplar.fScope != XSConstants.SCOPE_GLOBAL) 59 return null; 60 61 if ((exemplar.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) 63 return null; 64 65 SchemaGrammar sGrammar = fGrammarBucket.getGrammar(element.uri); 67 if (sGrammar == null) 68 return null; 69 70 XSElementDecl eDecl = sGrammar.getGlobalElementDecl(element.localpart); 72 if (eDecl == null) 73 return null; 74 75 if (substitutionGroupOK(eDecl, exemplar, exemplar.fBlock)) 77 return eDecl; 78 79 return null; 80 } 81 82 protected boolean substitutionGroupOK(XSElementDecl element, XSElementDecl exemplar, short blockingConstraint) { 85 if (element == exemplar) 88 return true; 89 90 if ((blockingConstraint & XSConstants.DERIVATION_SUBSTITUTION) != 0) 93 return false; 94 95 XSElementDecl subGroup = element.fSubGroup; 97 while (subGroup != null && subGroup != exemplar) { 98 subGroup = subGroup.fSubGroup; 99 } 100 101 if (subGroup == null) 102 return false; 103 104 short devMethod = 0, blockConstraint = blockingConstraint; 108 109 XSTypeDefinition type = element.fType; 113 while (type != exemplar.fType && type != SchemaGrammar.fAnyType) { 114 if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) 115 devMethod |= ((XSComplexTypeDecl)type).fDerivedBy; 116 else 117 devMethod |= XSConstants.DERIVATION_RESTRICTION; 118 type = type.getBaseType(); 119 if (type == null) 122 type = SchemaGrammar.fAnyType; 123 if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) 124 blockConstraint |= ((XSComplexTypeDecl)type).fBlock; 125 } 126 if (type != exemplar.fType) 127 return false; 128 129 if ((devMethod & blockConstraint) != 0) 130 return false; 131 132 return true; 133 } 134 135 public boolean inSubstitutionGroup(XSElementDecl element, XSElementDecl exemplar) { 137 return substitutionGroupOK(element, exemplar, exemplar.fBlock); 145 } 146 147 Hashtable fSubGroupsB = new Hashtable (); 153 private static final OneSubGroup[] EMPTY_VECTOR = new OneSubGroup[0]; 154 Hashtable fSubGroups = new Hashtable (); 156 157 160 public void reset() { 161 fSubGroupsB.clear(); 162 fSubGroups.clear(); 163 } 164 165 168 public void addSubstitutionGroup(XSElementDecl[] elements) { 169 XSElementDecl subHead, element; 170 Vector subGroup; 171 for (int i = elements.length-1; i >= 0; i--) { 173 element = elements[i]; 174 subHead = element.fSubGroup; 175 subGroup = (Vector )fSubGroupsB.get(subHead); 177 if (subGroup == null) { 178 subGroup = new Vector (); 180 fSubGroupsB.put(subHead, subGroup); 181 } 182 subGroup.addElement(element); 184 } 185 } 186 187 195 public XSElementDecl[] getSubstitutionGroup(XSElementDecl element) { 196 Object subGroup = fSubGroups.get(element); 198 if (subGroup != null) 199 return (XSElementDecl[])subGroup; 200 201 if ((element.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) { 202 fSubGroups.put(element, EMPTY_GROUP); 203 return EMPTY_GROUP; 204 } 205 206 OneSubGroup[] groupB = getSubGroupB(element, new OneSubGroup()); 209 int len = groupB.length, rlen = 0; 210 XSElementDecl[] ret = new XSElementDecl[len]; 211 for (int i = 0 ; i < len; i++) { 214 if ((element.fBlock & groupB[i].dMethod) == 0) 215 ret[rlen++] = groupB[i].sub; 216 } 217 if (rlen < len) { 219 XSElementDecl[] ret1 = new XSElementDecl[rlen]; 220 System.arraycopy(ret, 0, ret1, 0, rlen); 221 ret = ret1; 222 } 223 fSubGroups.put(element, ret); 225 226 return ret; 227 } 228 229 private OneSubGroup[] getSubGroupB(XSElementDecl element, OneSubGroup methods) { 231 Object subGroup = fSubGroupsB.get(element); 232 233 if (subGroup == null) { 235 fSubGroupsB.put(element, EMPTY_VECTOR); 236 return EMPTY_VECTOR; 237 } 238 239 if (subGroup instanceof OneSubGroup[]) 241 return (OneSubGroup[])subGroup; 242 243 Vector group = (Vector )subGroup, newGroup = new Vector (); 245 OneSubGroup[] group1; 246 short dMethod, bMethod, dSubMethod, bSubMethod; 249 for (int i = group.size()-1, j; i >= 0; i--) { 250 XSElementDecl sub = (XSElementDecl)group.elementAt(i); 252 if (!getDBMethods(sub.fType, element.fType, methods)) 253 continue; 254 dMethod = methods.dMethod; 256 bMethod = methods.bMethod; 257 newGroup.addElement(new OneSubGroup(sub, methods.dMethod, methods.bMethod)); 259 group1 = getSubGroupB(sub, methods); 261 for (j = group1.length-1; j >= 0; j--) { 262 dSubMethod = (short)(dMethod | group1[j].dMethod); 264 bSubMethod = (short)(bMethod | group1[j].bMethod); 265 if ((dSubMethod & bSubMethod) != 0) 267 continue; 268 newGroup.addElement(new OneSubGroup(group1[j].sub, dSubMethod, bSubMethod)); 269 } 270 } 271 OneSubGroup[] ret = new OneSubGroup[newGroup.size()]; 273 for (int i = newGroup.size()-1; i >= 0; i--) { 274 ret[i] = (OneSubGroup)newGroup.elementAt(i); 275 } 276 fSubGroupsB.put(element, ret); 278 279 return ret; 280 } 281 282 private boolean getDBMethods(XSTypeDefinition typed, XSTypeDefinition typeb, 283 OneSubGroup methods) { 284 short dMethod = 0, bMethod = 0; 285 while (typed != typeb && typed != SchemaGrammar.fAnyType) { 286 if (typed.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) 287 dMethod |= ((XSComplexTypeDecl)typed).fDerivedBy; 288 else 289 dMethod |= XSConstants.DERIVATION_RESTRICTION; 290 typed = typed.getBaseType(); 291 if (typed == null) 294 typed = SchemaGrammar.fAnyType; 295 if (typed.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) 296 bMethod |= ((XSComplexTypeDecl)typed).fBlock; 297 } 298 if (typed != typeb || (dMethod & bMethod) != 0) 300 return false; 301 302 methods.dMethod = dMethod; 304 methods.bMethod = bMethod; 305 return true; 306 } 307 308 private static final class OneSubGroup { 310 OneSubGroup() {} 311 OneSubGroup(XSElementDecl sub, short dMethod, short bMethod) { 312 this.sub = sub; 313 this.dMethod = dMethod; 314 this.bMethod = bMethod; 315 } 316 XSElementDecl sub; 318 short dMethod; 321 short bMethod; 324 } 325 } | Popular Tags |