/*******************************************************************************
 * Copyright (c) 2008 IGA Tosiki, NTT DATA BUSINESS BRAINS Corp.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IGA Tosiki (NTT DATA BUSINESS BRAINS Corp.) - initial API and implementation
 *******************************************************************************/
/*
 * blanco Framework
 * Copyright (C) 2008 NTT DATA BUSINESS BRAINS CORPORATION
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.html.normalizer.parser.helper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

import blanco.html.normalizer.parser.valueobject.BlancoHtmlEvent;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventCharacters;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventComments;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventEndDocument;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventEndElement;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventStartDocument;
import blanco.html.normalizer.parser.valueobject.BlancoHtmlEventStartElement;
import blanco.html.parser.valueobject.BlancoHtmlAttribute;

/**
 * HTML をパースして、HTMLイベントを取得します。
 * 
 * @author IGA Tosiki
 */
public class BlancoHtmlEventParserContentHandler implements ContentHandler,
        LexicalHandler {
    /**
     * HTMLイベントリスト。
     */
    protected List<BlancoHtmlEvent> fEventList = new ArrayList<BlancoHtmlEvent>();

    /**
     * パース結果のイベントリストを取得します。
     * 
     * なお、ここで戻されるのは、発生したイベント「そのまま」です。 オプションの終了タグなどの調整は実施されていません。
     * 
     * @return イベントリスト。
     */
    public List<BlancoHtmlEvent> getEventList() {
        return fEventList;
    }

    //
    // ContentHandler
    //

    public void setDocumentLocator(final Locator locator) {
    }

    /**
     * ドキュメントの開始。
     * 
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void startDocument() throws SAXException {
        final BlancoHtmlEventStartDocument event = new BlancoHtmlEventStartDocument();
        fEventList.add(event);
    }

    /**
     * ドキュメントの終了。
     * 
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void endDocument() throws SAXException {
        final BlancoHtmlEventEndDocument event = new BlancoHtmlEventEndDocument();
        fEventList.add(event);
    }

    /**
     * 要素の開始。
     * 
     * HTMLという特性のため、start と end とが必ずしも対に発生しません。
     * 
     * @param name
     *            要素名。
     * @param attrs
     *            属性のリスト。
     */
    public void startElement(final String uri, final String localName,
            final String name, final Attributes atts) throws SAXException {
        final BlancoHtmlEventStartElement event = new BlancoHtmlEventStartElement();
        fEventList.add(event);
        event.setName(name);
        final List<blanco.html.parser.valueobject.BlancoHtmlAttribute> attrs = new ArrayList<BlancoHtmlAttribute>();
        event.setAttrs(attrs);

        for (int index = 0; index < atts.getLength(); index++) {
            final BlancoHtmlAttribute attr = new BlancoHtmlAttribute();
            attrs.add(attr);
            attr.setQName(atts.getQName(index));
            attr.setLocalName(atts.getLocalName(index));
            attr.setType(atts.getType(index));
            attr.setUri(atts.getURI(index));
            attr.setValue(atts.getValue(index));
        }
    }

    /**
     * 要素の終了。
     * 
     * HTMLという特性のため、start と end とが必ずしも対に発生しません。
     * 
     * @param name
     *            要素名。
     */
    public void endElement(final String uri, final String localName,
            final String name) throws SAXException {
        final BlancoHtmlEventEndElement event = new BlancoHtmlEventEndElement();
        fEventList.add(event);
        event.setName(name);
    }

    /**
     * 文字列。文字参照などの処理がされていない文字列が「そのまま」戻ります。
     * 
     * @param argCharacters
     *            文字列。文字参照などは「そのまま」格納します。
     */
    public void characters(final char[] ch, final int start, final int length)
            throws SAXException {
        final BlancoHtmlEventCharacters event = new BlancoHtmlEventCharacters();
        fEventList.add(event);
        event.setCharacters(new String(ch, start, length));
    }

    /** {@inheritDoc} */
    public void ignorableWhitespace(final char[] ch, final int start,
            final int length) throws SAXException {
    }

    /** {@inheritDoc} */
    public void processingInstruction(final String target, final String data)
            throws SAXException {
    }

    /** {@inheritDoc} */
    public void skippedEntity(final String name) throws SAXException {
    }

    /** {@inheritDoc} */
    public void startPrefixMapping(final String prefix, final String uri)
            throws SAXException {
    }

    /** {@inheritDoc} */
    public void endPrefixMapping(final String prefix) throws SAXException {
    }

    // 
    // LexicalHandler
    //

    /**
     * コメント。そのままの文字列が戻ります。
     * 
     * @param argComments
     *            コメント文字列。「そのまま」格納します。
     * @param argType
     *            コメントの形式。0:!、1:%
     */

    public void comment(final char[] ch, final int start, final int length)
            throws SAXException {
        final BlancoHtmlEventComments event = new BlancoHtmlEventComments();
        fEventList.add(event);
        event.setComments(new String(ch, start, length));
    }

    /** {@inheritDoc} */
    public void startDTD(final String name, final String publicId,
            final String systemId) throws SAXException {
    }

    /** {@inheritDoc} */
    public void endDTD() throws SAXException {
    }

    /** {@inheritDoc} */
    public void startCDATA() throws SAXException {
    }

    /** {@inheritDoc} */
    public void endCDATA() throws SAXException {
    }

    /** {@inheritDoc} */
    public void startEntity(final String name) throws SAXException {
    }

    /** {@inheritDoc} */
    public void endEntity(final String name) throws SAXException {
    }
}
