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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
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 org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import org.apache.turbine.services.upload.TurbineUpload;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.eip.cayenne.om.portlet.AvzTIntramail;
import com.aimluck.eip.cayenne.om.portlet.AvzTIntramailFile;
import com.aimluck.eip.cayenne.om.portlet.AvzTIntramailMap;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTIntramail;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTIntramailFile;
import com.aimluck.eip.cayenne.om.portlet.auto._AvzTIntramailMap;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.fileupload.beans.FileuploadBean;
import com.aimluck.eip.fileupload.util.FileuploadUtils;
import com.aimluck.eip.intramail.IntraMailDetailResultData;
import com.aimluck.eip.intramail.beans.FileuploadLiteBean;
import com.aimluck.eip.intramail.beans.ReceiveUserBean;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.orm.query.ResultList;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.util.orgutils.ALOrgUtilsFactoryService;
import com.aimluck.eip.util.orgutils.ALOrgUtilsHandler;

/**
 * IntraMailのユーティリティクラスです。 <BR>
 * 
 */
public class IntraMailUtils {

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

  /** 件名の最大文字数 */
  public static final int FIELD_SUBJECT_MAX_LEN = 256;

  /** メール本文の最大文字数 */
  public static final int FIELD_BODY_MAX_LEN = 50000;

  /** 本文＋添付ファイルの最大長（kbyte） */
  public static final int MAIL_MAX_LEN = 7000;

  public static final String DRAFT_EDIT_FORM = "1";

  public static final String TRANSMISSION_CLS_SEND = "S";

  public static final String TRANSMISSION_CLS_RECEIVE = "R";

  public static final String DISABLED = "T";

  public static final String AVAILABLE = "F";

  public static final String READ_FLG_UNREAD = "F";

  public static final String READ_FLG_READ = "T";

  public static final String VIEW_FLG_VISIBLE = "T";

  public static final String VIEW_FLG_INVISIBLE = "F";

  public static final String MAIL_TYPE_REPLY = "1";

  public static final String MAIL_TYPE_ALL_REPLY = "2";

  public static final String MAIL_TYPE_FORWARD = "3";

  public static final String HEADER_ORIGINAL_MESSAGE =
    "\n\n------Original Message-------\n";

  public static final String PREFIX_REPLY = "Re:";

  public static final String PREFIX_FORWARD = "Fwd:";

  public static final String NO_TITLE = "[無題]";

  public static final String DATE_TIME_FORMAT =
    ALDateTimeField.DEFAULT_DATE_TIME_FORMAT;

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

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

  /**
   * AvzTIntramail オブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static AvzTIntramail getAvzTIntramail(RunData rundata, Context context)
      throws ALPageNotFoundException {

    try {
      String intramail_id =
        ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);
      if (intramail_id == null || Integer.valueOf(intramail_id) == null) {
        logger.debug("[AvzTIntramail] Empty ID...");
        return null;
      }

      SelectQuery<AvzTIntramail> query = Database.query(AvzTIntramail.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          intramail_id);

      query.setQualifier(exp1);

      ResultList<AvzTIntramail> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list.get(0);

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

  /**
   * AvzTIntramailMap取得処理
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static AvzTIntramailMap getAvzTIntramailMap(RunData rundata,
      Context context) {

    String map_id =
      ALEipUtils.getTemp(rundata, context, ALEipConstants.ENTITY_ID);

    try {
      if (map_id == null || Integer.valueOf(map_id) == null) {
        logger.debug("[AvzTIntramailMap] Empty ID...");
        return null;
      }

      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(_AvzTIntramailMap.ID_PK_COLUMN, map_id);

      query.setQualifier(exp1);

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list.get(0);

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

  /**
   * AvzTIntramailMap取得処理
   * 
   * @param mail_id
   * @param user_id
   * @param unread
   * @return
   */
  public static AvzTIntramailMap getAvzTIntramailMap(int mail_id, int user_id,
      boolean unread) {
    try {
      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailMap.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);

      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(_AvzTIntramailMap.USER_ID_PROPERTY, user_id);
      query.andQualifier(exp2);

      Expression exp3 =
        ExpressionFactory.matchExp(
          _AvzTIntramailMap.TRANSMISSION_CLS_PROPERTY,
          TRANSMISSION_CLS_RECEIVE);
      query.andQualifier(exp3);

      if (unread) {
        Expression exp4 =
          ExpressionFactory.matchExp(
            _AvzTIntramailMap.READ_FLG_PROPERTY,
            READ_FLG_UNREAD);
        query.andQualifier(exp4);
      }

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list.get(0);

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

  /**
   * AvzTIntramailMap取得処理
   * 
   * @param mail_id
   * @return
   */
  public static ResultList<AvzTIntramailMap> getAvzTIntramailMap(int mail_id) {

    try {
      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailMap.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);
      query.setQualifier(exp1);

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list;

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

  /**
   * 有効な（論理削除されていない）AvzTIntramailMapを取得する。
   * 
   * @param mail_id
   * @return
   */
  public static List<AvzTIntramailMap> getAvzTIntramailMapInAvailable(
      int mail_id) {

    try {
      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailMap.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);
      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(
          _AvzTIntramailMap.DISABLED_PROPERTY,
          AVAILABLE);
      query.andQualifier(exp2);

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list;

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

  /**
   * AvzTIntramailMap取得処理
   * 
   * @param mail_id
   * @param t_class
   * @return
   */
  public static ResultList<AvzTIntramailMap> getAvzTIntramailMap(int mail_id,
      String t_class) {

    try {
      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailMap.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);
      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(
          _AvzTIntramailMap.TRANSMISSION_CLS_PROPERTY,
          t_class);
      query.andQualifier(exp2);

      query.orderDesending(_AvzTIntramailMap.UPDATE_DATE_PROPERTY);

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }
      return list;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

  /**
   * AvzTIntramailMap取得処理(親ID, ユーザーID, 種別指定）
   * 
   * @param mail_id
   * @param t_class
   * @return
   */
  public static AvzTIntramailMap getAvzTIntramailMap(int mail_id, int user_id,
      String t_class) {

    try {
      SelectQuery<AvzTIntramailMap> query =
        Database.query(AvzTIntramailMap.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailMap.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);
      query.setQualifier(exp1);

      Expression exp2 =
        ExpressionFactory.matchExp(
          _AvzTIntramailMap.TRANSMISSION_CLS_PROPERTY,
          t_class);
      query.andQualifier(exp2);

      Expression exp3 =
        ExpressionFactory.matchExp(_AvzTIntramailMap.USER_ID_PROPERTY, user_id);
      query.andQualifier(exp3);

      ResultList<AvzTIntramailMap> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list.get(0);

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

  /**
   * AvzTIntramailFile取得処理
   * 
   * @param mail_id
   * @return
   */
  public static ResultList<AvzTIntramailFile> getAvzTIntramailFiles(int mail_id) {

    try {
      SelectQuery<AvzTIntramailFile> query =
        Database.query(AvzTIntramailFile.class);
      Expression exp1 =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailFile.TO_AVZ_TINTRAMAIL_PROPERTY
            + "."
            + _AvzTIntramail.INTRAMAIL_ID_PK_COLUMN,
          mail_id);
      query.setQualifier(exp1);

      ResultList<AvzTIntramailFile> list = query.getResultList();
      if (list == null || list.size() == 0) {
        logger.debug("[IntraMailUtils] Not found ID...");
        return null;
      }

      return list;

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

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

      }

      SelectQuery<AvzTIntramailFile> query =
        Database.query(AvzTIntramailFile.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailFile.FILE_ID_PK_COLUMN,
          Integer.valueOf(attachmentIndex));
      query.andQualifier(exp);
      ResultList<AvzTIntramailFile> files = query.getResultList();
      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();
    }
  }

  /**
   * ファイルオブジェクトモデルを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  public static AvzTIntramailFile getAvzTIntramailFile(int file_id)
      throws ALDBErrorException {
    try {
      SelectQuery<AvzTIntramailFile> query =
        Database.query(AvzTIntramailFile.class);
      Expression exp =
        ExpressionFactory.matchDbExp(
          _AvzTIntramailFile.FILE_ID_PK_COLUMN,
          file_id);
      query.andQualifier(exp);
      ResultList<AvzTIntramailFile> files = query.getResultList();
      if (files == null || files.size() == 0) {
        return null;
      }
      return files.get(0);
    } catch (Exception ex) {
      logger.error("[WorkflowUtils]", ex);
      throw new ALDBErrorException();
    }
  }

  /**
   * 依頼の詳細情報を取得する。
   * 
   * @param rundata
   * @param context
   */
  public static Object getResultDataDetail(Object obj, int user_id,
      String t_class) {

    try {
      AvzTIntramail mail = (AvzTIntramail) obj;
      IntraMailDetailResultData rd = new IntraMailDetailResultData();
      rd.initField();
      rd.setMailId(mail.getIntramailId().toString());

      if (t_class != null) {
        AvzTIntramailMap tmp_map =
          IntraMailUtils.getAvzTIntramailMap(
            mail.getIntramailId(),
            user_id,
            t_class);

        if (tmp_map != null) {
          rd.setMapId(String.valueOf(tmp_map.getId()));
        }
      }

      rd.setSubject(mail.getSubject());
      rd.setBody(mail.getBody());
      rd.setPerson(ALEipUtils.getUserFullName(mail.getOwnerId()));
      rd.setDest(getDestNames(mail));
      rd.setReceiveUserBeans(getReceiveUserBeans(mail));

      rd.setCreateDate(IntraMailUtils.translateDate(
        mail.getCreateDate(),
        "yyyy年M月d日"));
      rd.setUpdateDate(IntraMailUtils.translateDate(
        mail.getUpdateDate(),
        "yyyy年M月d日H時m分"));

      // ファイルリスト
      List<AvzTIntramailFile> list =
        getAvzTIntramailFiles(mail.getIntramailId());
      if (list != null && list.size() > 0) {
        List<FileuploadBean> attachmentFileList =
          new ArrayList<FileuploadBean>();
        FileuploadBean filebean = null;
        AvzTIntramailFile file = null;
        int lsize = list.size();
        for (int i = 0; i < lsize; i++) {
          file = list.get(i);
          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);
      }

      AvzTIntramailMap map =
        getAvzTIntramailMap(mail.getIntramailId(), user_id, true);
      if (map != null) {
        // 社内メールポートレットの既読処理
        map.setReadFlg(READ_FLG_READ);
        map.setUpdateDate(Calendar.getInstance().getTime());

        // 新着ポートレットの既読処理
        IntraMailWhatsNewUtils.shiftWhatsNewReadFlag(
          IntraMailWhatsNewUtils.WHATS_NEW_TYPE_INTRAMAIL,
          mail.getIntramailId(),
          user_id);
        Database.commit();
      }

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

  // public static String getDestNames(AvzTIntramail mail) {
  // List<AvzTIntramailMap> maps = mail.getAvzTIntramailMapArray();
  //   
  // StringBuffer buf = new StringBuffer();
  //    
  // int cnt = 0;
  // for( AvzTIntramailMap map : maps ) {
  // if( "S".equals(map.getTransmissionCls())) {
  // continue;
  // }
  // buf.append(ALEipUtils.getUserFullName(map.getUserId()));
  // //buf.append(" ");
  // cnt++;
  // if( cnt>0 ) {
  // buf.append(",・・・");
  // break;
  // }
  //      
  // }
  // return buf.toString();
  // }

  /**
   * 宛先ユーザー（ｓ）を取得します。
   */
  public static String getDestNames(AvzTIntramail mail) {
    List<AvzTIntramailMap> maps =
      getAvzTIntramailMap(mail.getIntramailId(), TRANSMISSION_CLS_RECEIVE);
    StringBuffer buf = new StringBuffer();
    if (maps != null) {
      for (AvzTIntramailMap map : maps) {
        buf.append(ALEipUtils.getUserFullName(map.getUserId()));
        buf.append("　");
      }
    }
    return buf.toString();
  }

  /**
   * 詳細画面での宛先リスト表示用データの生成を行ないます。
   * 
   * @param mail
   * @return
   */
  public static List<ReceiveUserBean> getReceiveUserBeans(AvzTIntramail mail) {
    List<AvzTIntramailMap> maps =
      getAvzTIntramailMap(mail.getIntramailId(), TRANSMISSION_CLS_RECEIVE);
    List<ReceiveUserBean> beans = new ArrayList<ReceiveUserBean>();
    if (maps != null) {
      for (AvzTIntramailMap map : maps) {
        ReceiveUserBean b = new ReceiveUserBean();
        b.setUserId(map.getUserId());
        b.setUserName(ALEipUtils.getUserFullName(map.getUserId()));
        b.setRead(READ_FLG_READ.equals(map.getReadFlg()));
        b.setUpdateDate(IntraMailUtils.translateDate(
          map.getUpdateDate(),
          "yyyy年M月d日H時m分"));
        beans.add(b);
      }
    }
    return beans;
  }

  /**
   * 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);
  }

  /**
   * 添付ファイル登録処理
   * 
   * @param rundata
   * @param context
   * @param request
   * @param oldrequest
   * @param fileuploadList
   * @param folderName
   * @param msgList
   * @return
   */
  public static boolean insertFileDataDelegate(RunData rundata,
      Context context, AvzTIntramail request,
      List<FileuploadLiteBean> fileuploadList, String folderName,
      List<String> msgList) {

    if (!checkFileSize(
      rundata,
      context,
      request,
      fileuploadList,
      folderName,
      msgList)) {
      // msgList.add("全容量が 7MB を超過した社内メールは送信できません。");
      return false;
    }

    int file_volume = 0;
    if (request.getMailVolume() != null) {
      file_volume = request.getMailVolume();
    }

    DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
    int uid = ALEipUtils.getUserId(rundata);
    String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);

    SelectQuery<AvzTIntramailFile> query =
      Database.query(AvzTIntramailFile.class);
    query.andQualifier(ExpressionFactory.matchDbExp(
      _AvzTIntramailFile.TO_AVZ_TINTRAMAIL_PROPERTY,
      request.getIntramailId()));
    if (fileuploadList != null) {
      for (FileuploadLiteBean bean : fileuploadList) {
        if (bean.isNewFile()) {
          continue;
        }
        Expression exp =
          ExpressionFactory.matchDbExp(
            _AvzTIntramailFile.FILE_ID_PK_COLUMN,
            bean.getFileId());
        query.andQualifier(exp.notExp());
      }
    }
    // DB上でトピックに属すが、送られてきたFileIDにIDが含まれていないファイルのリスト(削除されたファイルのリスト)
    ResultList<AvzTIntramailFile> delFiles = query.getResultList();

    if (delFiles.size() > 0) {
      // ローカルファイルに保存されているファイルを削除する．
      File file = null;
      int delsize = delFiles.size();
      for (int i = 0; i < delsize; i++) {
        file =
          new File(getSaveDirPath(org_id, uid)
            + (delFiles.get(i)).getFilePath());
        if (file.exists()) {
          file_volume -= file.length() / 1024;
          // System.out.println("★削除ファイルサイズ＝" + file_volume);
          file.delete();
        }
      }
      // データベースから添付ファイルのデータ削除
      Database.deleteAll(delFiles);
    }

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

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

        if (!filebean.isNewFile()) {
          continue;
        }

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

        String filename =
          FileuploadUtils.getNewFileName(getSaveDirPath(org_id, uid));

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

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

        file_volume += destFile.length() / 1024;

        // System.out.println("★追加ファイルサイズ＝" + file_volume);

        srcFile = null;
        destFile = null;
      }

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

      request.setMailVolume(file_volume);

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

  /**
   * 添付ファイルの合計容量が、制限値を超過していないかをチェックします。
   * 
   * @param rundata
   * @param context
   * @param request
   * @param oldrequest
   * @param fileuploadList
   * @param folderName
   * @param msgList
   * @return 制限値オーバー：false
   */
  public static boolean checkFileSize(RunData rundata, Context context,
      AvzTIntramail request, List<FileuploadLiteBean> fileuploadList,
      String folderName, List<String> msgList) {

    int file_volume = 0;
    if (request.getMailVolume() != null) {
      file_volume = request.getMailVolume();
    }

    // 本文のバイト数を加算
    // int body_length = request.getBody().getBytes().length / 1024;
    // file_volume += body_length;

    int uid = ALEipUtils.getUserId(rundata);
    String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);

    SelectQuery<AvzTIntramailFile> query =
      Database.query(AvzTIntramailFile.class);
    query.andQualifier(ExpressionFactory.matchDbExp(
      _AvzTIntramailFile.TO_AVZ_TINTRAMAIL_PROPERTY,
      request.getIntramailId()));
    if (fileuploadList != null) {
      for (FileuploadLiteBean bean : fileuploadList) {
        if (bean.isNewFile()) {
          continue;
        }
        Expression exp =
          ExpressionFactory.matchDbExp(
            _AvzTIntramailFile.FILE_ID_PK_COLUMN,
            bean.getFileId());
        query.andQualifier(exp.notExp());
      }
    }
    // DB上でトピックに属すが、送られてきたFileIDにIDが含まれていないファイルのリスト(削除されたファイルのリスト)
    ResultList<AvzTIntramailFile> delFiles = query.getResultList();

    if (delFiles.size() > 0) {
      // ローカルファイルに保存されているファイルを削除する．
      File file = null;
      int delsize = delFiles.size();
      for (int i = 0; i < delsize; i++) {
        file =
          new File(getSaveDirPath(org_id, uid)
            + (delFiles.get(i)).getFilePath());
        if (file.exists()) {
          file_volume -= file.length() / 1024;
          // System.out.println("★削除ファイルサイズ＝" + file_volume);
        }
      }
    }

    // 追加ファイルが無ければtrueを返して終了
    if (fileuploadList == null || fileuploadList.size() <= 0) {
      // System.out.println("★総ファイルサイズ＝" + file_volume);
      return true;
    }

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

        filebean = fileuploadList.get(i);

        if (!filebean.isNewFile()) {
          continue;
        }

        // String filename =
        // FileuploadUtils.getNewFileName(getSaveDirPath(org_id, uid));

        // ファイルの移動
        File srcFile =
          getAbsolutePath(org_id, uid, folderName, filebean.getFileId());

        file_volume += srcFile.length() / 1024;

        // System.out.println(srcFile.getName() + " " +srcFile.length()/1024 +
        // "：★追加ファイルサイズ＝" + file_volume);

        srcFile = null;
      }
      // System.out.println("★★総ファイルサイズ＝" + file_volume);

    } catch (Exception e) {
      e.printStackTrace();
      logger.error("Exception", e);
      msgList.add("容量チェック中にエラーが発生しました。システム管理者へ連絡下さい。");
      return false;
    }
    if (file_volume > TurbineUpload.getSizeMax() / 1024) {
      msgList.add("添付ファイル容量が"
        + TurbineUpload.getSizeMax()
        / 1024
        / 1024
        + "MB を超過した社内メールは送信できません。現容量=["
        + file_volume
        + "]KB");
      return false;
    }

    return true;
  }

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

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

  /**
   * 保存されている添付ファイルへのフルパス
   * 
   * @param org_id
   * @param userId
   * @param folderName
   * @param fileid
   * @return
   */
  public static File getAbsolutePath(String org_id, int userId,
      String folderName, String fileid) {
    File folder = FileuploadUtils.getFolder(org_id, userId, folderName);
    return new File(folder.getAbsolutePath() + File.separator + fileid);
  }

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

  // public static int getFileVolume(RunData rundata,
  // Context context, AvzTIntramail mail) {
  // int size = 0;
  // DataContext dataContext =
  // DatabaseOrmService.getInstance().getDataContext();
  // int uid = ALEipUtils.getUserId(rundata);
  // String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
  //    
  // SelectQuery query = new SelectQuery(AvzTIntramailFile.class);
  // query.andQualifier(ExpressionFactory
  // .matchDbExp(_AvzTIntramailFile.TO_AVZ_TINTRAMAIL_PROPERTY,
  // mail.getIntramailId()));
  // List<AvzTIntramailFile> files = dataContext.performQuery(query);
  // for( AvzTIntramailFile f : files ) {
  // String filename = f.getFilePath();
  // File destFile = new File(getAbsolutePath(org_id, uid,
  // filename));
  // System.out.println(destFile.getAbsolutePath());
  // }
  //    
  // return size;
  // }

  /**
   * 削除リクエストの対象のAvzTIntramailMapが最後の有効レコードかを判定する。
   * 
   * @param entity
   * @return 最後の有効レコードの場合：true
   */
  public static boolean isLastRecord(AvzTIntramailMap entity) {
    int mail_id = entity.getToAvzTIntramail().getIntramailId();
    List<AvzTIntramailMap> list =
      IntraMailUtils.getAvzTIntramailMapInAvailable(mail_id);
    if (list == null || list.size() == 1) {
      return true;
    }
    return false;
  }

  /**
   * AvzTIntramailの削除、AvzTIntramailMapの削除（PostgresのCASCADE指定による）、 添付ファイルの削除を行なう。
   * 
   * @param entity
   */
  public static void deleteAvzTIntramail(RunData rundata, Context context,
      AvzTIntramail entity) {

    String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
    int login_user_id = entity.getOwnerId();

    // ファイル削除処理
    List<String> fpaths = new ArrayList<String>();
    SelectQuery<AvzTIntramailFile> query =
      Database.query(AvzTIntramailFile.class);
    query.andQualifier(ExpressionFactory.matchDbExp(
      _AvzTIntramailFile.TO_AVZ_TINTRAMAIL_PROPERTY,
      entity.getIntramailId()));
    ResultList<AvzTIntramailFile> files = query.getResultList();
    if (files != null && files.size() > 0) {
      int fsize = files.size();
      for (int j = 0; j < fsize; j++) {
        fpaths.add((files.get(j)).getFilePath());
      }
    }

    if (fpaths.size() > 0) {
      // ローカルファイルに保存されているファイルを削除する．
      File file = null;
      int fsize = fpaths.size();
      for (int i = 0; i < fsize; i++) {
        file =
          new File(IntraMailUtils.getSaveDirPath(org_id, login_user_id)
            + fpaths.get(i));
        if (file.exists()) {
          file.delete();
        }
      }
    }
    // リクエストを削除
    Database.delete(entity);
  }

  /**
   * 添付ファイルを取得します。
   * 
   * @param rundata
   * @param migrate
   *            [返信][全員へ返信][転送]に伴うファイルのコピー：true
   * @return
   */
  public static List<FileuploadLiteBean> getFileuploadList(RunData rundata,
      boolean migrate) {
    String[] fileids =
      rundata
        .getParameters()
        .getStrings(FileuploadUtils.KEY_FILEUPLOAD_ID_LIST);
    if (fileids == null) {
      return null;
    }

    List<String> hadfileids = new ArrayList<String>();
    List<String> newfileids = new ArrayList<String>();

    for (int j = 0; j < fileids.length; j++) {
      if (fileids[j].trim().startsWith("s")) {
        if (!migrate) {
          hadfileids.add(fileids[j].trim().substring(1));
        } else {
          // 元メールのファイルを一時ファイルに配置してあるので、それらを新規ファイルとして扱う。
          newfileids.add(fileids[j].trim());
        }
      } else {
        newfileids.add(fileids[j].trim());
      }
    }

    List<FileuploadLiteBean> fileNameList = new ArrayList<FileuploadLiteBean>();
    FileuploadLiteBean filebean = null;
    String fileid = null;

    // 新規にアップロードされたファイルの処理
    if (newfileids.size() > 0) {
      String folderName =
        rundata.getParameters().getString(
          FileuploadUtils.KEY_FILEUPLOAD_FODLER_NAME);
      if (folderName == null || folderName.equals("")) {
        return null;
      }

      String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
      File folder =
        FileuploadUtils.getFolder(
          org_id,
          ALEipUtils.getUserId(rundata),
          folderName);
      String folderpath = folder.getAbsolutePath();

      int length = newfileids.size();
      for (int i = 0; i < length; i++) {
        if (newfileids.get(i) == null || newfileids.get(i).equals("")) {
          continue;
        }

        fileid = newfileids.get(i);

        BufferedReader reader = null;
        try {
          reader =
            new BufferedReader(new InputStreamReader(new FileInputStream(
              folderpath
                + File.separator
                + fileid
                + FileuploadUtils.EXT_FILENAME), FileuploadUtils.FILE_ENCODING));
          String line = reader.readLine();
          if (line == null || line.length() <= 0) {
            continue;
          }

          filebean = new FileuploadLiteBean();
          filebean.initField();
          filebean.setFolderName(fileids[i]);
          filebean.setFileId(String.valueOf(fileid));
          filebean.setFileName(line);
          fileNameList.add(filebean);
        } catch (Exception e) {
          logger.error("Exception", e);
        } finally {
          try {
            reader.close();
          } catch (Exception e) {
            logger.error("Exception", e);
          }
        }
      }
    }

    if (hadfileids.size() > 0) {
      // すでにあるファイルの処理
      List<String> hadfileidsValue = new ArrayList<String>();
      for (int k = 0; k < hadfileids.size(); k++) {
        fileid = hadfileids.get(k);
        hadfileidsValue.add(fileid);
      }

      try {
        // valueを元にDBを検索
        SelectQuery<AvzTIntramailFile> reqquery =
          Database.query(AvzTIntramailFile.class);
        Expression reqexp1 =
          ExpressionFactory.inDbExp(
            _AvzTIntramailFile.FILE_ID_PK_COLUMN,
            hadfileidsValue);
        reqquery.setQualifier(reqexp1);
        ResultList<AvzTIntramailFile> requests = reqquery.getResultList();
        int requestssize = requests.size();
        for (int i = 0; i < requestssize; i++) {
          AvzTIntramailFile file = requests.get(i);
          filebean = new FileuploadLiteBean();
          filebean.initField();
          filebean.setFileId(file.getFileId().toString());
          filebean.setFileName(file.getFileName());
          filebean.setFlagNewFile(false);
          fileNameList.add(filebean);
        }
      } catch (Exception ex) {
        logger.error("[IntraMailUtils] Exception.", ex);
      }
    }
    return fileNameList;
  }
}
