Package net.solosky.maplefetion.client.dialog

Source Code of net.solosky.maplefetion.client.dialog.DialogFactory$IdleDialogCheckTask

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Project  : MapleFetion2
* Package  : net.solosky.net.maplefetion.client.dialog
* File     : DialogFactory.java
* Author   : solosky < solosky772@qq.com >
* Created  : 2010-1-10
* License  : Apache License 2.0
*/
package net.solosky.maplefetion.client.dialog;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TimerTask;

import net.solosky.maplefetion.FetionConfig;
import net.solosky.maplefetion.FetionContext;
import net.solosky.maplefetion.bean.Buddy;
import net.solosky.maplefetion.bean.Group;
import net.solosky.maplefetion.bean.Presence;
import net.solosky.maplefetion.bean.Relation;
import net.solosky.maplefetion.net.TransferException;
import net.solosky.maplefetion.net.TransferFactory;
import net.solosky.maplefetion.sipc.SipcNotify;

/**
*
* 对话工厂,建立三种类型的对话
*
* @author solosky <solosky772@qq.com>
*/
public class DialogFactory
{
  /**
   * 客户端对象
   */
  private FetionContext context;

  /**
   * 服务器对话
   */
  private ServerDialog serverDialog;

  /**
   * 聊天对话列表
   */
  private ArrayList<ChatDialog> chatDialogList;

  /**
   * 群对话框列表
   */
  private ArrayList<GroupDialog> groupDialogList;
 
  /**
   * 定时空闲对话框检查任务
   */
  private TimerTask idleDialogCheckTask;
 

  /**
   * 默认构造函数
   *
   * @param client
   */
  public DialogFactory(FetionContext client)
  {
    this.context = client;
    this.chatDialogList = new ArrayList<ChatDialog>();
    this.groupDialogList = new ArrayList<GroupDialog>();
    this.idleDialogCheckTask = new IdleDialogCheckTask();

    this.context.getFetionTimer().scheduleTask(this.idleDialogCheckTask, 0 ,
                    FetionConfig.getInteger("fetion.dialog.check-idle-interval") * 1000);
  }

  /**
   * 创建服务器对话,只能创建一次
   *
   * @param user
   *            登录用户对象
   */
  public synchronized ServerDialog createServerDialog()
  {
    if(this.serverDialog==null) {
      this.serverDialog = new ServerDialog(context);
      return this.serverDialog;
    }else {
      throw new IllegalStateException("ServerDialog arealy created...");
    }
  }

  /**
   * 创建聊天对话
   *
   * @param buddy
   *            好友对象
   * @return
   */
  public synchronized ChatDialog createChatDialog(Buddy buddy)
          throws DialogException
  {
    Relation relation = buddy.getRelation();
    if( relation==Relation.BANNED ||
      relation==Relation.DECLINED ||
      relation==Relation.UNCONFIRMED) {
      throw new DialogException("Buddy relation is +"+buddy.getRelation()+", you couldn't send chat message to this buddy.");
    }
    ChatDialog dialog = this.findChatDialog(buddy);
    if (dialog != null && dialog.getState()!=DialogState.CLOSED && dialog.getState()!=DialogState.FAILED)
      return dialog;

    int presence = buddy.getPresence().getValue();
    // 如果用户手机在线 或者电脑离线,将建立手机聊天对话框
    if (presence == Presence.OFFLINE) {
      dialog = new BasicChatDialog(this.context, buddy);
    } else if (presence == Presence.ONLINE || presence == Presence.AWAY ||
                presence == Presence.BUSY   || presence == Presence.ROBOT ) { // 如果用户电脑在线,建立在线聊天对话框
      TransferFactory factory = this.context.getTransferFactory();
      if (factory.isMutiConnectionSupported()) {
        dialog = new LiveV2ChatDialog(buddy, this.context);
      } else {
        dialog = new LiveV1ChatDialog(buddy, this.context);
      }
    } else {
      throw new DialogException("Illegal buddy presence - presence="
              + Integer.toString(presence));
    }

    // 添加对话框至列表并返回
    this.chatDialogList.add(dialog);
    return dialog;
  }

  /**
   * 以一个邀请通知创建会话
   *
   * @param inviteNotify
   *            邀请的通知
   * @return
   */
  public synchronized ChatDialog createChatDialog(SipcNotify inviteNotify) throws DialogException
  {
    // 当收到会话邀请时,发起邀请的好友一定是在线,手机在线的好友是不会发起会话邀请的,所以这里无需判断好友状态
    ChatDialog dialog = null;

    if (this.context.getTransferFactory().isMutiConnectionSupported()) {
      dialog = new LiveV2ChatDialog(inviteNotify, context);
    } else {
      dialog = new LiveV1ChatDialog(inviteNotify, context);
    }
    this.chatDialogList.add(dialog);

    return dialog;
  }

  /**
   * 创建群组对话
   *
   * @param group
   *            群对象
   * @return
   */
  public synchronized GroupDialog createGroupDialog(Group group)
  {
    GroupDialog dialog = new GroupDialog(this.context, group);
    this.groupDialogList.add(dialog);
    return dialog;
  }

  /**
   * 查找聊天对话框 只是查找对话框的主要参与者
   *
   * @param buddy
   *            飞信对象
   * @return
   */
  public synchronized ChatDialog findChatDialog(Buddy buddy)
  {
    Iterator<ChatDialog> it = this.chatDialogList.iterator();
    ChatDialog dialog = null;
    while (it.hasNext()) {
      dialog = it.next();
      if (dialog.getMainBuddy().equals(buddy)) {
        return dialog;
      }
    }
    return null;
  }
 
  /**
   * 查找对话,如果对话不存在,建立一个新的对话
   * @param buddy    对话的好友
   * @return      聊天对话
   * @throws DialogException
   */
  public synchronized ChatDialog findOrCreateChatDialog(Buddy buddy) throws DialogException
  {
    ChatDialog dialog  = this.findChatDialog(buddy);
    if(dialog==null)
      dialog = this.createChatDialog(buddy);
   
    return dialog;
  }
 
  /**
   * 返回一个聊天对话框,首先查找当前活动的聊天对话,如果找到并且没有关闭就返回这个对话
   * 如果不存在或者会话已经关闭就新建立一个对话并返回
   * @param buddy    好友对象
   * @return      聊天对话
   * @throws DialogException
   */
  public synchronized ChatDialog getChatDialog(Buddy buddy) throws DialogException
  {
    ChatDialog dialog = this.findChatDialog(buddy);
    if(dialog!=null && dialog.getState()!=DialogState.CLOSED) {
      return dialog;
    }else {
      return this.createChatDialog(buddy);
    }
   
  }

  /**
   * 查找群对话框
   *
   * @param group
   *            群对象
   * @return
   */
  public synchronized GroupDialog findGroupDialog(Group group)
  {
    Iterator<GroupDialog> it = this.groupDialogList.iterator();
    GroupDialog dialog = null;
    while (it.hasNext()) {
      dialog = it.next();
      if (dialog.getGroup().equals(group)) {
        break;
      }
    }

    return dialog;
  }

  /**
   * 返回服务器对话框
   *
   * @return
   */
  public ServerDialog getServerDialog()
  {
    return this.serverDialog;
  }
 
  /**
   * 移除对话,不会关闭对话
   */
  public synchronized void removeDialog(Dialog dialog)
  {
    if (dialog instanceof ChatDialog) {
      this.chatDialogList.remove(dialog);
    }else if(dialog instanceof GroupDialog){
      this.groupDialogList.remove(dialog);
    }
  }
 
  /**
   * 关闭所有的对话框
   * @throws TransferException
   * @throws DialogException
   */
  public synchronized void closeAllDialog() throws TransferException, DialogException
  {
    ArrayList<GroupDialog> tmpGroupList = new ArrayList<GroupDialog>();
    tmpGroupList.addAll(this.groupDialogList);
    Iterator<GroupDialog> git = tmpGroupList.iterator();
    while(git.hasNext()) {
      git.next().closeDialog();
    }
   
    ArrayList<ChatDialog> tmpChatList   = new ArrayList<ChatDialog>();
    tmpChatList.addAll(this.chatDialogList);
    Iterator<ChatDialog> cit = tmpChatList.iterator();
    while(cit.hasNext()) {
      cit.next().closeDialog();
    }
   
    if(this.serverDialog!=null) {
      this.serverDialog.closeDialog();
      this.serverDialog = null;
    }
  }
 
 
  /**
   * 关闭对话框工厂
   * 停止定时任务
   */
  public void closeFactory()
  {
    this.idleDialogCheckTask.cancel();
    this.context.getFetionTimer().clearCanceledTask();
  }
 
 
  /**
   * 为了减少资源占用率,如果用户没有手动关闭对话框,就需要一个计划任务定时检查空闲的对话框,
   * 如果对话框在指定的时间没有收到消息,就关闭这个对话框
   */
  public synchronized void checkIdleDialog()
  {
    int maxIdleTime = FetionConfig
        .getInteger("fetion.dialog.max-idle-time"); // 最大空闲时间,单位秒,用户可以设置
        Iterator<ChatDialog> it = chatDialogList.iterator();
        while (it.hasNext()) {
          ChatDialog dialog = it.next();
          if (dialog.getState()==DialogState.CLOSED) {
            it.remove();
          }else if (dialog.getActiveTime() + maxIdleTime < (int) (System.currentTimeMillis() / 1000)) {
            //异步关闭,如果在这里关闭,因为有了一把DialogFactory的锁,在关闭对话框的过程中会去获得
            //相应对话框的锁,这就可能出现死锁,因此这里把关闭操作放在另外一个线程里,就不会出现死锁
            dialog.closeDialog(null);   
                it.remove();
          } else {
          }
        }
  }

  /**
   * 定时检查空闲对话框任务,只是对checkIdleDialog()的一个封装
   *
   * @author solosky <solosky772@qq.com>
   */
  private class IdleDialogCheckTask extends TimerTask
  {
    @Override
    public void run()
    {
      checkIdleDialog();
    }

  }
}
TOP

Related Classes of net.solosky.maplefetion.client.dialog.DialogFactory$IdleDialogCheckTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.