blob: 8e907051eeec5bb300d2e6323ee27c4d0a81042d [file] [log] [blame]
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xerces.internal.impl.xs;
import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
import com.sun.org.apache.xerces.internal.xs.XSConstants;
import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
import com.sun.org.apache.xerces.internal.xs.XSObjectList;
import com.sun.org.apache.xerces.internal.xs.XSWildcard;
/**
* The XML representation for an attribute group declaration
* schema component is a global <attributeGroup> element information item
*
* @xerces.internal
*
* @author Sandy Gao, IBM
* @author Rahul Srivastava, Sun Microsystems Inc.
*
* @version $Id: XSAttributeGroupDecl.java,v 1.7 2010-11-01 04:39:55 joehw Exp $
*/
public class XSAttributeGroupDecl implements XSAttributeGroupDefinition {
// name of the attribute group
public String fName = null;
// target namespace of the attribute group
public String fTargetNamespace = null;
// number of attribute uses included by this attribute group
int fAttrUseNum = 0;
// attribute uses included by this attribute group
private static final int INITIAL_SIZE = 5;
XSAttributeUseImpl[] fAttributeUses = new XSAttributeUseImpl[INITIAL_SIZE];
// attribute wildcard included by this attribute group
public XSWildcardDecl fAttributeWC = null;
// whether there is an attribute use whose type is or is derived from ID.
public String fIDAttrName = null;
// optional annotation
public XSObjectList fAnnotations;
protected XSObjectListImpl fAttrUses = null;
// The namespace schema information item corresponding to the target namespace
// of the attribute group definition, if it is globally declared; or null otherwise.
private XSNamespaceItem fNamespaceItem = null;
// add an attribute use
// if the type is derived from ID, but there is already another attribute
// use of type ID, then return the name of the other attribute use;
// otherwise, return null
public String addAttributeUse(XSAttributeUseImpl attrUse) {
// if this attribute use is prohibited, then don't check whether it's
// of type ID
if (attrUse.fUse != SchemaSymbols.USE_PROHIBITED) {
if (attrUse.fAttrDecl.fType.isIDType()) {
// if there is already an attribute use of type ID,
// return its name (and don't add it to the list, to avoid
// interruption to instance validation.
if (fIDAttrName == null)
fIDAttrName = attrUse.fAttrDecl.fName;
else
return fIDAttrName;
}
}
if (fAttrUseNum == fAttributeUses.length) {
fAttributeUses = resize(fAttributeUses, fAttrUseNum*2);
}
fAttributeUses[fAttrUseNum++] = attrUse;
return null;
}
public void replaceAttributeUse(XSAttributeUse oldUse, XSAttributeUseImpl newUse) {
for (int i=0; i<fAttrUseNum; i++) {
if (fAttributeUses[i] == oldUse) {
fAttributeUses[i] = newUse;
}
}
}
public XSAttributeUse getAttributeUse(String namespace, String name) {
for (int i=0; i<fAttrUseNum; i++) {
if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
(fAttributeUses[i].fAttrDecl.fName == name) )
return fAttributeUses[i];
}
return null;
}
public XSAttributeUse getAttributeUseNoProhibited(String namespace, String name) {
for (int i=0; i<fAttrUseNum; i++) {
if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
(fAttributeUses[i].fAttrDecl.fName == name) &&
(fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED))
return fAttributeUses[i];
}
return null;
}
public void removeProhibitedAttrs() {
if (fAttrUseNum == 0) return;
// Remove all prohibited attributes.
int count = 0;
XSAttributeUseImpl[] uses = new XSAttributeUseImpl[fAttrUseNum];
for (int i = 0; i < fAttrUseNum; i++) {
if (fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED) {
uses[count++] = fAttributeUses[i];
}
}
fAttributeUses = uses;
fAttrUseNum = count;
// Do not remove attributes that have the same name as the prohibited
// ones, because they are specified at the same level. Prohibited
// attributes are only to remove attributes from the base type in a
// restriction.
// int newCount = 0;
// if (pCount > 0) {
// OUTER: for (int i = 0; i < fAttrUseNum; i++) {
// if (fAttributeUses[i].fUse == SchemaSymbols.USE_PROHIBITED)
// continue;
// for (int j = 1; j <= pCount; j++) {
// if (fAttributeUses[i].fAttrDecl.fName == pUses[fAttrUseNum-pCount].fAttrDecl.fName &&
// fAttributeUses[i].fAttrDecl.fTargetNamespace == pUses[fAttrUseNum-pCount].fAttrDecl.fTargetNamespace) {
// continue OUTER;
// }
// }
// pUses[newCount++] = fAttributeUses[i];
// }
// fAttributeUses = pUses;
// fAttrUseNum = newCount;
// }
}
/**
* Check that the attributes in this group validly restrict those from a base group.
* If an error is found, an Object[] is returned. This contains the arguments for the error message
* describing the error. The last element in the array (at index arr.length - 1) is the the error code.
* Returns null if there is no error.
*
* REVISIT: is there a better way of returning the appropriate information for the error?
*
* @param typeName the name of the type containing this attribute group, used for error reporting purposes
* @param baseGroup the XSAttributeGroupDecl that is the base we are checking against
*/
public Object[] validRestrictionOf(String typeName, XSAttributeGroupDecl baseGroup) {
Object[] errorArgs = null;
XSAttributeUseImpl attrUse = null;
XSAttributeDecl attrDecl = null;
XSAttributeUseImpl baseAttrUse = null;
XSAttributeDecl baseAttrDecl = null;
for (int i=0; i<fAttrUseNum; i++) {
attrUse = fAttributeUses[i];
attrDecl = attrUse.fAttrDecl;
// Look for a match in the base
baseAttrUse = (XSAttributeUseImpl)baseGroup.getAttributeUse(attrDecl.fTargetNamespace,attrDecl.fName);
if (baseAttrUse != null) {
//
// derivation-ok-restriction. Constraint 2.1.1
//
if (baseAttrUse.getRequired() && !attrUse.getRequired()) {
errorArgs = new Object[]{typeName, attrDecl.fName,
attrUse.fUse == SchemaSymbols.USE_OPTIONAL ? SchemaSymbols.ATTVAL_OPTIONAL : SchemaSymbols.ATTVAL_PROHIBITED,
"derivation-ok-restriction.2.1.1"};
return errorArgs;
}
// if this attribute is prohibited in the derived type, don't
// need to check any of the following constraints.
if (attrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
continue;
}
baseAttrDecl = baseAttrUse.fAttrDecl;
//
// derivation-ok-restriction. Constraint 2.1.1
//
if (! XSConstraints.checkSimpleDerivationOk(attrDecl.fType,
baseAttrDecl.fType,
baseAttrDecl.fType.getFinal()) ) {
errorArgs = new Object[]{typeName, attrDecl.fName, attrDecl.fType.getName(),
baseAttrDecl.fType.getName(), "derivation-ok-restriction.2.1.2"};
return errorArgs;
}
//
// derivation-ok-restriction. Constraint 2.1.3
//
int baseConsType=baseAttrUse.fConstraintType!=XSConstants.VC_NONE?
baseAttrUse.fConstraintType:baseAttrDecl.getConstraintType();
int thisConstType = attrUse.fConstraintType!=XSConstants.VC_NONE?
attrUse.fConstraintType:attrDecl.getConstraintType();
if (baseConsType == XSConstants.VC_FIXED) {
if (thisConstType != XSConstants.VC_FIXED) {
errorArgs = new Object[]{typeName, attrDecl.fName,
"derivation-ok-restriction.2.1.3.a"};
return errorArgs;
} else {
// check the values are the same.
ValidatedInfo baseFixedValue=(baseAttrUse.fDefault!=null ?
baseAttrUse.fDefault: baseAttrDecl.fDefault);
ValidatedInfo thisFixedValue=(attrUse.fDefault!=null ?
attrUse.fDefault: attrDecl.fDefault);
if (!baseFixedValue.actualValue.equals(thisFixedValue.actualValue)) {
errorArgs = new Object[]{typeName, attrDecl.fName, thisFixedValue.stringValue(),
baseFixedValue.stringValue(), "derivation-ok-restriction.2.1.3.b"};
return errorArgs;
}
}
}
} else {
// No matching attribute in base - there should be a matching wildcard
//
// derivation-ok-restriction. Constraint 2.2
//
if (baseGroup.fAttributeWC == null) {
errorArgs = new Object[]{typeName, attrDecl.fName,
"derivation-ok-restriction.2.2.a"};
return errorArgs;
}
else if (!baseGroup.fAttributeWC.allowNamespace(attrDecl.fTargetNamespace)) {
errorArgs = new Object[]{typeName, attrDecl.fName,
attrDecl.fTargetNamespace==null?"":attrDecl.fTargetNamespace,
"derivation-ok-restriction.2.2.b"};
return errorArgs;
}
}
}
//
// Check that any REQUIRED attributes in the base have matching attributes
// in this group
// derivation-ok-restriction. Constraint 3
//
for (int i=0; i<baseGroup.fAttrUseNum; i++) {
baseAttrUse = baseGroup.fAttributeUses[i];
if (baseAttrUse.fUse == SchemaSymbols.USE_REQUIRED) {
baseAttrDecl = baseAttrUse.fAttrDecl;
// Look for a match in this group
if (getAttributeUse(baseAttrDecl.fTargetNamespace,baseAttrDecl.fName) == null) {
errorArgs = new Object[]{typeName, baseAttrUse.fAttrDecl.fName,
"derivation-ok-restriction.3"};
return errorArgs;
}
}
}
// Now, check wildcards
//
// derivation-ok-restriction. Constraint 4
//
if (fAttributeWC != null) {
if (baseGroup.fAttributeWC == null) {
errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.1"};
return errorArgs;
}
if (! fAttributeWC.isSubsetOf(baseGroup.fAttributeWC)) {
errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.2"};
return errorArgs;
}
if (fAttributeWC.weakerProcessContents(baseGroup.fAttributeWC)) {
errorArgs = new Object[]{typeName,
fAttributeWC.getProcessContentsAsString(),
baseGroup.fAttributeWC.getProcessContentsAsString(),
"derivation-ok-restriction.4.3"};
return errorArgs;
}
}
return null;
}
static final XSAttributeUseImpl[] resize(XSAttributeUseImpl[] oldArray, int newSize) {
XSAttributeUseImpl[] newArray = new XSAttributeUseImpl[newSize];
System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
return newArray;
}
// reset the attribute group declaration
public void reset(){
fName = null;
fTargetNamespace = null;
// reset attribute uses
for (int i=0;i<fAttrUseNum;i++) {
fAttributeUses[i] = null;
}
fAttrUseNum = 0;
fAttributeWC = null;
fAnnotations = null;
fIDAttrName = null;
}
/**
* Get the type of the object, i.e ELEMENT_DECLARATION.
*/
public short getType() {
return XSConstants.ATTRIBUTE_GROUP;
}
/**
* The <code>name</code> of this <code>XSObject</code> depending on the
* <code>XSObject</code> type.
*/
public String getName() {
return fName;
}
/**
* The namespace URI of this node, or <code>null</code> if it is
* unspecified. defines how a namespace URI is attached to schema
* components.
*/
public String getNamespace() {
return fTargetNamespace;
}
/**
* {attribute uses} A set of attribute uses.
*/
public XSObjectList getAttributeUses() {
if (fAttrUses == null){
fAttrUses = new XSObjectListImpl(fAttributeUses, fAttrUseNum);
}
return fAttrUses;
}
/**
* {attribute wildcard} Optional. A wildcard.
*/
public XSWildcard getAttributeWildcard() {
return fAttributeWC;
}
/**
* Optional. Annotation.
*/
public XSAnnotation getAnnotation() {
return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
}
/**
* Optional. Annotations.
*/
public XSObjectList getAnnotations() {
return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
}
/**
* @see org.apache.xerces.xs.XSObject#getNamespaceItem()
*/
public XSNamespaceItem getNamespaceItem() {
return fNamespaceItem;
}
void setNamespaceItem(XSNamespaceItem namespaceItem) {
fNamespaceItem = namespaceItem;
}
} // class XSAttributeGroupDecl