/*******************************************************************************
 * 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.util;

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

import org.xml.sax.SAXException;

import blanco.html.normalizer.parser.helper.BlancoHtmlEventParserContentHandler;
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.BlancoHtmlContentSerializer;
import blanco.html.parser.BlancoHtmlParser;
import blanco.html.parser.BlancoHtmlParserFactory;
import blanco.html.parser.valueobject.BlancoHtmlAttribute;
import blanco.xml.bind.BlancoXmlAttributesImpl;
import blanco.xml.bind.valueobject.BlancoXmlAttribute;

/**
 * HTMLイベントリストのためのユーティリティクラス。
 * 
 * @author IGA Tosiki
 */
public class BlancoHtmlEventListUtil {
    /**
     * 与えられた HTMLをパースしてイベントリストを取得します。
     * 
     * @param argInputHtml
     *            入力HTML。
     * @return パース結果の HTMLイベントリスト。
     * @throws IOException
     *             入出力例外が発生した場合。
     * @throws SAXException
     */
    public static final List<BlancoHtmlEvent> parse(final byte[] argInputHtml)
            throws IOException, SAXException {
        final BlancoHtmlEventParserContentHandler handler = new BlancoHtmlEventParserContentHandler();

        final BlancoHtmlParser parser = BlancoHtmlParserFactory.getInstance();
        parser.setHandler(handler);
        parser.parse(argInputHtml);

        return handler.getEventList();
    }

    /**
     * 与えられた HTMLイベントリストを HTMLにシリアライズします。
     * 
     * @param eventList
     *            入力となるイベントリスト。
     * @param writer
     *            出力となるライター。
     * @throws IOException
     *             入出力例外が発生した場合。
     * @throws SAXException
     */
    public static void serialize(final List<BlancoHtmlEvent> eventList,
            final BufferedWriter writer) throws IOException, SAXException {
        final BlancoHtmlContentSerializer serializer = new BlancoHtmlContentSerializer();
        serializer.setWriter(writer);

        for (BlancoHtmlEvent look : eventList) {
            if (look instanceof BlancoHtmlEventStartDocument) {
                serializer.startDocument();
            } else if (look instanceof BlancoHtmlEventEndDocument) {
                serializer.endDocument();
            } else if (look instanceof BlancoHtmlEventStartElement) {
                final BlancoHtmlEventStartElement event = (BlancoHtmlEventStartElement) look;
                final List<BlancoXmlAttribute> list = new ArrayList<BlancoXmlAttribute>();
                for (BlancoHtmlAttribute htmlAttr : event.getAttrs()) {
                    list.add(htmlAttr);
                }
                serializer.startElement(null, event.getName(), event.getName(),
                        new BlancoXmlAttributesImpl(list));
            } else if (look instanceof BlancoHtmlEventEndElement) {
                final BlancoHtmlEventEndElement event = (BlancoHtmlEventEndElement) look;
                serializer.endElement(null, event.getName(), event.getName());
            } else if (look instanceof BlancoHtmlEventCharacters) {
                final BlancoHtmlEventCharacters event = (BlancoHtmlEventCharacters) look;
                final char[] wrk = event.getCharacters().toCharArray();
                serializer.characters(wrk, 0, wrk.length);
            } else if (look instanceof BlancoHtmlEventComments) {
                final BlancoHtmlEventComments event = (BlancoHtmlEventComments) look;
                final char[] wrk = event.getComments().toCharArray();
                serializer.comment(wrk, 0, wrk.length);
            } else {
                throw new IllegalArgumentException("不明なイベント。これはありえません: "
                        + look.toString());
            }
        }

        // 最後に flush だけは実施します。close は行いません。
        serializer.getWriter().flush();
    }
}
