/*
 * blanco Framework
 * Copyright (C) 2004-2006 IGA Tosiki
 * 
 * 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.xml.bind;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import blanco.xml.bind.valueobject.BlancoXmlDocument;

/**
 * XMLからJavaオブジェクトを生成します。
 * 
 * このクラスは XML/バリューオブジェクトマッピング (X/Oマッピング) blancoXmlBinding の一部です。
 * 
 * @author IGA Tosiki
 */
public class BlancoXmlUnmarshaller {
    /**
     * XMLからJavaオブジェクトを生成します。
     * 
     * 参考:
     * http://java.sun.com/webservices/docs/1.6/api/javax/xml/bind/Unmarshaller.html
     * 
     * @param fileInput
     *            XMLファイル。
     * @return blancoXmlとしてのオブジェクト。
     */
    public BlancoXmlDocument unmarshal(final File fileInput) {
        if (fileInput.exists() == false) {
            throw new IllegalArgumentException("BlancoXmlUnmarshaller: ファイル["
                    + fileInput.getAbsolutePath() + "]は見つかりません。");
        }
        if (fileInput.isDirectory()) {
            throw new IllegalArgumentException("BlancoXmlUnmarshaller: ファイル["
                    + fileInput.getAbsolutePath() + "]はディレクトリです。");
        }
        if (fileInput.canRead() == false) {
            throw new IllegalArgumentException("BlancoXmlUnmarshaller: ファイル["
                    + fileInput.getAbsolutePath() + "]は読み込みできません。");
        }

        InputStream inStream = null;

        try {
            inStream = new BufferedInputStream(new FileInputStream(fileInput));

            return unmarshal(inStream);
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException(
                    "BlancoXmlUnmarshaller: 処理中に入出力例外が発生しました。" + e.toString());
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new IllegalArgumentException(
                            "BlancoXmlUnmarshaller: 処理中に入出力例外が発生しました。"
                                    + e.toString());
                }
            }
        }
    }

    /**
     * XMLからJavaオブジェクトを生成します。
     * 
     * 参考:
     * http://java.sun.com/webservices/docs/1.6/api/javax/xml/bind/Unmarshaller.html
     * 
     * @param inStream
     *            XML入力ストリーム。
     * @return blancoXmlとしてのオブジェクト。
     */
    public BlancoXmlDocument unmarshal(final InputStream inStream) {
        if (inStream == null) {
            throw new IllegalArgumentException(
                    "BlancoXmlUnmarshaller: 入力ストリームにnullが与えられました。");
        }

        final BlancoXmlUnmarshallerContentHandler handler = new BlancoXmlUnmarshallerContentHandler();

        // XMLReaderベースでは JDK 1.4.2で動作しませんでした。本プロダクトではトランスフォーマーベースとします。
        final SAXResult result = new SAXResult(handler);
        result.setHandler(handler);
        result.setLexicalHandler(handler);

        try {
            final TransformerFactory tf = TransformerFactory.newInstance();
            final Transformer transformer = tf.newTransformer();
            transformer.transform(new StreamSource(inStream), result);
        } catch (TransformerException e) {
            e.printStackTrace();
            throw new IllegalArgumentException(
                    "BlancoXmlUnmarshaller: 処理中にXML変換例外が発生しました。" + e.toString());
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new IllegalArgumentException(
                            "BlancoXmlUnmarshaller: 処理中に入出力例外が発生しました。"
                                    + e.toString());
                }
            }
        }

        return handler.getDocument();
    }
}
