/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * http://aipostyle.com/
 * 
 * Copyright(C) 2010 avanza Co.,Ltd. All rights reserved.
 * http://www.avnz.co.jp/
 * 
 * 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.extcabinet.util;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
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.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.eip.cayenne.om.portlet.AvzTCabinetFile;
import com.aimluck.eip.cayenne.om.portlet.AvzTCabinetFolder;
import com.aimluck.eip.cayenne.om.portlet.AvzTFileAcl;
import com.aimluck.eip.cayenne.om.portlet.AvzTFolderAcl;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTCabinetFile;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTCabinetFolder;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTFileAcl;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTFolderAcl;
import com.aimluck.eip.cayenne.om.security.TurbineGroup;
import com.aimluck.eip.cayenne.om.security.TurbineUserGroupRole;
import com.aimluck.eip.cayenne.om.security.auto._TurbineUserGroupRole;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.extcabinet.ExtCabinetAclResultData;
import com.aimluck.eip.extcabinet.ExtFolderInfo;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.ResultList;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.util.orgutils.ALOrgUtilsFactoryService;
import com.aimluck.eip.util.orgutils.ALOrgUtilsHandler;

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

  /** logger */
  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(ExtCabinetUtils.class.getName());

  /** フォルダ『ルートフォルダ』の予約 ID */
  public static final int ROOT_FODLER_ID = 1;

  /** 『ルートフォルダ』の親フォルダ ID */
  public static final int ROOT_PARENT_FODLER_ID = 0;

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

  /** リクエストの識別子 */
  public static final String REQUEST_KEY_FOLDER_ID = "folder_id";

  /** 共有ファイルを保管するディレクトリのカテゴリキーの指定 */
  protected static final String CATEGORY_KEY =
    "ext" + JetspeedResources.getString("aipo.cabinet.categorykey", "");

  /** 共有ファイルを保管するディレクトリの指定 */
  private static final String FOLDER_FILEDIR_CABINET =
    JetspeedResources.getString("aipo.filedir", "");

  // motegi start
  /** 対象（ユーザー、グループ、全員）のIDの格納キー */
  public static final String AUTHORITY_TARGET_ID = "target_id";

  /** 対象の種別 ユーザー"U"、グループ"G"、全員"E" の格納キー */
  public static final String AUTHORITY_TARGET_TYPE = "target_type";

  /** 権限付与・剥奪対象の種別 */
  public static final String AUTHORITY_LEVEL_USER = "U";

  public static final String AUTHORITY_LEVEL_GROUP = "G";

  public static final String AUTHORITY_LEVEL_EVERYONE = "E";

  /** 画面の権限チェックボックスの値 */
  public static final String AUTHORITY_ON = "1";

  public static final String AUTHORITY_OFF = "0";

  /** データベースのプロパティ値 権限付与"G"／剥奪"R" */
  public static final String AUTHORITY_GRANT = "G";

  public static final String AUTHORITY_REVOKE = "R";

  /** 画面－Javaで使用するキー */
  public static final String AUTHORITY_F = "file_creatable";

  public static final String AUTHORITY_C = "folder_creatable";

  public static final String AUTHORITY_R = "readable";

  public static final String AUTHORITY_U = "writable";

  public static final String AUTHORITY_D = "deletable";

  /** データベースのプロパティ値 ファイル追加"F"／フォルダ追加"C"／参照"R"／更新"U"／削除"D" */
  public static final String DB_PROPERTY_F = "F";

  public static final String DB_PROPERTY_C = "C";

  public static final String DB_PROPERTY_R = "R";

  public static final String DB_PROPERTY_U = "U";

  public static final String DB_PROPERTY_D = "D";

  /** 画面表示用 */
  public static final String ALL_USER = "ユーザー全員";

  // motegi end

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

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

      SelectQuery<AvzTCabinetFolder> query =
        Database.query(AvzTCabinetFolder.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          _AvzTCabinetFolder.FOLDER_ID_PK_COLUMN,
          folderid);
      query.setQualifier(exp);
      ResultList<AvzTCabinetFolder> folders = query.getResultList();
      if (folders == null || folders.size() == 0) {
        // 指定したフォルダ IDのレコードが見つからない場合
        logger.debug("[Cabinet Folder] Not found ID...");
        return null;
      }
      return (folders.get(0));
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

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

      SelectQuery<AvzTCabinetFile> query =
        Database.query(AvzTCabinetFile.class);
      Expression exp =
        ExpressionFactory
          .matchDbExp(_AvzTCabinetFile.FILE_ID_PK_COLUMN, fileid);
      query.setQualifier(exp);
      ResultList<AvzTCabinetFile> files = query.getResultList();
      if (files == null || files.size() == 0) {
        // 指定したファイル IDのレコードが見つからない場合
        logger.debug("[Cabinet File] Not found ID...");
        return null;
      }

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

  /**
   * ファイルオブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static ResultList<AvzTCabinetFile> getAvzTCabinetFileList(int folderId) {
    try {
      SelectQuery<AvzTCabinetFile> query =
        Database.query(AvzTCabinetFile.class);
      Expression exp =
        ExpressionFactory.matchExp(_AvzTCabinetFile.FOLDER_ID_PROPERTY, Integer
          .valueOf(folderId));
      query.setQualifier(exp);
      ResultList<AvzTCabinetFile> files = query.getResultList();
      if (files == null || files.size() == 0) {
        return null;
      }

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

  public static List<ExtFolderInfo> getFolderList(int folder_id) {
    try {
      SelectQuery<AvzTCabinetFolder> query =
        Database.query(AvzTCabinetFolder.class);
      query.orderAscending(_AvzTCabinetFolder.FOLDER_NAME_PROPERTY);
      ResultList<AvzTCabinetFolder> list = query.getResultList();
      if (list == null || list.size() < 0) {
        return null;
      }

      List<ExtFolderInfo> prerootlist =
        getExtFolderInfoList(
          list,
          folder_id,
          ExtCabinetUtils.ROOT_PARENT_FODLER_ID);

      List<ExtFolderInfo> result = getFolderList(prerootlist);

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

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

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

  }

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

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

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

  public static void setFolderVisible(List<ExtFolderInfo> folder_list,
      ExtFolderInfo selectedinfo, RunData rundata) {
    if (folder_list == null || folder_list.size() <= 0) {
      return;
    }

    List<ExtFolderInfo> list = new ArrayList<ExtFolderInfo>();
    ExtFolderInfo 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 = 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++) {
      ExtFolderInfo info1 = folder_list.get(i);
      boolean containsId = false;
      for (int j = 0; j < list.size(); j++) {
        ExtFolderInfo info2 = 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(
      List<ExtFolderInfo> folder_list, RunData rundata) {
    ExtFolderInfo info;
    int size = folder_list.size();
    /** アクセス権限による表示の制御 */
    List<Integer> invisible_children = new ArrayList<Integer>();
    for (int i = 0; i < size; i++) {
      info = folder_list.get(i);
      if (info.getHierarchyIndex() == 0) {
        info.setAuthorizedVisible(true);
        continue;
      }
      if (!invisible_children.contains(i)) {
        /** 既に見えないフォルダの子フォルダとして処理されたフォルダについては、アクセス権限チェックをスキップする */
        info
          .setAuthorizedVisible(isReadableFolder(info.getFolderId(), rundata));
      }
      if (!info.isAuthorizedVisible()) {
        /** 子フォルダも見えないようにする */
        for (int j = 0; j < size; j++) {
          ExtFolderInfo info1 = folder_list.get(j);
          if (info1.getParentFolderId() == info.getFolderId()) {
            invisible_children.add(j);
            info1.setAuthorizedVisible(false);
          }
        }
      }
    }
  }

  public static String getFolderPosition(List<ExtFolderInfo> folder_list,
      int folder_id) {
    String sepa = "<b> &gt; </b>";
    StringBuffer folderpath = new StringBuffer();
    ExtFolderInfo info = null;
    int parent_id = -1;
    int size = folder_list.size() - 1;
    for (int i = size; i >= 0; i--) {
      info = 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 ExtFolderInfo getSelectedFolderInfo(List<ExtFolderInfo> list,
      int folder_id) {
    ExtFolderInfo selected_folderinfo = null;
    int size = list.size();
    for (int i = 0; i < size; i++) {
      ExtFolderInfo info = 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_CABINET, 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_CABINET, 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 isFolderCreatableFolder(int folder_id, RunData rundata) {

    // if (folder_id == ExtCabinetUtils.ROOT_FODLER_ID) {
    // return true;
    // }
    AvzTCabinetFolder folder = ExtCabinetUtils.getFolderByPK(folder_id);
    int user_id = folder.getCreateUserId();
    List<String> aclHandle =
      ExtCabinetUtils.getFolderAclHandle(rundata, folder_id, user_id);
    return ExtCabinetUtils.isFolderCreatable(aclHandle);
  }

  /**
   * 現在ログインしているユーザーは指定したIDのフォルダにファイルを作成する権限を持つかを返します
   * 
   * @param folder_id
   * @param rundata
   * @return
   */
  public static boolean isFileCreatableFolder(int folder_id, RunData rundata) {

    // if (folder_id == ExtCabinetUtils.ROOT_FODLER_ID) {
    // return true;
    // }
    AvzTCabinetFolder folder = ExtCabinetUtils.getFolderByPK(folder_id);
    int user_id = folder.getCreateUserId();
    List<String> aclHandle =
      ExtCabinetUtils.getFolderAclHandle(rundata, folder_id, user_id);
    return ExtCabinetUtils.isFileCreatable(aclHandle);
  }

  /**
   * 現在ログインしているユーザーは指定したIDのフォルダを参照する権限を持つかを返します
   * 
   * @param folder_id
   * @param rundata
   * @return
   */
  public static boolean isReadableFolder(int folder_id, RunData rundata) {

    // if (folder_id == ExtCabinetUtils.ROOT_FODLER_ID) {
    // return true;
    // }
    AvzTCabinetFolder folder = ExtCabinetUtils.getFolderByPK(folder_id);
    int user_id = folder.getCreateUserId();
    List<String> aclHandle =
      ExtCabinetUtils.getFolderAclHandle(rundata, folder_id, user_id);
    return ExtCabinetUtils.isReadable(aclHandle);
  }

  /**
   * 現在ログインしているユーザーは指定したIDのフォルダを削除する権限を持つかを返します
   * 
   * @param folder_id
   * @param rundata
   * @return
   */
  public static boolean isDeletableFolder(int folder_id, RunData rundata) {
    AvzTCabinetFolder folder = ExtCabinetUtils.getFolderByPK(folder_id);
    int user_id = folder.getCreateUserId();
    List<String> aclHandle =
      ExtCabinetUtils.getFolderAclHandle(rundata, folder_id, user_id);
    return ExtCabinetUtils.isDeletable(aclHandle);
  }

  /**
   * 現在ログインしているユーザーは指定したIDのファイルを削除する権限を持つかを返します
   * 
   * @param folder_id
   * @param rundata
   * @return
   */

  public static boolean isDeletableFile(int file_id, RunData rundata) {
    AvzTCabinetFile file = ExtCabinetUtils.getFileByPK(file_id);
    int user_id = file.getCreateUserId();
    List<String> aclHandle =
      ExtCabinetUtils.getFileAclHandle(rundata, file_id, user_id);
    return ExtCabinetUtils.isDeletable(aclHandle);
  }

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

      }
      if (!info.isAuthorizedVisible()) {
        /** 不可視に設定したフォルダの子フォルダも見えないようにする */
        for (int j = 0; j < size; j++) {
          ExtFolderInfo info1 = folder_list.get(j);
          if (info1.getParentFolderId() == info.getFolderId()) {
            invisible_children.add(j);
            info1.setAuthorizedVisible(false);
          }
        }
      }
    }
  }

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

  public static List<AvzTCabinetFolder> getChildFolders(AvzTCabinetFolder folder) {
    List<AvzTCabinetFolder> list = new ArrayList<AvzTCabinetFolder>();
    List<AvzTCabinetFolder> children =
      ExtCabinetUtils.getChildren(folder.getFolderId());
    List<AvzTCabinetFolder> children_tmp = new ArrayList<AvzTCabinetFolder>();
    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(ExtCabinetUtils.getChildren((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 ResultList<AvzTCabinetFolder> getChildren(int parent_id) {

    SelectQuery<AvzTCabinetFolder> query =
      Database.query(AvzTCabinetFolder.class);
    Expression pk_exp =
      ExpressionFactory.matchExp(
        _AvzTCabinetFolder.PARENT_ID_PROPERTY,
        parent_id);
    query.setQualifier(pk_exp);
    ResultList<AvzTCabinetFolder> list = query.getResultList();
    return list;
  }

  public static AvzTCabinetFolder getFolderByPK(Integer folder_id) {

    SelectQuery<AvzTCabinetFolder> query =
      Database.query(AvzTCabinetFolder.class);
    Expression pk_exp =
      ExpressionFactory.matchDbExp(
        _AvzTCabinetFolder.FOLDER_ID_PK_COLUMN,
        folder_id);
    query.setQualifier(pk_exp);
    ResultList<AvzTCabinetFolder> list = query.getResultList();
    if (list == null || list.size() == 0) {
      return null;
    }
    AvzTCabinetFolder folder = list.get(0);
    return folder;
  }

  public static AvzTCabinetFile getFileByPK(Integer file_id) {

    SelectQuery<AvzTCabinetFile> query = Database.query(AvzTCabinetFile.class);
    Expression pk_exp =
      ExpressionFactory.matchDbExp(_AvzTCabinetFile.FILE_ID_PK_COLUMN, file_id);
    query.setQualifier(pk_exp);
    ResultList<AvzTCabinetFile> list = query.getResultList();
    AvzTCabinetFile folder = list.get(0);
    return folder;
  }

  /**
   * グループネーム（"1204101769781_1"など）からグループのエイリアス名（"商品開発部"など）を取得する
   * 
   * @param name
   *            グループネーム
   * @return エイリアスネーム
   */
  public static String getAriasNameByGroupName(String name) {
    String rtn = "";
    try {

      SelectQuery<TurbineGroup> query = Database.query(TurbineGroup.class);
      Expression exp =
        ExpressionFactory.matchDbExp(TurbineGroup.GROUP_NAME_COLUMN, name);
      query.andQualifier(exp);
      ResultList<TurbineGroup> list = query.getResultList();
      TurbineGroup tGroup = list.get(0);
      rtn = tGroup.getGroupAliasName();
    } catch (Exception ex) {
      ex.printStackTrace();
      logger.error("[convertName2Id]", ex);
    }
    return rtn;
  }

  /**
   * フォルダーの権限レコード情報を取得します。 優先順位は、ユーザー → グループ → 全員 となります。
   * 
   * @param folder_id
   * @param user_id
   * @return
   */
  public static ResultList<AvzTFolderAcl> getAvzTFolderAcl(int folder_id,
      int user_id) {

    // アクセス制御
    SelectQuery<AvzTFolderAcl> query = Database.query(AvzTFolderAcl.class);

    Expression exp01 =
      ExpressionFactory.matchExp(_AvzTFolderAcl.FOLDER_ID_PROPERTY, folder_id);
    query.setQualifier(exp01);

    Expression exp02 =
      ExpressionFactory.matchExp(
        _AvzTFolderAcl.TARGET_TYPE_PROPERTY,
        AUTHORITY_LEVEL_USER);
    query.andQualifier(exp02);

    Expression exp03 =
      ExpressionFactory.matchExp(_AvzTFolderAcl.TARGET_ID_PROPERTY, user_id);
    query.andQualifier(exp03);

    ResultList<AvzTFolderAcl> acls = query.getResultList();

    if (acls.size() == 0) {
      // 個人レベルの権限レコードが無い場合は、"グループ"レベルの権限レコードを探す。

      // ログインユーザーが所属するグループのGroupNameを取得します。
      List<String> groupNames = getBelongedGroups(user_id);
      if (groupNames.size() > 0) {
        SelectQuery<AvzTFolderAcl> query2 = Database.query(AvzTFolderAcl.class);

        Expression exp11 =
          ExpressionFactory.matchExp(
            _AvzTFolderAcl.FOLDER_ID_PROPERTY,
            folder_id);
        query2.setQualifier(exp11);

        Expression exp12 =
          ExpressionFactory.matchExp(
            _AvzTFolderAcl.TARGET_TYPE_PROPERTY,
            AUTHORITY_LEVEL_GROUP);
        query2.andQualifier(exp12);

        Expression exp13 =
          ExpressionFactory
            .inExp(_AvzTFolderAcl.TARGET_ID_PROPERTY, groupNames);
        query2.andQualifier(exp13);

        acls = query2.getResultList();
      }
      if (acls.size() == 0) {
        // それでも権限レコードが無い場合は、"全員"レベルの権限レコードを探す。
        SelectQuery<AvzTFolderAcl> query3 = Database.query(AvzTFolderAcl.class);

        Expression exp21 =
          ExpressionFactory.matchExp(
            _AvzTFolderAcl.FOLDER_ID_PROPERTY,
            folder_id);
        query3.setQualifier(exp21);

        Expression exp22 =
          ExpressionFactory.matchExp(
            _AvzTFolderAcl.TARGET_TYPE_PROPERTY,
            AUTHORITY_LEVEL_EVERYONE);
        query3.andQualifier(exp22);

        acls = query3.getResultList();
      }
    }

    return acls;
  }

  /**
   * ファイルの権限レコード情報を取得します。 優先順位は、ユーザー → グループ → 全員 となります。
   * 
   * @param folder_id
   * @param user_id
   * @return
   */
  public static List<AvzTFileAcl> getAvzTFileAcl(int file_id, int user_id) {

    // アクセス制御
    SelectQuery<AvzTFileAcl> query = Database.query(AvzTFileAcl.class);

    Expression exp01 =
      ExpressionFactory.matchExp(_AvzTFileAcl.FILE_ID_PROPERTY, file_id);
    query.setQualifier(exp01);

    Expression exp02 =
      ExpressionFactory.matchExp(
        _AvzTFileAcl.TARGET_TYPE_PROPERTY,
        AUTHORITY_LEVEL_USER);
    query.andQualifier(exp02);

    Expression exp03 =
      ExpressionFactory.matchExp(_AvzTFileAcl.TARGET_ID_PROPERTY, user_id);
    query.andQualifier(exp03);

    ResultList<AvzTFileAcl> acls = query.getResultList();

    if (acls.size() == 0) {
      // 個人レベルの権限レコードが無い場合は、"グループ"レベルの権限レコードを探す。

      // ログインユーザーが所属するグループのGroupNameを取得します。
      List<String> groupNames = getBelongedGroups(user_id);
      if (groupNames.size() > 0) {
        SelectQuery<AvzTFileAcl> query2 = Database.query(AvzTFileAcl.class);

        Expression exp11 =
          ExpressionFactory.matchExp(_AvzTFileAcl.FILE_ID_PROPERTY, file_id);
        query2.setQualifier(exp11);

        Expression exp12 =
          ExpressionFactory.matchExp(
            _AvzTFileAcl.TARGET_TYPE_PROPERTY,
            AUTHORITY_LEVEL_GROUP);
        query2.andQualifier(exp12);

        Expression exp13 =
          ExpressionFactory.inExp(_AvzTFileAcl.TARGET_ID_PROPERTY, groupNames);
        query2.andQualifier(exp13);

        // 一人のメンバーが、複数のグループで権限設定されていて権限に矛盾がある場合は、
        // "GRANT"を優先させます。
        acls = query2.getResultList();
      }
      if (acls.size() == 0) {
        // それでも権限レコードが無い場合は、"全員"レベルの権限レコードを探す。
        SelectQuery<AvzTFileAcl> query3 = Database.query(AvzTFileAcl.class);

        Expression exp21 =
          ExpressionFactory.matchExp(_AvzTFileAcl.FILE_ID_PROPERTY, file_id);
        query3.setQualifier(exp21);

        Expression exp22 =
          ExpressionFactory.matchExp(
            _AvzTFileAcl.TARGET_TYPE_PROPERTY,
            AUTHORITY_LEVEL_EVERYONE);
        query3.andQualifier(exp22);

        acls = query3.getResultList();
      }
    }

    return acls;
  }

  public static List<String> getFolderAclHandle(RunData rundata, int folder_id,
      int owner_id) {
    List<String> list = new ArrayList<String>();
    int current_user_id = ALEipUtils.getUserId(rundata);
    try {
      // if (current_user_id == owner_id || folder_id == ROOT_FODLER_ID) {
      if (current_user_id == owner_id) {
        // 自分が登録したフォルダとルートフォルダは無条件にフルアクセス可能です。
        list.add(AUTHORITY_F);
        list.add(AUTHORITY_C);
        list.add(AUTHORITY_R);
        list.add(AUTHORITY_U);
        list.add(AUTHORITY_D);
      } else {
        List<AvzTFolderAcl> acls = getAvzTFolderAcl(folder_id, current_user_id);
        int size = acls.size();
        for (int i = 0; i < size; i++) {
          AvzTFolderAcl record = acls.get(i);

          if (!AUTHORITY_GRANT.equals(record.getGrantFlg())) {
            continue;
          }

          if (DB_PROPERTY_F.equals(record.getAclType())) {
            list.add(AUTHORITY_F);
          } else if (DB_PROPERTY_C.equals(record.getAclType())) {
            list.add(AUTHORITY_C);
          } else if (DB_PROPERTY_R.equals(record.getAclType())) {
            list.add(AUTHORITY_R);
          } else if (DB_PROPERTY_U.equals(record.getAclType())) {
            list.add(AUTHORITY_U);
          } else if (DB_PROPERTY_D.equals(record.getAclType())) {
            list.add(AUTHORITY_D);
          }
        }
      }

      if (folder_id == ROOT_FODLER_ID && list.size() == 0) {
        // ルートフォルダの権限設定が全くされていなくても、最低限参照だけは出来るようにします
        list.add(AUTHORITY_R);
      }

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

  public static List<String> getFileAclHandle(RunData rundata, int file_id,
      int owner_id) {
    List<String> list = new ArrayList<String>();
    int current_user_id = ALEipUtils.getUserId(rundata);
    try {
      if (current_user_id == owner_id) {
        // 自分が登録したファイルは無条件にフルアクセス可能です。
        list.add(AUTHORITY_C);
        list.add(AUTHORITY_R);
        list.add(AUTHORITY_U);
        list.add(AUTHORITY_D);
      } else {
        List<AvzTFileAcl> acls = getAvzTFileAcl(file_id, current_user_id);
        int size = acls.size();
        for (int i = 0; i < size; i++) {
          AvzTFileAcl record = acls.get(i);

          if (!AUTHORITY_GRANT.equals(record.getGrantFlg())) {
            continue;
          }

          if (DB_PROPERTY_C.equals(record.getAclType())) {
            list.add(AUTHORITY_C);
          } else if (DB_PROPERTY_R.equals(record.getAclType())) {
            list.add(AUTHORITY_R);
          } else if (DB_PROPERTY_U.equals(record.getAclType())) {
            list.add(AUTHORITY_U);
          } else if (DB_PROPERTY_D.equals(record.getAclType())) {
            list.add(AUTHORITY_D);
          }
        }
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    return list;
  }

  public static List<ExtCabinetAclResultData> loadFolderAclList(long folder_id) {
    // 権限一覧
    List<ExtCabinetAclResultData> aclList =
      new ArrayList<ExtCabinetAclResultData>();
    try {
      // アクセス制御
      SelectQuery<AvzTFolderAcl> query = Database.query(AvzTFolderAcl.class);
      Expression exp =
        ExpressionFactory
          .matchExp(_AvzTFolderAcl.FOLDER_ID_PROPERTY, folder_id);
      query.setQualifier(exp);
      query.orderAscending(_AvzTFileAcl.TARGET_TYPE_PROPERTY);
      query.orderAscending(_AvzTFileAcl.TARGET_ID_PROPERTY);
      ResultList<AvzTFolderAcl> acls = query.getResultList();

      int size = acls.size();
      AvzTFolderAcl previous = null;
      ExtCabinetAclResultData rd = null;
      for (int i = 0; i < size; i++) {
        AvzTFolderAcl record = acls.get(i);
        if (previous == null
          || (!record.getTargetType().equals(previous.getTargetType()) || !record
            .getTargetId()
            .equals(previous.getTargetId()))) {

          if (rd != null) {
            aclList.add(rd);
          }

          rd = new ExtCabinetAclResultData();
          rd.initField();
          rd.setId(folder_id);
          rd.setTargetId(record.getTargetId());
          rd.setTargetType(record.getTargetType());
          if (AUTHORITY_LEVEL_USER.equals(rd.getTargetType().getValue())) {
            rd.setTargetName(ALEipUtils.getUserFullName(Integer.parseInt(rd
              .getTargetId()
              .getValue())));
          } else if (AUTHORITY_LEVEL_EVERYONE.equals(rd
            .getTargetType()
            .getValue())) {
            rd.setTargetName(ALL_USER);
          } else if (AUTHORITY_LEVEL_GROUP
            .equals(rd.getTargetType().getValue())) {
            rd.setTargetName(getAriasNameByGroupName(rd
              .getTargetId()
              .getValue()));
          }
        }
        if (DB_PROPERTY_F.equals(record.getAclType())) {
          rd.setFileCreatable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_C.equals(record.getAclType())) {
          rd.setFolderCreatable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_R.equals(record.getAclType())) {
          rd.setReadable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_U.equals(record.getAclType())) {
          rd.setWritable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_D.equals(record.getAclType())) {
          rd.setDeletable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        previous = record;
      }
      if (rd != null) {
        aclList.add(rd);
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    return aclList;
  }

  public static List<ExtCabinetAclResultData> loadFileAclList(long file_id) {
    // 権限一覧
    List<ExtCabinetAclResultData> aclList =
      new ArrayList<ExtCabinetAclResultData>();
    try {
      // アクセス制御
      SelectQuery<AvzTFileAcl> query = Database.query(AvzTFileAcl.class);
      Expression exp =
        ExpressionFactory.matchExp(_AvzTFileAcl.FILE_ID_PROPERTY, file_id);
      query.setQualifier(exp);
      query.orderAscending(_AvzTFileAcl.TARGET_TYPE_PROPERTY);
      query.orderAscending(_AvzTFileAcl.TARGET_ID_PROPERTY);
      ResultList<AvzTFileAcl> acls = query.getResultList();

      int size = acls.size();
      AvzTFileAcl previous = null;
      ExtCabinetAclResultData rd = null;
      for (int i = 0; i < size; i++) {
        AvzTFileAcl record = acls.get(i);
        if (previous == null
          || (!record.getTargetType().equals(previous.getTargetType()) || !record
            .getTargetId()
            .equals(previous.getTargetId()))) {

          if (rd != null) {
            aclList.add(rd);
          }

          rd = new ExtCabinetAclResultData();
          rd.initField();
          rd.setId(file_id);
          rd.setTargetId(record.getTargetId());
          rd.setTargetType(record.getTargetType());
          if (AUTHORITY_LEVEL_USER.equals(rd.getTargetType().getValue())) {
            rd.setTargetName(ALEipUtils.getUserFullName(Integer.parseInt(rd
              .getTargetId()
              .getValue())));
          } else if (AUTHORITY_LEVEL_EVERYONE.equals(rd
            .getTargetType()
            .getValue())) {
            rd.setTargetName(ALL_USER);
          } else if (AUTHORITY_LEVEL_GROUP
            .equals(rd.getTargetType().getValue())) {
            rd.setTargetName(getAriasNameByGroupName(rd
              .getTargetId()
              .getValue()));
          }
        }
        if (DB_PROPERTY_R.equals(record.getAclType())) {
          rd.setReadable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_U.equals(record.getAclType())) {
          rd.setWritable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        if (DB_PROPERTY_D.equals(record.getAclType())) {
          rd.setDeletable(AUTHORITY_GRANT.equals(record.getGrantFlg()));
        }
        previous = record;
      }
      if (rd != null) {
        aclList.add(rd);
      }
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    return aclList;
  }

  public static void insertFileAcl(AvzTCabinetFile file,
      List<Map<String, String>> aclRequestList) {

    Date nowDate = Calendar.getInstance().getTime();
    for (Map<String, String> map : aclRequestList) {

      String target_id = map.get(AUTHORITY_TARGET_ID);
      String target_type = map.get(AUTHORITY_TARGET_TYPE);

      // 権限設定についてはループ処理を行なうため、以下の２つの要素は余計なので削除
      map.remove(AUTHORITY_TARGET_ID);
      map.remove(AUTHORITY_TARGET_TYPE);

      for (Iterator<Entry<String, String>> it = map.entrySet().iterator(); it
        .hasNext();) {

        Map.Entry<String, String> entry = it.next();
        String key = entry.getKey();
        String value = entry.getValue();

        AvzTFileAcl acl = Database.create(AvzTFileAcl.class);

        acl.setTargetId(target_id);
        acl.setTargetType(target_type);
        acl.setToAvzTCabinetFile(file);

        String aclType = null;
        String grantFlg = null;
        if (AUTHORITY_R.equals(key)) {
          aclType = DB_PROPERTY_R;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_U.equals(key)) {
          aclType = DB_PROPERTY_U;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_D.equals(key)) {
          aclType = DB_PROPERTY_D;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        }
        acl.setAclType(aclType);
        acl.setGrantFlg(grantFlg);
        acl.setCreateDate(nowDate);
        acl.setUpdateDate(nowDate);
      }
    }
  }

  public static void insertFolderAcl(AvzTCabinetFolder folder,
      List<Map<String, String>> aclRequestList) {

    Date nowDate = Calendar.getInstance().getTime();
    for (Map<String, String> map : aclRequestList) {

      String target_id = map.get(AUTHORITY_TARGET_ID);
      String target_type = map.get(AUTHORITY_TARGET_TYPE);

      // 権限設定についてはループ処理を行なうため、以下の２つの要素は余計なので削除
      map.remove(AUTHORITY_TARGET_ID);
      map.remove(AUTHORITY_TARGET_TYPE);

      for (Iterator<Entry<String, String>> it = map.entrySet().iterator(); it
        .hasNext();) {

        Map.Entry<String, String> entry = it.next();
        String key = entry.getKey();
        String value = entry.getValue();

        AvzTFolderAcl acl = Database.create(AvzTFolderAcl.class);

        acl.setTargetId(target_id);
        acl.setTargetType(target_type);
        acl.setToAvzTCabinetFolder(folder);

        String aclType = null;
        String grantFlg = null;
        if (AUTHORITY_F.equals(key)) {
          aclType = DB_PROPERTY_F;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_C.equals(key)) {
          aclType = DB_PROPERTY_C;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_R.equals(key)) {
          aclType = DB_PROPERTY_R;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_U.equals(key)) {
          aclType = DB_PROPERTY_U;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        } else if (AUTHORITY_D.equals(key)) {
          aclType = DB_PROPERTY_D;
          if (AUTHORITY_ON.equals(value)) {
            grantFlg = AUTHORITY_GRANT;
          } else {
            grantFlg = AUTHORITY_REVOKE;
          }
        }
        acl.setAclType(aclType);
        acl.setGrantFlg(grantFlg);
        acl.setCreateDate(nowDate);
        acl.setUpdateDate(nowDate);
      }
    }
  }

  public static boolean isFileCreatable(List<String> aclHandle) {
    if (aclHandle.contains(AUTHORITY_F)) {
      return true;
    }
    return false;
  }

  public static boolean isFolderCreatable(List<String> aclHandle) {
    if (aclHandle.contains(AUTHORITY_C)) {
      return true;
    }
    return false;
  }

  public static boolean isReadable(List<String> aclHandle) {
    if (aclHandle.contains(AUTHORITY_R)) {
      return true;
    }
    return false;
  }

  public static boolean isWritable(List<String> aclHandle) {
    if (aclHandle.contains(AUTHORITY_U)) {
      return true;
    }
    return false;
  }

  public static boolean isDeletable(List<String> aclHandle) {
    if (aclHandle.contains(AUTHORITY_D)) {
      return true;
    }
    return false;
  }

  /**
   * 自分(ユーザーID)が所属するグループネームのリストを取得します。
   * 
   * @param user_id
   *            ユーザーID
   * @return 所属する部署リスト
   */
  public static List<String> getBelongedGroups(int user_id) {
    SelectQuery<TurbineUserGroupRole> query =
      Database.query(TurbineUserGroupRole.class);
    Expression exp1 =
      ExpressionFactory.matchExp(
        _TurbineUserGroupRole.TURBINE_USER_PROPERTY,
        Integer.valueOf(user_id));
    Expression exp2 =
      ExpressionFactory.greaterExp(
        _TurbineUserGroupRole.TURBINE_GROUP_PROPERTY,
        Integer.valueOf(3));
    query.setQualifier(exp1);
    query.andQualifier(exp2);
    ResultList<TurbineUserGroupRole> list = query.getResultList();

    List<String> groupNames = new ArrayList<String>();
    TurbineUserGroupRole ugr = null;
    for (int j = 0; j < list.size(); j++) {
      ugr = list.get(j);
      // System.out.println("所属するMyGroupId:" +
      // ugr.getTurbineGroup().getGroupAliasName());
      groupNames.add(ugr.getTurbineGroup().getName());
    }

    return groupNames;
  }

  public static List<ExtCabinetAclResultData> excludeLoginUser(
      List<ExtCabinetAclResultData> aclList, long login_user_id) {
    List<ExtCabinetAclResultData> tmp =
      new ArrayList<ExtCabinetAclResultData>();
    for (ExtCabinetAclResultData d : aclList) {
      if (ExtCabinetUtils.AUTHORITY_LEVEL_USER.equals(d
        .getTargetType()
        .getValue())
        && login_user_id == Long
          .valueOf(d.getTargetId().getValue())
          .longValue()) {
        continue;
      }
      tmp.add(d);
    }
    return tmp;
  }

}