Package org.exolab.castor.xml.schema.writer

Source Code of org.exolab.castor.xml.schema.writer.SchemaWriter

/**
* 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: SchemaWriter.java 7435 2008-02-05 23:14:25Z wguttmn $
*/

package org.exolab.castor.xml.schema.writer;

import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.exolab.castor.types.AnyNode;
import org.exolab.castor.xml.Namespaces;
import org.exolab.castor.xml.Serializer;
import org.exolab.castor.xml.schema.Annotated;
import org.exolab.castor.xml.schema.Annotation;
import org.exolab.castor.xml.schema.AppInfo;
import org.exolab.castor.xml.schema.AttributeDecl;
import org.exolab.castor.xml.schema.AttributeGroup;
import org.exolab.castor.xml.schema.AttributeGroupDecl;
import org.exolab.castor.xml.schema.AttributeGroupReference;
import org.exolab.castor.xml.schema.BlockList;
import org.exolab.castor.xml.schema.ComplexType;
import org.exolab.castor.xml.schema.ContentModelGroup;
import org.exolab.castor.xml.schema.ContentType;
import org.exolab.castor.xml.schema.Documentation;
import org.exolab.castor.xml.schema.ElementDecl;
import org.exolab.castor.xml.schema.Facet;
import org.exolab.castor.xml.schema.FinalList;
import org.exolab.castor.xml.schema.Form;
import org.exolab.castor.xml.schema.Group;
import org.exolab.castor.xml.schema.IdentityConstraint;
import org.exolab.castor.xml.schema.IdentityField;
import org.exolab.castor.xml.schema.IdentitySelector;
import org.exolab.castor.xml.schema.KeyRef;
import org.exolab.castor.xml.schema.ModelGroup;
import org.exolab.castor.xml.schema.RedefineSchema;
import org.exolab.castor.xml.schema.Schema;
import org.exolab.castor.xml.schema.SchemaContext;
import org.exolab.castor.xml.schema.SchemaContextImpl;
import org.exolab.castor.xml.schema.SchemaNames;
import org.exolab.castor.xml.schema.SimpleContent;
import org.exolab.castor.xml.schema.SimpleType;
import org.exolab.castor.xml.schema.Structure;
import org.exolab.castor.xml.schema.Union;
import org.exolab.castor.xml.schema.Wildcard;
import org.exolab.castor.xml.schema.XMLType;
import org.exolab.castor.xml.schema.simpletypes.ListType;
import org.exolab.castor.xml.util.AnyNode2SAX;
import org.xml.sax.DocumentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributeListImpl;

/**
* A class for serializing Schema models.
* @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
* @version $Revision: 7435 $ $Date: 2006-04-05 13:16:42 -0600 (Wed, 05 Apr 2006) $
**/
public class SchemaWriter {

    /**
     *  The {@link Log} instance to use.
     */
    private static final Log LOG = LogFactory.getLog(SchemaWriter.class);
    //------------------------/
    //- Schema element names -/
    //------------------------/

    /**
     * Annotation element name.
     */
    private static final String ANNOTATION    =  "annotation";

    /**
     * AppInfo element name.
     */
    private static final String APPINFO       = "appinfo";
   
    /**
     * Attribute element name.
     */
    private static final String ATTRIBUTE     =  "attribute";

    /**
     * AttributeGroup element name.
     */
    private static final String ATTRIBUTE_GROUP = "attributeGroup";

    /**
     * ComplexType element name.
     */
    private static final String COMPLEX_TYPE  =  "complexType";

    /**
     * Documentation element name.
     */
    private static final String DOCUMENTATION =  "documentation";

    /**
     * Element element name.
     */
    private static final String ELEMENT       =  "element";

    /**
     * ModelGroup element name.
     */
    private static final String GROUP         =  "group";

    /**
     * Restriction element name.
     */
    private static final String RESTRICTION   =  "restriction";

    /**
     * Schema element name.
     */
    private static final String SCHEMA        =  "schema";

    /**
     * SimpleType element name
     */
    private static final String SIMPLE_TYPE   =  "simpleType";

    //-------------------/
    //- Attribute names -/
    //-------------------/

    private static final String ATTR_NAME   = "name";
    private static final String ATTR_TYPE   = "type";

    private static final String VALUE_TRUE  = "true";


    /**
     * For use with SAX AttributeList
     */
    private static final String CDATA          =  "CDATA";
    private static final String XMLNS_PREFIX   =  "xmlns:";
    private static final String XMLNS_DEFAULT  =  "xmlns";
    private static final String DEFAULT_PREFIX =  "xsd";

    /**
     * The DocumentHandler to send events to
     */
    private DocumentHandler   _handler = null;

    /**
     * The AttributeList to send events to
     */
    private AttributeListImpl _atts = new AttributeListImpl();

    /**
     * This field is no longer used and only here for
     * backward compatibility.
     * @deprecated
    **/
    public static boolean enable = false;
   
    /** Castor XML context - mother of all dwelling. */
    private SchemaContext _schemaContext = null;

    /**
     * Creates a new SchemaWriter for the given Writer.
     *
     * @param writer the Writer to serialize to
     * @throws IOException in case taht wrapping the Writer fails
    **/
    public SchemaWriter(final Writer writer)
    throws IOException {
        this();
        Serializer serializer = _schemaContext.getSerializer();

        if (serializer == null) {
            throw new IOException("Unable to obtain serailizer");
        }

        serializer.setOutputCharStream(writer);

        DocumentHandler handler = serializer.asDocumentHandler();

        if (handler == null) {
            String err = "The following serializer is not SAX capable: ";
            err += serializer.getClass().getName();
            err += "; cannot proceed.";
            throw new IOException(err);
        }

        _handler = handler;

    } //-- SchemaWriter

    /**
     * Creates a new SchemaWriter for the given DocumentHandler.
     *
     * @param handler the DocumentHandler to send events to
    **/
    public SchemaWriter(final DocumentHandler handler) {
        this();

        if (handler == null) {
            throw new IllegalArgumentException("DocumentHandler must not be null.");
        }

        _handler = handler;
    } //-- SchemaWriter

    /**
     * A constructor to create an empty uninitialized SchemaWriter via XMLContext.
     */
    public SchemaWriter() {
        super();
        _schemaContext = new SchemaContextImpl();
    }
   
    /**
     * To set the {@link SchemaContext} to be used for the {@link SchemaWriter}.
     * @param schemaContext the {@link SchemaContext} to be used
     */
    public void setSchemaContext(final SchemaContext schemaContext) {
        _schemaContext = schemaContext;
    }
   
    /**
     * To set the DocumentHandler to a Writer - which is wrapped by a serializer.
     * @param writer the Writer to use for output
     * @throws IOException in case the Writer cannot be used for DocumentHandler
     */
    public void setDocumentHandler(final Writer writer) throws IOException {
        Serializer serializer = _schemaContext.getSerializer();

        if (serializer == null) {
            String message = "Unable to obtain serailizer";
            LOG.warn(message);
            throw new IOException(message);
        }

        serializer.setOutputCharStream(writer);

        DocumentHandler handler = serializer.asDocumentHandler();

        if (handler == null) {
            String err = "The following serializer is not SAX capable: ";
            err += serializer.getClass().getName();
            err += "; cannot proceed.";
            LOG.warn(err);
            throw new IOException(err);
        }

        _handler = handler;
    }
   
    /**
     * To directly set a DocumentHandler.
     * @param documentHandler set the DocumentHandler
     */
    public void setDocumentHandler(final DocumentHandler documentHandler) {
        if (documentHandler == null) {
            String message = "DocumentHandler must not be null.";
            LOG.warn(message);
            throw new IllegalArgumentException(message);
        }
        _handler = documentHandler;
    }

    public void write(final Schema schema)
    throws SAXException {
        if (schema == null)
            throw new IllegalArgumentException("Schema must not be null.");

        processSchema(schema);

    } //-- write


    /**
     * Processes the given annotated structure into events
     *
     * @param annotated the annotated structure to process into events
    **/
    private void processAnnotated(Annotated annotated, String schemaPrefix)
        throws SAXException
    {
        Enumeration enumeration = annotated.getAnnotations();
        while (enumeration.hasMoreElements())
            processAnnotation( (Annotation) enumeration.nextElement(), schemaPrefix );

    } //-- processAnnotated

    /**
     * Processes the given annotation into events
     *
     * @param annotation the annotation to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processAnnotation(Annotation annotation, String schemaPrefix)
        throws SAXException
    {

        _atts.clear();

        String ELEM_ANNOTATION = schemaPrefix + ANNOTATION;

        _handler.startElement(ELEM_ANNOTATION, _atts);

       
        //--process appinfo elements
        Enumeration enumeration = annotation.getAppInfo();
        String ELEM_APPINFO = schemaPrefix + APPINFO;
        while (enumeration.hasMoreElements()) {
            AppInfo app = (AppInfo) enumeration.nextElement();
           
            String source = app.getSource();
            String sourceName = _atts.getName(0);
            boolean isSourceIsNull = (sourceName == null);
            boolean isSourceExists = false;
           
            if (!isSourceIsNull)
            {
                isSourceExists = sourceName.equals(SchemaNames.SOURCE_ATTR);
            }
            if (source != null && !isSourceExists)
                _atts.addAttribute(SchemaNames.SOURCE_ATTR, CDATA,source);

            _handler.startElement(ELEM_APPINFO, _atts);
            Enumeration anyNodes = app.getObjects();
            while (anyNodes.hasMoreElements()) {
                Object obj = anyNodes.nextElement();
                if (obj instanceof AnyNode) {
                    AnyNode2SAX anyNode2SAX = new AnyNode2SAX((AnyNode)obj);
                    anyNode2SAX.setDocumentHandler(_handler);
                    anyNode2SAX.start();
                }
                else {
                    char[] chars = obj.toString().toCharArray();
                    _handler.characters(chars, 0, chars.length);
                   
                }
            }
            _handler.endElement(ELEM_APPINFO);
        }
       
        //-- process documentation elements
        enumeration = annotation.getDocumentation();
        String ELEM_DOCUMENTATION = schemaPrefix + DOCUMENTATION;
        while (enumeration.hasMoreElements()) {
            _atts.clear();
            Documentation doc = (Documentation) enumeration.nextElement();
            String source = doc.getSource();
            String sourceName = _atts.getName(0);
            boolean isSourceIsNull = (sourceName == null);
            boolean isSourceExists = false;
           
            if (!isSourceIsNull)
            {
                isSourceExists = sourceName.equals(SchemaNames.SOURCE_ATTR);
            }
            if (source != null && !isSourceExists)
            {
                _atts.addAttribute(SchemaNames.SOURCE_ATTR, CDATA,source);
            }

            _handler.startElement(ELEM_DOCUMENTATION, _atts);
            Enumeration anyNodes = doc.getObjects();
            while (anyNodes.hasMoreElements()) {
                Object obj = anyNodes.nextElement();
                if (obj instanceof AnyNode) {
                    AnyNode2SAX anyNode2SAX = new AnyNode2SAX((AnyNode)obj);
                    anyNode2SAX.setDocumentHandler(_handler);
                    anyNode2SAX.start();
                }
                else {
                    char[] chars = obj.toString().toCharArray();
                    _handler.characters(chars, 0, chars.length);
                   
                }
            }
            _handler.endElement(ELEM_DOCUMENTATION);
        }
       

        _handler.endElement(ELEM_ANNOTATION);

    } //-- processAnnotations

    /**
     * Processes the given attribute declaration
     *
     * @param attribute the attribute declaration to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processAttribute(AttributeDecl attribute, String schemaPrefix)
        throws SAXException
    {
        String ELEM_ATTRIBUTE = schemaPrefix + ATTRIBUTE;

        _atts.clear();

        boolean isReference = attribute.isReference();

        //-- name
        if (!isReference) {
            _atts.addAttribute(SchemaNames.NAME_ATTR, CDATA,
                attribute.getName());
        }
        else {
            _atts.addAttribute(SchemaNames.REF_ATTR, CDATA,
                attribute.getReferenceName());
        }


        //-- type attribute
        boolean hasAnonymousType = false;
        SimpleType type = attribute.getSimpleType();
        if ((!isReference) && (type != null)) {

            if (type.getName() != null) {

                String typeName = type.getName();

                //-- add prefix if necessary
                if (typeName.indexOf(':') < 0) {
                    if (type.isBuiltInType()) {
                        typeName = schemaPrefix + typeName;  // xsd prefix
                    }
                    else {
                        // resolve prefix
                        String namespace = type.getSchema().getTargetNamespace();
                        if (namespace == null) namespace = "";
                        String prefix = getNSPrefix(attribute.getSchema(), namespace);
                        if ((prefix != null) && (prefix.length() > 0))
                            typeName = prefix + ":" + typeName;
                    }
                }
                _atts.addAttribute(ATTR_TYPE, CDATA, typeName);
            }
            else hasAnonymousType = true;
        }

        // default or fixed values?
        //-- @default
        if (attribute.isDefault()) {
            _atts.addAttribute(SchemaNames.DEFAULT_ATTR, CDATA,
                attribute.getDefaultValue());
        }
        //-- @fixed
        else if (attribute.isFixed()) {
            _atts.addAttribute(SchemaNames.FIXED_ATTR, CDATA,
                attribute.getFixedValue());
        }

        //-- @form
        if (attribute.getForm() != null) {
            _atts.addAttribute(SchemaNames.FORM, CDATA,
                attribute.getForm().toString());
        }

        //-- @id (optional)
        if (attribute.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                attribute.getId());
        }

        //-- use : required
        if (attribute.isRequired()) {
            _atts.addAttribute(SchemaNames.USE_ATTR, CDATA,
                AttributeDecl.USE_REQUIRED);
        }
        //-- use : prohibited
        else if (attribute.isProhibited()) {
            _atts.addAttribute(SchemaNames.USE_ATTR, CDATA,
                AttributeDecl.USE_PROHIBITED);
        }

        _handler.startElement(ELEM_ATTRIBUTE, _atts);

        //-- process annotations
        processAnnotated(attribute, schemaPrefix);

        //-- process anonymous type if necessary
        if (hasAnonymousType) {
            processSimpleType(type, schemaPrefix);
        }

        _handler.endElement(ELEM_ATTRIBUTE);


    } //-- processAttribute

    /**
     * Processes the given attributeGroup declaration
     *
     * @param attGroup the attributeGroup declaration to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processAttributeGroup
        (AttributeGroup attGroup, String schemaPrefix)
        throws SAXException
    {
        String ELEM_ATTRIBUTE_GROUP = schemaPrefix + ATTRIBUTE_GROUP;

        _atts.clear();

        boolean isReference = (attGroup instanceof AttributeGroupReference);

        //-- name
        if (!isReference) {
            _atts.addAttribute(SchemaNames.NAME_ATTR, CDATA,
                ((AttributeGroupDecl)attGroup).getName());
        }
        else {
            _atts.addAttribute(SchemaNames.REF_ATTR, CDATA,
                ((AttributeGroupReference)attGroup).getReference());
        }

        //-- @id (optional)
        if (attGroup.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                attGroup.getId());
        }

        _handler.startElement(ELEM_ATTRIBUTE_GROUP, _atts);

        //-- process annotations
        processAnnotated(attGroup, schemaPrefix);

        if (!isReference) {
            AttributeGroupDecl group = (AttributeGroupDecl)attGroup;
            Enumeration enumeration = group.getLocalAttributes();
            while (enumeration.hasMoreElements()) {
                processAttribute((AttributeDecl)enumeration.nextElement(),
                    schemaPrefix);
            }
            enumeration = group.getLocalAttributeGroupReferences();
            while (enumeration.hasMoreElements()) {
                processAttributeGroup((AttributeGroup)enumeration.nextElement(),
                    schemaPrefix);
            }
           
            if (group.getAnyAttribute() != null) {
                processWildcard(group.getAnyAttribute(), schemaPrefix);
            }
        }

        _handler.endElement(ELEM_ATTRIBUTE_GROUP);


    } //-- processAttributeGroup

    /**
     * Processes the given complex type definition
     *
     * @param complexType the complex type definition to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processComplexType
        (ComplexType complexType, String schemaPrefix)
        throws SAXException
    {
        String ELEMENT_NAME = schemaPrefix + COMPLEX_TYPE;

        _atts.clear();

        //-- handle top-level only attributes
        if (complexType.isTopLevel()) {

            //-- @name
            _atts.addAttribute(SchemaNames.NAME_ATTR, CDATA,
                complexType.getName());

            //-- @abstract
            if (complexType.isAbstract()) {
                _atts.addAttribute(SchemaNames.ABSTRACT, CDATA, VALUE_TRUE);
            }

            //-- @block
            if (complexType.getBlock() != null) {
                _atts.addAttribute(SchemaNames.BLOCK_ATTR, CDATA,
                    complexType.getBlock().toString());
            }

            //-- @final
            if (complexType.getFinal() != null) {
                _atts.addAttribute(SchemaNames.FINAL_ATTR, CDATA,
                    complexType.getFinal().toString());
            }
        } //-- isTopLevel

        //-- @id
        if (complexType.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                complexType.getId());
        }

        //-- @mixed
        if (complexType.getContentType() == ContentType.mixed) {
            _atts.addAttribute(SchemaNames.MIXED, CDATA, VALUE_TRUE);
        }

        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process annotations
        processAnnotated(complexType, schemaPrefix);


        //-- handle simpleContent/complexContent if we have a baseType.
        String ELEM_CONTENT    = null;
        String ELEM_DERIVATION = null;
        XMLType baseType = complexType.getBaseType();
        if (baseType != null) {
            if (complexType.isSimpleContent())
                ELEM_CONTENT = schemaPrefix + SchemaNames.SIMPLE_CONTENT;
            else
                ELEM_CONTENT = schemaPrefix + SchemaNames.COMPLEX_CONTENT;

            _atts.clear();
            if (complexType.isComplexContent()) {
                if (complexType.getContentType() == ContentType.mixed) {
                    _atts.addAttribute(SchemaNames.MIXED, CDATA,
                        VALUE_TRUE);
                }

            }
            _handler.startElement(ELEM_CONTENT, _atts);

            ELEM_DERIVATION = schemaPrefix +
                complexType.getDerivationMethod();

            String baseTypeName = baseType.getName();

            //-- add "xsd" prefix if necessary
            if (complexType.isSimpleContent()) {
                //the base type can be a complexType in extension
                if (baseType.isSimpleType()) {
                    SimpleType simpleType = (SimpleType)baseType;
                    if (baseTypeName.indexOf(':') < 0) {
                        if (simpleType.isBuiltInType()) {
                            baseTypeName = schemaPrefix + baseTypeName;
                        }
                        else {
                            String targetNamespace = simpleType.getSchema().getTargetNamespace();
                            String prefix = getNSPrefix(complexType.getSchema(), targetNamespace);
                            if ((prefix != null) && (prefix.length() > 0)) {
                                baseTypeName = prefix + ":" + baseTypeName;
                            }
                        }
                    }
                }
            }
            else if (complexType.isComplexContent()) {
                //--complexType: add 'xsd' only for anyType
                if (baseType.isAnyType()) {
                    if (baseTypeName.indexOf(':') <0 ) {
                       baseTypeName = schemaPrefix + baseTypeName;
                    }

                }
            } //--end of 'xsd' appending
            //add the targetNamespace prefix if necessary
            if (baseType.isComplexType()) {
                String targetNamespace = baseType.getSchema().getTargetNamespace();
                //-- targetNamespace is null
                if (targetNamespace == null) {
                  if (complexType.isRedefined()) {
                    targetNamespace =  complexType.getSchema().getTargetNamespace();
                  }
                }
               
                else {
                  String nsPrefix = getNSPrefix(complexType.getSchema(), targetNamespace);
                  if ((nsPrefix != null) && (nsPrefix.length() != 0))
                      baseTypeName = nsPrefix +':'+ baseTypeName;
                  targetNamespace = null;
                  nsPrefix = null;
                }

            }
            _atts.clear();
            _atts.addAttribute(SchemaNames.BASE_ATTR, CDATA, baseTypeName);
            _handler.startElement(ELEM_DERIVATION, _atts);
            //--Any Facets to process?
            //--only relevant for the simpleContent with restriction
            if (complexType.isSimpleContent() && complexType.isRestricted()) {
                if (complexType.getContentType().getType() == ContentType.SIMPLE) {
                    SimpleContent simpleContent = (SimpleContent)complexType.getContentType();
                    SimpleType simpleType = simpleContent.getSimpleType();
                    //-- process facets
                    Enumeration enumeration = simpleType.getLocalFacets();
                    while (enumeration.hasMoreElements()) {
                        Facet facet = (Facet) enumeration.nextElement();
                        _atts.clear();
                        _atts.addAttribute(SchemaNames.VALUE_ATTR, CDATA,
                                           facet.getValue());
                        String facetName = schemaPrefix + facet.getName();
                        _handler.startElement(facetName, _atts);
                        Enumeration annotations = facet.getAnnotations();
                        while (annotations.hasMoreElements()) {
                            Annotation annotation = (Annotation)annotations.nextElement();
                            processAnnotation(annotation, schemaPrefix);
                        }
                       _handler.endElement(facetName);
                    } //--facets
                    enumeration = null;
                    simpleType = null;
                }
            }//--<simpleContent><restriction>

        }

        //-- process content model group
        processContentModelGroup(complexType, schemaPrefix);

        //-- process Attributes, must appear last in a complex type
        Enumeration enumeration = complexType.getLocalAttributeDecls();
        while (enumeration.hasMoreElements()) {
            processAttribute((AttributeDecl)enumeration.nextElement(), schemaPrefix);
        }
        enumeration = complexType.getAttributeGroupReferences();
        while (enumeration.hasMoreElements()) {
            processAttributeGroup((AttributeGroup)enumeration.nextElement(), schemaPrefix);
        }

        if (baseType != null) {
            _handler.endElement(ELEM_DERIVATION);
            _handler.endElement(ELEM_CONTENT);
        }

        if (complexType.getAnyAttribute() != null) {
            processWildcard(complexType.getAnyAttribute(), schemaPrefix);
        }
       
        _handler.endElement(ELEMENT_NAME);

    } //-- processComplexType

    /**
     * Processes the given ContentModelGroup
     *
     * @param contentModel the content model group to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processContentModelGroup
        (ContentModelGroup contentModel, String schemaPrefix)
        throws SAXException
    {
        Enumeration enumeration = contentModel.enumerate();
        while (enumeration.hasMoreElements()) {
            Structure structure = (Structure) enumeration.nextElement();
            switch (structure.getStructureType()) {
                case Structure.ELEMENT:
                    processElement((ElementDecl)structure, schemaPrefix);
                    break;
                case Structure.MODELGROUP:
                case Structure.GROUP:
                    processGroup((Group)structure, schemaPrefix);
                    break;
                case Structure.WILDCARD:
                    processWildcard((Wildcard)structure, schemaPrefix);
                    break;
                default:
                    break;
            }
        }
    } //-- contentModel

    /**
     * Processes the given element declaration
     *
     * @param element the element declaration to process into events
    **/
    private void processElement(ElementDecl element, String schemaPrefix)
        throws SAXException
    {
        String ELEMENT_NAME = schemaPrefix + ELEMENT;

        _atts.clear();


        //-- name or reference
        String value = element.getName();
        if (value != null) {
            if (element.isReference()) {
                String targetNamespace = element.getReference().getSchema().getTargetNamespace();
                String nsPrefix = getNSPrefix(element.getSchema(), targetNamespace);
                if ((nsPrefix != null) && (nsPrefix.length() != 0))
                    value = nsPrefix +':'+ value;
                targetNamespace = null;
                nsPrefix = null;
                _atts.addAttribute(SchemaNames.REF_ATTR, CDATA, value);

            }
            else
                _atts.addAttribute(ATTR_NAME, CDATA, value);
        }

        //-- minOccurs/maxOccurs
        int max = element.getMaxOccurs();
        int min = element.getMinOccurs();

        if (min != 1) {
            _atts.addAttribute(SchemaNames.MIN_OCCURS_ATTR, CDATA,
                Integer.toString(min));
        }

        if (max < 0) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                "unbounded");
        }
        else if (max != 1) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                Integer.toString(max));
        }

        //-- type attribute
        boolean hasAnonymousType = false;
        if (!element.isReference()) {
            XMLType type = element.getType();

            //-- no type?
            if (type == null) {
                //-- do nothing
            }
            //-- anonymous (in-lined) type
            else if (type.getName() == null) {
                hasAnonymousType = true;
            }
            //-- built-in simpleType
            else if (type.isSimpleType() && ((SimpleType)type).isBuiltInType()){
                _atts.addAttribute(ATTR_TYPE, CDATA,
                    schemaPrefix+type.getName());
            }
            else if (type.getStructureType() == Structure.ANYTYPE) {
                _atts.addAttribute(ATTR_TYPE, CDATA,
                    schemaPrefix+type.getName());
            }
            //-- type imported from another schema
            else if (isImportedType(type, element)) {
                String namespace = type.getSchema().getTargetNamespace();
                String prefix = getNSPrefix(element.getSchema(), namespace);
                if (prefix == null) {
                    //-- declare a temporary prefix
                    prefix = schemaPrefix + '2';
                    _atts.addAttribute("xmlns:" + prefix, CDATA, namespace);
                }
                _atts.addAttribute(ATTR_TYPE, CDATA,
                    prefix + ':' +type.getName());
            //-- otherwise...user defined type.
            }
            else {
                String typeName = type.getName();
                //add the targetNamespace prefix if necessary
                String targetNamespace = element.getSchema().getTargetNamespace();
                if ( targetNamespace!=null ) {
                    String nsPrefix = getNSPrefix(element.getSchema(), targetNamespace);
                    if ((nsPrefix != null) && (nsPrefix.length() != 0))
                        typeName = nsPrefix +':'+ typeName;
                    targetNamespace = null;
                    nsPrefix = null;
                }

                _atts.addAttribute(ATTR_TYPE, CDATA, typeName);
            }
        }

        // add various attributes if we are looking at a local element definition; iow,
        // for an element reference, this values should be specified on the
        // referenced (global) element definition only.
        if (!element.isReference()) {
           
            //-- @abstract
            if (element.isAbstract()) {
                _atts.addAttribute(SchemaNames.ABSTRACT, CDATA, VALUE_TRUE);
            }
           
            //-- @block
            if (element.getBlock() != null) {
                _atts.addAttribute(SchemaNames.BLOCK_ATTR, CDATA,
                        element.getBlock().toString());
            }
           
            //-- @default
            String defaultValue = element.getDefaultValue();
            if (defaultValue != null) {
                _atts.addAttribute(SchemaNames.DEFAULT_ATTR, CDATA,
                        defaultValue);
            }
           
            //-- @fixed
            String fixedValue = element.getFixedValue();
            if (fixedValue != null) {
                _atts.addAttribute(SchemaNames.FIXED_ATTR, CDATA,
                        fixedValue);
            }
           
            //-- @final
            FinalList finalValue = element.getFinal();
            if (finalValue != null) {
                _atts.addAttribute(SchemaNames.FINAL_ATTR, CDATA,
                        finalValue.toString());
            }
           
            //-- @substitutionGroup
            String substitutionGroup = element.getSubstitutionGroup();
            if (substitutionGroup != null) {
                _atts.addAttribute(SchemaNames.SUBSTITUTION_GROUP_ATTR, CDATA,
                        substitutionGroup);
            }
        }

        //-- @form
        Form form = element.getForm();
        if (form != null) {
            _atts.addAttribute(SchemaNames.FORM, CDATA, form.toString());
        }

        //-- @id
        String id = element.getId();
        if (id != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                id);
        }

        //-- @nillable
        if (element.isNillable()) {
            _atts.addAttribute(SchemaNames.NILLABLE_ATTR, CDATA,
                VALUE_TRUE);
        }


        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process annotations
        processAnnotated(element, schemaPrefix);

        //-- process anonymous type if necessary
        if (hasAnonymousType) {
            XMLType type = element.getType();
            if (type.isComplexType())
                processComplexType((ComplexType) type, schemaPrefix);
            else if (type.isSimpleType())
                   processSimpleType((SimpleType)type, schemaPrefix);
        }

        //-- process any identity-constraints
        Enumeration enumeration = element.getIdentityConstraints();
        while(enumeration.hasMoreElements()) {
            processIdentityConstraint((IdentityConstraint)enumeration.nextElement(),
                schemaPrefix);
        }

        _handler.endElement(ELEMENT_NAME);

    } //-- processElement

    /**
     * Processes the given group definition into SAX events
     *
     * @param group the group definition to process into SAX events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processGroup(Group group, String schemaPrefix)
        throws SAXException
    {
        String ELEMENT_NAME = schemaPrefix;

        //-- ModelGroup
        String reference = null;
        if (group instanceof ModelGroup) {
            ELEMENT_NAME += GROUP;
            ModelGroup mGroup = (ModelGroup)group;
            if (mGroup.hasReference()) {
                ModelGroup refGroup = mGroup.getReference();
                if (refGroup != null) {
                    reference = refGroup.getName();
                    //-- prefix
                    String namespace = refGroup.getSchema().getTargetNamespace();
                    if (namespace == null) namespace = "";
                    String prefix = getNSPrefix(mGroup.getSchema(), namespace);
                    if ((prefix != null) && (prefix.length() > 0))
                        reference = prefix + ':' + reference;
                   
                }
            }
        }
        //-- Group
        else {
            ELEMENT_NAME += group.getOrder().toString();
        }

        _atts.clear();

        //-- @id
        if (group.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                group.getId());
        }

        //-- reference
        if (reference != null) {
            _atts.addAttribute("ref", CDATA, reference);
        }
        else if (group.getName() != null) {
            _atts.addAttribute(ATTR_NAME, CDATA, group.getName());
        }

        //-- minOccurs/maxOccurs
        int max = group.getMaxOccurs();
        int min = group.getMinOccurs();

        if (min != 1) {
            _atts.addAttribute(SchemaNames.MIN_OCCURS_ATTR, CDATA,
                Integer.toString(min));
        }

        if (max < 0) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                "unbounded");
        }
        else if (max != 1) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                Integer.toString(max));
        }


        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process annotations
        processAnnotated(group, schemaPrefix);

        //-- process content model
        if (reference == null) {
            processContentModelGroup(group, schemaPrefix);
        }

        _handler.endElement(ELEMENT_NAME);

    } //-- processGroup

    /**
     * Processes the given IdentityConstraint
     *
     * @param constraint the IdentityConstraint to process
    **/
    private void processIdentityConstraint
        (IdentityConstraint constraint, String schemaPrefix)
        throws SAXException
    {

        if (constraint == null) return;

        String ELEMENT_NAME = schemaPrefix;

        String id    = null;
        String refer = null;

        switch (constraint.getStructureType()) {
            case Structure.KEYREF:
                ELEMENT_NAME += SchemaNames.KEYREF;
                refer = ((KeyRef)constraint).getRefer();
                break;
            case Structure.UNIQUE:
                ELEMENT_NAME += SchemaNames.UNIQUE;
                break;
            default:
                ELEMENT_NAME += SchemaNames.KEY;
                break;
        }

        id   = constraint.getId();

        _atts.clear();

        //-- name
        _atts.addAttribute(SchemaNames.NAME_ATTR, CDATA,
            constraint.getName());

        //-- id
        if (id != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA, id);
        }

        //-- refer
        if (refer != null) {
            _atts.addAttribute(SchemaNames.REFER_ATTR, CDATA, refer);
        }

        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process annotations
        processAnnotated(constraint, schemaPrefix);

        //-- process selector
        String ELEM_SELECTOR = schemaPrefix + SchemaNames.SELECTOR;
        String xpath = null;

        IdentitySelector selector = constraint.getSelector();
        xpath = selector.getXPath();
        id = selector.getId();
        _atts.clear();
        _atts.addAttribute(SchemaNames.XPATH_ATTR, CDATA, xpath);
        if (id != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA, id);
        }
        _handler.startElement(ELEM_SELECTOR, _atts);
        processAnnotated(selector, schemaPrefix);
        _handler.endElement(ELEM_SELECTOR);

        //-- process field(s)
        String ELEM_FIELD = schemaPrefix + SchemaNames.FIELD;
        Enumeration enumeration = constraint.getFields();
        while(enumeration.hasMoreElements()) {
            IdentityField field = (IdentityField) enumeration.nextElement();
            _atts.clear();
            id    = field.getId();
            xpath = field.getXPath();
            _atts.addAttribute(SchemaNames.XPATH_ATTR, CDATA, xpath);
            if (id != null) {
                _atts.addAttribute(SchemaNames.ID_ATTR, CDATA, id);
            }
            _handler.startElement(ELEM_FIELD, _atts);
            processAnnotated(field, schemaPrefix);
            _handler.endElement(ELEM_FIELD);
        }
        _handler.endElement(ELEMENT_NAME);

    } //-- processIdentityConstraint

    private void processSchema(Schema schema)
        throws SAXException
    {
        //-- calculate schema prefix
        String schemaPrefix = getNSPrefix(schema, schema.getSchemaNamespace());
        if (schemaPrefix == null) {
            schemaPrefix = DEFAULT_PREFIX;
        }

        //-- namespace declaration for xsd
        _atts.clear();
        if (schemaPrefix.length() == 0) {
            //-- declared as default namespace
            _atts.addAttribute(XMLNS_DEFAULT, CDATA,
                schema.getSchemaNamespace());
        }
        else {
            //-- declare namespace + prefix
            _atts.addAttribute(XMLNS_PREFIX + schemaPrefix, CDATA,
                schema.getSchemaNamespace());
        }



        //-- namespace declarations
        Namespaces namespaces = schema.getNamespaces();
        Enumeration keys = namespaces.getLocalNamespacePrefixes();
        while (keys.hasMoreElements()) {
            String nsPrefix = (String)keys.nextElement();
            if (!nsPrefix.equals(schemaPrefix)) {
                String ns = namespaces.getNamespaceURI(nsPrefix);
                if (nsPrefix.length() > 0) {
                    _atts.addAttribute(XMLNS_PREFIX + nsPrefix, CDATA, ns);
                }
                else {
                    _atts.addAttribute(XMLNS_DEFAULT, CDATA, ns);
                }
            }
        }

        //-- targetNS
        String value = schema.getTargetNamespace();
        if (value != null)
            _atts.addAttribute(SchemaNames.TARGET_NS_ATTR, CDATA, value);

        //-- attributeFormDefault
        Form form = schema.getAttributeFormDefault();
        if (form != null) {
            _atts.addAttribute(SchemaNames.ATTR_FORM_DEFAULT_ATTR, CDATA,
                form.toString());
        }
        //-- elementFormDefault
        form = schema.getElementFormDefault();
        if (form != null) {
            _atts.addAttribute(SchemaNames.ELEM_FORM_DEFAULT_ATTR, CDATA,
                form.toString());
        }

        //-- blockDefault
        BlockList blockList = schema.getBlockDefault();
        if (blockList != null) {
            _atts.addAttribute(SchemaNames.BLOCK_DEFAULT_ATTR, CDATA,
                blockList.toString());
        }

        //-- finalDefault
        FinalList finalList = schema.getFinalDefault();
        if (finalList != null) {
            _atts.addAttribute(SchemaNames.FINAL_DEFAULT_ATTR, CDATA,
                finalList.toString());
        }

        //--@version
        if (schema.getVersion() != null) {
            _atts.addAttribute(SchemaNames.VERSION_ATTR, CDATA,schema.getVersion());
        }


        //-- modify schemaPrefix to include ':'
        if (schemaPrefix.length() > 0) {
            schemaPrefix += ':';
        }

        _handler.startDocument();

        String ELEM_SCHEMA = schemaPrefix + SCHEMA;

        _handler.startElement(ELEM_SCHEMA, _atts);

        //-- process annotations
        processAnnotated(schema, schemaPrefix);

        Enumeration enumeration = null;
         //-- process all imported schemas
        enumeration = schema.getImportedSchema();
        while (enumeration.hasMoreElements()) {
            processImport((Schema)enumeration.nextElement(), schemaPrefix);
        }
       
        //-- process all cached included schemas
        enumeration = schema.getCachedIncludedSchemas();
        while (enumeration.hasMoreElements()) {
          processIncludedSchema((Schema)enumeration.nextElement(), schemaPrefix);
        }
       
        //-- process all redefinitions
        enumeration = schema.getRedefineSchema();
        while (enumeration.hasMoreElements()) {
          processRedefinition((RedefineSchema)enumeration.nextElement(), schema, schemaPrefix);
        }
       
        //-- process all top level attributeGroup declarations
        enumeration = schema.getAttributeGroups();
        while (enumeration.hasMoreElements()) {
          boolean found = false;
          AttributeGroup temp = (AttributeGroup) enumeration.nextElement();
          //-- check if this attributeGroup is not
            //-- part of a redefinition
           if (temp instanceof AttributeGroupDecl) {
            if (((AttributeGroupDecl)temp).isRedefined())
              found = true;
           }
           
           //--check if this attributeGroup is not
           //-- included
           Enumeration includedSchemas = schema.getCachedIncludedSchemas();
           while (includedSchemas.hasMoreElements()) {
               Schema tempSchema = (Schema)includedSchemas.nextElement();
               if (temp instanceof AttributeGroupDecl) {
                   String name = ((AttributeGroupDecl)temp).getName()
                   found = (tempSchema.getAttributeGroup(name)!= null);
               }
           }
          
           if (!found)
                processAttributeGroup(temp,schemaPrefix);
        }

        //-- process all top level attribute declarations
        enumeration = schema.getAttributes();
        while (enumeration.hasMoreElements()) {
          AttributeDecl temp = (AttributeDecl) enumeration.nextElement();
          boolean found = false;
          //--check if this attributeGroup is not
          //-- included
          Enumeration includedSchemas = schema.getCachedIncludedSchemas();
          while (includedSchemas.hasMoreElements()) {
            Schema tempSchema = (Schema)includedSchemas.nextElement();
            found = (tempSchema.getAttribute(temp.getName())!= null);
          }
         
          if (!found)
                processAttribute(temp,schemaPrefix);
        }

        //-- process all top level element declarations
        enumeration = schema.getElementDecls();
        while (enumeration.hasMoreElements()) {
          ElementDecl temp = (ElementDecl) enumeration.nextElement();
          boolean found = false;
          //--check if this attributeGroup is not
          //-- included
          Enumeration includedSchemas = schema.getCachedIncludedSchemas();
          while (includedSchemas.hasMoreElements()) {
            Schema tempSchema = (Schema)includedSchemas.nextElement();
            found = (tempSchema.getElementDecl(temp.getName())!= null);
          }
         
          if (!found)
              processElement(temp,schemaPrefix);
        }

        //-- process all top level complex types
        enumeration = schema.getComplexTypes();
        while (enumeration.hasMoreElements()) {
            ComplexType temp = (ComplexType) enumeration.nextElement();
            boolean found = false;
            //--check if this attributeGroup is not
            //-- included
            Enumeration includedSchemas = schema.getCachedIncludedSchemas();
            while (includedSchemas.hasMoreElements()) {
              Schema tempSchema = (Schema)includedSchemas.nextElement();
              found = (tempSchema.getComplexType(temp.getName())!= null);
            }
            if (!temp.isRedefined() && !found)
                processComplexType(temp, schemaPrefix);
        }

        //-- process all top level groups
        enumeration = schema.getModelGroups();
        while (enumeration.hasMoreElements()) {
          ModelGroup temp = (ModelGroup)enumeration.nextElement();
          boolean found = false;
          //--check if this Group is not
          //-- included
          Enumeration includedSchemas = schema.getCachedIncludedSchemas();
          while (includedSchemas.hasMoreElements()) {
            Schema tempSchema = (Schema)includedSchemas.nextElement();
            found = (tempSchema.getModelGroup(temp.getName())!= null);
          }
         
          if (!temp.isRedefined() && !found)
              processGroup(temp, schemaPrefix);
        }

        //-- process all top level simple types
        enumeration = schema.getSimpleTypes();
        while (enumeration.hasMoreElements()) {
            SimpleType temp = (SimpleType) enumeration.nextElement();
            boolean found = false;
            //--check if this attributeGroup is not
            //-- included
            Enumeration includedSchemas = schema.getCachedIncludedSchemas();
            while (includedSchemas.hasMoreElements()) {
              Schema tempSchema = (Schema)includedSchemas.nextElement();
              found = (tempSchema.getSimpleType(temp.getName())!= null);
            }
            if (!temp.isRedefined() && !found)
                processSimpleType(temp, schemaPrefix);
        }

        _handler.endElement(ELEM_SCHEMA);

        _handler.endDocument();

    } //-- processSchema

    /**
     * Process a Wildcard (xsd:any) component
     *
     * @param wildcard the Wildcard to process
     * @param schemaPrefix the namespace prefix to use for schema elements
     */
    private void processWildcard(Wildcard wildcard, String schemaPrefix)
        throws SAXException
    {
       
        String ELEMENT_NAME = null;
        if (wildcard.isAttributeWildcard())
            ELEMENT_NAME = schemaPrefix + SchemaNames.ANY_ATTRIBUTE;
        else
            ELEMENT_NAME = schemaPrefix + SchemaNames.ANY;
           
        _atts.clear();
       
        //-- @namespace
        StringBuffer namespace = new StringBuffer();
        Enumeration enumeration = wildcard.getNamespaces();
        while (enumeration.hasMoreElements()) {
            if (namespace.length() > 0) namespace.append(' ');
            namespace.append(enumeration.nextElement().toString());
        }
        if (namespace.length() > 0) {
            _atts.addAttribute(SchemaNames.NAMESPACE, CDATA, namespace.toString());
        }
       
        //-- minOccurs/maxOccurs
        int max = wildcard.getMaxOccurs();
        int min = wildcard.getMinOccurs();

        if (min != 1) {
            _atts.addAttribute(SchemaNames.MIN_OCCURS_ATTR, CDATA,
                Integer.toString(min));
        }

        if (max < 0) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                "unbounded");
        }
        else if (max != 1) {
            _atts.addAttribute(SchemaNames.MAX_OCCURS_ATTR, CDATA,
                Integer.toString(max));
        }
       
        //-- @processContents
        String value = wildcard.getProcessContent();
        if (value != null) {
            _atts.addAttribute(SchemaNames.PROCESS_CONTENTS, CDATA, value);
        }
        _handler.startElement(ELEMENT_NAME, _atts);
        processAnnotated(wildcard, schemaPrefix);
        _handler.endElement(ELEMENT_NAME);
       
    } //-- processWildcard
   
    /**
     * Process an imported schema
     *
     * @param schema the imported Schema to process
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processImport(Schema schema, String schemaPrefix)
        throws SAXException
    {
        String ELEMENT_NAME = schemaPrefix + SchemaNames.IMPORT;
        _atts.clear();

        String namespace = schema.getTargetNamespace();
        String schemaLoc = schema.getSchemaLocation();

        _atts.addAttribute("namespace", null, namespace);
        _atts.addAttribute("schemaLocation", null, schemaLoc);
        _handler.startElement(ELEMENT_NAME, _atts);
        _handler.endElement(ELEMENT_NAME);
    } //-- processImport
   
    /**
     * Process an included schema
     *
     * @param schema the imported Schema to process
     * @param schemaPrefix the namespace prefix to use for schema elements
     **/
    private void processIncludedSchema(Schema schema, String schemaPrefix)
  throws SAXException
  {
      String ELEMENT_NAME = schemaPrefix + SchemaNames.INCLUDE;
      _atts.clear();

      String schemaLoc = schema.getSchemaLocation();

      _atts.addAttribute("schemaLocation", null, schemaLoc);
      _handler.startElement(ELEMENT_NAME, _atts);
      _handler.endElement(ELEMENT_NAME);
    } //-- processImport
   
    /**
     * Process a set of redefinitions
     *
     * @param schema the redefined Schema to process
     * @param schemaPrefix the namespace prefix to use for schema elements
     **/
    private void processRedefinition(RedefineSchema schema, Schema parentSchema, String schemaPrefix)
  throws SAXException
  {
      String ELEMENT_NAME = schemaPrefix + SchemaNames.REDEFINE;
      _atts.clear();
       
      String schemaLoc = schema.getSchemaLocation();
      if (schemaLoc != "")
            _atts.addAttribute("schemaLocation", null, schemaLoc);
     
      _handler.startElement(ELEMENT_NAME, _atts);
       
      //-- process annotations
      processAnnotated(schema, schemaPrefix);
     
      if (schemaLoc != "") {
        Enumeration enumeration = null;
        //--process complexTypes
          enumeration = schema.enumerateComplexTypes();
          while (enumeration.hasMoreElements()) {
            ComplexType type = (ComplexType)enumeration.nextElement();
            processComplexType(type, schemaPrefix);
          }
        //--process simpleTypes
          enumeration = schema.enumerateSimpleTypes();
          while (enumeration.hasMoreElements()) {
            SimpleType type = (SimpleType)enumeration.nextElement();
            processSimpleType(type, schemaPrefix);
          }
        //--process groups
          enumeration = schema.enumerateGroups();
          while (enumeration.hasMoreElements()) {
            ModelGroup group= (ModelGroup)enumeration.nextElement();
            processGroup(group, schemaPrefix);
          }
        //--process AttributeGroups
          enumeration = schema.enumerateAttributeGroups();
          while (enumeration.hasMoreElements()) {
            AttributeGroupDecl attGroup = (AttributeGroupDecl)enumeration.nextElement();
            processAttributeGroup(attGroup, schemaPrefix);
          }
      }
      _handler.endElement(ELEMENT_NAME);
    } //-- processImport

    /**
     * Processes the given simple type definition
     *
     * @param simpleType the simple type definition to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processSimpleType
        (SimpleType simpleType, String schemaPrefix)
        throws SAXException
    {

        if (simpleType.isBuiltInType()) return;

        String ELEMENT_NAME = schemaPrefix + SIMPLE_TYPE;

        _atts.clear();

        String name = simpleType.getName();

        //-- top-level simple type
        if (name != null) {
            _atts.addAttribute(SchemaNames.NAME_ATTR, CDATA, name);
        }

        //-- @final
        if (simpleType.getFinal() != null) {
            _atts.addAttribute(SchemaNames.FINAL_ATTR, CDATA,
                simpleType.getFinal());
        }

        //-- @id
        if (simpleType.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA, simpleType.getId());
        }

        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process annotations
        processAnnotated(simpleType, schemaPrefix);

        //-- handle restriction
        SimpleType base = (SimpleType)simpleType.getBaseType();

        /*
         * In case we don't have a direct reference on the base type,
         * check whether its definition can be obtained from one of the
         * imported schemas.
         */
        String typeName = simpleType.getBaseTypeName();
        if(base == null && typeName != null) {
          Schema schema = simpleType.getSchema();
          base = getSimpleTypeFromSchema(schema, typeName);
        }

        boolean isRestriction = false;
        if (base != null) {
            if (simpleType instanceof ListType) {
                isRestriction = (base instanceof ListType);
            }
            else isRestriction = true;
        }
       
        if (isRestriction) {

            String ELEM_RESTRICTION = schemaPrefix + RESTRICTION;

            _atts.clear();

            typeName = base.getName();
            //-- add "xsd" prefix if necessary
            if (typeName.indexOf(':') < 0) {
                if (base.isBuiltInType()) {
                    typeName = schemaPrefix + typeName;
                }
                else {
                    String targetNamespace = base.getSchema().getTargetNamespace();
                    String prefix = getNSPrefix(simpleType.getSchema(), targetNamespace);
                    if ((prefix != null) && (prefix.length() > 0)) {
                        typeName = prefix + ":" + typeName;
                    }
                }
            }
            _atts.addAttribute(SchemaNames.BASE_ATTR, CDATA, typeName);

            _handler.startElement(ELEM_RESTRICTION, _atts);

            //-- process facets
            Enumeration enumeration = simpleType.getLocalFacets();
            while (enumeration.hasMoreElements()) {
                Facet facet = (Facet) enumeration.nextElement();
                _atts.clear();
                _atts.addAttribute(SchemaNames.VALUE_ATTR, CDATA,
                    facet.getValue());
                String facetName = schemaPrefix + facet.getName();
                _handler.startElement(facetName, _atts);
                Enumeration annotations = facet.getAnnotations();
                while (annotations.hasMoreElements()) {
                    Annotation annotation = (Annotation)annotations.nextElement();
                    processAnnotation(annotation, schemaPrefix);
                }
                _handler.endElement(facetName);
            }

            _handler.endElement(ELEM_RESTRICTION);
        }
        else if (simpleType instanceof Union) {
            processUnion((Union)simpleType, schemaPrefix);
        }
        //-- handle List
        else {

            String ELEM_LIST = schemaPrefix + SchemaNames.LIST;

            _atts.clear();

            SimpleType itemType = ((ListType)simpleType).getItemType();

            boolean topLevel = (itemType.getParent() == itemType.getSchema());
            if (itemType.isBuiltInType() || topLevel) {
                typeName = itemType.getName();
                //-- add "xsd" prefix if necessary
                if ((typeName.indexOf(':') < 0) && itemType.isBuiltInType()) {
                    typeName = schemaPrefix + typeName;
                }
                _atts.addAttribute("itemType", CDATA, typeName);
            }
            _handler.startElement(ELEM_LIST, _atts);

            //-- processAnnotations
            Annotation ann = ((ListType)simpleType).getLocalAnnotation();
            if (ann != null) {
                processAnnotation(ann, schemaPrefix);
            }
            //-- process simpleType if necessary
            if ((! topLevel) && (! itemType.isBuiltInType())) {
                processSimpleType(itemType, schemaPrefix);
            }
            _handler.endElement(ELEM_LIST);
        }

        _handler.endElement(ELEMENT_NAME);

    } //-- processSimpleType

    /**
     * Processes the given simpleType Union definition
     *
     * @param union the simpleType Union definition to process into events
     * @param schemaPrefix the namespace prefix to use for schema elements
    **/
    private void processUnion
        (Union union, String schemaPrefix)
        throws SAXException
    {

        String ELEMENT_NAME = schemaPrefix + SchemaNames.UNION;

        _atts.clear();

        if (union.getId() != null) {
            _atts.addAttribute(SchemaNames.ID_ATTR, CDATA,
                union.getId());
        }

        //-- process local simpleType references
        StringBuffer memberTypes = new StringBuffer();
        Enumeration enumeration = union.getMemberTypes();
        while (enumeration.hasMoreElements()) {
            SimpleType simpleType = (SimpleType)enumeration.nextElement();
            //-- ignore local simpleTypes;
            if (simpleType.getParent() != union.getSchema()) {
                continue;
            }
            //-- process top-level references
            if (memberTypes.length() > 0) memberTypes.append(' ');
            memberTypes.append(simpleType.getName());
        }
        if (memberTypes.length() > 0) {
            _atts.addAttribute(SchemaNames.MEMBER_TYPES_ATTR, CDATA,
                memberTypes.toString());
        }

        _handler.startElement(ELEMENT_NAME, _atts);

        //-- process local annotation
        Annotation annotation = union.getLocalAnnotation();
        if (annotation != null) {
            processAnnotation(annotation, schemaPrefix);
        }

        //-- process local simpleType definitions
        enumeration = union.getMemberTypes();
        while (enumeration.hasMoreElements()) {
            SimpleType simpleType = (SimpleType)enumeration.nextElement();
            //-- ignore top-level simpleTypes;
            if (simpleType.getParent() == union.getSchema())
                continue;
            processSimpleType(simpleType, schemaPrefix);
        }
        _handler.endElement(ELEMENT_NAME);

    } //-- processUnion

    /**
     * Determines if a given XMLType is imported by the
     * schema containing the element that refers to it.
     *
     * @param type the type to be checked to see if it is imported
     * @param element the schema element that references the type
    **/
    private boolean isImportedType(XMLType type, ElementDecl element) {
        String targetNS = type.getSchema().getTargetNamespace();
        if (targetNS != null) {
            return (element.getSchema().getImportedSchema(targetNS) != null);
        }
        return false;
    } //-- isImportedType

    /**
     * Determines the proper namespace prefix for a namespace
     * by scanning all declared namespaces for the schema.
     *
     * @param schema the schema in which the namespace is declared
     * @param namespace the namespace for which a prefix will be returned
    **/
    private String getNSPrefix(Schema schema, String namespace){
      if (namespace == null)
        namespace = "";
      return schema.getNamespaces().getNamespacePrefix(namespace);
    } //-- getNSPrefix
   
   
    /**
     * Walks over provided schema and its hierarchy looking for
     * the named type.
     *
     * @param schema Schema instance where to start searching from.
     * @param typeName Name of the type we search.
     *
     * @return Definition of the simple type is found, null otherwise.
     */
    private SimpleType getSimpleTypeFromSchema(Schema schema, String typeName) {
      SimpleType base = schema.getSimpleType(typeName);
      if(base == null) {
        Enumeration imports = schema.getImportedSchema();
        while (imports.hasMoreElements() && base == null) {
        Schema sch = (Schema) imports.nextElement();
        base = getSimpleTypeFromSchema(sch, typeName);
      }
      }
      return base;
    }
} //-- SchemaWriter
TOP

Related Classes of org.exolab.castor.xml.schema.writer.SchemaWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.