1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.xsom.impl; 27 28 import com.sun.xml.internal.xsom.XSElementDecl; 29 import com.sun.xml.internal.xsom.XSIdentityConstraint; 30 import com.sun.xml.internal.xsom.XSModelGroup; 31 import com.sun.xml.internal.xsom.XSModelGroupDecl; 32 import com.sun.xml.internal.xsom.XSTerm; 33 import com.sun.xml.internal.xsom.XSType; 34 import com.sun.xml.internal.xsom.XSWildcard; 35 import com.sun.xml.internal.xsom.XmlString; 36 import com.sun.xml.internal.xsom.impl.parser.PatcherManager; 37 import com.sun.xml.internal.xsom.impl.parser.SchemaDocumentImpl; 38 import com.sun.xml.internal.xsom.visitor.XSFunction; 39 import com.sun.xml.internal.xsom.visitor.XSTermFunction; 40 import com.sun.xml.internal.xsom.visitor.XSTermFunctionWithParam; 41 import com.sun.xml.internal.xsom.visitor.XSTermVisitor; 42 import com.sun.xml.internal.xsom.visitor.XSVisitor; 43 import org.xml.sax.Locator; 44 45 import java.util.Collections; 46 import java.util.HashSet; 47 import java.util.List; 48 import java.util.Set; 49 50 public class ElementDecl extends DeclarationImpl implements XSElementDecl, Ref.Term 51 { 52 public ElementDecl( PatcherManager reader, SchemaDocumentImpl owner, 53 AnnotationImpl _annon, Locator _loc, ForeignAttributesImpl fa, 54 String _tns, String _name, boolean _anonymous, 55 56 XmlString _defv, XmlString _fixedv, 57 boolean _nillable, boolean _abstract, Boolean _form, 58 Ref.Type _type, Ref.Element _substHead, 59 int _substDisallowed, int _substExcluded, 60 List<IdentityConstraintImpl> idConstraints) { 61 62 super(owner,_annon,_loc,fa,_tns,_name,_anonymous); 63 64 this.defaultValue = _defv; 65 this.fixedValue = _fixedv; 66 this.nillable = _nillable; 67 this._abstract = _abstract; 68 this.form = _form; 69 this.type = _type; 70 this.substHead = _substHead; 71 this.substDisallowed = _substDisallowed; 72 this.substExcluded = _substExcluded; 73 this.idConstraints = (List<XSIdentityConstraint>) Collections.unmodifiableList((List<? extends XSIdentityConstraint>)idConstraints); 74 75 for (IdentityConstraintImpl idc : idConstraints) 76 idc.setParent(this); 77 78 if(type==null) 79 throw new IllegalArgumentException(); 80 } 81 82 private XmlString defaultValue; 83 @Override 84 public XmlString getDefaultValue() { return defaultValue; } 85 86 private XmlString fixedValue; 87 @Override 88 public XmlString getFixedValue() { return fixedValue; } 89 90 private boolean nillable; 91 @Override 92 public boolean isNillable() { return nillable; } 93 94 private boolean _abstract; 95 @Override 96 public boolean isAbstract() { return _abstract; } 97 98 private Ref.Type type; 99 @Override 100 public XSType getType() { return type.getType(); } 101 102 private Ref.Element substHead; 103 @Override 104 public XSElementDecl getSubstAffiliation() { 105 if(substHead==null) return null; 106 return substHead.get(); 107 } 108 109 private int substDisallowed; 110 @Override 111 public boolean isSubstitutionDisallowed( int method ) { 112 return (substDisallowed&method)!=0; 113 } 114 115 private int substExcluded; 116 @Override 117 public boolean isSubstitutionExcluded( int method ) { 118 return (substExcluded&method)!=0; 119 } 120 121 private final List<XSIdentityConstraint> idConstraints; 122 @Override 123 public List<XSIdentityConstraint> getIdentityConstraints() { 124 return idConstraints; 125 } 126 127 private Boolean form; 128 @Override 129 public Boolean getForm() { 130 return form; 131 } 132 133 134 /** 135 * @deprecated 136 */ 137 @Override 138 public XSElementDecl[] listSubstitutables() { 139 Set<? extends XSElementDecl> s = getSubstitutables(); 140 return s.toArray(new XSElementDecl[s.size()]); 141 } 142 143 /** Set that represents element decls that can substitute this element. */ 144 private Set<XSElementDecl> substitutables = null; 145 146 /** Unmodifieable view of {@link #substitutables}. */ 147 private Set<XSElementDecl> substitutablesView = null; 148 149 @Override 150 public Set<? extends XSElementDecl> getSubstitutables() { 151 if( substitutables==null ) { 152 // if the field is null by the time this method 153 // is called, it means this element is substitutable by itself only. 154 substitutables = substitutablesView = Collections.singleton((XSElementDecl)this); 155 } 156 return substitutablesView; 157 } 158 159 protected void addSubstitutable( ElementDecl decl ) { 160 if( substitutables==null ) { 161 substitutables = new HashSet<XSElementDecl>(); 162 substitutables.add(this); 163 substitutablesView = Collections.unmodifiableSet(substitutables); 164 } 165 substitutables.add(decl); 166 } 167 168 169 public void updateSubstitutabilityMap() { 170 ElementDecl parent = this; 171 XSType type = this.getType(); 172 173 boolean rused = false; 174 boolean eused = false; 175 176 while( (parent=(ElementDecl)parent.getSubstAffiliation())!=null ) { 177 178 if(parent.isSubstitutionDisallowed(XSType.SUBSTITUTION)) 179 continue; 180 181 boolean rd = parent.isSubstitutionDisallowed(XSType.RESTRICTION); 182 boolean ed = parent.isSubstitutionDisallowed(XSType.EXTENSION); 183 184 if( (rd && rused) || ( ed && eused ) ) continue; 185 186 XSType parentType = parent.getType(); 187 while (type!=parentType) { 188 if(type.getDerivationMethod()==XSType.RESTRICTION) rused = true; 189 else eused = true; 190 191 type = type.getBaseType(); 192 if(type==null) // parentType and type doesn't share the common base type. a bug in the schema. 193 break; 194 195 if( type.isComplexType() ) { 196 rd |= type.asComplexType().isSubstitutionProhibited(XSType.RESTRICTION); 197 ed |= type.asComplexType().isSubstitutionProhibited(XSType.EXTENSION); 198 } 199 if (getRoot().getAnyType().equals(type)) break; 200 } 201 202 if( (rd && rused) || ( ed && eused ) ) continue; 203 204 // this element can substitute "parent" 205 parent.addSubstitutable(this); 206 } 207 } 208 209 @Override 210 public boolean canBeSubstitutedBy(XSElementDecl e) { 211 return getSubstitutables().contains(e); 212 } 213 214 @Override 215 public boolean isWildcard() { return false; } 216 @Override 217 public boolean isModelGroupDecl() { return false; } 218 @Override 219 public boolean isModelGroup() { return false; } 220 @Override 221 public boolean isElementDecl() { return true; } 222 223 @Override 224 public XSWildcard asWildcard() { return null; } 225 @Override 226 public XSModelGroupDecl asModelGroupDecl() { return null; } 227 @Override 228 public XSModelGroup asModelGroup() { return null; } 229 @Override 230 public XSElementDecl asElementDecl() { return this; } 231 232 233 234 235 @Override 236 public void visit( XSVisitor visitor ) { 237 visitor.elementDecl(this); 238 } 239 @Override 240 public void visit( XSTermVisitor visitor ) { 241 visitor.elementDecl(this); 242 } 243 @Override 244 public Object apply( XSTermFunction function ) { 245 return function.elementDecl(this); 246 } 247 248 @Override 249 public <T,P> T apply(XSTermFunctionWithParam<T, P> function, P param) { 250 return function.elementDecl(this,param); 251 } 252 253 @Override 254 public Object apply( XSFunction function ) { 255 return function.elementDecl(this); 256 } 257 258 259 // Ref.Term implementation 260 @Override 261 public XSTerm getTerm() { return this; } 262 }