/*
 * 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.mail;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.jar.Attributes;

import javax.mail.Address;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;

import org.apache.cayenne.CayenneRuntimeException;
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.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.eip.cayenne.om.portlet.AvzTMailSend;
import com.aimluck.eip.cayenne.om.portlet.EipMAddressbook;
import com.aimluck.eip.cayenne.om.portlet.EipMMailAccount;
import com.aimluck.eip.cayenne.om.portlet.EipTMail;
import com.aimluck.eip.cayenne.om.portlet.EipTMailFilter;
import com.aimluck.eip.cayenne.om.portlet.EipTMailFolder;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.mail.beans.ALMailSearchCondition;
import com.aimluck.eip.mail.util.ALAttachmentsExtractor;
import com.aimluck.eip.mail.util.ALMailUtils;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.ResultList;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.query.ALAvzTMailSendDirectSelectQuery;
import com.aimluck.eip.query.ALEipTMailDirectSelectQuery;
import com.aimluck.eip.services.storage.ALStorageService;
import com.aimluck.eip.util.ALEipUtils;
import com.sk_jp.mail.MailUtility;
import com.sk_jp.mail.MultipartUtility;

/**
 * 送受信したメールを保持するローカルフォルダの抽象クラスです。 <br />
 * 
 */
public abstract class ALAbstractFolder implements ALFolder {

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

  /** 受信 or 送信 */
  protected int type_mail = -1;

  protected String org_id;

  protected int user_id;

  protected int account_id;

  /** ルートフォルダのフルパス */
  protected String rootFolderPath = null;

  /** カテゴリキー（mail） */
  protected String categoryKey = null;

  /** 表示行数 */
  private int rows_num = 10;

  /** 表示文字数 */
  private int strlen = 0;

  /** 開始位置 */
  private int start;

  /** 総件数 */
  private int count;

  /** 総ページ数 */
  private int pages_num = 1;

  /** 現在のページ */
  private int current_page = 1;

  /** 現在のソート */
  private String current_sort;

  /** 現在のソートタイプ （asc:昇順、desc:降順） */
  private String current_sort_type;

  protected final String LIST_SORT_STR = new StringBuffer().append(this.getClass().getName()).append(ALEipConstants.LIST_SORT).toString();

  protected final String LIST_SORT_TYPE_STR = new StringBuffer().append(this.getClass().getName()).append(ALEipConstants.LIST_SORT_TYPE).toString();

  // add by motegi for 全文検索
  /** 本文検索ワード */
  protected String searchWord;

  /** 件名検索ワード */
  protected String searchSubjectWord;

  /** 差出人／受取人検索ワード */
  protected String searchAddressWord;

  /** サブフォルダも含む */
  protected String includeSubFolder;

  // add end

  // add start 運用フェーズ障害128
  private static final String KEYWORD_NULL_ERROR = "invalid byte sequence for encoding \"UTF8\": 0x00";

  // add end

  /**
   * コンストラクタ
   * 
   * @param parentFolder
   *            親フォルダ
   * @param folderName
   *            自身のフォルダ名
   */
  public ALAbstractFolder(int type_mail, String org_id, int user_id, int account_id) {
    this.type_mail = type_mail;
    this.org_id = org_id;
    this.user_id = user_id;
    this.account_id = account_id;
  }

  // add by motegi start 全文検索
  public ALAbstractFolder(int type_mail, String org_id, int user_id, int account_id, ALMailSearchCondition cond) {
    this.type_mail = type_mail;
    this.org_id = org_id;
    this.user_id = user_id;
    this.account_id = account_id;
    this.searchWord = cond.getSearchWord();
    this.searchSubjectWord = cond.getSearchSubjectWord();
    this.searchAddressWord = cond.getSearchAddressWord();
    this.includeSubFolder = cond.getIncludeSubFolder();
  }

  // add end

  protected void init(RunData rundata, Context context) {
    if (rundata.getParameters().containsKey(ALEipConstants.LIST_SORT)) {
      ALEipUtils.setTemp(rundata, context, LIST_SORT_STR, rundata.getParameters().getString(ALEipConstants.LIST_SORT));
    }

    if (rundata.getParameters().containsKey(ALEipConstants.LIST_SORT_TYPE)) {
      ALEipUtils.setTemp(rundata, context, LIST_SORT_TYPE_STR, rundata.getParameters().getString(ALEipConstants.LIST_SORT_TYPE));
    }

    if (rundata.getParameters().containsKey(ALEipConstants.LIST_START)) {
      current_page = rundata.getParameters().getInt(ALEipConstants.LIST_START);
    }
  }

  // change start 運用フェーズ障害128
  // protected boolean insertMailToDB(MimeMessage mimeMessage, String filePath,
  // boolean saveContents, boolean isRead) throws Throwable {
  protected boolean insertMailToDB(MimeMessage mimeMessage, String filePath, boolean saveContents, boolean isRead, boolean convertNull) throws Throwable {
    // change end
    try {
      // EipTMail email = Database.create(EipTMail.class);

      if (saveContents) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        mimeMessage.writeTo(output);
      } else {
        Session session = Session.getDefaultInstance(new Properties());
        Message newMsg = new MimeMessage(session);
        Enumeration<?> headers = mimeMessage.getAllHeaders();
        while (headers.hasMoreElements()) {
          Header h = (Header) headers.nextElement();
          newMsg.addHeader(h.getName(), h.getValue());
        }
        newMsg.setText("メールのサイズが7MBを超えていたため、このメールを受信できませんでした。\r\n 誠に恐れ入りますが、別のメーラーで受信してください。");
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        newMsg.writeTo(output);
      }

      String subject;
      Address[] presonAddress;
      Address[] receiveAddress;
      String preson;
      Date sentDate = null;

      // 件名
      subject = mimeMessage.getHeader(ALLocalMailMessage.SUBJECT, null);
      if (subject == null) {
        subject = MailUtility.encodeWordJIS("無題");
      } else {
        subject = subject.replaceAll("\r", "");
        subject = subject.replaceAll("\n", "");
      }

      String type0 = (ALFolder.TYPE_RECEIVE == type_mail) ? "R" : "S";

      // 差出人 or 受取人
      if ("R".equals(type0)) {
        try {
          presonAddress = mimeMessage.getFrom();
        } catch (MessagingException ex) {
          presonAddress = null;
        }
      } else {
        try {
          presonAddress = mimeMessage.getAllRecipients();
        } catch (MessagingException ex) {
          presonAddress = null;
        }
      }

      try {
        receiveAddress = mimeMessage.getAllRecipients();
      } catch (MessagingException ex) {
        // change start 受入テスト障害292 Undisclosed-Recipient:;の場合にnullになるのに対応
        // receiveAddress = null;
        receiveAddress = new Address[0];
        // change end
      }

      if (presonAddress != null && presonAddress.length > 0) {
        // change start 2011.11.18
        // String personaladdr =
        // ALMailUtils.getOneString(ALMailUtils.getTokens(presonAddress[0]
        // .toString(), ALMailUtils.CR), "");
        // try {
        // preson = MailUtility.decodeText(personaladdr);
        // if (presonAddress.length > 1) {
        // preson += "，...";
        // }
        // } catch (RuntimeException ex) {
        // logger.error("Exception", ex);
        // preson = "--";
        // }
        if ("R".equals(type0)) {
          String personaladdr = ALMailUtils.getOneString(ALMailUtils.getTokens(presonAddress[0].toString(), ALMailUtils.CR), "");
          try {
            // change start 20111223 SHIFT-JIS対応
            // preson = MailUtility.decodeText(personaladdr);
            preson = ALMailUtils.decodeText(personaladdr);
            // change end
            if (presonAddress.length > 1) {
              preson += "，...";
            }
          } catch (RuntimeException ex) {
            logger.error("Exception", ex);
            preson = "--";
          }
        } else {
          preson = ALMailUtils.getAddressString(presonAddress);
        }
        // change end
      } else {
        preson = "--";
      }

      // 日付
      try {
        sentDate = mimeMessage.getSentDate();
      } catch (MessagingException ex) {
      }
      if (sentDate == null) {
        sentDate = Calendar.getInstance().getTime();
      }

      // ファイル容量（KB）
      int fileVolume = 0;
      try {
        fileVolume = (int) Math.ceil(mimeMessage.getSize() / 1024.0);
      } catch (MessagingException ex) {
        fileVolume = 0;
      }

      // 添付ファイルの有無
      String hasAttachments = null;
      // change start
      // if (saveContents) {
      try {
        ALAttachmentsExtractor h = new ALAttachmentsExtractor();
        MultipartUtility.process(mimeMessage, h);
        hasAttachments = (h.getCount() > 0) ? "T" : "F";
      } catch (MessagingException ex) {
        hasAttachments = "F";
      }
      // } else {
      // hasAttachments = "F";
      // }
      // change end

      // メールタイプ・既読フラグ
      String type = (ALFolder.TYPE_RECEIVE == type_mail) ? "R" : "S";
      String read_flg = isRead ? "T" : "F";

      // アカウントのフォルダに代入
      EipMMailAccount account = ALMailUtils.getMailAccount(user_id, account_id);
      // change start
      // int folder_id = account.getDefaultFolderId();
      int folder_id = 0;
      // change end

      // change start
      if (ALFolder.TYPE_RECEIVE == type_mail) {
        // 受信メールの場合

        folder_id = account.getDefaultFolderId();

        // フォルダ振り分け処理
        List<EipTMailFilter> filters = ALMailUtils.getEipTMailFilters(account);
        if (filters != null) {
          for (EipTMailFilter mailFilter : filters) {
            if (ALMailUtils.isMatchFilter(mailFilter, subject, preson, receiveAddress)) {
              folder_id = mailFilter.getEipTMailFolder().getFolderId();
              break;
            }
          }
        }

        EipTMail email = Database.create(EipTMail.class);

        email.setUserId(Integer.valueOf(user_id));
        email.setAccountId(Integer.valueOf(account_id));
        email.setType(type);
        email.setReadFlg(read_flg);
        email.setSubject(subject);
        // change start 運用フェーズ障害128
        // email.setPerson(preson);
        email.setPerson(convertNullChar(preson, convertNull));
        // change end
        email.setEventDate(sentDate);
        email.setFileVolume(Integer.valueOf(fileVolume));
        email.setHasFiles(hasAttachments);
        email.setFilePath(filePath);
        email.setFolderId(Integer.valueOf(folder_id));

        // 作成日
        email.setCreateDate(Calendar.getInstance().getTime());
        // 更新日
        email.setUpdateDate(Calendar.getInstance().getTime());

        // add start
        // 検索文字列
        // change start 2012.1.11
        // utf-7対応
        // email.setTextForSearch(ALMailUtils.parseContent(mimeMessage
        // .getContent()));
        // remove start 2次開発 要件No.20 キャラクタセットCP932メール対応
        // Object content = null;
        // try {
        // content = mimeMessage.getContent();
        // } catch (Exception e) {
        // logger.error("受信メールのコンテンツ取得に失敗しました（件名：" + email.getSubject() + "
        // 受信者：" + ALEipUtils.getUserLoginName(Integer.valueOf(user_id)) + " " +
        // e);
        // // change start 2012.1.17
        // // 受入障害No.216 utf-7対応
        // // content = "";
        // content = ALMailUtils.getUnsupportedEncodingContent(mimeMessage,
        // email.getSubject(), Integer.valueOf(user_id));
        // // change end
        // }
        // remove end
        // change start 2012.2.21 受入障害対応No.293
        // email.setTextForSearch(ALMailUtils.parseContent(content));
        try {
          // change start 2次開発 要件No.20 キャラクタセットCP932メール対応
          // email.setTextForSearch(convertNullChar(ALMailUtils.parseContent(content,
          // mimeMessage), convertNull));
          ALLocalMailMessage tmpMessage = new ALLocalMailMessage(mimeMessage, "");
          // Content-Transfer-Encoding:が「sevenbit」の場合に「7bit」に変換
          String[] str_list_encoding = tmpMessage.getHeader(ALLocalMailMessage.CONTENT_TRANSFER_ENCORDING);
          if (null != str_list_encoding && str_list_encoding.length > 0) {
            String str_encoding = str_list_encoding[0];
            if ("sevenbit".equals(str_encoding)) {
              tmpMessage.setHeader(ALLocalMailMessage.CONTENT_TRANSFER_ENCORDING, ALMailUtils.STR_7BIT);
            }
          }
          email.setTextForSearch(convertNullChar(tmpMessage.getBodyText(), convertNull));
          // change end
        } catch (Exception e) {
          logger.error("受信メールファイルからの本文情報の取得に失敗しました（件名："
            + email.getSubject()
            + " 受信者："
            + ALEipUtils.getUserLoginName(Integer.valueOf(user_id))
            + " "
            + " 対象ファイルパス："
            + getFullName()
            + ALStorageService.separator()
            + filePath
            + e);
          email.setTextForSearch("");
        }
        // change end 2012.2.21
        // change end
        // change start 20111223 SHIFT-JIS対応
        // email.setSubjectForSearch(mimeMessage.getSubject());
        email.setSubjectForSearch(convertNullChar(ALMailUtils.decodeSubjectBase(mimeMessage.getHeader("Subject", null)), convertNull));
        // change end
        email.setAddressForSearch(convertNullChar(preson, convertNull));
        // 開封確認送信済みフラグ（未送信）
        email.setNotificationFlg("F");

        // add end

      } else {
        // 送信メールの場合
        AvzTMailSend emailSend = Database.create(AvzTMailSend.class);

        emailSend.setUserId(Integer.valueOf(user_id));
        emailSend.setAccountId(Integer.valueOf(account_id));
        emailSend.setType(type);
        emailSend.setReadFlg("T"); // 送信時は必ず既読とする
        emailSend.setSubject(subject);
        // change start 運用フェーズ障害128
        // emailSend.setPerson(preson);
        emailSend.setPerson(convertNullChar(preson, convertNull));
        // change end
        emailSend.setEventDate(sentDate);
        emailSend.setFileVolume(Integer.valueOf(fileVolume));
        emailSend.setHasFiles(hasAttachments);
        emailSend.setFilePath(filePath);

        // 送信トレイのフォルダID
        folder_id = account.getDefaultSendFolderId();
        emailSend.setFolderId(Integer.valueOf(folder_id));

        // 作成日
        emailSend.setCreateDate(Calendar.getInstance().getTime());
        // 更新日
        emailSend.setUpdateDate(Calendar.getInstance().getTime());

        // 全文検索
        // change start 運用フェーズ障害128
        // emailSend.setTextForSearch(ALMailUtils.parseContent(mimeMessage
        // .getContent(), mimeMessage));
        emailSend.setTextForSearch(convertNullChar(ALMailUtils.parseContent(mimeMessage.getContent(), mimeMessage), convertNull));
        // change end

        // change start 運用フェーズ障害128
        // emailSend.setSubjectForSearch(mimeMessage.getSubject());
        emailSend.setSubjectForSearch(convertNullChar(mimeMessage.getSubject(), convertNull));
        // change end

        // change start 運用フェーズ障害128
        // emailSend.setAddressForSearch(preson);
        emailSend.setAddressForSearch(convertNullChar(preson, convertNull));
        // change end

      }
      // フォルダ情報取得
      EipTMailFolder folder = ALMailUtils.getEipTMailFolder(account, Integer.valueOf(folder_id).toString());
      // フォルダ容量更新（単位：byte）
      folder.setFolderVolume(folder.getFolderVolume() + fileVolume * 1024);

      // change end

      Database.commit();
    } catch (Throwable t) {
      // add start 運用フェーズ障害128
      if (t instanceof CayenneRuntimeException && !convertNull) {
        CayenneRuntimeException e = (CayenneRuntimeException) t;
        if (e.getCause().getMessage().contains(KEYWORD_NULL_ERROR)) {
          logger.error("NULLコードのため、メール情報のDB保存に失敗しました。NULLコードを置換してリトライします。", t);
          Database.rollback();
          return false;
        }
      }
      // add end
      Database.rollback();
      // change start
      throw t;
      // logger.error(t);
      // return false;
      // change end
    }
    return true;
  }

  /**
   * フォルダを指定してメール情報をDBに登録します。<BR>
   * 
   * @param mimeMessage
   * @param filePath
   * @param folderId
   * @param saveContents
   * @param isRead
   * @return
   * @throws Throwable
   */
  // change start 運用フェーズ障害128
  // protected boolean insertMailToDBByFolder(MimeMessage mimeMessage,
  // String filePath, String folderId, boolean saveContents, boolean isRead)
  protected boolean insertMailToDBByFolder(MimeMessage mimeMessage, String filePath, String folderId, boolean saveContents, boolean isRead, boolean convertNull)
  // change end
      throws Throwable {
    try {

      if (saveContents) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        mimeMessage.writeTo(output);
      } else {
        Session session = Session.getDefaultInstance(new Properties());
        Message newMsg = new MimeMessage(session);
        Enumeration<?> headers = mimeMessage.getAllHeaders();
        while (headers.hasMoreElements()) {
          Header h = (Header) headers.nextElement();
          newMsg.addHeader(h.getName(), h.getValue());
        }
        newMsg.setText("メールのサイズが7MBを超えていたため、このメールを受信できませんでした。\r\n 誠に恐れ入りますが、別のメーラーで受信してください。");
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        newMsg.writeTo(output);
      }

      String subject;
      Address[] presonAddress;
      Address[] receiveAddress;
      String preson;
      Date sentDate = null;

      // 件名
      subject = mimeMessage.getHeader(ALLocalMailMessage.SUBJECT, null);
      if (subject == null) {
        subject = MailUtility.encodeWordJIS("無題");
      } else {
        subject = subject.replaceAll("\r", "");
        subject = subject.replaceAll("\n", "");
      }

      String type0 = (ALFolder.TYPE_RECEIVE == type_mail) ? "R" : "S";

      // 差出人 or 受取人
      if ("R".equals(type0)) {
        try {
          presonAddress = mimeMessage.getFrom();
        } catch (MessagingException ex) {
          presonAddress = null;
        }
      } else {
        try {
          presonAddress = mimeMessage.getAllRecipients();
        } catch (MessagingException ex) {
          presonAddress = null;
        }
      }

      try {
        receiveAddress = mimeMessage.getAllRecipients();
      } catch (MessagingException ex) {
        // change start 受入テスト障害292 Undisclosed-Recipient:;の場合にnullになるのに対応
        // receiveAddress = null;
        receiveAddress = new Address[0];
        // change end
      }

      if (presonAddress != null && presonAddress.length > 0) {
        // change start 2011.11.18
        // String personaladdr =
        // ALMailUtils.getOneString(ALMailUtils.getTokens(presonAddress[0]
        // .toString(), ALMailUtils.CR), "");
        // try {
        // preson = MailUtility.decodeText(personaladdr);
        // if (presonAddress.length > 1) {
        // preson += "，...";
        // }
        // } catch (RuntimeException ex) {
        // logger.error("Exception", ex);
        // preson = "--";
        // }
        if ("R".equals(type0)) {
          String personaladdr = ALMailUtils.getOneString(ALMailUtils.getTokens(presonAddress[0].toString(), ALMailUtils.CR), "");
          try {
            // change start 2012.2.7 中国語対応
            // preson = MailUtility.decodeText(personaladdr);
            preson = ALMailUtils.decodeText(personaladdr);
            // change end 2012.2.7
            if (presonAddress.length > 1) {
              preson += "，...";
            }
          } catch (RuntimeException ex) {
            logger.error("Exception", ex);
            preson = "--";
          }
        } else {
          preson = ALMailUtils.getAddressString(presonAddress);
        }
        // change end
      } else {
        preson = "--";
      }

      // 日付
      try {
        sentDate = mimeMessage.getSentDate();
      } catch (MessagingException ex) {
      }
      if (sentDate == null) {
        sentDate = Calendar.getInstance().getTime();
      }

      // ファイル容量（KB）
      int fileVolume = 0;
      try {
        fileVolume = (int) Math.ceil(mimeMessage.getSize() / 1024.0);
      } catch (MessagingException ex) {
        fileVolume = 0;
      }

      // 添付ファイルの有無
      String hasAttachments = null;
      try {
        ALAttachmentsExtractor h = new ALAttachmentsExtractor();
        MultipartUtility.process(mimeMessage, h);
        hasAttachments = (h.getCount() > 0) ? "T" : "F";
      } catch (MessagingException ex) {
        hasAttachments = "F";
      }

      // メールタイプ・既読フラグ
      String type = (ALFolder.TYPE_RECEIVE == type_mail) ? "R" : "S";
      String read_flg = isRead ? "T" : "F";

      // アカウントのフォルダに代入
      EipMMailAccount account = ALMailUtils.getMailAccount(user_id, account_id);

      if (ALFolder.TYPE_RECEIVE == type_mail) {
        // 受信メールの場合

        EipTMail email = Database.create(EipTMail.class);

        email.setUserId(Integer.valueOf(user_id));
        email.setAccountId(Integer.valueOf(account_id));
        email.setType(type);
        email.setReadFlg(read_flg);
        email.setSubject(subject);
        // change start 運用フェーズ障害128
        // email.setPerson(preson);
        email.setPerson(convertNullChar(preson, convertNull));
        // change end
        email.setEventDate(sentDate);
        email.setFileVolume(Integer.valueOf(fileVolume));
        email.setHasFiles(hasAttachments);
        email.setFilePath(filePath);
        email.setFolderId(Integer.valueOf(folderId));

        // 作成日
        email.setCreateDate(Calendar.getInstance().getTime());
        // 更新日
        email.setUpdateDate(Calendar.getInstance().getTime());

        // change start 2012.1.11
        // email.setTextForSearch(ALMailUtils.parseContent(mimeMessage
        // .getContent()));
        // email.setSubjectForSearch(mimeMessage.getSubject());
        // utf-7対応
        // email.setTextForSearch(ALMailUtils.parseContent(mimeMessage
        // .getContent()));
        // remove start 2次開発 要件No.20 キャラクタセットCP932メール対応
        // Object content = null;
        // try {
        // content = mimeMessage.getContent();
        // } catch (Exception e) {
        // logger.error("受信メールのコンテンツ取得に失敗しました（件名：" + email.getSubject() + "
        // 受信者：" + ALEipUtils.getUserLoginName(Integer.valueOf(user_id)) + " " +
        // e);
        // // change start 2012.1.17
        // // 受入障害No.216 utf-7対応
        // // content = "";
        // content = ALMailUtils.getUnsupportedEncodingContent(mimeMessage,
        // email.getSubject(), Integer.valueOf(user_id));
        // // change end
        // }
        // remove end
        // change start 2012.2.21 受入障害対応No.293
        // email.setTextForSearch(ALMailUtils.parseContent(content));
        try {
          // change start 2次開発 要件No.20 キャラクタセットCP932メール対応
          // email.setTextForSearch(convertNullChar(ALMailUtils.parseContent(content,
          // mimeMessage), convertNull));
          // Content-Transfer-Encoding:が「sevenbit」の場合に「7bit」に変換
          String[] str_list_encoding = mimeMessage.getHeader(ALLocalMailMessage.CONTENT_TRANSFER_ENCORDING);
          if (null != str_list_encoding && str_list_encoding.length > 0) {
            String str_encoding = str_list_encoding[0];
            if ("sevenbit".equals(str_encoding)) {
              mimeMessage.setHeader(ALLocalMailMessage.CONTENT_TRANSFER_ENCORDING, ALMailUtils.STR_7BIT);
            }
          }
          email.setTextForSearch(convertNullChar(((ALLocalMailMessage) mimeMessage).getBodyText(), convertNull));
          // change end
        } catch (Exception e) {
          logger.error("受信メールファイルからの本文情報の取得に失敗しました（件名："
            + email.getSubject()
            + " 受信者："
            + ALEipUtils.getUserLoginName(Integer.valueOf(user_id))
            + " "
            + " 対象ファイルパス："
            + getFullName()
            + ALStorageService.separator()
            + filePath
            + e);
          email.setTextForSearch("");
        }
        // change end 2012.2.21
        email.setSubjectForSearch(convertNullChar(ALMailUtils.decodeSubjectBase(mimeMessage.getHeader("Subject", null)), convertNull));
        // change end
        email.setAddressForSearch(convertNullChar(preson, convertNull));

      } else {
        // 送信メールの場合
        AvzTMailSend emailSend = Database.create(AvzTMailSend.class);

        emailSend.setUserId(Integer.valueOf(user_id));
        emailSend.setAccountId(Integer.valueOf(account_id));
        emailSend.setType(type);
        emailSend.setReadFlg("T"); // 送信時は必ず既読とする
        emailSend.setSubject(subject);
        emailSend.setPerson(preson);
        emailSend.setEventDate(sentDate);
        emailSend.setFileVolume(Integer.valueOf(fileVolume));
        emailSend.setHasFiles(hasAttachments);
        emailSend.setFilePath(filePath);
        emailSend.setFolderId(Integer.valueOf(folderId));

        // 作成日
        emailSend.setCreateDate(Calendar.getInstance().getTime());
        // 更新日
        emailSend.setUpdateDate(Calendar.getInstance().getTime());

        // 全文検索
        // change start 運用フェーズ障害128
        // emailSend.setTextForSearch(ALMailUtils.parseContent(mimeMessage
        // .getContent(), mimeMessage));
        emailSend.setTextForSearch(convertNullChar(ALMailUtils.parseContent(mimeMessage.getContent(), mimeMessage), convertNull));
        // change end

        // change start 運用フェーズ障害128
        // emailSend.setSubjectForSearch(mimeMessage.getSubject());
        emailSend.setSubjectForSearch(convertNullChar(mimeMessage.getSubject(), convertNull));
        // change end

        // change start 運用フェーズ障害128
        // emailSend.setAddressForSearch(preson);
        emailSend.setAddressForSearch(convertNullChar(preson, convertNull));
        // change end

      }
      // フォルダ情報取得
      EipTMailFolder folder = ALMailUtils.getEipTMailFolder(account, Integer.valueOf(folderId).toString());
      // フォルダ容量更新（単位：byte）
      folder.setFolderVolume(folder.getFolderVolume() + fileVolume * 1024);

      Database.commit();
    } catch (Throwable t) {
      // add start 運用フェーズ障害128
      if (t instanceof CayenneRuntimeException && !convertNull) {
        CayenneRuntimeException e = (CayenneRuntimeException) t;
        if (e.getCause().getMessage().contains(KEYWORD_NULL_ERROR)) {
          logger.error("NULLコードのため、メール情報のDB保存に失敗しました。NULLコードを置換してリトライします。", t);
          Database.rollback();
          return false;
        }
      }
      // add end
      Database.rollback();
      // change start
      throw t;
      // logger.error(t);
      // return false;
      // change end
    }
    return true;
  }

  /**
   * 受信メールのインデックス情報を取得します。
   * <p>
   * 
   * @param rundata
   * @param context
   * @return
   */
  @Override
  public ResultList<EipTMail> getIndexRows(RunData rundata, Context context) throws Exception {
    try {
      // // 未読メール総数をセットする．
      // setUnreadMailSum();
      // // 最終更新日を取得し，セットする．
      // setFinalAccessDate(rundata, context);

      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("p2a-sort"));
      }

      init(rundata, context);

      // ソート対象が日時だった場合、ソート順を逆にする．
      if ("date".equals(ALEipUtils.getTemp(rundata, context, LIST_SORT_STR))) {
        String sort_type = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
        if (sort_type == null || sort_type.equals("")) {
          ALEipUtils.setTemp(rundata, context, LIST_SORT_TYPE_STR, ALEipConstants.LIST_SORT_TYPE_DESC);
        }
      }
      // change start
      // 受入障害対応No.133
      // SelectQuery<EipTMail> query = getSelectQuery(rundata, context);
      // buildSelectQueryForListView(query);
      // buildSelectQueryForListViewSort(query, rundata, context);
      ALEipTMailDirectSelectQuery query = new ALEipTMailDirectSelectQuery();
      buildSelectQueryForListView(query);
      buildDirectSelectQueryForListViewSort(query, rundata, context);
      // メールタイプが「受信」の場合、セッションからフォルダIDを取得する
      String folder_id = ALEipUtils.getTemp(rundata, context, ALMailUtils.FOLDER_ID);
      String folder_kind = ALMailUtils.FOLDER_KIND_RECEIVE;

      query.setUserId(user_id);
      query.setAccountId(account_id);

      // 全文検索
      // 本文
      if (searchWord != null && searchWord.length() > 0) {
        query.setSearchWordQuery(searchWord);
      }
      // 件名
      if (searchSubjectWord != null && searchSubjectWord.length() > 0) {
        query.setSearchSubjectWordQuery(searchSubjectWord);
      }
      // 差出人
      if (searchAddressWord != null && searchAddressWord.length() > 0) {
        // change start 運用フェーズ課題・障害台帳No.１３３
        // query.setSearchAddressWordQuery(searchAddressWord);
        query.setSearchAddressWordQuery(convertAddressSearchWord(user_id, searchAddressWord));
        // change end
      }

      // 検索キーワードが指定され、かつ「サブフォルダも含む」場合は子フォルダも条件に含める
      if (((searchWord != null && searchWord.length() > 0) || (searchSubjectWord != null && searchSubjectWord.length() > 0) || (searchAddressWord != null && searchAddressWord
        .length() > 0))
        && (includeSubFolder != null)
        && includeSubFolder.length() > 0) {
        List<ALExtFolderInfo> folder_hierarchy_list = ALMailUtils.getFolderList(Integer.parseInt(folder_id), account_id, folder_kind);
        List<String> child_folder_id_list = new ArrayList<String>();
        child_folder_id_list.add(folder_id);
        if (folder_hierarchy_list != null) {
          for (int i = 0; i < folder_hierarchy_list.size(); i++) {
            // 子フォルダ情報取得
            child_folder_id_list.add(Integer.toString(folder_hierarchy_list.get(i).getFolderId()));
          }
        }
        query.setChildFolderIds(child_folder_id_list);
      } else {
        // 現在処理中のフォルダを指定する
        query.setFolderId(folder_id);
      }
      // 受入障害対応No.133
      // change end

      ResultList<EipTMail> resultList = query.getResultList();
      setPageParam(resultList.getTotalCount());
      return resultList;
    } catch (Exception ex) {
      // change start
      // return null;
      logger.error("Exception", ex);
      throw ex;
      // change end
    }
  }

  /**
   * 送信メールのインデックス情報を取得します。
   * <p>
   * 
   * @param rundata
   * @param context
   * @return
   */
  @Override
  public ResultList<AvzTMailSend> getIndexRowsSend(RunData rundata, Context context) throws Exception {
    try {
      // // 未読メール総数をセットする．
      // setUnreadMailSum();
      // // 最終更新日を取得し，セットする．
      // setFinalAccessDate(rundata, context);

      // add start
      String folder_kind = ALMailUtils.FOLDER_KIND_SEND;
      // フォルダIDを取得する
      String folder_id = ALEipUtils.getTemp(rundata, context, ALMailUtils.FOLDER_ID);
      // add end

      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("p2a-sort"));
      }

      init(rundata, context);

      // ソート対象が日時だった場合、ソート順を逆にする．
      if ("date".equals(ALEipUtils.getTemp(rundata, context, LIST_SORT_STR))) {
        String sort_type = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
        if (sort_type == null || sort_type.equals("")) {
          ALEipUtils.setTemp(rundata, context, LIST_SORT_TYPE_STR, ALEipConstants.LIST_SORT_TYPE_DESC);
        }
      }
      // change start
      // 受入障害対応No.133
      // SelectQuery<AvzTMailSend> query = getSelectQuerySend(rundata, context);
      // buildSelectQuerySendForListView(query);
      // buildSelectQuerySendForListViewSort(query, rundata, context);
      ALAvzTMailSendDirectSelectQuery query = new ALAvzTMailSendDirectSelectQuery();
      buildSelectQueryForListView(query);
      buildDirectSelectQueryForListViewSort(query, rundata, context);

      query.setUserId(user_id);
      query.setAccountId(account_id);
      // 全文検索
      if (searchWord != null && searchWord.length() > 0) {
        query.setSearchWordQuery(searchWord);
      }

      if (searchSubjectWord != null && searchSubjectWord.length() > 0) {
        query.setSearchSubjectWordQuery(searchSubjectWord);
      }

      if (searchAddressWord != null && searchAddressWord.length() > 0) {
        // change start 運用フェーズ課題・障害台帳No.１３３
        // query.setSearchAddressWordQuery(searchAddressWord);
        query.setSearchAddressWordQuery(convertAddressSearchWord(user_id, searchAddressWord));
        // change end
      }

      // 検索キーワードが指定され、かつ「サブフォルダも含む」場合は子フォルダも条件に含める
      if (((searchWord != null && searchWord.length() > 0) || (searchSubjectWord != null && searchSubjectWord.length() > 0) || (searchAddressWord != null && searchAddressWord
        .length() > 0))
        && (includeSubFolder != null)
        && includeSubFolder.length() > 0) {
        List<ALExtFolderInfo> folder_hierarchy_list = ALMailUtils.getFolderList(Integer.parseInt(folder_id), account_id, folder_kind);
        List<String> child_folder_id_list = new ArrayList<String>();
        child_folder_id_list.add(folder_id);
        if (folder_hierarchy_list != null) {
          for (int i = 0; i < folder_hierarchy_list.size(); i++) {
            // 子フォルダ情報取得
            child_folder_id_list.add(Integer.toString(folder_hierarchy_list.get(i).getFolderId()));
          }
        }
        query.setChildFolderIds(child_folder_id_list);
      } else {
        // 現在処理中のフォルダを指定する
        query.setFolderId(folder_id);
      }
      // 受入障害対応No.133
      // change end

      ResultList<AvzTMailSend> resultList = query.getResultList();
      setPageParam(resultList.getTotalCount());
      return resultList;
    } catch (Exception ex) {
      // change start
      // logger.error("Exception", ex);
      // return null;
      throw ex;
      // change end
    }
  }

  // remove start
  // 受入障害対応No.133
  // /**
  // * 検索条件を設定した SelectQuery を返します。 <BR>
  // *
  // * @param rundata
  // * @param context
  // * @return
  // */
  // private SelectQuery<EipTMail> getSelectQuery(RunData rundata, Context
  // context) {
  // String type = (type_mail == TYPE_RECEIVE) ? "R" : "S";
  //
  // // メールタイプが「受信」の場合、セッションからフォルダIDを取得する
  // String folder_id = "";
  // String folder_kind = "";
  // if (type_mail == TYPE_RECEIVE) {
  // folder_id = ALEipUtils.getTemp(rundata, context, ALMailUtils.FOLDER_ID);
  // folder_kind = ALMailUtils.FOLDER_KIND_RECEIVE;
  // }
  //
  // SelectQuery<EipTMail> query = Database.query(EipTMail.class);
  // query.select(EipTMail.MAIL_ID_PK_COLUMN);
  // query.select(EipTMail.READ_FLG_COLUMN);
  // query.select(EipTMail.SUBJECT_COLUMN);
  // query.select(EipTMail.PERSON_COLUMN);
  // query.select(EipTMail.EVENT_DATE_COLUMN);
  // query.select(EipTMail.FILE_VOLUME_COLUMN);
  // query.select(EipTMail.HAS_FILES_COLUMN);
  // query.select(EipTMail.FILE_PATH_COLUMN);
  // query.select(EipTMail.REPLY_FORWARD_COLUMN);
  // Expression exp1 =
  // ExpressionFactory.matchExp(EipTMail.USER_ID_PROPERTY, Integer
  // .valueOf(user_id));
  // query.setQualifier(exp1);
  // Expression exp2 =
  // ExpressionFactory.matchExp(EipTMail.ACCOUNT_ID_PROPERTY, Integer
  // .valueOf(account_id));
  // query.andQualifier(exp2);
  // Expression exp3 = ExpressionFactory.matchExp(EipTMail.TYPE_PROPERTY, type);
  // query.andQualifier(exp3);
  //
  // // folder_id が空でなければ、フォルダIDで絞り込む
  // // remove start 下部に移動
  // // if (!("".equals(folder_id))) {
  // // Expression exp4 =
  // // ExpressionFactory.matchExp(EipTMail.FOLDER_ID_PROPERTY, Integer
  // // .valueOf(folder_id));
  // // query.andQualifier(exp4);
  // // }
  // // remove end
  //
  // // add start for 全文検索
  // if (searchWord != null && searchWord.length() > 0) {
  // Expression exp5 =
  // ExpressionFactory.likeExp(EipTMail.TEXT_FOR_SEARCH_PROPERTY, "%"
  // + searchWord
  // + "%");
  // query.andQualifier(exp5);
  // }
  //
  // if (searchSubjectWord != null && searchSubjectWord.length() > 0) {
  // Expression exp6 =
  // ExpressionFactory.likeExp(EipTMail.SUBJECT_FOR_SEARCH_PROPERTY, "%"
  // + searchSubjectWord
  // + "%");
  // query.andQualifier(exp6);
  // }
  //
  // if (searchAddressWord != null && searchAddressWord.length() > 0) {
  // Expression exp7 =
  // ExpressionFactory.likeExp(EipTMail.ADDRESS_FOR_SEARCH_PROPERTY, "%"
  // + searchAddressWord
  // + "%");
  // query.andQualifier(exp7);
  // }
  //
  // // 検索キーワードが指定され、かつ「サブフォルダも含む」場合は子フォルダも条件に含める
  // if (((searchWord != null && searchWord.length() > 0)
  // || (searchSubjectWord != null && searchSubjectWord.length() > 0) ||
  // (searchAddressWord != null && searchAddressWord
  // .length() > 0))
  // && (includeSubFolder != null)
  // && includeSubFolder.length() > 0) {
  // List<ALExtFolderInfo> folder_hierarchy_list =
  // ALMailUtils.getFolderList(
  // Integer.parseInt(folder_id),
  // account_id,
  // folder_kind);
  // List<String> child_folder_id_list = new ArrayList<String>();
  // child_folder_id_list.add(folder_id);
  // if (folder_hierarchy_list != null) {
  // for (int i = 0; i < folder_hierarchy_list.size(); i++) {
  // // 子フォルダ情報取得
  // child_folder_id_list.add(Integer.toString(folder_hierarchy_list
  // .get(i)
  // .getFolderId()));
  // }
  // }
  // Expression exp8 =
  // ExpressionFactory.inExp(
  // EipTMail.FOLDER_ID_PROPERTY,
  // child_folder_id_list);
  // query.andQualifier(exp8);
  // } else {
  // // 現在処理中のフォルダを指定する
  // Expression exp8 =
  // ExpressionFactory.matchExp(EipTMail.FOLDER_ID_PROPERTY, Integer
  // .valueOf(folder_id));
  // query.andQualifier(exp8);
  // }
  //
  // // add end
  //
  // return query;
  // }

  // /**
  // * 検索条件を設定した SelectQuery を返します。 <BR>
  // * 送信メール
  // *
  // * @param rundata
  // * @param context
  // * @return
  // */
  // private SelectQuery<AvzTMailSend> getSelectQuerySend(RunData rundata,
  // Context context) {
  // String type = ALMailUtils.FOLDER_KIND_SEND;
  // String folder_kind = ALMailUtils.FOLDER_KIND_SEND;
  //
  // // フォルダIDを取得する
  // String folder_id =
  // ALEipUtils.getTemp(rundata, context, ALMailUtils.FOLDER_ID);
  //
  // SelectQuery<AvzTMailSend> query = Database.query(AvzTMailSend.class);
  // query.select(AvzTMailSend.MAIL_ID_PK_COLUMN);
  // query.select(AvzTMailSend.READ_FLG_COLUMN);
  // query.select(AvzTMailSend.SUBJECT_COLUMN);
  // query.select(AvzTMailSend.PERSON_COLUMN);
  // query.select(AvzTMailSend.EVENT_DATE_COLUMN);
  // query.select(AvzTMailSend.FILE_VOLUME_COLUMN);
  // query.select(AvzTMailSend.HAS_FILES_COLUMN);
  // query.select(AvzTMailSend.FILE_PATH_COLUMN);
  // query.select(AvzTMailSend.REPLY_FORWARD_COLUMN);
  // Expression exp1 =
  // ExpressionFactory.matchExp(AvzTMailSend.USER_ID_PROPERTY, Integer
  // .valueOf(user_id));
  // query.setQualifier(exp1);
  // Expression exp2 =
  // ExpressionFactory.matchExp(AvzTMailSend.ACCOUNT_ID_PROPERTY, Integer
  // .valueOf(account_id));
  // query.andQualifier(exp2);
  // Expression exp3 =
  // ExpressionFactory.matchExp(AvzTMailSend.TYPE_PROPERTY, type);
  // query.andQualifier(exp3);
  //
  // // folder_id が空でなければ、フォルダIDで絞り込む
  // // if (!("".equals(folder_id))) {
  // // Expression exp4 =
  // // ExpressionFactory.matchExp(AvzTMailSend.FOLDER_ID_PROPERTY, Integer
  // // .valueOf(folder_id));
  // // query.andQualifier(exp4);
  // // }
  //
  // // 全文検索
  // if (searchWord != null && searchWord.length() > 0) {
  // Expression exp5 =
  // ExpressionFactory.likeExp(AvzTMailSend.TEXT_FOR_SEARCH_PROPERTY, "%"
  // + searchWord
  // + "%");
  // query.andQualifier(exp5);
  // }
  //
  // if (searchSubjectWord != null && searchSubjectWord.length() > 0) {
  // Expression exp6 =
  // ExpressionFactory.likeExp(AvzTMailSend.SUBJECT_FOR_SEARCH_PROPERTY, "%"
  // + searchSubjectWord
  // + "%");
  // query.andQualifier(exp6);
  // }
  //
  // if (searchAddressWord != null && searchAddressWord.length() > 0) {
  // Expression exp7 =
  // ExpressionFactory.likeExp(AvzTMailSend.ADDRESS_FOR_SEARCH_PROPERTY, "%"
  // + searchAddressWord
  // + "%");
  // query.andQualifier(exp7);
  // }
  //
  // // 検索キーワードが指定され、かつ「サブフォルダも含む」場合は子フォルダも条件に含める
  // if (((searchWord != null && searchWord.length() > 0)
  // || (searchSubjectWord != null && searchSubjectWord.length() > 0) ||
  // (searchAddressWord != null && searchAddressWord
  // .length() > 0))
  // && (includeSubFolder != null)
  // && includeSubFolder.length() > 0) {
  // List<ALExtFolderInfo> folder_hierarchy_list =
  // ALMailUtils.getFolderList(
  // Integer.parseInt(folder_id),
  // account_id,
  // folder_kind);
  // List<String> child_folder_id_list = new ArrayList<String>();
  // child_folder_id_list.add(folder_id);
  // if (folder_hierarchy_list != null) {
  // for (int i = 0; i < folder_hierarchy_list.size(); i++) {
  // // 子フォルダ情報取得
  // child_folder_id_list.add(Integer.toString(folder_hierarchy_list
  // .get(i)
  // .getFolderId()));
  // }
  // }
  // Expression exp8 =
  // ExpressionFactory.inExp(
  // AvzTMailSend.FOLDER_ID_PROPERTY,
  // child_folder_id_list);
  // query.andQualifier(exp8);
  // } else {
  // // 現在処理中のフォルダを指定する
  // Expression exp8 =
  // ExpressionFactory.matchExp(AvzTMailSend.FOLDER_ID_PROPERTY, Integer
  // .valueOf(folder_id));
  // query.andQualifier(exp8);
  // }
  //
  // return query;
  // }
  // 受入障害対応No.133
  // remove end
  /**
   * 保存してある UID リストを取得する．
   * 
   * @return
   */
  @Override
  public List<String> loadUID() {
    List<String> oldUIDL = new ArrayList<String>();

    BufferedReader reader = null;
    InputStream is = null;
    try {
      try {
        is = ALStorageService.getFile(getFullName() + ALStorageService.separator() + ALFolder.FILE_UIDL);
      } catch (Throwable t) {
        //
      }
      if (is == null) {
        return oldUIDL;
      }
      reader = new BufferedReader(new InputStreamReader(is));
      String line = null;
      while ((line = reader.readLine()) != null) {
        oldUIDL.add(line);
      }

    } catch (IOException ioe) {
      //
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException i) {
          //
        }
      }
      if (reader != null) {
        try {
          reader.close();
        } catch (IOException ioe) {
        }
      }
    }
    return oldUIDL;
  }

  /**
   * UID の一覧を保存する．
   * 
   * @param oldUIDL
   */
  @Override
  public void saveUID(List<String> oldUIDL) {
    try {
      int length = oldUIDL.size();
      StringBuilder b = new StringBuilder();
      for (int i = 0; i < length; i++) {
        b.append(oldUIDL.get(i));
        b.append(System.getProperty("line.separator"));
      }

      ALStorageService.saveFile(new ByteArrayInputStream(b.toString().getBytes("utf-8")), getFullName() + ALStorageService.separator(), ALFolder.FILE_UIDL);

    } catch (IOException ioe) {
    } finally {

    }
  }

  @Override
  public void setRootFolderPath(String str) {
    rootFolderPath = str;
  }

  protected String getRootFolderPath() {
    return (rootFolderPath != null && !"".equals(rootFolderPath)) ? rootFolderPath : ALMailUtils.rootFolderPath;
  }

  protected String getCategoryKey() {
    return (categoryKey != null && !"".equals(categoryKey)) ? categoryKey : ALMailUtils.categoryKey;
  }

  /**
   * 自身のフォルダまでのフルパスを取得する。
   * 
   * @return
   */
  @Override
  public String getFullName() {
    StringBuilder key = new StringBuilder();
    String categoryKeytmp = getCategoryKey();

    if (categoryKeytmp != null && !"".equals(categoryKeytmp)) {
      key.append(categoryKeytmp);
    }
    key.append(ALStorageService.separator());
    key.append(user_id);
    key.append(ALStorageService.separator());
    key.append(account_id);

    if (ALFolder.TYPE_RECEIVE == type_mail) {
      key.append(ALStorageService.separator()).append("Receive");
    } else {
      key.append(ALStorageService.separator()).append("Send");
    }

    return ALStorageService.getDocumentPath(ALMailUtils.rootFolderPath, key.toString());
  }

  // remove start
  // 受入障害対応No.133
  // /**
  // * ページング結果のリストを取得します。
  // *
  // * @param records
  // * 検索結果
  // */
  // protected void buildSelectQueryForListView(SelectQuery<EipTMail> query) {
  // query.limit(getRowsNum());
  // query.page(current_page);
  // }
  //
  // /**
  // * ページング結果のリストを取得します。
  // *
  // * @param records
  // * 検索結果
  // */
  // protected void buildSelectQuerySendForListView(SelectQuery<AvzTMailSend>
  // query) {
  // query.limit(getRowsNum());
  // query.page(current_page);
  // }
  //
  // /**
  // * ページング結果のリストを取得します。
  // *
  // * @param records
  // * 検索結果
  // * @deprecated
  // */
  // @Deprecated
  // protected List<EipTMail> buildPaginatedList(List<EipTMail> records) {
  // List<EipTMail> list = new ArrayList<EipTMail>();
  //
  // setPageParam(records.size());
  //
  // int size = records.size();
  // int end = (start + rows_num <= size) ? start + rows_num : size;
  // for (int i = start; i < end; i++) {
  // list.add(records.get(i));
  // }
  //
  // return list;
  // }
  // 受入障害対応No.133
  // remove end
  /**
   * 
   * @param cnt
   */
  protected void setPageParam(int cnt) {
    count = cnt;
    pages_num = ((int) (Math.ceil(count / (double) rows_num)));
    current_page = (current_page <= pages_num) ? current_page : pages_num;
    start = rows_num * ((current_page > 0) ? (current_page - 1) : current_page);
  }

  // remove start
  // 受入障害対応No.133
  // /**
  // * ソート用の <code>SelectQuery</code> を構築します。
  // *
  // * @param crt
  // * @return
  // */
  // protected SelectQuery<EipTMail> buildSelectQueryForListViewSort(
  // SelectQuery<EipTMail> query, RunData rundata, Context context) {
  // String sort = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
  // String sort_type = ALEipUtils.getTemp(rundata, context,
  // LIST_SORT_TYPE_STR);
  // String crt_key = null;
  // Attributes map = getColumnMap();
  // if (sort == null) {
  // return query;
  // }
  // crt_key = map.getValue(sort);
  // if (crt_key == null) {
  // return query;
  // }
  // if (sort_type != null
  // && ALEipConstants.LIST_SORT_TYPE_DESC.equals(sort_type)) {
  // query.orderDesending(crt_key);
  // } else {
  // query.orderAscending(crt_key);
  // sort_type = ALEipConstants.LIST_SORT_TYPE_ASC;
  // }
  // current_sort = sort;
  // current_sort_type = sort_type;
  // return query;
  // }

  // /**
  // * ソート用の <code>SelectQuery</code> を構築します。
  // *
  // * @param crt
  // * @return
  // */
  // protected SelectQuery<AvzTMailSend> buildSelectQuerySendForListViewSort(
  // SelectQuery<AvzTMailSend> query, RunData rundata, Context context) {
  // String sort = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
  // String sort_type = ALEipUtils.getTemp(rundata, context,
  // LIST_SORT_TYPE_STR);
  // String crt_key = null;
  // Attributes map = getColumnMap();
  // if (sort == null) {
  // return query;
  // }
  // crt_key = map.getValue(sort);
  // if (crt_key == null) {
  // return query;
  // }
  // if (sort_type != null
  // && ALEipConstants.LIST_SORT_TYPE_DESC.equals(sort_type)) {
  // query.orderDesending(crt_key);
  // } else {
  // query.orderAscending(crt_key);
  // sort_type = ALEipConstants.LIST_SORT_TYPE_ASC;
  // }
  // current_sort = sort;
  // current_sort_type = sort_type;
  // return query;
  // }
  // 受入障害対応No.133
  // remove end

  /**
   * 表示する項目数を設定します。
   * 
   * @param num
   */
  @Override
  public void setRowsNum(int num) {
    if (num >= 1) {
      rows_num = num;
    }
  }

  /**
   * 表示文字数を設定します。
   * 
   * @param num
   */
  public void setStrLength(int num) {
    if (num >= 0) {
      strlen = num;
    }
  }

  /**
   * 表示文字数を取得します。
   * 
   * @return
   */
  @Override
  public int getStrLength() {
    return strlen;
  }

  /**
   * 表示する項目数を取得します。
   * 
   * @return
   */
  @Override
  public int getRowsNum() {
    return rows_num;
  }

  /**
   * 総件数を取得します。
   * 
   * @return
   */
  @Override
  public int getCount() {
    return count;
  }

  /**
   * 総ページ数を取得します。
   * 
   * @return
   */
  @Override
  public int getPagesNum() {
    return pages_num;
  }

  /**
   * 現在表示されているページを取得します。
   * 
   * @return
   */
  @Override
  public int getCurrentPage() {
    return current_page;
  }

  /**
   * 
   * @return
   */
  @Override
  public String getCurrentSort() {
    return current_sort;
  }

  /**
   * 
   * @return
   */
  @Override
  public String getCurrentSortType() {
    return current_sort_type;
  }

  /**
   * 
   * @return
   */
  protected abstract Attributes getColumnMap();

  /**
   * @return
   */
  @Override
  public int getStart() {
    return start;
  }

  // add start
  // 受入障害対応No.133
  /**
   * SQLオブジェクトにページング情報を設定する。
   * 
   * @param query
   *            SQLオブジェクト
   */
  protected void buildSelectQueryForListView(ALEipTMailDirectSelectQuery query) {
    query.limit(getRowsNum());
    query.page(current_page);
  }

  /**
   * SQLオブジェクトにページング情報を設定する。
   * 
   * @param query
   *            SQLオブジェクト
   */
  protected void buildSelectQueryForListView(ALAvzTMailSendDirectSelectQuery query) {
    query.limit(getRowsNum());
    query.page(current_page);
  }

  /**
   * ソート用の <code>SelectQuery</code> を構築します。
   * 
   * @param crt
   * @return
   */
  protected ALEipTMailDirectSelectQuery buildDirectSelectQueryForListViewSort(ALEipTMailDirectSelectQuery query, RunData rundata, Context context) {
    String sort = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
    String sort_type = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
    String crt_key = null;
    Attributes map = getDirectColumnMap();
    if (sort == null) {
      return query;
    }
    crt_key = map.getValue(sort);
    if (crt_key == null) {
      return query;
    }
    if (sort_type != null && ALEipConstants.LIST_SORT_TYPE_DESC.equals(sort_type)) {
      query.orderDesending(crt_key);
    } else {
      query.orderAscending(crt_key);
      sort_type = ALEipConstants.LIST_SORT_TYPE_ASC;
    }
    current_sort = sort;
    current_sort_type = sort_type;
    return query;
  }

  /**
   * ソート用の <code>SelectQuery</code> を構築します。
   * 
   * @param crt
   * @return
   */
  protected ALAvzTMailSendDirectSelectQuery buildDirectSelectQueryForListViewSort(ALAvzTMailSendDirectSelectQuery query, RunData rundata, Context context) {
    String sort = ALEipUtils.getTemp(rundata, context, LIST_SORT_STR);
    String sort_type = ALEipUtils.getTemp(rundata, context, LIST_SORT_TYPE_STR);
    String crt_key = null;
    Attributes map = getDirectColumnMap();
    if (sort == null) {
      return query;
    }
    crt_key = map.getValue(sort);
    if (crt_key == null) {
      return query;
    }
    if (sort_type != null && ALEipConstants.LIST_SORT_TYPE_DESC.equals(sort_type)) {
      query.orderDesending(crt_key);
    } else {
      query.orderAscending(crt_key);
      sort_type = ALEipConstants.LIST_SORT_TYPE_ASC;
    }
    current_sort = sort;
    current_sort_type = sort_type;
    return query;
  }

  protected Attributes getDirectColumnMap() {
    Attributes map = new Attributes();
    map.putValue("read_flg", "read_flg");
    map.putValue("subject", "subject");
    map.putValue("person", "person");
    map.putValue("date", "event_date");
    map.putValue("volume", "volume");
    map.putValue("has_files", "has_files");
    return map;
  }

  // 受入障害対応No.133
  // add end

  // add start 運用フェーズ障害128
  private String convertNullChar(String src, boolean convertNull) {
    if (!convertNull) {
      return src;
    }
    return src.replace("\0", ALMailUtils.REPLACE_NULL_CHAR);
  }

  // add end

  // add start 運用フェーズ課題・障害台帳No.１３３
  /**
   * 差出人（受取人）キーワードで個人アドレス帳を検索し、メールアドレスを取得して、検索キーワードを構築する
   * 
   * @param userid
   *            ユーザーID
   * @param word
   *            差出人（受取人）キーワード
   * @return 検索キーワード
   */
  public static List<String> convertAddressSearchWord(int userid, String word) {
    List<String> list = new ArrayList<String>(0);
    // 差出人（受取人）キーワード（画面入力値）はデフォルトとして設定
    list.add(word);

    SelectQuery<EipMAddressbook> query = Database.query(EipMAddressbook.class);

    Expression exp01 = ExpressionFactory.matchExp(EipMAddressbook.OWNER_ID_PROPERTY, userid);
    Expression exp02 = ExpressionFactory.likeExp(EipMAddressbook.LAST_NAME_PROPERTY, "%" + word + "%");
    query.select(EipMAddressbook.EMAIL_COLUMN);
    query.setQualifier(exp01).andQualifier(exp02);

    List<EipMAddressbook> addressbook_list = query.fetchList();

    if (addressbook_list != null && addressbook_list.size() > 0) {
      for (EipMAddressbook record : addressbook_list) {
        // ヒットした個人アドレスのメールアドレスを設定
        list.add(record.getEmail());
      }
    }
    return list;
  }
  // add end
}
