package blanco.doclisting;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import blanco.commons.util.BlancoXmlUtil;

/**
 * blancoDocListingから共通的に利用されるユーティリティクラスです。
 * 
 * @author IGA Tosiki
 */
public class BlancoDocListingUtil {
    /**
     * 与えられたXMLファイルをパースしてDocumentElementを取得します。
     * 
     * @param fileRead
     *            XMLとして読み込む入力ファイル
     * @return 読み込んだ結果、作成されたエレメント
     */
    public static Element parseXmlDocument(final File fileRead) {
        if (fileRead.exists() == false) {
            throw new IllegalArgumentException("入力ファイル["
                    + fileRead.getAbsolutePath() + "]が見つかりません。処理中断します。");
        }
        final DocumentBuilderFactory documentFactory = DocumentBuilderFactory
                .newInstance();
        DocumentBuilder documentBuilder = null;
        Document document = null;
        try {
            documentBuilder = documentFactory.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            throw new IllegalArgumentException("例外発生。処理中断します。:" + ex.toString());
        }
        try {
            document = documentBuilder.parse(fileRead);
        } catch (SAXException ex) {
            throw new IllegalArgumentException("例外発生。処理中断します。:" + ex.toString());
        } catch (IOException ex) {
            throw new IllegalArgumentException("例外発生。処理中断します。:" + ex.toString());
        }
        return document.getDocumentElement();
    }

    /**
     * 与えられたノードをコピーします。
     * 
     * @param nodeSource
     *            コピー元ノード。nullが与えられた場合には処理を全く行わないまま制御を戻します。
     * @param documentTarget
     *            ターゲットのDocument。
     * @param elementTarget
     *            ターゲットのElement。
     */
    public static void copyNode(final Node nodeSource,
            final Document documentTarget, final Element elementTarget) {
        if (nodeSource == null) {
            // ソースがnullの場合には処理を行いません。
            return;
        }
        if (documentTarget == null) {
            // ターゲットがnullの場合には処理を行いません。
            return;
        }
        if (elementTarget == null) {
            // ターゲットがnullの場合には処理を行いません。
            return;
        }

        final NodeList nodeList = nodeSource.getChildNodes();
        if (nodeList == null) {
            return;
        }

        final int nodeListSize = nodeList.getLength();
        for (int index = 0; index < nodeListSize; index++) {
            final Node nodeLook = nodeList.item(index);
            if (nodeLook instanceof Element) {
                final Element elementNew = documentTarget
                        .createElement(nodeLook.getNodeName());
                elementTarget.appendChild(elementNew);
                copyNode(nodeLook, documentTarget, elementNew);
            } else if (nodeLook instanceof Text) {
                final Text textCopy = documentTarget
                        .createTextNode(((Text) nodeLook).getData());
                elementTarget.appendChild(textCopy);
            } else {
                System.out.println("無視ノード:[" + nodeList.toString() + "]");
            }
        }
    }

    /**
     * 与えられたリストをキーをもとにソートします。
     * 
     * @param argKeyElementName
     *            ソートのキー名。
     * @param argListCommon
     *            ソートしたいリスト。
     */
    public static void sortListByKey(final String argKeyElementName,
            final List argListCommon) {
        // ソートの処理が必要です。
        Collections.sort(argListCommon, new Comparator() {
            public int compare(final Object arg1, final Object arg2) {
                final Element val1 = (Element) arg1;
                final Element val2 = (Element) arg2;
                final String strVal1 = BlancoXmlUtil.getTextContent(val1,
                        argKeyElementName);
                final String strVal2 = BlancoXmlUtil.getTextContent(val2,
                        argKeyElementName);
                if (strVal1 == null) {
                    return -1;
                }
                if (strVal2 == null) {
                    return 1;
                }
                return (strVal1.compareTo(strVal2));
            }
        });
    }
}
