/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * Copyright (C) 2004-2011 Aimluck,Inc.
 * http://www.aipo.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.aimluck.eip.workflow.util;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.imageio.ImageIO;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.jetspeed.om.security.UserIdPrincipal;
import org.apache.jetspeed.services.JetspeedSecurity;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import org.apache.jetspeed.services.security.JetspeedSecurityException;
import org.apache.turbine.services.InstantiationException;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.commons.field.ALNumberField;
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.cayenne.om.security.TurbineUser;
import com.aimluck.eip.common.ALBaseUser;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALEipUser;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.fileupload.beans.FileuploadBean;
import com.aimluck.eip.fileupload.beans.FileuploadLiteBean;
import com.aimluck.eip.fileupload.util.FileuploadUtils;
import com.aimluck.eip.mail.ALAdminMailContext;
import com.aimluck.eip.mail.ALAdminMailMessage;
import com.aimluck.eip.mail.ALMailService;
import com.aimluck.eip.mail.util.ALEipUserAddr;
import com.aimluck.eip.mail.util.ALMailUtils;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SelectQuery;
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.services.orgutils.ALOrgUtilsService;
import com.aimluck.eip.services.social.ALActivityService;
import com.aimluck.eip.services.social.model.ALActivityPutRequest;
import com.aimluck.eip.services.storage.ALStorageService;
import com.aimluck.eip.user.beans.UserLiteBean;
import com.aimluck.eip.util.ALCellularUtils;
import com.aimluck.eip.util.ALCommonUtils;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.workflow.WorkflowCategoryResultData;
import com.aimluck.eip.workflow.WorkflowDecisionRecordData;
import com.aimluck.eip.workflow.WorkflowDetailResultData;
import com.aimluck.eip.workflow.WorkflowOldRequestResultData;
import com.aimluck.eip.workflow.WorkflowRouteResultData;
import com.aimluck.eip.workflow.beans.WorkflowMailBean;

/**
 * ワークフローのユーティリティクラスです。 <BR>
 * 
 */
public class WorkflowUtils {

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

  /** 申請 */
  public static final String DB_STATUS_REQUEST = "R";

  /** 確認中 */
  public static final String DB_STATUS_CONFIRM = "C";

  /** 確認前 */
  public static final String DB_STATUS_WAIT = "W";

  /** 承認 */
  public static final String DB_STATUS_ACCEPT = "A";

  /** 否認 */
  public static final String DB_STATUS_DENIAL = "D";

  /** 削除・無効化のため自動承認 */
  public static final String DB_STATUS_THROUGH = "T";

  /** すべて承認 */
  public static final String DB_PROGRESS_ACCEPT = "A";

  /** 確認中 */
  public static final String DB_PROGRESS_WAIT = "W";

  /** 申請者に差し戻し */
  public static final String DB_PROGRESS_DENAIL = "D";

  /** 再申請済み */
  public static final String DB_PROGRESS_REAPPLY = "R";

  /** データベースに登録されたファイルを表す識別子 */
  public static final String PREFIX_DBFILE = "DBF";

  /** デフォルトエンコーディングを表わすシステムプロパティのキー */
  public static final String FILE_ENCODING = JetspeedResources.getString(
    "content.defaultencoding",
    "UTF-8");

  /** ワークフローの添付ファイルを保管するディレクトリの指定 */
  private static final String FOLDER_FILEDIR_WORKFLOW = JetspeedResources
    .getString("aipo.filedir", "");

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

  public enum Type {
    REQUEST, DENAIL, ACCEPT
  }

  /**
   * Request オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param mode_update
   * @return
   */
  public static EipTWorkflowRequest getEipTWorkflowRequest(RunData rundata,
      Context context, boolean mode_update) throws ALPageNotFoundException {
    int uid = ALEipUtils.getUserId(rundata);
    String requestid =
      ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);
    try {
      if (requestid == null || Integer.valueOf(requestid) == null) {
        // Request IDが空の場合
        logger.debug("[WorkflowUtils] Empty ID...");
        return null;
      }

      // アクセス権の判定
      SelectQuery<EipTWorkflowRequestMap> query10 =
        Database.query(EipTWorkflowRequestMap.class);
      Expression exp10 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequestMap.EIP_TWORKFLOW_REQUEST_PROPERTY
            + "."
            + EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          Integer.valueOf(requestid));
      Expression exp11 =
        ExpressionFactory
          .matchExp(EipTWorkflowRequestMap.USER_ID_PROPERTY, uid);
      query10.setQualifier(exp10.andExp(exp11));
      List<EipTWorkflowRequestMap> maps = query10.fetchList();
      if (maps == null || maps.size() == 0) {
        // 指定したアカウントIDのレコードが見つからない場合
        logger.debug("[WorkFlow] Invalid user access...");
        throw new ALPageNotFoundException();
      }

      SelectQuery<EipTWorkflowRequest> query =
        Database.query(EipTWorkflowRequest.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          requestid);
      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(
          EipTWorkflowRequest.EIP_TWORKFLOW_REQUEST_MAP_PROPERTY
            + "."
            + EipTWorkflowRequestMap.USER_ID_PROPERTY,
          Integer.valueOf(ALEipUtils.getUserId(rundata)));
      query.andQualifier(exp2);

      if (mode_update) {
        Expression exp3 =
          ExpressionFactory.matchExp(
            EipTWorkflowRequest.EIP_TWORKFLOW_REQUEST_MAP_PROPERTY
              + "."
              + EipTWorkflowRequestMap.STATUS_PROPERTY,
            DB_STATUS_CONFIRM);
        query.andQualifier(exp3);

        Expression exp4 =
          ExpressionFactory.matchExp(
            EipTWorkflowRequest.PROGRESS_PROPERTY,
            DB_PROGRESS_WAIT);
        query.andQualifier(exp4);
      }

      List<EipTWorkflowRequest> requests = query.fetchList();

      if (requests == null || requests.size() == 0) {
        // 指定した Request IDのレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        return null;
      }

      return requests.get(0);
    } catch (ALPageNotFoundException pageNotFound) {
      logger.error(pageNotFound);
      throw pageNotFound;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * Request オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param mode_update
   * @return
   */
  public static EipTWorkflowRequest getEipTWorkflowRequestAll(RunData rundata,
      Context context) {
    String requestid =
      ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);

    try {
      if (requestid == null || Integer.valueOf(requestid) == null) {
        // Request IDが空の場合
        logger.debug("[WorkflowUtils] Empty ID...");
        return null;
      }

      SelectQuery<EipTWorkflowRequest> query =
        Database.query(EipTWorkflowRequest.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          requestid);
      query.setQualifier(exp1);

      List<EipTWorkflowRequest> requests = query.fetchList();
      if (requests == null || requests.size() == 0) {
        // 指定した Request IDのレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        return null;
      }
      return requests.get(0);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

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

      SelectQuery<EipTWorkflowRequest> query =
        Database.query(EipTWorkflowRequest.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          requestid);
      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(
          EipTWorkflowRequest.USER_ID_PROPERTY,
          Integer.valueOf(ALEipUtils.getUserId(rundata)));
      query.andQualifier(exp2);

      List<EipTWorkflowRequest> requests = query.fetchList();

      if (requests == null || requests.size() == 0) {
        // 指定した Request IDのレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        return null;
      }
      return requests.get(0);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ファイルオブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static EipTWorkflowFile getEipTWorkflowFile(RunData rundata)
      throws ALPageNotFoundException, ALDBErrorException {
    try {
      int attachmentIndex =
        rundata.getParameters().getInt("attachmentIndex", -1);
      if (attachmentIndex < 0) {
        // ID が空の場合
        logger.debug("[WorkflowUtils] Empty ID...");
        throw new ALPageNotFoundException();

      }

      SelectQuery<EipTWorkflowFile> query =
        Database.query(EipTWorkflowFile.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          EipTWorkflowFile.FILE_ID_PK_COLUMN,
          Integer.valueOf(attachmentIndex));
      query.andQualifier(exp);
      List<EipTWorkflowFile> files = query.fetchList();
      if (files == null || files.size() == 0) {
        // 指定した ID のレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        throw new ALPageNotFoundException();
      }
      return files.get(0);
    } catch (Exception ex) {
      logger.error("[WorkflowUtils]", ex);
      throw new ALDBErrorException();
    }
  }

  public static List<EipTWorkflowRequestMap> getEipTWorkflowRequestMap(
      EipTWorkflowRequest request) {
    try {
      SelectQuery<EipTWorkflowRequestMap> query =
        Database.query(EipTWorkflowRequestMap.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequestMap.EIP_TWORKFLOW_REQUEST_PROPERTY
            + "."
            + EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          request.getRequestId());
      query.setQualifier(exp);
      query.orderAscending(EipTWorkflowRequestMap.ORDER_INDEX_PROPERTY);

      List<EipTWorkflowRequestMap> maps = query.fetchList();

      if (maps == null || maps.size() == 0) {
        // 指定した Request IDのレコードが見つからない場合
        logger.debug("[WorkflowSelectData] Not found ID...");
        return null;
      }
      return maps;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ワークフローカテゴリ オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param mode_update
   * @return
   */
  public static EipTWorkflowCategory getEipTWorkflowCategory(RunData rundata,
      Context context) {
    String categoryid =
      ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);
    try {
      if (categoryid == null || Integer.valueOf(categoryid) == null) {
        // Request IDが空の場合
        logger.debug("[WorkflowUtils] Empty ID...");
        return null;
      }

      SelectQuery<EipTWorkflowCategory> query =
        Database.query(EipTWorkflowCategory.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowCategory.CATEGORY_ID_PK_COLUMN,
          categoryid);
      query.setQualifier(exp1);

      List<EipTWorkflowCategory> categories = query.fetchList();

      if (categories == null || categories.size() == 0) {
        // 指定したカテゴリIDのレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        return null;
      }
      return categories.get(0);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ワークフローカテゴリ オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static EipTWorkflowCategory getEipTWorkflowCategory(Long category_id) {
    try {
      EipTWorkflowCategory category =
        Database.get(EipTWorkflowCategory.class, category_id);

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

  /**
   * カテゴリの一覧を取得する。
   * 
   * @param rundata
   * @param context
   */
  public static List<WorkflowCategoryResultData> loadCategoryList(
      RunData rundata, Context context) {
    try {
      // カテゴリ一覧
      List<WorkflowCategoryResultData> categoryList =
        new ArrayList<WorkflowCategoryResultData>();

      SelectQuery<EipTWorkflowCategory> query =
        Database.query(EipTWorkflowCategory.class);
      List<EipTWorkflowCategory> aList = query.fetchList();

      for (EipTWorkflowCategory record : aList) {
        WorkflowCategoryResultData rd = new WorkflowCategoryResultData();
        rd.initField();
        rd.setCategoryId(record.getCategoryId().longValue());
        rd.setCategoryName(record.getCategoryName());
        rd.setOrderTemplate(record.getTemplate());
        categoryList.add(rd);
      }

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

  /**
   * ワークフロー申請経路 オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param mode_update
   * @return
   */
  public static EipTWorkflowRoute getEipTWorkflowRoute(RunData rundata,
      Context context) {
    String routeid =
      ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);
    try {
      if (routeid == null || Integer.valueOf(routeid) == null) {
        // Request IDが空の場合
        logger.debug("[WorkflowUtils] Empty ID...");
        return null;
      }

      SelectQuery<EipTWorkflowRoute> query =
        Database.query(EipTWorkflowRoute.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRoute.ROUTE_ID_PK_COLUMN,
          routeid);
      query.setQualifier(exp1);

      List<EipTWorkflowRoute> routes = query.fetchList();

      if (routes == null || routes.size() == 0) {
        // 指定したカテゴリIDのレコードが見つからない場合
        logger.debug("[WorkflowUtils] Not found ID...");
        return null;
      }
      return routes.get(0);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * ワークフロー申請経路 オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static EipTWorkflowRoute getEipTWorkflowRoute(Long route_id) {
    try {
      EipTWorkflowRoute route = Database.get(EipTWorkflowRoute.class, route_id);

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

  /**
   * 申請経路の一覧を取得する。
   * 
   * @param rundata
   * @param context
   */
  public static List<WorkflowRouteResultData> loadRouteList(RunData rundata,
      Context context) {
    try {
      // 申請経路一覧
      List<WorkflowRouteResultData> routeList =
        new ArrayList<WorkflowRouteResultData>();

      SelectQuery<EipTWorkflowRoute> query =
        Database.query(EipTWorkflowRoute.class);
      query.orderAscending(EipTWorkflowRoute.ROUTE_NAME_PROPERTY);
      List<EipTWorkflowRoute> aList = query.fetchList();

      for (EipTWorkflowRoute record : aList) {
        WorkflowRouteResultData rd = new WorkflowRouteResultData();
        rd.initField();
        rd.setRouteId(record.getRouteId().longValue());
        rd.setRouteName(record.getRouteName());
        rd.setRoute(record.getRoute());
        routeList.add(rd);
      }

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

  /**
   * 依頼の詳細情報を取得する。
   * 
   * @param rundata
   * @param context
   */
  public static Object getResultDataDetail(Object obj, ALEipUser login_user) {
    try {
      EipTWorkflowRequest record = (EipTWorkflowRequest) obj;
      WorkflowDetailResultData rd = new WorkflowDetailResultData();
      rd.initField();
      rd.setUserId(record.getUserId().longValue());
      rd.setRequestName(record.getRequestName());
      rd.setRequestId(record.getRequestId().longValue());
      rd.setCategoryId(record
        .getEipTWorkflowCategory()
        .getCategoryId()
        .longValue());
      rd.setCategoryName(record.getEipTWorkflowCategory().getCategoryName());
      rd.setPriorityString(WorkflowUtils.getPriorityString(record
        .getPriority()
        .intValue()));
      rd.setNote(record.getNote());
      rd.setPrice(record.getPrice().longValue());
      rd.setProgress(record.getProgress());
      rd.setCanRemandApplicant(true);
      if (record.getEipTWorkflowRoute() != null) {
        rd.setRouteName(record.getEipTWorkflowRoute().getRouteName());
      }

      List<WorkflowDecisionRecordData> drList =
        new ArrayList<WorkflowDecisionRecordData>();
      List<WorkflowDecisionRecordData> remandList =
        new ArrayList<WorkflowDecisionRecordData>();
      ALEipUser user = null;
      EipTWorkflowRequestMap map = null;
      WorkflowDecisionRecordData drd = null;
      List<EipTWorkflowRequestMap> maps =
        WorkflowUtils.getEipTWorkflowRequestMap(record);
      int size = maps.size();
      boolean is_past = true;
      for (int i = 0; i < size; i++) {
        map = maps.get(i);
        drd = new WorkflowDecisionRecordData();
        drd.initField();

        // ログインユーザより後なら差し戻し先として選ばない
        if (login_user.getUserId().getValue() == map.getUserId().longValue()) {
          is_past = false;
        }

        user = ALEipUtils.getALEipUser(map.getUserId().intValue());
        drd.setUserId(map.getUserId().intValue());
        drd.setUserAliasName(user.getAliasName().getValue());
        drd.setStatus(map.getStatus());
        drd.setStatusString(WorkflowUtils.getStatusString(map.getStatus()));
        drd.setOrder(map.getOrderIndex().intValue());
        drd.setNote(map.getNote());
        drd.setUpdateDate(WorkflowUtils.translateDate(
          map.getUpdateDate(),
          "yyyy年M月d日H時m分"));
        drList.add(drd);

        // 無効化、もしくは削除されているユーザーは差し戻し先として選べないようにする
        if (is_past && !isDisabledOrDeleted(map.getUserId().toString())) {
          remandList.add(drd);
        } else {
          // 申請者に差し戻し不可能
          if (i == 0) {
            rd.setCanRemandApplicant(false);
          }
        }
      }
      rd.setDecisionRecords(drList);
      rd.setRemandingRecords(remandList);

      // 過去の申請内容
      if (record.getParentId().intValue() != 0) {
        List<EipTWorkflowRequest> oldReuqests = getOldRequests(record);
        if (oldReuqests != null && oldReuqests.size() > 0) {
          List<WorkflowOldRequestResultData> oldList =
            new ArrayList<WorkflowOldRequestResultData>();
          int osize = oldReuqests.size();
          for (int i = 0; i < osize; i++) {
            EipTWorkflowRequest request = oldReuqests.get(i);
            WorkflowOldRequestResultData orrd =
              new WorkflowOldRequestResultData();
            orrd.initField();
            orrd.setRequestId(request.getRequestId().intValue());
            orrd.setRequestName(request.getRequestName());
            orrd.setCategoryName(request
              .getEipTWorkflowCategory()
              .getCategoryName());
            orrd.setUpdateDate(WorkflowUtils.translateDate(request
              .getUpdateDate(), "yyyy年M月d日H時m分"));
            oldList.add(orrd);
          }
          rd.setOldRequestLinks(oldList);
        }
      }

      // ファイルリスト
      List<EipTWorkflowFile> list =
        getSelectQueryForFiles(record.getRequestId().intValue()).fetchList();
      if (list != null && list.size() > 0) {
        List<FileuploadBean> attachmentFileList =
          new ArrayList<FileuploadBean>();
        FileuploadBean filebean = null;
        for (EipTWorkflowFile file : list) {
          String realname = file.getFileName();
          javax.activation.DataHandler hData =
            new javax.activation.DataHandler(
              new javax.activation.FileDataSource(realname));

          filebean = new FileuploadBean();
          filebean.setFileId(file.getFileId().intValue());
          filebean.setFileName(realname);
          if (hData != null) {
            filebean.setContentType(hData.getContentType());
          }
          filebean.setIsImage(FileuploadUtils.isImage(realname));
          attachmentFileList.add(filebean);
        }
        rd.setAttachmentFiles(attachmentFileList);
      }

      rd.setCreateDate(WorkflowUtils.translateDate(
        record.getCreateDate(),
        "yyyy年M月d日H時m分"));
      rd.setUpdateDate(WorkflowUtils.translateDate(
        record.getUpdateDate(),
        "yyyy年M月d日H時m分"));
      return rd;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  private static List<EipTWorkflowRequest> getOldRequests(
      EipTWorkflowRequest request) {
    try {
      SelectQuery<EipTWorkflowRequest> query =
        Database.query(EipTWorkflowRequest.class);
      Expression exp11 =
        ExpressionFactory.matchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          request.getParentId());
      Expression exp12 =
        ExpressionFactory.matchExp(
          EipTWorkflowRequest.PARENT_ID_PROPERTY,
          request.getParentId());
      query.setQualifier(exp11.orExp(exp12));
      Expression exp2 =
        ExpressionFactory.noMatchDbExp(
          EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
          request.getRequestId());
      query.andQualifier(exp2);

      query.orderAscending(EipTWorkflowRequest.UPDATE_DATE_PROPERTY);

      List<EipTWorkflowRequest> requests = query.fetchList();

      if (requests == null || requests.size() == 0) {
        // 指定した Request IDのレコードが見つからない場合
        logger.debug("[WorkflowSelectData] Not found ID...");
        return null;
      }
      return requests;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * 重要度を表す画像名を取得します。 <BR>
   * 1 : 高い : priority_high.gif <BR>
   * 2 : やや高い : priority_middle_high.gif <BR>
   * 3 : 普通 : priority_middle.gif <BR>
   * 4 : やや低い : priority_middle_low.gif <BR>
   * 5 : 低い : priority_low.gif <BR>
   * 
   * @param i
   * @return
   */
  public static String getPriorityImage(int i) {
    String[] temp =
      {
        "priority_high.gif",
        "priority_middle_high.gif",
        "priority_middle.gif",
        "priority_middle_low.gif",
        "priority_low.gif" };
    String image = null;
    try {
      image = temp[i - 1];
    } catch (Exception ex) {
      // logger.error("Exeption", ex);
    }
    return image;
  }

  /**
   * 重要度を表す文字列を取得します。 <BR>
   * 1 : 高い : priority_high.gif <BR>
   * 2 : やや高い : priority_middle_high.gif <BR>
   * 3 : 普通 : priority_middle.gif <BR>
   * 4 : やや低い : priority_middle_low.gif <BR>
   * 5 : 低い : priority_low.gif <BR>
   * 
   * @param i
   * @return
   */
  public static String getPriorityString(int i) {
    String[] temp = { "高い", "やや高い", "普通", "やや低い", "低い" };
    String string = null;
    try {
      string = temp[i - 1];
    } catch (Exception ex) {
      // logger.error("Exeption", ex);
    }
    return string;
  }

  /**
   * 状態を表す画像名を取得します。 <BR>
   * 0 : 未着手 <BR>
   * 10 : 10% <BR>
   * 20 : 20% <BR>
   * : :<BR>
   * 90 : 90% <BR>
   * 100 : 完了 <BR>
   * 
   * @param i
   * @return
   */
  public static String getStateImage(int i) {
    String[] temp =
      {
        "state_000.gif",
        "state_010.gif",
        "state_020.gif",
        "state_030.gif",
        "state_040.gif",
        "state_050.gif",
        "state_060.gif",
        "state_070.gif",
        "state_080.gif",
        "state_090.gif",
        "state_100.gif" };
    String image = null;
    try {
      image = temp[i / 10];
    } catch (Exception ex) {
      // logger.error("Exeption", ex);
    }
    return image;
  }

  /**
   * 状態を表す文字列を取得します。 <BR>
   * 0 : 未着手 <BR>
   * 10 : 10% <BR>
   * 20 : 20% <BR>
   * : :<BR>
   * 90 : 90% <BR>
   * 100 : 完了 <BR>
   * 
   * @param i
   * @return
   */
  public static String getStateString(int i) {
    if (i == 0) {
      return "未着手";
    } else if (i == 100) {
      return "完了";
    } else {
      return new StringBuffer().append(i).append("%").toString();
    }
  }

  /**
   * 
   * @param status
   */
  public static String getStatusString(String status) {
    String res = "";
    if (DB_STATUS_REQUEST.equals(status)) {
      res = "申請";
    } else if (DB_STATUS_CONFIRM.equals(status)) {
      res = "確認中";
    } else if (DB_STATUS_WAIT.equals(status)) {
      res = "確認前";
    } else if (DB_STATUS_ACCEPT.equals(status)) {
      res = "承認";
    } else if (DB_STATUS_DENIAL.equals(status)) {
      res = "否認";
    } else if (DB_STATUS_THROUGH.equals(status)) {
      res = "自動承認";
    }
    return res;
  }

  /**
   * Date のオブジェクトを指定した形式の文字列に変換する．
   * 
   * @param date
   * @param dateFormat
   * @return
   */
  public static String translateDate(Date date, String dateFormat) {
    if (date == null) {
      return "Unknown";
    }

    // 日付を表示形式に変換
    SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
    sdf.setTimeZone(TimeZone.getDefault());
    return sdf.format(date);
  }

  /**
   * 3 桁でカンマ区切りした文字列を取得する．
   * 
   * @param money
   * @return
   */
  public static String translateMoneyStr(String money) {
    if (money == null || money.length() == 0) {
      return money;
    }

    StringBuffer sb = new StringBuffer();
    int len = money.length();
    int count = len / 3;
    int del = len % 3;
    sb.append(money.substring(0, del));
    if (count > 0) {
      if (len > 3 && del != 0) {
        sb.append(",");
      }
      for (int i = 0; i < count; i++) {
        sb.append(money.substring(del + 3 * i, del + 3 * i + 3));
        if (i != count - 1) {
          sb.append(",");
        }
      }
    }
    return sb.toString();
  }

  /**
   * メール送信
   */
  public static boolean sendMail(RunData rundata, EipTWorkflowRequest request,
      List<ALEipUser> destUsers, List<String> msgList) throws Exception {

    String orgId = Database.getDomainName();
    String subject = "[" + ALOrgUtilsService.getAlias() + "]ワークフロー";

    try {
      List<ALEipUser> memberList = new ArrayList<ALEipUser>();
      memberList.addAll(destUsers);
      List<ALEipUserAddr> destMemberList =
        ALMailUtils.getALEipUserAddrs(
          memberList,
          ALEipUtils.getUserId(rundata),
          false);

      List<ALAdminMailMessage> messageList =
        new ArrayList<ALAdminMailMessage>();
      for (ALEipUserAddr destMember : destMemberList) {
        ALAdminMailMessage message = new ALAdminMailMessage(destMember);
        message.setPcSubject(subject);
        message.setCellularSubject(subject);
        message.setPcBody(WorkflowUtils.createMsgForPc(rundata, request));
        message.setCellularBody(WorkflowUtils.createMsgForCellPhone(
          rundata,
          request,
          destMember.getUserId()));
        messageList.add(message);
      }

      List<String> errors =
        ALMailService.sendAdminMail(new ALAdminMailContext(orgId, ALEipUtils
          .getUserId(rundata), messageList, ALMailUtils
          .getSendDestType(ALMailUtils.KEY_MSGTYPE_WORKFLOW)));
      msgList.addAll(errors);

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

  public static boolean sendMailForUpdate(RunData rundata,
      List<EipTWorkflowRequestMap> sendMailMaps, EipTWorkflowRequest request,
      Type flowStatus) {

    WorkflowMailBean mailBean = new WorkflowMailBean();
    mailBean.setOrgId(Database.getDomainName());
    mailBean.setSubject("[" + ALOrgUtilsService.getAlias() + "]ワークフロー");
    mailBean.setLoginUserId(ALEipUtils.getUserId(rundata));
    mailBean.setAipoAlias(ALOrgUtilsService.getAlias());
    mailBean.setGlobalUrl(ALMailUtils.getGlobalurl());
    mailBean.setLocalUrl(ALMailUtils.getLocalurl());

    return sendMailForUpdateCore(sendMailMaps, request, flowStatus, mailBean);
  }

  public static boolean sendMailForUpdateCore(
      List<EipTWorkflowRequestMap> sendMailMaps, EipTWorkflowRequest request,
      Type flowStatus, WorkflowMailBean mailBean) {

    List<String> msgList = new ArrayList<String>();

    List<ALEipUserAddr> userAddressList = new ArrayList<ALEipUserAddr>();

    String msgForPcPrefix =
      createMsgForPcAtUpdatePrefix(request, flowStatus, mailBean);
    String msgForCellPrefix =
      createMsgForCellAtUpdatePrefix(request, flowStatus, mailBean);

    if ("".equals(msgForPcPrefix) || "".equals(msgForCellPrefix)) {
      return false;
    }

    for (EipTWorkflowRequestMap requestMap : sendMailMaps) {
      userAddressList.add(ALMailUtils.getALEipUserAddrByUserId(requestMap
        .getUserId()));
    }

    try {
      for (ALEipUserAddr userAddr : userAddressList) {

        ALEipUser rcptUser = ALEipUtils.getALEipUser(userAddr.getUserId());

        String msgForPc =
          msgForPcPrefix + createMsgAtUpdateSuffix(rcptUser, false, mailBean);

        String msgForCell =
          msgForCellPrefix + createMsgAtUpdateSuffix(rcptUser, true, mailBean);

        ALMailUtils.sendMailDelegateOne(mailBean.getOrgId(), mailBean
          .getLoginUserId(), userAddr, mailBean.getSubject(), mailBean
          .getSubject(), msgForPc, msgForCell, ALMailUtils
          .getSendDestType(ALMailUtils.KEY_MSGTYPE_WORKFLOW), msgList);
      }
    } catch (Exception e) {
      logger.error(e);
      return false;
    }

    return true;
  }

  public static String createMsgForPcAtUpdatePrefix(
      EipTWorkflowRequest request, Type flowStatus, WorkflowMailBean mailBean) {

    ALEipUser user;
    try {
      user = ALEipUtils.getALEipUser(request.getUserId());
    } catch (ALDBErrorException e) {
      logger.error(e);
      user = new ALEipUser();
    }

    try {
      StringBuilder body = new StringBuilder("");
      body.append(user.getAliasName().toString());
      body.append(getMessageHead(flowStatus, ALMailUtils.CR));
      body.append(getMessageContent(request, ALMailUtils.CR, false, mailBean));
      return body.toString();
    } catch (Exception e) {
      logger.error(e);
      return "";
    }

  }

  public static String createMsgForCellAtUpdatePrefix(
      EipTWorkflowRequest request, Type flowStatus, WorkflowMailBean mailBean) {

    ALEipUser user;
    try {
      user = ALEipUtils.getALEipUser(request.getUserId());
    } catch (ALDBErrorException e) {
      logger.error(e);
      user = new ALEipUser();
    }

    try {
      StringBuilder body = new StringBuilder("");
      body.append(user.getAliasName().toString());
      body.append(getMessageHead(flowStatus, ALMailUtils.CR));
      body.append(getMessageContent(request, ALMailUtils.CR, true, mailBean));
      return body.toString();
    } catch (Exception e) {
      logger.error(e);
      return "";
    }
  }

  public static String createMsgAtUpdateSuffix(ALEipUser user, boolean isCell,
      WorkflowMailBean mailBean) {
    return getMessageAipoUri(user, isCell, ALMailUtils.CR, mailBean)
      + getMessageSignature(ALMailUtils.CR, mailBean);
  }

  public static String getMessageHead(Type flowStatus, String CR)
      throws Exception {
    StringBuilder body = new StringBuilder("");

    switch (flowStatus) {
      case REQUEST:
        body.append("さんからの承認依頼です。").append(CR).append(CR);
        body.append("[決裁状況]").append(CR);
        body.append("決裁待ち").append(CR);
        break;
      case DENAIL:
        body.append("さんの申請は差し戻されました。").append(CR).append(CR);
        body.append("[決裁状況]").append(CR);
        body.append("差戻要確認").append(CR);
        break;
      case ACCEPT:
        body.append("さんの申請は承認されました。").append(CR).append(CR);
        body.append("[決裁状況]").append(CR);
        body.append("承認済み").append(CR);
        break;
      default:

    }

    return body.toString();
  }

  public static String getMessageContent(EipTWorkflowRequest request,
      String CR, boolean isCell, WorkflowMailBean mailBean) {
    StringBuilder body = new StringBuilder("");

    body.append("[表題]").append(CR);
    body.append(request.getEipTWorkflowCategory().getCategoryName()).append(CR);

    if (request.getRequestName() != null
      && (!"".equals(request.getRequestName()))) {
      body.append(request.getRequestName()).append(CR);
    }

    body
      .append("[申請日]")
      .append(CR)
      .append(
        WorkflowUtils.translateDate(request.getCreateDate(), "yyyy年M月d日H時m分"))
      .append(CR);

    body
      .append("[重要度]")
      .append(CR)
      .append(WorkflowUtils.getPriorityString(request.getPriority().intValue()))
      .append(CR);

    if (!isCell) {
      body.append("[申請内容]").append(CR).append(request.getNote()).append(CR);
    }

    if (request.getPrice() != null && (request.getPrice().intValue() > 0)) {
      body
        .append("[金額]")
        .append(CR)
        .append(request.getPrice())
        .append(" 円")
        .append(CR);
    }

    body.append(CR);
    body.append("[").append(mailBean.getAipoAlias()).append("へのアクセス]").append(
      CR);

    return body.toString();
  }

  public static String getMessageAipoUri(ALEipUser user, boolean isCell,
      String CR, WorkflowMailBean mailBean) {
    boolean enableAsp = JetspeedResources.getBoolean("aipo.asp", false);

    StringBuilder body = new StringBuilder("");

    if (isCell) {
      body.append(CR);
      body
        .append("[")
        .append(mailBean.getAipoAlias())
        .append("へのアクセス]")
        .append(CR);
      body.append("　").append(mailBean.getGlobalUrl()).append("?key=").append(
        ALCellularUtils.getCellularKey(user)).append(CR);
    } else {
      if (enableAsp) {
        body.append("　").append(mailBean.getGlobalUrl()).append(CR);
      } else {
        body.append("・社外").append(CR);
        body.append("　").append(mailBean.getGlobalUrl()).append(CR);
        body.append("・社内").append(CR);
        body.append("　").append(mailBean.getLocalUrl()).append(CR).append(CR);
      }
    }
    return body.toString();
  }

  public static String getMessageSignature(String CR, WorkflowMailBean mailBean) {
    StringBuilder body = new StringBuilder("");
    body.append("---------------------").append(CR);
    body.append(mailBean.getAipoAlias()).append(CR);
    return body.toString();
  }

  /**
   * パソコンへ送信するメールの内容を作成する．
   * 
   * @return
   */
  public static String createMsgForPc(RunData rundata,
      EipTWorkflowRequest request) {
    String CR = ALMailUtils.CR;

    WorkflowMailBean mailBean = new WorkflowMailBean();
    mailBean.setOrgId(Database.getDomainName());
    mailBean.setSubject("[" + ALOrgUtilsService.getAlias() + "]ワークフロー");
    mailBean.setLoginUserId(ALEipUtils.getUserId(rundata));
    mailBean.setAipoAlias(ALOrgUtilsService.getAlias());
    mailBean.setGlobalUrl(ALMailUtils.getGlobalurl());
    mailBean.setLocalUrl(ALMailUtils.getLocalurl());

    ALBaseUser user = null;
    ALEipUser user2 = null;

    try {
      user =
        (ALBaseUser) JetspeedSecurity.getUser(new UserIdPrincipal(request
          .getUserId()
          .toString()));
      user2 = ALEipUtils.getALEipUser(request.getUserId().intValue());
    } catch (Exception e) {
      return "";
    }
    StringBuffer body = new StringBuffer("");
    body.append(user2.getAliasName().toString());
    if (!user.getEmail().equals("")) {
      body.append("(").append(user.getEmail()).append(")");
    }

    if ("D".equals(request.getProgress())) {
      body.append("さんの申請は差し戻されました。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("差戻要確認").append(CR);
    } else if ("A".equals(request.getProgress())) {
      body.append("さんの申請は承認されました。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("承認済み").append(CR);
    } else {
      body.append("さんからの承認依頼です。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("決裁待ち").append(CR);
    }

    body.append(getMessageContent(request, CR, false, mailBean));
    body.append(createMsgAtUpdateSuffix(user2, false, mailBean));

    return body.toString();
  }

  /**
   * 携帯電話へ送信するメールの内容を作成する．
   * 
   * @return
   */
  public static String createMsgForCellPhone(RunData rundata,
      EipTWorkflowRequest request, int destUserID) {

    String CR = ALMailUtils.CR;

    WorkflowMailBean mailBean = new WorkflowMailBean();
    mailBean.setOrgId(Database.getDomainName());
    mailBean.setSubject("[" + ALOrgUtilsService.getAlias() + "]ワークフロー");
    mailBean.setLoginUserId(ALEipUtils.getUserId(rundata));
    mailBean.setAipoAlias(ALOrgUtilsService.getAlias());
    mailBean.setGlobalUrl(ALMailUtils.getGlobalurl());
    mailBean.setLocalUrl(ALMailUtils.getLocalurl());

    ALBaseUser user = null;
    ALEipUser user2 = null;

    try {
      user =
        (ALBaseUser) JetspeedSecurity.getUser(new UserIdPrincipal(request
          .getUserId()
          .toString()));
      user2 = ALEipUtils.getALEipUser(request.getUserId().intValue());
    } catch (JetspeedSecurityException e) {
      return "";
    } catch (ALDBErrorException e) {
      return "";
    }

    StringBuffer body = new StringBuffer("");
    body.append(user2.getAliasName().toString());
    if (!user.getEmail().equals("")) {
      body.append("(").append(user.getEmail()).append(")");
    }

    if ("D".equals(request.getProgress())) {
      body.append("さんの申請は差し戻されました。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("差戻要確認").append(CR);
    } else if ("A".equals(request.getProgress())) {
      body.append("さんの申請は承認されました。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("承認済み").append(CR);
    } else {
      body.append("さんからの承認依頼です。").append(CR).append(CR);
      body.append("[決裁状況]").append(CR);
      body.append("決裁待ち").append(CR);
    }

    body.append(getMessageContent(request, CR, true, mailBean));
    body.append(createMsgAtUpdateSuffix(user2, true, mailBean));

    return body.toString();
  }

  public static boolean hasWorkFlowAuthority(List<ALEipUser> memberList) {
    int size = memberList.size();
    List<ALNumberField> userIds = new ArrayList<ALNumberField>();
    for (int i = 0; i < size; i++) {
      userIds.add(memberList.get(i).getUserId());
    }

    return false;
  }

  public static boolean insertFileDataDelegate(RunData rundata,
      Context context, EipTWorkflowRequest request,
      EipTWorkflowRequest oldrequest, List<FileuploadLiteBean> fileuploadList,
      String folderName, List<String> msgList) {

    int uid = ALEipUtils.getUserId(rundata);
    String orgId = Database.getDomainName();
    String[] fileids = rundata.getParameters().getStrings("attachments");

    // fileidsがnullなら、ファイルがアップロードされていないので、trueを返して終了
    if (fileids == null) {
      return true;
    }

    int fileIDsize;
    if (fileids[0].equals("")) {
      fileIDsize = 0;
    } else {
      fileIDsize = fileids.length;
    }
    // 送られてきたFileIDの個数とDB上の当該RequestID中の添付ファイル検索を行った結果の個数が一致したら、
    // 変更が無かったとみなし、trueを返して終了。
    SelectQuery<EipTWorkflowFile> dbquery =
      Database.query(EipTWorkflowFile.class);
    dbquery.andQualifier(ExpressionFactory.matchDbExp(
      EipTWorkflowFile.EIP_TWORKFLOW_REQUEST_PROPERTY,
      request.getRequestId()));
    for (int i = 0; i < fileIDsize; i++) {
      dbquery.orQualifier(ExpressionFactory.matchDbExp(
        EipTWorkflowFile.FILE_ID_PK_COLUMN,
        fileids[i]));
    }
    List<EipTWorkflowFile> files = dbquery.fetchList();
    ;

    if (files.size() == fileIDsize
      && (fileuploadList == null || fileuploadList.size() <= 0)) {
      return true;
    }

    SelectQuery<EipTWorkflowFile> query =
      Database.query(EipTWorkflowFile.class);
    query.andQualifier(ExpressionFactory.matchDbExp(
      EipTWorkflowFile.EIP_TWORKFLOW_REQUEST_PROPERTY,
      request.getRequestId()));
    for (int i = 0; i < fileIDsize; i++) {
      Expression exp =
        ExpressionFactory.matchDbExp(
          EipTWorkflowFile.FILE_ID_PK_COLUMN,
          Integer.parseInt(fileids[i]));
      query.andQualifier(exp.notExp());
    }
    // DB上でトピックに属すが、送られてきたFileIDにIDが含まれていないファイルのリスト(削除されたファイルのリスト)
    List<EipTWorkflowFile> delFiles = query.fetchList();

    if (delFiles.size() > 0) {
      // ローカルファイルに保存されているファイルを削除する．
      int delsize = delFiles.size();
      for (int i = 0; i < delsize; i++) {
        ALStorageService.deleteFile(WorkflowUtils.getSaveDirPath(orgId, uid)
          + (delFiles.get(i)).getFilePath());
      }
      // データベースから添付ファイルのデータ削除
      Database.deleteAll(delFiles);
    }

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

    // ファイル追加処理
    try {
      FileuploadLiteBean filebean = null;
      int size = fileuploadList.size();
      for (int i = 0; i < size; i++) {
        filebean = fileuploadList.get(i);

        // サムネイル処理
        String[] acceptExts = ImageIO.getWriterFormatNames();
        byte[] fileThumbnail =
          FileuploadUtils.getBytesShrinkFilebean(
            orgId,
            folderName,
            uid,
            filebean,
            acceptExts,
            FileuploadUtils.DEF_THUMBNAIL_WIDTH,
            FileuploadUtils.DEF_THUMBNAIL_HEIGTH,
            msgList);

        String filename = i + "_" + String.valueOf(System.nanoTime());

        // 新規オブジェクトモデル
        EipTWorkflowFile file = Database.create(EipTWorkflowFile.class);
        // 所有者
        file.setOwnerId(Integer.valueOf(uid));
        // リクエストID
        file.setEipTWorkflowRequest(request);
        // ファイル名
        file.setFileName(filebean.getFileName());
        // ファイルパス
        file.setFilePath(WorkflowUtils.getRelativePath(filename));
        // サムネイル画像
        if (fileThumbnail != null) {
          file.setFileThumbnail(fileThumbnail);
        }
        // 作成日
        file.setCreateDate(Calendar.getInstance().getTime());
        // 更新日
        file.setUpdateDate(Calendar.getInstance().getTime());

        // ファイルの移動
        ALStorageService.copyTmpFile(uid, folderName, String.valueOf(filebean
          .getFileId()), FOLDER_FILEDIR_WORKFLOW, CATEGORY_KEY
          + ALStorageService.separator()
          + uid, filename);
      }

      // 添付ファイル保存先のフォルダを削除
      ALStorageService.deleteTmpFolder(uid, folderName);
    } catch (Exception e) {
      logger.error("Exception", e);
      return false;
    }
    return true;
  }

  /**
   * ユーザ毎のルート保存先（絶対パス）を取得します。
   * 
   * @param uid
   * @return
   */
  public static String getSaveDirPath(String orgId, int uid) {
    return ALStorageService.getDocumentPath(
      FOLDER_FILEDIR_WORKFLOW,
      CATEGORY_KEY + ALStorageService.separator() + uid);
  }

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

  public static List<UserLiteBean> getAuthorityUsers(RunData rundata,
      String groupname, boolean includeLoginuser) {

    try {
      // アクセス権限
      ALAccessControlFactoryService aclservice =
        (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
          .getInstance())
          .getService(ALAccessControlFactoryService.SERVICE_NAME);
      ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();

      List<TurbineUser> ulist =
        aclhandler.getAuthorityUsersFromGroup(
          rundata,
          ALAccessControlConstants.POERTLET_FEATURE_WORKFLOW_REQUEST_SELF,
          groupname,
          includeLoginuser);

      List<UserLiteBean> list = new ArrayList<UserLiteBean>();

      UserLiteBean user;
      // ユーザデータを作成し、返却リストへ格納
      for (TurbineUser tuser : ulist) {
        user = new UserLiteBean();
        user.initField();
        user.setUserId(tuser.getUserId());
        user.setName(tuser.getLoginName());
        user.setAliasName(tuser.getFirstName(), tuser.getLastName());
        list.add(user);
      }
      return list;
    } catch (InstantiationException e) {
      return null;
    }

  }

  /**
   * ファイル検索のクエリを返します
   * 
   * @param requestid
   *          ファイルを検索するリクエストのid
   * @return query
   */
  private static SelectQuery<EipTWorkflowFile> getSelectQueryForFiles(
      int requestid) {
    SelectQuery<EipTWorkflowFile> query =
      Database.query(EipTWorkflowFile.class);
    Expression exp =
      ExpressionFactory.matchDbExp(
        EipTWorkflowRequest.REQUEST_ID_PK_COLUMN,
        Integer.valueOf(requestid));
    query.setQualifier(exp);
    return query;
  }

  /**
   * 指定した ID に対するユーザの名前を取得する．
   * 
   * @param userId
   * @return
   */
  public static String getName(String userId) {
    if (userId == null || userId.equals("")) {
      return null;
    }

    String firstName = null;
    String lastName = null;
    StringBuffer buffer = new StringBuffer();

    try {
      SelectQuery<TurbineUser> query = Database.query(TurbineUser.class);
      Expression exp =
        ExpressionFactory.matchDbExp(TurbineUser.USER_ID_PK_COLUMN, Integer
          .valueOf(userId));
      query.setQualifier(exp);
      List<TurbineUser> destUserList = query.fetchList();
      if (destUserList == null || destUserList.size() <= 0) {
        return null;
      }
      firstName = (destUserList.get(0)).getFirstName();
      lastName = (destUserList.get(0)).getLastName();
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    return buffer.append(lastName).append(" ").append(firstName).toString();
  }

  /**
   * 指定した ID に対するユーザのログイン名を取得する．
   * 
   * @param userId
   * @return
   */
  public static String getUserName(String userId) {
    if (userId == null || userId.equals("")) {
      return null;
    }

    String userName = null;

    try {
      SelectQuery<TurbineUser> query = Database.query(TurbineUser.class);
      Expression exp =
        ExpressionFactory.matchDbExp(TurbineUser.USER_ID_PK_COLUMN, Integer
          .valueOf(userId));
      query.setQualifier(exp);
      List<TurbineUser> destUserList = query.fetchList();
      if (destUserList == null || destUserList.size() <= 0) {
        return null;
      }
      userName = (destUserList.get(0)).getLoginName();
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    return userName;
  }

  public static Integer getRouteIdFromCategoryId(Integer categoryId) {
    if (categoryId == null || categoryId <= 0) {
      return null;
    }

    Integer routeId = null;

    try {
      SelectQuery<EipTWorkflowCategory> query =
        Database.query(EipTWorkflowCategory.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          EipTWorkflowCategory.CATEGORY_ID_PK_COLUMN,
          Integer.valueOf(categoryId));
      query.setQualifier(exp);
      List<EipTWorkflowCategory> list = query.fetchList();
      if (list == null || list.size() <= 0) {
        return null;
      }
      routeId = (list.get(0)).getEipTWorkflowRoute().getRouteId();
    } catch (Exception ex) {
      return null;
    }
    return routeId;
  }

  /**
   * 指定した ID のユーザを取得する
   * 
   * @param userId
   * @return
   */
  public static TurbineUser getTurbineUser(String userId) {
    if (userId == null || userId.equals("")) {
      return null;
    }
    try {
      SelectQuery<TurbineUser> query = Database.query(TurbineUser.class);
      Expression exp =
        ExpressionFactory.matchDbExp(TurbineUser.USER_ID_PK_COLUMN, Integer
          .valueOf(userId));
      query.setQualifier(exp);
      List<TurbineUser> destUserList = query.fetchList();
      if (destUserList == null || destUserList.size() <= 0) {
        return null;
      }
      return destUserList.get(0);
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * 指定した ID のユーザが削除済みかどうかを調べる。
   * 
   * @param userId
   * @return
   */
  public static boolean isDisabledOrDeleted(String userId) {
    if (null == userId || "".equals(userId)) {
      return true;
    }
    int _userId = Integer.parseInt(userId);
    return isDisabledOrDeleted(_userId);
  }

  public static boolean isDisabledOrDeleted(int userId) {
    try {
      TurbineUser user = ALEipUtils.getTurbineUser(userId);

      if (user == null) {
        return true;
      }

      String disabled = user.getDisabled();
      return ("T".equals(disabled) || "N".equals(disabled));

    } catch (ALDBErrorException e) {
      logger.error("Exception", e);
      return true;
    }

  }

  public static void createWorkflowRequestActivity(EipTWorkflowRequest request,
      String loginName, List<String> recipients, Type type) {
    if (recipients != null && recipients.size() > 0) {
      EipTWorkflowCategory category = request.getEipTWorkflowCategory();
      String name = request.getRequestName();

      StringBuilder b = new StringBuilder("申請「");
      if (category != null) {
        b.append(ALCommonUtils.compressString(category.getCategoryName(), 10));
        if (name != null && name.length() > 0) {
          b.append("：");
        }
      }

      b
        .append(ALCommonUtils.compressString(request.getRequestName(), 20))
        .append("」");
      switch (type) {
        case REQUEST:
          b.append("の確認依頼をだしました。");
          break;
        case DENAIL:
          b.append("を差し戻しました。");
          break;
        case ACCEPT:
          b.append("を承認しました。");
          break;
        default:

      }
      String portletParams =
        new StringBuilder("?template=WorkflowDetailScreen")
          .append("&entityid=")
          .append(request.getRequestId())
          .toString();
      ALActivityService.create(new ALActivityPutRequest()
        .withAppId("Workflow")
        .withLoginName(loginName)
        .withPortletParams(portletParams)
        .withRecipients(recipients)
        .withTile(b.toString())
        .witchPriority(1f)
        .withExternalId(String.valueOf(request.getRequestId())));
    }
  }
}
