/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * Copyright (C) 2004-2008 Aimluck,Inc.
 * http://aipostyle.com/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.aimluck.eip.document.util;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.eip.document.FolderInfo;
import com.aimluck.eip.cayenne.om.account.EipMUserPosition;
import com.aimluck.eip.cayenne.om.portlet.EipTExtTimecard;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFile;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFolder;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFolderMap;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentRelationMap;
import com.aimluck.eip.cayenne.om.security.TurbineGroup;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALEipUser;
import com.aimluck.eip.libdocument.common.LibDocumentConstants;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.services.accessctl.ALAccessControlConstants;
import com.aimluck.eip.services.accessctl.ALAccessControlFactoryService;
import com.aimluck.eip.services.accessctl.ALAccessControlHandler;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.util.orgutils.ALOrgUtilsFactoryService;
import com.aimluck.eip.util.orgutils.ALOrgUtilsHandler;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFileMap;
import com.aimluck.eip.common.ALEipGroup;
import com.aimluck.eip.document.util.RelationuploadUtils;
import com.aimluck.eip.document.beans.RelationuploadLiteBean;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentRequestMap;

import java.util.Calendar;
import java.util.Date;

import jp.co.imtt.ImwareLogger;

import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowCategory;
import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowFile;
import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowRequest;
import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowRequestMap;
import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowRoute;
import com.aimluck.eip.whatsnew.util.WhatsNewUtils;
import com.aimluck.eip.workflow.util.WorkflowUtils;
import com.aimluck.eip.fileupload.util.FileuploadUtils;
import com.aimluck.eip.document.common.DocumentConstants;
import com.aimluck.eip.workflow.common.WorkflowConstants;
import com.aimluck.eip.services.accessctl.ALAccessControlFactoryService;
import com.aimluck.eip.services.eventlog.ALEventlogConstants;
import com.aimluck.eip.services.eventlog.ALEventlogFactoryService;
import com.aimluck.eip.document.common.DocumentAccessMember;

/**
 * 文書管理のユーティリティクラスです。 <BR>
 *
 */
public class DocumentUtils {

  /** logger */
  private static final JetspeedLogger logger = JetspeedLogFactoryService
      .getLogger(DocumentUtils.class.getName());
  
  private static final ImwareLogger imwareLogger = new ImwareLogger("document");
  
  
  /** フォルダ『ルートフォルダ』の予約 ID */
  public static final int ROOT_FODLER_ID = 1;

  /** セッションの識別子 */
  public static final String KEY_FOLDER_ID = "folder_id";

  /** 文書を保管するディレクトリのカテゴリキーの指定 */
  protected static final String CATEGORY_KEY = JetspeedResources.getString(
      "aipo.document.categorykey", "");

  /** 文書を保管するディレクトリの指定 */
  private static final String FOLDER_FILEDIR_DOCUMENT = JetspeedResources
      .getString("aipo.filedir", "");

  /** 全てのユーザーが閲覧／追加／編集／削除可 */
  public static final int ACCESS_PUBLIC_ALL = 0;

  /** 全てのユーザーが閲覧可。ただし追加／編集／削除できるのは所属メンバーのみ。 */
  public static final int ACCESS_PUBLIC_MEMBER = 1;

  /** 所属メンバーのみ閲覧／追加／編集／削除可 */
  public static final int ACCESS_SECRET_MEMBER = 2;

  /** 自分のみ閲覧／追加／編集／削除可 */
  public static final int ACCESS_SECRET_SELF = 3;

  /** 全てのユーザーが閲覧／追加／編集／削除可 */
  public static final String PUBLIC_FLAG_PUBLIC_ALL = "P";

  /** 全てのユーザーが閲覧可。ただし追加／編集／削除できるのは所属メンバーのみ。 */
  public static final String PUBLIC_FLAG_PUBLIC_MEMBER = "E";

  /** 所属メンバーのみ閲覧／追加／編集／削除可 */
  public static final String PUBLIC_FLAG_SECRET_MEMBER = "S";

  /** 自分のみ閲覧／追加／編集／削除可 */
  public static final String PUBLIC_FLAG_SECRET_SELF = "O";

  /**
   * フォルダオブジェクトモデルを取得します。 <BR>
   *
   * @param rundata
   * @param context
   * @return
   */
  public static ImwTDocumentFolder getImwTDocumentFolder(RunData rundata,
      Context context) {
    String folderid = ALEipUtils.getTemp(rundata, context, KEY_FOLDER_ID);

    try {
      if (folderid == null || Integer.valueOf(folderid) == null) {
        // ファイル IDが空の場合
        logger.debug("[Document Folder] Empty ID...");
        return null;
      }

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFolder.class);
      Expression exp = ExpressionFactory.matchDbExp(
          ImwTDocumentFolder.FOLDER_ID_PK_COLUMN, folderid);
      query.setQualifier(exp);
      List folders = dataContext.performQuery(query);
      if (folders == null || folders.size() == 0) {
        // 指定したフォルダ IDのレコードが見つからない場合
        logger.debug("[Document Folder] Not found ID...");
        return null;
      }
      return ((ImwTDocumentFolder) folders.get(0));
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ファイルオブジェクトモデルを取得します。 <BR>
   *
   * @param rundata
   * @param context
   * @return
   */
  public static ImwTDocumentFile getImwTDocumentFile(RunData rundata,
      Context context) {
    String fileid = ALEipUtils.getTemp(rundata, context,
        ALEipConstants.ENTITY_ID);
    try {
      if (fileid == null || Integer.valueOf(fileid) == null) {
        // ファイル IDが空の場合
        logger.debug("[Document File] Empty ID...");
        return null;
      }

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFile.class);
      Expression exp = ExpressionFactory.matchDbExp(
          ImwTDocumentFile.FILE_ID_PK_COLUMN, fileid);
      query.setQualifier(exp);
      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        // 指定したファイル IDのレコードが見つからない場合
        logger.debug("[Document File] Not found ID...");
        return null;
      }

      return ((ImwTDocumentFile) files.get(0));
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * 関連文書ファイルパスの配列を取得します。 <BR>
   *
   * @param rundata
   * @param context
   * @return
   */
  public static List getImwTDocumentRelationMap(Integer docid) {
    try {
      if (docid == null || Integer.valueOf(docid) == null) {
        // DOCIDが空の場合
        logger.debug("[Document RelationMap] Empty ID...");
        return null;
      }

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.DOC_ID_PROPERTY, docid);
      query.setQualifier(exp);
      List files = dataContext.performQuery(query);
      List filepath = new ArrayList();
      ImwTDocumentRelationMap map;
      if (files == null || files.size() == 0) {
        // 指定したDOCIDのレコードが見つからない場合
        logger.debug("[Document RelationMap] Not found ID...");
        return null;
      } else {
        for (int i = 0; i < files.size(); i++) {
          map = (ImwTDocumentRelationMap) files.get(i);
          filepath.add(map.getFilePath());
        }
      }

      return filepath;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ファイルオブジェクトモデルを取得します。 <BR>
   *
   * @param rundata
   * @param context
   * @return
   */
  public static List getImwTDocumentFileList(int folderId) {
    try {
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFile.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentFile.FOLDER_ID_PROPERTY, Integer.valueOf(folderId));
      query.setQualifier(exp);
      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        return null;
      }
  
      return files;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  // 2010/06/29 lib/libdocument の LibDocumentUtils に移植
  /**
   * 文書IDよりファイルオブジェクトモデルを取得します。 <BR>
   *
   * @param rundata
   * @param context
   * @return
   */
/*
  public static List getDocFilePathList(Integer docId) {
    try {
      if (docId==null){
        return null;
      }
      List filePaths = new ArrayList();
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFile.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentFile.DOC_ID_PROPERTY, docId);
      query.setQualifier(exp);
      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        return null;
      } else {
        for (Object obj:files){
          ImwTDocumentFile file = (ImwTDocumentFile)obj;
          if (file.getFilePath()!=null){
            filePaths.add(file.getFilePath());
          }
        }
        return filePaths;
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }
*/

  public static ArrayList getFolderList() {
    try {
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFolder.class);
      List list = dataContext.performQuery(query);
      if (list == null || list.size() < 0)
        return null;

      ArrayList prerootlist = getImwTDocumentFolderList(list, 0, 0);

      ArrayList result = getFolderList(prerootlist);

      return result;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static ArrayList getFolderList(List list) {
    try {
      if (list == null || list.size() <= 0)
        return null;

      ArrayList res = new ArrayList();
      int size = list.size();
      for (int i = 0; i < size; i++) {
        FolderInfo info = (FolderInfo) list.get(i);
        res.add(info);
        List infos = info.getList();
        List a = getFolderList(infos);
        if (a != null && a.size() > 0) {
          res.addAll(a);
        }
      }
      return res;
    } catch (Exception e) {
      return null;
    }

  }

  private static ArrayList getImwTDocumentFolderList(List dblist,
      int parent_id, int hierarchy_index) {
    ArrayList list = new ArrayList();
    int size = dblist.size();
    for (int i = 0; i < size; i++) {
      ImwTDocumentFolder folder = (ImwTDocumentFolder) dblist.get(i);
      if (folder.getParentId().intValue() == parent_id) {
        FolderInfo info = new FolderInfo();
        info.setHierarchyIndex(hierarchy_index);
        info.setFolderId(folder.getFolderId().intValue());
        info.setParentFolderId(folder.getParentId().intValue());
        info.setFolderName(folder.getFolderName());
        list.add(info);
      }
    }

    if (list.size() <= 0)
      return null;

    int size2 = list.size();
    for (int i = 0; i < size2; i++) {
      FolderInfo info = (FolderInfo) list.get(i);
      List colist = getImwTDocumentFolderList(dblist, info.getFolderId(), info
          .getHierarchyIndex() + 1);
      if (colist != null && colist.size() > 0) {
        info.setList(colist);
      }
    }
    return list;
  }

  public static void setFolderVisible(ArrayList folder_list,
      FolderInfo selectedinfo, RunData rundata) {
    if (folder_list == null || folder_list.size() <= 0)
      return;

    ArrayList list = new ArrayList();
    FolderInfo info = null;
    int hierarchy_index = 0;
    int parent_id = 0;
    int size = folder_list.size() - 1;
    for (int i = size; i >= 0; i--) {
      if (hierarchy_index < 0) {
        break;
      }
      info = (FolderInfo) folder_list.get(i);
      if (null != selectedinfo
          && info.getFolderId() == selectedinfo.getFolderId()) {
        /** 新しく開かれたフォルダ */
        info.setOpened(true);
        list.add(0, info);
        parent_id = info.getParentFolderId();
        hierarchy_index = info.getHierarchyIndex() - 1;
      } else if (info.getFolderId() == parent_id) {
        // 親フォルダを捜す
        info.setOpened(true);
        list.add(0, info);
        parent_id = info.getParentFolderId();
        hierarchy_index = info.getHierarchyIndex() - 1;
      }
    }

    size = folder_list.size();
    for (int i = 0; i < size; i++) {
      FolderInfo info1 = (FolderInfo) folder_list.get(i);
      boolean containsId = false;
      for (int j = 0; j < list.size(); j++) {
        FolderInfo info2 = (FolderInfo) list.get(j);
        if (info1.getFolderId() == info2.getFolderId()) {
          containsId = true;
          break;
        } else if (info1.getParentFolderId() == info2.getFolderId()) {
          containsId = true;
          break;
        }
      }
      if (containsId) {
        info1.setVisible(true);
      } else {
        info1.setVisible(false);
      }
    }
    /** アクセス権限による可視、不可視の設定 */
    setFolderAuthorizedVisible(folder_list, rundata);
  }

  /**
   * リスト中のフォルダに対し、閲覧権限の有無により、可視、不可視を設定します
   *
   * @param folder_list
   * @param rundata
   */
  public static void setFolderAuthorizedVisible(ArrayList folder_list,
      RunData rundata) {
    FolderInfo info;
    int size = folder_list.size();
    /** アクセス権限による表示の制御 */
    List invisible_children = new ArrayList();
    for (int i = 0; i < size; i++) {
      info = (FolderInfo) folder_list.get(i);
      if (info.getHierarchyIndex() == 0
          && isAccessibleFolder(info.getFolderId(), rundata)) {
        info.setAuthorizedVisible(true);
        continue;
      }
      if (!invisible_children.contains(i)) {
        /** 既に見えないフォルダの子フォルダとして処理されたフォルダについては、アクセス権限チェックをスキップする */
        info.setAuthorizedVisible(isAccessibleFolder(info.getFolderId(),
            rundata));
      }
      if (!info.isAuthorizedVisible()) {
        /** 子フォルダも見えないようにする */
        for (int j = 0; j < size; j++) {
          FolderInfo info1 = (FolderInfo) folder_list.get(j);
          if (info1.getParentFolderId() == info.getFolderId()) {
            invisible_children.add(j);
            info1.setAuthorizedVisible(false);
          }
        }
      }
    }
  }

  public static String getFolderPosition(ArrayList folder_list, int folder_id) {
    String sepa = "<b> &gt; </b>";
    StringBuffer folderpath = new StringBuffer();
    FolderInfo info = null;
    int parent_id = -1;
    int size = folder_list.size() - 1;
    for (int i = size; i >= 0; i--) {
      info = (FolderInfo) folder_list.get(i);
      if (info.getFolderId() <= 1) {
        // 「ルートフォルダ」は含めない
        folderpath.insert(0, info.getFolderName());
        break;
      }
      if (info.getFolderId() == folder_id) {
        folderpath.append(sepa);
        folderpath.append(info.getFolderName());
        parent_id = info.getParentFolderId();
      } else if (info.getFolderId() == parent_id) {
        // 親フォルダを捜す
        folderpath.insert(0, info.getFolderName());
        folderpath.insert(0, sepa);
        parent_id = info.getParentFolderId();
      }
    }

    return folderpath.toString();
  }

  public static FolderInfo getSelectedFolderInfo(ArrayList list, int folder_id) {
    FolderInfo selected_folderinfo = null;
    int size = list.size();
    for (int i = 0; i < size; i++) {
      FolderInfo info = (FolderInfo) list.get(i);
      if (info.getFolderId() == folder_id) {
        selected_folderinfo = info;
        break;
      }
    }
    return selected_folderinfo;
  }

  /**
   * ユーザ毎のルート保存先（絶対パス）を取得します。
   *
   * @param uid
   * @return
   */
  public static String getSaveDirPath(String orgId) {
    ALOrgUtilsHandler handler = ALOrgUtilsFactoryService.getInstance()
        .getOrgUtilsHandler();
    File path = handler.getDocumentPath(FOLDER_FILEDIR_DOCUMENT, orgId,
        CATEGORY_KEY);
    if (!path.exists()) {
      path.mkdirs();
    }
    return path.getAbsolutePath();
  }

  /**
   * ユーザ毎の保存先（相対パス）を取得します。
   *
   * @param uid
   * @return
   */
  public static String getRelativePath(String fileName) {
    return new StringBuffer().append("/").append(fileName).toString();
  }

  /**
   * 添付ファイル保存先（絶対パス）を取得します。
   *
   * @param uid
   * @return
   */
  public static String getAbsolutePath(String orgId, String fileName) {
    ALOrgUtilsHandler handler = ALOrgUtilsFactoryService.getInstance()
        .getOrgUtilsHandler();
    StringBuffer sb = new StringBuffer().append(
        handler.getDocumentPath(FOLDER_FILEDIR_DOCUMENT, orgId, CATEGORY_KEY))
        .append(File.separator);
    File f = new File(sb.toString());
    if (!f.exists()) {
      f.mkdirs();
    }
    return sb.append(File.separator).append(fileName).toString();
  }

  /**
   * 現在ログインしているユーザーは指定したIDのフォルダを閲覧する権限を持つかを返します
   *
   * @param folder_id
   * @param rundata
   * @return
   */
  public static boolean isAccessibleFolder(int folder_id, RunData rundata) {
    ImwTDocumentFolder folder = getFolderByPK(folder_id);
    int public_flag = Integer.valueOf(folder.getPublicFlag());
    int current_user_id = ALEipUtils.getUserId(rundata);

    // ログインユーザが文書管理システム管理者かどうか
    // フォルダの削除権限があるかどうかで判断する。
    ALAccessControlFactoryService aclservice = (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
        .getInstance()).getService(ALAccessControlFactoryService.SERVICE_NAME);
    ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();
    boolean isDocAdmin = aclhandler.hasAuthority((int) ALEipUtils.getALEipUser(
        rundata).getUserId().getValue(),
        ALAccessControlConstants.POERTLET_FEATURE_DOCUMENT_FOLDER,
        ALAccessControlConstants.VALUE_ACL_DELETE);

    //文書管理システム管理者は全フォルダ閲覧可能
    if (isDocAdmin) {
      return true;
    }
    // ルートフォルダは全員閲覧可能
    else if (folder.getFolderId() == DocumentUtils.ROOT_FODLER_ID) {
      return true;
    } else {
      // 閲覧権限があるユーザーか確認する
      // フォルダID、ログインユーザIDは必ず存在するためNULLにならない

      StringBuffer statement = new StringBuffer();

      statement.append(" SELECT * ");
      statement.append("    FROM");
      statement.append("    IMW_T_DOCUMENT_FOLDER_MAP AS MAP");
      statement.append("    LEFT JOIN");
      statement.append("    TURBINE_USER_GROUP_ROLE AS GRP");
      statement.append("    ON MAP.GROUP_ID = GRP.GROUP_ID");
      statement.append("    WHERE");
      statement.append("    MAP.FOLDER_ID = ");
      statement.append(folder.getFolderId());
      statement.append("    AND");
      statement.append("    (");
      statement.append("        MAP.GROUP_ID = -1");
      statement.append("        OR");
      statement.append("        MAP.USER_ID = ");
      statement.append(current_user_id);
      statement.append("        OR");
      statement.append("        (");
      statement.append("            MAP.GROUP_ID IN");
      statement.append("                (SELECT GROUP_ID");
      statement.append("                FROM TURBINE_USER_GROUP_ROLE");
      statement
          .append("                WHERE TURBINE_USER_GROUP_ROLE.USER_ID = ");
      statement.append(current_user_id);
      statement.append("                )");
      statement.append("            AND");
      statement.append("            GRP.USER_ID =");
      statement.append(current_user_id);
      statement.append("         )");
      statement.append("    )");

      String query = statement.toString();

      try {
        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();
        SQLTemplate rawSelect = new SQLTemplate(ImwTDocumentFolderMap.class,
            query, true);
        rawSelect.setFetchingDataRows(true);
        List list = dataContext.performQuery(rawSelect);

        if (list != null && list.size() != 0) {
          return true;
        }
      } catch (Exception ex) {
        logger.error("Exception", ex);
        return false;
      }
    }

    return false;
  }

  /* Aipo 既存ソース
   public static boolean isAccessibleFolder(int folder_id, RunData rundata) {
     ImwTDocumentFolder folder = getFolderByPK(folder_id);
     int public_flag = Integer.valueOf(folder.getPublicFlag());
     int current_user_id = ALEipUtils.getUserId(rundata);
     if (folder.getParentId() == DocumentUtils.ROOT_FODLER_ID
         || folder.getFolderId() == DocumentUtils.ROOT_FODLER_ID) {
       // ルートフォルダまたはその直下のフォルダである場合
       if (public_flag == DocumentUtils.ACCESS_PUBLIC_ALL
           || public_flag == DocumentUtils.ACCESS_PUBLIC_MEMBER) {
         // 全員が閲覧可能
         return true;
       } else if (public_flag == DocumentUtils.ACCESS_SECRET_SELF) {
         // 作成者本人のみ閲覧可能
         if (folder.getCreateUserId() == current_user_id)
           return true;
       } else {
         // 閲覧権限があるユーザーか確認する
         DataContext dataContext = DatabaseOrmService.getInstance()
             .getDataContext();
         SelectQuery query = new SelectQuery(ImwTDocumentFolderMap.class);
         Expression exp1 = ExpressionFactory.matchDbExp(
             ImwTDocumentFolderMap.IMW_TDOCUMENT_FOLDER_PROPERTY, folder);
         Expression exp2 = ExpressionFactory.matchExp(
             ImwTDocumentFolderMap.USER_ID_PROPERTY, current_user_id);
         query.setQualifier(exp1);
         query.andQualifier(exp2);
         List list = dataContext.performQuery(query);
         if (list != null && list.size() != 0)
           return true;
       }
       return false;
     } else {
       // 何らかのフォルダの子フォルダである場合
       if (public_flag == DocumentUtils.ACCESS_PUBLIC_ALL) {
         // 上位フォルダでアクセス制限がかかっている可能性あり。再帰的に調査する
         return isAccessibleFolder(folder.getParentId(), rundata);
       } else if (public_flag == DocumentUtils.ACCESS_PUBLIC_MEMBER) {
         // 上位フォルダでのアクセス制限は無い。
         return true;
       } else if (public_flag == DocumentUtils.ACCESS_SECRET_SELF) {
         // 作成者本人のみ閲覧可能
         if (folder.getCreateUserId() == current_user_id)
           return true;
       } else {
         // 閲覧権限があるユーザーか確認する
         DataContext dataContext = DatabaseOrmService.getInstance()
             .getDataContext();
         SelectQuery query = new SelectQuery(ImwTDocumentFolderMap.class);
         Expression exp1 = ExpressionFactory.matchDbExp(
             ImwTDocumentFolderMap.IMW_TDOCUMENT_FOLDER_PROPERTY, folder);
         Expression exp2 = ExpressionFactory.matchExp(
             ImwTDocumentFolderMap.USER_ID_PROPERTY, current_user_id);
         query.setQualifier(exp1);
         query.andQualifier(exp2);
         List list = dataContext.performQuery(query);
         if (list != null && list.size() != 0)
           return true;
       }
       return false;
     }
   }
   */

  /**
   * 現在ログインしているユーザーは指定したIDのフォルダを編集する権限を持つかを返します
   *
   * @param folder_id
   * @param rundata
   * @return
   */
  public static boolean isEditableFolder(int folder_id, RunData rundata) {
    // IMW_T_DOCUMENT_FOLDER_MAP の権限では、全員編集可能とする。（ロールで制限する）
    return true;
  }

  /* Aipo既存ソース
  public static boolean isEditableFolder(int folder_id, RunData rundata) {
    int current_user_id = ALEipUtils.getUserId(rundata);
    ImwTDocumentFolder folder = DocumentUtils.getFolderByPK(folder_id);
    int public_flag = Integer.valueOf(folder.getPublicFlag());
    if (folder.getParentId() == DocumentUtils.ROOT_FODLER_ID
        || folder.getFolderId() == DocumentUtils.ROOT_FODLER_ID) {
      // ルートフォルダまたはその直下のフォルダである場合
      if (public_flag == DocumentUtils.ACCESS_PUBLIC_ALL) {
        // 全員が編集可能
        return true;
      } else if (public_flag == DocumentUtils.ACCESS_SECRET_SELF) {
        // 作成者本人のみ編集可能
        if (folder.getCreateUserId() == current_user_id)
          return true;
      } else {
        // 編集権限があるユーザーか確認する
        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();
        SelectQuery query = new SelectQuery(ImwTDocumentFolderMap.class);
        Expression exp1 = ExpressionFactory.matchDbExp(
            ImwTDocumentFolderMap.IMW_TDOCUMENT_FOLDER_PROPERTY, folder);
        Expression exp2 = ExpressionFactory.matchExp(
            ImwTDocumentFolderMap.USER_ID_PROPERTY, current_user_id);
        query.setQualifier(exp1);
        query.andQualifier(exp2);
        List list = dataContext.performQuery(query);
        if (list != null && list.size() != 0)
          return true;
      }
      return false;
    } else {
      // 何らかのフォルダの子フォルダの場合
      if (public_flag == DocumentUtils.ACCESS_PUBLIC_ALL) {
        // 上位フォルダでアクセス制限がかかっている可能性あり。再帰的に調査する
        return isEditableFolder(folder.getParentId(), rundata);
      } else if (public_flag == DocumentUtils.ACCESS_SECRET_SELF) {
        // 作成者本人のみ編集可能
        if (folder.getCreateUserId() == current_user_id)
          return true;
      } else {
        // 編集権限があるユーザーか確認する
        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();
        SelectQuery query = new SelectQuery(ImwTDocumentFolderMap.class);
        Expression exp1 = ExpressionFactory.matchDbExp(
            ImwTDocumentFolderMap.IMW_TDOCUMENT_FOLDER_PROPERTY, folder);
        Expression exp2 = ExpressionFactory.matchExp(
            ImwTDocumentFolderMap.USER_ID_PROPERTY, current_user_id);
        query.setQualifier(exp1);
        query.andQualifier(exp2);
        List list = dataContext.performQuery(query);
        if (list != null && list.size() != 0)
          return true;
      }
      return false;
    }
  }
   */

  /**
   * フォームで使用するフォルダのリストに対し、権限的に不可視なフォルダを設定します
   *
   * @param folder_list
   * @param rundata
   */
  public static void setFolderVisibleForForm(ArrayList folder_list,
      RunData rundata) {
    int size = folder_list.size();
    FolderInfo info;
    List invisible_children = new ArrayList();
    for (int i = 0; i < size; i++) {
      info = (FolderInfo) folder_list.get(i);
      if (info.getHierarchyIndex() == 0) {
        info.setAuthorizedVisible(true);
        continue;
      }
      if (!invisible_children.contains(i)) {
        /** 見えないフォルダの子フォルダとして処理済みのフォルダについては、アクセス権限チェックをスキップする */
        //info
        //    .setAuthorizedVisible(isEditableFolder(info.getFolderId(), rundata));
        info.setAuthorizedVisible(isAccessibleFolder(info.getFolderId(),
            rundata));
      }
      if (!info.isAuthorizedVisible()) {
        /** 不可視に設定したフォルダの子フォルダも見えないようにする */
        for (int j = 0; j < size; j++) {
          FolderInfo info1 = (FolderInfo) folder_list.get(j);
          if (info1.getParentFolderId() == info.getFolderId()) {
            invisible_children.add(j);
            info1.setAuthorizedVisible(false);
          }
        }
      }
    }
  }

  /**
   * 権限的に閲覧可能な全フォルダのIDを返します。
   *
   * @param rundata
   * @return
   */
  public static ArrayList getAuthorizedVisibleFolderIds(RunData rundata) {
    ArrayList ids = new ArrayList();
    ArrayList list = DocumentUtils.getFolderList();
    DocumentUtils.setFolderAuthorizedVisible(list, rundata);
    FolderInfo folder;
    for (int i = 0; i < list.size(); i++) {
      folder = (FolderInfo) list.get(i);
      if (folder.isAuthorizedVisible())
        ids.add(folder.getFolderId());
    }
    return ids;
  }

  /**
   * 上位でアクセスコントロールを行っているフォルダを再帰的に検索します
   *
   * @param parentId
   * @return
   */
  public static Integer getAccessControlFolderId(Integer parentId) {
    if (parentId == DocumentUtils.ROOT_FODLER_ID)
      /** ルートまでさかのぼってもアクセスコントロールがされていない場合 */
      return 1;
    ImwTDocumentFolder folder = getFolderByPK(parentId);
    if (Integer.valueOf(folder.getPublicFlag()) == DocumentUtils.ACCESS_PUBLIC_ALL) {
      /** さらに上位のフォルダでアクセスコントロールが設定されている可能性がある */
      return DocumentUtils.getAccessControlFolderId(folder.getParentId());
    } else {
      /** このフォルダでアクセスコントロールが設定されている */
      return folder.getFolderId();
    }
  }

  public static List getChildFolders(ImwTDocumentFolder folder) {
    List list = new ArrayList();
    List children = DocumentUtils.getChildren(folder.getFolderId());
    List children_tmp = new ArrayList();
    list.addAll(children);
    int add_count = children.size();
    while (add_count > 0) {
      add_count = 0;
      for (int i = 0; i < children.size(); i++) {
        children_tmp.addAll(DocumentUtils
            .getChildren(((ImwTDocumentFolder) children.get(i)).getFolderId()));
      }
      add_count = children_tmp.size();
      children.clear();
      children.addAll(children_tmp);
      list.addAll(children_tmp);
      children_tmp.clear();
    }
    return list;
  }

  public static List getChildren(int parent_id) {
    DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
    SelectQuery query = new SelectQuery(ImwTDocumentFolder.class);
    Expression pk_exp = ExpressionFactory.matchExp(
        ImwTDocumentFolder.PARENT_ID_PROPERTY, parent_id);
    query.setQualifier(pk_exp);
    List list = dataContext.performQuery(query);
    return list;
  }

  public static ImwTDocumentFolder getFolderByPK(Integer folder_id) {
    DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
    SelectQuery query = new SelectQuery(ImwTDocumentFolder.class);
    Expression pk_exp = ExpressionFactory.matchDbExp(
        ImwTDocumentFolder.FOLDER_ID_PK_COLUMN, folder_id);
    query.setQualifier(pk_exp);
    List list = dataContext.performQuery(query);
    ImwTDocumentFolder folder = (ImwTDocumentFolder) list.get(0);
    return folder;
  }

  /**
   * rundata から取得したメンバーリストをグループリストとユーザリストに振り分けます。 <BR>
   *　ユーザリストにログインユーザを追加します。<BR>
   */
  public static boolean separateGroupAndUser(RunData rundata,
      String memberListName, ArrayList groupList, ArrayList userList) {
    try {
      /* 変数の宣言 */
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      Integer memLen;
      List member_g = new ArrayList();
      List member_u = new ArrayList();
      SelectQuery query;
      Expression exp;

      /* リストの初期化 */
      //groupList.clear();
      //userList.clear();
      /* メンバーリストの取得 */
      String member[] = rundata.getParameters().getStrings(memberListName);

      //String temp;
      /* 取得に成功した場合 */
      if (member != null) {
        /* 先頭の1文字でグループとユーザに振り分ける。 */
        for (String mem : member) {
          memLen = mem.length();
          //temp = mem.substring(0,1);
          if ("G".equals(mem.substring(0, 1))) {
            //temp = mem.substring(1,memLen);
            member_g.add(mem.substring(1, memLen));
          } else if ("U".equals(mem.substring(0, 1))) {
            //temp = mem.substring(1,memLen);
            member_u.add(mem.substring(1, memLen));
          }
        }

        /* グループリストの作成 */
        if (member_g.size() != 0) {
          query = new SelectQuery(TurbineGroup.class);
          exp = ExpressionFactory.inExp(TurbineGroup.GROUP_NAME_PROPERTY,
              member_g);
          query.setQualifier(exp);

          List glist = dataContext.performQuery(query);
          groupList.addAll(glist);
        }

        /* ユーザリストの作成 */
        if (member_u.size() != 0) {
          query = new SelectQuery(TurbineUser.class);
          exp = ExpressionFactory.inExp(TurbineUser.LOGIN_NAME_PROPERTY,
              member_u);
          query.setQualifier(exp);
          userList.addAll(ALEipUtils.getUsersFromSelectQuery(query));
        }
      }
      // ユーザーリストにログインユーザが含まれていない場合、追加     
      ALEipUser login_user = ALEipUtils.getALEipUser(rundata);
      boolean duplicate = false;
      for (Object obj : userList) {
        ALEipUser user = (ALEipUser) obj;
        if (user.getUserId().getValue() == login_user.getUserId().getValue()) {
          duplicate = true;
          break;
        }
      }
      if (!duplicate) {
        userList.add(login_user);
      }

      return true;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
  }

  /**
   * IMW_T_DOCUMENT_FILE テーブルの DOC_ID の最大値を取得します。 <BR>
   *
   */
  public static Integer getMaxDocId() {
    try {
      Integer max = 0;
      Integer docId;
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFile.class);

      List list = dataContext.performQuery(query);

      if (list.size() == 0) {
        return 0;
      } else {
        for (Object obj : list) {
          ImwTDocumentFile file = new ImwTDocumentFile();
          file = (ImwTDocumentFile) obj;
          docId = file.getDocId();
          if (docId != null && docId > max) {
            max = docId;
          }
        }
      }

      return max;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return 0;
    }
  }

  /* ALEipUtils.java getUsersFromSelectQuery をコピーして編集*/
  /**
   * <code>SelectQuery</code> の条件に従ってグループを取得します。
   * 
   * @param crt
   * @return ALEipGroup の List
   */
  public static List getGroupFromSelectQuery(SelectQuery query) {
    List list = new ArrayList();
    try {
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      List glist = dataContext.performQuery(query);
      int size = glist.size();

      for (int i = 0; i < size; i++) {
        TurbineGroup record = (TurbineGroup) glist.get(i);
        ALEipGroup group = new ALEipGroup();
        group.initField();
        group.setName("G" + record.getGroupName());
        group.setAliasName(record.getGroupAliasName());
        list.add(group);
      }
    } catch (Exception ex) {
      logger.error("[DocumentFolderSelectData]", ex);
    }
    return list;
  }

  /* ALEipUtils.java getUsersFromSelectQuery をコピーして編集*/
  /**
   * <code>SelectQuery</code> の条件に従ってユーザーを取得します。
   * 
   * @param crt
   * @return ALEipUser の List
   */
  public static List getUsersFromSelectQuery(SelectQuery query) {
    List list = new ArrayList();
    try {
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      query.addOrdering(TurbineUser.EIP_MUSER_POSITION_PROPERTY + "."
          + EipMUserPosition.POSITION_PROPERTY, true);
      List ulist = dataContext.performQuery(query);
      int size = ulist.size();

      for (int i = 0; i < size; i++) {
        TurbineUser record = (TurbineUser) ulist.get(i);
        ALEipUser user = new ALEipUser();
        user.initField();
        user.setUserId(record.getUserId().intValue());
        user.setName("U" + record.getLoginName());
        user.setAliasName(record.getFirstName(), record.getLastName());
        list.add(user);
      }
    } catch (Exception ex) {
      logger.error("[ALEipUtils]", ex);
    }
    return list;
  }

  /**
   * ファイル追加、追加申請、追加再申請、チェックイン、チェックイン再申請時に<BR>
   * 登録を解除された関連文書を削除し、新規登録された関連文書を登録します。<BR>
   * WorkflowUtilのinsertFileDataDelegate（添付ファイル登録処理）を元に作成
   * @param rundata
   * @param context
   * @param dataContext
   * @param docId
   * @param requestStatus
   * @param relationuploadList
   * @param folderName
   * @param msgList
   * @return 成功:true 失敗：false
   */
  public static boolean insertRelationFiles(RunData rundata, Context context,
      DataContext dataContext, Integer docId, Integer requestStatus,
      List relationuploadList, String folderName, ArrayList msgList) {

    try {
      int uid = ALEipUtils.getUserId(rundata);
      String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
      String[] fileids = rundata.getParameters().getStrings("relations");

      // ファイルがアップロードされていなくても、削除処理は行う。
      int fileIDsize = 0;
      if (fileids != null) {
        if (fileids[0].equals("")) {
          fileIDsize = 0;
        } else {
          fileIDsize = fileids.length;
        }
      }

      ArrayList oldFileids = new ArrayList();
      ArrayList newFileids = new ArrayList();

      // ファイル追加：障害３ 関連文書を削除して空にした場合にファイル追加できない問題の対応
      // fileids[0]が""の場合も対応
      // 取得に成功した場合
      if (fileids != null && fileIDsize > 0) {
        // 先頭の1文字で過去の登録ファイルと現在登録したファイルに振り分ける。
        for (String id : fileids) {
          int idLen = id.length();
          if (id.startsWith("I")) {
            String temp = id.substring(1, idLen);
            oldFileids.add(id.substring(1, idLen));
          } else {
            newFileids.add(id);
          }
        }
      }

      int oldFileIDsize = oldFileids.size();

      // 登録を解除されたファイルの削除
      SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
      query.andQualifier(ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.DOC_ID_PROPERTY, docId));
      query.andQualifier(ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY, requestStatus));
      for (Object id:oldFileids) {
        Expression exp = ExpressionFactory.matchDbExp(
            ImwTDocumentRelationMap.ID_PK_COLUMN, Integer.parseInt(id.toString()));
        query.andQualifier(exp.notExp());
      }
      // DB上でトピックに属すが、送られてきたFileIDにIDが含まれていないファイルのリスト(削除されたファイルのリスト)
      List delFiles = dataContext.performQuery(query);

      if (delFiles.size() > 0) {
        // ローカルファイルに保存されているファイルを削除する．
        File file = null;
        for (Object delFile:delFiles) {
          file = new File(DocumentUtils.getSaveDirPath(org_id)
              + (String) ((ImwTDocumentRelationMap) delFile)
                  .getFilePath());
          if (file.exists()) {
            file.delete();
          }
        }
        // データベースから添付ファイルのデータ削除
        dataContext.deleteObjects(delFiles);
      }

      // 追加ファイルが無ければtrueを返して終了
      if (relationuploadList == null || relationuploadList.size() <= 0
          || fileids == null || fileIDsize == 0) {
        return true;
      }

      // ファイル追加処理
      RelationuploadLiteBean filebean = null;
      int size = relationuploadList.size();

      for (Object obj:relationuploadList) {

        filebean = (RelationuploadLiteBean)obj;
        
        String filename = RelationuploadUtils.getNewFileName(DocumentUtils
            .getSaveDirPath(org_id));

        // 新規オブジェクトモデル
        ImwTDocumentRelationMap file = (ImwTDocumentRelationMap) dataContext
            .createAndRegisterNewObject(ImwTDocumentRelationMap.class);

        // 文書ID
        file.setDocId(docId);

        // ファイル名
        file.setFileName(filebean.getFileName());
        // ファイルパス
        file.setFilePath(DocumentUtils.getRelativePath(filename));

        // 申請状態
        file.setRequestStatus(requestStatus);

        // ファイルの移動
        File srcFile = RelationuploadUtils.getAbsolutePath(org_id, uid,
            folderName, filebean.getFileId());
        File destFile = new File(DocumentUtils
            .getAbsolutePath(org_id, filename));
        RelationuploadUtils.copyFile(srcFile, destFile);

        srcFile = null;
        destFile = null;

      }

      // 添付ファイル保存先のフォルダを削除
      File folder = RelationuploadUtils.getFolder(org_id, uid, folderName);
      RelationuploadUtils.deleteFolder(folder);
    } catch (Exception e) {
      logger.error("Exception", e);
      dataContext.rollbackChanges();
      return false;
    }
    return true;
  }

  /**
   * チェックイン申請時、登録を解除されていない古い関連文書を複製し、新規登録された関連文書の登録を行います。
   * @param rundata
   * @param context
   * @param dataContext
   * @param docId
   * @param requestStatus
   * @param relationuploadList
   * @param folderName
   * @param msgList
   * @return　成功:true 失敗：false
   */
  public static boolean insertRelationFilesForRequestCheckin(RunData rundata,
      Context context, DataContext dataContext, Integer docId,
      Integer requestStatus, List relationuploadList, String folderName,
      ArrayList msgList) {
    try {
      int uid = ALEipUtils.getUserId(rundata);
      String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
      String[] fileids = rundata.getParameters().getStrings("relations");

      // ファイルがアップロードされていなくても、複製処理は行う。

      int fileIDsize = 0;
      if (fileids != null) {
        if (fileids[0].equals("")) {
          fileIDsize = 0;
        } else {
          fileIDsize = fileids.length;
        }
      }

      ArrayList oldFileids = new ArrayList();
      ArrayList newFileids = new ArrayList();
      
      oldFileids.clear();
      newFileids.clear();

      // ファイル追加：障害３ 関連文書を削除して空にした場合にファイル追加できない問題の対応
      // fileids[0]が""の場合も対応
      // 取得に成功した場合 
      if (fileids != null && fileIDsize > 0) {
        // 先頭の1文字で過去の登録ファイルと現在登録したファイルに振り分ける。 
        // （VMファイル側で、過去の登録ファイルには頭に"I"が付与されている。）
        for (String id : fileids) {
          int idLen = id.length();
          if (id.startsWith("I")) {
            oldFileids.add(id.substring(1, idLen));
          } else {
            newFileids.add(id);
          }
        }
      }

      int oldFileIDsize = oldFileids.size();

      // 登録を解除されていないファイルがある場合のみ複製処理を実行
      if (oldFileids!=null && oldFileIDsize > 0) {
        // 登録を解除されていない過去のファイルの複製
        SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
                
        query.setQualifier(
            ExpressionFactory.matchExp(ImwTDocumentRelationMap.DOC_ID_PROPERTY, docId));
        
        query.andQualifier(ExpressionFactory.inDbExp(ImwTDocumentRelationMap.ID_PK_COLUMN, oldFileids));
        /*
        for (Object id : oldFileids) {
          Expression exp = ExpressionFactory.matchDbExp(
              ImwTDocumentRelationMap.ID_PK_COLUMN, Integer.parseInt(id
                  .toString()));
          query.orQualifier(exp);
        }
        */
        // DB上でトピックに属し、送られてきたFileIDにIDが含まれているファイルのリスト(複製するべきファイルのリスト)
        List copyFiles = dataContext.performQuery(query);

        // ファイル複製処理
        if (copyFiles != null && copyFiles.size() > 0) {
          for (Object obj : copyFiles) {
            ImwTDocumentRelationMap rfile = (ImwTDocumentRelationMap) obj;

            String filename = RelationuploadUtils.getNewFileName(DocumentUtils
                .getSaveDirPath(org_id));

            // 新規オブジェクトモデル
            ImwTDocumentRelationMap file = (ImwTDocumentRelationMap) dataContext
                .createAndRegisterNewObject(ImwTDocumentRelationMap.class);

            // 文書ID
            file.setDocId(docId);

            // ファイル名
            file.setFileName(rfile.getFileName());
            // ファイルパス
            file.setFilePath(DocumentUtils.getRelativePath(filename));

            // 申請状態
            file.setRequestStatus(1);

            // ファイルの移動
            File srcFile = new File(DocumentUtils.getAbsolutePath(org_id, rfile
                .getFilePath()));
            File destFile = new File(DocumentUtils.getAbsolutePath(org_id,
                filename));
            RelationuploadUtils.copyFile(srcFile, destFile);

            srcFile = null;
            destFile = null;
          }
        }
      }

      // 追加ファイルが無ければtrueを返して終了
      if (relationuploadList == null || relationuploadList.size() <= 0
          || fileids == null || fileIDsize == 0) {
        return true;
      }

      // ファイル追加処理
      RelationuploadLiteBean filebean = null;
      int size = relationuploadList.size();

      for (Object obj:relationuploadList) {  
        filebean = (RelationuploadLiteBean)obj;
        
        String filename = RelationuploadUtils.getNewFileName(DocumentUtils
            .getSaveDirPath(org_id));

        // 新規オブジェクトモデル
        ImwTDocumentRelationMap file = (ImwTDocumentRelationMap) dataContext
            .createAndRegisterNewObject(ImwTDocumentRelationMap.class);

        // 文書ID
        file.setDocId(docId);

        // ファイル名
        file.setFileName(filebean.getFileName());
        // ファイルパス
        file.setFilePath(DocumentUtils.getRelativePath(filename));

        // 申請状態
        file.setRequestStatus(1);

        // ファイルの移動
        File srcFile = RelationuploadUtils.getAbsolutePath(org_id, uid,
            folderName, filebean.getFileId());
        File destFile = new File(DocumentUtils
            .getAbsolutePath(org_id, filename));
        RelationuploadUtils.copyFile(srcFile, destFile);

        srcFile = null;
        destFile = null;

      }

      // 添付ファイル保存先のフォルダを削除
      File folder = RelationuploadUtils.getFolder(org_id, uid, folderName);
      RelationuploadUtils.deleteFolder(folder);
    } catch (Exception e) {
      logger.error("Exception", e);
      dataContext.rollbackChanges();
      return false;
    }
    return true;
  }


  /**
   * 次の文書IDを取得します   取得失敗時、NULLを返します
   * ここで取得に失敗する場合は、postgreSQLで　"CREATE SEQUENCE imw_t_document_file_doc_id_seq;"
   * を実行していない可能性があります
   * @return 次の文書ID
   */
  public static Integer getNextDocId() {
    try {
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();

      StringBuffer statement = new StringBuffer();

      statement.append("SELECT nextval('imw_t_document_file_doc_id_seq')");

      String query = statement.toString();

      SQLTemplate rawSelect = new SQLTemplate(ImwTDocumentFile.class, query,
          true);
      rawSelect.setFetchingDataRows(true);
      List list = dataContext.performQuery(rawSelect);
      DataRow dataRow;
      dataRow = (DataRow) list.get(0);

      Object obj = ALEipUtils.getObjFromDataRow(dataRow, "nextval");

      String str = obj.toString();

      Integer docId = Integer.valueOf(str);
      //Integer docId = (Integer) ALEipUtils.getObjFromDataRow(dataRow,"nextval");
      //System.out.println("docId = [" + docId + "]");

      return docId;

    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ログインユーザが文書管理システム管理者かどうかを返します
   * @param rundata
   * @return
   */
  public static boolean isDocAdmin(RunData rundata) {
    // ログインユーザが文書管理システム管理者かどうか
    // フォルダの削除権限があるかどうかで判断する。
    ALAccessControlFactoryService aclservice = (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
        .getInstance()).getService(ALAccessControlFactoryService.SERVICE_NAME);
    ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();
    boolean ret = aclhandler.hasAuthority((int) ALEipUtils
        .getALEipUser(rundata).getUserId().getValue(),
        ALAccessControlConstants.POERTLET_FEATURE_DOCUMENT_FOLDER,
        ALAccessControlConstants.VALUE_ACL_DELETE);
    return ret;
  }

  /**
   * 文書管理-ワークフロー連携がONかどうかを返します
   * @param 
   * @return 文書管理-ワークフロー連携がONかどうか
   */
  public static boolean isDocWorkflowCoop() {
    try {
      if (JetspeedResources.getInt("imware.cooperation.document_workflow") == 1) {
        return true;
      } else {
        return false;
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
  }

  /**
   * 文書IDを返します
   * @param rundata, context
   * @return 文書ID
   */
  public static Integer getDocId(RunData rundata, Context context) {
    ImwTDocumentFile file = getImwTDocumentFile(rundata, context);
    if (file == null) {
      return null;
    } else {
      return file.getDocId();
    }
  }

  /**
   * 再申請かどうかを返します
   * @param 文書ID
   * @return 再申請かどうか
   */
  public static boolean isDocReqAgain(Integer docId) {
    if (docId == null) {
      return false;
    } else {
      try {
        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();
        SelectQuery query = new SelectQuery(ImwTDocumentRequestMap.class);
        // 文書ID = 引数の文書ID
        Expression exp = ExpressionFactory.matchExp(
            ImwTDocumentRequestMap.DOC_ID_PROPERTY, docId);
        query.setQualifier(exp);
        // AND 差戻しフラグ = 1
        Expression exp2 = ExpressionFactory.matchExp(
            ImwTDocumentRequestMap.DENIED_PROPERTY, Integer.valueOf(1));
        query.andQualifier(exp2);
        // AND 過去フラグ = 0
        Expression exp3 = ExpressionFactory.matchExp(
            ImwTDocumentRequestMap.PAST_PROPERTY, Integer.valueOf(0));
        query.andQualifier(exp3);

        List files = dataContext.performQuery(query);

        if (files == null || files.size() == 0) {
          return false;
        } else {
          return true;
        }
      } catch (Exception ex) {
        logger.error("Exception", ex);
        return false;
      }
    }
  }

  /**
   * 申請依頼をデータベースに格納します。 <BR>
   *
   * @param rundata
   * @param context
   * @param file
   * @param request
   * @param mode
   * @param note
   * @param memberList
   * @param is_saved_route
   * @param route_id
   * @return TRUE 成功 FALSE 失敗
   */
  public static boolean insertRequest(RunData rundata, DataContext dataContext,
      ImwTDocumentFile file, EipTWorkflowRequest request, String mode,
      String note, ArrayList memberList, boolean is_saved_route, long route_id) {
    try {
      if (file == null) {
        dataContext.rollbackChanges();
        return false;
      }

      ALEipUser login_user = ALEipUtils.getALEipUser(rundata);

      //Integer request_id = getNextRequestId();   
      //if(request_id==null) return false;

      Date nowDate = Calendar.getInstance().getTime();

      // 申請種類
      Integer requestType = null;
      // ワークフロー依頼名     
      String request_name = "";
      if (DocumentConstants.MODE_REQUEST_INSERT.equals(mode)
          || DocumentConstants.MODE_REQAGAIN_INSERT.equals(mode)) {
        requestType = LibDocumentConstants.ID_REQUEST_INSERT;
      } else if (DocumentConstants.MODE_REQUEST_CHECKOUT.equals(mode)) {
        requestType = LibDocumentConstants.ID_REQUEST_CHECKOUT;
      } else if (DocumentConstants.MODE_REQUEST_CHECKIN.equals(mode)
          || DocumentConstants.MODE_REQAGAIN_CHECKIN.equals(mode)) {
        requestType = LibDocumentConstants.ID_REQUEST_CHECKIN;
      } else if (DocumentConstants.MODE_REQUEST_CHECKOUT_CANCEL.equals(mode)) {
        requestType = LibDocumentConstants.ID_REQUEST_CHECKOUT_CANCEL;
      } else if (DocumentConstants.MODE_REQUEST_DELETE.equals(mode)) {
        requestType = LibDocumentConstants.ID_REQUEST_DELETE;
      }
      request_name = decodeIdRequest(requestType, DocumentConstants.NAME_REQUEST);
      request_name += " - " + file.getFileName();

      EipTWorkflowCategory category = WorkflowUtils.getEipTWorkflowCategory(
          dataContext, (long)WorkflowConstants.CATEGORY_DOCUMENT);

      // リクエスト名
      request.setRequestName(request_name);

      // 親ID 常に新しい申請とする。
      request.setParentId(Integer.valueOf(0));
      
      // カテゴリID
      request.setEipTWorkflowCategory(category);
      // 申請経路ID

      if (is_saved_route) {
        EipTWorkflowRoute route = WorkflowUtils.getEipTWorkflowRoute(
            dataContext, Long.valueOf(route_id));
        request.setEipTWorkflowRoute(route);
      }
      // ユーザーID
      request.setUserId(Integer
          .valueOf((int) login_user.getUserId().getValue()));
      // 優先度
      request.setPriority(Short.valueOf("3"));
      // メモ
      request.setNote(note);
      // 金額
      request.setPrice(Long.valueOf(0));
      // 承認フラグ
      request.setProgress(WorkflowUtils.DB_PROGRESS_WAIT);
      // 作成日
      request.setCreateDate(Calendar.getInstance().getTime());
      // 更新日
      request.setUpdateDate(Calendar.getInstance().getTime());

      // 申請先の設定
      insertEipTWorkflowRequestMap(request, login_user,
          WorkflowUtils.DB_STATUS_REQUEST, 0, nowDate, 0, dataContext);
      insertEipTWorkflowRequestMap(request, (ALEipUser) memberList.get(0),
          WorkflowUtils.DB_STATUS_CONFIRM, 1, nowDate, 0, dataContext);

      int size = memberList.size();
      for (int i = 1; i < size; i++) {
        insertEipTWorkflowRequestMap(request, (ALEipUser) memberList.get(i),
            WorkflowUtils.DB_STATUS_WAIT, (i + 1), nowDate, 1, dataContext);
      }
      
      // 再申請時、ワークフロー依頼テーブルの旧申請レコードの削除
      if (DocumentConstants.MODE_REQAGAIN_INSERT.equals(mode)
          || DocumentConstants.MODE_REQAGAIN_CHECKIN.equals(mode)) {
        ImwTDocumentRequestMap requestMap = getImwTDocumentRequestMapByDocId(file
            .getDocId());
        if (requestMap != null) {
          SelectQuery query = new SelectQuery(EipTWorkflowRequest.class);
          Expression exp = ExpressionFactory.matchDbExp(
              EipTWorkflowRequest.REQUEST_ID_PK_COLUMN, requestMap
                  .getRequestId());
          query.setQualifier(exp);
          List requests = dataContext.performQuery(query);
          dataContext.deleteObjects(requests);
        }
      }

      // 文書申請マップテーブルへ登録
      ImwTDocumentRequestMap drmap = (ImwTDocumentRequestMap) dataContext
          .createAndRegisterNewObject(ImwTDocumentRequestMap.class);

      drmap.setDocId(file.getDocId());
      drmap.setRequestUserId(Integer.valueOf((int) login_user.getUserId()
          .getValue()));
      drmap.setRequestType(requestType);
      drmap.setDenied(Integer.valueOf(0));
      drmap.setPast(Integer.valueOf(0));

      drmap.setEipTWorkflowRequest(request);
      drmap.setImwTDocumentFile(file);
    } catch (Exception ex) {
      dataContext.rollbackChanges();
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  /**
   * 申請依頼　後処理
   * @param 文書ID
   * @return 再申請かどうか
   */
  public static boolean insertRequestEnd(RunData rundata,
      DataContext dataContext, 
      ImwTDocumentFile file ,EipTWorkflowRequest request, ArrayList memberList) {
    try {

      //int uid = ALEipUtils.getUserId(rundata);
      //String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
      //String folderName = rundata.getParameters().getString("folderName");
      // イベントログに保存
      ALEventlogFactoryService.getInstance().getEventlogHandler().log(
          request.getRequestId(),
          ALEventlogConstants.PORTLET_TYPE_WORKFLOW,
          request.getEipTWorkflowCategory().getCategoryName() + " "
              + request.getRequestName());

      // 次の申請先に新着ポートレット登録
      ALEipUser nextUser = (ALEipUser) memberList.get(0);
      ALAccessControlFactoryService aclservice = (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
          .getInstance())
          .getService(ALAccessControlFactoryService.SERVICE_NAME);
      ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();

      if (aclhandler.hasAuthority((int) nextUser.getUserId().getValue(),
          ALAccessControlConstants.POERTLET_FEATURE_WORKFLOW_REQUEST_SELF,
          ALAccessControlConstants.VALUE_ACL_DETAIL)) {
        WhatsNewUtils.insertWhatsNew(dataContext,
            WhatsNewUtils.WHATS_NEW_TYPE_WORKFLOW_REQUEST, request
                .getRequestId().intValue(), (int) nextUser.getUserId()
                .getValue());
      }
      // 次の申請先にメール送信
      //Upd 20110615 小濵 Start
      //WorkflowUtils.sendMail(rundata, request, nextUser, new ArrayList());
      WorkflowUtils.sendMail(rundata, request, nextUser, new ArrayList(),false,String.valueOf(ALEipUtils.getUserId(rundata)));
      //Upd 20110615 小濵 End

      //File folder = FileuploadUtils.getFolder(org_id, uid, folderName);
      // 添付ファイル保存先のフォルダを削除
      //FileuploadUtils.deleteFolder(folder);

      // ログ出力
      ALEipUser login_user = ALEipUtils.getALEipUser(rundata);
      String user = "";
      String filename = "";
      String filepath = "";
      String requestType = "";
      String docId = "";
      if(login_user!=null) {
        user = login_user.getAliasName().getValue();
      }
      if(file!=null){
        filename = file.getFileName();
        filepath = getFolderPath(file.getImwTDocumentFolder().getFolderId());
        docId = file.getDocId().toString();
        if (file.getDocId()!=null){
          ImwTDocumentRequestMap drmap = getImwTDocumentRequestMapByDocId(file.getDocId());
          if (drmap!=null){
            requestType = decodeIdRequest(drmap.getRequestType(), DocumentConstants.NAME_REQUEST);
          }
        }
      }
      
      String message = 
          "[user]" + user + "\t" + 
          "[action]" + requestType + "：" + filename + "（" + filepath + "）\t" + 
          "[文書ID]" + docId ;
      imwareLogger.info(message);
      
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  /**
   *
   * @param request
   * @param user
   * @param status
   *            R: 申請 C : 確認 A: 承認 D: 否認
   */
  public static void insertEipTWorkflowRequestMap(EipTWorkflowRequest request,
      ALEipUser user, String status, int order, Date now, int pullupOk,
      DataContext dataContext) {
    EipTWorkflowRequestMap map = (EipTWorkflowRequestMap) dataContext
        .createAndRegisterNewObject(EipTWorkflowRequestMap.class);
    int userid = (int) user.getUserId().getValue();
    map.setEipTWorkflowRequest(request);
    map.setUserId(Integer.valueOf(userid));
    // R: 申請 C : 確認 A: 承認 D: 否認
    map.setStatus(status);
    map.setOrderIndex(Integer.valueOf(order));
    map.setCreateDate(now);
    map.setUpdateDate(now);
    map.setPullupOk(pullupOk);
  }

  /**
   * 指定したユーザ名のオブジェクトを取得する．
   *
   * @param userList
   * @param userName
   * @return
   */
  public static TurbineUser getEipUserRecord(List userList, String userName) {
    int size = userList.size();
    for (int i = 0; i < size; i++) {
      TurbineUser record = (TurbineUser) userList.get(i);
      if (record.getLoginName().equals(userName)) {
        return record;
      }
    }
    return null;
  }

  /**
   * 画面より申請経路のメンバーを取得する．
   *
   * @param rundata
   * @param メンバーリスト
   * @param 申請経路から取得したか
   * @param ルートID
   * @return 取得の成否
   */
  public static boolean setWorkflowMemberFromRunData(RunData rundata,
      ArrayList memberList, boolean is_saved_route, long route_id) {
    String userNames[] = rundata.getParameters().getStrings(
        "positions_workflow");
    
    memberList.clear();

    try {

      if (is_saved_route) {

        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();

        SelectQuery query1 = new SelectQuery(EipTWorkflowRoute.class);
        Expression exp1 = ExpressionFactory.matchDbExp(
            EipTWorkflowRoute.ROUTE_ID_PK_COLUMN, route_id);

        query1.setQualifier(exp1);

        List list1 = dataContext.performQuery(query1);

        EipTWorkflowRoute record = (EipTWorkflowRoute) list1.get(0);
        String route = record.getRoute();

        if (!"".equals(route)) {
          StringTokenizer st = new StringTokenizer(route, ",");
          int lengthru = st.countTokens();
          String routeUserNames[] = new String[lengthru];

          for (int i = 0; i < lengthru; i++) {
            routeUserNames[i] = WorkflowUtils.getUserName(st.nextToken());
          }

          SelectQuery query = new SelectQuery(TurbineUser.class);
          Expression exp2 = ExpressionFactory.inExp(
              TurbineUser.LOGIN_NAME_PROPERTY, routeUserNames);
          Expression exp3 = ExpressionFactory.matchExp(
              TurbineUser.DISABLED_PROPERTY, "F");
          query.setQualifier(exp2);
          query.andQualifier(exp3);

          List list = dataContext.performQuery(query);

          TurbineUser record1 = null;
          int length = routeUserNames.length;
          for (int i = 0; i < length; i++) {
            record1 = getEipUserRecord(list, routeUserNames[i]);
            ALEipUser user = new ALEipUser();
            user.initField();
            user.setUserId(record1.getUserId().intValue());
            user.setName(record1.getLoginName());
            user.setAliasName(record1.getFirstName(), record1.getLastName());
            memberList.add(user);
          }
        }
      } else if (userNames != null && userNames.length > 0) {

        DataContext dataContext = DatabaseOrmService.getInstance()
            .getDataContext();
        SelectQuery query = new SelectQuery(TurbineUser.class);
        Expression exp1 = ExpressionFactory.inExp(
            TurbineUser.LOGIN_NAME_PROPERTY, userNames);
        Expression exp2 = ExpressionFactory.matchExp(
            TurbineUser.DISABLED_PROPERTY, "F");
        query.setQualifier(exp1);
        query.andQualifier(exp2);

        List list = dataContext.performQuery(query);

        TurbineUser record = null;
        int length = userNames.length;
        for (int i = 0; i < length; i++) {
          record = getEipUserRecord(list, userNames[i]);
          ALEipUser user = new ALEipUser();
          user.initField();
          user.setUserId(record.getUserId().intValue());
          user.setName(record.getLoginName());
          user.setAliasName(record.getFirstName(), record.getLastName());
          memberList.add(user);
        }
      }
      return true;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
  }
  
  public static boolean setWorkflowMember(ArrayList memberList, String route){
    try{
      DataContext dataContext = DatabaseOrmService.getInstance()
      .getDataContext();
      memberList.clear();
      if (!"".equals(route)) {
        StringTokenizer st = new StringTokenizer(route, ",");
        int lengthru = st.countTokens();
        String routeUserNames[] = new String[lengthru];

        for (int i = 0; i < lengthru; i++) {
          routeUserNames[i] = WorkflowUtils.getUserName(st.nextToken());
        }

        SelectQuery query = new SelectQuery(TurbineUser.class);
        Expression exp2 = ExpressionFactory.inExp(
            TurbineUser.LOGIN_NAME_PROPERTY, routeUserNames);
        Expression exp3 = ExpressionFactory.matchExp(
            TurbineUser.DISABLED_PROPERTY, "F");
        query.setQualifier(exp2);
        query.andQualifier(exp3);

        List list = dataContext.performQuery(query);

        TurbineUser record1 = null;
        int length = routeUserNames.length;
        for (int i = 0; i < length; i++) {
          record1 = getEipUserRecord(list, routeUserNames[i]);
          ALEipUser user = new ALEipUser();
          user.initField();
          user.setUserId(record1.getUserId().intValue());
          user.setName(record1.getLoginName());
          user.setAliasName(record1.getFirstName(), record1.getLastName());
          memberList.add(user);
        }
      }
      return true;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
  }

  /**
   * 申請マップオブジェクトモデルを取得します。 <BR>
   *
   * @param 文書ID
   * @return　文書ファイル申請マップオブジェクト
   */
  public static ImwTDocumentRequestMap getImwTDocumentRequestMapByDocId(
      Integer docId) {

    try {
      if (docId == null || Integer.valueOf(docId) == null) {
        return null;
      }

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentRequestMap.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentRequestMap.DOC_ID_PROPERTY, docId);
      Expression exp2 = ExpressionFactory.matchExp(
          ImwTDocumentRequestMap.PAST_PROPERTY, Integer.valueOf(0));
      query.setQualifier(exp);
      query.andQualifier(exp2);
      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        // 指定したファイル IDのレコードが見つからない場合
        logger.debug("[Document Request Map] Not found Map ID...");
        return null;
      }

      return ((ImwTDocumentRequestMap) files.get(0));
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ワークフロー依頼オブジェクトモデルを取得します。 <BR>
   *
   * @param 文書ID
   * @return　文書ファイル申請マップオブジェクト
   */
  public static EipTWorkflowRequest getEipTWorkflowRequestByDocId(Integer docId) {

    try {
      if (docId == null || Integer.valueOf(docId) == null) {
        return null;
      }

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();

      ImwTDocumentRequestMap requestMap = getImwTDocumentRequestMapByDocId(docId);

      if (requestMap == null)
        return null;

      SelectQuery query = new SelectQuery(EipTWorkflowRequest.class);
      Expression exp = ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN, requestMap.getRequestId());
      query.setQualifier(exp);

      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        // 指定したファイル IDのレコードが見つからない場合
        logger.debug("[Workflow Request] Not found request ID...");
        return null;
      }

      return ((EipTWorkflowRequest) files.get(0));
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * 申請種類を取得します。 <BR>
   *
   * @param 文書ID
   * @return　文書ファイル申請マップオブジェクト
   */
  public static Integer getRequestTypeByDocId(Integer docId) {
    ImwTDocumentRequestMap map = getImwTDocumentRequestMapByDocId(docId);

    if (map == null) {
      return 0;
    } else {
      return map.getRequestType();
    }
  }

//2010/06/25 ワークフロー詳細画面で利用するため、lib/libdocument の LibDocumentUtils に移植
  /**
   * 関連マップのファイルパスを取得します。 <BR>
   *
   * @param 文書ID
   * @param 申請状態
   * @return　関連マップのファイルパス
   */
/*
  public static ArrayList getRelationFilePaths(Integer docId,
      Integer requestStatus) {

    try {
      if (docId == null || Integer.valueOf(docId) == null) {
        return null;
      }

      ArrayList paths = new ArrayList();

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.DOC_ID_PROPERTY, docId);
      query.setQualifier(exp);
      if (requestStatus != null) {
        Expression exp2 = ExpressionFactory.matchExp(
            ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY, requestStatus);
        query.setQualifier(exp2);
      }

      List files = dataContext.performQuery(query);
      if (files == null || files.size() == 0) {
        // 指定したファイル IDのレコードが見つからない場合
        logger.debug("[Document Relation Map] Not found Map ID...");
        return null;
      } else {
        for (Object file : files) {
          paths.add(((ImwTDocumentRelationMap) file).getFilePath());
        }
      }

      return paths;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }
*/
  
//2010/06/28 ワークフロー詳細画面で利用するため、lib/libdocument の LibDocumentUtils に移植
  /**
   * 文書ファイルマップテーブルと文書ファイル関連マップのレコードを削除します。(コミットはしません） <BR>
   *
   * @param dataContext
   * @param 文書ID
   * @param 申請状態
   * @return　成否
   */
/*  
  public static boolean deleteFileMap(DataContext dataContext, Integer docId,
      Integer requestStatus) {
    try {
      if (docId == null)
        return false;

      SelectQuery query = new SelectQuery(ImwTDocumentFileMap.class);
      Expression exp;
      Expression exp2;
      exp = ExpressionFactory.matchExp(ImwTDocumentFileMap.DOC_ID_PROPERTY,
          docId);
      query.setQualifier(exp);
      if (requestStatus != null) {
        exp2 = ExpressionFactory.matchExp(
            ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY, requestStatus);
        query.andQualifier(exp2);
      }
      List filemaps = dataContext.performQuery(query);
      dataContext.deleteObjects(filemaps);

    } catch (Exception ex) {
      dataContext.rollbackChanges();
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }
*/
  
  // 2010/06/25 ワークフロー詳細画面で利用するため、lib/libdocument の LibDocumentUtils に移植
  /**
   * 文書ファイルテーブルと文書ファイルマップテーブルと文書ファイル関連マップのレコードを削除します。(コミットはしません） <BR>
   *
   * @param dataContext
   * @param 文書ファイルオブジェクト
   * @param 申請状態
   * @return　成否
   */
/*
  public static boolean deleteDocument(DataContext dataContext,
      ImwTDocumentFile file, Integer requestStatus) {
    try {
      if (file == null) {
        dataContext.rollbackChanges();
        return false;
      }

      //文書ファイルマップIDの取得
      String relFileId = file.getDocId().toString();

      //文書ファイル
      Expression expressionFile = ExpressionFactory.matchDbExp(
          ImwTDocumentFile.FILE_ID_PK_COLUMN, file.getFileId());
      //文書ファイルマップ
      Expression expressionFileMap = ExpressionFactory.matchExp(
          ImwTDocumentFileMap.DOC_ID_PROPERTY, relFileId)
          .andExp(ExpressionFactory.matchExp(
              ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY,1));
      //文書ファイル関連マップ
      Expression expressionRelationMap = ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.DOC_ID_PROPERTY, relFileId)
          .andExp(ExpressionFactory.matchExp(
              ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY,1));;

      SelectQuery queryFile = new SelectQuery(ImwTDocumentFile.class);
      SelectQuery queryFileMap = new SelectQuery(ImwTDocumentFileMap.class);
      SelectQuery queryRelationMap = new SelectQuery(
          ImwTDocumentRelationMap.class);

      queryFile.setQualifier(expressionFile);
      queryFileMap.setQualifier(expressionFileMap);
      queryRelationMap.setQualifier(expressionRelationMap);

      //申請状態
      if (requestStatus != null) {
        Expression expressionFileMap2 = ExpressionFactory.matchExp(
            ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY, requestStatus);
        Expression expressionRelationMap2 = ExpressionFactory.matchExp(
            ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY, requestStatus);

        queryFileMap.andQualifier(expressionFileMap2);
        queryRelationMap.andQualifier(expressionRelationMap2);
      }

      List listFile = dataContext.performQuery(queryFile);
      List listFileMap = dataContext.performQuery(queryFileMap);
      List listFileRelationMap = dataContext.performQuery(queryRelationMap);

      //文書ファイルマップ
      dataContext.deleteObjects(listFileMap);
      //関連文書ファイルマップ
      dataContext.deleteObjects(listFileRelationMap);
      //文書ファイル
      dataContext.deleteObjects(listFile);
    } catch (Exception ex) {
      dataContext.rollbackChanges();
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }
*/
  
  // 2010/06/25 ワークフロー詳細画面で利用するため、lib/libdocument の LibDocumentUtils に移植
  /**
   * 文書削除の後処理を行います。 <BR>
   *
   * @param ファイルID
   * @param ファイル名
   * @param ファイルパス
   * @param 組織ID
   * @param 関連マップのファイルパスのリスト
   * @return　成否
   */
/*
  public static boolean deleteDocumentEnd(ImwTDocumentFile file, String org_id,
      List relation_file_path) {
    try {
      if (file == null) {
        return false;
      }

      // ファイルパスの取得
      String local_file_pass = file.getFilePath();
      //　ファイルIDの取得
      int entityId = file.getFileId();
      // ファイルタイトルの取得
      String fileName = file.getFileTitle();

      // イベントログに保存
      ALEventlogFactoryService.getInstance().getEventlogHandler().log(entityId,
          ALEventlogConstants.PORTLET_TYPE_DOCUMENT_FILE, fileName);

      if (local_file_pass != null && !"".equals(local_file_pass)) {
        // ローカルファイルに保存されているファイルを削除する．
        File local_file = null;
        local_file = new File(DocumentUtils.getSaveDirPath(org_id)
            + local_file_pass);
        if (local_file.exists()) {
          local_file.delete();
        }
      }
      if (relation_file_path != null && relation_file_path.size() > 0) {
        for (int i = 0; i < relation_file_path.size(); i++) {
          // ローカルファイルに保存されている関連文書を削除する．
          File local_file = null;
          local_file = new File(DocumentUtils.getSaveDirPath(org_id)
              + relation_file_path.get(i).toString());
          if (local_file.exists()) {
            local_file.delete();
          }
        }
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }
*/
  
  /**
   * リクエストをデータベースから削除します。 <BR>
   *
   * @param request
   * @return TRUE 成功 FALSE 失敗
   */
  public static boolean deleteRequest(DataContext dataContext,
      EipTWorkflowRequest request) {
    try {
      if (request == null) {
        dataContext.rollbackChanges();
        return false;
      }
      SelectQuery query;
      Expression exp;

      // 文書ファイル申請マップを削除   DELETE CASCADE を設定したため リクエスト削除時に同時に消える
      /*
      query = new SelectQuery(ImwTDocumentRequestMap.class);
      exp = ExpressionFactory.matchExp(
          ImwTDocumentRequestMap.REQUEST_ID_PROPERTY, request.getRequestId());
      query.setQualifier(exp);
      List maps = dataContext.performQuery(query);
      
      dataContext.deleteObjects(maps);
       */

      // リクエストを削除
      query = new SelectQuery(EipTWorkflowRequest.class);
      exp = ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN, request.getRequestId());
      query.setQualifier(exp);
      List requests = dataContext.performQuery(query);
      dataContext.deleteObjects(requests);

    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  public static boolean deleteRequestEnd(EipTWorkflowRequest request,
      String catname) {
    try {
      // イベントログ用

      String reqname = request.getRequestName();

      // イベントログに保存
      ALEventlogFactoryService.getInstance().getEventlogHandler().log(
          request.getRequestId(), ALEventlogConstants.PORTLET_TYPE_WORKFLOW,
          catname + " " + reqname);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  public static String getNewFileInfo(ImwTDocumentFile file,
      boolean is_member_read, boolean is_member_edit, ArrayList readGroups,
      ArrayList readUsers, ArrayList editGroups, ArrayList editUsers,
      String[] relationids, List relationuploadList) {
    String note = "";
    
    // フォルダ階層取得
    String folderPosition = "";
    ArrayList folder_hierarchy_list = new ArrayList();
    folder_hierarchy_list = DocumentUtils.getFolderList();
    Integer folder_id = file.getImwTDocumentFolder().getFolderId();
    if (folder_hierarchy_list != null && folder_id != null){
      folderPosition = DocumentUtils.getFolderPosition(folder_hierarchy_list,folder_id);
      if(folderPosition!=null){
        folderPosition = folderPosition.replaceAll("<b> &gt; </b>", " > ");
      }
    }
    
    note += "タイトル：" + file.getFileTitle() + "\r\n";
    note += "ファイル名：" + file.getFileName() + "\r\n";
    note += "バージョン：" + file.getFileRevMj() + "." + file.getFileRevMn() + "\r\n";
    note += "関連文書：" + "\r\n"
        + newRelationToNote(relationids, relationuploadList, "　");
    note += "公開終了日：" + dateToString(file.getOpenEndDate(), "yyyy'年'M'月'd'日'")
        + "\r\n";
    note += "保存終了日：" + dateToString(file.getSaveEndDate(), "yyyy'年'M'月'd'日'")
        + "\r\n";
    note += "保存先フォルダ：" + folderPosition + "\r\n";
    note += "チェックインコメント：" + file.getCheckinComment() + "\r\n";
    note += "メモ：" + file.getNote() + "\r\n";
    note += "アクセス権限：\r\n";
    note += "　【閲覧権限】\r\n";
    if (is_member_read) {
      note += groupsToNote(readGroups, "　　");
      note += usersToNote(readUsers, "　　");
    } else {
      note += "　　全てのユーザー\r\n";
    }
    note += "　【編集権限】\r\n";
    if (is_member_edit) {
      note += groupsToNote(editGroups, "　　");
      note += usersToNote(editUsers, "　　");
    } else {
      note += "　　全てのユーザー\r\n";
    }

    return note;
  }

  /**
   * 追加申請、チェックイン申請時の関連文書のファイル名のリストをテキスト化
   * @param relationids
   * @param relationuploadList
   * @param header
   * @return　ファイル名のリストのテキスト
   */
  public static String newRelationToNote(String relationids[],
      List relationuploadList, String header) {
    try {
      String note = "";
      ArrayList oldFileids = new ArrayList();
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();

      if (header == null) {
        header = "";
      }

      int relSize = 0;
      if (relationids != null) {
        if (relationids[0].equals("")) {
          relSize = 0;
        } else {
          relSize = relationids.length;
        }
      }

      if (relationids != null && relSize > 0) {
        // 先頭の1文字で過去の登録ファイルを抽出
        for (String id : relationids) {
          int idLen = id.length();
          if ("I".equals(id.substring(0, 1))) {
            String temp = id.substring(1, idLen);
            oldFileids.add(id.substring(1, idLen));
          }
        }

        // 過去に追加したファイル名を取得
        if (oldFileids != null && oldFileids.size() > 0) {
          for (Object obj : oldFileids) {
            String id = obj.toString();
            SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
            query.setQualifier(ExpressionFactory.matchDbExp(
                ImwTDocumentRelationMap.ID_PK_COLUMN, id));
            List files = dataContext.performQuery(query);
            if (files != null && files.size() > 0) {
              ImwTDocumentRelationMap file = (ImwTDocumentRelationMap) (files
                  .get(0));
              note += header + file.getFileName() + "\r\n";
            }
          }
        }
      }

      // 新規追加ファイル名を取得
      if (relationuploadList != null && relationuploadList.size() > 0) {
        for (Object obj : relationuploadList) {
          RelationuploadLiteBean filebean = (RelationuploadLiteBean) obj;
          note += header + filebean.getFileName() + "\r\n";
        }
      }
      return note;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }

  /**
   * チェックアウト申請、チェックアウト取消申請、削除申請のファイル情報をテキスト化
   * @param file
   * @return
   */
  public static String getOldFileInfo(ImwTDocumentFile file) {
    try {

      if (file == null) {
        return "";
      }
      DocumentAccessMember readMember = new DocumentAccessMember();
      DocumentAccessMember editMember = new DocumentAccessMember();

      // フォルダ階層取得
      String folderPosition = "";
      ArrayList folder_hierarchy_list = new ArrayList();
      folder_hierarchy_list = DocumentUtils.getFolderList();
      Integer folder_id = file.getImwTDocumentFolder().getFolderId();
      if (folder_hierarchy_list != null && folder_id != null){
        folderPosition = DocumentUtils.getFolderPosition(folder_hierarchy_list,folder_id);
        if(folderPosition!=null){
          folderPosition = folderPosition.replaceAll("<b> &gt; </b>", " > ");
        }
      }
      
      String note = "";
      note += "タイトル：" + file.getFileTitle() + "\r\n";
      note += "ファイル名：" + file.getFileName() + "\r\n";
      note += "バージョン：" + file.getFileRevMj() + "." + file.getFileRevMn()
          + "\r\n";
      note += "関連文書：" + "\r\n" + oldRelationToNote(file, "　");
      note += "公開終了日：" + dateToString(file.getOpenEndDate(), "yyyy'年'M'月'd'日'")
          + "\r\n";
      note += "保存終了日：" + dateToString(file.getSaveEndDate(), "yyyy'年'M'月'd'日'")
          + "\r\n";
      note += "保存先フォルダ：" + folderPosition + "\r\n";
      note += "チェックインコメント：" + file.getCheckinComment() + "\r\n";
      note += "メモ：" + file.getNote() + "\r\n";
      note += "アクセス権限：\r\n";
      note += "　【閲覧権限】\r\n";

      getMemberFromMap(readMember, file.getDocId(), 0, 0);
      getMemberFromMap(editMember, file.getDocId(), 1, 0);

      if (readMember.getIsMember()) {
        note += groupsToNote(readMember.getGroups(), "　　");
        note += usersToNote(readMember.getUsers(), "　　");
      } else {
        note += "　　全てのユーザー\r\n";
      }
      note += "　【編集権限】\r\n";
      if (editMember.getIsMember()) {
        note += groupsToNote(editMember.getGroups(), "　　");
        note += usersToNote(editMember.getUsers(), "　　");
      } else {
        note += "　　全てのユーザー\r\n";
      }

      return note;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }
  
  /**
   * 追加申請、チェックイン申請時の関連文書のファイル名のリストをテキスト化
   * @param relationids
   * @param relationuploadList
   * @param header
   * @return　ファイル名のリストのテキスト
   */
  public static String oldRelationToNote(ImwTDocumentFile file, String header) {
    try {

      if (file == null || file.getDocId() == null) {
        return "";
      }

      String note = "";
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      Integer docId = file.getDocId();

      SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
      query.setQualifier(ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.DOC_ID_PROPERTY, docId));
      query.andQualifier(ExpressionFactory.matchExp(
          ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY, 0));
      List maps = dataContext.performQuery(query);
      if (maps != null && maps.size() > 0) {
        for(Object obj :maps){
          ImwTDocumentRelationMap map = (ImwTDocumentRelationMap) obj;
          note += header + map.getFileName() + "\r\n";
        }
      }

      return note;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }
  
  /**
   * IMW_T_DOCUMENT_FILE_MAP から権限を持つグループリストとユーザリストを抽出します
   * 
   */
  protected static boolean getMemberFromMap(DocumentAccessMember member,
      Integer docId, Integer editable, Integer requestStatus) {
    try {

      if (docId == null){
        return false;
      }
      // 変数の宣言
      SelectQuery query;
      Expression exp, exp2, exp3;
      DataContext dataContext = DatabaseOrmService.getInstance()
      .getDataContext();
      
      ArrayList groupList = member.getGroups();
      ArrayList userList = member.getUsers();
      
      member.setIsMember(true);

      // グループのリストを取得
      query = new SelectQuery(ImwTDocumentFileMap.class);
      exp = ExpressionFactory.matchExp(ImwTDocumentFileMap.DOC_ID_PROPERTY,
          docId);
      exp2 = ExpressionFactory.matchExp(ImwTDocumentFileMap.EDITABLE_PROPERTY,
          editable);
      exp3 = ExpressionFactory.matchExp(ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY,
          requestStatus);
      query.setQualifier(exp);
      query.andQualifier(exp2);
      query.andQualifier(exp3);
      List glist = dataContext.performQuery(query);

      List group = new ArrayList();
      int gsize = glist.size();
      for (int i = 0; i < gsize; i++) {
        ImwTDocumentFileMap map = (ImwTDocumentFileMap) glist.get(i);
        Integer gid = map.getGroupId();
        if (gid != null) {
          //全ユーザーが権限を持つ場合
          if (gid.intValue() == -1) {
            member.setIsMember(false);
            break;
          }
          group.add(map.getGroupId());
        }
      }
      query = new SelectQuery(TurbineGroup.class);
      exp = ExpressionFactory.inDbExp(TurbineGroup.GROUP_ID_PK_COLUMN, group);
      query.setQualifier(exp);
      groupList.addAll(DocumentUtils.getGroupFromSelectQuery(query));
      
      // メンバーのリストを取得
      query = new SelectQuery(ImwTDocumentFileMap.class);
      exp = ExpressionFactory.matchExp(ImwTDocumentFileMap.DOC_ID_PROPERTY,
          docId);
      exp2 = ExpressionFactory.matchExp(ImwTDocumentFileMap.EDITABLE_PROPERTY,
          editable);
      exp3 = ExpressionFactory.matchExp(ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY,
          requestStatus);
      query.setQualifier(exp);
      query.andQualifier(exp2);
      query.andQualifier(exp3);
      List list = dataContext.performQuery(query);

      List users = new ArrayList();
      int usize = list.size();
      for (int i = 0; i < usize; i++) {
        ImwTDocumentFileMap map = (ImwTDocumentFileMap) list.get(i);
        users.add(map.getUserId());
      }
      query = new SelectQuery(TurbineUser.class);
      exp = ExpressionFactory.inDbExp(TurbineUser.USER_ID_PK_COLUMN, users);
      query.setQualifier(exp);
      userList.addAll(DocumentUtils.getUsersFromSelectQuery(query));

      return true;
    } catch (Exception ex) {
      return false;
    }
  }
  
  public static String groupsToNote(ArrayList groups, String header) {
    try {
      String note = "";
      if (header == null) {
        header = "";
      }

      for (Object obj : groups) {
        TurbineGroup group = (TurbineGroup) obj;
        note += header + group.getGroupAliasName() + "\r\n";
      }

      return note;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }

  public static String usersToNote(ArrayList users, String header) {
    try {
      String note = "";

      for (Object obj : users) {
        ALEipUser user = (ALEipUser) obj;
        note += header + user.getAliasName().getValue() + "\r\n";
      }

      return note;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }

  public static String dateToString(Date date, String format) {
    try {
      if (date == null || "".equals(date)) {
        return "";
      }
      if (format == null || "".equals(format)) {
        format = "yyyy/MM/dd";
      }
      DateFormat df = new SimpleDateFormat(format);
      return df.format(date);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }
  
  /**
   * 文書申請のデフォルトの申請経路オブジェクトを取得します。
   * @return　文書申請のデフォルトの申請経路オブジェクト
   */
  public static EipTWorkflowRoute getDocRoute(){
    try {
      DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
      SelectQuery query = new SelectQuery(EipTWorkflowCategory.class);
      Expression exp = ExpressionFactory.matchDbExp(
          EipTWorkflowCategory.CATEGORY_ID_PK_COLUMN, WorkflowConstants.CATEGORY_DOCUMENT);
      query.andQualifier(exp);
      List records = dataContext.performQuery(query);
      
      if (records != null){
        EipTWorkflowCategory category = (EipTWorkflowCategory) records.get(0);
        return category.getEipTWorkflowRoute();
      }
      return null;

    } catch (Exception ex){
      logger.error("Exception", ex);
      return null;
    }
  }
/*  
  public static boolean requestLog(ImwTDocumentFile file, EipTWorkflowRequest request){
    try {
      String message = "";
      String userName = "";
      
      
      return true;
    } catch (Exception ex){
      logger.error("Exception", ex);
      return false;
    }
  }
*/
  /**
   * 申請種類IDを接尾語を付けた文字列に変換します。<BR>
   * @param 申請種類ID
   * @param 接尾語
   * @return 申請種類　文字列
   */
  public static String decodeIdRequest(int id, String footer) {
    try {
      String str = "";
      switch (id) {
      case LibDocumentConstants.ID_REQUEST_INSERT:
        str = DocumentConstants.NAME_REQUEST_INSERT + footer;
        break;
      case LibDocumentConstants.ID_REQUEST_CHECKOUT:
        str = DocumentConstants.NAME_REQUEST_CHECKOUT + footer;
        break;
      case LibDocumentConstants.ID_REQUEST_CHECKIN:
        str = DocumentConstants.NAME_REQUEST_CHECKIN + footer;
        break;
      case LibDocumentConstants.ID_REQUEST_CHECKOUT_CANCEL:
        str = DocumentConstants.NAME_REQUEST_CHECKOUT_CANCEL + footer;
        break;
      case LibDocumentConstants.ID_REQUEST_DELETE:
        str = DocumentConstants.NAME_REQUEST_DELETE + footer;
        break;
      default:
        str = "";
        break;
      }
      return str;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return "";
    }
  }
  
  /**
   * ファイルが申請中かどうかを返します。
   * @param file
   * @return
   */
  public static boolean isDocRequesting(ImwTDocumentFile file) {
    try {
      ImwTDocumentRequestMap rmap;
      if (file==null){
        return false;
      }
      rmap = getImwTDocumentRequestMapByDocId(file.getDocId());
      if (rmap == null){
        return false;
      } else {
        return true;
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return false;
    }
  }
    
  // 2010/06/29 lib/libdocument の LibDocumentUtils に移植
  /**
   * 現在有効な最新の文書オブジェクトを取得します。
   * @return　文書申請のデフォルトの申請経路オブジェクト
   */
/*
  public static ImwTDocumentFile getLastDoc(Integer docId){
    try {
      if (docId==null) {
        return null;
      }
      
      DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
      SelectQuery query = new SelectQuery(ImwTDocumentFile.class);
      Expression exp = ExpressionFactory.matchExp(
          ImwTDocumentFile.DOC_ID_PROPERTY, docId);
      Expression exp2 = ExpressionFactory.matchExp(
          ImwTDocumentFile.STATUS_PROPERTY, 0);
      Expression exp3 = ExpressionFactory.matchExp(
          ImwTDocumentFile.STATUS_PROPERTY, 1);
      query.setQualifier(exp);
      query.andQualifier(exp2.orExp(exp3));
      List records = dataContext.performQuery(query);
      
      if (records != null){
        ImwTDocumentFile file = (ImwTDocumentFile) records.get(0);
        return file;
      }
      return null;

    } catch (Exception ex){
      logger.error("Exception", ex);
      return null;
    }
  }
*/
  
  /**
   * 特殊文字をエスケープします。
   */
  public static String escapeSpecial(String word, String escape){
    try{
      if ("\\".equals(escape)){
        // バックスラッシュをLIKE句中で普通の文字として検索するには
        // SQL文中でバックスラッシュが4個必要
        word = word.replace("\\", "\\\\\\\\");
        // エスケープ文字はSQL文中でバックスラッシュ2個
        escape = "\\\\";
      } else {
        word = word.replace(escape, escape + escape);
        // エスケープ文字をバックスラッシュ以外にした場合
        // SQL文中でバックスラッシュは2個でよい
        word = word.replace("\\", "\\\\");
      }
      
      word = word.replaceAll("'", "''");      
      word = word.replace("_", escape + "_");
      word = word.replace("%", escape + "%");
      return word;
    } catch (Exception ex){
      logger.error("Exception", ex);
      return "";
    }
  }
  
  /**
   * 特殊文字をエスケープします。
   */
  public static String escapeSpecial(String word){
    return escapeSpecial(word, "\\");
  }
  
  /**
   * 文字列が数値であるかチェックします。
   */
  public static boolean isNumber(String numString){
    try{
      Double.parseDouble(numString);
      return true;
    } catch(Exception ex){
      return false;
    }
  }
  
  /**
   * フォルダ階層を取得します
   * @param folder_id
   * @return String
   */
  public static String getFolderPath(Integer folder_id){
    // フォルダ階層取得
    String folderPosition = "";
    ArrayList folder_hierarchy_list = new ArrayList();
    folder_hierarchy_list = DocumentUtils.getFolderList();
    //Integer folder_id = file.getImwTDocumentFolder().getFolderId();
    if (folder_hierarchy_list != null && folder_id != null){
      folderPosition = DocumentUtils.getFolderPosition(folder_hierarchy_list,folder_id);
      if(folderPosition!=null){
        folderPosition = folderPosition.replaceAll("<b> &gt; </b>", " > ");
      }
    }
    return folderPosition;
  }
}