/* Copyright (c) 2011 Danish Maritime Authority
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
package dk.dma.ais.abnormal.analyzer.analysis;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.MoreExecutors;
import dk.dma.ais.abnormal.analyzer.behaviour.BehaviourManager;
import dk.dma.ais.abnormal.event.db.EventRepository;
import dk.dma.ais.tracker.eventEmittingTracker.EventEmittingTracker;
import dk.dma.ais.tracker.eventEmittingTracker.events.TimeEvent;
import net.jcip.annotations.NotThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.concurrent.Executor;
/**
* An Analysis is a class which is known to the ais-ab-analyzer application and possesses certain public
* methods which can be called to analyze and detect events.
*
* The Analysis class is an abstract class which all analyses must inherit from.
*
* The Analysis class provides basic methods to its subclasses, so they can reuse the code to raise and
* lower events.
*
* @author Thomas Borg Salling <tbsalling@tbsalling.dk>
*
*/
@NotThreadSafe
public abstract class PeriodicAnalysis extends Analysis {
private static final Logger LOG = LoggerFactory.getLogger(PeriodicAnalysis.class);
/** Minimum no. of msecs between runs of this analysis. */
private int analysisPeriodMillis = Integer.MAX_VALUE;
/** The time when the next analysis should be run. */
private long currentRunTime = -1L;
/** The time when the next analysis should be run. */
private long nextRunTime = 0L;
/** Executor to perform the actual work. */
private final Executor executor = MoreExecutors.directExecutor();
public PeriodicAnalysis(EventRepository eventRepository, EventEmittingTracker trackingService, BehaviourManager behaviourManager) {
super(eventRepository, trackingService, behaviourManager);
}
@Override
public String toString() {
return "PeriodicAnalysis{" +
"analysisPeriodMillis=" + analysisPeriodMillis +
"} " + super.toString();
}
/** Perform the actual analysis */
protected abstract void performAnalysis();
protected void setAnalysisPeriodMillis(int analysisPeriodMillis) {
this.analysisPeriodMillis = analysisPeriodMillis;
}
@Subscribe
public void onMark(TimeEvent timeEvent) {
final long now = timeEvent.getTimestamp().toEpochMilli();
if (nextRunTime <= now) {
currentRunTime = now;
if (LOG.isDebugEnabled()) {
LOG.debug("currentRunTime: " + new Date(currentRunTime) + " " + currentRunTime + " (nextRunTime was " + new Date(nextRunTime) + " " + nextRunTime + ")");
}
executor.execute(() -> performAnalysis());
currentRunTime = -1L;
nextRunTime = now + analysisPeriodMillis;
if (LOG.isDebugEnabled()) {
LOG.debug("nextRunTime: " + new Date(nextRunTime) + " " + nextRunTime);
}
}
}
public long getCurrentRunTime() {
return currentRunTime;
}
public long getNextRunTime() {
return nextRunTime;
}
}