TestRoots/watchdog

View on GitHub
core/src/nl/tudelft/watchdog/core/logic/interval/IDEIntervalManagerBase.java

Summary

Maintainability
A
0 mins
Test Coverage
package nl.tudelft.watchdog.core.logic.interval;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.RandomStringUtils;

import nl.tudelft.watchdog.core.logic.interval.intervaltypes.EditorIntervalBase;
import nl.tudelft.watchdog.core.logic.interval.intervaltypes.IntervalBase;
import nl.tudelft.watchdog.core.logic.interval.intervaltypes.TypingInterval;
import nl.tudelft.watchdog.core.logic.storage.PersisterBase;
import nl.tudelft.watchdog.core.util.WatchDogLogger;

/**
 * Base class for managing intervals generated by the IDE.
 * Contains functionality for retrieving, adding and closing intervals.
 * Each plugin should extends this class and implement the missing functionality.
 */
public abstract class IDEIntervalManagerBase extends IntervalManagerBase {

    private EditorIntervalBase editorInterval;

    /**
     * The session seed, a random number generated on each instantiation of the
     * IntervalManager to be able to tell running Eclipse instances apart.
     */
    private String sessionSeed;

    private PersisterBase intervalsToTransferPersister;

    private PersisterBase intervalsStatisticsPersister;

    /** Constructor. */
    protected IDEIntervalManagerBase(PersisterBase intervalsToTransferPersister,
            PersisterBase intervalsStatisticsPersister) {
        this.intervalsToTransferPersister = intervalsToTransferPersister;
        this.intervalsStatisticsPersister = intervalsStatisticsPersister;
        generateAndSetSessionSeed();
    }

    /** Generates and sets a new random session seed. */
    public void generateAndSetSessionSeed() {
        this.sessionSeed = RandomStringUtils.randomAlphabetic(40);
    }

    /**
     * Adds the supplied interval to the list of intervals. New intervals must
     * use this method to be registered properly. Handles the addition of
     * already closed intervals properly. Delegates to the correct adding
     * mechanism.
     */
    public void addInterval(IntervalBase interval) {
        interval.setSessionSeed(sessionSeed);
        if (interval instanceof EditorIntervalBase) {
            EditorIntervalBase editorInterval = (EditorIntervalBase) interval;
            addEditorInterval(editorInterval);
        } else {
            addRegularIntervalBase(interval);
        }

        WatchDogLogger.getInstance().logInfo(
                "Created interval " + interval + " " + interval.getType());
        if (interval.isClosed()) {
            closeInterval(interval);
        }
    }

    private void addRegularIntervalBase(IntervalBase interval) {
        if (intervals.size() > 30) {
            WatchDogLogger
                    .getInstance()
                    .logSevere(
                            "Too many open intervals. Something fishy is going on here! Cannot add more intervals.");
            return;
        }
        intervals.add(interval);
    }

    /**
     * Updates the given EditorIntervalBase.
     */
    private void addEditorInterval(EditorIntervalBase editorInterval) {
        this.editorInterval = editorInterval;
    }

    /**
     * Closes the current interval (if it is not already closed). Handles
     * <code>null</code> gracefully.
     */
    public void closeInterval(IntervalBase interval, Date forcedDate) {
        if (interval == null) {
            return;
        }

        interval.setEndTime(forcedDate);
        closeInterval(interval);
    }

    private void closeInterval(IntervalBase interval) {
        if (interval == null) {
            return;
        }

        if (interval instanceof TypingInterval) {
            TypingInterval typingInterval = (TypingInterval) interval;
            setEndingDocumentOf(typingInterval);
        }

        interval.close();

        if (interval instanceof EditorIntervalBase) {
            editorInterval = null;
        } else {
            intervals.remove(interval);
        }
        intervalsToTransferPersister.save(interval);
        intervalsStatisticsPersister.save(interval);
        WatchDogLogger.getInstance().logInfo(
                "closed interval " + interval + " " + interval.getType());
    }

    /**
     * Sets the ending document of the given typing interval.
     * To be implemented by the subclasses for specific IDEs.
     */
    protected abstract void setEndingDocumentOf(TypingInterval typingInterval);

    /** Closes all currently open intervals. */
    public void closeAllIntervals() {
        Date closingDate = new Date();
        closeAllIntervals(closingDate);
    }

    /** Closes all currently open intervals with the supplied closing date. */
    public void closeAllIntervals(Date closingDate) {
        closeInterval(editorInterval, closingDate);
        ArrayList<IntervalBase> copiedIntervals = new ArrayList<IntervalBase>(intervals);
        Iterator<IntervalBase> iterator = copiedIntervals.listIterator();
        while (iterator.hasNext()) {
            // we need to remove the interval first from the list in order to
            // avoid ConcurrentListModification Exceptions.
            IntervalBase interval = iterator.next();
            iterator.remove();
            closeInterval(interval, closingDate);
        }
        intervals.clear();
    }

    /**
     * @return the single {@link EditorIntervalBase} that is actually a
     *         {@link EditorIntervalBase}. There can only be one such interval
     *         at any given time. If there is none, <code>null</code>.
     */
    public EditorIntervalBase getEditorInterval() {
        return editorInterval;
    }

    /** Returns an immutable list of recorded intervals. */
    public List<IntervalBase> getOpenIntervals() {
        return Collections.unmodifiableList(intervals);
    }

    /**
     * @return the statistics persister.
     */
    public PersisterBase getIntervalsStatisticsPersister() {
        return intervalsStatisticsPersister;
    }

    /**
     * @return the session seed used by this interval manager.
     */
    public String getSessionSeed() {
        return sessionSeed;
    }

}