/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * http://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.xml.xsom.impl; import com.sun.xml.xsom.XSElementDecl; import com.sun.xml.xsom.XSIdentityConstraint; import com.sun.xml.xsom.XSModelGroup; import com.sun.xml.xsom.XSModelGroupDecl; import com.sun.xml.xsom.XSTerm; import com.sun.xml.xsom.XSType; import com.sun.xml.xsom.XSWildcard; import com.sun.xml.xsom.XmlString; import com.sun.xml.xsom.impl.parser.PatcherManager; import com.sun.xml.xsom.impl.parser.SchemaDocumentImpl; import com.sun.xml.xsom.visitor.XSFunction; import com.sun.xml.xsom.visitor.XSTermFunction; import com.sun.xml.xsom.visitor.XSTermFunctionWithParam; import com.sun.xml.xsom.visitor.XSTermVisitor; import com.sun.xml.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<IdentityConstraintImpl> 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<XSIdentityConstraint>) Collections.unmodifiableList((List<? extends XSIdentityConstraint>)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<XSIdentityConstraint> idConstraints; @Override public List<XSIdentityConstraint> getIdentityConstraints() { return idConstraints; } private Boolean form; @Override public Boolean getForm() { return form; } /** * @deprecated */ @Override public XSElementDecl[] listSubstitutables() { Set<? extends XSElementDecl> s = getSubstitutables(); return s.toArray(new XSElementDecl[s.size()]); } /** Set that represents element decls that can substitute this element. */ private Set<XSElementDecl> substitutables = null; /** Unmodifieable view of {@link #substitutables}. */ private Set<XSElementDecl> substitutablesView = null; @Override public Set<? extends XSElementDecl> 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<XSElementDecl>(); 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,P> T apply(XSTermFunctionWithParam<T, P> 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; } }