001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.impl.xs;
019:
020: import org.apache.xerces.impl.dv.ValidatedInfo;
021: import org.apache.xerces.xs.XSAnnotation;
022: import org.apache.xerces.xs.XSAttributeGroupDefinition;
023: import org.apache.xerces.xs.XSAttributeUse;
024: import org.apache.xerces.xs.XSConstants;
025: import org.apache.xerces.xs.XSNamespaceItem;
026: import org.apache.xerces.xs.XSObjectList;
027: import org.apache.xerces.xs.XSWildcard;
028: import org.apache.xerces.impl.xs.util.XSObjectListImpl;
029:
030: /**
031: * The XML representation for an attribute group declaration
032: * schema component is a global <attributeGroup> element information item
033: *
034: * @xerces.internal
035: *
036: * @author Sandy Gao, IBM
037: * @author Rahul Srivastava, Sun Microsystems Inc.
038: *
039: * @version $Id: XSAttributeGroupDecl.java 449424 2006-09-24 16:22:30Z mrglavas $
040: */
041: public class XSAttributeGroupDecl implements XSAttributeGroupDefinition {
042:
043: // name of the attribute group
044: public String fName = null;
045: // target namespace of the attribute group
046: public String fTargetNamespace = null;
047: // number of attribute uses included by this attribute group
048: int fAttrUseNum = 0;
049: // attribute uses included by this attribute group
050: private static final int INITIAL_SIZE = 5;
051: XSAttributeUseImpl[] fAttributeUses = new XSAttributeUseImpl[INITIAL_SIZE];
052: // attribute wildcard included by this attribute group
053: public XSWildcardDecl fAttributeWC = null;
054: // whether there is an attribute use whose type is or is derived from ID.
055: public String fIDAttrName = null;
056:
057: // optional annotation
058: public XSObjectList fAnnotations;
059:
060: protected XSObjectListImpl fAttrUses = null;
061:
062: // add an attribute use
063: // if the type is derived from ID, but there is already another attribute
064: // use of type ID, then return the name of the other attribute use;
065: // otherwise, return null
066: public String addAttributeUse(XSAttributeUseImpl attrUse) {
067:
068: if (fAttrUseNum == fAttributeUses.length) {
069: fAttributeUses = resize(fAttributeUses, fAttrUseNum * 2);
070: }
071: fAttributeUses[fAttrUseNum++] = attrUse;
072: // if this attribute use is prohibited, then don't check whether it's
073: // of type ID
074: if (attrUse.fUse == SchemaSymbols.USE_PROHIBITED)
075: return null;
076:
077: if (attrUse.fAttrDecl.fType.isIDType()) {
078: // if there is already an attribute use of type ID, return it' sname
079: if (fIDAttrName == null)
080: fIDAttrName = attrUse.fAttrDecl.fName;
081: else
082: return fIDAttrName;
083: }
084:
085: return null;
086: }
087:
088: public XSAttributeUse getAttributeUse(String namespace, String name) {
089: for (int i = 0; i < fAttrUseNum; i++) {
090: if ((fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace)
091: && (fAttributeUses[i].fAttrDecl.fName == name))
092: return fAttributeUses[i];
093: }
094:
095: return null;
096: }
097:
098: public void removeProhibitedAttrs() {
099: if (fAttrUseNum == 0)
100: return;
101: int pCount = 0;
102: XSAttributeUseImpl[] pUses = new XSAttributeUseImpl[fAttrUseNum];
103: for (int i = 0; i < fAttrUseNum; i++) {
104: if (fAttributeUses[i].fUse == SchemaSymbols.USE_PROHIBITED) {
105: pCount++;
106: // we use the entries at the end, so that we can use the
107: // first entries to store non-prohibited attribute uses,
108: // hence avoid creating a new array.
109: pUses[fAttrUseNum - pCount] = fAttributeUses[i];
110: }
111: }
112:
113: int newCount = 0;
114: if (pCount > 0) {
115: OUTER: for (int i = 0; i < fAttrUseNum; i++) {
116: if (fAttributeUses[i].fUse == SchemaSymbols.USE_PROHIBITED)
117: continue;
118: for (int j = 1; j <= pCount; j++) {
119: if (fAttributeUses[i].fAttrDecl.fName == pUses[fAttrUseNum
120: - pCount].fAttrDecl.fName
121: && fAttributeUses[i].fAttrDecl.fTargetNamespace == pUses[fAttrUseNum
122: - pCount].fAttrDecl.fTargetNamespace) {
123: continue OUTER;
124: }
125: }
126: pUses[newCount++] = fAttributeUses[i];
127: }
128: fAttributeUses = pUses;
129: fAttrUseNum = newCount;
130: }
131: }
132:
133: /**
134: * Check that the attributes in this group validly restrict those from a base group.
135: * If an error is found, an Object[] is returned. This contains the arguments for the error message
136: * describing the error. The last element in the array (at index arr.length - 1) is the the error code.
137: * Returns null if there is no error.
138: *
139: * REVISIT: is there a better way of returning the appropriate information for the error?
140: *
141: * @param typeName the name of the type containing this attribute group, used for error reporting purposes
142: * @param baseGroup the XSAttributeGroupDecl that is the base we are checking against
143: */
144: public Object[] validRestrictionOf(String typeName,
145: XSAttributeGroupDecl baseGroup) {
146:
147: Object[] errorArgs = null;
148: XSAttributeUseImpl attrUse = null;
149: XSAttributeDecl attrDecl = null;
150: XSAttributeUseImpl baseAttrUse = null;
151: XSAttributeDecl baseAttrDecl = null;
152:
153: for (int i = 0; i < fAttrUseNum; i++) {
154:
155: attrUse = fAttributeUses[i];
156: attrDecl = attrUse.fAttrDecl;
157:
158: // Look for a match in the base
159: baseAttrUse = (XSAttributeUseImpl) baseGroup
160: .getAttributeUse(attrDecl.fTargetNamespace,
161: attrDecl.fName);
162: if (baseAttrUse != null) {
163: //
164: // derivation-ok-restriction. Constraint 2.1.1
165: //
166:
167: if (baseAttrUse.getRequired() && !attrUse.getRequired()) {
168: errorArgs = new Object[] {
169: typeName,
170: attrDecl.fName,
171: attrUse.fUse == SchemaSymbols.USE_OPTIONAL ? SchemaSymbols.ATTVAL_OPTIONAL
172: : SchemaSymbols.ATTVAL_PROHIBITED,
173: "derivation-ok-restriction.2.1.1" };
174: return errorArgs;
175: }
176:
177: // if this attribute is prohibited in the derived type, don't
178: // need to check any of the following constraints.
179: if (attrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
180: continue;
181: }
182:
183: baseAttrDecl = baseAttrUse.fAttrDecl;
184: //
185: // derivation-ok-restriction. Constraint 2.1.1
186: //
187: if (!XSConstraints.checkSimpleDerivationOk(
188: attrDecl.fType, baseAttrDecl.fType,
189: baseAttrDecl.fType.getFinal())) {
190: errorArgs = new Object[] { typeName,
191: attrDecl.fName, attrDecl.fType.getName(),
192: baseAttrDecl.fType.getName(),
193: "derivation-ok-restriction.2.1.2" };
194: return errorArgs;
195: }
196:
197: //
198: // derivation-ok-restriction. Constraint 2.1.3
199: //
200: int baseConsType = baseAttrUse.fConstraintType != XSConstants.VC_NONE ? baseAttrUse.fConstraintType
201: : baseAttrDecl.getConstraintType();
202: int this ConstType = attrUse.fConstraintType != XSConstants.VC_NONE ? attrUse.fConstraintType
203: : attrDecl.getConstraintType();
204:
205: if (baseConsType == XSConstants.VC_FIXED) {
206:
207: if (this ConstType != XSConstants.VC_FIXED) {
208: errorArgs = new Object[] { typeName,
209: attrDecl.fName,
210: "derivation-ok-restriction.2.1.3.a" };
211: return errorArgs;
212: } else {
213: // check the values are the same.
214: ValidatedInfo baseFixedValue = (baseAttrUse.fDefault != null ? baseAttrUse.fDefault
215: : baseAttrDecl.fDefault);
216: ValidatedInfo this FixedValue = (attrUse.fDefault != null ? attrUse.fDefault
217: : attrDecl.fDefault);
218: if (!baseFixedValue.actualValue
219: .equals(this FixedValue.actualValue)) {
220: errorArgs = new Object[] { typeName,
221: attrDecl.fName,
222: this FixedValue.stringValue(),
223: baseFixedValue.stringValue(),
224: "derivation-ok-restriction.2.1.3.b" };
225: return errorArgs;
226: }
227:
228: }
229:
230: }
231: } else {
232: // No matching attribute in base - there should be a matching wildcard
233:
234: //
235: // derivation-ok-restriction. Constraint 2.2
236: //
237: if (baseGroup.fAttributeWC == null) {
238: errorArgs = new Object[] { typeName,
239: attrDecl.fName,
240: "derivation-ok-restriction.2.2.a" };
241: return errorArgs;
242: } else if (!baseGroup.fAttributeWC
243: .allowNamespace(attrDecl.fTargetNamespace)) {
244: errorArgs = new Object[] {
245: typeName,
246: attrDecl.fName,
247: attrDecl.fTargetNamespace == null ? ""
248: : attrDecl.fTargetNamespace,
249: "derivation-ok-restriction.2.2.b" };
250: return errorArgs;
251: }
252: }
253: }
254:
255: //
256: // Check that any REQUIRED attributes in the base have matching attributes
257: // in this group
258: // derivation-ok-restriction. Constraint 3
259: //
260: for (int i = 0; i < baseGroup.fAttrUseNum; i++) {
261:
262: baseAttrUse = baseGroup.fAttributeUses[i];
263:
264: if (baseAttrUse.fUse == SchemaSymbols.USE_REQUIRED) {
265:
266: baseAttrDecl = baseAttrUse.fAttrDecl;
267: // Look for a match in this group
268: if (getAttributeUse(baseAttrDecl.fTargetNamespace,
269: baseAttrDecl.fName) == null) {
270: errorArgs = new Object[] { typeName,
271: baseAttrUse.fAttrDecl.fName,
272: "derivation-ok-restriction.3" };
273: return errorArgs;
274: }
275: }
276: }
277:
278: // Now, check wildcards
279: //
280: // derivation-ok-restriction. Constraint 4
281: //
282: if (fAttributeWC != null) {
283: if (baseGroup.fAttributeWC == null) {
284: errorArgs = new Object[] { typeName,
285: "derivation-ok-restriction.4.1" };
286: return errorArgs;
287: }
288: if (!fAttributeWC.isSubsetOf(baseGroup.fAttributeWC)) {
289: errorArgs = new Object[] { typeName,
290: "derivation-ok-restriction.4.2" };
291: return errorArgs;
292: }
293: if (fAttributeWC
294: .weakerProcessContents(baseGroup.fAttributeWC)) {
295: errorArgs = new Object[] {
296: typeName,
297: fAttributeWC.getProcessContentsAsString(),
298: baseGroup.fAttributeWC
299: .getProcessContentsAsString(),
300: "derivation-ok-restriction.4.3" };
301: return errorArgs;
302: }
303: }
304:
305: return null;
306:
307: }
308:
309: static final XSAttributeUseImpl[] resize(
310: XSAttributeUseImpl[] oldArray, int newSize) {
311: XSAttributeUseImpl[] newArray = new XSAttributeUseImpl[newSize];
312: System.arraycopy(oldArray, 0, newArray, 0, Math.min(
313: oldArray.length, newSize));
314: return newArray;
315: }
316:
317: // reset the attribute group declaration
318: public void reset() {
319: fName = null;
320: fTargetNamespace = null;
321: // reset attribute uses
322: for (int i = 0; i < fAttrUseNum; i++) {
323: fAttributeUses[i] = null;
324: }
325: fAttrUseNum = 0;
326: fAttributeWC = null;
327: fAnnotations = null;
328: fIDAttrName = null;
329:
330: }
331:
332: /**
333: * Get the type of the object, i.e ELEMENT_DECLARATION.
334: */
335: public short getType() {
336: return XSConstants.ATTRIBUTE_GROUP;
337: }
338:
339: /**
340: * The <code>name</code> of this <code>XSObject</code> depending on the
341: * <code>XSObject</code> type.
342: */
343: public String getName() {
344: return fName;
345: }
346:
347: /**
348: * The namespace URI of this node, or <code>null</code> if it is
349: * unspecified. defines how a namespace URI is attached to schema
350: * components.
351: */
352: public String getNamespace() {
353: return fTargetNamespace;
354: }
355:
356: /**
357: * {attribute uses} A set of attribute uses.
358: */
359: public XSObjectList getAttributeUses() {
360: if (fAttrUses == null) {
361: fAttrUses = new XSObjectListImpl(fAttributeUses,
362: fAttrUseNum);
363: }
364: return fAttrUses;
365: }
366:
367: /**
368: * {attribute wildcard} Optional. A wildcard.
369: */
370: public XSWildcard getAttributeWildcard() {
371: return fAttributeWC;
372: }
373:
374: /**
375: * Optional. Annotation.
376: */
377: public XSAnnotation getAnnotation() {
378: return (fAnnotations != null) ? (XSAnnotation) fAnnotations
379: .item(0) : null;
380: }
381:
382: /**
383: * Optional. Annotations.
384: */
385: public XSObjectList getAnnotations() {
386: return (fAnnotations != null) ? fAnnotations
387: : XSObjectListImpl.EMPTY_LIST;
388: }
389:
390: /**
391: * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
392: */
393: public XSNamespaceItem getNamespaceItem() {
394: //REVISIT: implement
395: return null;
396: }
397:
398: } // class XSAttributeGroupDecl
|