net.femtoparsec.jnlmin.AbstractTokenTask.java Source code

Java tutorial

Introduction

Here is the source code for net.femtoparsec.jnlmin.AbstractTokenTask.java

Source

/*
 * @copyright Copyright (c) 2012, Bastien Aracil
 *    All rights reserved.
 *    New BSD license. See http://en.wikipedia.org/wiki/Bsd_license
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *       * Redistributions of source code must retain the above copyright
 *         notice, this list of conditions and the following disclaimer.
 *       * Redistributions in binary form must reproduce the above copyright
 *         notice, this list of conditions and the following disclaimer in the
 *         documentation and/or other materials provided with the distribution.
 *       * The name of Bastien Aracil may not be used to endorse or promote products
 *         derived from this software without specific prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *    DISCLAIMED. IN NO EVENT SHALL BASTIEN ARACIL BE LIABLE FOR ANY
 *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package net.femtoparsec.jnlmin;

import org.apache.commons.lang3.Validate;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * @author Bastien Aracil
 * Date: 29/11/12
 */
public abstract class AbstractTokenTask<T extends MinimizerResult> implements TokenTask<T> {

    private Deque<MinimizerListener> listeners = new ArrayDeque<>();

    private final StatusManager statusManager;

    private final GenericMinimizerTokenResult<T> tokenResult;

    protected AbstractTokenTask(StatusManager statusManager) {
        this(statusManager, new GenericMinimizerTokenResult<T>());
    }

    protected AbstractTokenTask(StatusManager statusManager, GenericMinimizerTokenResult<T> tokenResult) {
        this.statusManager = Validate.notNull(statusManager, "statusManager");
        this.tokenResult = tokenResult;
    }

    @Override
    final public void run() {
        dispatchStarting();
        if (!statusManager.run()) {
            throwException(new RuntimeException("Invalid status : " + statusManager.getStatus()));
        } else {
            dispatchRunning();
            try {
                T result = this.minimize();
                dispatchResult(result);
                this.tokenResult.setResult(result);
                if (!this.statusManager.stop()) {
                    throwException(
                            new RuntimeException("Invalid status for stopping: " + statusManager.getStatus()));
                }
                if (!this.statusManager.end(result.getEndingStatus())) {
                    throwException(new RuntimeException("Invalid status for ending: " + statusManager.getStatus()));
                }

            } catch (Exception e) {
                throwException(e);
            }
        }
    }

    @Override
    final public GenericMinimizerTokenResult<T> getTokenResult() {
        return this.tokenResult;
    }

    @Override
    public void addMinimizerListener(MinimizerListener listener) {
        this.listeners.addFirst(listener);
    }

    @Override
    public void removeMinimizerListener(MinimizerListener listener) {
        this.listeners.remove(listener);
    }

    protected boolean isRunning() {
        return this.statusManager.getStatus() == MinimizerStatus.RUNNING && !Thread.interrupted();
    }

    protected void throwException(Exception exception) {
        this.tokenResult.setException(exception);
        this.tokenResult.setResult(null);
        statusManager.error();
        dispatchError();
    }

    protected MinimizerStatus getEndingStatus(boolean done, boolean toManyIterations, boolean toManyEvaluations) {
        final MinimizerStatus endingStatus;
        if (done) {
            endingStatus = MinimizerStatus.DONE;
        } else if (toManyIterations) {
            endingStatus = MinimizerStatus.FAILED_TO_MANY_ITERATIONS;
        } else if (toManyEvaluations) {
            endingStatus = MinimizerStatus.FAILED_TO_MANY_EVALUATIONS;
        } else {
            endingStatus = MinimizerStatus.STOPPED;
        }
        return endingStatus;
    }

    protected abstract T minimize();

    protected abstract double[] getFirstGuess();

    protected void dispatchEvent(MinimizerEvent event) {
        for (MinimizerListener listener : listeners) {
            listener.onMinimizerEvent(event);
        }
    }

    private void dispatchStarting() {
        if (this.listeners.isEmpty()) {
            return;
        }
        MinimizerEventImpl event = new MinimizerEventImpl();
        event.setMinimizerStatus(MinimizerStatus.STARTING);
        event.setNbEvaluations(0);
        event.setNbIterations(0);
        event.setParameters(this.getFirstGuess());
        event.setPenalty(Double.NaN);
        this.dispatchEvent(event);
    }

    private void dispatchRunning() {
        if (this.listeners.isEmpty()) {
            return;
        }
        MinimizerEventImpl event = new MinimizerEventImpl();
        event.setMinimizerStatus(MinimizerStatus.RUNNING);
        event.setNbEvaluations(0);
        event.setNbIterations(0);
        event.setParameters(this.getFirstGuess());
        event.setPenalty(Double.NaN);
        this.dispatchEvent(event);
    }

    private void dispatchResult(T result) {
        if (this.listeners.isEmpty()) {
            return;
        }
        MinimizerEventImpl event = new MinimizerEventImpl();
        event.setMinimizerStatus(result.getEndingStatus());
        event.setNbEvaluations(result.getNbEvaluations());
        event.setNbIterations(result.getNbIterations());
        event.setParameters(result.getParameters());
        event.setPenalty(result.getPenalty());
        this.dispatchEvent(event);
    }

    private void dispatchError() {
        if (this.listeners.isEmpty()) {
            return;
        }
        MinimizerEventImpl event = new MinimizerEventImpl();
        event.setMinimizerStatus(MinimizerStatus.ERROR);
        event.setNbEvaluations(0);
        event.setNbIterations(0);
        event.setParameters(null);
        event.setPenalty(Double.NaN);
        this.dispatchEvent(event);
    }

    protected void dispatchIteration(int nbIterations, int nbEvaluations, double penalty, double[] parameters) {
        if (this.listeners.isEmpty()) {
            return;
        }
        MinimizerEventImpl event = new MinimizerEventImpl();
        event.setMinimizerStatus(MinimizerStatus.RUNNING);
        event.setNbEvaluations(nbEvaluations);
        event.setNbIterations(nbIterations);
        event.setParameters(parameters);
        event.setPenalty(penalty);
        this.dispatchEvent(event);
    }
}