/**
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of Intalio, Inc. For written permission,
* please contact info@exolab.org.
*
* 4. Products derived from this Software may not be called "Exolab"
* nor may "Exolab" appear in their names without prior written
* permission of Intalio, Inc. Exolab is a registered
* trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
* (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved.
*
* $Id$
*/
package org.exolab.castor.xml.schema;
import org.exolab.castor.xml.ValidationException;
/**
* An XML Schema Attribute Definition
* @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
* @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $
**/
public final class AttributeDecl extends Annotated {
/** SerialVersionUID */
private static final long serialVersionUID = -8720345516857919305L;
/**
* The use attribute value for optional
**/
public static final String USE_OPTIONAL = "optional";
/**
* The use attribute value for prohibited
**/
public static final String USE_PROHIBITED = "prohibited";
/**
* The use attribute value for required
**/
public static final String USE_REQUIRED = "required";
private static final short OPTIONAL = 3;
private static final short PROHIBITED = 4;
private static final short REQUIRED = 5;
/**
* Error message for a null argument
**/
private static String NULL_ARGUMENT
= "A null argument was passed to the constructor of " +
AttributeDecl.class.getName();
/**
* The default namespace form for this AttributeDecl (optional).
**/
private Form _form = null;
/**
* The id for this AttributeDecl
**/
private String _id = null;
/**
* The name of attributes defined by this AttributeDecl
**/
private String _name = null;
/**
* The parent for this AttributeDecl
**/
private Structure _parent = null;
/**
* The Schema to which this AttributeDecl belongs
**/
private Schema _schema = null;
/**
* The simple type for this AttributeDecl.
**/
private SimpleType _simpleType = null;
/**
* The current value of the 'use' property. The value
* is OPTIONAL by default.
**/
private short _useFlag = OPTIONAL;
/**
* The fixed value for attribute instances of this
* attribute declaration.
**/
private String _fixed = null;
/**
* The default value for attribute instances of this attribute declaration.
*/
private String _default = null;
/**
* A reference to a top-level attribute
*/
private String _attributeRef = null;
/**
* Creates a new AttrDecl with the given name
* @param name of the Attribute defined by this attribute declaration
* @param schema the schema that contains the new attrDecl
**/
public AttributeDecl(Schema schema, String name) {
if (schema == null) {
String err = NULL_ARGUMENT + "; 'schema' must not be null.";
throw new IllegalArgumentException(err);
}
_schema = schema;
setName(name);
} //-- AttributeDecl
/**
* Creates a new AttrDecl in the given schema.
* @param schema the schema that contains the new attrDecl
**/
public AttributeDecl(Schema schema) {
if (schema == null) {
String err = NULL_ARGUMENT + "; 'schema' must not be null.";
throw new IllegalArgumentException(err);
}
_schema = schema;
} //-- AttributeDecl
/**
* Returns the Form for this attribute declaration. The Form object species
* whether or not names are qualified or unqualified for instances of
* this attribute declaration. If null, the Form should be obtained from the
* parent Schema.
*
* @return the Form for this attribute declaration, or null if not set.
**/
public Form getForm() {
return _form;
} //-- getForm
/**
* Returns the Id for this attribute declaration
*
* @return the Id for this attribute declaration
**/
public String getId() {
return _id;
} //-- getId
/**
* Returns the name of attributes defined by this AttributeDecl.
* If this AttributeDecl is a reference to another AttributeDecl,
* the reference will be resolved and the name of the referenced
* AttributeDecl will be returned. The name will always be
* an NCName, no namespace prefix will be included.
*
* @return the name of attributes defined by this AttributeDecl.
**/
public String getName() {
return getName(false);
} //-- getName
/**
* Returns the name of this Attribute declaration. The name will
* always be an NCName, no namespace prefix will be included.
*
* @param ignoreRef a boolean that when false, indicates
* that if this is an attribute reference to return the
* reference name. Otherwise the only the local name is used.
*
* @return the name of this attribute declaration
**/
public String getName(boolean ignoreRef) {
if (isReference() && ignoreRef == false) {
//-- strip prefix we can only return
//-- an NCName from this method
String ncname = _attributeRef;
//-- check for namespace prefix
int idx = ncname.indexOf(':');
if (idx > 0) {
ncname = ncname.substring(idx+1);
}
return ncname;
}
return _name;
} //-- getName
/**
* Returns the parent of this AttributeDecl, this value may be null if
* no parent has been set.
*
* @return the parent Structure of this AttributeDecl.
**/
public Structure getParent() {
return _parent;
} //-- getParent
/**
* Returns the data type associated with this AttributeDecl.
*
* @return the data type associated with this AttributeDecl.
**/
public SimpleType getSimpleType() {
SimpleType result = null;
if (isReference()) {
AttributeDecl attribute = getReference();
if (attribute != null)
result = attribute.getSimpleType();
else
return null;
}
if (_simpleType == null)
return null;
result = (SimpleType)_simpleType.getType();
if (result != null) {
Schema tempSchema = result.getSchema().getMasterSchema();
if (tempSchema != null) {
SimpleType tempType = tempSchema.getSimpleType(result.getName());
if (tempType != null) {
result = tempType;
}
}
}
return result;
} //-- getSimpleType
/**
* Returns the AttributeDecl that this attribute definition references.
* This will return null if this attribute definition does not reference
* a different attribute definition.
* @return the AttributeDecl that this attribute definition references
**/
public AttributeDecl getReference() {
AttributeDecl result = null;
if (_attributeRef != null) {
result = _schema.getAttribute(_attributeRef);
if (result == null) {
String err = "Unable to find attribute referenced :\" ";
err += _attributeRef;
err +="\"";
throw new IllegalStateException(err);
}
}
return result;
} //-- getReference
/**
* Returns the actual reference name of this AttributeDecl, or null
* if this AttributeDecl is not a reference. The name returned, if not
* null, will be a QName, possibly containing the namespace prefix.
*
* @return the reference name
*/
public String getReferenceName() {
return _attributeRef;
} //-- getReference
/**
* Returns the Schema that this AttributeGroupDecl belongs to.
*
* @return the Schema that this AttributeGroupDecl belongs to.
**/
public Schema getSchema() {
return _schema;
} //-- getSchema
/**
* Returns the value of the use attribute for this attribute
* declaration or attribute reference. If this is a reference
* the value of the use attribute will *not* be obtained
* from the referenced attribute declaration as top-level
* attributes do not take into account the use attribute.
*
* @return the value of the use attribute for this attribute
* declaration
*/
public String getUse() {
//-- Note: Do not resolve reference, since top-level
//-- atts do not specify the "use" attribute.
switch (_useFlag) {
case PROHIBITED:
return USE_PROHIBITED;
case REQUIRED:
return USE_REQUIRED;
default:
return USE_OPTIONAL;
}
} //-- getUse
/**
* Returns the default value of this element definition.
*
* @return the default value of this element definition,
* or null if no default was specified.
**/
public String getDefaultValue() {
return _default;
} //-- getDefaultValue
/**
* Returns the fixed value of this element definition.
*
* @return the fixed value of this element definition,
* or null if no default was specified.
*/
public String getFixedValue() {
return _fixed;
} //-- getFixedValue
/**
* Returns true if the "default" flag is set.
*
* @return true if the "default" flag is set.
*/
public boolean isDefault() {
return (_default != null) && (_default.length() > 0);
} //-- isFixed
/**
* Returns true if the use attribute is equal to "optional".
*
* @return true if the use attribute is equal to "optional".
**/
public boolean isFixed() {
return (_fixed != null) && (_fixed.length() >0);
} //-- isFixed
/**
* Returns true if the use attribute is equal to "optional".
*
* @return true if the use attribute is equal to "optional".
**/
public boolean isOptional() {
String use = getUse();
return use.equals(USE_OPTIONAL);
} //-- isOptional
/**
* Returns true if the use attribute is equal to "prohibited".
*
* @return true if the use attribute is equal to "prohibited".
**/
public boolean isProhibited() {
String use = getUse();
return use.equals(USE_PROHIBITED);
} //-- isProhibited
/**
* Returns true if the 'use' attribute is equal to REQUIRED and
* there is no specified value. If a value is specifed and the
* 'use' attribute is "required" then required is will return
* false, because the attribute value automatically becomes
* fixed.
*
* @return true if the use attribute is equal to "required" and
* no default value has been specified, otherwise false
**/
public boolean isRequired() {
String use = getUse();
return (use.equals(USE_REQUIRED));
} //-- getRequired
/**
* Returns true if this attribute definition simply references another
* attribute Definition
* @return true if this attribute definition is a reference
*/
public boolean isReference() {
return (_attributeRef != null);
} //-- isReference
/**
* Sets the Form for this attribute declaration. The Form object species
* whether or not names are qualified or unqualified for instances of
* this attribute declaration. If null, the Form is to be obtained from
* the parent Schema.
*
* @param form the Form type for this attribute declaration.
**/
public void setForm(Form form) {
_form = form;
} //-- setForm
/**
* Sets the Id for this attribute declaration
*
* @param id the Id for this attribute declaration
**/
public void setId(String id) {
_id = id;
} //-- setId
/**
* Sets the name of attributes defined by this attribute definition
* @param name the name of the this AttributeDecl. Must be a valid NCName.
* @exception IllegalArgumentException when the name is not valid
**/
public void setName(String name) {
if (name == null) {
String err = "AttributeDecl#setName: 'name' must not be null.";
throw new IllegalArgumentException(err);
}
//-- handle namespace if necessary
int idx = name.indexOf(':');
if (idx >= 0) {
//-- we should resolve nsPrefix...just ignore for now
//-- use local name
name = name.substring(idx + 1);
}
if (name.length() == 0) {
String err = "AttributeDecl#setName: 'name' must not be "+
"zero-length.";
throw new IllegalArgumentException(err);
}
_name = name;
} //-- setName
/**
* Sets the parent for this AttributeDecl
*
* @param parent the parent Structure for this AttributeDecl
**/
protected void setParent(Structure parent) {
if (parent != null) {
switch (parent.getStructureType()) {
case Structure.ATTRIBUTE_GROUP:
case Structure.COMPLEX_TYPE:
case Structure.SCHEMA:
break;
default:
String error = "Invalid parent for group";
throw new IllegalArgumentException(error);
}
}
_parent = parent;
} //-- setParent
/**
* Sets the reference for this attribute definition
* @param reference the Attribute definition that this definition references
**/
public void setReference(AttributeDecl reference) {
if (reference == null)
this._attributeRef = null;
else
this._attributeRef = reference.getName();
} //-- setReference
/**
* Sets the reference for this attribute definition
* @param reference the name of the attribute definition that this
* definition references
**/
public void setReference(String reference) {
this._attributeRef = reference;
} //-- setReference
/**
* Sets the SimpleType for this attribute declaration
* @param simpleType the SimpleType for this attribute
* declaration
**/
public void setSimpleType(SimpleType simpleType) {
_simpleType = simpleType;
if (simpleType != null) {
simpleType.setParent(this);
}
} //-- setSimpleType
/**
* Sets the simple type of this attribute to be a reference.
*
* @param name the name of the simpleType being referenced, must
* not be null.
**/
public void setSimpleTypeReference(String name) {
SimpleTypeReference reference
= new SimpleTypeReference(_schema, name);
setSimpleType(reference);
} //-- setSimpleTypeReference
/**
* Sets the 'use' attribute of this attribute declaration
* Note: this should not be used to set the flag to FIXED or DEFAULT
* @param value one of the following:
* ("prohibited" | "optional" | "required")
*
* @see #USE_PROHIBITED
* @see #USE_OPTIONAL
* @see #USE_REQUIRED
**/
public void setUse(String value) {
if (value == null) {
_useFlag = OPTIONAL;
return;
}
if (value.equals(USE_REQUIRED))
_useFlag = REQUIRED;
else if (value.equals(USE_OPTIONAL))
_useFlag = OPTIONAL;
else if (value.equals(USE_PROHIBITED))
_useFlag = PROHIBITED;
else {
throw new IllegalArgumentException("Invalid value for 'use': " +
value);
}
} //-- setUse
/**
* Sets the DEFAULT value
*/
public void setDefaultValue(String value) {
if ((_fixed != null) && (_fixed.length() > 0)) {
throw new IllegalStateException("'default' and 'fixed' must not be both present.");
}
_default = value;
}
/**
* Sets the FIXED value.
*/
public void setFixedValue(String value) {
if ((_default != null) && (_default.length() > 0)) {
throw new IllegalStateException("'default' and 'fixed' must not be both present.");
}
_fixed = value;
}
//-------------------------------/
//- Implementation of Structure -/
//-------------------------------/
/**
* Returns the type of this Schema Structure
* @return the type of this Schema Structure
**/
public short getStructureType() {
return Structure.ATTRIBUTE;
} //-- getStructureType
/**
* Checks the validity of this Attribute declaration
* @exception ValidationException when this Attribute declaration
* is invalid
**/
public void validate()
throws ValidationException
{
if ((_attributeRef == null) && (_name == null)) {
String err = "<attribute> is missing required 'name' attribute.";
throw new ValidationException(err);
}
if (_attributeRef != null) {
if (_schema.getAttribute(_attributeRef) == null) {
String err = "<attribute ref=\"" + _attributeRef + "\"> "+
"is not resolvable.";
throw new ValidationException(err);
}
return;
}
} //-- validate
/**
* Set the parent schema of the current ElementDecl.
* The parent schema should at least have the same targetNamespace
* of the current schema.
*
* This method is protected since it is only meant to be used by the internal
* API to propagate the parent XML Schema in case of a redefinition for instance.
* @param schema
*/
protected void setSchema(Schema schema) {
_schema = schema;
}
/**
* Indicates whether a type is set for this element definiion.
* @return True if a type is set.
*/
public boolean hasXMLType() {
return (_simpleType != null);
}
} //-- AttrDecl