

package org.dom4j.io;

import javax.xml.parsers.SAXParser;
import org.dom4j.Element;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.apache.xerces.xs.PSVIProvider;
import org.dom4j.Attribute;
import org.dom4j.DocumentFactory;
import org.dom4j.ElementHandler;
import org.dom4j.QName;
import org.dom4j.schema.SchemaAwareAttribute;
import org.dom4j.schema.SchemaAwareElement;

/**
 *
 * @author  mike skells
 */
public class SchemaAwareSAXContentHandler extends SAXContentHandler{
    
    private final PSVIProvider psviProvider;
    
    /** Creates a new instance of SchemaAwareDispatchHandler */
    public SchemaAwareSAXContentHandler(PSVIProvider psviProvider) {
        this.psviProvider = psviProvider;
    }
    
    public SchemaAwareSAXContentHandler(PSVIProvider psviProvider, DocumentFactory documentFactory) {
        super(documentFactory);
        this.psviProvider = psviProvider;
    }
    
    public SchemaAwareSAXContentHandler(PSVIProvider psviProvider, DocumentFactory documentFactory,
    ElementHandler elementHandler) {
        super(documentFactory, elementHandler);
        this.psviProvider = psviProvider;
    }
    
    public SchemaAwareSAXContentHandler(PSVIProvider psviProvider, DocumentFactory documentFactory,
    ElementHandler elementHandler, ElementStack elementStack) {
        super(documentFactory, elementHandler, elementStack);
        this.psviProvider = psviProvider;
    }
    
    
    public void startElement(String namespaceURI, String localName,
    String qualifiedName, Attributes attributes) throws SAXException {
        super.startElement(namespaceURI, localName, qualifiedName, attributes);
        Element currentElement = getElementStack().getCurrent();
        if (currentElement instanceof SchemaAwareElement) {
            SchemaAwareElement schemaAwareElement = (SchemaAwareElement)currentElement;
            initElementPsvi(schemaAwareElement);
        } else {
            warn("Not a SchemaAwareElement "+ currentElement.getClass());
        }
    }
    
    protected void initElementPsvi(SchemaAwareElement schemaAwareElement) {
        schemaAwareElement.initElementPsvi(psviProvider.getElementPSVI());
    }
    protected void initAttributePsvi(SchemaAwareAttribute schemaAwareAttribute, int attributesIndex) {
        schemaAwareAttribute.initAttributePsvi(psviProvider.getAttributePSVI(attributesIndex));
    }
    
    protected void warn(String msg) {
        System.out.print("SchemaAwareSAXContentHandler - warn :");
        System.out.println(msg);
        
    }
    
    protected void addAttributes(Element element, Attributes attributes) {
        super.addAttributes(element, attributes);
        int expectedTargetIndex = 0;
        for (int sourceIndex = 0, max = attributes.getLength(); sourceIndex < max ; sourceIndex++) {
            String qualifiedName = attributes.getQName(sourceIndex);
            if (!qualifiedName.startsWith("xmlns")) {
                Attribute attribute = element.attribute(expectedTargetIndex++);
                if (!attribute.getQualifiedName().equals(qualifiedName)) {
                    QName qname = element.getQName(qualifiedName);
                    attribute = element.attribute(qname);
                }
                if (attribute instanceof SchemaAwareAttribute) {
                    SchemaAwareAttribute schemaAwareAttribute = (SchemaAwareAttribute)attribute;
                    initAttributePsvi(schemaAwareAttribute,sourceIndex);
                } else {
                    warn("Not a SchemaAwareAttribute "+ attribute.getClass());
                }
            }
        }
    }
}
