/** * 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 2004 (C) Intalio Inc. All Rights Reserved. * * $Id$ */ package org.exolab.castor.xml.schema; import java.util.Collection; import java.util.Collections; import java.util.Hashtable; import java.util.Map; import org.exolab.castor.xml.ValidationException; /** * <p>This class is a wrapper used to save meta information concerning redefined * structures from an XML schema.</p> * * <p>This wrapper is identified by: * <ul> * <li>a reference to the schema redefined</li> * <li>the schema location of the redefined schema</li> * <li>A vector containing the names of the structures redefined</li> * </ul> * * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a> * @version $Revision$ $Date: 2006-04-13 06:47:36 -0600 (Thu, 13 Apr 2006) $ **/ public class RedefineSchema extends Annotated { /** SerialVersionUID */ private static final long serialVersionUID = -7095458840388436859L; /** * The original schema that is imported in the * parent schema */ private Schema _originalSchema; /** * The parent schema in which this redefined XML Schema * is used. */ private Schema _parentSchema; /** * The schema location of the redefined schema */ private String _schemaLocation = null; /** * A vector with the names of the redefined complexTypes */ private Map<String, ComplexType> _complexTypes; /** * A vector with the names of the redefined simpleTypes */ private Map<String, SimpleType> _simpleTypes; /** * A vector with the names of the redefined groups */ private Map<String, ModelGroup> _groups; /** * A vector with the names of the redefined attributeGroups */ private Map<String, AttributeGroup> _attributeGroups; /** * Default constructor to create a RedefineSchema * that contains only Annotations * */ public RedefineSchema(Schema parentSchema) { super(); _parentSchema = parentSchema; _schemaLocation = ""; } /** * Constructs a new RedefineSchema structure */ public RedefineSchema(Schema parentSchema, Schema originalSchema) { super(); _schemaLocation = originalSchema.getSchemaLocation(); _parentSchema = parentSchema; _originalSchema= originalSchema; _complexTypes = new Hashtable<String, ComplexType>(); _simpleTypes = new Hashtable<String, SimpleType>(); _attributeGroups = new Hashtable<String, AttributeGroup>(); _groups = new Hashtable<String, ModelGroup>(); } /** * Adds the given complexType in the list of redefined complexTypes. * @param complexType the ComplexType to add. */ public void addComplexType(ComplexType complexType) throws SchemaException { if (_schemaLocation.length() == 0) throw new IllegalStateException("A RedefineSchema with no schemaLocation must contain only annotations"); String name = complexType.getName(); if (name == null) { String err = "a global ComplexType must contain a name."; throw new SchemaException(err); } if (complexType.getSchema() != _parentSchema) { String err = "invalid attempt to add an ComplexType which "; err += "belongs to a different Schema; type name: " + name; throw new SchemaException(err); } if (getComplexType(name) != null ) { String err = "In the RedefineSchema:"+_schemaLocation+"a ComplexType already exists with the given name: "; throw new SchemaException(err + name); } //--forces the redefine character complexType.setRedefined(); _complexTypes.put(name, complexType); complexType.setParent(_parentSchema); } /** * Enumerates the complexType names. * @return an enumeration of the names of the redefined ComplexTypes */ public Collection<ComplexType> enumerateComplexTypes() { if (_schemaLocation.length() == 0) { return Collections.emptyList(); } return _complexTypes.values(); } /** * Returns the ComplexType corresponding to the given name. * * @param name the name of the ComplexType to look for. * @return the ComplexType corresponding to the gven name. */ public ComplexType getComplexType(String name) { if (_schemaLocation.length() == 0) { return null; } return _complexTypes.get(name); } /** * Returns true if this redefinition contains a redefinition for a complexType with * the given name. * * @param name the canonical name of the complexType. */ public boolean hasComplexTypeRedefinition(String name) { if (_schemaLocation.length() == 0) return false; return (_complexTypes.containsKey(name)); } /** * Removes the complexType with the given name from the redefine structure. * * @param complexType The complexType to be removed from this Redefined Structure. */ public boolean removeComplexType(ComplexType complexType) { if (_schemaLocation.length() == 0) return false; boolean result = false; if (_complexTypes.containsValue(complexType)) { _complexTypes.remove(complexType); result = true; } return result; } /** * Adds a simpleType in the list of redefined simpleTypes. * * @param simpleType the SimpleType to add. */ public void addSimpleType(SimpleType simpleType) throws SchemaException { String name = simpleType.getName(); if (name == null) throw new IllegalArgumentException("A redefined simpleType must have a name"); if (_schemaLocation.length() == 0) throw new IllegalStateException("A RedefineSchema with no schemaLocation must contain only annotations"); if (simpleType.getSchema() != _parentSchema) { String err = "invalid attempt to add a SimpleType which "; err += "belongs to a different Schema; type name: " + name; throw new SchemaException(err); } if (getSimpleType(name) != null) { String err = "In the RedefineSchema:"+_schemaLocation+"a SimpleType already exists with the given name: "; throw new SchemaException(err + name); } //--forces the redefine character simpleType.setRedefined(); simpleType.setParent(this); _simpleTypes.put(name, simpleType); } /** * Enumerates the simpleType names. * @return an enumeration of the names of the redefined SimpleTypes. */ public Collection<SimpleType> enumerateSimpleTypes() { if (_schemaLocation.length() == 0) { return Collections.emptyList(); } return _simpleTypes.values(); } /** * Returns the SimpleType corresponding to the given name. * * @param name the name of the SimpleType to look for. * @return the SimpleType corresponding to the gven name. */ public SimpleType getSimpleType(String name) { if (_schemaLocation.length() == 0) { return null; } return _simpleTypes.get(name); } /** * Returns true if this redefinition contains a redefinition for a simpleType with * the given name. * * @param name the canonical name of the simpleType. */ public boolean hasSimpleTypeRedefinition(String name) { if (_schemaLocation.length() == 0) { return false; } return (_simpleTypes.containsKey(name)); } /** * Removes the given simpleType from the redefine structure. * * @param simpleType the simpleType to be removed from this Redefined Structure. */ public boolean removeSimpleType(SimpleType simpleType) { if (_schemaLocation.length() == 0) return false; boolean result = false; if (_simpleTypes.containsValue(simpleType)) { _simpleTypes.remove(simpleType); result = true; } return result; } /** * Adds a group name in the list of redefined groups. */ public void addGroup(ModelGroup group) throws SchemaException { if (_schemaLocation.length() == 0) { throw new IllegalStateException("A RedefineSchema with no schemaLocation must contain only annotations"); } String name = group.getName(); if (name == null) { String err = "a group declaration must contain a name."; throw new SchemaException(err); } if (getModelGroup(name) != null) { String err = "In the RedefineSchema:"+ _schemaLocation+" a group declaration already exists with the given name: "; throw new SchemaException(err + name); } //--forces the redefine character group.setRedefined(); group.setParent(_parentSchema); _groups.put(name, group); } /** * Returns the Model Group of the given name that is contained in this RedefineSchema. * * @param name the name of the ModelGroup to retrieve. * @return the ModelGroup of the given name contained in this RedefineSchema. */ public ModelGroup getModelGroup(String name) { if (_schemaLocation.length() == 0) { return null; } return _groups.get(name); } /** * Enumerates the group names. * @return an enumeration of the names of the redefined groups. */ public Collection<ModelGroup> enumerateGroups() { if (_schemaLocation.length() == 0) { return Collections.emptyList(); } return _groups.values(); } /** * Returns true if this redefinition contains a redefinition for a group with * the given name. * * @param name the canonical name of the complexType. */ public boolean hasGroupRedefinition(String name) { if (_schemaLocation.length() == 0) return false; return (_groups.containsKey(name)); } /** * Removes the given ModelGroup from the redefine structure. * * @param group the ModelGroup to be removed from this Redefined Structure. */ public boolean removeGroup(ModelGroup group) { if (_schemaLocation.length() == 0) return false; boolean result = false; if (_groups.containsValue(group)) { _groups.remove(group); result = true; } return result; } /** * Adds a AttributeGroup name in the list of redefined attributeGroups. */ public void addAttributeGroup(AttributeGroupDecl attrGroup) throws SchemaException { if (_schemaLocation.length() == 0) throw new IllegalStateException("A RedefineSchema with no schemaLocation must contain only annotations"); if (attrGroup == null) return; String name = attrGroup.getName(); //-- handle namespace prefix, if necessary int idx = name.indexOf(':'); if (idx >= 0) { String nsPrefix = name.substring(0,idx); name = name.substring(idx + 1); String ns = _parentSchema.getNamespace(nsPrefix); if (ns == null) { String err = "addAttributeGroup: "; err += "Namespace prefix not recognized '"+nsPrefix+"'"; throw new IllegalArgumentException(err); } if (!ns.equals(_parentSchema.getTargetNamespace())) { String err = "AttributeGroup has different namespace " + "than this Schema definition."; throw new IllegalArgumentException(err); } } if (attrGroup.getSchema() != _parentSchema) { String err = "invalid attempt to add an AttributeGroup which "; err += "belongs to a different Schema; " + name; throw new SchemaException(err); } attrGroup.setRedefined(); _attributeGroups.put(name, attrGroup); } /** * Returns the AttributeGroup corresponding to the given * canonical name (unqualified name). * * @return the AttributeGroup corresponding to the given * canonical name (unqualified name). */ public AttributeGroupDecl getAttributeGroup(String name) { if (_schemaLocation.length() == 0) return null; return (AttributeGroupDecl)_attributeGroups.get(name); } /** * Enumerates the attributeGroup names. * @return an enumeration of the names of the redefined AttributeGroups. */ public Collection<AttributeGroup> enumerateAttributeGroups() { if (_schemaLocation.length() == 0) { return Collections.emptyList(); } return _attributeGroups.values(); } /** * Returns true if this redefinition contains a redefinition for an AttributeGroup with * the given name. * * @param name the canonical name of the complexType. */ public boolean hasAttributeGroupRedefinition(String name) { if (_schemaLocation.length() == 0) return false; return (_attributeGroups.containsKey(name)); } /** * Removes the attributeGroup with the given name from the redefine structure. * * @param attrGroup the attributeGroup to be removed from this Redefined Structure. */ public boolean removeAttributeGroup(AttributeGroupDecl attrGroup) { if (_schemaLocation.length() == 0) return false; boolean result = false; if (_attributeGroups.containsValue(attrGroup)) { _attributeGroups.remove(attrGroup); result = true; } return result; } /** * Returns true if at least one structure other than * an annotation is present. * * @return true if at least one structure other than * an annotation is present. */ public boolean hasRedefinition() { if (_schemaLocation.length() == 0) return false; return (!_complexTypes.isEmpty()) || (!_simpleTypes.isEmpty()) || (!_groups.isEmpty()) || (!_attributeGroups.isEmpty()); } /** * Returns the URI of the imported schema. * * @return the URI of the imported schema. */ public String getSchemaLocation() { return _schemaLocation; } /** * Returns the schema imported used for the redefinitions. * @return the original schema imported. */ public Schema getOriginalSchema() { return _originalSchema; } /** * Returns the parent schema in which this RedefineSchema is used. * * @return the parent schema in which this Redefined Schema * is used. */ public Schema getParentSchema(){ return _parentSchema; } /** * Returns the type of this Redefine Structure * @return the type of this Redefin Structure **/ public short getStructureType() { return Structure.REDEFINE; } //-- getStructureType public void validate() throws ValidationException { //-- no validation performed on the structure since //-- it is simply a place holder for names and not for real structures. } }