View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * 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  
21  package com.sun.org.apache.xerces.internal.impl.xs;
22  
23  import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
24  import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
25  import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
26  import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
27  import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
28  import com.sun.org.apache.xerces.internal.xs.XSConstants;
29  import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
30  import com.sun.org.apache.xerces.internal.xs.XSObjectList;
31  import com.sun.org.apache.xerces.internal.xs.XSWildcard;
32  
33  /**
34   * The XML representation for an attribute group declaration
35   * schema component is a global <attributeGroup> element information item
36   *
37   * @xerces.internal
38   *
39   * @author Sandy Gao, IBM
40   * @author Rahul Srivastava, Sun Microsystems Inc.
41   *
42   * @version $Id: XSAttributeGroupDecl.java,v 1.7 2010-11-01 04:39:55 joehw Exp $
43   */
44  public class XSAttributeGroupDecl implements XSAttributeGroupDefinition {
45  
46      // name of the attribute group
47      public String fName = null;
48      // target namespace of the attribute group
49      public String fTargetNamespace = null;
50      // number of attribute uses included by this attribute group
51      int fAttrUseNum = 0;
52      // attribute uses included by this attribute group
53      private static final int INITIAL_SIZE = 5;
54      XSAttributeUseImpl[] fAttributeUses = new XSAttributeUseImpl[INITIAL_SIZE];
55      // attribute wildcard included by this attribute group
56      public XSWildcardDecl fAttributeWC = null;
57      // whether there is an attribute use whose type is or is derived from ID.
58      public String fIDAttrName = null;
59  
60      // optional annotation
61      public XSObjectList fAnnotations;
62  
63      protected XSObjectListImpl fAttrUses = null;
64  
65      // The namespace schema information item corresponding to the target namespace
66      // of the attribute group definition, if it is globally declared; or null otherwise.
67      private XSNamespaceItem fNamespaceItem = null;
68  
69      // add an attribute use
70      // if the type is derived from ID, but there is already another attribute
71      // use of type ID, then return the name of the other attribute use;
72      // otherwise, return null
73      public String addAttributeUse(XSAttributeUseImpl attrUse) {
74  
75          // if this attribute use is prohibited, then don't check whether it's
76          // of type ID
77          if (attrUse.fUse != SchemaSymbols.USE_PROHIBITED) {
78              if (attrUse.fAttrDecl.fType.isIDType()) {
79                  // if there is already an attribute use of type ID,
80                  // return its name (and don't add it to the list, to avoid
81                  // interruption to instance validation.
82                  if (fIDAttrName == null)
83                      fIDAttrName = attrUse.fAttrDecl.fName;
84                  else
85                      return fIDAttrName;
86              }
87          }
88  
89          if (fAttrUseNum == fAttributeUses.length) {
90              fAttributeUses = resize(fAttributeUses, fAttrUseNum*2);
91          }
92          fAttributeUses[fAttrUseNum++] = attrUse;
93  
94          return null;
95      }
96  
97      public void replaceAttributeUse(XSAttributeUse oldUse, XSAttributeUseImpl newUse) {
98          for (int i=0; i<fAttrUseNum; i++) {
99              if (fAttributeUses[i] == oldUse) {
100                 fAttributeUses[i] = newUse;
101             }
102         }
103     }
104 
105     public XSAttributeUse getAttributeUse(String namespace, String name) {
106         for (int i=0; i<fAttrUseNum; i++) {
107             if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
108                  (fAttributeUses[i].fAttrDecl.fName == name) )
109                 return fAttributeUses[i];
110         }
111 
112         return null;
113     }
114 
115     public XSAttributeUse getAttributeUseNoProhibited(String namespace, String name) {
116         for (int i=0; i<fAttrUseNum; i++) {
117             if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
118                  (fAttributeUses[i].fAttrDecl.fName == name) &&
119                  (fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED))
120                 return fAttributeUses[i];
121         }
122 
123         return null;
124     }
125 
126     public void removeProhibitedAttrs() {
127         if (fAttrUseNum == 0) return;
128         // Remove all prohibited attributes.
129         int count = 0;
130         XSAttributeUseImpl[] uses = new XSAttributeUseImpl[fAttrUseNum];
131         for (int i = 0; i < fAttrUseNum; i++) {
132             if (fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED) {
133                 uses[count++] = fAttributeUses[i];
134             }
135         }
136         fAttributeUses = uses;
137         fAttrUseNum = count;
138 
139         // Do not remove attributes that have the same name as the prohibited
140         // ones, because they are specified at the same level. Prohibited
141         // attributes are only to remove attributes from the base type in a
142         // restriction.
143 //        int newCount = 0;
144 //        if (pCount > 0) {
145 //            OUTER: for (int i = 0; i < fAttrUseNum; i++) {
146 //                if (fAttributeUses[i].fUse == SchemaSymbols.USE_PROHIBITED)
147 //                    continue;
148 //                for (int j = 1; j <= pCount; j++) {
149 //                    if (fAttributeUses[i].fAttrDecl.fName == pUses[fAttrUseNum-pCount].fAttrDecl.fName &&
150 //                        fAttributeUses[i].fAttrDecl.fTargetNamespace == pUses[fAttrUseNum-pCount].fAttrDecl.fTargetNamespace) {
151 //                        continue OUTER;
152 //                    }
153 //                }
154 //                pUses[newCount++] = fAttributeUses[i];
155 //            }
156 //            fAttributeUses = pUses;
157 //            fAttrUseNum = newCount;
158 //        }
159     }
160 
161     /**
162      * Check that the attributes in this group validly restrict those from a base group.
163      * If an error is found, an Object[] is returned. This contains the arguments for the error message
164      * describing the error. The last element in the array (at index arr.length - 1) is the the error code.
165      * Returns null if there is no error.
166      *
167      * REVISIT: is there a better way of returning the appropriate information for the error?
168      *
169      * @param typeName the name of the type containing this attribute group, used for error reporting purposes
170      * @param baseGroup the XSAttributeGroupDecl that is the base we are checking against
171      */
172     public Object[] validRestrictionOf(String typeName, XSAttributeGroupDecl baseGroup) {
173 
174         Object[] errorArgs = null;
175         XSAttributeUseImpl attrUse = null;
176         XSAttributeDecl attrDecl = null;
177         XSAttributeUseImpl baseAttrUse = null;
178         XSAttributeDecl baseAttrDecl = null;
179 
180         for (int i=0; i<fAttrUseNum; i++) {
181 
182             attrUse = fAttributeUses[i];
183             attrDecl = attrUse.fAttrDecl;
184 
185             // Look for a match in the base
186             baseAttrUse = (XSAttributeUseImpl)baseGroup.getAttributeUse(attrDecl.fTargetNamespace,attrDecl.fName);
187             if (baseAttrUse != null) {
188                 //
189                 // derivation-ok-restriction.  Constraint 2.1.1
190                 //
191 
192                 if (baseAttrUse.getRequired() && !attrUse.getRequired()) {
193                     errorArgs = new Object[]{typeName, attrDecl.fName,
194                                              attrUse.fUse == SchemaSymbols.USE_OPTIONAL ? SchemaSymbols.ATTVAL_OPTIONAL : SchemaSymbols.ATTVAL_PROHIBITED,
195                                              "derivation-ok-restriction.2.1.1"};
196                     return errorArgs;
197                 }
198 
199                 // if this attribute is prohibited in the derived type, don't
200                 // need to check any of the following constraints.
201                 if (attrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
202                     continue;
203                 }
204 
205                 baseAttrDecl = baseAttrUse.fAttrDecl;
206                 //
207                 // derivation-ok-restriction.  Constraint 2.1.1
208                 //
209                 if (! XSConstraints.checkSimpleDerivationOk(attrDecl.fType,
210                                                             baseAttrDecl.fType,
211                                                             baseAttrDecl.fType.getFinal()) ) {
212                                         errorArgs = new Object[]{typeName, attrDecl.fName, attrDecl.fType.getName(),
213                                                                      baseAttrDecl.fType.getName(), "derivation-ok-restriction.2.1.2"};
214                                         return errorArgs;
215                 }
216 
217 
218                 //
219                 // derivation-ok-restriction.  Constraint 2.1.3
220                 //
221                 int baseConsType=baseAttrUse.fConstraintType!=XSConstants.VC_NONE?
222                                  baseAttrUse.fConstraintType:baseAttrDecl.getConstraintType();
223                 int thisConstType = attrUse.fConstraintType!=XSConstants.VC_NONE?
224                                     attrUse.fConstraintType:attrDecl.getConstraintType();
225 
226                 if (baseConsType == XSConstants.VC_FIXED) {
227 
228                     if (thisConstType != XSConstants.VC_FIXED) {
229                                                 errorArgs = new Object[]{typeName, attrDecl.fName,
230                                                                                                  "derivation-ok-restriction.2.1.3.a"};
231                                                 return errorArgs;
232                     } else {
233                         // check the values are the same.
234                         ValidatedInfo baseFixedValue=(baseAttrUse.fDefault!=null ?
235                                                       baseAttrUse.fDefault: baseAttrDecl.fDefault);
236                         ValidatedInfo thisFixedValue=(attrUse.fDefault!=null ?
237                                                       attrUse.fDefault: attrDecl.fDefault);
238                         if (!baseFixedValue.actualValue.equals(thisFixedValue.actualValue)) {
239                                                         errorArgs = new Object[]{typeName, attrDecl.fName, thisFixedValue.stringValue(),
240                                                                                                          baseFixedValue.stringValue(), "derivation-ok-restriction.2.1.3.b"};
241                                                         return errorArgs;
242                         }
243 
244                     }
245 
246                 }
247             } else {
248                 // No matching attribute in base - there should be a matching wildcard
249 
250                 //
251                 // derivation-ok-restriction.  Constraint 2.2
252                 //
253                 if (baseGroup.fAttributeWC == null) {
254                                         errorArgs = new Object[]{typeName, attrDecl.fName,
255                                                                                          "derivation-ok-restriction.2.2.a"};
256                                         return errorArgs;
257                 }
258                 else if (!baseGroup.fAttributeWC.allowNamespace(attrDecl.fTargetNamespace)) {
259                                         errorArgs = new Object[]{typeName, attrDecl.fName,
260                                              attrDecl.fTargetNamespace==null?"":attrDecl.fTargetNamespace,
261                                                                                          "derivation-ok-restriction.2.2.b"};
262                                         return errorArgs;
263                 }
264             }
265         }
266 
267         //
268         // Check that any REQUIRED attributes in the base have matching attributes
269         // in this group
270         // derivation-ok-restriction.  Constraint 3
271         //
272         for (int i=0; i<baseGroup.fAttrUseNum; i++) {
273 
274             baseAttrUse = baseGroup.fAttributeUses[i];
275 
276             if (baseAttrUse.fUse == SchemaSymbols.USE_REQUIRED) {
277 
278                 baseAttrDecl = baseAttrUse.fAttrDecl;
279                 // Look for a match in this group
280                 if (getAttributeUse(baseAttrDecl.fTargetNamespace,baseAttrDecl.fName) == null) {
281                                         errorArgs = new Object[]{typeName, baseAttrUse.fAttrDecl.fName,
282                                                                                          "derivation-ok-restriction.3"};
283                                         return errorArgs;
284                 }
285             }
286         }
287 
288 
289         // Now, check wildcards
290         //
291         // derivation-ok-restriction.  Constraint 4
292         //
293         if (fAttributeWC != null) {
294             if (baseGroup.fAttributeWC == null) {
295                                 errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.1"};
296                                 return errorArgs;
297             }
298             if (! fAttributeWC.isSubsetOf(baseGroup.fAttributeWC)) {
299                                 errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.2"};
300                                 return errorArgs;
301             }
302             if (fAttributeWC.weakerProcessContents(baseGroup.fAttributeWC)) {
303                                 errorArgs = new Object[]{typeName,
304                                                                                  fAttributeWC.getProcessContentsAsString(),
305                                                                                  baseGroup.fAttributeWC.getProcessContentsAsString(),
306                                                                                  "derivation-ok-restriction.4.3"};
307                                 return errorArgs;
308             }
309         }
310 
311         return null;
312 
313     }
314 
315     static final XSAttributeUseImpl[] resize(XSAttributeUseImpl[] oldArray, int newSize) {
316         XSAttributeUseImpl[] newArray = new XSAttributeUseImpl[newSize];
317         System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
318         return newArray;
319     }
320 
321     // reset the attribute group declaration
322     public void reset(){
323         fName = null;
324         fTargetNamespace = null;
325         // reset attribute uses
326         for (int i=0;i<fAttrUseNum;i++) {
327             fAttributeUses[i] = null;
328         }
329         fAttrUseNum = 0;
330         fAttributeWC = null;
331         fAnnotations = null;
332         fIDAttrName = null;
333 
334     }
335 
336     /**
337      * Get the type of the object, i.e ELEMENT_DECLARATION.
338      */
339     public short getType() {
340         return XSConstants.ATTRIBUTE_GROUP;
341     }
342 
343     /**
344      * The <code>name</code> of this <code>XSObject</code> depending on the
345      * <code>XSObject</code> type.
346      */
347     public String getName() {
348         return fName;
349     }
350 
351     /**
352      * The namespace URI of this node, or <code>null</code> if it is
353      * unspecified.  defines how a namespace URI is attached to schema
354      * components.
355      */
356     public String getNamespace() {
357         return fTargetNamespace;
358     }
359 
360     /**
361      * {attribute uses} A set of attribute uses.
362      */
363     public XSObjectList getAttributeUses() {
364         if (fAttrUses == null){
365             fAttrUses = new XSObjectListImpl(fAttributeUses, fAttrUseNum);
366         }
367         return fAttrUses;
368     }
369 
370     /**
371      * {attribute wildcard} Optional. A wildcard.
372      */
373     public XSWildcard getAttributeWildcard() {
374         return fAttributeWC;
375     }
376 
377     /**
378      * Optional. Annotation.
379      */
380     public XSAnnotation getAnnotation() {
381         return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
382     }
383 
384     /**
385      * Optional. Annotations.
386      */
387     public XSObjectList getAnnotations() {
388         return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
389     }
390 
391     /**
392      * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
393      */
394     public XSNamespaceItem getNamespaceItem() {
395         return fNamespaceItem;
396     }
397 
398     void setNamespaceItem(XSNamespaceItem namespaceItem) {
399         fNamespaceItem = namespaceItem;
400     }
401 
402 } // class XSAttributeGroupDecl