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

import java.io.File;
import java.util.List;

import blanco.commons.util.BlancoStringUtil;
import blanco.xliff.valueobject.BlancoXliff;
import blanco.xliff.valueobject.BlancoXliffAltTrans;
import blanco.xliff.valueobject.BlancoXliffNote;
import blanco.xliff.valueobject.BlancoXliffTarget;
import blanco.xliff.valueobject.BlancoXliffTool;
import blanco.xliff.valueobject.BlancoXliffTransUnit;
import blanco.xml.bind.BlancoXmlBindingUtil;
import blanco.xml.bind.BlancoXmlUnmarshaller;
import blanco.xml.bind.valueobject.BlancoXmlDocument;
import blanco.xml.bind.valueobject.BlancoXmlElement;

public class BlancoXliffParser {
    public static void main(final String[] args) {
        new File("./tmp").mkdirs();
        System.out.println(new BlancoXliffParser().parse(new File(
                "./tmp/Test.xlf")));
    }

    public BlancoXliff parse(final File argFileTarget) {
        final BlancoXmlDocument document = new BlancoXmlUnmarshaller()
                .unmarshal(argFileTarget);
        return document2ValueObject(document);
    }

    public BlancoXliff document2ValueObject(final BlancoXmlDocument argDocument) {
        final BlancoXmlElement eleXliff = (BlancoXmlElement) argDocument
                .getChildNodes().get(0);
        if ("xliff".equals(eleXliff.getLocalName()) == false) {
            throw new IllegalArgumentException("不正なXLIFFが与えられました。("
                    + eleXliff.getLocalName() + ")");
        }

        final BlancoXliff xliff = new BlancoXliff();
        xliff
                .setVersion(BlancoXmlBindingUtil.getAttribute(eleXliff,
                        "version"));

        final BlancoXmlElement eleFile = BlancoXmlBindingUtil.getElement(
                eleXliff, "file");
        if (eleFile == null) {
            throw new IllegalArgumentException("不正なXLIFFが与えられました。file見つけられず");
        }

        xliff.setSourceLanguage(BlancoXmlBindingUtil.getAttribute(eleFile,
                "source-language"));
        xliff.setTargetLanguage(BlancoXmlBindingUtil.getAttribute(eleFile,
                "target-language"));

        final BlancoXmlElement eleHeader = BlancoXmlBindingUtil.getElement(
                eleFile, "header");
        if (eleHeader == null) {
            throw new IllegalArgumentException("不正なXLIFFが与えられました。header見つけられず");
        }
        final BlancoXmlElement eleBody = BlancoXmlBindingUtil.getElement(
                eleFile, "body");
        if (eleBody == null) {
            throw new IllegalArgumentException("不正なXLIFFが与えられました。body見つけられず");
        }

        final List toolList = BlancoXmlBindingUtil.getElementsByTagName(
                eleHeader, "tool");
        for (int indexTool = 0; indexTool < toolList.size(); indexTool++) {
            final BlancoXliffTool tool = new BlancoXliffTool();
            final BlancoXmlElement eleTool = (BlancoXmlElement) toolList
                    .get(indexTool);
            tool.setToolId(BlancoXmlBindingUtil
                    .getAttribute(eleTool, "tool-id"));
            tool.setToolName(BlancoXmlBindingUtil.getAttribute(eleTool,
                    "tool-name"));
            xliff.getToolList().add(tool);
        }

        final List transUnitList = BlancoXmlBindingUtil.getElementsByTagName(
                eleBody, "trans-unit");
        for (int indexTransUnit = 0; indexTransUnit < transUnitList.size(); indexTransUnit++) {
            final BlancoXmlElement transUnit = (BlancoXmlElement) transUnitList
                    .get(indexTransUnit);
            final BlancoXliffTransUnit eleTransUnit = new BlancoXliffTransUnit();

            // trans-unitのid属性
            eleTransUnit.setId(BlancoXmlBindingUtil.getAttribute(transUnit,
                    "id"));

            // trans-unitのtranslate属性
            eleTransUnit.setTranslate("no".equals(BlancoXmlBindingUtil
                    .getAttribute(transUnit, "translate")) == false);

            // source要素
            eleTransUnit.setSource(BlancoXmlBindingUtil.getTextContent(
                    transUnit, "source"));

            // target要素
            {
                final BlancoXmlElement target = BlancoXmlBindingUtil
                        .getElement(transUnit, "target");
                if (target != null) {
                    final BlancoXliffTarget eleTarget = new BlancoXliffTarget();
                    eleTransUnit.setTarget(eleTarget);

                    parseTarget(target, eleTarget);
                }
            }

            // note要素
            List noteList = BlancoXmlBindingUtil.getElementsByTagName(
                    transUnit, "note");
            for (int indexNoteList = 0; indexNoteList < noteList.size(); indexNoteList++) {
                final BlancoXmlElement note = (BlancoXmlElement) noteList
                        .get(indexNoteList);
                final BlancoXliffNote eleNote = new BlancoXliffNote();
                eleTransUnit.getNoteList().add(eleNote);

                // xml-lang属性
                final String lang = BlancoStringUtil
                        .null2Blank(BlancoXmlBindingUtil.getAttribute(note,
                                "xml:lang"));
                if (lang.length() > 0) {
                    eleNote.setLang(lang);
                }

                // from属性
                final String from = BlancoStringUtil
                        .null2Blank(BlancoXmlBindingUtil.getAttribute(note,
                                " from"));
                if (from.length() > 0) {
                    eleNote.setFrom(from);
                }

                // note要素テキスト
                eleNote.setText(BlancoXmlBindingUtil.getTextContent(note));

            }

            // alt-trans要素
            List altTransList = BlancoXmlBindingUtil.getElementsByTagName(
                    transUnit, "alt-trans");
            for (int indexAltTrans = 0; indexAltTrans < altTransList.size(); indexAltTrans++) {
                final BlancoXmlElement altTrans = (BlancoXmlElement) altTransList
                        .get(indexAltTrans);
                final BlancoXliffAltTrans eleAltTrans = new BlancoXliffAltTrans();
                eleTransUnit.getAltTransList().add(eleAltTrans);

                // tool-id属性
                final String toolId = BlancoStringUtil
                        .null2Blank(BlancoXmlBindingUtil.getAttribute(altTrans,
                                "tool-id"));
                if (toolId.length() > 0) {
                    eleAltTrans.setToolId(toolId);
                }

                // source要素
                eleAltTrans.setSource(BlancoXmlBindingUtil.getTextContent(
                        altTrans, "source"));

                // target要素
                {
                    final BlancoXmlElement target = BlancoXmlBindingUtil
                            .getElement(altTrans, "target");
                    if (target != null) {
                        final BlancoXliffTarget eleTarget = new BlancoXliffTarget();
                        eleAltTrans.setTarget(eleTarget);

                        parseTarget(target, eleTarget);
                    }
                }

                // note要素
                List altTransNoteList = BlancoXmlBindingUtil
                        .getElementsByTagName(altTrans, "note");
                for (int indexNoteList = 0; indexNoteList < altTransNoteList
                        .size(); indexNoteList++) {
                    final BlancoXmlElement note = (BlancoXmlElement) altTransNoteList
                            .get(indexNoteList);
                    final BlancoXliffNote eleNote = new BlancoXliffNote();
                    eleAltTrans.getNoteList().add(eleNote);

                    // xml-lang属性
                    final String lang = BlancoStringUtil
                            .null2Blank(BlancoXmlBindingUtil.getAttribute(note,
                                    "xml:lang"));
                    if (lang.length() > 0) {
                        eleNote.setLang(lang);
                    }

                    // from属性
                    final String from = BlancoStringUtil
                            .null2Blank(BlancoXmlBindingUtil.getAttribute(note,
                                    " from"));
                    if (from.length() > 0) {
                        eleNote.setFrom(from);
                    }

                    // note要素テキスト
                    eleNote.setText(BlancoXmlBindingUtil.getTextContent(note));

                }
            }

            xliff.getTransUnitList().add(eleTransUnit);
        }
        return xliff;
    }

    private void parseTarget(final BlancoXmlElement target,
            final BlancoXliffTarget eleTarget) {
        eleTarget.setTarget(BlancoXmlBindingUtil.getTextContent(target));

        String lang = BlancoStringUtil.null2Blank(BlancoXmlBindingUtil
                .getAttribute(target, "xml:lang"));
        if (lang.length() > 0) {
            eleTarget.setLang(lang);
        }

        String state = BlancoStringUtil.null2Blank(BlancoXmlBindingUtil
                .getAttribute(target, "state"));
        if (lang.length() > 0) {
            eleTarget.setState(state);
        }
    }
}
