/*
* Copyright 2010 Gal Dolber.
*
* Licensed 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.
*/
package com.guit.client.command;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.logging.client.LogConfiguration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.guit.client.async.AbstractAsyncCallback;
import com.guit.client.async.event.LoadingEvent;
import com.guit.client.command.action.Action;
import com.guit.client.command.action.Response;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.logging.Logger;
public class CommandServiceImpl implements CommandService, ScheduledCommand {
private final EventBus eventBus;
private final CommandRpcAsync service;
private final Logger logger = Logger.getLogger("CommandServiceImpl");
private int executions = 0;
private HashMap<Action<Response>, ArrayList<AsyncCallback<Response>>> actionsMap =
new LinkedHashMap<Action<Response>, ArrayList<AsyncCallback<Response>>>();
// Requests pools
private final ArrayList<CommandBatchRequestUnit> singleRequestPool =
new ArrayList<CommandBatchRequestUnit>();
private final ArrayList<CommandSingleRequestUnit> batchRequestPool =
new ArrayList<CommandSingleRequestUnit>();
// Cache
private final HashMap<Action<Response>, Response> cache =
new HashMap<Action<Response>, Response>();
private boolean schedulerActive = false;
@Inject
public CommandServiceImpl(EventBus eventBus, CommandRpcAsync service) {
this.eventBus = eventBus;
this.service = service;
}
@Override
public <A extends Action<R>, R extends Response> void execute(A action,
AbstractAsyncCallback<R> callback) {
addToBatch(action, callback);
if (!schedulerActive) {
Scheduler.get().scheduleDeferred(this);
schedulerActive = true;
}
}
@SuppressWarnings("unchecked")
public <A, R> void addToBatch(A action, AsyncCallback<R> callback) {
ArrayList<AsyncCallback<Response>> callbacks = actionsMap.get(action);
if (callbacks == null) {
callbacks = new ArrayList<AsyncCallback<Response>>();
}
callbacks.add((AsyncCallback<Response>) callback);
actionsMap.put((Action<Response>) action, callbacks);
if (LogConfiguration.loggingIsEnabled()) {
logger.info(actionsMap.size() + " actions in queue");
}
}
@Override
public <A extends Action<R>, R extends Response> void executeLater(A action,
AbstractAsyncCallback<R> callback) {
addToBatch(action, callback);
}
/**
* Get a single request unit.
*/
private CommandBatchRequestUnit getBatchRequestUnit() {
if (singleRequestPool.size() > 0) {
CommandBatchRequestUnit poolInstance = singleRequestPool.get(0);
singleRequestPool.remove(0);
return poolInstance;
} else {
return new CommandBatchRequestUnit(cache, eventBus, service,
new CommandRequestUnitFinish<CommandBatchRequestUnit>() {
@Override
public void onFinish(CommandBatchRequestUnit requestUnit) {
singleRequestPool.add(requestUnit);
executions--;
if (executions == 0) {
eventBus.fireEvent(new LoadingEvent(true));
}
}
});
}
}
/**
* Get a batch request unit.
*/
private CommandSingleRequestUnit getSingleRequestUnit() {
if (batchRequestPool.size() > 0) {
CommandSingleRequestUnit poolInstance = batchRequestPool.get(0);
batchRequestPool.remove(0);
return poolInstance;
} else {
return new CommandSingleRequestUnit(cache, eventBus, service,
new CommandRequestUnitFinish<CommandSingleRequestUnit>() {
@Override
public void onFinish(CommandSingleRequestUnit requestUnit) {
batchRequestPool.add(requestUnit);
executions--;
if (executions == 0) {
eventBus.fireEvent(new LoadingEvent(true));
}
}
});
}
}
@Override
public void deleteCache() {
cache.clear();
}
@Override
public void execute() {
schedulerActive = false;
if (LogConfiguration.loggingIsEnabled()) {
logger.info("Execute " + actionsMap.size() + " actions");
}
if (!actionsMap.isEmpty()) {
eventBus.fireEvent(new LoadingEvent(false));
executions++;
HashMap<Action<Response>, ArrayList<AsyncCallback<Response>>> copy =
new HashMap<Action<Response>, ArrayList<AsyncCallback<Response>>>();
copy.putAll(actionsMap);
actionsMap = new HashMap<Action<Response>, ArrayList<AsyncCallback<Response>>>();
if (actionsMap.size() == 1) {
getSingleRequestUnit().execute(copy);
} else {
getBatchRequestUnit().execute(copy);
}
}
}
}