/*
 * Copyright 2006 Mask@ Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function BackgroundLoad(){
}

/* Initialization of background load */
BackgroundLoad.init = function(){

  /* initialize the internal variables */
  BackgroundLoad.layoutHash = new Object();  // key: layout name, value: parent dom object or temporary dom object
  BackgroundLoad.containerHash = new Object();  // key: dom object's id, value: the name of the layout shown in the dom object
  BackgroundLoad.divUniqueID = 0;
  BackgroundLoad.HIDE_ZONE = {top:3000, left:3000};

  /* create the progress bar */
  BackgroundLoad.progressBarWindow = document.createElement("div");
  BackgroundLoad.progressBarWindow.style.position = "absolute";
  BackgroundLoad.progressBarWindow.style.zIndex = 32767;
  BackgroundLoad.progressBarWindow.style.top = "100px";
  BackgroundLoad.progressBarWindow.style.left = "100px";
  BackgroundLoad.progressBarWindow.style.border = "3px solid black";
  BackgroundLoad.progressBarWindow.style.width = "300px";
  BackgroundLoad.progressBarWindow.style.height = "50px";
  BackgroundLoad.progressBarWindow.style.padding = "1em";
  BackgroundLoad.progressBarWindow.style.backgroundColor = "pink";
}

/* show the progress bar */
BackgroundLoad.showProgressBar = function(){

  if(!BackgroundLoad.isProgressBarLoaded){
    document.body.appendChild(BackgroundLoad.progressBarWindow);
    BackgroundLoad.isProgressBarLoaded = true;
  }

  /* show it in the middle of the browser window */
  BackgroundLoad.progressBarWindow.style.top = 
    (document.body.clientHeight - BackgroundLoad.progressBarWindow.offsetHeight) / 2;
  BackgroundLoad.progressBarWindow.style.left =
    (document.body.clientWidth - BackgroundLoad.progressBarWindow.offsetWidth) / 2;

}

/* hide the progress bar */
BackgroundLoad.hideProgressBar = function(){

  BackgroundLoad.progressBarWindow.style.top = BackgroundLoad.HIDE_ZONE.top;
  BackgroundLoad.progressBarWindow.style.left = BackgroundLoad.HIDE_ZONE.left;

}

/* load layout in background */
/* parameter: {'fileName':<layout xml file name>, 'refParentObjText':<親DIVタグのDOMのテキスト表現>} の配列 */
BackgroundLoad.loadLayout = function(args){

  BackgroundLoad.args = args;  // TODO: setTimeoutで引数に渡せなかった。後で直す
  BackgroundLoad.showProgressBar();
  
  BackgroundLoad.progressBarWindow.innerHTML = args.length + "つのファイルの取得・コンパイル中";

  setTimeout(BackgroundLoad.loadLayout2, 500);  // Pause for 0.5 second for the progress bar to be shown
}

BackgroundLoad.loadLayout2 = function(){
  var args = BackgroundLoad.args;  // TODO: setTimeoutで引数に渡せなかった。後で直す
  BackgroundLoad.args = null;  // TODO: setTimeoutで引数に渡せなかった。後で直す
  
  BackgroundLoad.layoutNameArray = new Array();
  
  for (var i = 0; i < args.length; i++){
    BackgroundLoad.loadLayout3(args[i]);
  }

  BackgroundLoad.progressBarWindow.innerHTML = "";
  for (var i = 0; i < args.length; i++){
    BackgroundLoad.progressBarWindow.innerHTML += "<div>[" + BackgroundLoad.layoutNameArray[i] + "] <span id='_maskat_layout_loadStatusMessage_" + BackgroundLoad.layoutNameArray[i] + "'>ロード待ち</span></div>";
  }
  
  BackgroundLoad.nextLayoutIndex = 0; 
  BackgroundLoad.loadLayout3_1();
}

BackgroundLoad.loadLayout3_1 = function(){

  if (BackgroundLoad.nextLayoutIndex > BackgroundLoad.layoutNameArray.length - 1){
    BackgroundLoad.hideProgressBar();
  }
  else{
    var statusMessageDOM = document.getElementById("_maskat_layout_loadStatusMessage_" + BackgroundLoad.layoutNameArray[BackgroundLoad.nextLayoutIndex]);
    statusMessageDOM.innerHTML = "ロード中";
    setTimeout(BackgroundLoad.loadLayout3_2, 500);  // Pause for 0.5 second for the screen to be updated
  }
}

BackgroundLoad.loadLayout3_2 = function(){
  loadLayout(BackgroundLoad.layoutNameArray[BackgroundLoad.nextLayoutIndex]);
  
  var statusMessageDOM = document.getElementById("_maskat_layout_loadStatusMessage_" + BackgroundLoad.layoutNameArray[BackgroundLoad.nextLayoutIndex]);
  statusMessageDOM.innerHTML = "ロード完了";


  BackgroundLoad.nextLayoutIndex++;
  setTimeout(BackgroundLoad.loadLayout3_1, 500);  // Pause for 0.5 second for the screen to be updated
}


/* Helper function of BackgroundLoad.loadLayout */
BackgroundLoad.loadLayout3 = function(arg){
  var xmlhttp;
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) {
      xmlhttp = false;
    }
  }
  if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  if (xmlhttp) {
    xmlhttp.open("GET", "http://localhost:8080/maskat/"+arg.fileName, false);
    xmlhttp.send(null);
    if (xmlhttp.status == 200) {
      BackgroundLoad.loadLayout4(xmlhttp.responseText, arg.refParentObjText);
    } else {
      maskat.getFWLog().error("リソースの取得に失敗しました");
    }
  }
  else {
    maskat.getFWLog().error('非同期通信モジュールの取得に失敗しました。\n処理を停止します。');
    return;
  }
}

/* Helper function of BackgroundLoad.loadLayout */
BackgroundLoad.loadLayout4 = function(layoutXML, refParentObjText){
  // TODO: What if the layout has already been loaded

  var sourceDoc = CrossBrowser.XML2DOM(layoutXML);
//  var layoutName = CrossBrowser.getElementsByTagName(sourceDoc, "layout")[0].getAttribute("name");
  var layoutName = sourceDoc.getElementsByTagName("layout").item(0).getAttribute("name");
  var refParentObj = eval(refParentObjText);

  // if refParentObj a "div" dom object
  if (refParentObj.tagName != null && refParentObj.tagName.toUpperCase() == "DIV"){

    /* create a "div" dom object which is located out of the screen, 
       and load layout into that dom object(the div is out of the screen so that the layout is "invisible") */

    var layoutDIV = document.createElement("div");
    layoutDIV.id = "_maskat_" + refParentObj.id + "_" + BackgroundLoad.divUniqueID++;
    layoutDIV.style.position = "absolute";
    layoutDIV.style.top = BackgroundLoad.HIDE_ZONE.top;
    layoutDIV.style.left = BackgroundLoad.HIDE_ZONE.left;
    layoutDIV.style.width = refParentObj.style.width;
    layoutDIV.style.height = refParentObj.style.height;
    document.body.appendChild(layoutDIV);

    var rialtoJSSrc;
    try{
      rialtoJSSrc = maskat.interpretLayoutXML(sourceDoc, 'document.getElementById("' + layoutDIV.id + '")');
    } catch(e){
      maskat.handleFrameworkError("",e);
    }
    maskat.loadJSSrc(rialtoJSSrc);
    
    BackgroundLoad.layoutNameArray.push(layoutName);

    BackgroundLoad.layoutHash[layoutName] = {"refParentObj":refParentObj, "layoutDIV":layoutDIV};
    BackgroundLoad.containerHash[refParentObj.id] = null;

  }
  // TODO: if refParentObj is a rialto container object
  

}

BackgroundLoad.unloadLayout = function(layoutName){
  if (BackgroundLoad.layoutHash[layoutName] != undefined){
    // TODO: remove all the components belong to the layout

    BackgroundLoad.hideLayout(layoutName);

    var layoutDIV = BackgroundLoad.layoutHash[layoutName].layoutDIV;
    layoutDIV.parentNode.removeChild(layoutDIV);

    delete BackgroundLoad.layoutHash[layoutName];
  }
  else {
    maskat.getFWLog().error(layoutName + "レイアウトはロードされていないので、アンロードできません。");
  }
}

BackgroundLoad.showLayout = function(layoutName){
  if (BackgroundLoad.layoutHash[layoutName] != undefined){
    var currentLayoutName = BackgroundLoad.containerHash[BackgroundLoad.layoutHash[layoutName].refParentObj.id];
    if (currentLayoutName != null){
      // hide the current layout
      BackgroundLoad.hideLayout(currentLayoutName);
    }
    
    var layoutDIV = BackgroundLoad.layoutHash[layoutName].layoutDIV;
    var refParentObj = BackgroundLoad.layoutHash[layoutName].refParentObj;
    layoutDIV.style.top = refParentObj.style.top;
    layoutDIV.style.left = refParentObj.style.left;
    
    BackgroundLoad.containerHash[BackgroundLoad.layoutHash[layoutName].refParentObj.id] = layoutName;
  }
  else {
    maskat.getFWLog().error(layoutName + "レイアウトはロードされていないので、表示できません。");
  }
}

BackgroundLoad.hideLayout = function(layoutName){
  if (BackgroundLoad.layoutHash[layoutName] != undefined){
    var currentLayoutName = BackgroundLoad.containerHash[BackgroundLoad.layoutHash[layoutName].refParentObj.id];
    /* Only when the name specified is the name of the layout currently displayed */
    if (currentLayoutName == layoutName){
      var layoutDIV = BackgroundLoad.layoutHash[layoutName].layoutDIV;
      layoutDIV.style.top = BackgroundLoad.HIDE_ZONE.top;
      layoutDIV.style.left = BackgroundLoad.HIDE_ZONE.left;
    
      BackgroundLoad.containerHash[BackgroundLoad.layoutHash[layoutName].refParentObj.id] = null;
    }
  }
  else {
    maskat.getFWLog().error(layoutName + "レイアウトはロードされていないので、非表示にできません。");
  }
}

BackgroundLoad.init();

/*
 * Cross Browser utility function class
 */

function CrossBrowser(){
}

// Set the internal variables indicating browser type
CrossBrowser.init = function(){
  CrossBrowser.isIE = false;
  CrossBrowser.isFF = false;

  if (navigator.appName == "Microsoft Internet Explorer"){
    CrossBrowser.isIE = true;
  }
  else if (navigator.appName == "Netscape"){
    CrossBrowser.isFF = true;
  }
  else {
    maskat.getFWLog().fatal("お使いのブラウザは動作保障対象外です。本システムは正しく機能しません。");
  }
}

// transfer the parameter string into a xml dom object
CrossBrowser.XML2DOM = function(srcXML){
  var desDOM;

  if (CrossBrowser.isIE){
    desDOM = new ActiveXObject("MSXML2.DOMDocument");
    desDOM.async = false;
    desDOM.resolveExternals = false;
    desDOM.validateOnParse = false;
    desDOM.loadXML(srcXML);
  }
  else if (CrossBrowser.isFF){
    desDOM = (new DOMParser()).parseFromString(srcXML, "text/xml");
  }

  return desDOM;
}

// The cross browser implementation of getElementsByTagName(IE: namespace is needed, Firefox: namespace is not needed)
CrossBrowser.getElementsByTagName = function(srcDOM, tagName){
  if (CrossBrowser.isIE){
    return(srcDOM.getElementsByTagName(srcDOM.documentElement.prefix + ":" + tagName));
  }
  else if (CrossBrowser.isFF){
    return(srcDOM.getElementsByTagName(tagName));
  }
}

// transfer a xml dom object into xml string
CrossBrowser.getInnerContents = function(srcElm){
  if (CrossBrowser.isIE){
    return(srcElm.xml);
  }
  else if (CrossBrowser.isFF){
    return((new XMLSerializer).serializeToString(srcElm));
  }
}

CrossBrowser.init();

 
//// Dynamically load JavaScript file ////

maskat.loadJSFile_i = 0;  // "script" tag is given a unique id by using this variable

maskat.loadJSFile = function(fileName){
  var elementScript = document.createElement("script");
  document.acsync = false;
  elementScript.id = "forDynamicJSFileLoad" + maskat.loadJSFile_i++;  
  elementScript.src = fileName;
  document.getElementsByTagName("head").item(0).appendChild(elementScript);
//  elementScript.parentNode.replaceChild(elementScript, elementScript);
}

//// Dynamically load CSS file ////

maskat.loadCSSFile_i = 0;  // "script" tag is given a unique id by using this variable

maskat.loadCSSFile = function(fileName){
  var elementLink = document.createElement("link");
  elementLink.id = "forDynamicCSSFileLoad" + maskat.loadCSSFile_i++;  
  elementLink.href = fileName;
  document.getElementsByTagName("head").item(0).appendChild(elementLink);
//  elementLink.parentNode.replaceChild(elementLink, elementLink);
}

//// Dynamically load JavaScript source ////

maskat.loadJSSrc_i = 0; // "script" tag is given a unique id by using this variable

maskat.loadJSSrc = function(jsSrc){
  var elementScript = document.createElement("script");
  document.async = false;
  elementScript.id = "forDynamicJSSrcLoad" + maskat.loadJSSrc_i++;  
  elementScript.text = jsSrc;
  document.getElementsByTagName("head").item(0).appendChild(elementScript);
  document.getElementsByTagName("head").item(0).removeChild(elementScript);
//  elementScript.parentNode.replaceChild(elementScript, elementScript);
}

maskat.layouts = new Object;

/**
 * manipulate the UI on a per-layout basis
 */
maskat.Layout = function(name){
    this.name = name;
    this.components=new Object;
    this.componentsLevel1=new Object;
    this.isLoaded = false;
    maskat.layouts[this.name] = this;
}

maskat.Layout.prototype.hide=function(){
    for (key in this.componentsLevel1){
        if (this.componentsLevel1[key]!=null && (typeof this.componentsLevel1[key].setVisible == "function")){
            this.componentsLevel1[key].setVisible(false);
        }
    }
}
maskat.Layout.prototype.show=function(){
    if (this.isLoaded == false){
        //load the layout
        loadLayout(this.name);
        this.isLoaded = true;
        return;
    }
    for (key in this.componentsLevel1){
        if (this.componentsLevel1[key]!=null && (typeof this.componentsLevel1[key].setVisible == "function")){
            this.componentsLevel1[key].setVisible(true);
        }
    }
}
maskat.Layout.prototype.remove=function(){
    for (key in this.componentsLevel1){
        if (this.componentsLevel1[key]!=null && (typeof this.components[key].remove == "function")){
            this.componentsLevel1[key].remove();
        }
    }
    delete maskat.layouts[this.name];
}

maskat.showLayout = function(layoutName){
    var layoutObj = maskat.layouts[layoutName];
    if (layoutObj != null){
        layoutObj.show();
    }
}

maskat.hideLayout = function(layoutName){
    var layoutObj = maskat.layouts[layoutName];
    if (layoutObj != null){
        layoutObj.hide();
    }
}

maskat.removeLayout = function(layoutName){
    var layoutObj = maskat.layouts[layoutName];
    if (layoutObj != null){
        layoutObj.remove();
    }
}
/**
 * Notice: the parameter targetDiv should not be a dom object, but a string 
 * by which we could get a dom object. For example: "document.getElement('div')"
 */
maskat.loadLayoutFile = function(layoutDefFileName, targetDiv, bToShow) {
    try{
        var layoutDOM = maskat.loadXMLFile(layoutDefFileName);
        var rialtoJSSrc; // javascript source after the transformation
        rialtoJSSrc = maskat.interpretLayoutXML(layoutDOM, targetDiv);
        maskat.loadJSSrc(rialtoJSSrc);

        if (bToShow==true || arguments.length <= 2){
            var layoutElements = layoutDOM.getElementsByTagName("layout");
            for (var i = 0; i < layoutElements.length; i++){
              var layoutName = layoutElements[i].getAttribute("name");
              maskat.layouts[layoutName].show();
              // add KeyNavi
              document.onkeydown=maskat.setForcus;
            }
        }
        document.onselectstart = function(){return true};
    }catch(e){
        maskat.handleFrameworkError("レイアウトファイルロードにエラーが発生しました。",e);
    }
}

maskat.loadEventFile = function(fileName){
  try {
    var eventDefDOM = maskat.loadXMLFile(fileName).documentElement;

    maskat.loadLayoutEvents(eventDefDOM);
    maskat.loadComponentEvents(eventDefDOM);
  }
  catch (e){
    maskat.handleFrameworkError("イベント処理中エラーが発生しました。",e);
  }
}

maskat.loadLayoutEvents = function(eventDefDOM){
    var eventNode = maskat.xpath(eventDefDOM, 'event[@id="onload"]');
    if (eventNode){
      var IDs = {component:null, event:"onload"};
      var onloadFunc = maskat.autoGenEventFunc(eventNode, eventDefDOM, IDs, null);
      onloadFunc();
    }
}

maskat.loadComponentEvents = function(eventDefDOM){
    var componentNodes = maskat.xpath(eventDefDOM, 'component');
    for (var i = 0; i < componentNodes.length; i++){
      var componentNode = componentNodes[i];
      var componentID = maskat.xpath(componentNode, '@id');
      var eventNodes = maskat.xpath(componentNode, 'event');
      for (var j = 0; j < eventNodes.length; j++){
        var eventNode = eventNodes[j];
        var eventID = maskat.xpath(eventNode, '@id');
      
        var IDs = {component:componentID, event:eventID};
      
        var componentObj = null;
        try {
          componentObj = eval(IDs.component);
//          var layoutName = maskat.xpath(eventDefDOM, '@layoutName');
//          componentObj = maskat.layouts[layoutName].components[componentID];
        }
        catch (e){
          throw new MaskatError({name: "EventXML Syntax Error",
                                 message: "コンポーネント'" + IDs.component + "'が画面定義XMLに定義されていません。",
                                 fileName: "maskat.js",
                                 functionName: "maskat.loadComponentEvents"});
        }
        componentObj[IDs.event] = maskat.autoGenEventFunc(eventNode, eventDefDOM, IDs, componentObj);
        maskat.getFWLog().trace("コンポーネント[" + componentID + "]の[" + eventID + "]はバインディングされました。");
      }
    }
}


//generate a processing function for the event node.
maskat.autoGenEventFunc = function(eventNode, eventDefDOM, IDs, hostComponent){
  try {
  
    // the processing of event tag
    var eventRefID = maskat.xpath(eventNode, '@ref');
    if (eventRefID){
      var eventRefNode = maskat.xpath(eventDefDOM, 'eventRef[@id="' + eventRefID + '"]');
      if (eventRefNode){
        for (var i = 0; i < eventRefNode.childNodes.length; i++){
          eventNode.appendChild(eventRefNode.childNodes[i].cloneNode(true));
        }
        // eventNode.removeAttribute("ref");  // ref属性を二度と利用できなくする
      }
      else {
        throw new MaskatError({name: "EventXML Syntax Error",
                               message: "id値'" + eventRefID + "'を持つeventRef要素が見つかりません。",
                               fileName: "maskat.js",
                               functionName: "maskat.loadComponentEvents"});
      }
    }
  
    // processing of the <event type="local" ...> tag
    if (maskat.xpath(eventNode, '@type') == "local"){
      return function(x){
        try {
          maskat.getFWLog().trace("コンポーネント[" + IDs.component + "]の[" + IDs.event + "]イベントが発行される");
          maskat.startFunc(eventNode, IDs);
          
          var validator = maskat.getValidator(false);
  
          // processing of <result> tag
          var resultNodes = maskat.xpath(eventNode, 'result');
          if (resultNodes.length == 1){
            var resultNode = resultNodes[0];
            var targetNodes = maskat.xpath(resultNode, 'target');
            for (var i = 0; i < targetNodes.length; i++){
              var targetNode = targetNodes[i];
              try {
                maskat.parseLocalTarget(targetNode, validator);
              }
              catch (e){
                if (e instanceof maskat.ValidationError){
                  validator.acceptError(e);
                }
                else {
                  throw e;
                }
              }
              if (validator.errors.length > 0){
                if (maskat.validationErrorHandler){
                  maskat.validationErrorHandler(validator.errors);
                }
                return;
              }
            }
          }
  
          maskat.finishFunc(eventNode, IDs);
        }
        catch (e){
          if (e instanceof MaskatProcessInterruption){
            // Do Nothing
          }else
              maskat.handleFrameworkError("イベント実行時にエラーが発生しました。",e);
        }
      }
    }
  
    // processing of <event type="remote" ...> tag
    else {
      return function(x){
        try {
          maskat.getFWLog().trace("コンポーネント[" + IDs.component + "]の[" + IDs.event + "]イベントが発行される");
          maskat.startFunc(eventNode, IDs);
          
          var validator = maskat.getValidator(false);

          // create the XML to be sent
          var sendXML;
          var paramNodes = maskat.xpath(eventNode, 'param');
          if (paramNodes.length == 1){
            var paramNode = paramNodes[0];
            var rootNode = maskat.xpath(paramNode, '@rootNode');
            var sourceNodes = maskat.xpath(paramNode, 'source');
          
            sendXML = '<' + rootNode;
            var ns = maskat.xpath(eventNode, 'param[1]/@ns');
            if (ns){
              sendXML += ' xmlns="' + ns + '"';
            }
            sendXML += '>';
            
            for (var i = 0; i < paramNode.childNodes.length; i++){
              var paramChildNode = paramNode.childNodes[i];
              if (paramChildNode.nodeType != 1){
                continue;
              }
              

              var parserFunc = maskat.intprSendTele;
              if (paramChildNode.prefix && paramChildNode.prefix != ""){
                var parserFuncName = "maskat." + paramChildNode.prefix + "SendTeleParser";
                parserFunc = eval(parserFuncName);
                if (!parserFunc){
                  throw new MaskatError({name: "Extended Syntax Error",
                                         message: "独自拡張タグ'" + paramChildNode.nodeName + "'を利用するには専用パーサとして'" + parserFuncName + "'関数を定義する必要があります。",
                                         fileName: "maskat.js",
                                         functionName: "maskat.autoGenEventFunc"});
                }
              }

              try{
                sendXML += parserFunc(paramChildNode, validator);
              }
              catch (e){
                if (e instanceof maskat.ValidationError){
                  validator.acceptError(e);
                }
                else {
                  throw e;
                }
              }
              if (validator.errors.length > 0){
                if (maskat.validationErrorHandler){
                  maskat.validationErrorHandler(validator.errors);
                }
                return;
              }
            }
            
            sendXML += '</' + rootNode + '>';

            var soap = maskat.xpath(paramNode, '@soap');
            if (soap=="true"){
                sendXML = maskat.soap.wrapMessage(sendXML,paramNode);
            }

            sendXML = '<?xml version="1.0" encoding="UTF-8"?>' + sendXML;
          }

          maskat.asyncTele(sendXML, eventNode, eventDefDOM, IDs, soap, hostComponent);
        }
        catch (e){
          // Output the log message here.
          // これより上にエラーをthrowできないので(呼び出し元はWebブラウザとなる)、ここでログを出力する
          if (e instanceof MaskatProcessInterruption){
            // Do Nothing
          }else
              maskat.handleFrameworkError("イベント実行時にエラーが発生しました。",e);
        }
      }
    }
  }
  catch (e){
    throw e;
  }
}

maskat.parseLocalTarget = function(targetNode, validator){
  try {
    var inName = maskat.xpath(targetNode, '@in');
    var inObj = maskat.getObjByName(inName);
    var inObjWrap;
    if (inObj){
      inObjWrap = new ObjWrapper(inObj);
    }

    var outName = maskat.xpath(targetNode, '@out');
    var outObj = maskat.getObjByName(outName);
    var outObjWrap;
    if (outObj){
      outObjWrap = new ObjWrapper(outObj);
    }

    //find an appropriate "worker" by the workType attribute.
    var workType = maskat.xpath(targetNode, '@workType');
    if (workType!=null){
        var worker = ObjWrapper.findLocalWorker(workType);
        if (worker==null){
            throw new MaskatError({name: "teleTypeエラー",
                             message: "workType:["+workType+"]は定義されていませんでした。",
                             fileName: "maskat.js",
                             functionName: "maskat.parseLocalTarget"});
        }
        worker.work(outObj,inObj,targetNode);
        return;
    }

    var typeName = maskat.xpath(targetNode, '@type');

    if (!inName && outObjWrap){
      // clear the out object's content
      outObjWrap.clear();
    }
    else if (inObjWrap && outObjWrap && (maskat.isRialtoObj(outObj) || !outObjWrap.isSingleDataObj())){
      //if outObj is a javascript object, the setValue cannot function. So avoid this.
      var value = inObjWrap.getSingleValue();
      if (value && value != ""){
        if (typeName && typeName != ""){
          var descName = maskat.xpath(targetNode, '@desc');
          var minName = maskat.xpath(targetNode, '@min');
          var maxName = maskat.xpath(targetNode, '@max');
          var regexp = maskat.xpath(targetNode, '@regexp');

          validator.validate(inName, value, typeName, descName, minName, maxName, regexp);
        }
     
        // TODO: check in and out are all "single value object"(like string,number)
        maskat.getFWLog().trace("["+outName+"]に単一値["+value+"]をセットしました。");
        outObjWrap.setSingleValue(value);
      }
      else {
        if (typeName == "required"){
          var vTarget = new Object;
          vTarget.desc = descName;
          validator.acceptError(new maskat.ValidationError(vTarget, "入力してください。"));
        }
        else {
          return;
        }
      }
    }
    else if (inObjWrap && outName && 
       ((outObjWrap==null) || (!maskat.isRialtoObj(outObj) && outObjWrap.isSingleDataObj() ))){
      //if outObj is a javascript object
      var value = inObjWrap.getSingleValue();
      if (value && value != ""){
        if (typeName && typeName != ""){
          var descName = maskat.xpath(targetNode, '@desc');
          var minName = maskat.xpath(targetNode, '@min');
          var maxName = maskat.xpath(targetNode, '@max');
          var regexp = maskat.xpath(targetNode, '@regexp');

          validator.validate(inName, value, typeName, descName, minName, maxName, regexp);
        }

        //surround the value with quotation("), in case that value is the name of a variable or const like "true", "window".
        var statement = outName + " = \"" + value + "\";";
        maskat.getFWLog().trace("ローカルマッピング："+statement);
        eval(statement);
      }
      else {
        if (typeName == "required"){
          var vTarget = new Object;
          vTarget.desc = descName;
          validator.acceptError(new maskat.ValidationError(vTarget, "入力してください。"));
        }
        else {
          return;
        }
      }
    }    
    else {
      throw new MaskatError({name: "Mapping Error",
                             message: "in'" + inName + "'からout'" + outName + "'へのマッピングに対応していません。",
                             fileName: "maskat.js",
                             functionName: "maskat.parseLocalTarget"});
    }
  }
  catch (e){
    throw e;
  }
}

maskat.LEFTBRACKETREG = new RegExp("<","g");
maskat.RIGHTBRACKETREG = new RegExp(">","g");
maskat.AMPREG = new RegExp("\&","g");

maskat.toXMLData = function(value){
   value = ""+value;
   value = value.replace(maskat.AMPREG,"&amp;");
   value = value.replace(maskat.LEFTBRACKETREG,"&lt;");
   value = value.replace(maskat.RIGHTBRACKETREG,"&gt;");
   return value;;
}

maskat.intprSendTele = function(sourceNode, validator){
  try {
    var objName = maskat.xpath(sourceNode, '@obj');
    var objObj = maskat.getObjByName(objName);

    if (objObj == null){
      throw new MaskatError({name: "Mapping Error",
                             message: "送信元オブジェクト'" + objName + "'が未定義です。",
                             fileName: "maskat.js",
                             functionName: "maskat.intprSendTele"});
    }
    
    var teleType = maskat.xpath(sourceNode,"@teleType");
    if (teleType!=null){
        var teleMaker = ObjWrapper.findTeleMaker(teleType);
        if (teleMaker==null){
            throw new MaskatError({name: "teleTypeエラー",
                             message: "sourceの属性teleType:["+teleType+"]は定義されていませんでした。",
                             fileName: "maskat.js",
                             functionName: "maskat.intprSendTele"});
            
        }
        return teleMaker.make(objObj,validator,sourceNode);
    }
    
    var objObjWrap = new ObjWrapper(objObj);

    if (objObjWrap.isSingleDataObj()){
      //// 単一値を送信
      
      var value = objObjWrap.getSingleValue();

      var typeName = maskat.xpath(sourceNode, '@type');
      var descName = maskat.xpath(sourceNode, '@desc');

      var sendBlankElementName = maskat.xpath(sourceNode, '@sendBlankElement');

      // If it is of an empty value, then send it only when sendBlankElementName == "true"
      if ((value!=null && value != "") || sendBlankElementName == "true"){
        var nodeName = maskat.xpath(sourceNode, '@node');
        
        var minName = maskat.xpath(sourceNode, '@min');
        var maxName = maskat.xpath(sourceNode, '@max');
        
        var regexp = maskat.xpath(sourceNode, '@regexp');
        
        validator.validate(objName, value, typeName, descName, minName, maxName, regexp);
        return "<" + nodeName + ">" + maskat.toXMLData(value) + "</" + nodeName + ">";
      }
      else {
        if (typeName == "required"){
          var vTarget = new Object;
          vTarget.desc = descName;
          validator.acceptError(new maskat.ValidationError(vTarget, "入力してください。"));
        }
        else {
          return "";
        }
      }
    }
    else if (objObjWrap.isMultiDataObj()){
      var fromkeyName = maskat.xpath(sourceNode, '@fromkey');
      var idxRefName = maskat.xpath(sourceNode, '@idxRef');

      if (fromkeyName){
        // the value of the specified column of the selected line is sent

        var selectedIndex = objObjWrap.getSelectedIndex();
        if (selectedIndex != -1){
        
          var targetObjWrap = objObjWrap;
        
          var idxRefName = maskat.xpath(sourceNode, '@idxRef');  // TODO: 二重宣言
          var idxRefObj = maskat.getObjByName(idxRefName);
          if (idxRefObj){
            var idxRefObjWrap = new ObjWrapper(idxRefObj);
            if (!idxRefObjWrap.isMultiDataObj()){
              throw new MaskatError({name: "Mapping Error",
                                     message: "idxRefは複数データ型オブジェクトを指定して下さい",  // TODO:more detailed
                                     fileName: "maskat.js",
                                     functionName: "maskat.intprSendTele"});
            }
            targetObjWrap = idxRefObjWrap;
          }

          var value = targetObjWrap.getValueFromMultiData(selectedIndex, fromkeyName);
         
          var sendBlankElementName = maskat.xpath(sourceNode, '@sendBlankElement');
      
          if ((value && value != "") || sendBlankElementName == "true"){
            var nodeName = maskat.xpath(sourceNode, '@node');
            return "<" + nodeName + ">" + maskat.toXMLData(value) + "</" + nodeName + ">";
          }
        }
      }
      else if (idxRefName){
        // send the data of the selected line

        if (objObjWrap.isMultiSelect()){
          var childNodeName = maskat.xpath(sourceNode, '@childNode');
          if (!childNodeName){
            throw new MaskatError({name: "EventXML Syntax Error",
                                   message: "複数行選択データの送信マッピングの際には、childNode属性の指定が必須です。",  // TODO:詳細に
                                   fileName: "maskat.js",
                                   functionName: "maskat.intprSendTele"});
          }
          var nodeName = maskat.xpath(sourceNode, '@node');
          
          var indexArray = objObjWrap.getSelectedIndexes();
          
          var bindNodes = maskat.xpath(sourceNode, 'bind');
          if (bindNodes.length == 0){
            return "";
          }
          var bindMapping = new Object();
          for (i = 0; i < bindNodes.length; i++){
            var bindNode = bindNodes[i];
            var fromkeyValue = maskat.xpath(bindNode, '@fromkey');
            var nodeValue = maskat.xpath(bindNode, '@node');
            bindMapping[fromkeyValue] = new Array;
            bindMapping[fromkeyValue][0] = nodeValue;
            if (maskat.xpath(bindNode, '@sendBlankElement')=="true"){
                bindMapping[fromkeyValue][1] = true;
            }else{
                bindMapping[fromkeyValue][1] = false;
            }
          }

          var targetObjWrap = objObjWrap;

          var idxRefName = maskat.xpath(sourceNode, '@idxRef');
          var idxRefObj = maskat.getObjByName(idxRefName);
          if (idxRefObj){
            var idxRefObjWrap = new ObjWrapper(idxRefObj);
            if (!idxRefObjWrap.isMultiDataObj()){
              throw new MaskatError({name: "Mapping Error",
                                     message: "idxRefは複数データ型オブジェクトを指定して下さい",  // TODO:詳細に
                                     fileName: "maskat.js",
                                     functionName: "maskat.intprSendTele"});
            }
            targetObjWrap = idxRefObjWrap;
          }
          
          var resultXML = "";

          //var sendBlankElementName = maskat.xpath(sourceNode, '@sendBlankElement');

          for (var i = 0; i < indexArray.length; i++){
            var resultXMLRow = "";
            for (var fromkeyValue in bindMapping){
              var value = targetObjWrap.getValueFromMultiData(indexArray[i], fromkeyValue);
              var sendBlankElement = bindMapping[fromkeyValue][1];
              if ((value && value != "") || sendBlankElement == true){
                resultXMLRow += "<" + bindMapping[fromkeyValue][0] + ">" + maskat.toXMLData(value) + "</" + bindMapping[fromkeyValue][0] + ">";
              }
            }
            if (resultXMLRow != ""){
              resultXMLRow = "<" + childNodeName + ">" + resultXMLRow + "</" + childNodeName + ">";
            }
            resultXML += resultXMLRow;
          }
          if (resultXML != "" && nodeName!=null && nodeName!=""){
            resultXML = "<" + nodeName + ">" + resultXML + "</" + nodeName + ">";
          }
          
          return resultXML;
        }
        else {
          //single selection
          var index = objObjWrap.getSelectedIndex();
          if (index == -1){
            return "";
          }
          
          var nodeName = maskat.xpath(sourceNode, '@node');
          
          var bindNodes = maskat.xpath(sourceNode, 'bind');
          if (bindNodes.length == 0){
            return "";
          }
          var bindMapping = new Object();
          for (i = 0; i < bindNodes.length; i++){
            var bindNode = bindNodes[i];
            var fromkeyValue = maskat.xpath(bindNode, '@fromkey');
            var nodeValue = maskat.xpath(bindNode, '@node');
            bindMapping[fromkeyValue] = new Array;
            bindMapping[fromkeyValue][0] = nodeValue;
            if (maskat.xpath(bindNode, '@sendBlankElement')=="true"){
                bindMapping[fromkeyValue][1] = true;
            }else{
                bindMapping[fromkeyValue][1] = false;
            }
          }
          
          var targetObjWrap = objObjWrap;

          var idxRefName = maskat.xpath(sourceNode, '@idxRef');
          var idxRefObj = maskat.getObjByName(idxRefName);
          if (idxRefObj){
            var idxRefObjWrap = new ObjWrapper(idxRefObj);
            if (!idxRefObjWrap.isMultiDataObj()){
              throw new MaskatError({name: "Mapping Error",
                                     message: "idxRefは複数データ型オブジェクトを指定して下さい",  // TODO:詳細に
                                     fileName: "maskat.js",
                                     functionName: "maskat.intprSendTele"});
            }
            targetObjWrap = idxRefObjWrap;
          }
          
          var resultXML = "";
          
          //var sendBlankElementName = maskat.xpath(sourceNode, '@sendBlankElement');

          for (var fromkeyValue in bindMapping){
            var value = targetObjWrap.getValueFromMultiData(index, fromkeyValue);
            var sendBlankElement = bindMapping[fromkeyValue][1];
            if ((value && value != "") || sendBlankElement == true){
              resultXML += "<" + bindMapping[fromkeyValue][0] + ">" + maskat.toXMLData(value) + "</" + bindMapping[fromkeyValue][0] + ">";
            }
          }

          if (nodeName!=null && nodeName!="") 
             resultXML = "<" + nodeName + ">" + resultXML + "</" + nodeName + ">";
  
          return resultXML;
        }
      }
      else {
        // send all the datas of a plural data

        var childNodeName = maskat.xpath(sourceNode, '@childNode');
        if (childNodeName){
          // TODO: MaskatError
        }
        var nodeName = maskat.xpath(sourceNode, '@node');
      
        var bindNodes = maskat.xpath(sourceNode, 'bind');
        if (bindNodes.length == 0){
          return "";
        }
        var bindMapping = new Object();
        for (var i = 0; i < bindNodes.length; i++){
          var bindNode = bindNodes[i];
          var fromkeyValue = maskat.xpath(bindNode, '@fromkey');
          var nodeValue = maskat.xpath(bindNode, '@node');
          bindMapping[fromkeyValue] = new Array;
          bindMapping[fromkeyValue][0] = nodeValue;
            if (maskat.xpath(bindNode, '@sendBlankElement')=="true"){
                bindMapping[fromkeyValue][1] = true;
            }else{
                bindMapping[fromkeyValue][1] = false;
            }
        }

        var resultXML = "";
        
        //var sendBlankElementName = maskat.xpath(sourceNode, '@sendBlankElement');

        for (i = 0; i < objObjWrap.getRowNum(); i++){
          var resultXMLRow = "";
          for (var fromkeyValue in bindMapping){
            var value = objObjWrap.getValueFromMultiData(i, fromkeyValue);
            var sendBlankElement = bindMapping[fromkeyValue][1];
            if ((value && value != "") || sendBlankElement == true){
              resultXMLRow += "<" + bindMapping[fromkeyValue][0] + ">" + maskat.toXMLData(value) + "</" + bindMapping[fromkeyValue][0] + ">";
            }
          }
          if (resultXMLRow != ""){
            resultXMLRow = "<" + childNodeName + ">" + resultXMLRow + "</" + childNodeName + ">";
          }
          resultXML += resultXMLRow;
        }
        if (resultXML != "" && nodeName!=null && nodeName!=""){
          resultXML = "<" + nodeName + ">" + resultXML + "</" + nodeName + ">";
        }
        return resultXML;
      }
    }
    return "";
  }
  catch (e){
    throw e;
  }
}

maskat.toParamStr = function(obj){
    if (obj==null || obj==undefined){
        return "";
    }
    return obj.toString();
}


maskat.intprRecvTele = function(eventNode, teleDOM){
  try {
    var eventType = maskat.xpath(eventNode, '@type');
    var resultNodes = maskat.xpath(eventNode, 'result');
    var resultNode;
    if (resultNodes.length == 1){
      resultNode = resultNodes[0];
    }
    
    if (teleDOM.nodeName == "errors"){
      var onErrorTele;
      if (resultNode){
        onErrorTele = maskat.xpath(resultNode, '@onErrorTele');
      }
      
      if (onErrorTele){
        try {
          eval(onErrorTele + "(teleDOM);");
        }
        catch (e){
          throw new MaskatError({name: "onErrorTele Error",
                                 message: "onErrorTele関数が定義されていません。",
                                 fileName: "maskat.js",
                                 functionName: "maskat.intprRecvTele"});
        }
      }
      else {
        // process it with the defaule error handling method processErrorTele
        maskat.processErrorTele(teleDOM);
      }
      throw new MaskatProcessInterruption(
          {name: "intprRecvTele Function Interruption",
           message: "エラー電文処理関数実行後の処理停止",
           fileName: "maskat.js",
           functionName: "maskat.intprRecvTele"});
    }
    else if (resultNode) {
      var rootNode = maskat.xpath(resultNode, '@rootNode');
      var soap = maskat.xpath(resultNode, '@soap');
      if (soap=="true"){
          teleDOM = maskat.soap.unwrapDOM(teleDOM,resultNode);
      }
      
      if (teleDOM.nodeName != rootNode){
        throw new MaskatError({name: "Received Tele Error",
                               message: "受信電文XMLのルートノード名'" + teleDOM.nodeName + "'とイベント定義XMLで指定した受信電文XMLのルートノード名'" + rootNode + "'が一致していません。",
                               fileName: "maskat.js",
                               functionName: "maskat.intprRecvTele"});
      }
      else{
        var eventNodeType = maskat.xpath(eventNode, '@type');
        var targetNodes = maskat.xpath(resultNode, 'target');
        for (var i = 0; i < targetNodes.length; i++){
          var targetNode = targetNodes[i];
          var targetNodeType = maskat.xpath(targetNode, '@type');
          if (targetNodeType != "local" && eventNodeType != "local"){
            maskat.parseRemoteTarget(targetNode, teleDOM);
          }
          else {
            maskat.parseLocalTarget(targetNode);
          }
        }
      }
    }
  }
  catch (e){
    throw e;
  }
}

maskat.parseRemoteTarget = function(targetNode, teleDOM){
  try {
    var outName = maskat.xpath(targetNode, '@out');
    var outObj = maskat.getObjByName(outName);
    var outObjWrap;
    if (outObj){
      outObjWrap = new ObjWrapper(outObj);
    }

    //if teleType is presented, then find the corresponding teleconsumer to parse the xml
    var teleType = maskat.xpath(targetNode, '@teleType');
    if (teleType!=null){
        var pluggableTeleConsumer = ObjWrapper.findTeleConsumer(teleType);
        if (pluggableTeleConsumer==null){
            throw new MaskatError({name: "teleTypeエラー",
                             message: "teleType:["+teleType+"]は定義されていませんでした。",
                             fileName: "maskat.js",
                             functionName: "maskat.parseRemoteTarget"});
        }
        pluggableTeleConsumer.consume(outObj,maskat.xpath(teleDOM, maskat.xpath(targetNode, '@in')));
        return;
    }

    // Check if the data from the received xml can be set into the target object.
    var isInSingleData = false;
    var isInMultiData = false;
    var isOutJSObj = false;
    var isOutSingleData = false;
    var isOutMultiData = false;
    if (maskat.xpath(targetNode, '@inkey')){
      isInMultiData = true;
    }
    else {
      isInSingleData = true;
    }
    if (!outObjWrap || outObjWrap.isJSObj()){
      isOutJSObj = true;
    }
    if (outObjWrap && outObjWrap.isSingleDataObj()){
      isOutSingleData = true;
    }
    else if (outObjWrap && outObjWrap.isMultiDataObj()){
      isOutMultiData = true;
    }
    if (!(isOutJSObj || (isInSingleData && isOutSingleData) || (isInMultiData && isOutMultiData))){
      var inDataType = "未対応型";
      var outDataType = "未対応型";
      if (isInSingleData){
        inDataType = "単一データ型";
      }
      else if (isInMultiData){
        inDataType = "複数データ型";
      }
      if (isOutSingleData && isOutMultiData){
        outDataType = "単一/複数両用データ型";
      }
      else if (isOutSingleData){
        outDataType = "単一データ型";
      }
      else if (isOutMultiData){
        outDataType = "複数データ型";
      }
      throw new MaskatError({name: "Mapping Error",
                             message: "受信電文のデータ形式(" + inDataType + ")と、出力先オブジェクトの受け入れ可能データ形式(" + outDataType + ")が一致していません。",
                             fileName: "maskat.js",
                             functionName: "maskat.parseRemoteTarget"});
    }

    // get the data from the received xml.
    var inData;
    if (isInSingleData){
      inData = maskat.xpath(teleDOM, maskat.xpath(targetNode, '@in') + '/text()');
    }
    else if (isInMultiData){
      var i;
      var bindNodes = maskat.xpath(targetNode, 'bind');
      var bindMapping;
      if (bindNodes.length != 0){
        bindMapping = new Object();
        for (i = 0; i < bindNodes.length; i++){
          var bindNode = bindNodes[i];
          var tokeyValue = maskat.xpath(bindNode, '@tokey');
          var nodeValue = maskat.xpath(bindNode, '@node');
          bindMapping[nodeValue] = tokeyValue;
        }
      }
 
      var inValue = maskat.xpath(targetNode, '@in');
      var inkeyValue = maskat.xpath(targetNode, '@inkey');
      var xpath;
      if (inValue==null || inValue==""){
          xpath = inkeyValue;
      }else{
          xpath = inValue + "[1]/" + inkeyValue;
      }
      var teleRowNodes = maskat.xpath(teleDOM, xpath);
      if (teleRowNodes.length == 0){
        // No data from the received xml.
        return;
      }

      var inData = new Array(teleRowNodes.length);
      for (i = 0; i < inData.length; i++){
        inData[i] = new Object();
      }

      if (bindMapping){
        for (i = 0; i < teleRowNodes.length; i++){
          var teleRowNode = teleRowNodes[i];
          for (var nodeValue in bindMapping){
            var colNodes = maskat.xpath(teleRowNode, nodeValue);
            if (colNodes.length == 1){
              inData[i][bindMapping[nodeValue]] = maskat.xpath(colNodes[0], "text()");
            }
          }
        }
      }
      else {
        for (i = 0; i < teleRowNodes.length; i++){
          var teleRowNode = teleRowNodes[i];
          for (var j = 0; j < teleRowNode.childNodes.length; j++){
            if (teleRowNode.childNodes[j].nodeType != 1){
              continue;
            }
            if (teleRowNode.childNodes[j].hasChildNodes())
                inData[i][teleRowNode.childNodes[j].nodeName] = teleRowNode.childNodes[j].childNodes[0].nodeValue;
            else
                inData[i][teleRowNode.childNodes[j].nodeName] = "";
          }
        }
      }
    }

    //TODO 受信電文データのデバッグ出力
    /*
    // 受信電文データのデバッグ出力
    if (maskat.isArray(inData)){
      for (var i = 0; i < inData.length; i++){
        for (var j in inData[i]){
          alert(inData[i][j]);
        }
      }
    }
    else{
      alert(inData);
    }
    */

    // 出力先オブジェクトに受信電文データを設定
    if (isOutJSObj){
      eval(outName + " = inData");
    }
    else if (outObjWrap && outObjWrap.isSingleDataObj()){
      outObjWrap.setSingleValue(inData);
    }
    else if (outObjWrap && outObjWrap.isMultiDataObj()){
      outObjWrap.setMultiValue(inData);
    }
  }
  catch (e){
    throw e;
  }
}

//グローバル範囲でname変数を取得する、定義されなければ、undefinedを戻り値とする
maskat.getObjByName = function(name){
  var obj = null;
  try{
    obj = eval(name);
  }
  catch (e){
  }
  return obj;
}


// デフォルトのエラー電文処理関数
maskat.processErrorTele = function(teleDOM){
  try {
    var errorCodeText = maskat.xpath(teleDOM, 'error/errorCode/text()');
    var messageCodeText = maskat.xpath(teleDOM, 'error/messageCode/text()');
    var messageText = maskat.xpath(teleDOM, 'error/message/text()');
    var infoText = maskat.xpath(teleDOM, 'error/info/text()');
    var systemErrorMessageText = maskat.xpath(teleDOM, 'error/systemErrorMessage/text()');

    var errorMsg = "エラーが発生しました。\nerrorCode:" + errorCodeText + "\nmessageCode:"
                   + messageCodeText + "\nmessage:" + messageText;
    if (infoText){
      errorMsg += "\ninfo:" + infoText;
    }
    if (systemErrorMessageText){
      errorMsg += "\nsystemErrorMessage:" + systemErrorMessageText;
    }

    throw new MaskatError({name: "Received Tele Error",
                           message: errorMsg,
                           fileName: "maskat.js",
                           functionName: "maskat.processErrorTele"});
  }
  catch (e){
    throw e;
  }
}





// 同期通信でサーバからXMLファイルを取得し、そのDOMのdocumentElementを返す
maskat.loadXMLFile = function(xmlFile){
  var xhr;
  try {
    xhr = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xhr = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) {
      xhr = false;
    }
  }
  if (!xhr && typeof XMLHttpRequest != 'undefined') {
    xhr = new XMLHttpRequest();
  }
  if (xhr) {
    xhr.open("GET", xmlFile, false);
    xhr.send(null);
    if (xhr.readyState == 4){
      if (xhr.status == 200) {
        if (xhr.responseXML && xhr.responseXML.nodeType == 9){
          return(xhr.responseXML);
        }
        else {
          throw new MaskatError({name: "File Error",
                               message: "サーバから取得したファイル'" + xmlFile + "'が正規のXML文書ではありません。\nファイル内のテキスト文字列: " + xhr.responseText,
                               fileName: "maskat.js",
                               functionName: "maskat.loadXMLFile"});
        }
      }
      else {
        throw new MaskatError({name: "XMLHttpRequest Error",
                               message: "サーバからファイル'" + xmlFile + "'を正常に取得できませんでした。\nXMLHttpRequest#readyState: " + xhr.readyState + "\nXMLHttpRequest#status: " + xhr.status,
                               fileName: "maskat.js",
                               functionName: "maskat.loadXMLFile"});
      }
    }
  }
  else{
    throw new MaskatError({name: "XMLHttpRequest Error",
                           message: "XMLHttpRequestオブジェクトが取得できませんでした。",
                           fileName: "maskat.js",
                           functionName: "maskat.loadXMLFile"});
  }
}

maskat.asyncTele = function(data, eventNode, eventDefDOM, IDs, soap, hostComponent){
  try {
    // XMLHttpRequestオブジェクトの取得
    var xhr;
    try {
      xhr = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
        xhr = false;
      }
    }
    if (!xhr && typeof XMLHttpRequest != 'undefined') {
      xhr = new XMLHttpRequest();
    }
    if (!xhr) {
      throw new MaskatError({name: "XMLHttpRequest Error",
                             message: "XMLHttpRequestオブジェクトが取得できませんでした。",
                             fileName: "maskat.js",
                             functionName: "maskat.asyncTele"});
    }

    // remoteUrl属性値の取得
    var remoteUrl = maskat.xpath(eventNode, '@remoteUrl');
    if (!remoteUrl){
      remoteUrl = maskat.xpath(eventDefDOM, 'remoteUrl/@url');
      if (!remoteUrl){
        throw new MaskatError({name: "EventXML Syntax Error",
                               message: "リモート通信するイベント要素に対してはremoteUrlの指定が必須です。",
                               fileName: "maskat.js",
                               functionName: "maskat.asyncTele"});
      }
    }

    // async属性値の取得
    var async = maskat.xpath(eventNode, '@async');
    if (async==null || async == "true"){//デフォルトは非同期
      async = true;
    }
    else {
      async = false;
    }
    xhr.open("POST", remoteUrl, true);  // async=true(同期通信)でも内部的には非同期通信を行う
    maskat.getCMULog().trace("XmlHttpRequestのopenメソッドを呼び出されました。url:「" + remoteUrl + "」");

    // ヘッダ処理
    var headerNodes = maskat.xpath(eventNode, 'header');
    for (var i = 0; i < headerNodes.length; i++){
      var headerValue = encodeURI(maskat.xpath(headerNodes[i], '@value'));
      xhr.setRequestHeader(maskat.xpath(headerNodes[i], '@name'), headerValue);
    }
    headerNodes = maskat.xpath(eventDefDOM, 'header');
    for (var i = 0; i < headerNodes.length; i++){
      var headerValue = encodeURI(maskat.xpath(headerNodes[i], '@value'));
      xhr.setRequestHeader(maskat.xpath(headerNodes[i], '@name'), headerValue);
    }
    if (soap=="true"){
       xhr.setRequestHeader("Content-Type", "application/soap+xml");
    }
    else {
       xhr.setRequestHeader("Content-Type", "application/xml");
    }
    if (IDs.component){
      xhr.setRequestHeader("maskat_componentID", IDs.component);
    }
    xhr.setRequestHeader("maskat_eventID", IDs.event);

    // タイムアウト
    var timeout = maskat.xpath(eventNode, '@timeout');
    if (timeout){
      var onTimeoutError = maskat.xpath(eventNode, '@onTimeoutError');
      if (onTimeoutError){
        try {
          onTimeoutError = eval(onTimeoutError);
        }
        catch (e){
          throw new MaskatError({name: "onTimeoutError Error",
                                 message: "onTimeoutError関数' + onTimeoutError + 'が定義されていません。",
                                 fileName: "maskat.js",
                                 functionName: "maskat.asyncTele"});
        }
      }
      else {
        // デフォルトのonTimeoutError関数で処理
        onTimeoutError = maskat.defaultOnTimeoutError;
      }
    }
    
    
    var sendObj = new maskat.sendObj({xhr: xhr, data: data, async: async,
                        eventNode: eventNode, IDs: IDs, timeout: timeout,
                        onTimeoutError: onTimeoutError, hostComponent: hostComponent});
    
    // コールバック関数の設定
    var callbackFunc = maskat.autoCallBackFunc(sendObj);
    xhr.onreadystatechange = callbackFunc;
    
    maskat.globalVar.sendQueueThread.add(sendObj);

    if (CrossBrowser.isFF && async == "false"){
      // FireFoxのXMLHttpRequest同期通信ではコールバックとしてonreadystatechangeは呼ばれないので、ここで明示的に呼ぶ
      callbackFunc();
    }

  }
  catch (e){
    if (sendObj!=null && sendObj.async!=true){
      sendObj.commuEnd();
    }
    throw e;
  }
}


maskat.globalVar.sendObjUniqueID = 0;
maskat.globalVar.syncConn = false;  // 起動時はfalse


maskat.sendObj = function(param){
  this.id = maskat.globalVar.sendObjUniqueID++;
  this.xhr = param.xhr;
  this.data = param.data;
  this.async = param.async;
  this.eventNode = param.eventNode;
  this.IDs = param.IDs;
  this.timeout = param.timeout;
  this.onTimeoutError = param.onTimeoutError;
  this.hostComponent = param.hostComponent;
}
maskat.sendObj.prototype.send = function(){
  maskat.beforeFunc(this.eventNode, this.xhr, this.data, this.IDs);
  
  maskat.globalVar.processingHash.add(this);
  if (this.hostComponent instanceof rialto.widget.Button && this.hostComponent.setEnable != null
          && this.async == false){
      this.hostComponent.setEnable(false);
  }
  
  if (this.timeout){
    this.onTimeoutErrorID = setTimeout("maskat.globalVar.processingHash.timeout(" + this.id + ")" , this.timeout);
  }
  
  this.xhr.send(this.data);
  maskat.getCMULog().trace("送信電文：[" + this.data + "]");
}
maskat.sendObj.prototype.receive = function(){
  maskat.autoCallBackFunc2(this);
}
maskat.sendObj.prototype.commuEnd = function(){
  if (this.hostComponent instanceof rialto.widget.Button && this.hostComponent.setEnable != null
          && this.async == false){
      this.hostComponent.setEnable(true);
      this.hostComponent = null;
  }
  if (this.async!=true && maskat.globalVar.syncConnDialog!=null && 
      maskat.globalVar.syncConnDialog.remove!=null){
       // ダイアログボックス閉じる
       maskat.globalVar.syncConnDialog.remove();
       maskat.globalVar.syncConnDialog = null;
       // 同期通信
       maskat.globalVar.syncConn = false;
  }
}


maskat.sendQueueThread = function(){
  this.queue = new Array();
}
maskat.sendQueueThread.prototype.add = function(obj){
  this.queue.push(obj);
  this.sendCheck();
}
maskat.sendQueueThread.prototype.sendCheck = function(){
 try{
  var thisObj = maskat.globalVar.sendQueueThread;
  if (thisObj.queue.length > 0){
    if (!maskat.globalVar.syncConn){
      maskat.globalVar.syncConn = true;  // 同期/非同期に関わらずすぐにロックをかける
      var sendObj = thisObj.queue.shift();
      if (!sendObj.async){
        // ダイアログボックス表示
        var _maskat_connecting_popup = new rialto.widget.PopUp('_maskat_connecting_popup', 50, 50, 250, 50,
            null, '通信中', 'Transparent', {withCloseButon:false});
        var _maskat_connecting_label = new rialto.widget.Label('_maskat_connecting_label', 10, 10,
            _maskat_connecting_popup, '通信中です。しばらくお待ち下さい。', null,
            {name:'_maskat_connecting_label', top:10, left:10, text:'通信中です。しばらくお待ち下さい。',
            parent:_maskat_connecting_popup});
        maskat.globalVar.syncConnDialog = _maskat_connecting_popup;
      }
      else {
        maskat.globalVar.syncConn = false;  // 非同期であればこの時点でロック解除
      }
      sendObj.send();
      thisObj.sendCheck();
    }
    else {
      setTimeout(thisObj.sendCheck, 500);
    }
   }
 }catch(e){
      if (sendObj!=null)
         sendObj.commuEnd();

      if (e instanceof MaskatProcessInterruption){
          //Do Nothing
      }
      // これより上にエラーをthrowできないので(非同期通信時のmaskat.autoCallBackFuncの
      // 呼び出し元はWebブラウザとなる)、ここでログを出力
      else
          maskat.handleFrameworkError("maskat.sendQueueThread.prototype.sendCheck呼び出し時にエラーが発生しました。",e);
  }
}
maskat.globalVar.sendQueueThread = new maskat.sendQueueThread();


maskat.processingHash = function(){
  this.hash = new Object();
}
maskat.processingHash.prototype.add = function(obj){
  this.hash[obj.id] = obj;
}
maskat.processingHash.prototype.remove = function(obj){
  this.hash[obj.id] = undefined;
}
maskat.processingHash.prototype.timeout = function(id){
  var timeoutObj = this.hash[id];
  
  timeoutObj.xhr.abort();
  timeoutObj.commuEnd();
  timeoutObj.onTimeoutError();
  this.hash[id] = undefined;
}
maskat.globalVar.processingHash = new maskat.processingHash();


maskat.receiveQueueThread = function(){
  this.queue = new Array();
}
maskat.receiveQueueThread.prototype.add = function(obj){
  this.queue.push(obj);
  this.receiveCheck();
}
maskat.receiveQueueThread.prototype.receiveCheck = function(){
  var thisObj = maskat.globalVar.receiveQueueThread;
  if (thisObj.queue.length > 0){
    if (!maskat.globalVar.syncConn){
      var receiveObj = thisObj.queue.shift();
      receiveObj.receive();
      thisObj.receiveCheck();
    }
    else {
      setTimeout(thisObj.receiveCheck, 500);
    }
  }
}
maskat.globalVar.receiveQueueThread = new maskat.receiveQueueThread();


maskat.defaultOnTimeoutError = function(){
  alert("defaultOnTimeoutError");
}


maskat.autoCallBackFunc = function(sendObj){
  return function(){
    try{
      if (sendObj.xhr.readyState == 4){
        if (sendObj.xhr.status == 200){
          maskat.getCMULog().trace("受信電文[" + sendObj.xhr.responseText + "]");
          // タイムアウト解除
          if (sendObj.timeout){
            clearTimeout(sendObj.onTimeoutErrorID);
          }
          
          maskat.globalVar.processingHash.remove(sendObj.id);

          if (sendObj.async){
            // 非同期通信
            maskat.globalVar.receiveQueueThread.add(sendObj);
          }
          else {
            // 同期通信
            maskat.autoCallBackFunc2(sendObj);
          }
        }
        else if (sendObj.xhr.status == 0){
          // timeoutエラーのXHR#abort時
        }
        else{
          throw new MaskatError({name: "XMLHttpRequest Error",
                                 message: "サーバから受信電文を正常に取得できませんでした。\nXHR#readyState: " + sendObj.xhr.readyState + "\nXHR#status: " + sendObj.xhr.status,
                                 fileName: "maskat.js",
                                 functionName: "maskat.autoCallBackFunc"});
        }
      }
    }
    catch (e){
      if (sendObj!=null)
         sendObj.commuEnd();

      if (e instanceof MaskatProcessInterruption){
        // Do Nothing
      }
      // これより上にエラーをthrowできないので(非同期通信時のmaskat.autoCallBackFuncの
      // 呼び出し元はWebブラウザとなる)、ここでログを出力
      else
          maskat.handleFrameworkError("maskat.autoCallBackFunc呼び出し時(受信電文処理)にエラーが発生しました。",e);
    }
  };
}

maskat.autoCallBackFunc2 = function(sendObj){
  sendObj.recvDOM = sendObj.xhr.responseXML.documentElement;
  maskat.afterFunc(sendObj);
  maskat.intprRecvTele(sendObj.eventNode, sendObj.recvDOM);

  sendObj.commuEnd();
  maskat.finishFunc(sendObj.eventNode, sendObj.IDs);
}


maskat.startFunc = function(eventNode, IDs){
    var startFunc = maskat.xpath(eventNode, '@start');
    if (startFunc){
      var param = new Object();
      param.stopProcess = false;
      try{
        eval(startFunc + "(param);");
      }
      catch (e){
        maskat.getFWLog().error("["+IDs.component+"]の["+IDs.event+"]イベントのstart関数実行中、エラーが発生。");
        throw e;
      }
      if (param.stopProcess){
        throw new MaskatProcessInterruption(
          {name: "Start Function Interruption",
           message: "componentID'" + IDs.component + "',eventID'" + IDs.event + "'のstart関数内で処理停止",
           fileName: "intpr.js",
           functionName: "maskat.startFunc"});
      }
    }
}

maskat.beforeFunc = function(eventNode, xhr, sendXML, IDs){
    var beforeFunc = maskat.xpath(eventNode, '@before');
    if (beforeFunc){
      var param = new Object();
      param.stopProcess = false;
      param.xhr = xhr;
      param.sendXML = sendXML;
      try{
        eval(beforeFunc + "(param);");
      }
      catch(e){
        maskat.getFWLog().error("["+IDs.component+"]の["+IDs.event+"]イベントのbefore関数実行中、エラーが発生。");
        throw e;
      }
      if (param.stopProcess){
        throw new MaskatProcessInterruption(
          {name: "Before Function Interruption",
           message: "componentID'" + IDs.component + "',eventID'" + IDs.event + "'のbefore関数内で処理停止",
           fileName: "intpr.js",
           functionName: "maskat.beforeFunc"});
      }
    }
}

maskat.afterFunc = function(sendObj){
    var afterFunc = maskat.xpath(sendObj.eventNode, '@after');
    if (afterFunc){
      var param = new Object();
      param.stopProcess = false;
      param.xhr = sendObj.xhr;
      param.recvDOM = sendObj.recvDOM;
      try{
        eval(afterFunc + "(param);");
        sendObj.recvDOM = param.recvDOM;
      }
      catch(e){
        maskat.getFWLog().error("["+sendObj.IDs.component+"]の["+sendObj.IDs.event+"]イベントのafter関数実行中、エラーが発生。");
        throw e;
      }
      if (param.stopProcess){
        throw new MaskatProcessInterruption(
          {name: "After Function Interruption",
           message: "componentID'" + sendObj.IDs.component + "',eventID'" + sendObj.IDs.event + "'のafter関数内で処理停止",
           fileName: "intpr.js",
           functionName: "maskat.afterFunc"});
      }
    }
}

maskat.finishFunc = function(eventNode, IDs){
    var finishFunc = maskat.xpath(eventNode, '@finish');
    if (finishFunc){
      try{
        eval(finishFunc + "();");
      }
      catch(e){
        maskat.getFWLog().error("["+IDs.component+"]の["+IDs.event+"]イベントのfinish関数実行中、エラーが発生。");
        throw e;
      }
    }
}

/* Mask@版XPath制限事項
   ・ロケーションパスは相対ロケーションパスのみ指定可能。
   ・軸(axis)はchildとattributeのみ。childとattributeはそれぞれ省略記法のみ(child:(省略して何も書かない), attribute: @)
   ・ノードテスト(nodetest)は要素名(child軸の場合)、属性名(attribute軸の場合)、'text()'のみ
   ・述語(predicate)はchild軸に対してのみ利用可能
   ・述語は[n]か[@name="value"]のみ。左記述語を複数回並べて指定することを禁止。
   ・[注意] 述語の[n]のnは1-index。ゼロ始まりではない。
   Mask@版XPath拡張事項
   ・attribute軸はロケーションステップの最後、かつ単一Nodeに対してのみ利用可能。
     その場合、戻り値は属性名の文字列。属性が定義されていない場合はnull。
   ・text()ノードテストはロケーションステップの最後、かつ単一親Nodeに対してのみ利用可能。
     その場合、戻り値はテキスト文字列。
   ・ロケーションステップの最後に述語が使われていた場合、戻り値は単一Nodeとする(述語がマッチしなければnullを返す)。
   ・その他の場合の戻り値: Node集合
*/

maskat.xpath = function(dom, locationPath){
  var locationStep = locationPath.split("/");
  var i;
  var j;
  var k;
  
  if (!dom || dom.nodeType != 1){  // ELEMENT_NODE
    throw new MaskatError({name: "Mask@XPath Syntax Error",
                           message: "引数domが不正です。引数domにはDOMの要素ノードを指定して下さい。",
                           fileName: "maskat.js",
                           functionName: "maskat.xpath"});
  }
  
  var domArray = new Array();

  domArray.push(dom);
  
  var isLastPredicate = false;
  
  for (i = 0; i < locationStep.length; i++){
    var domNextArray = new Array();
    for (j = 0; j < domArray.length; j++){

      // 軸がattributeの場合
      if (locationStep[i].charAt(0) == "@"){
        if (i != locationStep.length - 1 || domArray.length != 1){
          throw new MaskatError({name: "Mask@XPath Syntax Error",
                                 message: "attribute軸はロケーションステップの最後、かつ単一Nodeに対してのみ利用可能です。\nエラーが発生したロケーションパス: " + locationPath,
                                 fileName: "maskat.js",
                                 functionName: "maskat.xpath"});
        }
        else {
          var attributeName = locationStep[i].substring(1, locationStep[i].length);
          var attributeNode = domArray[j].getAttributeNode(attributeName);
          if (attributeNode){
            // すぐに属性値(文字列)を返す
            return attributeNode.nodeValue;
          }
          else {
            // 属性が設定されていない場合はすぐにnullを返す
            return null;
          }
        }
      }
      
      // ノードテストがtext()のchild軸の場合
      else if (locationStep[i] == "text()"){
        if (i != locationStep.length - 1 || domArray.length != 1){
          throw new MaskatError({name: "Mask@XPath Syntax Error",
                                 message: "text()ノードテストはロケーションステップの最後、かつ単一親Nodeに対してのみ利用可能です。\nエラーが発生したロケーションパス: " + locationPath,
                                 fileName: "maskat.js",
                                 functionName: "maskat.xpath"});
        }
        else {
          if (domArray[j].childNodes && domArray[j].childNodes.length == 1
                 && (domArray[j].childNodes[0].nodeType == 3 || domArray[j].childNodes[0].nodeType == 4)){
            return domArray[j].childNodes[0].nodeValue;
          }
          else if (domArray[j].childNodes && domArray[j].childNodes.length == 0){
            return "";
          }
          else {
            throw new MaskatError({name: "Mask@XPath Syntax Error",
                                   message: "text()ノードテストを指定したノードのXML形式が不正です。\nエラーが発生したロケーションパス: " + locationPath,
                                   fileName: "maskat.js",
                                   functionName: "maskat.xpath"});
          }
        }
      }
      
      // ノードテストが要素名のchild軸の場合
      else{

        var nodeTest = null;
        var predicate = null;
        var predicateAttributeName = null;
        var predicateAttributeValue = null;
        var nodePos = 0;
    
        if (locationStep[i].indexOf("[") != -1){
          nodeTest = locationStep[i].substring(0, locationStep[i].indexOf("["));
          predicate = locationStep[i].substring(locationStep[i].indexOf("[") + 1, locationStep[i].indexOf("]"));

          if (predicate.charAt(0) == "@"){
            predicateAttributeName = predicate.substring(1, predicate.indexOf("="));
            predicateAttributeValue = predicate.substring(predicate.indexOf("=") + 2, predicate.length - 1); // ダブルクォートのことを考慮に入れる
          }
          else {
            nodePos = parseInt(predicate);
            if (isNaN(nodePos)){
              throw new MaskatError({name: "Mask@XPath Syntax Error",
                                     message: "述語が不正です。\nエラーが発生したロケーションパス: " + locationPath,
                                     fileName: "intpr.js",
                                     functionName: "maskat.xpath"});
            }
          }
          
          if (i == locationStep.length - 1){
            isLastPredicate = true;
          }
          
        }
        else{
          nodeTest = locationStep[i];
        }
        
        var currentNodePos = 0;  // 述語[n]を処理するために利用

        for (k = 0; k < domArray[j].childNodes.length; k++){
          var childNode = domArray[j].childNodes[k];
          if (childNode.nodeType != 1){  // ELEMENT_NODE
            continue;
          }
          if (childNode.nodeName == nodeTest){
            currentNodePos++;
            if (predicate){
              if (predicateAttributeName){
                if (childNode.getAttribute(predicateAttributeName) != predicateAttributeValue){
                  continue;
                }
                else if (isLastPredicate){
                  return childNode;
                }
              }
              else {
                if (nodePos != currentNodePos){
                  continue;
                }
                else if (isLastPredicate){
                  return childNode;
                }
              }
            }
            domNextArray.push(childNode);
          }
        }
      }
    }
    domArray = domNextArray;
  }

  if (isLastPredicate){
    return null;
  }
  else {
    return domArray;
  }
}

 maskat.RadioGroup = function(group){
  this.group = group;
  this.type = "radioGroup";
  this.base = rialto.widget.AbstractComponent;
  this.radioMemberArray = new Array();
  this.radioMemberNameArray = new Array();
  this.tabIndex=0;
}

maskat.RadioGroup.prototype = new rialto.widget.AbstractComponent;

maskat.RadioGroup.prototype.addRadioMemberName = function(radioMemberName){
  this.radioMemberNameArray.push(radioMemberName);
}

maskat.RadioGroup.prototype.addRadioMember = function(radioMember){
  this.radioMemberArray.push(radioMember);
}

maskat.RadioGroup.prototype.getSelValue = function(){
  for (var i = 0; i < this.radioMemberArray.length; i++){
    if (this.radioMemberArray[i].isCheck()){
      return this.radioMemberArray[i].name;
    }
  }
  return "";
}

maskat.RadioGroup.prototype.setSelValue = function(radioName){
  for (var i = 0; i < this.radioMemberArray.length; i++){
    if (this.radioMemberArray[i].name == radioName){
      this.radioMemberArray[i].setCheck(true);
      return;
    }
  }
}

maskat.RadioGroup.prototype.initRadio = function(){
  for (var i = 0; i < this.radioMemberArray.length; i++){
    this.radioMemberArray[i].setCheck(false);
  }
}

// タブインデックス用
var focusObj = null;
var focusNode = null;
var tagIndexMap = new Object();

maskat.syntax = {
  AbstractComponent: {
    bWithoutPlaceIn: {type: "boolean"},
    name: {type: "string"},
    type: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "string"},
    height: {type: "string"},
    position: {type: "enum", elem: ["static", "absolute", "relative"], def: "absolute"},
    enable: {type: "boolean"},
    draggable: {type: "boolean"},
    resizable: {type: "boolean"},
    autoResizableH: {type: "boolean"},
    autoResizableW: {type: "boolean"}
  },
  layoutDef: {
  },
  layout: {
    name: {type: "string", req: true},
    refParentHTML: {type: "string", req: false}
  },
  window: {
    parent: {type: "object"},
    title: {type: "string"},
    icone: {type: "string"},
    style: {type: "enum", elem: ["default", "fenetre"], def: "fenetre"}
  },
  frame: {
    dynamic: {type: "boolean"},
    open: {type: "boolean"},
    title: {type: "string"},
    printTitle: {type: "string"},
    autoResizeContenu: {type: "boolean"},
    autoResizeParent: {type: "boolean"},
    boolPrint: {type: "boolean"},
    boolMaxi: {type: "boolean"},
    parent: {type: "object"}
  },
  popup: {
    name: {type: "string"},  // 名前変更
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "number"},
    height: {type: "number"},
    contenu: {type: "string"},
    title: {type: "string"},  // 名前変更
    suffFond: {type: "enum", elem: ["Gris", "Transparent"], def: "Transparent"},
    modeContainer: {type: "enum", elem: ["AutoScroll", "nonFen"]},  // AutoScrollを指定するとRialtoエラー
    bSansBtonClose: {type: "boolean"},
    oCiuLie: {type: "unknown"}  // TODO: 要チェック
  },
  form: {
    name: {type: "string"},  // 名前変更
    left: {type: "number"},
    top: {type: "number"},
    url: {type: "string"},
    parent: {type: "object"},
    imgBtonSubmit: {type: "object"},
    autoSubmit: {type: "boolean"},
    method: {type: "enum", elem: ["post", "get"], def: "post"},
    boolWithFenWait: {type: "boolean"},
    boolAsynch: {type: "boolean"},
    idCont: {type: "string"},
    canBeCancel: {type: "boolean"},
    boolIframe: {type: "boolean"},
    onSuccess: {type: "object"},
    callBackObjectOnSuccess: {type: "object"}
  },
  tabFolder: {
    autoResizeContenu: {type: "boolean"},
    autoResizeParent: {type: "boolean"},
    autoRedimTab: {type: "boolean"},
    isClosable: {type: "boolean"},
    draggableItem: {type: "boolean"},
    widthTabName: {type: "number"},
    parent: {type: "object"},
    noActiveTab: {type: "number", def: 1},  // taglibでの追加属性
    tabIndex: {type: "number", def: -1}
  },
  tabItem: {
    name: {type: "string"},
    title: {type: "string"}
  },
  splitter: {
    prop: {type: "integer"},
    orientation: {type: "enum", elem: ["v", "h"]},
    autoResizeContenu: {type: "boolean"},
    autoResizeParent: {type: "boolean"},
    autoResizableH: {type: "boolean"},
    autoResizableW: {type: "boolean"},
    style: {type: "enum", elem: ["normal", "3D"]},
    overflow: {type: "enum", elem: ["auto", "hidden"]},
    modeLim: {type: "enum", elem: ["%", "abs"]},
    limInf: {type: "number"},
    limSup: {type: "number"},
    reverseClose: {type: "boolean"},
    withImg: {type: "boolean"},
    tailleCurs: {type: "number"},
    parent: {type: "object"}
  },
  divSplit: {
    name: {type: "string"},
    backgroundColor: {type: "string", def: "white"}
  },
  image: {
    imageOut: {type: "string"},
    left: {type: "number"},
    top: {type: "number"},
    parent: {type: "object"},
    alternateText: {type: "string"},
    imageOn: {type: "string"},
    imageDisabled: {type: "string"},
    boolFloatRight: {type: "boolean"},
    boolFloatLeft: {type: "boolean"}
  },
  label: {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    parent: {type: "object"},
    text: {type: "string"},
    className: {type: "string"},
    position: {type: "enum", elem: ["static", "relative", "absolute"]}
  },
  text: {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "number"},
    datatype: {type: "enum", elem: ["T", "P", "A", "N", "I", "D", "H", "Hi"]},
    parent: {type: "object"},
    position: {type: "enum", elem: ["static", "relative", "absolute"]},
    nbchar: {type: "number"},
    autoUp: {type: "boolean"},
    disable: {type: "boolean"},
    isRequired: {type: "boolean"},
    rows: {type: "number"},
    initValue: {type: "string"},
    accessKey: {type: "string"},
    tabIndex: {type: "number"}
  },
  button: {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    title: {type: "string"},
    alt: {type: "string"},
    parent: {type: "object"},
    enable: {type: "boolean"},
    tabIndex: {type: "number", def: -1}
  },
  combo: {
    tabData: {type: "object", def: '[]'},
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "number"},
    parent: {type: "object"},
    position: {type: "enum", elem: ["static", "relative", "absolute"]},
    suggest: {type: "boolean"},
    enable: {type: "boolean"},
    heightItem: {type: "number"},
    tabIndex: {type: "number", def: -1}
  },
  comboItem: {
    text: {type: "string"},
    value: {type: "string"}
  },
  codeLib: {
    name: {type: "string"},  // 名前変更
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "number"},
    parent: {type: "object"},
    arrValue: {type: "object"},
    boolWithLabel: {type: "boolean", alias: "withLabel"},
    url: {type: "string"},
    submitOnload: {type: "boolean"},
    alwaysRefresh: {type: "boolean"},
    codeWidth: {type: "number"},
    tabIndex: {type: "number", def: -1}
  },
  radioGroup: {
    name: {type: "string"},
    tabIndex: {type: "number", def: -1}
  },
  radioMember: {
    ref: {type: "string"}
  },
  radio: {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    parent: {type: "object"},
    group: {type: "string"}, // レイアウト定義XML的には使用してはいけないが、処理上許可
    text: {type: "string"},
    checked: {type: "boolean"},
    className: {type: "string"}
  },
  checkbox: {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    parent: {type: "object"},
    text: {type: "string"},
    checked: {type: "boolean"},
    className: {type: "string"},
    tabIndex: {type: "number", def: -1}
  },
  alert: {
    name: {type: "string"},
    mess: {type: "string"}
  },
  divHtml: {
  	name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    parent: {type: "object"},
    className: {type: "string"},
    position: {type: "enum", elem: ["static", "relative", "absolute"]}
  },
  treeview: {
    boolSelActive: {type: "boolean"},
    withT: {type: "boolean"},
    rootOpen: {type: "boolean"},
    withRoot: {type: "boolean"},
    autoResizableH: {type: "boolean"},
    autoResizableW: {type: "boolean"},
    draggableNode: {type: "boolean"},
    rootNode: {type: "object"},
    parent: {type: "object"},
    tabIndex: {type: "number"}
  },
  treeNode: {
    typeInfo: {type: "string"},
    sText: {type: "string", alias:"text"},
    sIcon: {type: "string", alias:"icon"},
    sIcon2: {type: "string", alias:"icon2"},
    onclick: {type: "string"},
    open: {type: "boolean"},
    reload: {type: "boolean"},
    url: {type: "string"}
  },
  grid: {
    TabEntete: {type: "object"},
    bNavig: {type: "boolean"},
    cellActive: {type: "boolean"},
    sortable: {type: "boolean"},
    multiSelect: {type: "boolean"},
    lineHeight: {type: "number"},
    rang: {type: "number"},
    widthLastCell: {type: "number"},
    actifClic: {type: "boolean"},
    boolPrint: {type: "boolean"},
    switchable: {type: "boolean"},
    printTitle: {type: "string"},
    autoResizeContenu: {type: "boolean"},
    autoResizeParent: {type: "boolean"},
    writable: {type: "boolean"},
    tabTypeCol: {type: "object"},
    parent: {type: "object"},
    tabIndex: {type: "number", def: -1}
  },
  gridHeader: {
    width: {type: "number"},
    title: {type: "string"},
    type: {type: "enum", elem: ["number", "date", "string"]}
  },
/*  gridCellCombo: {
    value: {type: "string"},
    text: {type: "string"}
  },*/
  gridLine: {
  },
  gridCell: {
    value: {type: "string"}
  },
  javaScript: {
  },
  javaScriptGlobal: {
  },
  desc: {
  }
}

maskat.syntax.init = function(){
  // AbstractComponentの属性を継承するコンポーネントの属性初期化
  for(var attr in maskat.syntax.AbstractComponent){
    maskat.syntax.window[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.frame[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.tabFolder[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.splitter[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.image[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.treeview[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.treeNode[attr] = maskat.syntax.AbstractComponent[attr];
    maskat.syntax.grid[attr] = maskat.syntax.AbstractComponent[attr];
  }
  // 追加
  maskat.syntax.tabFolder.width.req = true;
  maskat.syntax.tabFolder.height.req = true;
}
maskat.syntax.init();

maskat.syntax.validate = function(layoutDOM){
  maskat.syntax.validateElement(layoutDOM.documentElement);
}

maskat.syntax.validateElement = function(domElem){
  var i;

  // 要素名validation
  var nodeName = domElem.nodeName;
  if (maskat.syntax[nodeName] == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "要素名'" + nodeName + "'は不正な要素名です。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.syntax.validateElement"});
  }
  else{
    // 属性validation
    if (domElem.attributes){
      for (i = 0; i < domElem.attributes.length; i++){
        var attributeName = domElem.attributes[i].name;
        if (maskat.syntax[nodeName][attributeName] == undefined){
          throw new MaskatError({name: "layoutXML Syntax Error",
                                 message: "要素名'" + nodeName + "'の属性の内、属性名'" + attributeName + "'は不正な属性名です。",
                                 fileName: "layoutXMLInterpreter.js",
                                 functionName: "maskat.syntax.validateElement"});
        }
      }
    }
  }

  // 子要素を再帰的にvalidation
  if (domElem.hasChildNodes()){
    for (i = 0; i < domElem.childNodes.length; i++){
      if (domElem.childNodes[i].nodeType == 1){  // ELEMENT_NODE
        maskat.syntax.validateElement(domElem.childNodes[i]);
      }
    }
  }
}

maskat.interpretLayoutXML = function(layoutDOM, refParentHTML){

  // レイアウト定義XMLのvalidation [通常利用時はコメントアウト]
  maskat.syntax.validate(layoutDOM);

  // 変換後のJavaScriptソース
  var output = "";

  // ルート要素から現在の要素までのパス上にある要素オブジェクトの配列
  var pathObjArray = new Array();

  var i;
  var j;
  
  // layout要素の出現回数
  var layoutNum = 0;

  // ルート要素直下の子要素を処理
  for (i = 0; i < layoutDOM.documentElement.childNodes.length; i++){
    var domElem = layoutDOM.documentElement.childNodes[i];
    if (domElem.nodeType != 1){  // ELEMENT_NODE以外は無視
      continue;
    }
    else if (domElem.nodeName == "layout"){
      if (layoutNum > 0){
        throw new MaskatError({name: "layoutXML Syntax Error",
                               message: "layout要素は、1つのレイアウト定義XMLファイルに1つしか存在できません。",
                               fileName: "layoutXMLInterpreter.js",
                               functionName: "maskat.interpretLayoutXML"});
      }
      else{
        layoutNum++;
        if (refParentHTML){
          domElem.setAttribute("refParentHTML", refParentHTML);
        }
        output += maskat.transLayoutTag(pathObjArray, domElem);
      }
    }
    else if (domElem.nodeName == "javaScriptGlobal"){
      // "<javaScriptGlobal><![CDATA[...]]></javaScriptGlobal>"の"..."の部分を取得する
      if (domElem.hasChildNodes()){
        for (j = 0; j < domElem.childNodes.length; j++){
          if (domElem.childNodes[j].nodeType == 4){  // CDATA_SECTION
            output += domElem.childNodes[j].nodeValue + "\n";
          }
        }
      }
    }
    else{
      throw new MaskatError({name: "layoutXML Syntax Error",
                             message: "ルート要素の子要素として、不正な要素'" + domElem.nodeName + "'があります。",
                             fileName: "layoutXMLInterpreter.js",
                             functionName: "maskat.interpretLayoutXML"});
    }
  }

  return output;
}


////////////////////////////////////////////////////////////
//
// layout
//
////////////////////////////////////////////////////////////

maskat.transLayoutTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);
  if (attr.name==null || attr.name==""){
        throw new MaskatError({name: "layoutXML Syntax Error",
                               message: "layout要素のname属性は必須属性です。",
                               fileName: "layoutXMLInterpreter.js",
                               functionName: "maskat.transLayoutTag"});
  }

  new maskat.Layout(attr.name);
  //// 前変換
  output += "function " + attr.name + "(){\n";
  output += "var layoutObj = maskat.layouts[\"" + attr.name + "\"];\n";

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var layoutObj = new maskat.LayoutClass(attr.name, attr.refParentHTML);
    pathObjArray.push(layoutObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換
  output += "return layoutObj;\n}\n";

  return output;
}

maskat.LayoutClass = function(name, refParentHTML){
  this.name = name;
  this.refParentHTML = refParentHTML;
}
maskat.LayoutClass.prototype.isContainer = true;
maskat.LayoutClass.prototype.getRefObj = function(){ return this.refParentHTML; }


////////////////////////////////////////////////////////////
//
// window
//
////////////////////////////////////////////////////////////

maskat.transWindowTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }
  
  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.SimpleWindow(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var windowObj = new maskat.WindowClass(attr.name);
    pathObjArray.push(windowObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.WindowClass = function(name){
  this.name = name;
}
maskat.WindowClass.prototype.isContainer = true;
maskat.WindowClass.prototype.getRefObj = function(){ return this.name; }


////////////////////////////////////////////////////////////
//
// popup
//
////////////////////////////////////////////////////////////

maskat.transPopupTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.PopUp("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "width") + ", "
                      + maskat.composeSingleParam(domElem, attr, "height") + ", "
                      + maskat.composeSingleParam(domElem, attr, "contenu") + ", "
                      + maskat.composeSingleParam(domElem, attr, "title") + ", "
                      + maskat.composeSingleParam(domElem, attr, "suffFond") + ", "
                      + strObjPar + ");\n";
                      //+ maskat.composeSingleParam(domElem, attr, "modeContainer") + ", "
                      //+ maskat.composeSingleParam(domElem, attr, "bSansBtonClose") + ", "
                      //+ maskat.composeSingleParam(domElem, attr, "oCiuLie") + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var popupObj = new maskat.PopupClass(attr.name);
    pathObjArray.push(popupObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.PopupClass = function(name){
  this.name = name;
}
maskat.PopupClass.prototype.isContainer = true;
maskat.PopupClass.prototype.getRefObj = function(){ return this.name; }

////////////////////////////////////////////////////////////
//
// frame
//
////////////////////////////////////////////////////////////

maskat.transFrameTag = function(pathObjArray, domElem){

  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Frame(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";
  
  // add keyNavi
  output += attr.name + ".cadre.tabIndex=-1;\n";
  
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var frameObj = new maskat.FrameClass(attr.name);
    pathObjArray.push(frameObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }
  //// 後変換
  return output;
}

maskat.FrameClass = function(name){
  this.name = name;
}
maskat.FrameClass.prototype.isContainer = true;
maskat.FrameClass.prototype.getRefObj = function(){ return this.name; }


////////////////////////////////////////////////////////////
//
// form
//
////////////////////////////////////////////////////////////

maskat.transFormTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Form("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "url") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var formObj = new maskat.FormClass(attr.name);
    pathObjArray.push(formObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.FormClass = function(name){
  this.name = name;
}
maskat.FormClass.prototype.isContainer = true;
maskat.FormClass.prototype.getRefObj = function(){ return this.name; }

////////////////////////////////////////////////////////////
//
// tabFolder
//
////////////////////////////////////////////////////////////

maskat.transTabFolderTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  // 特別な内部変数
  var _tabFolderNbTabs = 0;

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.TabFolder(" + strObjPar +");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".divContenuGlobal.tabIndex=-1;\n";
  output += attr.name + ".divExt.tabIndex=" + num + ";\n";
  output += attr.name + ".divExt.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";
  
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var tabFolderObj = new maskat.TabFolderClass(attr.name, _tabFolderNbTabs);
    pathObjArray.push(tabFolderObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);

  }

  //// 後変換
  
  _tabFolderNbTabs = tabFolderObj.nbTabs;
  
  if (attr.noActiveTab <= 0) {
    attr.noActiveTab = 1;
  }
  else if (attr.noActiveTab > _tabFolderNbTabs ){
    attr.noActiveTab = _tabFolderNbTabs ;
  }
  output += "layoutObj.components[\""+attr.name + "\"].activeTab((" + attr.noActiveTab + " - 1));\n";

  return output;
}

maskat.TabFolderClass = function(name, nbTabs){
  this.name = name;
  this.nbTabs = nbTabs;
}
maskat.TabFolderClass.prototype.isContainer = true;
maskat.TabFolderClass.prototype.getRefObj = function(){ return this.name; }
maskat.TabFolderClass.prototype.incrementNbTabs = function(){ this.nbTabs++; }


////////////////////////////////////////////////////////////
//
// tabItem
//
////////////////////////////////////////////////////////////

maskat.transTabItemTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.TabClassのインスタンスを取得する
  var tabFolderClassObj;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.TabFolderClass){
      tabFolderClassObj = pathObjArray[i];
      break;
    }
  }
  if (tabFolderClassObj == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "tabItem(name:'" + attr.name +"')の親要素としてtabFolder要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transTabItemTag"});
  }

  // maskat.TabClassインスタンスのgetRefObjメソッドの戻り値を取得する
  var refObjName = tabFolderClassObj.getRefObj();

  output += attr.name + " = layoutObj.components[\""+ refObjName + "\"].addTabItem("
                      + maskat.composeSingleParam(domElem, attr, "title") + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";
  
  // maskat.TabClassインスタンスのタブの数をインクリメントする
  tabFolderClassObj.incrementNbTabs();

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var tabItemObj = new maskat.TabItemClass(attr.name);
    pathObjArray.push(tabItemObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.TabItemClass = function(name){
  this.name = name;
}
maskat.TabItemClass.prototype.isContainer = true;
maskat.TabItemClass.prototype.getRefObj = function(){ return this.name; }


////////////////////////////////////////////////////////////
//
// splitter
//
////////////////////////////////////////////////////////////

maskat.transSplitterTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  if (attr["width"]!=null && attr["width"]!=""){
      attr["autoResizableW"]=false;
  }
  if (attr["height"]!=null && attr["height"]!=""){
      attr["autoResizableH"]=false;
  }
  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Splitter(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var splitterObj = new maskat.SplitterClass(attr.name);
    pathObjArray.push(splitterObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);

  }

  //// 後変換

  return output;
}

maskat.SplitterClass = function(name){
  this.name = name;
  this.divSplitCount=0;//子ノードのdivSplitノード数
}
maskat.SplitterClass.prototype.isContainer = true;
maskat.SplitterClass.prototype.getRefObj = function(){ return this.name; }


////////////////////////////////////////////////////////////
//
// divSplit
//
////////////////////////////////////////////////////////////

maskat.transDivSplitTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  var thisRefObjName;

  // 親タグがmaskat.SplitterClassかどうか
  var pathObj = pathObjArray[pathObjArray.length - 1];
  if (pathObj instanceof maskat.SplitterClass){
    var parentRefObjName = pathObj.getRefObj();
    if (pathObj.divSplitCount>=2){
       throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "splitter(name:'" + parentRefObjName +"')要素のdivSplit子要素は二つしか定義できません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transDivSplitTag"});
    }
    pathObj.divSplitCount++;
    attr.name="div"+pathObj.divSplitCount;
    thisRefObjName = "layoutObj.components[\""+parentRefObjName + "\"]." + attr.name;

    if (attr.backgroundColor != ""){
      output += "layoutObj.components[\""+parentRefObjName + "\"]." + attr.name +".style.backgroundColor='"
             + attr.backgroundColor + "';\n";
    }
  }
  else{
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "divSplit(name:'" + attr.name +"')の親要素としてsplitter要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transDivSplitTag"});
  }

  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var divSplitObj = new maskat.DivSplitClass(attr.name, thisRefObjName);
    pathObjArray.push(divSplitObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.DivSplitClass = function(name, thisRefObjName){
  this.name = name;
  this.refObjName = thisRefObjName;
}
maskat.DivSplitClass.prototype.isContainer = true;
maskat.DivSplitClass.prototype.getRefObj = function(){ return this.refObjName; }


////////////////////////////////////////////////////////////
//
// image
//
////////////////////////////////////////////////////////////

maskat.transImageTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Image("
                      + maskat.composeSingleParam(domElem, attr, "imageOut") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + maskat.composeSingleParam(domElem, attr, "alternateText") + ", "
                      + maskat.composeSingleParam(domElem, attr, "imageOn") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// label
//
////////////////////////////////////////////////////////////

maskat.transLabelTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Label("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + maskat.composeSingleParam(domElem, attr, "text") + ", "
                      + maskat.composeSingleParam(domElem, attr, "className") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]=" + attr.name + ";\n";
  
  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// text
//
////////////////////////////////////////////////////////////

maskat.transTextTag = function(pathObjArray, domElem){

  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Text("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "width") + ", "
                      + maskat.composeSingleParam(domElem, attr, "datatype") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  output += attr.name + ".onfocus = function(e){" +
		  "focusObj=" + attr.name + ";};\n";
  rialto.widget.Form.prototype.tabIndex++;

  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// button
//
////////////////////////////////////////////////////////////

maskat.transButtonTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Button("
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "title") + ", "
                      + maskat.composeSingleParam(domElem, attr, "alt") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".divExt.tabIndex=" + num + ";\n";
  output += attr.name + ".divExt.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";
  		
  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// combo
//
////////////////////////////////////////////////////////////

maskat.transComboTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Combo("
                      + maskat.composeSingleParam(domElem, attr, "tabData") + ", "
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "width") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".text.champs.tabIndex=" + num + ";\n";
  output += attr.name + ".text.champs.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";	
  		
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var comboObj = new maskat.ComboClass(attr.name);
    pathObjArray.push(comboObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}


maskat.ComboClass = function(name){
  this.name = name;
}
maskat.ComboClass.prototype.isContainer = false;

////////////////////////////////////////////////////////////
//
// comboItem
//
////////////////////////////////////////////////////////////

maskat.transComboItemTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.ComboClassのオブジェクト
  // のnameプロパティの値を取得する
  var comboName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.ComboClass){
      comboName = pathObjArray[i].name;
      break;
    }
  }
  if (comboName == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "comboItem(value:'" + attr.value +"')の親要素としてCombo要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transComboItemTag"});
  }

  output += comboName + ".addItem('" + attr.value + "', '" + attr.text + "');\n";

  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// codeLib
//
////////////////////////////////////////////////////////////

maskat.transCodeLibTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.codeLabel("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "width") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]=" + attr.name + ";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".divExt.tabIndex=-1;\n";
  output += attr.name + ".code.champs.tabIndex=" + num + ";\n";
  output += attr.name + ".code.champs.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";
  output += attr.name + ".img.divExt.tabIndex=" + num + ";\n";
  output += attr.name + ".img.divExt.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";  

  //// 子供の処理

  //// 後変換

  return output;
}


////////////////////////////////////////////////////////////
//
// radioGroup
//
////////////////////////////////////////////////////////////

maskat.transRadioGroupTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換
  output += attr.name + " = new maskat.RadioGroup('" + attr.name + "');\n";
  
  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var radioGroupObj = new maskat.RadioGroupClass(attr.name, num);
    pathObjArray.push(radioGroupObj);
    
    if (!maskat.radioGroupHash){
      maskat.radioGroupHash = new Object();
    }
    if(!maskat.radioGroupIndexHash){
    	maskat.radioGroupIndexHash = new Object();
    }
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }
  
  //// 後変換
  return output;
}


maskat.RadioGroupClass = function(name, num){
  this.name = name;
  this.tabIndex=num;
}
maskat.RadioGroupClass.prototype.isContainer = false;


////////////////////////////////////////////////////////////
//
// radioMember
//
////////////////////////////////////////////////////////////

maskat.transRadioMemberTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.RadioGroupClassのオブジェクト
  // のnameプロパティの値を取得する
  var radioGroupName;
  var radioGroupIndex;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.RadioGroupClass){
      radioGroupName = pathObjArray[i].name;
      radioGroupIndex = pathObjArray[i].tabIndex;
      break;
    }
  }
  if (radioGroupName == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "radioMember(ref:'" + attr.ref +"')の親要素としてRadioGroup要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transRadioMemberTag"});
  }

  output += radioGroupName + ".addRadioMemberName('" + attr.ref + "');\n";
  
  maskat.radioGroupHash[attr.ref] = radioGroupName;
  maskat.radioGroupIndexHash[attr.ref] = radioGroupIndex;
  //// 子供の処理

  //// 後変換
  return output;
}


////////////////////////////////////////////////////////////
//
// radio
//
////////////////////////////////////////////////////////////

maskat.transRadioTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;
  
  var groupDefinedByRadioGroup = null;
  if (maskat.radioGroupHash){
    groupDefinedByRadioGroup = maskat.radioGroupHash[attr["name"]];
  }
  if (groupDefinedByRadioGroup==null){
      attr["group"]="";
  }else{
      attr["group"]=groupDefinedByRadioGroup;
  }
  
  output += attr.name + " = new rialto.widget.Radio("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + maskat.composeSingleParam(domElem, attr, "group") + ", "
                      + maskat.composeSingleParam(domElem, attr, "text") + ", "
                      + maskat.composeSingleParam(domElem, attr, "checked") + ", "
                      + maskat.composeSingleParam(domElem, attr, "className") + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";
  
  // add KeyNavi
  var num = -1;
  if(maskat.radioGroupIndexHash){
  	num = maskat.radioGroupIndexHash[attr["name"]];
  }
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".radio.tabIndex=" + num + ";\n";
//  output += attr.name + ".divExt.tabIndex=" + num + ";\n";
  output += attr.name + ".radio.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";this.click();}\n";
  		
  if (groupDefinedByRadioGroup!=null)
      output += groupDefinedByRadioGroup + ".addRadioMember(" + attr["name"] + ");\n";

  //// 子供の処理

  //// 後変換
  return output;
}

////////////////////////////////////////////////////////////
//
// checkbox
//
////////////////////////////////////////////////////////////

maskat.transCheckboxTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  output += attr.name + " = new rialto.widget.Checkbox("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + maskat.composeSingleParam(domElem, attr, "text") + ", "
                      + maskat.composeSingleParam(domElem, attr, "checked") + ", "
                      + maskat.composeSingleParam(domElem, attr, "className") + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  output += attr.name + ".checkbox.tabIndex=" + num + ";\n";
  output += attr.name + ".checkbox.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";
  
  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// alert
//
////////////////////////////////////////////////////////////

maskat.transAlertTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  output += attr.name + " = new rialto.widget.Alert("
                      + maskat.composeSingleParam(domElem, attr, "mess") + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  //// 子供の処理

  //// 後変換

  return output;
}

////////////////////////////////////////////////////////////
//
// divHtml
//
////////////////////////////////////////////////////////////

maskat.transDivHtmlTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  // "<rialto:divHtml><![CDATA[...]]></rialto:divHtml>"の"..."の部分を取得する
  var cdataValue = "";
  if (domElem.hasChildNodes()){
    for (var i = 0; i < domElem.childNodes.length; i++){
      if (domElem.childNodes[i].nodeType == 4){  // CDATA_SECTION
        cdataValue += domElem.childNodes[i].nodeValue;
      }
    }
  }
  if (cdataValue != ""){
    // cdataValueに改行が含まれると、3行下のinnerHTMLの文字列を作成した際に文字列が不正になるので、改行を取り除く
    cdataValue = maskat.removeNewLine(cdataValue);
  }
  
  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new maskat.widget.DivHtml("
                      + maskat.composeSingleParam(domElem, attr, "name") + ", "
                      + maskat.composeSingleParam(domElem, attr, "top") + ", "
                      + maskat.composeSingleParam(domElem, attr, "left") + ", "
                      + maskat.composeSingleParam(domElem, attr, "parent") + ", "
                      + "'" + cdataValue + "', "
                      + maskat.composeSingleParam(domElem, attr, "className") + ", "
                      + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";
  
  //// 子供の処理

  //// 後変換

  return output;
  
}

////////////////////////////////////////////////////////////
//
// treeview
//
////////////////////////////////////////////////////////////

maskat.transTreeviewTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Tree(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  tagIndexMap[attr.name]=num;
  output += attr.name + ".divExt.tabIndex=-1;\n";
  
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var treeviewObj = new maskat.TreeviewClass(attr.name, num);
    pathObjArray.push(treeviewObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.TreeviewClass = function(name){
  this.name = name;
}
maskat.TreeviewClass.prototype.isContainer = true;
maskat.TreeviewClass.prototype.getRefObj = function(){ return this.name; }

////////////////////////////////////////////////////////////
//
// treeNode
//
////////////////////////////////////////////////////////////

maskat.transTreeNodeTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.TreeviewClassのオブジェクト
  // のnameプロパティの値を取得する
  var treeviewName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.TreeviewClass){
      treeviewName = pathObjArray[i].name;
      break;
    }
  }
  
  if (treeviewName == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "treeNode(name:'" + attr.name +"')の親要素としてtreeview要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transTreeNodeTag"});
  }
  
  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " =layoutObj.components[\""+ treeviewName + "\"].createAndAddNode("
         + refObjName + ".id, " + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add KeyNavi
  var num = tagIndexMap[treeviewName];
  output += attr.name + ".DIVENTETE.tabIndex=" + num + ";\n";
  output += attr.name + ".DIVENTETE.onfocus = function(e){" +
  		"focusObj=" + attr.name + ";};\n";
  
  //// 子供の処理
  if (domElem.hasChildNodes()){
    // 自タグのオブジェクトを作成
    var treenodeObj = new maskat.TreeNodeClass(attr.name);
    pathObjArray.push(treenodeObj);

    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  return output;
}

maskat.TreeNodeClass = function(name){
  this.name = name;
}
maskat.TreeNodeClass.prototype.isContainer = true;
maskat.TreeNodeClass.prototype.getRefObj = function(){ return this.name; }


////////////////////////////////////////////////////////////
//
// grid
//
////////////////////////////////////////////////////////////

maskat.transGridTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  //// 子供の処理
  // 自タグのオブジェクトを作成
  var gridObj = new maskat.GridClass(attr.name);
  if (domElem.hasChildNodes()){
    pathObjArray.push(gridObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  if (gridObj.strEntete == "" && attr.TabEntete == undefined){
    throw new MaskatError({name: "Grid Error",
                           message: "grid(grid名:'" + domElem.tagName + "')のヘッダ列(列名)が未定義です。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridTag"});
  }
  else{
    gridObj.strEntete = "[" + gridObj.strEntete.substring(0, gridObj.strEntete.length - 2) + "]";
  }

  if (gridObj.strTabTypeCol == "" && attr.tabTypeCol == undefined){
    throw new MaskatError({name: "Grid Error",
                           message: "grid(grid名:'" + domElem.tagName + "')のヘッダ列(列属性)が未定義です。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridTag"});
  }
  else{
    gridObj.strTabTypeCol = "[" + gridObj.strTabTypeCol.substring(0, gridObj.strTabTypeCol.length - 2) + "]";
  }

  if (attr.TabEntete == undefined){
    attr.TabEntete = gridObj.strEntete;
  }
  if (attr.tabTypeCol == undefined){
    attr.tabTypeCol = gridObj.strTabTypeCol;
  }

  var strObjPar = maskat.composeParam(domElem, attr);

  output += attr.name + " = new rialto.widget.Grid(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";

  // add keyNavi
  var num = maskat.composeSingleParam(domElem, attr, "tabIndex");
  if(num >= 0){
  	rialto.widget.Form.prototype.tabIndex = num;
  }
  tagIndexMap[attr.name] = num;
  output += attr.name + ".divExt.tabIndex=-1;\n";
  output += attr.name + ".tableauHTML.tabIndex=-1;\n";
  	
  if (gridObj.strLignes != ""){
    gridObj.strLignes = "[" + gridObj.strLignes.substring(0, gridObj.strLignes.length - 2) + "]";
    output += "layoutObj.components[\""+attr.name + "\"].fillGrid(" + gridObj.strLignes + ");\n";
  }

  return output;
}

maskat.GridClass = function(name){
  this.name = name;
  this.strEntete = "";
  this.strTabTypeCol = "";
  this.strLignes = "";
}
maskat.GridClass.prototype.isContainer = false;
maskat.GridClass.prototype.appendStrEntete = function(str){ this.strEntete += str; }
maskat.GridClass.prototype.appendStrTabTypeCol = function(str){ this.strTabTypeCol += str; }
maskat.GridClass.prototype.appendStrLignes = function(str){ this.strLignes += str; }

////////////////////////////////////////////////////////////
//
// gridHeader
//
////////////////////////////////////////////////////////////

maskat.transGridHeaderTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);
  
/*  //// 子供の処理
  // 自タグのオブジェクトを作成
  var gridHeaderObj = new maskat.GridHeaderClass();
  if (domElem.hasChildNodes()){
    pathObjArray.push(gridHeaderObj);
    
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }*/

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.GridClassのオブジェクトを取得する
  var gridClassObj;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.GridClass){
      gridClassObj = pathObjArray[i];
      break;
    }
  }
  if (gridClassObj == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "gridHeader(title:'" + attr.title +"')の親要素としてgrid要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridHeaderTag"});
  }

  gridClassObj.appendStrEntete("'" + attr.title + "', ");
  //if (gridHeaderObj.cellCombo==""){
  gridClassObj.appendStrTabTypeCol("['" + attr.type + "', " + attr.width + "], ");
  //}else{
  //   gridClassObj.appendStrTabTypeCol("['" + attr.type + "', " + attr.width + ",[" +
  //           gridHeaderObj.cellCombo.substring(0,gridHeaderObj.cellCombo.length-2) + "]], ");
  //}

  //// 子供の処理

  //// 後変換

  return output;
}

/*maskat.GridHeaderClass = function(name){
  this.cellCombo = "";
}
maskat.GridHeaderClass.prototype.appendStrCellCombo = function(str){ this.cellCombo += str; }

maskat.transGridCellComboTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  // 属性の取得
  maskat.receiveAttributes(domElem, attr);
  
  // pathObjArrayの要素を降順に走査し、maskat.GridClassのオブジェクトを取得する
  var gridHeaderObj;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.GridHeaderClass){
      gridHeaderObj = pathObjArray[i];
      break;
    }
  }
  if (gridHeaderObj == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "gridCellCombo(value:'" + attr.value +"',text:'" + attr.text +"')の親要素としてgridHeader要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridCellComboTag"});
  }
  
  gridHeaderObj.appendStrCellCombo("['" + attr.value + "', '" + attr.text + "'], ");
  
  return output;
}*/

////////////////////////////////////////////////////////////
//
// gridLine
//
////////////////////////////////////////////////////////////

maskat.transGridLineTag = function(pathObjArray, domElem){
  var output = "";

  //// 属性の取得

  //// 前変換

  //// 子供の処理
  // 自タグのオブジェクトを作成
  var gridLineObj = new maskat.GridLineClass();
  if (domElem.hasChildNodes()){
    pathObjArray.push(gridLineObj);
    // 全ての子供の処理
    output += maskat.transChildNodes(pathObjArray, domElem);
  }

  //// 後変換

  // pathObjArrayの要素を降順に走査し、maskat.GridClassのオブジェクトを取得する
  var gridClassObj;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.GridClass){
      gridClassObj = pathObjArray[i];
      break;
    }
  }
  if (gridClassObj == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "gridLineの親要素としてgrid要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridLineTag"});
  }

  if (gridLineObj.strLigne != ""){
    gridLineObj.strLigne = gridLineObj.strLigne.substring(0, gridLineObj.strLigne.length - 2);
  }
  gridClassObj.appendStrLignes("[" + gridLineObj.strLigne + "], ");

  return output;
}


maskat.GridLineClass = function(){
  this.strLigne = "";
}
maskat.GridLineClass.prototype.isContainer = false;
maskat.GridLineClass.prototype.appendStrLigne = function(str){ this.strLigne += str; }


////////////////////////////////////////////////////////////
//
// gridCell
//
////////////////////////////////////////////////////////////

maskat.transGridCellTag = function(pathObjArray, domElem){
  var output = "";
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、maskat.GridLineClassのオブジェクトを取得する
  var gridLineClassObj;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i] instanceof maskat.GridLineClass){
      gridLineClassObj = pathObjArray[i];
      break;
    }
  }
  if (gridLineClassObj == undefined){
    throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "gridCell(value:'" + attr.value + "')の親要素としてgridLine要素がありません。",
                           fileName: "layoutXMLInterpreter.js",
                           functionName: "maskat.transGridCellTag"});
  }

  gridLineClassObj.appendStrLigne("'" + attr.value + "', ");

  //// 子供の処理

  //// 後変換

  return output;
}


////////////////////////////////////////////////////////////
//
// javaScript
//
////////////////////////////////////////////////////////////

maskat.transJavaScriptTag = function(pathObjArray, domElem){
  var output = "";

  //// 属性の取得

  //// 前変換

  // "<rialto:javaScript><![CDATA[...]]></rialto:javaScript>"の"..."の部分を取得する
  if (domElem.hasChildNodes()){
    for (var i = 0; i < domElem.childNodes.length; i++){
      if (domElem.childNodes[i].nodeType == 4){  // CDATA_SECTION
        output += domElem.childNodes[i].nodeValue + "\n";
      }
    }
  }

  //// 子供の処理

  //// 後変換

  return output;
}


////////////////////////////////////////////////////////////
//
// desc
//
////////////////////////////////////////////////////////////

maskat.transDescTag = function(pathObjArray, domElem){
  return "";
}


////////////////////////////////////////////////////////////
//
// 共通関数
//
////////////////////////////////////////////////////////////

maskat.receiveAttributes = function(domElem, attr){
  // ユーザ指定の属性値の設定
  for(var i = 0; i < domElem.attributes.length; i++){
    var attrName = domElem.attributes[i].nodeName;
    var attrValue = domElem.attributes[i].nodeValue;
    attr[attrName] = attrValue;
  }

  // デフォルト値があり、かつユーザが未設定の属性は、そのデフォルト値を設定
  var allAttr = maskat.syntax[domElem.nodeName];
  for(var allAttrItem in allAttr){
    if(allAttr[allAttrItem].def != undefined && attr[allAttrItem] == undefined){
      attr[allAttrItem] = allAttr[allAttrItem].def;
    }
  }
}

maskat.composeParam = function(domElem, attr){
  var strObjPar = "{";

  for(var attrItem in attr){
    var attrItemType = maskat.syntax[domElem.nodeName][attrItem].type;
    var alias = maskat.syntax[domElem.nodeName][attrItem].alias;
    var attributeName = attrItem;
    if (alias!=null)
       attributeName = alias;
    if (attrItemType == "string" || attrItemType == "enum"){
      strObjPar += attributeName + ":'" + attr[attrItem] + "', ";
    }
    else{
        if ((attr[attrItem]+"" !== ""))
//        if (attr[attrItem]!=null && attr[attrItem]!="")
          strObjPar += attributeName + ":" + attr[attrItem] + ", ";
    }
  }

  strObjPar = strObjPar.substring(0, strObjPar.length - 2);  //最後の", "を取り除く
  strObjPar += "}";
  
  return strObjPar;
}

maskat.composeSingleParam = function(domElem, attr, attrName){

  // 未定義の属性はnullに設定する
  if(attr[attrName] == undefined){
    return null;
  }
  var attrType = maskat.syntax[domElem.nodeName][attrName].type;
  if (attrType == "string" || attrType == "enum"){
    return "'" + attr[attrName] + "'";
  }
  else{
    if (attr[attrName]==""){
        return null; 
        // new rialto.widget.XXX('xx', 0, 00, parent, '', 'ラジオボックス',   , '');
        //　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　~~~を避けるために
    }
    return attr[attrName];
  }
}

maskat.transChildNodes = function(pathObjArray, domElem){
  var output = "";

  var processingLayoutChild = false;
  var layoutName = null;
  var parentObj = pathObjArray[pathObjArray.length-1];
  if (parentObj instanceof maskat.LayoutClass){
      processingLayoutChild = true;
      layoutName = parentObj.name;
  }
  // 各子供を順番に処理
  for (var i = 0; i < domElem.childNodes.length; i++){
    var domElemNext = domElem.childNodes[i];

    if(domElemNext.nodeType != 1){  // ELEMENT_NODE以外は無視
      continue;
    }

    var domElemNextNodeName = domElemNext.nodeName;

    var nextTransMethodName
      = "maskat.trans"
           + domElemNextNodeName.charAt(0).toUpperCase()
           + domElemNextNodeName.substring(1, domElemNextNodeName.length)
           + "Tag"

    /* maskat.interpretLayoutXML関数の最初でmaskat.syntax.validate関数を実行していれば以下のチェックは不要。
    if (eval(nextTransMethodName) == undefined){
      throw new MaskatError({name: "layoutXML Syntax Error",
                             message: "要素名'" + domElemNext.nodeName + "'は不正です。",
                             fileName: "layoutXMLInterpreter.js",
                             functionName: "maskat.transChildNodes"});
    }
    */

    // pathObjArrayの要素数を保存
    var pathObjArraylength = pathObjArray.length;

    output += eval(nextTransMethodName + "(pathObjArray, domElemNext)");
    
    if (processingLayoutChild==true){
        //レイアウトのレベル１子ノード
        var nameNode = domElemNext.getAttributeNode("name");
        if (nameNode!=null){
            var childName = nameNode.nodeValue;
            output += "maskat.layouts[\"" + layoutName + "\"].componentsLevel1[\""+childName+"\"] " + 
                  "= maskat.layouts[\"" + layoutName + "\"].components[\""+childName+"\"];\n";
        }
    }

    // pathObjArrayを、子供の処理をする前の状態に戻す
    while(pathObjArraylength < pathObjArray.length){
      pathObjArray.pop();
    }

  }
  
  return output;
}

maskat.removeNewLine = function(str){
  while (str.indexOf("\r") != -1){
    str = str.substring(0, str.indexOf("\r")) + str.substring(str.indexOf("\r") + 1, str.length);
  }
  while (str.indexOf("\n") != -1){
    str = str.substring(0, str.indexOf("\n")) + str.substring(str.indexOf("\n") + 1, str.length);
  }
  return str;
}

/**
 * JavaScriptオブジェクトとRialtoオブジェクトをWrapして統一のインターフェースを提供する。
 */

function ObjWrapper(object){
  this.obj = object;
}

ObjWrapper.prototype.isMultiSelect = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        return this.obj.multiSelect; // [RialtoAPI依存]
      case "treeview":
        return false; // treeviewは現状、複数選択不可能
      default:
        break;
    }
  }
  throw new MaskatError({name: "Type Error",
                         message: "このオブジェクトに対してこの関数は実行できません。",
                         fileName: "objWrapper.js",
                         functionName: "ObjWrapper.prototype.isMultiSelect"});
}

ObjWrapper.prototype.isSingleDataObj = function(){
  if (maskat.isRialtoObj(this.obj)){
    // this.objはRialtoオブジェクト
    switch (this.obj.type){  // [RialtoAPI依存]
      case "label":
      case "text":
      case "combo":
      case "checkbox":
      case "radioGroup":
      case "codelib":
      case "divHtml":
        return true;
      default:
      	if(this.obj.isSingle){
      		return true;
      	}
        return false;
    }
  }
  else {
    // this.objはJavaScriptオブジェクト
    return !maskat.isArray(this.obj);
  }
}

ObjWrapper.prototype.isMultiDataObj = function(){
  if (maskat.isRialtoObj(this.obj)){
    // this.objはRialtoオブジェクト
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
      case "treeview":
        return true;
      default:
      	if(this.obj.isMulti){
      		return true;
      	}
        return false;
    }
  }
  else {
    // this.objはJavaScriptオブジェクト
    return maskat.isArray(this.obj);  // TODO: 2次元配列指定にする？
  }
}


ObjWrapper.prototype.getSingleValue = function(){
  if (!this.isSingleDataObj()){
    throw new MaskatError({name: "Type Error",
                           message: "複数データ型のオブジェクトに対してこの関数は実行できません。",
                           fileName: "objWrapper.js",
                           functionName: "ObjWrapper.prototype.getSingleValue"});
  }
  else {
    if (maskat.isRialtoObj(this.obj)){
      switch (this.obj.type){
        case "label":
          return this.obj.text;  // [RialtoAPI依存] getterAPIがないので直接textプロパティを参照
        case "text":
          return this.obj.getValue();  // [RialtoAPI依存] rialto.widget.Text.prototype.getValue
        case "combo":
          return this.obj.getSelValue();  // [RialtoAPI依存] rialto.widget.Combo.prototype.getSelValue
        case "checkbox":
          // boolean値ではなく文字列として返す
          return "" + this.obj.isCheck();  // [RialtoAPI依存] rialto.widget.Checkbox.prototype.getCheck, rialto.widget.Radio.prototype.getCheck
        case "radioGroup":
          return this.obj.getSelValue();
        case "codelib":
          return this.obj.getValue();
        default:
          if(this.obj.getSingleValue){
            return this.obj.getSingleValue();
          }
          break;
      }
    }
    else{
      // JavaScriptオブジェクト
      return this.obj;
    }
  }
}

ObjWrapper.prototype.setSingleValue = function(val){
  if (!this.isSingleDataObj()){
    throw new MaskatError({name: "Type Error",
                           message: "複数データ型のオブジェクトに対してこの関数は実行できません。",
                           fileName: "objWrapper.js",
                           functionName: "ObjWrapper.prototype.setSingleValue"});
  }
  else {
    if (maskat.isRialtoObj(this.obj)){
      switch (this.obj.type){  // [RialtoAPI依存]
        case "label":
          this.obj.setText(val);  // [RialtoAPI依存] rialto.widget.Label.prototype.setText
          break;
        case "text":
          this.obj.setValue(val);  // [RialtoAPI依存] rialto.widget.Text.prototype.setValue
          break;
        case "combo":
          this.obj.selWithValue(val);  // [RialtoAPI依存] rialto.widget.Combo.prototype.selWithValue
          break;
        case "checkbox":
          if (val == "true"){
            this.obj.setCheck(true);  // [RialtoAPI依存] rialto.widget.Checkbox.prototype.setCheck, rialto.widget.Radio.prototype.setCheck
          }
          else {
            this.obj.setCheck(false);  // [RialtoAPI依存] rialto.widget.Checkbox.prototype.setCheck, rialto.widget.Radio.prototype.setCheck
          }
          break;
        case "radioGroup":
          this.obj.setSelValue(val);
          break;
        case "divHtml":
          this.obj.setElement(val);
          break;
        default:
          if(this.obj.setSingleValue){
            this.obj.setSingleValue(val);
          }
          break;
      }
    }
    else{
      // TODO: JavaScriptオブジェクトへのsetValue
      throw new Error("非rialtoオブジェクトはsetValueできない。"+this.obj.base);
    }
  }
}

ObjWrapper.prototype.setMultiValue = function(val){
  if (!this.isMultiDataObj()){
    throw new MaskatError({name: "Type Error",
                           message: "単一データ型のオブジェクトに対してこの関数は実行できません。",
                           fileName: "objWrapper.js",
                           functionName: "ObjWrapper.prototype.setValue"});
  }
  else {
    if (maskat.isRialtoObj(this.obj)){
      switch (this.obj.type){  // [RialtoAPI依存]
        case "grid":
          this.setGridValue(val);
          break;
        case "treeview":
          this.setTreeValue(val);
          break;
        default:
          if(this.obj.setMultiValue){
            return this.obj.setMultiValue(val);
          }
          break;
      }
    }
    else{
      // TODO: JavaScriptオブジェクトへのsetValue
    }
  }
}


ObjWrapper.prototype.setTreeValue = function(val){
  try {
    // 現在のツリーの全てのノードを削除
    if (this.obj.rootNode != null){  // [RialtoAPI依存]
        this.obj.rootNode.remove();  // このAPIでいいのか要チェック
        this.obj.rootNode = null;
    }

    for (var i = 0; i < val.length; i++){
      var parentName;
      if (!val[i]["PARENT"]){
        // ルートノードの場合
        parentName = this.obj.name;
      }
      else {
        parentName = val[i]["PARENT"];
      }
      eval(val[i]["NAME"] + "= " + this.obj.name + ".createAndAddNode(" + parentName + ".id,{name:'" + val[i]["NAME"] + "',text:'" + maskat.escapeDoubleQuote(val[i]["TEXT"]) + "',icon:'images/imTreeview/pict_synthetik_off.gif',icon2:'',open:true,reload:false,onclick:''});" );  // [RialtoAPI依存]
      
      // add keyNavi
      var num = tagIndexMap[this.obj.name];
	  output = "";
	  output += val[i]["NAME"] + ".DIVENTETE.tabIndex=" + num + ";\n";
      output += val[i]["NAME"] + ".DIVENTETE.onfocus = function(e){" +
  		   "focusObj=" + val[i]["NAME"] + ";};\n";
      eval(output);
      
      for (var key in val[i]){
        if (key.charAt(0) == "_"){
          if(!(eval(val[i]["NAME"] + ".maskatHiddenField"))){
            eval(val[i]["NAME"] + ".maskatHiddenField = new Object();");
          }
          eval(val[i]["NAME"] + ".maskatHiddenField['" + key + "'] = '" + val[i][key] + "';");
        }
      }
      
    }
  }
  catch (e){
    throw e;
  }
}

ObjWrapper.prototype.setGridValue = function(val){
  try {
    if (val.length==0){
        this.obj.deleteLines();
        return;
    }
    var gridJSStr = "[";
    for (var i = 0; i < val.length; i++){
      gridJSStr += "[";
      for (var j in val[i]){
        var colIndex = parseInt(j);
        if (!isNaN(colIndex)) {// && colIndex < this.obj.NbreCol){  // [RialtoAPI依存] Gridオブジェクトの列数
          gridJSStr += '"' + maskat.escapeDoubleQuote(val[i][j]) + '",';  // TODO: itemValueから"を\"に変換
        }
      }
      gridJSStr = gridJSStr.substring(0, gridJSStr.length - 1);  // 最後の','を取り除く
      gridJSStr += "],";
    }
    gridJSStr = gridJSStr.substring(0, gridJSStr.length - 1);  // 最後の','を取り除く
    gridJSStr += "]";

    eval("this.obj.fillGrid(" + gridJSStr + ", 0, false)");
  }
  catch (e){
    throw e;
  }
}

ObjWrapper.prototype.getSelectedIndex = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        return this.obj.indLineClic; // [RialtoAPI依存]
      case "treeview":
        if (this.obj.currentSelNode){
          return maskat.getTreeRowNumByName(this.obj, this.obj.currentSelNode.name);
        }
        else {
          return -1;
        }
      default:
        break;
    }
  }
  throw new MaskatError({name: "Type Error",
                         message: "このオブジェクトに対してこの関数は実行できません。",  // TODO: 詳細に
                         fileName: "objWrapper.js",
                         functionName: "ObjWrapper.prototype.getSelectedIndex"});
}


maskat.getTreeRowNumByName = function(treeview, name){
  if (!treeview.rootNode){
    return -1;
  }
  
  var treeNodeStack = new Array();
  treeNodeStack.push(treeview.rootNode);
  
  var rowNum = -1;
  
  while (treeNodeStack.length != 0){
    var treeNode = treeNodeStack.pop();
    rowNum++;
    if (treeNode.name == name){
      return rowNum;
    }
    else {
      if (treeNode.hasChild()){  // [RialtoAPI依存]
        for (var i = treeNode.arrChildNode.length - 1; i >= 0 ; i--){
          treeNodeStack.push(treeNode.arrChildNode[i]);
        }
      }
    }
  }
  
  // 最終的に見つからなかった場合(ありえない)
  return -1;
}


ObjWrapper.prototype.getSelectedIndexes = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        var indexArray = new Array();
        for (var i = 0; i < this.obj.tabData.length; i++){ // [RialtoAPI依存]
          var lineData = this.obj.tabData[i]; // [RialtoAPI依存]
          if (lineData.sel == true){ // [RialtoAPI依存]
            indexArray.push(i);
          }
        }
        return indexArray;
      case "treeview":
        // TODO: 
      default:
        break;
    }
  }

  throw new MaskatError({name: "Type Error",
                         message: "このオブジェクトに対してこの関数は実行できません。",  // TODO: 詳細に
                         fileName: "objWrapper.js",
                         functionName: "ObjWrapper.prototype.getSelectedIndexes"});
}

ObjWrapper.prototype.getColNum = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        return this.obj.NbreCol;  // [RialtoAPI依存]
      case "treeview":
        // TODO: 対象APIを探す。
      default:
        break;
    }
  }
  
  throw new MaskatError({name: "Type Error",
                         message: "このオブジェクトに対してこの関数は実行できません。",  // TODO: 詳細に
                         fileName: "objWrapper.js",
                         functionName: "ObjWrapper.prototype.getColLength"});
}

ObjWrapper.prototype.getRowNum = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        if (this.obj.tabData){ // [RialtoAPI依存]
          return this.obj.tabData.length;  // [RialtoAPI依存]
        }
        else {
          return 0;
        }
      case "treeview":
        return maskat.countDescendantTreeNode(this.obj);
      default:
        break;
    }
  }
  else if (maskat.isArray(this.obj)){
    return this.obj.length;
  }
  
  throw new MaskatError({name: "Type Error",
                         message: "このオブジェクトに対してこの関数は実行できません。",  // TODO: 詳細に
                         fileName: "objWrapper.js",
                         functionName: "ObjWrapper.prototype.getRowNum"});
}


maskat.countDescendantTreeNode = function(treeview){
  if (!treeview.rootNode){  // [RialtoAPI依存]
    return 0;
  }

  var num = 0;
  var treeNodeArray = new Array();
  treeNodeArray.push(treeview.rootNode);  // [RialtoAPI依存]

  while (treeNodeArray.length != 0){
    treeNode = treeNodeArray.shift();
    num++;
    if (treeNode.hasChild()){
      for (var i = 0; i < treeNode.arrChildNode.length; i++){  // [RialtoAPI依存]
        treeNodeArray.push(treeNode.arrChildNode[i]);
      }
    }
  }
  return num;
}

ObjWrapper.prototype.getValueFromMultiData = function(row, col){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){ // [RialtoAPI依存]
      case "grid":
        return this.obj.tabData[row][col];  // [RialtoAPI依存]
      case "treeview":
        // row:行数, col:fromkey(ID/TEXT/PARENT)
        var treeNode = maskat.findTreeNodeByRowNum(this.obj, row);  // 同じ引数でfromkey分呼ばれるのでキャッシュすべき
        if (!treeNode){
          return null;
        }
        
        if (col.charAt(0) == "_"){
          if (!treeNode.maskatHiddenField){
            return "";
          }
          return treeNode.maskatHiddenField[col];
        }
        else{
          switch (col){
            case "NAME":
              return treeNode.name;
            case "TEXT":
              return treeNode.text;
            case "PARENT":
              if (treeNode.fatherNode){
                return treeNode.fatherNode.name;
              }
              else {
                return null;
              }
            default:
              throw new MaskatError({name: "EventXML Syntax Error",
                                     message: "Treeviewオブジェクトに対するfromkey'" + col + "'は未対応です。",
                                     fileName: "objWrapper.js",
                                     functionName: "ObjWrapper.prototype.getValueFromMultiData"});
          }
        }
      default:
        break;
    }
  }
  else if (maskat.isArray(this.obj)){  // TODO: 2次元配列チェックする？
    return this.obj[row][col];
  }
  else {
    throw new MaskatError({name: "Type Error",
                           message: "このオブジェクトに対してこの関数は実行できません。",  // TODO: 詳細に
                           fileName: "objWrapper.js",
                           functionName: "ObjWrapper.prototype.getValueFromMultiData"});
  }
}

maskat.findTreeNodeByRowNum = function(treeview, row){
  if (!treeview.rootNode || row == -1){
    return null;
  }
  
  var treeNodeStack = new Array();
  treeNodeStack.push(treeview.rootNode);

  var currentRow = -1;

  while (treeNodeStack.length != 0){
    var treeNode = treeNodeStack.pop();
    currentRow++;
    if (currentRow == row){
      return treeNode;
    }
    else {
      if (treeNode.hasChild()){  // [RialtoAPI依存]
        for (var i = treeNode.arrChildNode.length - 1; i >= 0 ; i--){
          treeNodeStack.push(treeNode.arrChildNode[i]);
        }
      }
    }
  }

  return null;

}




ObjWrapper.prototype.isJSObj = function(){
  return !maskat.isRialtoObj(this.obj);  // 将来Rialto以外のライブラリを利用する際は変更する
}

ObjWrapper.prototype.clear = function(){
  if (maskat.isRialtoObj(this.obj)){
    switch (this.obj.type){
      case "label":
        this.obj.setText("");  // [RialtoAPI依存] rialto.widget.Label.prototype.setText
        break;
      case "text":
        this.obj.setValue("");  // [RialtoAPI依存] rialto.widget.Text.prototype.setValue
        break;
      case "checkbox":
        this.obj.setCheck(false);  // [RialtoAPI依存] rialto.widget.Checkbox.prototype.setCheck, rialto.widget.Radio.prototype.setCheck
        break;
      case "radioGroup":
        this.obj.initRadio();
        break;
      case "grid":
        this.obj.initTab();
        break;
      case "treeview":
        if (this.obj.rootNode){  // [RialtoAPI依存]
          this.obj.rootNode.remove();  // このAPIでいいのか要チェック
          this.obj.rootNode = null;
        }
        break;
    }
  }
}

maskat.isRialtoObj = function(obj){
  return (obj && (typeof obj == "object") && (obj instanceof rialto.widget.AbstractComponent));
}

maskat.isArray = function(obj) {
  return (obj && (typeof obj == "object") && (obj.constructor == Array));
}

maskat.escapeDoubleQuote = function(str){
  return(str.split('"').join('\\"'));
}

//受信電文コンシューマー
//受信電文ノードからデータを取得して、オブジェクトに入れる
ObjWrapper.pluggableTeleConsumers={};

ObjWrapper.registerTeleConsumer = function(name,teleConsumer){
    ObjWrapper.pluggableTeleConsumers[name]=teleConsumer;
}

ObjWrapper.unregisterTeleConsumer = function(name){
    ObjWrapper.pluggableTeleConsumers[name]=null;
}

ObjWrapper.findTeleConsumer = function(teleType){
    return ObjWrapper.pluggableTeleConsumers[teleType];
}

//送信電文maker
//オブジェクトからデータを取得して、受信電文を組み立てる
ObjWrapper.pluggableTeleMakers={};

ObjWrapper.registerTeleMaker = function(name,maker){
    ObjWrapper.pluggableTeleMakers[name]=maker;
}

ObjWrapper.unregisterTeleMaker = function(name){
    ObjWrapper.pluggableTeleMakers[name]=null;
}

ObjWrapper.findTeleMaker = function(teleType){
    return ObjWrapper.pluggableTeleMakers[teleType];
}


//ワーカー、ローカルデータバインディング処理
ObjWrapper.pluggableLocalWorkers={};

ObjWrapper.registerLocalWorker = function(name,localWorker){
    ObjWrapper.pluggableLocalWorkers[name]=localWorker;
}

ObjWrapper.unregisterLocalWorker = function(name){
    ObjWrapper.pluggableLocalWorkers[name]=null;
}

ObjWrapper.findLocalWorker = function(workType){
    return ObjWrapper.pluggableLocalWorkers[workType];
}

maskat.soap={};

maskat.soap.wrapMessage = function(xmlMessage,paramNode){
    var prev = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\">"+
        " <soap:Body>";
    return prev + xmlMessage + "</soap:Body></soap:Envelope>";
}

/**
 * 受信電文(soapの場合)から、soap bodyのDOMノードを取得
 * 
 * @param teleDOM 受信電文
 * @return bodyの中身ノード
 */
maskat.soap.unwrapDOM = function(teleDOM,resultNode){
    var children = teleDOM.childNodes;
    var hasBody = false;
    for (var i=0;i<children.length;i++){
        if (children[i].nodeName.indexOf("Body")!=-1){
            //SOAP仕様にしたがって、SOAPメッセージには、HeaderとBody二つ子要素しかないので、
            //nodeNameに「Body」があれば、Body要素であるはず。
            hasBody=true;
            if (children[i].childNodes.length==0){
                throw new MaskatError({name: "Received Tele Error",
                               message: "受信SOAPメッセージのBody要素には子要素がありません。",
                               fileName: "soap.js",
                               functionName: "maskat.soap.unwrapDOM"});
            }
            return children[i].childNodes[0];
        }
    }
    if (!hasBody){
        throw new MaskatError({name: "Received Tele Error",
                       message: "受信SOAPメッセージのBody要素はありません。",
                       fileName: "soap.js",
                       functionName: "maskat.soap.unwrapDOM"});
    }
}
 
 /**
 * デフォルトのエラー処理関数(alertで全部のエラーを表示)
 * maskat.validationErrorHandlerカスタマイズすることができます。
 */
maskat.validationErrorHandler=function(errors){
	for (var i=0;i<errors.length;i++){
		var error = errors[i];
		alert(error.vTarget.desc+ " " + error.message);
	}
}

maskat.getValidator = function(throwOnErrorPar){
    var validator = maskat.globalVar.validator;
    validator.throwOnError = throwOnErrorPar;
    validator.exValidators = new Object;
    validator.errors = new Array;
    return validator;
}

/**
 * validationエラー
 */
maskat.ValidationError = function(vTarget,message){
    this.vTarget = vTarget;
    this.message = message;
}
maskat.ValidationError.prototype = new Error;

/**
 * NullValidatorはvalidation操作何もしない
 * それを使えば、validationを無効にすることができます
 */
maskat.NullValidator=function(){
    this.throwOnError=false;
    this.errors = new Array;
};
maskat.NullValidator.prototype.acceptError = function(error){
    //何もしない
}
maskat.NullValidator.prototype.validate=function(objName,value,type,desc){
    //何もしない。
}
maskat.NullValidator.prototype.regValidator=function(value,type){
    //何もしない。
}

/**
 * デフォルトvalidationオブジェクト
 */
maskat.DefaultValidator=function(){
    this.throwOnError = true;
    //true:バリデーションエラーがあったら、すぐthrow new Error
    //false:バリデーションエラーがあったら、validatorに保存する
    this.exValidators = new Object;
    this.errors = new Array;
}

maskat.DefaultValidator.prototype.acceptError = function(error){
    this.errors.push(error);
}

/**
 * カスタマイズvalidatorを登録することができます。
 * 拡張validatorを登録する
 */
maskat.DefaultValidator.prototype.regValidator=function(typeName,validator){
    this.exValidators[typeName] = validator;
}

maskat.DefaultValidator.prototype.validate=function(objName,value,type,desc,min,max,regexp){
    var vTarget = new Object;//validation target
    vTarget.objName = objName;
    vTarget.value = value;
    vTarget.desc = desc;
    vTarget.minVal = parseInt(min);
    vTarget.maxVal = parseInt(max);
    vTarget.regexp = regexp;
    try{
        if (type=="byte"){
            this.validateByte(vTarget);
        }
        if (type=="short"){
            this.validateShort(vTarget);
        }
        if (type=="int"){
            this.validateInt(vTarget);
        }
        if (type=="long"){
            this.validateLong(vTarget);
        }
        if (type=="float"){
            this.validateFloat(vTarget);
        }
        if (type=="string"){
            this.validateString(vTarget);
        }
        if (type=="date"){
            this.validateDate(vTarget);
        }
        if (type=="time"){
            this.validateTime(vTarget);
        }
        //拡張validatorでバリデーション
        var exValidator = this.exValidators[type];
        if (exValidator)
            exValidator.validate(vTarget);
    }catch(e){
       if (e instanceof maskat.ValidationError){
           if (!this.throwOnError){
              this.acceptError(e);
              return;
           }
       }
       throw e;
    }

}

maskat.DefaultValidator.prototype.validateIntegralNumRange=function(vTarget,minVal,maxVal,minLength,maxLength){
    if (!this.isIntegralNum(vTarget.value)) {
        throw new maskat.ValidationError(vTarget,"数字チェックに失敗しました。");
    }else{
        if (!isNaN(minLength)){
            if (vTarget.value.length<minLength)
               throw new maskat.ValidationError(vTarget,"長さチェック失敗。最小桁数："+minLength);
        }
        if (!isNaN(maxLength)){
            if (vTarget.value.length>maxLength)
                throw new maskat.ValidationError(vTarget,"長さチェック失敗。最大桁数："+maxLength);
        }
        var iValue = parseInt(vTarget.value);
        if (isNaN(iValue) || !(iValue >= minVal && iValue <= maxVal)) {
            throw new maskat.ValidationError(vTarget,"データの範囲不正(" + 
                minVal + " ... " + maxVal + ")。");
        }
    }
}

maskat.DefaultValidator.prototype.validateByte=function(vTarget){
    this.validateIntegralNumRange(vTarget,-128,127,vTarget.minVal,vTarget.maxVal);
}

maskat.DefaultValidator.prototype.validateShort=function(vTarget){
    this.validateIntegralNumRange(vTarget,-32768,32767,vTarget.minVal,vTarget.maxVal);
}

maskat.DefaultValidator.prototype.validateInt=function(vTarget){
    this.validateIntegralNumRange(vTarget,-2147483648,2147483647,vTarget.minVal,vTarget.maxVal);
}

maskat.DefaultValidator.prototype.validateLong=function(vTarget){
    this.validateIntegralNumRange(vTarget,-9223372036854775808,9223372036854775807,vTarget.minVal,vTarget.maxVal);
    //注：javascriptの整数はdouble-precision、16位のprecisionだけ。
    //だから、longチェックは-9223372036854776000~9223372036854776000の範囲になってしまう
}

maskat.DefaultValidator.prototype.validateFloat=function(vTarget){
    //vTargetは正しい数字であろうかチェック....
    // remove '.' before checking digits
    var tempArray = vTarget.value.split('.');
    if (tempArray.length>2){
        throw new maskat.ValidationError(vTarget,"floatチェック失敗。");
    }
    //Strip off leading '0'
    var zeroIndex = 0;
    var joinedString= tempArray.join('');
    while (joinedString.charAt(zeroIndex) == '0') {
        zeroIndex++;
    }
    var noZeroString = joinedString.substring(zeroIndex,joinedString.length);

    if (!this.isIntegralNum(noZeroString)) {
        throw new maskat.ValidationError(vTarget,"floatチェック失敗。");
    }
    var iValue = parseFloat(vTarget.value);
    if (isNaN(iValue)) {
        throw new maskat.ValidationError(vTarget,"floatチェック失敗。");
    }
}

maskat.DefaultValidator.prototype.isIntegralNum = function(argvalue) {
    argvalue = argvalue.toString();
    var validChars = "0123456789";
    var startFrom = 0;
    if (argvalue.charAt(0) == "0") {
        return false;
    }
    if (argvalue.charAt(0) == "-") {
        startFrom = 1;
    }

    for (var n = startFrom; n < argvalue.length; n++) {
        if (validChars.indexOf(argvalue.substring(n, n+1)) == -1) return false;
    }
    return true;
}

maskat.DefaultValidator.prototype.validateTime=function(vTarget){
    var bValid = true;
    var timeRegexp = new RegExp("^(\\d{2})[:](\\d{2})[:](\\d{2})$");
    var matched = timeRegexp.exec(vTarget.value);
    if (matched!=null){
        if (!isValidTime(matched[1],matched[2],matched[3])){
            bValid=false;
        }
    } else {
        bValid=false;
    }
     if (!bValid)
        throw new maskat.ValidationError(vTarget,"time チェック失敗。hh:mm:ss");
}

maskat.DefaultValidator.prototype.validateString=function(vTarget){
    if (!vTarget.value instanceof String){
        alert("vTarget.valueはStringではありません。チェックできません。");
        return;
    }
    if (!isNaN(vTarget.minVal)){
        if (vTarget.value.length<vTarget.minVal)
           throw new maskat.ValidationError(vTarget,"長さチェック失敗。最小文字数："+vTarget.minVal);
    }
    if (!isNaN(vTarget.maxVal)){
        if (vTarget.value.length>vTarget.maxVal)
            throw new maskat.ValidationError(vTarget,"長さチェック失敗。最大文字数："+vTarget.maxVal);
    }
    
    var regexp = vTarget.regexp;
    if (regexp){
    	var regexpObj = new RegExp(regexp);
    	if (!vTarget.value.match(regexpObj)){
    		throw new maskat.ValidationError(vTarget,"入力フォーマット不正です。");
    	}
    }
//  throw new Error("定義不正：type=stringの場合、必ずmin或いはmaxを数字値で定義してください。");
}

maskat.DefaultValidator.prototype.validateDate=function(vTarget,datePattern) {
     var bValid = true;
     var MONTH = "MM";
     var DAY = "dd";
     var YEAR = "yyyy";
     var i = 0;
     var fields = new Array();

     if (datePattern == null)
         datePattern="yyyy-MM-dd";//デフォルトdatePattern

     var orderMonth = datePattern.indexOf(MONTH);
     var orderDay = datePattern.indexOf(DAY);
     var orderYear = datePattern.indexOf(YEAR);
     if ((orderDay < orderYear && orderDay > orderMonth)) {
         var iDelim1 = orderMonth + MONTH.length;
         var iDelim2 = orderDay + DAY.length;
         var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
         var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
         if (iDelim1 == orderDay && iDelim2 == orderYear) {
            dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$");
         } else if (iDelim1 == orderDay) {
            dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$");
         } else if (iDelim2 == orderYear) {
            dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$");
         } else {
            dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$");
         }
         var matched = dateRegexp.exec(vTarget.value);
         if(matched != null) {
            if (!isValidDate(matched[2], matched[1], matched[3])) {
               bValid =  false;
            }
         } else {
            bValid =  false;
         }
     } else if ((orderMonth < orderYear && orderMonth > orderDay)) {
         var iDelim1 = orderDay + DAY.length;
         var iDelim2 = orderMonth + MONTH.length;
         var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
         var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
         if (iDelim1 == orderMonth && iDelim2 == orderYear) {
             dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$");
         } else if (iDelim1 == orderMonth) {
             dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$");
         } else if (iDelim2 == orderYear) {
             dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$");
         } else {
             dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$");
         }
         var matched = dateRegexp.exec(vTarget.value);
         if(matched != null) {
             if (!isValidDate(matched[1], matched[2], matched[3])) {
                 bValid =  false;
              }
         } else {
             bValid =  false;
         }
     } else if ((orderMonth > orderYear && orderMonth < orderDay)) {
         var iDelim1 = orderYear + YEAR.length;
         var iDelim2 = orderMonth + MONTH.length;
         var delim1 = datePattern.substring(iDelim1, iDelim1 + 1);
         var delim2 = datePattern.substring(iDelim2, iDelim2 + 1);
         if (iDelim1 == orderMonth && iDelim2 == orderDay) {
             dateRegexp = new RegExp("^(\\d{4})(\\d{2})(\\d{2})$");
         } else if (iDelim1 == orderMonth) {
             dateRegexp = new RegExp("^(\\d{4})(\\d{2})[" + delim2 + "](\\d{2})$");
         } else if (iDelim2 == orderDay) {
             dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})(\\d{2})$");
         } else {
             dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{2})$");
         }
         var matched = dateRegexp.exec(vTarget.value);
         if(matched != null) {
             if (!isValidDate(matched[3], matched[2], matched[1])) {
                 bValid =  false;
             }
         } else {
              bValid =  false;
         }
     } 
     if (!bValid)
        throw new maskat.ValidationError(vTarget,"dateチェック失敗。"+datePattern);
}

function isValidDate(day, month, year) {
    if (month < 1 || month > 12) {
        return false;
    }
    if (day < 1 || day > 31) {
        return false;
    }
    if ((month == 4 || month == 6 || month == 9 || month == 11) &&
        (day == 31)) {
        return false;
    }
    if (month == 2) {
        var leap = (year % 4 == 0 &&
           (year % 100 != 0 || year % 400 == 0));
        if (day>29 || (day == 29 && !leap)) {
            return false;
        }
    }
    return true;
}

function isValidTime(hour,minute,second){
    if (hour < 0 || hour > 23)
        return false;
    if (minute < 0 || minute > 59)
        return false;
    if (second < 0 || second > 59)
        return false;
    return true;
}

maskat.globalVar.validator = new maskat.DefaultValidator();

/**
 * validation errorが検出されたら、onValidationErrorに
 */
//maskat.DefaultValidator.prototype.onValidationError=function(outputObj){
//    this.context.accept(outputObj);
//}

/**
 * 
 */
//maskat.ValidationContext=function(){
//    this.errors = new Array();
//}

//maskat.ValidationContext.prototype.accept=function(outputObj){
//    this.errors.push(outputObj);
//}

//maskat.ValidationContext.prototype.validationFeedback=function(){
//    for (var i=0;i<this.errors.length;i++){
//        alert(this.errors[i].objName+"のバリデーションに以下のようなエラー："+this.errors[i].message);
//    }
//}


maskat.widget={};

maskat.widget.DivHtml=function(name,top,left,parent,element,className,objPar){
	var objParam=new Object;
	objParam.name=name;
	objParam.type="divHtml";
	objParam.left=left;
	objParam.top=top;
	if(objPar!=null){objParam.position=objPar.position;}
	
	this.base=rialto.widget.AbstractComponent;
	this.base(objParam);
	objPar=null;
	objParam=null;
	this.element=element;
	if(className!=''&&className!=null){
		this.className=className;
	}
	else{
		this.className="libNormal";
	}
	var oThis=this;
	this.divExt.id=this.id+"_DivGen";
	this.divExt.style.position=this.position;
	this.divExt.style.left=this.left+"px";
	this.divExt.style.top=this.top+"px";
	this.divExt.className=this.className;
	this.divExt.innerHTML=this.element;
	this.divExt.style.whiteSpace="nowrap";
	if(parent){this.placeIn(parent);};
}
maskat.widget.DivHtml.prototype=new rialto.widget.AbstractComponent;
maskat.widget.DivHtml.prototype.setElement=function(element){
	this.element=element;
	this.divExt.innerHTML=this.element;
}

maskat.setForcus = function(e){
	if (!e) e=window.event;
	code = e.keyCode;
	if(focusObj){
		// ボタンの場合
		if(focusObj.type == "button"){
			if(code == 13 || code == 32){
				focusObj.divExt.onclick();
				return false;
			}
		// テキストの場合
		} else if(focusObj.type == "text"){
			// なし		
		// タブの場合
		} else if(focusObj.type == "tabFolder"){
			var currentActiveIndex = focusObj.indActiveTab;
			var maxIndex = focusObj.arrTabItem.length - 1;
			if(code == 39){
				if (currentActiveIndex < maxIndex){
	         		focusObj.activeTab(currentActiveIndex + 1);
	         		return false;
	        	}
			} else if(code == 37){
				if (currentActiveIndex > 0){
					focusObj.activeTab(currentActiveIndex - 1);
					return false;
				}			
			}
		// コードリブの場合
		} else if(focusObj.type == "codelib"){
			if(code == 13){
				focusObj.img.onclick();
			}
		// ラジオボタンの場合
		} else if(focusObj.type == "radio"){
			// なし
		// コンボボックスの場合
		} else if(focusObj.type == "combo"){
			// なし
		// ツリーノードの場合
		} else if(focusObj.type == "treenode"){
			if(code == 13 || code == 32){
				if(focusObj.hasChild()){
					focusObj.toggle();
					return false;
				} else {
					focusObj.click();
					return false;
				}
			} else if(code == 37){
				if(focusObj.hasChild() && focusObj.open){
					focusObj.toggle();
					return false;
				}
			} else if(code == 39){
				if(focusObj.hasChild() && !focusObj.open){
					focusObj.toggle();
					return false;
				}			
			} else if(code == 40){
				var next = null; 
				if(focusObj.hasChild() && focusObj.open){
					next = focusObj.first();
				} else {
					if(!focusObj.isLast()){
						next = focusObj.next();
					} else {
						var buff = focusObj.fatherNode;
						while(buff){
							if(!buff.isLast()){
								buff = buff.next();
								break;
							}
							buff = buff.fatherNode;
						}
						if(buff){
							next = buff;
						}
					}
				}
				if(next){
					next.DIVENTETE.focus();
					return false;
				}
			} else if(code == 38){
				var previous = null;
				if(focusObj.isFirst()){
					if(focusObj.fatherNode){
						previous = focusObj.fatherNode;
					}
				} else {
					var buff = focusObj.previous();
					while(buff.hasChild() && buff.open){
						buff = buff.last();
					}
					if(buff){
						previous = buff;
					}
				}
				if(previous){
					previous.DIVENTETE.focus();
					return false;
				}
			}
		// チェックボックスの場合
		} else if(focusObj.type == "checkbox"){
			if(code == 13){
				if(focusObj.checked){
					focusObj.setCheck(false, false);
					return false;
				} else {
					focusObj.setCheck(true, false);
					return false;
				}
			}
		// グリッドの場合
		} else if(focusObj.type == "grid"){
			if (focusObj.text != null){
				return true;
			}
			if(code == 13 || code == 32){
				focusObj.afterOnClick(focusObj.getLineIndex(focusNode), focusObj.getCellIndex(focusNode));
				return false;
			} else {
				var next = null;
				if(focusObj.cellActive){
					var currentActiveLineIndex = focusObj.getLineIndex(focusNode);
					var currentActiveColIndex = focusObj.getCellIndex(focusNode);
					var maxLineIndex = focusObj.NbreLig - 1;
					var maxColIndex = focusObj.NbreCol - 1;
					if(code == 37){
						if(0 < currentActiveColIndex){
							next = focusObj.getHtmlCellFromIndex(currentActiveLineIndex, --currentActiveColIndex);
						}
					} else if(code == 39){
						if(maxColIndex > currentActiveColIndex){
							next = focusObj.getHtmlCellFromIndex(currentActiveLineIndex, ++currentActiveColIndex);
						}
					} else if(code == 40){
						if(maxLineIndex > currentActiveLineIndex){
							next = focusObj.getHtmlCellFromIndex(++currentActiveLineIndex, currentActiveColIndex);
						}
					} else if(code == 38){
						if(0 < currentActiveLineIndex){
							next = focusObj.getHtmlCellFromIndex(--currentActiveLineIndex, currentActiveColIndex);
						}
					}
				} else {
					var currentActiveIndex = focusObj.getLineIndex(focusNode);
					var maxIndex = focusObj.NbreLig - 1;
					if(code == 40){
						if(maxIndex > currentActiveIndex){
							next = focusObj.getHtmlLineFromIndex(++currentActiveIndex);
						}
					} else if(code == 38){
						if(0 < currentActiveIndex){
							next = focusObj.getHtmlLineFromIndex(--currentActiveIndex);
						}
					}
				}
				if(next){
					next.focus();
					return false;
				}
			}
		}
		
	}
}


rialto.widget.Grid.prototype.refreshGrid = function () {
    this.deleteLines(true);
    this.idInt = 0;
    this.mapArray = new Array;
    if (this.navigation) {
        this.majZoneNavigation();
    }
    var tabINNERHTML = new Array();
    for (var i = this.debInd; i < this.finInd; i++) {
        tabINNERHTML.push(this.addLineWithINNER(i));
    }
    this.tableauHTML.innerHTML = tabINNERHTML.join("");
    this.updateLineCell();
    
    var oThis = this;
    num = tagIndexMap[this.name];
    for (var i = this.debInd; i < this.finInd; i++){
    	if (this.cellActive) {
    		for (var j = 0;j < this.NbreCol; j++) {
    			var node = this.getHtmlCellFromIndex(i,j);
    			node.tabIndex = num;
    			node.onfocus = function(e){
    				focusObj = oThis;
    				focusNode = this;
    			}
    		}
    	} else {
    		var line = this.getHtmlLineFromIndex(i);
    		line.tabIndex = num;
    		line.onfocus = function(e){
    			focusObj = oThis;
    			focusNode = this;
    		}
    	}
    }

};

/**
 * フレームワーク例外処理共通関数
 */
maskat.handleFrameworkError = function(message,e){
    if (e instanceof MaskatError){
       maskat.getFWLog().error(message
           + "\nname: " + e.name + "\nmessage: " + e.message
           + "\nfileName: " + e.fileName + "\nfunctionName: " + e.functionName);
    }
    else{
       maskat.getFWLog().error(message,e);
    }
}

/** マスカットフレームワーク用ログ */
maskat.getFWLog = function(){
	return maskat.frameworkLog;
}

/** マスカットフレームワーク通信ログ */
maskat.getCMULog = function(){
	return maskat.commuLog;
}

/** マスカットアプリケーションログ */
maskat.getAppLog = function(){
	return maskat.appLog;
}

/** log4javascriptは初期化できない場合、仮ログオブジェクト */
maskat.FakeLog = function(){
}
maskat.FakeLog.prototype.addAppender = function(){};
maskat.FakeLog.prototype.removeAppender = function(){};
maskat.FakeLog.prototype.removeAllAppenders = function(){};
maskat.FakeLog.prototype.getLevel = function(){};
maskat.FakeLog.prototype.setLevel = function(){};
maskat.FakeLog.prototype.log = function(){};
maskat.FakeLog.prototype.trace = function(){};
maskat.FakeLog.prototype.debug = function(){};
maskat.FakeLog.prototype.info = function(){};
maskat.FakeLog.prototype.warn = function(message,exception){
	if (exception != null)
		alert(message+":"+exception);
	else
		alert(message);
};
maskat.FakeLog.prototype.error = maskat.FakeLog.prototype.warn;
maskat.FakeLog.prototype.fatal = maskat.FakeLog.prototype.warn;

maskat.initLog = function(){
    if (typeof log4javascript=="undefined"){
    	//alert("log4javascript初期化できません。ログ機能使えません。");
    	maskat.frameworkLog = new maskat.FakeLog();
    	maskat.commuLog = new maskat.FakeLog();
    	maskat.appLog = new maskat.FakeLog();
    	return;
    }
    // %dは時間   %cはlogger種類  %pはログレベル  %mは出力メッセージまたはオブジェクト
	var layout = new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %-6c [%-5p] %m{2}");

	var popUpAppender = new log4javascript.PopUpAppender(true);
	popUpAppender.setReopenWhenClosed(true);//閉じる後でも、ログ出力があれば、もう一度ログウィンドウを開く
	popUpAppender.setMaxMessages(100);//最大メッセージ数
	popUpAppender.setLayout(layout);

	var criticalAppender = new log4javascript.PopUpAppender(true);
	criticalAppender.setReopenWhenClosed(true);
	criticalAppender.setFocusPopUp(true);//ログ出力があったら、ログウィンドウをフォーカスに当たる
	criticalAppender.setMaxMessages(100);
	criticalAppender.setThreshold(log4javascript.Level.ERROR);//このログウィンドウでERROR以上のログしか出力しない
	criticalAppender.setLayout(layout);

	maskat.frameworkLog = log4javascript.getLogger("一般");
	maskat.frameworkLog.addAppender(popUpAppender);
	maskat.frameworkLog.addAppender(criticalAppender);
	maskat.frameworkLog.setLevel(log4javascript.Level.TRACE);

	maskat.commuLog = log4javascript.getLogger("通信");
	maskat.commuLog.addAppender(popUpAppender);
	maskat.commuLog.addAppender(criticalAppender);
	maskat.commuLog.setLevel(log4javascript.Level.TRACE);

	var popAppenderForApp = new log4javascript.PopUpAppender(true);
	popAppenderForApp.setReopenWhenClosed(true);
	popAppenderForApp.setMaxMessages(10);
	popAppenderForApp.setLayout(layout);

	maskat.appLog = log4javascript.getLogger("アプリ");
	maskat.appLog.addAppender(popAppenderForApp);
	maskat.appLog.setLevel(log4javascript.Level.INFO);//INFO以下のレベルのログはこのアプリloggerに出力しない
	
	log4javascript.setShowStackTraces(true);//例外のスタックトレース出力
}

maskat.initLog();

