/*
 * blanco Framework
 * Copyright (C) 2004-2006 IGA Tosiki
 * 
 * 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.stringconverter;

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

import blanco.cg.BlancoCgObjectFactory;
import blanco.cg.BlancoCgSupportedLang;
import blanco.cg.transformer.BlancoCgTransformerFactory;
import blanco.cg.util.BlancoCgLineUtil;
import blanco.cg.util.BlancoCgSourceUtil;
import blanco.cg.valueobject.BlancoCgClass;
import blanco.cg.valueobject.BlancoCgField;
import blanco.cg.valueobject.BlancoCgMethod;
import blanco.cg.valueobject.BlancoCgSourceFile;
import blanco.commons.util.BlancoNameAdjuster;
import blanco.commons.util.BlancoNameUtil;
import blanco.commons.util.BlancoStringUtil;
import blanco.stringconverter.message.BlancoStringConverterMessage;
import blanco.stringconverter.resourcebundle.BlancoStringConverterResourceBundle;
import blanco.stringconverter.valueobject.BlancoStringConverterFieldStructure;
import blanco.stringconverter.valueobject.BlancoStringConverterStructure;

/**
 * 「文字列変換定義書」Excel様式から文字列変換を処理するクラス・ソースコードを生成。
 * 
 * このクラスは、中間XMLファイルからソースコードを自動生成する機能を担います。
 * 
 * @author IGA Tosiki
 */
public class BlancoStringConverterXml2SourceFile {
    /**
     * メッセージ。
     */
    private final BlancoStringConverterMessage fMsg = new BlancoStringConverterMessage();

    /**
     * このプロダクトのリソースバンドルへのアクセスオブジェクト。
     */
    private final BlancoStringConverterResourceBundle fBundle = new BlancoStringConverterResourceBundle();

    /**
     * 出力対象となるプログラミング言語。
     */
    private int fTargetLang = BlancoCgSupportedLang.NOT_DEFINED;

    /**
     * 内部的に利用するblancoCg用ファクトリ。
     */
    private BlancoCgObjectFactory fCgFactory = null;

    /**
     * 内部的に利用するblancoCg用ソースファイル情報。
     */
    private BlancoCgSourceFile fCgSourceFile = null;

    /**
     * 内部的に利用するblancoCg用クラス情報。
     */
    private BlancoCgClass fCgClass = null;

    /**
     * 中間XMLファイルからソースコードを自動生成します。
     * 
     * @param argMetaXmlSourceFile
     *            メタ情報が含まれているXMLファイル。
     * @param argTargetLang
     *            出力対象となるプログラミング言語。
     * @param argDirectoryTarget
     *            ソースコード生成先ディレクトリ (/mainを除く部分を指定します)。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void process(final File argMetaXmlSourceFile,
            final String argTargetLang, final File argDirectoryTarget)
            throws IOException {

        fTargetLang = new BlancoCgSupportedLang().convertToInt(argTargetLang);
        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        case BlancoCgSupportedLang.CS:
        case BlancoCgSupportedLang.JS:
        case BlancoCgSupportedLang.VB:
        case BlancoCgSupportedLang.PHP:
        case BlancoCgSupportedLang.RUBY:
        case BlancoCgSupportedLang.PYTHON:
            break;
        default:
            throw new IllegalArgumentException(fMsg.getMbsci002(argTargetLang));
        }

        final BlancoStringConverterStructure[] structures = new BlancoStringConverterXmlParser()
                .parse(argMetaXmlSourceFile);

        for (int index = 0; index < structures.length; index++) {
            // メタ情報の解析結果をもとにソースコード自動生成を実行します。
            structure2Source(structures[index], argDirectoryTarget);
        }
    }

    /**
     * 収集された情報を元に、ソースコードを自動生成します。
     * 
     * @param argStructure
     *            メタファイルから収集できた処理構造データ。
     * @param argDirectoryTarget
     *            ソースコードの出力先フォルダ。
     */
    public void structure2Source(
            final BlancoStringConverterStructure argStructure,
            final File argDirectoryTarget) {

        // 従来と互換性を持たせるため、/mainサブフォルダに出力します。
        final File fileBlancoMain = new File(argDirectoryTarget
                .getAbsolutePath()
                + "/main");

        fCgFactory = BlancoCgObjectFactory.getInstance();
        fCgSourceFile = fCgFactory.createSourceFile(argStructure.getPackage(),
                null);
        fCgClass = fCgFactory.createClass(argStructure.getName()
                + BlancoStringUtil.null2Blank(argStructure.getSuffix()),
                BlancoStringUtil.null2Blank(argStructure.getDescription()));
        fCgSourceFile.getClassList().add(fCgClass);

        expandField(argStructure);
        expandMethodConvert(argStructure);

        BlancoCgTransformerFactory.getSourceTransformer(fTargetLang).transform(
                fCgSourceFile, fileBlancoMain);
    }

    /**
     * 定数フィールドを展開します。
     * 
     * @param argProcessStructure
     *            メタファイルから収集できた処理構造データ。
     */
    private void expandField(
            final BlancoStringConverterStructure argProcessStructure) {

        String defaultString = null;

        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
            defaultString = "new String[][] {";
            break;
        case BlancoCgSupportedLang.CS:
            defaultString = "new string[][] {";
            break;
        case BlancoCgSupportedLang.JS:
        case BlancoCgSupportedLang.RUBY:
        case BlancoCgSupportedLang.PYTHON:
            defaultString = "[";
            break;
        case BlancoCgSupportedLang.VB:
            defaultString = "{";
            break;
        case BlancoCgSupportedLang.PHP:
            defaultString = "array(";
            break;
        }

        for (int indexField = 0; indexField < argProcessStructure
                .getFieldList().size(); indexField++) {
            final BlancoStringConverterFieldStructure fieldLook = (BlancoStringConverterFieldStructure) argProcessStructure
                    .getFieldList().get(indexField);
            if (indexField != 0) {
                defaultString += ", ";
            }

            switch (fTargetLang) {
            case BlancoCgSupportedLang.JAVA:
                defaultString += "new String[] { "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + " }";
                break;
            case BlancoCgSupportedLang.CS:
                defaultString += "new string[] { "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + " }";
                break;
            case BlancoCgSupportedLang.JS:
                defaultString += "[ "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + " ]";
                break;
            case BlancoCgSupportedLang.VB:
                defaultString += "{ "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + " }";
                break;
            case BlancoCgSupportedLang.PHP:
                defaultString += "array("
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + ")";
                break;
            case BlancoCgSupportedLang.RUBY:
                defaultString += "[ "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang) + " ]";
                break;
            case BlancoCgSupportedLang.PYTHON:
                // Pythonでは１行が長すぎると実行時エラーがおきるようなので
                // 改行しています。
                defaultString += "[ "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getFrom())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + ", "
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgSourceUtil.escapeStringAsSource(fTargetLang,
                                fieldLook.getTo())
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang)
                        + " ]\n";
                break;
            }

            String strComment = "";
            if (fieldLook.getNo() != null) {
                strComment += fBundle
                        .getXml2sourceFileFieldNo(BlancoCgSourceUtil
                                .escapeStringAsLangDoc(fTargetLang, fieldLook
                                        .getNo()));
            }
            if (fieldLook.getDescription() != null) {
                if (strComment.length() > 0) {
                    // NoとDescriptionの間に空白を挿入。
                    strComment += " ";
                }
                strComment += fBundle
                        .getXml2sourceFileDescription(BlancoCgSourceUtil
                                .escapeStringAsLangDoc(fTargetLang, fieldLook
                                        .getDescription()));
            }

            switch (fTargetLang) {
            case BlancoCgSupportedLang.VB:
            case BlancoCgSupportedLang.RUBY:
            case BlancoCgSupportedLang.PYTHON:
                break;
            default:
                if (strComment.length() > 0) {
                    defaultString += "/* " + strComment + " */";
                }
                break;
            }
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        case BlancoCgSupportedLang.CS:
        case BlancoCgSupportedLang.VB:
            defaultString += " }";
            break;
        case BlancoCgSupportedLang.JS:
        case BlancoCgSupportedLang.RUBY:
        case BlancoCgSupportedLang.PYTHON:
            defaultString += " ]";
            break;
        case BlancoCgSupportedLang.PHP:
            defaultString += " )";
            break;
        }

        BlancoCgField cgField = null;
        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        case BlancoCgSupportedLang.CS:
        case BlancoCgSupportedLang.JS:
        case BlancoCgSupportedLang.RUBY:
        default:
            cgField = fCgFactory.createField("STRING_CONVERT_DEF",
                    getTypeString() + "[][]", "文字列置換定義。");
            break;
        case BlancoCgSupportedLang.VB:
            cgField = fCgFactory.createField("STRING_CONVERT_DEF(,)",
                    getTypeString(), "文字列置換定義。");
            break;
        case BlancoCgSupportedLang.PHP:
            cgField = fCgFactory.createField("STRING_CONVERT_DEF",
                    "array[int][int]string", "文字列置換定義。");
            break;
        }
        fCgClass.getFieldList().add(cgField);

        cgField.setAccess("public");
        switch (fTargetLang) {
        default:
            cgField.setStatic(true);
            cgField.setFinal(true);
            break;
        case BlancoCgSupportedLang.VB:
        case BlancoCgSupportedLang.PHP:
            // VBでは２次元配列を定数化できません。
            // PHPでは配列を定数化できません。
            break;
        }
        cgField.setDefault(defaultString);
    }

    /**
     * convertメソッドを展開します。
     * 
     * @param argProcessStructure
     *            メタファイルから収集できた処理構造データ。
     */
    private void expandMethodConvert(
            final BlancoStringConverterStructure argProcessStructure) {

        final BlancoCgMethod cgMethod = fCgFactory.createMethod(
                getMethodName("convert"), "文字列変換定義に従い、文字列を変換します。");
        fCgClass.getMethodList().add(cgMethod);
        cgMethod.getParameterList().add(
                fCgFactory.createParameter("argCheck", getTypeString(),
                        "変換対象の文字列。", true));
        cgMethod.setReturn(fCgFactory.createReturn(getTypeString(),
                "文字列変換定義にしたがって変換された文字列。変換定義にひとつも合致しない場合には元の文字列が戻ります。"));

        final List lineList = cgMethod.getLineList();

        lineList.add(BlancoCgLineUtil.getVariableDeclaration(fTargetLang,
                "wrkString", BlancoNameUtil.trimJavaPackage(getTypeString()),
                BlancoCgLineUtil.getStringLiteralEnclosure(fTargetLang)
                        + BlancoCgLineUtil
                                .getStringLiteralEnclosure(fTargetLang))
                + BlancoCgLineUtil.getTerminator(fTargetLang));

        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "int index = 0", "index < argCheck.length()", ""));
            lineList.add("final String look = argCheck.substring(index)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.CS:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "int index = 0", "index < argCheck.Length", ""));
            lineList.add("string look = argCheck.Substring(index)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.JS:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "var index = 0", "index < argCheck.length", ""));
            lineList.add("var look = argCheck.substring(index)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.VB:
            lineList.add(BlancoCgLineUtil.getForBeginVb(fTargetLang,
                    "index As Integer = 0", "argCheck.length - 1", "0"));
            lineList.add("Dim look As String = argCheck.Substring(index)");
            break;
        case BlancoCgSupportedLang.PHP:
            fCgSourceFile.getImportList().add("mbstring.mb_strlen");
            lineList
                    .add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "arraySize = mb_strlen("
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "argCheck)"
                            + BlancoCgLineUtil.getTerminator(fTargetLang));
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "index = 0", BlancoCgLineUtil
                            .getVariablePrefix(fTargetLang)
                            + "index < "
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "arraySize", ""));
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "look = mb_substr("
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "argCheck, "
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index)" + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.RUBY:
            lineList.add("index = 0");
            lineList.add(BlancoCgLineUtil.getWhileBeginRuby(fTargetLang,
                    "index < argCheck.length()"));
            lineList
                    .add("look = argCheck.slice(index, argCheck.length()-index)");
            break;
        case BlancoCgSupportedLang.PYTHON:
            lineList.add("index = 0");
            lineList.add(BlancoCgLineUtil.getWhileBeginRuby(fTargetLang,
                    "index < len(argCheck)"));
            lineList.add("look = argCheck[index:]");
            break;
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.PYTHON:
            lineList.add(BlancoCgLineUtil.getVariableDeclaration(fTargetLang,
                    "isFound", getTypeBooleanDef(), "False")
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        default:
            lineList.add(BlancoCgLineUtil.getVariableDeclaration(fTargetLang,
                    "isFound", getTypeBooleanDef(), "false")
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "int indexDef = 0", "indexDef < STRING_CONVERT_DEF.length",
                    "indexDef++"));
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.startsWith(STRING_CONVERT_DEF[indexDef][0])"));
            lineList.add("wrkString += STRING_CONVERT_DEF[indexDef][1];");
            lineList.add("index += STRING_CONVERT_DEF[indexDef][0].length();");
            break;
        case BlancoCgSupportedLang.CS:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "int indexDef = 0", "indexDef < STRING_CONVERT_DEF.Length",
                    "indexDef++"));

            // 2006.10.02 t.iga
            // C#.NETのStartsWithに濁音まわりの比較時にバグが含まれている模様。これに対応するためにJavaなどとは異なり
            // Substringを実施したうえに一致比較を行っています。
            lineList.add("string wrkStrComp = look;");
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.Length > STRING_CONVERT_DEF[indexDef][0].Length"));
            lineList
                    .add("wrkStrComp = wrkStrComp.Substring(0, STRING_CONVERT_DEF[indexDef][0].Length);");
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));

            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "STRING_CONVERT_DEF[indexDef][0].Equals(wrkStrComp)"));
            lineList.add("wrkString += STRING_CONVERT_DEF[indexDef][1];");
            lineList.add("index += STRING_CONVERT_DEF[indexDef][0].Length;");
            break;
        case BlancoCgSupportedLang.JS:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "var indexDef = 0", "indexDef < " + fCgClass.getName()
                            + ".STRING_CONVERT_DEF.length", "indexDef++"));

            // 2006.10.04 t.iga
            // JavaScriptのsearchメソッドは正規表現対応であるので、これはblancoStringConverterとしては利用できません。これに対応するためにJavaなどとは異なり
            // substringを実施したうえに一致比較を行っています。
            lineList.add("var wrkStrComp = look;");
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.length > " + fCgClass.getName()
                            + ".STRING_CONVERT_DEF[indexDef][0].length"));
            lineList.add("wrkStrComp = wrkStrComp.substring(0, "
                    + fCgClass.getName()
                    + ".STRING_CONVERT_DEF[indexDef][0].length);");
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));

            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "wrkStrComp === " + fCgClass.getName()
                            + ".STRING_CONVERT_DEF[indexDef][0]"));
            lineList.add("wrkString += " + fCgClass.getName()
                    + ".STRING_CONVERT_DEF[indexDef][1];");
            lineList.add("index += " + fCgClass.getName()
                    + ".STRING_CONVERT_DEF[indexDef][0].length;");
            break;
        case BlancoCgSupportedLang.VB:
            lineList.add(BlancoCgLineUtil.getForBeginVb(fTargetLang,
                    "indexDef As Integer = 0", "STRING_CONVERT_DEF.length -1"));

            lineList.add("Dim wrkStrComp As String = look");
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.length > STRING_CONVERT_DEF(indexDef, 0).Length"));
            lineList
                    .add("wrkStrComp = wrkStrComp.substring(0, STRING_CONVERT_DEF(indexDef, 0).Length)");
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));

            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "wrkStrComp = STRING_CONVERT_DEF(indexDef, 0)"));
            lineList.add("wrkString += STRING_CONVERT_DEF(indexDef, 1)");
            lineList.add("index += STRING_CONVERT_DEF(indexDef, 0).Length");
            break;
        case BlancoCgSupportedLang.PHP:
            lineList.add(BlancoCgLineUtil.getForBeginJava(fTargetLang,
                    "$indexDef = 0",
                    "$indexDef < count($this->STRING_CONVERT_DEF)",
                    "$indexDef++"));

            lineList
                    .add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "wrkStrComp = "
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "look;");
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "mb_strlen($look) > mb_strlen($this->STRING_CONVERT_DEF["
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "indexDef][0])"));
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "wrkStrComp = mb_substr("
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "wrkStrComp, 0, mb_strlen($this->STRING_CONVERT_DEF["
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "indexDef][0]));");
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));

            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "wrkStrComp === $this->STRING_CONVERT_DEF["
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "indexDef][0]"));
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "wrkString = "
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "wrkString "
                    + BlancoCgLineUtil
                            .getStringConcatenationOperator(fTargetLang)
                    + " $this->STRING_CONVERT_DEF["
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "indexDef][1]"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index += mb_strlen($this->STRING_CONVERT_DEF["
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "indexDef][0])"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.RUBY:
            lineList.add(BlancoCgLineUtil.getForBeginRuby(fTargetLang,
                    "indexDef", "0", "STRING_CONVERT_DEF.length-1"));
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.index(STRING_CONVERT_DEF[indexDef][0]) == 0"));
            lineList.add("wrkString += STRING_CONVERT_DEF[indexDef][1]");
            lineList.add("index += STRING_CONVERT_DEF[indexDef][0].length()");
            break;
        case BlancoCgSupportedLang.PYTHON:
            lineList.add(BlancoCgLineUtil.getForBeginPython(fTargetLang,
                    "indexDef", "range(len(self.STRING_CONVERT_DEF))"));
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "look.find(self.STRING_CONVERT_DEF[indexDef][0]) == 0"));
            lineList.add("wrkString += self.STRING_CONVERT_DEF[indexDef][1]");
            lineList.add("index += len(self.STRING_CONVERT_DEF[indexDef][0])");
            break;
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.PYTHON:
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "isFound = True"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        default:
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "isFound = true"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        }

        lineList.add(BlancoCgLineUtil.getForExit(fTargetLang)
                + BlancoCgLineUtil.getTerminator(fTargetLang));
        lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));
        lineList.add(BlancoCgLineUtil.getForEnd(fTargetLang));

        switch (fTargetLang) {
        case BlancoCgSupportedLang.VB:
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "isFound = False"));
            break;
        case BlancoCgSupportedLang.PYTHON:
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang,
                    "isFound == False"));
            break;
        default:
            lineList.add(BlancoCgLineUtil.getIfBegin(fTargetLang, "!"
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "isFound"));
            break;
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        case BlancoCgSupportedLang.JS:
            lineList.add("wrkString += argCheck.charAt(index)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.CS:
        case BlancoCgSupportedLang.VB:
            lineList.add("wrkString += argCheck.Substring(index, 1)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.PHP:
            lineList
                    .add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "wrkString = "
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "wrkString "
                            + BlancoCgLineUtil
                                    .getStringConcatenationOperator(fTargetLang)
                            + " mb_substr("
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "argCheck, "
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "index, 1)"
                            + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.RUBY:
            lineList.add("wrkString += look.slice(/./)"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        case BlancoCgSupportedLang.PYTHON:
            lineList.add("wrkString += unicode(argCheck[index:])[0].encode()"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            break;
        }

        switch (fTargetLang) {
        case BlancoCgSupportedLang.RUBY:
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index = "
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index + look.slice(/./).length()"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));
            break;
        case BlancoCgSupportedLang.PYTHON:
            lineList.add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index = "
                    + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                    + "index + len(unicode(argCheck[index:])[0].encode())"
                    + BlancoCgLineUtil.getTerminator(fTargetLang));
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));
            break;
        default:
            lineList
                    .add(BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "index = "
                            + BlancoCgLineUtil.getVariablePrefix(fTargetLang)
                            + "index + 1"
                            + BlancoCgLineUtil.getTerminator(fTargetLang));
            lineList.add(BlancoCgLineUtil.getIfEnd(fTargetLang));
            break;
        }

        lineList.add(BlancoCgLineUtil.getForEnd(fTargetLang));
        lineList.add("");
        lineList.add(BlancoCgLineUtil.getReturn(fTargetLang, BlancoCgLineUtil
                .getVariablePrefix(fTargetLang))
                + "wrkString" + BlancoCgLineUtil.getTerminator(fTargetLang));
    }

    /**
     * プログラミング言語処理系に合った boolean 型を宣言する際の名称を取得します。
     * 
     * 型の読み替え。
     * 
     * @return
     */
    private final String getTypeBooleanDef() {
        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        default:
            return "boolean";
        case BlancoCgSupportedLang.CS:
            return "bool";
        case BlancoCgSupportedLang.JS:
            return "var";
        case BlancoCgSupportedLang.VB:
            return "Boolean";
        case BlancoCgSupportedLang.PHP:
            return "boolean";
        }
    }

    /**
     * プログラミング言語処理系に合った String 型の名称を取得します。
     * 
     * 型の読み替え。
     * 
     * @return
     */
    private final String getTypeString() {
        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
            return "java.lang.String";
        default:
        case BlancoCgSupportedLang.CS:
            return "string";
        case BlancoCgSupportedLang.JS:
            return "string";
        case BlancoCgSupportedLang.VB:
            return "String";
        case BlancoCgSupportedLang.PHP:
            return "string";
        }
    }

    /**
     * プログラミング言語処理系に合った メソッドの名前変形をおこないます。
     * 
     * メソッド名の読み替え。
     * 
     * @param argMethodName
     *            メソッド名。
     * @return
     */
    private final String getMethodName(final String argMethodName) {
        switch (fTargetLang) {
        case BlancoCgSupportedLang.JAVA:
        default:
            return argMethodName;
        case BlancoCgSupportedLang.CS:
            return BlancoNameAdjuster.toUpperCaseTitle(argMethodName);
        case BlancoCgSupportedLang.JS:
            return argMethodName;
        }
    }
}
