1/*
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3 */
4/*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements.  See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package com.sun.org.apache.xerces.internal.impl.xs;
22
23import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
24import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
25import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
26import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
27import com.sun.org.apache.xerces.internal.xni.QName;
28import com.sun.org.apache.xerces.internal.xs.ShortList;
29import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
30import com.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
31import com.sun.org.apache.xerces.internal.xs.XSConstants;
32import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
33import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
34import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
35import com.sun.org.apache.xerces.internal.xs.XSObjectList;
36import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
37import com.sun.org.apache.xerces.internal.xs.XSValue;
38
39/**
40 * The XML representation for an element declaration
41 * schema component is an <element> element information item
42 *
43 * @xerces.internal
44 *
45 * @author Elena Litani, IBM
46 * @author Sandy Gao, IBM
47 */
48public class XSElementDecl implements XSElementDeclaration {
49
50    // scopes
51    public final static short     SCOPE_ABSENT        = 0;
52    public final static short     SCOPE_GLOBAL        = 1;
53    public final static short     SCOPE_LOCAL         = 2;
54
55    // name of the element
56    public String fName = null;
57    // target namespace of the element
58    public String fTargetNamespace = null;
59    // type of the element
60    public XSTypeDefinition fType = null;
61    public QName fUnresolvedTypeName = null;
62    // misc flag of the element: nillable/abstract/fixed
63    short fMiscFlags = 0;
64    public short fScope = XSConstants.SCOPE_ABSENT;
65    // enclosing complex type, when the scope is local
66    XSComplexTypeDecl fEnclosingCT = null;
67    // block set (disallowed substitutions) of the element
68    public short fBlock = XSConstants.DERIVATION_NONE;
69    // final set (substitution group exclusions) of the element
70    public short fFinal = XSConstants.DERIVATION_NONE;
71    // optional annotation
72    public XSObjectList fAnnotations = null;
73    // value constraint value
74    public ValidatedInfo fDefault = null;
75    // the substitution group affiliation of the element
76    public XSElementDecl fSubGroup = null;
77    // identity constraints
78    static final int INITIAL_SIZE = 2;
79    int fIDCPos = 0;
80    IdentityConstraint[] fIDConstraints = new IdentityConstraint[INITIAL_SIZE];
81    // The namespace schema information item corresponding to the target namespace
82    // of the element declaration, if it is globally declared; or null otherwise.
83    private XSNamespaceItem fNamespaceItem = null;
84
85    private static final short CONSTRAINT_MASK = 3;
86    private static final short NILLABLE        = 4;
87    private static final short ABSTRACT        = 8;
88
89    // methods to get/set misc flag
90    public void setConstraintType(short constraintType) {
91        // first clear the bits
92        fMiscFlags ^= (fMiscFlags & CONSTRAINT_MASK);
93        // then set the proper one
94        fMiscFlags |= (constraintType & CONSTRAINT_MASK);
95    }
96    public void setIsNillable() {
97        fMiscFlags |= NILLABLE;
98    }
99    public void setIsAbstract() {
100        fMiscFlags |= ABSTRACT;
101    }
102    public void setIsGlobal() {
103        fScope = SCOPE_GLOBAL;
104    }
105    public void setIsLocal(XSComplexTypeDecl enclosingCT) {
106        fScope = SCOPE_LOCAL;
107        fEnclosingCT = enclosingCT;
108    }
109
110    public void addIDConstraint(IdentityConstraint idc) {
111        if (fIDCPos == fIDConstraints.length) {
112            fIDConstraints = resize(fIDConstraints, fIDCPos*2);
113        }
114        fIDConstraints[fIDCPos++] = idc;
115    }
116
117    public IdentityConstraint[] getIDConstraints() {
118        if (fIDCPos == 0) {
119            return null;
120        }
121        if (fIDCPos < fIDConstraints.length) {
122            fIDConstraints = resize(fIDConstraints, fIDCPos);
123        }
124        return fIDConstraints;
125    }
126
127    static final IdentityConstraint[] resize(IdentityConstraint[] oldArray, int newSize) {
128        IdentityConstraint[] newArray = new IdentityConstraint[newSize];
129        System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
130        return newArray;
131    }
132
133    /**
134     * get the string description of this element
135     */
136    private String fDescription = null;
137    public String toString() {
138        if (fDescription == null) {
139            if (fTargetNamespace != null) {
140                StringBuffer buffer = new StringBuffer(
141                    fTargetNamespace.length() +
142                    ((fName != null) ? fName.length() : 4) + 3);
143                buffer.append('"');
144                buffer.append(fTargetNamespace);
145                buffer.append('"');
146                buffer.append(':');
147                buffer.append(fName);
148                fDescription = buffer.toString();
149            }
150            else {
151                fDescription = fName;
152            }
153        }
154        return fDescription;
155    }
156
157    /**
158     * get the hash code
159     */
160    public int hashCode() {
161        int code = fName.hashCode();
162        if (fTargetNamespace != null)
163            code = (code<<16)+fTargetNamespace.hashCode();
164        return code;
165    }
166
167    /**
168     * whether two decls are the same
169     */
170    public boolean equals(Object o) {
171        return o == this;
172    }
173
174    /**
175      * Reset current element declaration
176      */
177    public void reset(){
178        fScope = XSConstants.SCOPE_ABSENT;
179        fName = null;
180        fTargetNamespace = null;
181        fType = null;
182        fUnresolvedTypeName = null;
183        fMiscFlags = 0;
184        fBlock = XSConstants.DERIVATION_NONE;
185        fFinal = XSConstants.DERIVATION_NONE;
186        fDefault = null;
187        fAnnotations = null;
188        fSubGroup = null;
189        // reset identity constraints
190        for (int i=0;i<fIDCPos;i++) {
191            fIDConstraints[i] = null;
192        }
193
194        fIDCPos = 0;
195    }
196
197    /**
198     * Get the type of the object, i.e ELEMENT_DECLARATION.
199     */
200    public short getType() {
201        return XSConstants.ELEMENT_DECLARATION;
202    }
203
204    /**
205     * The <code>name</code> of this <code>XSObject</code> depending on the
206     * <code>XSObject</code> type.
207     */
208    public String getName() {
209        return fName;
210    }
211
212    /**
213     * The namespace URI of this node, or <code>null</code> if it is
214     * unspecified.  defines how a namespace URI is attached to schema
215     * components.
216     */
217    public String getNamespace() {
218        return fTargetNamespace;
219    }
220
221    /**
222     * Either a simple type definition or a complex type definition.
223     */
224    public XSTypeDefinition getTypeDefinition() {
225        return fType;
226    }
227
228    /**
229     * Optional. Either global or a complex type definition (
230     * <code>ctDefinition</code>). This property is absent in the case of
231     * declarations within named model groups: their scope will be
232     * determined when they are used in the construction of complex type
233     * definitions.
234     */
235    public short getScope() {
236        return fScope;
237    }
238
239    /**
240     * Locally scoped declarations are available for use only within the
241     * complex type definition identified by the <code>scope</code>
242     * property.
243     */
244    public XSComplexTypeDefinition getEnclosingCTDefinition() {
245        return fEnclosingCT;
246    }
247
248    /**
249     * A value constraint: one of default, fixed.
250     */
251    public short getConstraintType() {
252        return (short)(fMiscFlags & CONSTRAINT_MASK);
253    }
254
255    /**
256     * A value constraint: The actual value (with respect to the {type
257     * definition})
258     */
259    @Deprecated
260    public String getConstraintValue() {
261        // REVISIT: SCAPI: what's the proper representation
262        return getConstraintType() == XSConstants.VC_NONE ?
263               null :
264               fDefault.stringValue();
265    }
266
267    /**
268     * If {nillable} is true, then an element may also be valid if it carries
269     * the namespace qualified attribute with [local name] nil from
270     * namespace http://www.w3.org/2001/XMLSchema-instance and value true
271     * (see xsi:nil (2.6.2)) even if it has no text or element content
272     * despite a {content type} which would otherwise require content.
273     */
274    public boolean getNillable() {
275        return ((fMiscFlags & NILLABLE) != 0);
276    }
277
278    /**
279     * {identity-constraint definitions} A set of constraint definitions.
280     */
281    public XSNamedMap getIdentityConstraints() {
282        return new XSNamedMapImpl(fIDConstraints, fIDCPos);
283    }
284
285    /**
286     * {substitution group affiliation} Optional. A top-level element
287     * definition.
288     */
289    public XSElementDeclaration getSubstitutionGroupAffiliation() {
290        return fSubGroup;
291    }
292
293    /**
294     * Convenience method. Check if <code>exclusion</code> is a substitution
295     * group exclusion for this element declaration.
296     * @param exclusion Extension, restriction or none. Represents final
297     *   set for the element.
298     * @return True if <code>exclusion</code> is a part of the substitution
299     *   group exclusion subset.
300     */
301    public boolean isSubstitutionGroupExclusion(short exclusion) {
302        return (fFinal & exclusion) != 0;
303    }
304
305    /**
306     * Specifies if this declaration can be nominated as
307     * the {substitution group affiliation} of other
308     * element declarations having the same {type definition}
309     * or types derived therefrom.
310     *
311     * @return A bit flag representing {extension, restriction} or NONE.
312     */
313    public short getSubstitutionGroupExclusions() {
314        return fFinal;
315    }
316
317    /**
318     * Convenience method. Check if <code>disallowed</code> is a disallowed
319     * substitution for this element declaration.
320     * @param disallowed Substitution, extension, restriction or none.
321     *   Represents a block set for the element.
322     * @return True if <code>disallowed</code> is a part of the substitution
323     *   group exclusion subset.
324     */
325    public boolean isDisallowedSubstitution(short disallowed) {
326        return (fBlock & disallowed) != 0;
327    }
328
329    /**
330     * The supplied values for {disallowed substitutions}
331     *
332     * @return A bit flag representing {substitution, extension, restriction} or NONE.
333     */
334    public short getDisallowedSubstitutions() {
335        return fBlock;
336    }
337
338    /**
339     * {abstract} A boolean.
340     */
341    public boolean getAbstract() {
342        return ((fMiscFlags & ABSTRACT) != 0);
343    }
344
345    /**
346     * Optional. Annotation.
347     */
348    public XSAnnotation getAnnotation() {
349        return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
350    }
351
352    /**
353     * Optional. Annotations.
354     */
355    public XSObjectList getAnnotations() {
356        return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
357    }
358
359
360    /**
361     * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
362     */
363    public XSNamespaceItem getNamespaceItem() {
364        return fNamespaceItem;
365    }
366
367    void setNamespaceItem(XSNamespaceItem namespaceItem) {
368        fNamespaceItem = namespaceItem;
369    }
370
371    @Deprecated
372    public Object getActualVC() {
373        return getConstraintType() == XSConstants.VC_NONE ?
374               null :
375               fDefault.actualValue;
376    }
377
378    @Deprecated
379    public short getActualVCType() {
380        return getConstraintType() == XSConstants.VC_NONE ?
381               XSConstants.UNAVAILABLE_DT :
382               fDefault.actualValueType;
383    }
384
385    @Deprecated
386    public ShortList getItemValueTypes() {
387        return getConstraintType() == XSConstants.VC_NONE ?
388               null :
389               fDefault.itemValueTypes;
390    }
391
392    public XSValue getValueConstraintValue() {
393        return fDefault;
394    }
395
396} // class XSElementDecl
397