/**
* Copyright 2010 JBoss Inc
*
* 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.jbpm.process.instance.timer;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.drools.common.InternalKnowledgeRuntime;
import org.drools.time.Job;
import org.drools.time.JobContext;
import org.drools.time.JobHandle;
import org.drools.time.TimerService;
import org.drools.time.impl.IntervalTrigger;
import org.jbpm.process.instance.InternalProcessRuntime;
import org.jbpm.process.instance.ProcessInstance;
/**
*
* @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
*/
public class TimerManager {
private long timerId = 0;
private InternalKnowledgeRuntime kruntime;
private TimerService timerService;
private Map<Long, TimerInstance> timers = new HashMap<Long, TimerInstance>();
private Job processJob = new ProcessJob();
public TimerManager(InternalKnowledgeRuntime kruntime,
TimerService timerService) {
this.kruntime = kruntime;
this.timerService = timerService;
}
public void registerTimer(final TimerInstance timer,
ProcessInstance processInstance) {
timer.setId( ++timerId );
timer.setProcessInstanceId( processInstance.getId() );
timer.setActivated( new Date() );
ProcessJobContext ctx = new ProcessJobContext( timer,
processInstance.getId(),
this.kruntime );
JobHandle jobHandle = this.timerService.scheduleJob( processJob,
ctx,
new IntervalTrigger( timerService.getCurrentTime(),
null,
null,
-1,
timer.getDelay(),
timer.getPeriod(),
null,
null ) );
timer.setJobHandle( jobHandle );
timers.put( timer.getId(),
timer );
}
public void internalAddTimer(final TimerInstance timer) {
ProcessJobContext ctx = new ProcessJobContext( timer,
timer.getProcessInstanceId(),
this.kruntime );
long delay;
Date lastTriggered = timer.getLastTriggered();
if ( lastTriggered == null ) {
Date activated = timer.getActivated();
Date now = new Date();
long timespan = now.getTime() - activated.getTime();
delay = timer.getDelay() - timespan;
if ( delay < 0 ) {
delay = 0;
}
} else {
Date now = new Date();
long timespan = now.getTime() - lastTriggered.getTime();
delay = timespan - timer.getPeriod();
if ( delay < 0 ) {
delay = 0;
}
}
JobHandle jobHandle = this.timerService.scheduleJob( processJob,
ctx,
new IntervalTrigger( timerService.getCurrentTime(),
null,
null,
-1,
delay,
timer.getPeriod(),
null,
null ) );
timer.setJobHandle( jobHandle );
timers.put( timer.getId(),
timer );
}
public void cancelTimer(long timerId) {
TimerInstance timer = timers.remove( timerId );
if ( timer != null ) {
timerService.removeJob( timer.getJobHandle() );
}
}
public void dispose() {
for ( TimerInstance timer : timers.values() ) {
timerService.removeJob( timer.getJobHandle() );
}
timerService.shutdown();
}
public TimerService getTimerService() {
return this.timerService;
}
public Collection<TimerInstance> getTimers() {
return timers.values();
}
public long internalGetTimerId() {
return timerId;
}
public void internalSetTimerId(long timerId) {
this.timerId = timerId;
}
public void setTimerService(TimerService timerService) {
this.timerService = timerService;
}
public class ProcessJob
implements
Job {
public void execute(JobContext c) {
ProcessJobContext ctx = (ProcessJobContext) c;
Long processInstanceId = ctx.getProcessInstanceId();
InternalKnowledgeRuntime kruntime = ctx.getKnowledgeRuntime();
if ( processInstanceId == null ) {
throw new IllegalArgumentException( "Could not find process instance for timer " );
}
ctx.getTimer().setLastTriggered( new Date() );
((InternalProcessRuntime) kruntime.getProcessRuntime())
.getSignalManager().signalEvent( processInstanceId,
"timerTriggered",
ctx.getTimer() );
if ( ctx.getTimer().getPeriod() == 0 ) {
TimerManager.this.timers.remove( ctx.getTimer().getId() );
}
}
}
public static class ProcessJobContext
implements
JobContext {
private Long processInstanceId;
private InternalKnowledgeRuntime kruntime;
private TimerInstance timer;
private JobHandle jobHandle;
public ProcessJobContext(final TimerInstance timer,
final Long processInstanceId,
final InternalKnowledgeRuntime kruntime) {
this.timer = timer;
this.processInstanceId = processInstanceId;
this.kruntime = kruntime;
}
public Long getProcessInstanceId() {
return processInstanceId;
}
public InternalKnowledgeRuntime getKnowledgeRuntime() {
return kruntime;
}
public JobHandle getJobHandle() {
return this.jobHandle;
}
public void setJobHandle(JobHandle jobHandle) {
this.jobHandle = jobHandle;
}
public TimerInstance getTimer() {
return timer;
}
}
}