/*******************************************************************************
 * 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.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import blanco.commons.util.BlancoFileUtil;
import blanco.xliff.valueobject.BlancoXliff;
import blanco.xliff.valueobject.BlancoXliffAltTrans;
import blanco.xliff.valueobject.BlancoXliffFile;
import blanco.xliff.valueobject.BlancoXliffHeader;
import blanco.xliff.valueobject.BlancoXliffTool;
import blanco.xliff.valueobject.BlancoXliffTransUnit;

/**
 * XLIFFを操作するためのユーティリティー。
 * 
 * @author IGA Tosiki
 */
public class BlancoXliffUtil {
    /**
     * XLIFF情報のインスタンスを取得します。
     * 
     * 指定されたディレクトリにXLIFFが既にあればそれを利用します。XLIFFがまだ無い場合にはインスタンスを新規に作成します。(ファイル作成は伴いません)
     * 
     * @param argXliffdir
     * @param argBundleSymbolicName
     * @return
     */
    public static BlancoXliff getXliffInstance(final File fileXliffdir,
            final String argBundleSymbolicName) {
        BlancoXliff xliff;
        final File fileXliff = new File(fileXliffdir.getAbsolutePath() + "/"
                + argBundleSymbolicName + ".xlf");
        if (fileXliff.exists()) {
            // 存在する場合には読み込みます。
            xliff = new BlancoXliffParser().parse(fileXliff);
        } else {
            // 存在しない場合には新規作成します。
            xliff = new BlancoXliff();
        }
        return xliff;
    }

    /**
     * XLIFF情報を保存します。
     * 
     * @param xliff
     * @param argXliffdir
     * @param argBundleSymbolicName
     * @return
     * @throws IOException
     */
    public static int saveXliffInstance(final BlancoXliff xliff,
            final File fileXliffdir, final String argBundleSymbolicName)
            throws IOException {
        final File fileXliff = new File(fileXliffdir.getAbsolutePath() + "/"
                + argBundleSymbolicName + ".xlf");
        final ByteArrayOutputStream outStream = new ByteArrayOutputStream(8192);

        new BlancoXliffSerializer().serialize(xliff, outStream);

        return BlancoFileUtil.bytes2FileIfNecessary(outStream.toByteArray(),
                fileXliff);
    }

    /**
     * XLIFFに tool 登録をセットします。
     * 
     * 無ければ追加、既に存在していれば内容を更新します。
     * 
     * @param xliff
     * @param tool
     */
    public static void setTool(final BlancoXliffHeader header,
            final BlancoXliffTool tool) {
        for (int index = 0; index < header.getToolList().size(); index++) {
            final BlancoXliffTool toolLook = (BlancoXliffTool) header
                    .getToolList().get(index);
            if (toolLook.getToolId().equals(tool.getToolId())) {
                // 既に存在する。情報を上書き。
                toolLook.setToolName(tool.getToolName());

                return;
            }
        }

        // そのツールは未登録。内容を追加します。
        header.getToolList().add(tool);
    }

    /**
     * fileを取得します。無ければnullを戻します。
     * 
     * @param xliff
     * @param path
     * @return
     */
    public static BlancoXliffFile getFile(final BlancoXliff xliff,
            final String path) {
        for (int indexFile = 0; indexFile < xliff.getFileList().size(); indexFile++) {
            final BlancoXliffFile file = (BlancoXliffFile) xliff.getFileList()
                    .get(indexFile);
            if (path.equals(file.getOriginal())) {
                // それだ！
                return file;
            }
        }
        // 見つかりませんでした。
        return null;
    }

    /**
     * 指定された id の trans-unit を取得します。
     * 
     * @param xliff
     * @param id
     * @return 見つかればそのオブジェクト。無ければ null。
     */
    public static BlancoXliffTransUnit getTransUnit(final BlancoXliff xliff,
            final String id) {
        for (int indexFile = 0; indexFile < xliff.getFileList().size(); indexFile++) {
            final BlancoXliffFile file = (BlancoXliffFile) xliff.getFileList()
                    .get(indexFile);
            for (int index = 0; index < file.getBody().getTransUnitList()
                    .size(); index++) {
                final BlancoXliffTransUnit transUnit = (BlancoXliffTransUnit) file
                        .getBody().getTransUnitList().get(index);
                if (transUnit.getId().equals(id)) {
                    // 既にあればそれを採用。
                    return transUnit;
                }
            }
        }
        return null;
    }

    /**
     * 指定されたtool-id, source, targetに合致する alt-trans バリューオブジェクトを取得します。
     * 
     * 存在しない場合には null を戻します。
     * 
     * @param transUnit
     * @param toolId
     * @param sourceString
     * @param targetString
     * @return
     */
    public static BlancoXliffAltTrans getAltTrans(
            final BlancoXliffTransUnit transUnit, final String toolId,
            final String sourceString, final String targetString) {
        for (int index = 0; index < transUnit.getAltTransList().size(); index++) {
            final BlancoXliffAltTrans altTrans = (BlancoXliffAltTrans) transUnit
                    .getAltTransList().get(index);
            if (toolId.equals(altTrans.getToolId()) == false) {
                // 他のtool-idのものはスキップします。
                continue;
            }
            if (sourceString.equals(altTrans.getSource())
                    && targetString.equals(altTrans.getTarget().getTarget())) {
                // tool-id, source, target の全てが一致しました。
                // これが求めるべき alt-trans バリューオブジェクトです。
                return altTrans;
            }
        }

        return null;
    }
}
