/*
 * @(#)MapperType1.java
 *
 * RID-X : Mapper
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2002/02/15
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 */

package jp.co.nri.rid.mapper;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Vector;
import org.w3c.dom.*;
import org.apache.xpath.XPathAPI;

import jp.co.nri.rid.error.RidException;
import jp.co.nri.rid.error.*;


import jp.co.iti.fagot.doc.DocManager;
import jp.co.iti.fagot.util.ZProperties;
import jp.co.iti.fagot.util.ZString;


/**
 * Mapper(Type2)
 */
public class MapperType2 extends MapperBase {

    /** エラーメッセージ **/
    private static String pr_errorString;

    /*　ROOT　ELEMENTの定義：RID　*/
    /** RidProjectの定義 **/
    private static final String ROOT_ELEMENT  = "RidProject";
    /** MapAttrの定義 **/
    private static final String MAP_ATTR      = "MapAttr";
    /** MapAttrDataの定義 **/
    private static final String MAP_ATTR_DATA = "MapAttrData";
    /** Rid_Tmpの定義 **/
    private static final String RID_TMP       = "Rid_Tmp";
    /** MapDataの定義 **/
    private static final String MAPDATA       = "MapData";

    /*　属性の定義　*/
    /** srcTagの定義 **/
    private static final String SRC_TAG       = "srcTag";
    /** srcKeyの定義 **/
    private static final String SRC_KEY       = "srcKey";
    /** dataTagの定義 **/
    private static final String DATA_TAG      = "dataTag";
    /** dataKeyの定義 **/
    private static final String DATA_KEY      = "dataKey";
    /** inTagの定義 **/
    private static final String IN_TAG        = "inTag";
    /** outAttrの定義 **/
    private static final String OUT_ATTR      = "outAttr";
    /** nameの定義 **/
    private static final String NAME          = "name";


/**
  * コンストラクタ
  *
  */
    public MapperType2() {
        //クリア
        pr_errorString = "";
    }


/**
  * (Mapper_Type2)
  *
  * テンプレートファイル（HTML)の<Rid_Tmp>タグを
　* DATAドキュメントの値に置換して、指定されたファイルに出力する
  *
  * @param  String      in_file         INPUTファイル   (HTML形式)
  * @param  Document　  data_doc        DATAドキュメント(XML 形式)
  * @param  String      out_file        OUTPUTファイル  (HTML形式)
  *
  * @return boolean     true(成功) / false (失敗)
  */
    public boolean Type2(String in_file, Document data_doc, String out_file)  throws RidException {

        boolean ret = false;
        Vector  data_lst = new Vector();
        RidMessage ridMsg = new RidMessage();

        try {
            //ファイル有無
            if (checkFile(in_file)) {
                //DATAドキュメントの解析
                ret = type2DataDocParser(data_doc, data_lst);
                if (ret) {
                    //生成
                    ret = type2Generate(in_file, data_lst, out_file);
                }
            }
            //イメージファイルをコピーする
            if (ret){
              MapperResource  mr = new MapperResource();
              mr.imageFileCopy(in_file, out_file);
            }
        }
        catch(Exception e){
            String err_msg = ridMsg.Error("E4002"," (Mapper) " + e.getMessage());
            if (err_msg.indexOf("Filename too long") != -1) {
                err_msg =  ridMsg.Error("E4003"," (Mapper) " + e.getMessage());
            }
            throw new RidException(err_msg);
        }
        return ret;
   }

/**
  * (Mapper_Type2)
  *
  * テンプレートファイル（HTML)の<Rid_Tmp>タグを
　* DATAドキュメントの値に置換して、指定されたファイルに出力する
  *
  * @param  String      in_file         INPUTファイル   (HTML形式)
  * @param  Document　  data_doc        DATAドキュメント(XML 形式)
  * @param  String      out_file        OUTPUTファイル  (HTML形式)
  *
  * @return boolean     true(成功) / false (失敗)
  */
    public boolean TypeScript(String in_file, Document data_doc, String out_file)  throws RidException {

        boolean ret = false;
        Vector  data_lst = new Vector();
        RidMessage ridMsg = new RidMessage();

        try {
            //ファイル有無
            if (checkFile(in_file)) {
                //DATAドキュメントの解析
                ret = type2DataDocParser(data_doc, data_lst);
                if (ret) {
                    //生成
                    ret = type2Generate(in_file, data_lst, out_file);
                }
            }
        }
        catch(Exception e){
            String err_msg = ridMsg.Error("E4002"," (Mapper) " + e.getMessage());
            if (err_msg.indexOf("Filename too long") != -1) {
                err_msg =  ridMsg.Error("E4003"," (Mapper) " + e.getMessage());
            }
            throw new RidException(err_msg);
        }
        return ret;
   }



/**
  * (Mapper_Type2)
  * データファイルの解析
  *
  * @param  String      data_file       データファイル名
  * @param  Vector      data_lst        DataItemクラスの配列
  *
  * @return boolean     true(成功) / false(失敗)
  */
    public boolean type2DataDocParser(Document data_doc, Vector data_lst) throws Exception {


        XmlUtil xu = new XmlUtil();
        boolean ret = false;

        // データXMLファイルのルートエレメントを取得する
        Element root_elem = root_elem = data_doc.getDocumentElement();
        if (!checkRootElement(root_elem, ROOT_ELEMENT)) {
            String msg = "Root element name is different.";
            setErrorString(msg);
            root_elem = null;
        }

        if(root_elem != null) {
            NodeList data_elem_lst = XPathAPI.selectNodeList(root_elem, "*");
            for (int i =0; i < data_elem_lst.getLength(); i++) {
                Element data_elem = (Element)data_elem_lst.item(i);

                // ADD Data List
                DataItem data = new DataItem();
                data.tagName  = RID_TMP;
                data.keyName  = data_elem.getNodeName();
                data.inData   = xu.getTextValue(data_elem);
                data.outAttr  = "";
                data_lst.add(data);
            }
            ret = true;
        }
        return ret;
    }



/**
  * (Mapper_Type2)
  * TYPE2の生成
  *
  * @param  String      in_file         入力ファイル名
  * @param  Vector      data_lst        DataItemクラスの配列
  * @param  String      out_file        出力入力ファイル名
  *
  * @return boolean     true(成功) / false(失敗)
  */
    public boolean type2Generate(String in_file, Vector data_lst, String out_file) throws Exception{

        boolean ret = false;

        char str[] = new char[256];

        // 入力ファイルから<RID_TMP>タグの情報を抜出す
        Vector inTag_lst = new Vector();
        templateFileParser(in_file, inTag_lst);

        // INPUTファイルのオープン
        InputStreamReader InData=new InputStreamReader(new FileInputStream(in_file));

        // OUTOUTファイルのオープン
        OutputStreamWriter outWriter = new OutputStreamWriter(new FileOutputStream(out_file));

        int pos = 0;
        for ( int n = 0; n < inTag_lst.size(); n ++ ) {
            TagItem inTag = (TagItem)inTag_lst.elementAt(n);

            // <Rid_Tmp>タグの最初の位置まで出力する
            while ((InData.read(str, 0, 1)) != -1) {
                if (pos < inTag.sPos) {
                    outWriter.write(str, 0, 1);
                } else {
                    pos++;
                    break;
                }
                pos++;
            }

            // Rid_TmpののNAME属性と同じ
            for ( int m = 0; m < data_lst.size(); m ++ ) {
                DataItem data = (DataItem)data_lst.elementAt(m);
                if (inTag.keyName.compareToIgnoreCase(data.keyName) == 0)
                    outWriter.write(data.inData, 0, data.inData.length());
            }

            // </Rid_Tmp>タグを読飛ばす
            while ((InData.read(str, 0, 1)) != -1) {
                if (pos < inTag.ePos) {
                    //読み飛ばし;
                } else {
                    pos++;
                    break;
                }
                pos++;
            }
        }

        // 最後まで読込む
        while ((InData.read(str, 0, 1)) != -1) {
            outWriter.write(str, 0, 1);
        }

        // ファイルクローズ
        InData.close();
        outWriter.close();
        
        return true;
   }


/**
  * (Mapper_Type2)
  * Templateファイルから<RID_TMP>の情報を抜出す
  *
  * @param  String      in_file         入力ファイル名
  * @param  Vector      data_lst        DataItemクラスの配列
  *
  * @return void
  */
    private void templateFileParser(String in_file, Vector inTag_lst) throws Exception {

        //in_file　Parser
        Vector tag_lst = new Vector();
        htmlParser(in_file, tag_lst);

        // HTMLタグの配列から、MapItemのsrcTagタグを抜出す
        for (int n = 0; n < tag_lst.size(); n ++ ) {
            // HTMLタグ情報の取得
            TagItem htmlTag = (TagItem)tag_lst.elementAt(n);

            //大文字に変換
            String tagStringUp  = htmlTag.tagString.toUpperCase();
            String srcTagUp     = "<" + RID_TMP.toUpperCase();

            //srcTagタグの判断
            if (tagStringUp.indexOf(srcTagUp) != -1) {

                //srcKeyの取得
                String srcKey = getAttrValue(htmlTag.tagString, NAME);

                //
                if (srcKey != ""){
                  TagItem srcTag = new TagItem();
                  srcTag.tagName     = RID_TMP;
                  srcTag.keyName     = srcKey;
                  srcTag.tagString   = htmlTag.tagString;
                  srcTag.sPos        = htmlTag.sPos;
                  srcTag.ePos        = htmlTag.ePos;
                  inTag_lst.add(srcTag);
                }
            }
        }
  }

/**
  * ファイルが存在するかどうか、読み込み可能かどうかを確認する
  *
  * @param  String      in_file         入力Lファイル名
  *
  * @return boolean     true(存在する) / false (存在しない)
  */
    public boolean checkFile(String in_file) {

        boolean ret = true;

        if (!isFile(in_file)) {
            String msg = "no such source file: \"" + in_file + "\"";
            setErrorString(msg);
            ret =  false;
        }
        return ret;
    }


/**
  * エラーメッセージの設定
  *
  * @param  String      errorString     エラーメッセージ
  * @return void
  */
    private void setErrorString(String errorString) {
        pr_errorString = errorString;
    }

/**
  * エラーメッセージの取得
  *
  * @return String      エラーメッセージ
  */
    public String getErrorString() {
        return pr_errorString;
    }

/****************************************************************************************************************/




}