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

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.Attributes;

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

import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.commons.field.ALNumberField;
import com.aimluck.commons.field.ALStringField;
import com.aimluck.commons.utils.ALDateUtil;
import com.aimluck.eip.document.common.DocumentConstants;
import com.aimluck.eip.document.util.DocumentUtils;
import com.aimluck.eip.cayenne.om.portlet.EipTWorkflowRoute;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFile;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentFileMap;
import com.aimluck.eip.cayenne.om.portlet.ImwTDocumentRelationMap;
import com.aimluck.eip.cayenne.om.security.TurbineGroup;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.cayenne.om.security.TurbineUserGroupRole;
import com.aimluck.eip.common.ALAbstractSelectData;
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.modules.actions.common.ALAction;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.services.accessctl.ALAccessControlConstants;
import com.aimluck.eip.services.accessctl.ALAccessControlFactoryService;
import com.aimluck.eip.services.accessctl.ALAccessControlHandler;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.workflow.util.WorkflowUtils;

/**
 * 文書管理のファイル検索データを管理するためのクラスです。 <br />
 */
public class DocumentSelectData extends ALAbstractSelectData {

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

  /** 選択されたフォルダ情報 */
  private FolderInfo selected_folderinfo = null;

  private ArrayList folder_hierarchy_list;

  /** ファイル総数 */
  private int fileSum;
  
  private ArrayList relList;

  /** フォルダの閲覧権限 */
  private boolean isAccessible = true;

  /** フォルダの編集権限 */
  private boolean isEditable = true;
  
  /** 削除権限の有無 */
  private boolean isDocumentDelete = false;
  
  /** 編集権限の有無 */
  private boolean isDocumentUpdate = false;

  /** ノーマル画面の表示かどうか */
  private boolean isNormalContext = false;

  /** ログインユーザが文書管理システム管理者かどうか */
  private boolean isDocAdmin = false;
  
  private RunData rundata;

  /** アクセス権限 */
  /** メンバー選択が必要かどうか */
  private boolean isMemberRead;
  private boolean isMemberEdit;

  /** <code>target_user_id</code> 表示対象のユーザ ID */
  private String target_user_id;

  /** <code>userList</code> 表示切り替え用のユーザリスト */
  private List userList = null;

  /** <code>today</code> 今日 */
  private ALDateTimeField today;
  
  /** 申請経路一覧 */
  private List routeList;
  
  /** 申請経路ID */
  private ALNumberField route_id;

  private ALStringField route;
  
  /** 申請経路の選択 */
  private boolean is_saved_route;
  
  private ArrayList workflowMemberList;
  
  public void setIsNormalContext(boolean flg) {
    isNormalContext = flg;
  }

  /**
   *
   * @param action
   * @param rundata
   * @param context
   * @see com.aimluck.eip.common.ALAbstractSelectData#init(com.aimluck.eip.modules.actions.common.ALAction,
   *      org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
   */
  public void init(ALAction action, RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {

    //セッションにソート情報が存在しない場合、ファイルタイトルでソート
    String sort = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
    if (sort == null || sort.equals("")) {
      ALEipUtils.setTemp(rundata, context, LIST_SORT_STR, ALEipUtils
          .getPortlet(rundata, context).getPortletConfig().getInitParameter(
              "p1c-sort"));
      logger.debug("[DocumentSelectData] Init Parameter. : "
          + ALEipUtils.getPortlet(rundata, context).getPortletConfig()
              .getInitParameter("p1c-sort"));
    }

    int fid = DocumentUtils.ROOT_FODLER_ID;
    if (isNormalContext) {
      String id = ALEipUtils.getPortlet(rundata, context).getPortletConfig()
          .getInitParameter("p3a-folder");
      fid = Integer.parseInt(id);
    } else {
      // 自ポートレットからのリクエストであれば、パラメータを展開しセッションに保存する。
      if (ALEipUtils.isMatch(rundata, context)) {
        // ENTITY ID
        if (rundata.getParameters().containsKey(DocumentUtils.KEY_FOLDER_ID)) {
          ALEipUtils.setTemp(rundata, context, DocumentUtils.KEY_FOLDER_ID,
              rundata.getParameters().getString(DocumentUtils.KEY_FOLDER_ID));
        }
      }
      String tmpfid = ALEipUtils.getTemp(rundata, context,
          DocumentUtils.KEY_FOLDER_ID);
      if (tmpfid != null && !"".equals(tmpfid)) {
        try {
          fid = Integer.parseInt(tmpfid);
          /** フォルダ権限のチェック */
          isAccessible = DocumentUtils.isAccessibleFolder(fid, rundata);
          isEditable = DocumentUtils.isEditableFolder(fid, rundata);
        } catch (Exception e) {
          fid = DocumentUtils.ROOT_FODLER_ID;
        }
      }
    }

    folder_hierarchy_list = DocumentUtils.getFolderList();
    if (folder_hierarchy_list != null && folder_hierarchy_list.size() > 0) {
      int size = folder_hierarchy_list.size();
      for (int i = 0; i < size; i++) {
        FolderInfo info = (FolderInfo) folder_hierarchy_list.get(i);
        if (info.getFolderId() == fid) {
          selected_folderinfo = info;
          break;
        }
      }
      if (selected_folderinfo == null) {
        selected_folderinfo = (FolderInfo) folder_hierarchy_list.get(0);
      }
    }
    // ログインユーザが文書管理システム管理者かどうか
    isDocAdmin = DocumentUtils.isDocAdmin(rundata);

    // 今日
    today = new ALDateTimeField("yyyy-MM-dd");
    Calendar to = Calendar.getInstance();
    to.set(Calendar.HOUR_OF_DAY, 0);
    to.set(Calendar.MINUTE, 0);
    today.setValue(to.getTime());
    
    // 指定ユーザをセッションに設定する．
    setupLists(rundata, context);
    
    // 申請経路リストの設定。
    routeList = new ArrayList();
    route_id = new ALNumberField();
    route = new ALStringField();
    
    loadRouteList(rundata,context);
  
    // デフォルトの申請経路があれば設定する。
    workflowMemberList = new ArrayList();
    EipTWorkflowRoute docRoute = DocumentUtils.getDocRoute();
    if(docRoute != null){
      is_saved_route = true;
      route_id.setValue(docRoute.getRouteId());
      route.setValue(docRoute.getRoute());
      DocumentUtils.setWorkflowMember(workflowMemberList, route.getValue());
    } else {
      is_saved_route = false;
    }
    
    this.rundata = rundata;

    super.init(action, rundata, context);
  }

  /**
   * @see com.aimluck.eip.common.ALAbstractSelectData#selectList(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  protected List selectList(RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {

    StringBuffer statement = new StringBuffer();
    statement.append(" SELECT");
    statement.append("      FILE.FILE_ID");
    statement.append("     ,FILE.DOC_ID");
    statement.append("     ,FILE.FILE_REV_MJ");
    statement.append("     ,FILE.FILE_REV_MN");
    statement.append("     ,FILE.FOLDER_ID");
    statement.append("     ,FILE.FILE_TITLE");
    statement.append("     ,FILE.FILE_NAME");
    statement.append("     ,FILE.FILE_SIZE");
    statement.append("     ,FILE.FILE_PATH");
    statement.append("     ,FILE.OPEN_END_DATE");
    statement.append("     ,FILE.SAVE_END_DATE");
    statement.append("     ,FILE.STATUS");
    statement.append("     ,FILE.CHECKIN_COMMENT");
    statement.append("     ,FILE.NOTE");
    statement.append("     ,FILE.CREATE_USER_ID");
    statement.append("     ,FILE.CHECKOUT_USER_ID");
    statement.append("     ,FILE.UPDATE_USER_ID");
    statement.append("     ,FILE.CREATE_DATE");
    statement.append("     ,FILE.CHECKOUT_DATE");
    statement.append("     ,FILE.UPDATE_DATE");
    statement.append("     ,REQUEST_USER.USER_ID AS REQUEST_USER_ID");
    statement.append("     ,REQUEST_MAP.REQUEST_TYPE");
    statement.append(" FROM IMW_T_DOCUMENT_FILE FILE");
    statement.append("     LEFT OUTER JOIN IMW_T_DOCUMENT_REQUEST_MAP REQUEST_MAP ON");
    statement.append("             FILE.DOC_ID = REQUEST_MAP.DOC_ID");
    statement.append("         AND (");
    statement.append("                   REQUEST_MAP.PAST =  0");
    statement.append("                OR REQUEST_MAP.PAST IS NULL");
    statement.append("             )");
    statement.append("     LEFT OUTER JOIN TURBINE_USER CHECKOUT_USER ON");
    statement.append("             CHECKOUT_USER.USER_ID  = FILE.CHECKOUT_USER_ID");
    statement.append("     LEFT OUTER JOIN TURBINE_USER REQUEST_USER ON");
    statement.append("             REQUEST_USER.USER_ID  = REQUEST_MAP.REQUEST_USER_ID");
    statement.append(" WHERE");
    statement.append("         FILE.FOLDER_ID = " + Integer.valueOf(selected_folderinfo.getFolderId()));

    if (isDocAdmin) {
      // 管理者
      statement.append("     AND (     (     REQUEST_MAP.REQUEST_USER_ID IS NOT NULL");
      statement.append("                 AND (     (     REQUEST_MAP.REQUEST_TYPE    IN (1, 3)");
      statement.append("                             AND FILE.STATUS                 =  '3'");
      statement.append("                           )");
      statement.append("                        OR (     REQUEST_MAP.REQUEST_TYPE    IN (2, 4, 5)");
      statement.append("                             AND FILE.STATUS                 IN ('0','1')");
      statement.append("                           )");
      statement.append("                     )");
      statement.append("               )");
      statement.append("            OR (     REQUEST_MAP.REQUEST_USER_ID IS NULL");
      statement.append("                 AND FILE.STATUS                 IN ('0','1')");
      statement.append("               )");
      statement.append("         )");
    } else {
      // 一般ユーザ
      statement.append("     AND (     (     REQUEST_MAP.REQUEST_TYPE IN (1, 3)");
      statement.append("                 AND (     (     REQUEST_MAP.REQUEST_USER_ID =  " + ALEipUtils.getALEipUser(rundata).getUserId().getValue());
      statement.append("                             AND FILE.STATUS                 =  '3'");
      statement.append("                           )");
      statement.append("                        OR (     REQUEST_MAP.REQUEST_USER_ID <> " + ALEipUtils.getALEipUser(rundata).getUserId().getValue());
      statement.append("                             AND FILE.STATUS                 IN ('0','1')");
      statement.append("                           )");
      statement.append("                     )");
      statement.append("               )");
      statement.append("            OR (     REQUEST_MAP.REQUEST_TYPE    IN (2, 4, 5)");
      statement.append("                 AND REQUEST_MAP.REQUEST_USER_ID IS NOT NULL");
      statement.append("                 AND FILE.STATUS                 IN ('0','1')");
      statement.append("               )");
      statement.append("            OR (     REQUEST_MAP.REQUEST_USER_ID IS NULL");
      statement.append("                 AND FILE.STATUS                 IN ('0','1')");
      statement.append("               )");
      statement.append("         )");
      statement.append("     AND (");
      statement.append("             FILE.OPEN_END_DATE IS NULL");
      statement.append("         OR  FILE.OPEN_END_DATE >= to_date('" + today.toString() + "','YYYY-MM-DD')");
      statement.append("         )");
      statement.append("     AND FILE.DOC_ID    IN (" + getVisibleDocIdStr() + ")");
    }

    // ソート順の設定
    String listSortStr = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
    String listSortTypeStr = "";
    if (ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR) != null) {
      listSortTypeStr = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
    }

    super.setCurrentSort(listSortStr);
    super.setCurrentSortType(listSortTypeStr);
    
    statement.append(" ORDER BY");
    if(listSortStr.equals("file_title")){
      statement.append("      FILE.FILE_TITLE " + listSortTypeStr);
    } else if(listSortStr.equals("file_name")){
      statement.append("      FILE.FILE_NAME " + listSortTypeStr);
    } else if(listSortStr.equals("file_rev")){
      statement.append("      FILE.FILE_REV_MJ " + listSortTypeStr);
      statement.append("     ,FILE.FILE_REV_MN " + listSortTypeStr);
    } else if(listSortStr.equals("update_date")){
      statement.append("      FILE.UPDATE_DATE " + listSortTypeStr);
    } else if(listSortStr.equals("file_size")){
      statement.append("      FILE.FILE_SIZE " + listSortTypeStr);
    } else if(listSortStr.equals("checkout_user")){
      statement.append("      CHECKOUT_USER.LAST_NAME_KANA " + listSortTypeStr);
      statement.append("     ,CHECKOUT_USER.FIRST_NAME_KANA " + listSortTypeStr);
    } else if(listSortStr.equals("request_user")){
      statement.append("      REQUEST_USER.LAST_NAME_KANA " + listSortTypeStr);
      statement.append("     ,REQUEST_USER.FIRST_NAME_KANA " + listSortTypeStr);
    }
  
    String query = statement.toString();

    try {
      DocumentUtils.setFolderVisible(folder_hierarchy_list, selected_folderinfo, rundata);

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

      int recordNum = list.size();
      DataRow dataRow;
      List worklist = new ArrayList();
      for (int i = 0; i < recordNum; i++) {
        dataRow = (DataRow) list.get(i);
        ImwTDocumentFile imwTDocumentFile = new ImwTDocumentFile();
        imwTDocumentFile.setFileId((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_ID_COLUMN).toString());
        imwTDocumentFile.setDocId((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.DOC_ID_COLUMN));
        imwTDocumentFile.setFileRevMj((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_REV_MJ_COLUMN));
        imwTDocumentFile.setFileRevMn((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_REV_MN_COLUMN));
        imwTDocumentFile.setFolderId((Integer) Integer.valueOf(ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FOLDER_ID_COLUMN).toString()));
        imwTDocumentFile.setFileTitle((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_TITLE_COLUMN));
        imwTDocumentFile.setFileName((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_NAME_COLUMN));
        imwTDocumentFile.setFileSize((Long) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_SIZE_COLUMN));
        imwTDocumentFile.setFilePath((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.FILE_PATH_COLUMN));
        imwTDocumentFile.setOpenEndDate((Date) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.OPEN_END_DATE_COLUMN));
        imwTDocumentFile.setSaveEndDate((Date) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.SAVE_END_DATE_COLUMN));
        imwTDocumentFile.setStatus((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.STATUS_COLUMN));
        imwTDocumentFile.setCheckinComment((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.CHECKIN_COMMENT_COLUMN));
        imwTDocumentFile.setNote((String) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.NOTE_COLUMN));
        imwTDocumentFile.setCreateUserId((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.CREATE_USER_ID_COLUMN));
        imwTDocumentFile.setCheckoutUserId((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.CHECKOUT_USER_ID_COLUMN));
        imwTDocumentFile.setUpdateUserId((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.UPDATE_USER_ID_COLUMN));
        imwTDocumentFile.setCreateDate((Date) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.CREATE_DATE_COLUMN));
        imwTDocumentFile.setCheckoutDate((Date) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.CHECKOUT_DATE_COLUMN));
        imwTDocumentFile.setUpdateDate((Date) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.UPDATE_DATE_COLUMN));
        imwTDocumentFile.setRequestUserId((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.REQUEST_USER_ID_COLUMN));
        imwTDocumentFile.setRequestType((Integer) ALEipUtils.getObjFromDataRow(dataRow,ImwTDocumentFile.REQUEST_TYPE_COLUMN));
        worklist.add(imwTDocumentFile);
      }
      // ファイル総数をセットする．
      if (list == null) {
        return new ArrayList();
      } else {
        fileSum = worklist.size();
      }
      return buildPaginatedList(worklist);
      
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
    
//    try {
//      DocumentUtils.setFolderVisible(folder_hierarchy_list, selected_folderinfo,
//          rundata);
//
//      DataContext dataContext = DatabaseOrmService.getInstance()
//          .getDataContext();
//
//      SelectQuery query = getSelectQuery(rundata, context);
//      buildSelectQueryForListView(query);
//      buildSelectQueryForListViewSort(query, rundata, context);
//      //バージョンでソートする場合、マイナー番号のソート文を追加
//      if(ALEipUtils.getTemp(rundata, context, LIST_SORT_STR).equals("file_rev")){
//        String sort_type = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
//        if (sort_type != null
//            && ALEipConstants.LIST_SORT_TYPE_DESC.equals(sort_type)) {
//          //取得ソートタイプが降順、またはNULL以外の場合
//          query.addOrdering(ImwTDocumentFile.FILE_REV_MN_PROPERTY, false);
//        } else {
//          //取得ソートタイプが昇順の場合
//          query.addOrdering(ImwTDocumentFile.FILE_REV_MN_PROPERTY, true);
//        }
//      }
//
//      List list = dataContext.performQuery(query);
//      // ファイル総数をセットする．
//      if (list == null) {
//        return new ArrayList();
//      } else {
//        fileSum = list.size();
//      }
//      return buildPaginatedList(list);
//    } catch (Exception ex) {
//      logger.error("Exception", ex);
//      return null;
//    }
  }

//  /**
//   * 検索条件を設定した SelectQuery を返します。 <BR>
//   *
//   * @param rundata
//   * @param context
//   * @return
//   */
//  private SelectQuery getSelectQuery(RunData rundata, Context context) {
//
//    SelectQuery query = new SelectQuery(ImwTDocumentFile.class);
//    
//    if (selected_folderinfo != null) {
//      //選択フォルダIDの一致するファイルのみ取得
//      Expression exp1 = ExpressionFactory.matchExp(
//          ImwTDocumentFile.FOLDER_ID_PROPERTY,
//          Integer.valueOf(selected_folderinfo.getFolderId()));
//      //ステータスが0か1（最新のファイル）のみ取得
//      Expression exp2 = ExpressionFactory.matchExp(
//          ImwTDocumentFile.STATUS_PROPERTY, '0');
//      Expression exp3 = ExpressionFactory.matchExp(
//          ImwTDocumentFile.STATUS_PROPERTY, '1');
//      //公開終了日が未設定、または現在日以降のファイルのみ取得
//      Expression exp4 = ExpressionFactory.matchExp(
//          ImwTDocumentFile.OPEN_END_DATE_PROPERTY, null);
//      Expression exp5 = ExpressionFactory.greaterOrEqualExp(
//          ImwTDocumentFile.OPEN_END_DATE_PROPERTY, 
//          ALDateUtil.format(new Date(), "yyyy-MM-dd"));
//      //参照可能ファイルのみ取得
//      Expression exp6;
//      if (getVisibleDocId().size() == 0) {
//        //参照可能ファイルが存在しない場合
//        exp6 = ExpressionFactory.matchExp(
//            ImwTDocumentFile.DOC_ID_PROPERTY, null);
//      } else {
//        //参照可能ファイルが存在する場合
//        exp6 = ExpressionFactory.inExp(
//            ImwTDocumentFile.DOC_ID_PROPERTY, getVisibleDocId());
//      }
//      
//      query.setQualifier(exp1);
//      query.andQualifier(exp2.orExp(exp3));
//      //文書管理システム管理者は、アクセス権限と公開期間に関係なくファイルを閲覧できる
//      if (!isDocAdmin) {
//        query.andQualifier(exp4.orExp(exp5));
//        query.andQualifier(exp6);
//      }
//
//    }
//    query.setDistinct(true);
//
//    return buildSelectQueryForFilter(query, rundata, context);
//  }

  /**
   * ログインユーザが所属するグループの一覧を返します。 <BR>
   *
   * @return grouplist
   */
  private List getUserGroupId() {
    List grouplist = new ArrayList();
    DataContext dataContext = DatabaseOrmService.getInstance()
        .getDataContext();
    SelectQuery query = new SelectQuery(TurbineUserGroupRole.class);
    Expression exp1 = ExpressionFactory.matchExp(
        TurbineUserGroupRole.TURBINE_USER_PROPERTY,
        ALEipUtils.getALEipUser(rundata).getUserId().getValue());
    query.setQualifier(exp1);
    List maplist = dataContext.performQuery(query);

    for(int i = 0; i < maplist.size(); i++){
      TurbineUserGroupRole map = (TurbineUserGroupRole) maplist.get(i);
      grouplist.add(map.getTurbineGroup());
    }
    return grouplist;
  }
  
  /**
   * ユーザが参照可能な文書ファイルのDOC_IDを返します。\<BR>
   * （参照権限が複数指定されている場合、同じDOC_IDが取得されます）\<BR>
   *
   * @param 
   * @return docid
   */
  private String getVisibleDocIdStr() {
    String docidstr = "";
    List docidlist = getVisibleDocId();
    for(int i = 0; i < docidlist.size(); i++){
      if (i != 0) {
        docidstr += ",";
      }
      docidstr += "'" + docidlist.get(i).toString() + "'";
    }
    return docidstr;
  }  
  
  /**
   * ユーザが参照可能な文書ファイルのDOC_IDを返します。\<BR>
   * （参照権限が複数指定されている場合、同じDOC_IDが取得されます）\<BR>
   *
   * @param 
   * @return docid
   */
  private List getVisibleDocId() {
    List docidlist = new ArrayList();
    DataContext dataContext = DatabaseOrmService.getInstance()
        .getDataContext();
    SelectQuery query = new SelectQuery(ImwTDocumentFileMap.class);
    Expression exp1 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.USER_ID_PROPERTY,
        ALEipUtils.getALEipUser(rundata).getUserId().getValue());
    Expression exp2 = ExpressionFactory.inExp(
        ImwTDocumentFileMap.GROUP_ID_PROPERTY, getUserGroupId());
    Expression exp3 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.GROUP_ID_PROPERTY, -1);
    query.setQualifier(exp1.orExp(exp2).orExp(exp3));
    List maplist = dataContext.performQuery(query);

    for(int i = 0; i < maplist.size(); i++){
      ImwTDocumentFileMap map = (ImwTDocumentFileMap) maplist.get(i);
      docidlist.add(map.getDocId());
    }
    return docidlist;
  }
  
  /**
   * @see com.aimluck.eip.common.ALAbstractSelectData#selectDetail(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  protected Object selectDetail(RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {
    return DocumentUtils.getImwTDocumentFile(rundata, context);
  }

  /**
   * @see com.aimluck.eip.common.ALAbstractSelectData#getResultData(java.lang.Object)
   */
  protected Object getResultData(Object obj) throws ALPageNotFoundException,
      ALDBErrorException {
    try {
      ImwTDocumentFile record = (ImwTDocumentFile) obj;
      
      DocumentFileResultData rd = new DocumentFileResultData();
      rd.initField();
      rd.setFileId(record.getFileId().longValue());
      rd.setFileTitle(record.getFileTitle());
      rd.setFileName(record.getFileName());
      rd.setFileRevMj(record.getFileRevMj());
      rd.setFileRevMn(record.getFileRevMn());
      rd.setFileSize(record.getFileSize());
      
      // 申請中かどうか
      rd.setIsRequesting(DocumentUtils.isDocRequesting(record));
      
      // 再申請の条件を満たすか
      rd.setIsReqAgain(DocumentUtils.isDocReqAgain(record.getDocId()));
      

      //チェックアウトユーザ名取得
      String checkoutUserName = "";
      if (record.getCheckoutUserId() != null) {
        ALEipUser checkoutUser = ALEipUtils.getALEipUser(record.getCheckoutUserId()
            .intValue());
        if (checkoutUser != null) {
          checkoutUserName = checkoutUser.getAliasName().getValue();
          }
        if (record.getCheckoutUserId() == ALEipUtils.getALEipUser(rundata).getUserId().getValue()) {
          //チェックアウトユーザとログインユーザが同一の場合
          rd.setCheckoutStatus(2);
        } else if (record.getCheckoutUserId() != -1) {
          //チェックアウトユーザが存在する場合場合
          rd.setCheckoutStatus(1);
        } else {
          //チェックアウトされていない場合
          rd.setCheckoutStatus(0);
        }
      }
      rd.setCheckoutUser(checkoutUserName);
      //申請者名取得
      String requestUserName = "";
      if (record.getRequestUserId() != null) {
        ALEipUser requestUser = ALEipUtils.getALEipUser(record.getRequestUserId()
            .intValue());
        if (requestUser != null) {
          requestUserName = requestUser.getAliasName().getValue();
          }
        if (record.getRequestUserId() == ALEipUtils.getALEipUser(rundata).getUserId().getValue()) {
          //申請者とログインユーザが同一の場合
          rd.setRequestStatus(2);
        } else if (record.getRequestUserId() != -1) {
          //申請者が存在する場合場合
          rd.setRequestStatus(1);
        } else {
          //申請されていない場合
          rd.setRequestStatus(0);
        }
      }
      rd.setRequestUser(requestUserName);
      //申請種類取得
      Integer requestType = 0;
      String requestTypeName = "";
      if (record.getRequestType() != null) {
        requestType = record.getRequestType();
      }
      requestTypeName = DocumentUtils.decodeIdRequest(requestType, DocumentConstants.NAME_REQUESTING);
      rd.setRequestType(requestTypeName);
      
      rd.setUpdateDate(ALDateUtil.format(record.getUpdateDate(), "yyyy年M月d日"));

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

  /**
   * @see com.aimluck.eip.common.ALAbstractSelectData#getResultDataDetail(java.lang.Object)
   */
  protected Object getResultDataDetail(Object obj)
      throws ALPageNotFoundException, ALDBErrorException {
    try {
      ImwTDocumentFile record = (ImwTDocumentFile) obj;

      DocumentFileResultData rd = new DocumentFileResultData();
      rd.initField();
      rd.setFileId(record.getFileId().longValue());
      rd.setFileTitle(record.getFileTitle());
      //文書ファイルID
      Long fileID = record.getFileId().longValue();
      //バージョン
      rd.setFileRevMj(record.getFileRevMj());
      rd.setFileRevMn(record.getFileRevMn());
      //公開終了日
      if(record.getOpenEndDate() != null){
        rd.setOpenEndDate(ALDateUtil.format(record.getOpenEndDate(), "yyyy年M月d日"));
      }else{
        rd.setOpenEndDate("");
      }
      //保存終了日
      if(record.getSaveEndDate() != null){
        rd.setSaveEndDate(ALDateUtil.format(record.getSaveEndDate(), "yyyy年M月d日"));
      }else{
        rd.setSaveEndDate("");
      }
      //コメント
      rd.setCheckinComment(record.getCheckinComment());
 
      // 申請中かどうか
      rd.setIsRequesting(DocumentUtils.isDocRequesting(record));
      
      // 再申請の条件を満たすか
      rd.setIsReqAgain(DocumentUtils.isDocReqAgain(record.getDocId()));
      
      // 申請種類
      rd.setRequestType(DocumentUtils.getRequestTypeByDocId(record.getDocId()).toString());
      
      //関連文書名
      DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
      SelectQuery mapquery = new SelectQuery(ImwTDocumentFile.class);
      Expression mapexp = ExpressionFactory.matchExp(
          ImwTDocumentFile.DOC_ID_PROPERTY,
          record.getDocId());
      mapquery.setQualifier(mapexp);
      List listFile = dataContext.performQuery(mapquery);

      //ファイルテーブルのDOCIDの取得
      List relFileList = new ArrayList();
      for (int i = 0; i < listFile.size(); i++) {
        ImwTDocumentFile map = (ImwTDocumentFile) listFile.get(i);
        relFileList.add(map.getDocId());
      }
      
      //関連文書マップからファイルリストの取得
      SelectQuery query = new SelectQuery(ImwTDocumentRelationMap.class);
      Expression exp = ExpressionFactory.inExp(ImwTDocumentRelationMap.DOC_ID_PROPERTY,
          relFileList);
      query.setQualifier(exp);
      Expression exp2;
      if("3".equals(record.getStatus())){
        // 追加申請中、チェックイン申請中の関連文書は申請中の関連文書を表示する
        exp2 = ExpressionFactory.matchExp(
            ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY,1);
      } else {
        // それ以外の場合は、確定した関連文書を表示する
        exp2 = ExpressionFactory.matchExp(
            ImwTDocumentRelationMap.REQUEST_STATUS_PROPERTY,0);        
      }
      query.andQualifier(exp2);
      relList = new ArrayList();
      relList.addAll(getRelFileSelectQuery(query));
      
      //ファイル削除権限の有無の取得
      ALAccessControlFactoryService aclservice = (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
          .getInstance()).getService(ALAccessControlFactoryService.SERVICE_NAME);
      ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();
      isDocumentDelete = aclhandler.hasAuthority((int) ALEipUtils.getALEipUser(rundata).getUserId().getValue(),
          ALAccessControlConstants.POERTLET_FEATURE_DOCUMENT_FILE,
          ALAccessControlConstants.VALUE_ACL_DELETE);
      //ファイル編集権限の有無の取得
      //ロールで編集権限を持っているか
      boolean isEditableRole = aclhandler.hasAuthority((int) ALEipUtils.getALEipUser(rundata).getUserId().getValue(),
          ALAccessControlConstants.POERTLET_FEATURE_DOCUMENT_FILE,
          ALAccessControlConstants.VALUE_ACL_UPDATE);
      //ファイルの編集権限を持っているか
      boolean isEditableFile = getisEditableFile(record.getDocId().intValue());
      if (isEditableRole && isEditableFile) {
        isDocumentUpdate = true;
      }

      ArrayList readGroupList = new ArrayList();
      ArrayList readUserList = new ArrayList();
      ArrayList editGroupList = new ArrayList();
      ArrayList editUserList = new ArrayList();
      isMemberRead = false;
      isMemberEdit = false;
      
      Integer requestStatus = null;
      if("3".equals(record.getStatus())){
        // 追加申請・チェックイン申請時は申請中のアクセス権限を表示
        requestStatus = 1;
      } else {
        // その他の申請時は確定したアクセス権限を表示
        requestStatus = 0;
      }
      
      // 閲覧メンバーリストを取得
      getMemberFromMap(readGroupList, readUserList, record.getDocId().intValue(), Integer.valueOf(0), requestStatus);
      rd.setReadGroupList(readGroupList);
      rd.setReadUserList(readUserList);
      rd.setIsMemberRead(isMemberRead);
      
      // 編集メンバーリストを取得
      getMemberFromMap(editGroupList, editUserList, record.getDocId().intValue(), Integer.valueOf(1), requestStatus);
      rd.setEditGroupList(editGroupList);
      rd.setEditUserList(editUserList);
      rd.setIsMemberEdit(isMemberEdit);
      
      //チェックアウト者
      String checkoutUserName = "";
      if(record.getCheckoutUserId() != null && record.getCheckoutUserId() != -1){
         ALEipUser checkoutUser = ALEipUtils.getALEipUser(record.getCheckoutUserId()
          .intValue());
        if (checkoutUser != null) {
          checkoutUserName = checkoutUser.getAliasName().getValue();
        }
        rd.setCheckoutUser(checkoutUserName);
        rd.setCheckoutStatus(1);
      }else{
        rd.setCheckoutUser(null);
        rd.setCheckoutStatus(0);
      }
      //チェックアウト日
      rd.setCheckoutDate(ALDateUtil.format(record.getCheckoutDate(), "yyyy年M月d日"));

      //申請者
      String requestUserName = "";
      if(record.getRequestUserId() != null && record.getRequestUserId() != -1){
         ALEipUser requestUser = ALEipUtils.getALEipUser(record.getRequestUserId()
          .intValue());
        if (requestUser != null) {
          requestUserName = requestUser.getAliasName().getValue();
        }
        rd.setRequestUser(requestUserName);
        rd.setRequestStatus(1);
      }else{
        rd.setRequestUser(null);
        rd.setRequestStatus(0);
      }
      
      rd.setFileName(record.getFileName());
      rd.setFileSize(record.getFileSize().longValue());
      rd.setPosition(DocumentUtils.getFolderPosition(folder_hierarchy_list,
          record.getFolderId().intValue()));
      rd.setNote(record.getNote());
      rd.setisEditable((DocumentUtils.isEditableFolder(record.getFolderId(),
          rundata)));

      String createUserName = "";
      ALEipUser createUser = ALEipUtils.getALEipUser(record.getCreateUserId()
          .intValue());
      if (createUser != null) {
        createUserName = createUser.getAliasName().getValue();
      }
      rd.setCreateUser(createUserName);
      rd.setCreateDate(ALDateUtil.format(record.getCreateDate(), "yyyy年M月d日"));
      String updateUserName = "";
      ALEipUser updateUser = ALEipUtils.getALEipUser(record.getUpdateUserId()
          .intValue());
      if (updateUser != null) {
        updateUserName = updateUser.getAliasName().getValue();
      }
      rd.setUpdateUser(updateUserName);
      rd.setUpdateDate(ALDateUtil.format(record.getUpdateDate(), "yyyy年M月d日"));
      
      return rd;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * IMW_T_DOCUMENT_FILE_MAP から権限を持つグループリストとユーザリストを抽出します
   * 
   */
  protected boolean getMemberFromMap
  (ArrayList groupList, ArrayList userList, int docId, Integer editable, Integer requestStatus)
  {
    try{
      
      // 変数の宣言
      SelectQuery query;
      Expression exp, exp2, exp3;
      DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
      
      // グループのリストを取得
      query = new SelectQuery(ImwTDocumentFileMap.class);
      exp = ExpressionFactory.matchExp(
          ImwTDocumentFileMap.DOC_ID_PROPERTY, docId);
      exp2 = ExpressionFactory.matchExp(
          ImwTDocumentFileMap.EDITABLE_PROPERTY, editable);
      query.setQualifier(exp);
      query.andQualifier(exp2);
      if (requestStatus != null){
        exp3 = ExpressionFactory.matchExp(
            ImwTDocumentFileMap.REQUEST_STATUS_PROPERTY, requestStatus);
        query.andQualifier(exp3);
      }
      List glist = dataContext.performQuery(query);

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

      List users = new ArrayList();
      int usize = list.size();
      for (int i = 0; i < usize; i++) {
        ImwTDocumentFileMap map = (ImwTDocumentFileMap) list.get(i);
        users.add(map.getUserId());
      }
      query = new SelectQuery(TurbineUser.class);
      exp = ExpressionFactory.inDbExp(
          TurbineUser.USER_ID_PK_COLUMN, users);
      query.setQualifier(exp);
      userList.addAll(DocumentUtils.getUsersFromSelectQuery(query));
      
      return true;
    }
    catch (Exception ex){
      return false;
    }
  }
    
  /**
   * 関連文書ファイルリストの取得
   * @param query
   * @return リスト
   */
  public static List getRelFileSelectQuery(SelectQuery query) {
    List relList = new ArrayList();
    try {
      
      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      List glist = dataContext.performQuery(query);
      int size = glist.size();

      for (int i = 0; i < size; i++) {
        ImwTDocumentRelationMap record = (ImwTDocumentRelationMap) glist.get(i);
        DocumentFileRelationMap relMap = new DocumentFileRelationMap();
        relMap.initField();
        relMap.setFileID(record.getFileId());
        relMap.setFileName(record.getFileName());
        relList.add(relMap);
      }
    } catch (Exception ex) {
      logger.error("[DocumentSelectData]", ex);
    }
    return relList;
  }
  
  /**
   * ユーザがファイルの編集が可能か返します。\<BR>
   *
   * @param docid
   * @return true:編集可/false:編集不可
   */
  private boolean getisEditableFile(int docid) {
    
    //　文書管理システム管理者は無条件で編集可能
    if(isDocAdmin){
      return true;
    }
    
    List docidlist = new ArrayList();
    DataContext dataContext = DatabaseOrmService.getInstance()
        .getDataContext();
    SelectQuery query = new SelectQuery(ImwTDocumentFileMap.class);
    Expression exp1 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.USER_ID_PROPERTY,
        ALEipUtils.getALEipUser(rundata).getUserId().getValue());
    Expression exp2 = ExpressionFactory.inExp(
        ImwTDocumentFileMap.GROUP_ID_PROPERTY, getUserGroupId());
    Expression exp3 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.GROUP_ID_PROPERTY, -1);
    Expression exp4 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.EDITABLE_PROPERTY, 1);
    Expression exp5 = ExpressionFactory.matchExp(
        ImwTDocumentFileMap.DOC_ID_PROPERTY, docid);
    query.setQualifier(exp1.orExp(exp2).orExp(exp3));
    query.andQualifier(exp4);
    query.andQualifier(exp5);
    List maplist = dataContext.performQuery(query);
    if(maplist.size() > 0){
      return true;
    }
    return false;
  }
  
  public List getRelList() {
    return relList;
  }

  public ArrayList getFolderHierarchyList() {
    return folder_hierarchy_list;
  }

  public FolderInfo getSelectedFolderInfo() {
    return selected_folderinfo;
  }

  /**
   * @see com.aimluck.eip.common.ALAbstractSelectData#getColumnMap()
   */
  protected Attributes getColumnMap() {
    Attributes map = new Attributes();
//    map.putValue("file_title", ImwTDocumentFile.FILE_TITLE_PROPERTY);
//    map.putValue("file_name", ImwTDocumentFile.FILE_NAME_PROPERTY);
//    map.putValue("file_rev", ImwTDocumentFile.FILE_REV_MJ_PROPERTY);
//    map.putValue("update_date", ImwTDocumentFile.UPDATE_DATE_PROPERTY);
//    map.putValue("file_size", ImwTDocumentFile.FILE_SIZE_PROPERTY);
//    //チェックアウトユーザ名のソートにはユーザの苗字カナを指定
//    map.putValue("checkout_user", ImwTDocumentFile.TURBINE_USER_PROPERTY
//        + "." + TurbineUser.LAST_NAME_KANA_PROPERTY);
    return map;
  }

  /**
   *
   * @param id
   * @return
   */
  public boolean isMatch(int id1, long id2) {
    return id1 == (int) id2;
  }

  /**
   * ファイル総数を取得する． <BR>
   *
   * @return
   */
  public int getFileSum() {
    return fileSum;
  }

  /**
   * アクセス権限チェック用メソッド。<br />
   * アクセス権限の機能名を返します。
   *
   * @return
   */
  public String getAclPortletFeature() {
    return ALAccessControlConstants.POERTLET_FEATURE_DOCUMENT_FILE;
  }

  public boolean isAccessible() {
    return isAccessible;
  }

  public boolean isEditable() {
    return isEditable;
  }

  public void setEditable(boolean isEditable) {
    this.isEditable = isEditable;
  }

  public boolean isDocumentDelete() {
    return isDocumentDelete;
  }

  public boolean isDocumentUpdate() {
    return isDocumentUpdate;
  }

  public boolean getIsDocWorkflowCoop() {
    return DocumentUtils.isDocWorkflowCoop();
  }
  
  public boolean getIsDocAdmin() {
    return this.isDocAdmin;
  }

  /**
   * 指定ユーザをセッションに設定する．
   * 
   * @param rundata
   * @param context
   * @throws ALDBErrorException
   */
  private void setupLists(RunData rundata, Context context) {
    userList = ALEipUtils.getUsers("LoginUser");

    if (userList == null || userList.size() == 0) {
      target_user_id = "";
      ALEipUtils.removeTemp(rundata, context, "target_user_id");
      return;
    }

    target_user_id = Integer.toString(ALEipUtils.getUserId(rundata));
  }

  /**
   * 表示切り替え時に指定するユーザ ID
   * 
   * @return
   */
  public String getTargetUserId() {
    // ログインユーザの ID を設定する．
    return target_user_id;
  }

  /**
   * ユーザの一覧を取得する．
   * 
   * @param groupname
   * @return
   */
  public List getUsers() {
    return userList;
  }
  
  
  /**
  *
  * @param rundata
  * @param context
  */
 public void loadRouteList(RunData rundata, Context context) {
   routeList = WorkflowUtils.loadRouteList(rundata, context);
 }
 
  /**
   * 申請経路一覧を取得します。 <BR>
   *
   * @return
   */
  public List getRouteList() {
    return routeList;
  }

  public void setRouteList(List routeList) {
    this.routeList = routeList;
  }

  public ALNumberField getRouteId() {
    return route_id;
  }

  public void setRouteId(ALNumberField route_id) {
    this.route_id = route_id;
  }

  public ALStringField getRoute() {
    return route;
  }

  public void setRoute(ALStringField route) {
    this.route = route;
  }

  public boolean getIsSavedRoute() {
    return is_saved_route;
  }

  public void setIsSavedRoute(boolean is_saved_route) {
    this.is_saved_route = is_saved_route;
  }
  
  public String getRouteH() {
    StringBuffer routeun = new StringBuffer();
    String username;

    if (route.getValue() != null && !"".equals(route.getValue())) {
      StringTokenizer st = new StringTokenizer(route.getValue(), ",");
      while (st.hasMoreTokens()) {
        username = WorkflowUtils.getName(st.nextToken());
        routeun.append(username);
        routeun.append(" -> ");
      }
      routeun.append("完了");

      return routeun.toString();
    }
    return "";
  }
  
  /**
   * グループメンバーを取得します。 <BR>
   *
   * @return
   */
  public List getWorkflowMemberList() {
    return workflowMemberList;
  }
  
}
