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

import java.io.File;
import java.io.OutputStream;

import blanco.commons.util.BlancoStringUtil;
import blanco.tmx.valueobject.BlancoTmx;
import blanco.tmx.valueobject.BlancoTmxBody;
import blanco.tmx.valueobject.BlancoTmxHeader;
import blanco.tmx.valueobject.BlancoTmxTu;
import blanco.tmx.valueobject.BlancoTmxTuv;
import blanco.xml.bind.BlancoXmlMarshaller;
import blanco.xml.bind.valueobject.BlancoXmlAttribute;
import blanco.xml.bind.valueobject.BlancoXmlCharacters;
import blanco.xml.bind.valueobject.BlancoXmlDocument;
import blanco.xml.bind.valueobject.BlancoXmlElement;

/**
 * LISA TMX をシリアライズするクラス。
 * 
 * @author IGA Tosiki
 */
public class BlancoTmxSerializer {
    private BlancoXmlCharacters charNewLineWithIndent0 = null;

    private BlancoXmlCharacters charNewLineWithIndent2 = null;

    private BlancoXmlCharacters charNewLineWithIndent4 = null;

    private BlancoXmlCharacters charNewLineWithIndent6 = null;

    private BlancoXmlCharacters charNewLineWithIndent8 = null;

    private BlancoXmlCharacters charNewLineWithIndent10 = null;

    private boolean fIndent = true;

    public BlancoTmxSerializer() {
        charNewLineWithIndent0 = new BlancoXmlCharacters();
        charNewLineWithIndent2 = new BlancoXmlCharacters();
        charNewLineWithIndent4 = new BlancoXmlCharacters();
        charNewLineWithIndent6 = new BlancoXmlCharacters();
        charNewLineWithIndent8 = new BlancoXmlCharacters();
        charNewLineWithIndent10 = new BlancoXmlCharacters();
        charNewLineWithIndent0.setValue("\n");
        charNewLineWithIndent2.setValue("\n  ");
        charNewLineWithIndent4.setValue("\n    ");
        charNewLineWithIndent6.setValue("\n      ");
        charNewLineWithIndent8.setValue("\n        ");
        charNewLineWithIndent10.setValue("\n          ");
    }

    public void setIndent(final boolean indent) {
        fIndent = indent;
    }

    /**
     * TMX情報をストリームに出力します。
     * 
     * @param argTmx
     * @param outStream
     */
    public void serialize(final BlancoTmx argTmx, final OutputStream outStream) {
        new BlancoXmlMarshaller().marshal(valueObject2Document(argTmx),
                outStream);
    }

    /**
     * TMX情報をファイルに出力します。
     * 
     * @param argTmx
     * @param argFileTarget
     */
    public void serialize(final BlancoTmx argTmx, final File argFileTarget) {
        new BlancoXmlMarshaller().marshal(valueObject2Document(argTmx),
                argFileTarget);
    }

    /**
     * 与えられたTMX情報から blancoXml DOMツリーを作成します。
     * 
     * @param argTmx
     * @return
     */
    public BlancoXmlDocument valueObject2Document(final BlancoTmx argTmx) {
        final BlancoXmlDocument document = new BlancoXmlDocument();

        final BlancoXmlElement eleTmx = new BlancoXmlElement();
        eleTmx.setQName("tmx");
        document.getChildNodes().add(eleTmx);

        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleTmx.getAtts().add(attr);
            attr.setQName("version");
            attr.setValue(argTmx.getVersion());
        }

        eleTmx.getChildNodes().add(charNewLineWithIndent2);

        serializeHeader(argTmx, eleTmx);

        eleTmx.getChildNodes().add(charNewLineWithIndent2);

        serializeBody(argTmx, eleTmx);

        eleTmx.getChildNodes().add(charNewLineWithIndent0);

        return document;
    }

    private void serializeHeader(final BlancoTmx argTmx,
            final BlancoXmlElement eleTmx) {
        final BlancoTmxHeader header = argTmx.getHeader();

        final BlancoXmlElement eleHeader = new BlancoXmlElement();
        eleTmx.getChildNodes().add(eleHeader);
        eleHeader.setQName("header");
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("creationtool");
            attr.setValue(header.getCreationtool());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("creationtoolversion");
            attr.setValue(header.getCreationtoolversion());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("segtype");
            attr.setValue(header.getSegtype());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("o-tmf");
            attr.setValue(header.getOTmf());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("adminlang");
            attr.setValue(header.getAdminlang());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("srclang");
            attr.setValue(header.getSrclang());
        }
        {
            final BlancoXmlAttribute attr = new BlancoXmlAttribute();
            eleHeader.getAtts().add(attr);
            attr.setQName("datatype");
            attr.setValue(header.getDatatype());
        }

        // eleHeader.getChildNodes().add(charNewLineWithIndent2);
    }

    private void serializeBody(final BlancoTmx argTmx,
            final BlancoXmlElement eleTmx) {
        final BlancoTmxBody body = argTmx.getBody();

        final BlancoXmlElement eleBody = new BlancoXmlElement();
        eleTmx.getChildNodes().add(eleBody);
        eleBody.setQName("body");

        for (int indexTu = 0; indexTu < body.getTuList().size(); indexTu++) {
            final BlancoTmxTu tu = (BlancoTmxTu) body.getTuList().get(indexTu);
            final BlancoXmlElement eleTu = new BlancoXmlElement();
            if (fIndent) {
                eleBody.getChildNodes().add(charNewLineWithIndent4);
            } else {
                eleBody.getChildNodes().add(charNewLineWithIndent0);
            }
            eleBody.getChildNodes().add(eleTu);
            eleTu.setQName("tu");
            if (BlancoStringUtil.null2Blank(tu.getTuid()).length() > 0) {
                final BlancoXmlAttribute attr = new BlancoXmlAttribute();
                eleTu.getAtts().add(attr);
                attr.setQName("tuid");
                attr.setValue(tu.getTuid());
            }

            for (int indexTuv = 0; indexTuv < tu.getTuvList().size(); indexTuv++) {
                final BlancoTmxTuv tuv = (BlancoTmxTuv) tu.getTuvList().get(
                        indexTuv);
                final BlancoXmlElement eleTuv = new BlancoXmlElement();
                if (fIndent) {
                    eleTu.getChildNodes().add(charNewLineWithIndent6);
                } else {
                    eleTu.getChildNodes().add(charNewLineWithIndent0);
                }
                eleTu.getChildNodes().add(eleTuv);
                eleTuv.setQName("tuv");
                {
                    final BlancoXmlAttribute attr = new BlancoXmlAttribute();
                    eleTuv.getAtts().add(attr);
                    attr.setQName("xml:lang");
                    attr.setValue(tuv.getLang());
                }

                if (fIndent == false) {
                    eleTuv.getChildNodes().add(charNewLineWithIndent0);
                }

                final BlancoXmlElement eleSeg = new BlancoXmlElement();
                eleTuv.getChildNodes().add(eleSeg);
                eleSeg.setQName("seg");
                {
                    final BlancoXmlCharacters xmlString = new BlancoXmlCharacters();
                    xmlString.setValue(tuv.getSeg());
                    eleSeg.getChildNodes().add(xmlString);
                }
            }
            if (fIndent) {
                eleTu.getChildNodes().add(charNewLineWithIndent4);
            } else {
                eleTu.getChildNodes().add(charNewLineWithIndent0);
            }
        }

        if (fIndent) {
            eleBody.getChildNodes().add(charNewLineWithIndent2);
        } else {
            eleBody.getChildNodes().add(charNewLineWithIndent0);
        }
    }
}
