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

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;

import blanco.commons.util.BlancoStringUtil;
import blanco.properties.manifest.valueobject.BlancoPropertiesManifest;
import blanco.properties.resourcebundle.BlancoPropertiesResourceBundle;

/**
 * マニフェスト情報 ([MANIFEST.MF]ファイル) を作成するクラス。
 * 
 * TODO nl_fragment.properties 生成は別クラスに分割すべきかどうか検討すること。
 * 
 * @author IGA Tosiki
 */
public class BlancoPropertiesManifestWriter {
    /**
     * プログラムで利用するリソースバンドル。
     */
    private final BlancoPropertiesResourceBundle fBundle = new BlancoPropertiesResourceBundle();

    protected String fTargetLocale = "ja";

    public void setTargetLocale(final String arg) {
        fTargetLocale = arg;
    }

    /**
     * マニフェスト情報一式を書き出します。
     * 
     * @param manifest
     *            マニフェスト。
     * @param targetDir
     *            出力先となるディレクトリ。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void write(final BlancoPropertiesManifest manifest,
            final File targetDir) throws IOException {
        if (targetDir.exists() == false) {
            targetDir.mkdirs();
        }

        // nl_fragment.properties を出力。
        writeFragmentProperties(manifest, targetDir);

        // META-INF/MANIFEST.MF を出力。
        {
            final File metaInfDir = new File(targetDir.getAbsolutePath()
                    + "/META-INF");
            if (metaInfDir.exists() == false) {
                metaInfDir.mkdirs();
            }

            // 必要に応じて項目の値を上書きしてセット。
            final BlancoPropertiesManifest manifestWrk = new BlancoPropertiesManifest();
            manifestWrk.setBundleName("%nlFragmentName");
            manifestWrk.setBundleSymbolicName(manifest.getBundleSymbolicName()
                    + "." + fBundle.getSymbolicNameSuffixWithoutLocale()
                    + fTargetLocale + " ;singleton=true");
            manifestWrk.setBundleVersion(manifest.getBundleVersion());
            manifestWrk.setBundleVendor("%nlProviderName");
            manifestWrk.setFragmentHost(manifest.getBundleSymbolicName());
            manifestWrk.setBundleLocalization("nl_fragment");
            writeManifestMfInternal(manifestWrk, new File(targetDir
                    .getAbsolutePath()
                    + "/META-INF/MANIFEST.MF"));
        }
    }

    /**
     * nl_fragment.properties を出力します。
     * 
     * @param manifest
     *            マニフェスト。
     * @param targetDir
     *            出力先となるディレクトリ。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    private void writeFragmentProperties(
            final BlancoPropertiesManifest manifest, final File targetDir)
            throws IOException {
        final BufferedWriter writer = new BufferedWriter(new FileWriter(
                targetDir.getAbsolutePath() + "/nl_fragment.properties"));
        writer.write("#");
        writer.newLine();

        // 注意: プロバイダ名は上書きしています。
        writer.write("nlProviderName=" + fBundle.getManifestBundleVendor());
        writer.newLine();

        String bundleName = manifest.getBundleName();
        if (bundleName.startsWith("%")) {
            bundleName = manifest.getBundleSymbolicName();
        }

        {
            final Locale locTarget = new Locale(fTargetLocale);
            writer.write("nlFragmentName=" + bundleName + " "
                    + locTarget.getDisplayLanguage(Locale.US) + " NLS Support");
        }

        writer.newLine();
        writer.close();
    }

    /**
     * META-INF/MANIFEST.MF を出力します。
     * 
     * @param manifest
     *            マニフェスト。
     * @param outFile
     *            出力先ファイル。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    private void writeManifestMfInternal(
            final BlancoPropertiesManifest manifest, final File outFile)
            throws IOException {

        final BufferedWriter writer = new BufferedWriter(
                new FileWriter(outFile));
        writer.write("Manifest-Version: " + manifest.getManifestVersion());
        writer.newLine();

        writer.write("Bundle-Name: " + manifest.getBundleName());
        writer.newLine();

        if (BlancoStringUtil.null2Blank(manifest.getBundleSymbolicName())
                .length() > 0) {
            writer.write("Bundle-SymbolicName: "
                    + manifest.getBundleSymbolicName());
            writer.newLine();
        }

        if (BlancoStringUtil.null2Blank(manifest.getBundleVersion()).length() > 0) {
            writer.write("Bundle-Version: " + manifest.getBundleVersion());
            writer.newLine();
        }

        if (BlancoStringUtil.null2Blank(manifest.getBundleVendor()).length() > 0) {
            writer.write("Bundle-Vendor: " + manifest.getBundleVendor());
            writer.newLine();
        }

        if (BlancoStringUtil.null2Blank(manifest.getFragmentHost()).length() > 0) {
            writer.write("Fragment-Host: " + manifest.getFragmentHost());
            writer.newLine();
        }

        if (BlancoStringUtil.null2Blank(manifest.getBundleLocalization())
                .length() > 0) {
            writer.write("Bundle-Localization: "
                    + manifest.getBundleLocalization());
            writer.newLine();
        }

        writer.close();
    }
}
