/* * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.xml.internal.xsom.impl; import com.sun.xml.internal.xsom.XSElementDecl; import com.sun.xml.internal.xsom.XSIdentityConstraint; import com.sun.xml.internal.xsom.XSModelGroup; import com.sun.xml.internal.xsom.XSModelGroupDecl; import com.sun.xml.internal.xsom.XSTerm; import com.sun.xml.internal.xsom.XSType; import com.sun.xml.internal.xsom.XSWildcard; import com.sun.xml.internal.xsom.XmlString; import com.sun.xml.internal.xsom.impl.parser.PatcherManager; import com.sun.xml.internal.xsom.impl.parser.SchemaDocumentImpl; import com.sun.xml.internal.xsom.visitor.XSFunction; import com.sun.xml.internal.xsom.visitor.XSTermFunction; import com.sun.xml.internal.xsom.visitor.XSTermFunctionWithParam; import com.sun.xml.internal.xsom.visitor.XSTermVisitor; import com.sun.xml.internal.xsom.visitor.XSVisitor; import org.xml.sax.Locator; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; public class ElementDecl extends DeclarationImpl implements XSElementDecl, Ref.Term { public ElementDecl( PatcherManager reader, SchemaDocumentImpl owner, AnnotationImpl _annon, Locator _loc, ForeignAttributesImpl fa, String _tns, String _name, boolean _anonymous, XmlString _defv, XmlString _fixedv, boolean _nillable, boolean _abstract, Boolean _form, Ref.Type _type, Ref.Element _substHead, int _substDisallowed, int _substExcluded, List idConstraints) { super(owner,_annon,_loc,fa,_tns,_name,_anonymous); this.defaultValue = _defv; this.fixedValue = _fixedv; this.nillable = _nillable; this._abstract = _abstract; this.form = _form; this.type = _type; this.substHead = _substHead; this.substDisallowed = _substDisallowed; this.substExcluded = _substExcluded; this.idConstraints = (List) Collections.unmodifiableList((List)idConstraints); for (IdentityConstraintImpl idc : idConstraints) idc.setParent(this); if(type==null) throw new IllegalArgumentException(); } private XmlString defaultValue; @Override public XmlString getDefaultValue() { return defaultValue; } private XmlString fixedValue; @Override public XmlString getFixedValue() { return fixedValue; } private boolean nillable; @Override public boolean isNillable() { return nillable; } private boolean _abstract; @Override public boolean isAbstract() { return _abstract; } private Ref.Type type; @Override public XSType getType() { return type.getType(); } private Ref.Element substHead; @Override public XSElementDecl getSubstAffiliation() { if(substHead==null) return null; return substHead.get(); } private int substDisallowed; @Override public boolean isSubstitutionDisallowed( int method ) { return (substDisallowed&method)!=0; } private int substExcluded; @Override public boolean isSubstitutionExcluded( int method ) { return (substExcluded&method)!=0; } private final List idConstraints; @Override public List getIdentityConstraints() { return idConstraints; } private Boolean form; @Override public Boolean getForm() { return form; } /** * @deprecated */ @Override public XSElementDecl[] listSubstitutables() { Set s = getSubstitutables(); return s.toArray(new XSElementDecl[s.size()]); } /** Set that represents element decls that can substitute this element. */ private Set substitutables = null; /** Unmodifieable view of {@link #substitutables}. */ private Set substitutablesView = null; @Override public Set getSubstitutables() { if( substitutables==null ) { // if the field is null by the time this method // is called, it means this element is substitutable by itself only. substitutables = substitutablesView = Collections.singleton((XSElementDecl)this); } return substitutablesView; } protected void addSubstitutable( ElementDecl decl ) { if( substitutables==null ) { substitutables = new HashSet(); substitutables.add(this); substitutablesView = Collections.unmodifiableSet(substitutables); } substitutables.add(decl); } public void updateSubstitutabilityMap() { ElementDecl parent = this; XSType type = this.getType(); boolean rused = false; boolean eused = false; while( (parent=(ElementDecl)parent.getSubstAffiliation())!=null ) { if(parent.isSubstitutionDisallowed(XSType.SUBSTITUTION)) continue; boolean rd = parent.isSubstitutionDisallowed(XSType.RESTRICTION); boolean ed = parent.isSubstitutionDisallowed(XSType.EXTENSION); if( (rd && rused) || ( ed && eused ) ) continue; XSType parentType = parent.getType(); while (type!=parentType) { if(type.getDerivationMethod()==XSType.RESTRICTION) rused = true; else eused = true; type = type.getBaseType(); if(type==null) // parentType and type doesn't share the common base type. a bug in the schema. break; if( type.isComplexType() ) { rd |= type.asComplexType().isSubstitutionProhibited(XSType.RESTRICTION); ed |= type.asComplexType().isSubstitutionProhibited(XSType.EXTENSION); } if (getRoot().getAnyType().equals(type)) break; } if( (rd && rused) || ( ed && eused ) ) continue; // this element can substitute "parent" parent.addSubstitutable(this); } } @Override public boolean canBeSubstitutedBy(XSElementDecl e) { return getSubstitutables().contains(e); } @Override public boolean isWildcard() { return false; } @Override public boolean isModelGroupDecl() { return false; } @Override public boolean isModelGroup() { return false; } @Override public boolean isElementDecl() { return true; } @Override public XSWildcard asWildcard() { return null; } @Override public XSModelGroupDecl asModelGroupDecl() { return null; } @Override public XSModelGroup asModelGroup() { return null; } @Override public XSElementDecl asElementDecl() { return this; } @Override public void visit( XSVisitor visitor ) { visitor.elementDecl(this); } @Override public void visit( XSTermVisitor visitor ) { visitor.elementDecl(this); } @Override public Object apply( XSTermFunction function ) { return function.elementDecl(this); } @Override public T apply(XSTermFunctionWithParam function, P param) { return function.elementDecl(this,param); } @Override public Object apply( XSFunction function ) { return function.elementDecl(this); } // Ref.Term implementation @Override public XSTerm getTerm() { return this; } }