package com.aincc.lib.network;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.RejectedExecutionException;
import com.aincc.lib.network.common.BaseTask;
import com.aincc.lib.network.common.BaseTrans;
import com.aincc.lib.network.common.BaseTransEx;
import com.aincc.lib.network.common.INetworkListener;
import com.aincc.lib.network.common.NetworkErrorType;
import com.aincc.lib.network.http.HttpTask;
import com.aincc.lib.network.http.HttpTrans;
/**
*
* <h3><b>NetworkProcessor</b></h3></br>
*
* network processor
*
* @author aincc@barusoft.com
* @version 1.0.0
* @since 1.0.0
*/
public class NetHttpProcessor
{
/**
* error message mapping list
*
* @since 1.0.0
*/
private static HashMap<Integer, NetworkErrorType> errorMap = new HashMap<Integer, NetworkErrorType>();
/**
* processor
*
* @since 1.0.0
*/
private volatile static NetHttpProcessor processor;
/**
* max concurrent task count
*
* @since 1.0.0
*/
private static final int MAX_CONCURRENT = 10;
/**
* max task sequence
*
* @since 1.0.0
*/
private static final int MAX_TASK_SEQ = 65536;
/**
* invalid sequence
*
* @since 1.0.0
*/
public static final int INVALID_UNI_SEQ = -1;
/**
* task sequence
*
* @since 1.0.0
*/
private static int taskSeq = 0;
/**
* running task count
*
* @since 1.0.0
*/
private int runningCount = 0;
/**
* running task
*
* @since 1.0.0
*/
private Hashtable<Integer, BaseTask<?>> runningTask = null;
/**
* delayed task
*
* @since 1.0.0
*/
private Queue<BaseTask<?>> delayedTask = null;
/**
* regist message for specific error type
*
* @since 1.0.0
* @param type
* @param message
*/
public static void registerErrorMessage(NetworkErrorType type, String message)
{
if (null != message)
{
type.setMessage(message);
}
errorMap.put(type.getType(), type);
}
/**
*
* @since 1.0.0
* @param type
* @return NetworkErrorType
*/
public static NetworkErrorType getErrorMessage(NetworkErrorType type)
{
if (errorMap.containsKey(type.getType()))
{
return errorMap.get(type.getMessage());
}
return NetworkErrorType.UNKNOWN_ERROR;
}
/**
*
* @since 1.0.0
*/
public static NetHttpProcessor getInstance()
{
if (null == processor)
{
synchronized (NetHttpProcessor.class)
{
if (null == processor)
{
processor = new NetHttpProcessor();
}
}
}
return processor;
}
/**
* send transaction (for http)
*
* @since 1.0.0
* @param serviceUrl
* @param listener
* @param task
*/
public void sendHttp(String serviceUrl, INetworkListener listener, HttpTask<?, ?> task)
{
task.setListener(listener);
task.setProcessor(processor);
((HttpTrans) task.getTr()).setServiceUri(serviceUrl);
processor.send(task);
}
/**
* cancel all
*
* @since 1.0.0
*/
public void cancelAll()
{
processor.cancel();
}
/**
* private constructor
*
* @since 1.0.0
*/
private NetHttpProcessor()
{
if (null == runningTask)
{
runningTask = new Hashtable<Integer, BaseTask<?>>();
}
if (null == delayedTask)
{
delayedTask = new LinkedList<BaseTask<?>>();
}
}
/**
* send transaction
*
* @since 1.0.0
* @param task
*/
private void send(HttpTask<?, ?> task)
{
synchronized (this)
{
try
{
taskSeq = (taskSeq + 1) % MAX_TASK_SEQ;
task.setTaskSeq(taskSeq);
if (runningCount >= MAX_CONCURRENT)
{
delayedTask.add(task);
}
else
{
runningCount++;
runningTask.put(task.getTaskSeq(), task);
task.execute();
}
}
catch (RejectedExecutionException e)
{
e.printStackTrace();
task.getListener().iNetRejectedExecution(new BaseTransEx(getErrorMessage(NetworkErrorType.ERROR_SEND).toString(), ((BaseTrans) task.getTr()).getParam()));
}
}
}
/**
*
* @since 1.0.0
*/
private void cancel()
{
synchronized (this)
{
delayedTask.clear();
Set<Entry<Integer, BaseTask<?>>> entrySet = runningTask.entrySet();
Iterator<Entry<Integer, BaseTask<?>>> it = entrySet.iterator();
while (it.hasNext())
{
Entry<Integer, BaseTask<?>> entry = it.next();
BaseTask<?> task = entry.getValue();
if (null != task && task.isRunning())
{
task.cancel(true);
}
}
runningTask.clear();
runningCount = 0;
}
}
/**
*
* @since 1.0.0
* @param completeTaskKey
*/
public void nextTask(int completeTaskKey)
{
synchronized (this)
{
if (runningTask.containsKey(completeTaskKey))
{
runningTask.remove(completeTaskKey);
}
if (runningCount > 0)
{
runningCount--;
if (!delayedTask.isEmpty())
{
processor.send((HttpTask<?, ?>) delayedTask.poll());
}
}
}
}
}