/*
* Copyright 2011 cruxframework.org.
*
* 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 org.cruxframework.crux.core.client.executor;
import java.util.Date;
import com.google.gwt.user.client.Timer;
/**
* An executor that only executes the first and the last
* call to a given action.
* "Last call" means "the last call in N milliseconds",
* where N can be parameterized at the constructor.
* If there was only one call (begin call), a second one (end call)
* is emulated.
*
* @author Gesse Dafe
*/
public abstract class BeginEndExecutor
{
private int maxIntervalBetweenStartAndEnd;
private long lastExec = new Date().getTime();
boolean isRunning = false;
private boolean doEndActionExecuted = false;
/**
* Creates an executor that only executes the first and the last
* call to a given action.
*
* @param end if more than <code>maxIntervalBetweenStartAndEnd</code>
* milliseconds has passed since the previous call, considers that
* the current call is a begin call.
*/
public BeginEndExecutor(int maxIntervalBetweenStartAndEnd)
{
this.maxIntervalBetweenStartAndEnd = maxIntervalBetweenStartAndEnd;
}
/**
* Used for scheduling the end call
*/
private Timer timer = new Timer()
{
public void run()
{
execute();
}
};
/**
* Throttles the invocations on the executor
*/
public void execute()
{
long now = new Date().getTime();
if(timer != null)
{
timer.cancel();
}
if(!isRunning)
{
if (doEndActionExecuted)
{
long delta = now - lastExec;
if(delta > maxIntervalBetweenStartAndEnd)
{
isRunning = true;
doBeginAction();
timer.schedule(maxIntervalBetweenStartAndEnd);
}
}
else
{
isRunning = true;
doBeginAction();
timer.schedule(maxIntervalBetweenStartAndEnd);
}
}
else
{
if(timer != null)
{
timer.cancel();
}
long delta = now - lastExec;
if(delta < maxIntervalBetweenStartAndEnd)
{
timer.schedule(maxIntervalBetweenStartAndEnd);
}
else
{
doEndAction();
isRunning = false;
doEndActionExecuted = true;
}
}
lastExec = now;
}
/**
* Called when the first call is made for the executor
*/
protected abstract void doEndAction();
/**
* Called when the last call is made for the executor
*/
protected abstract void doBeginAction();
}