org.jactr.core.runtime.ACTRRuntime.java Source code

Java tutorial

Introduction

Here is the source code for org.jactr.core.runtime.ACTRRuntime.java

Source

/*
 * Created on May 8, 2006 Copyright (C) 2001-5, Anthony Harrison anh23@pitt.edu
 * (jactr.org) 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 2.1 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 Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jactr.core.runtime;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Executor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.time.IClock;
import org.jactr.core.event.ACTREventDispatcher;
import org.jactr.core.model.IModel;
import org.jactr.core.reality.connector.IConnector;
import org.jactr.core.reality.connector.LocalConnector;
import org.jactr.core.runtime.controller.IController;
import org.jactr.core.runtime.event.ACTRRuntimeEvent;
import org.jactr.core.runtime.event.IACTRRuntimeListener;

public class ACTRRuntime {
    /**
     * logger definition
     */
    static public final Log LOGGER = LogFactory.getLog(ACTRRuntime.class);

    static private ACTRRuntime _instance;

    private Collection<IModel> _allModels;

    private Runnable _onStart;

    private Runnable _onStop;

    private Object _applicationData;

    private IController _controller;

    ACTREventDispatcher<ACTRRuntime, IACTRRuntimeListener> _eventDispatcher;

    private IConnector _commonRealityConnector;

    private File _workingDirectory;

    /**
     * return the ACTRRuntime singleton
     * 
     * @return
     */
    static public ACTRRuntime getRuntime() {
        synchronized (ACTRRuntime.class) {
            if (_instance == null)
                _instance = new ACTRRuntime();
            return _instance;
        }
    }

    protected ACTRRuntime() {
        _allModels = Collections.synchronizedList(new ArrayList<IModel>());
        _eventDispatcher = new ACTREventDispatcher<ACTRRuntime, IACTRRuntimeListener>();
        setConnector(new LocalConnector());
        setWorkingDirectory(new File(System.getProperty("user.dir")));
    }

    public File getWorkingDirectory() {
        return _workingDirectory;
    }

    public void setWorkingDirectory(File workingDirectory) {
        _workingDirectory = workingDirectory;
    }

    public IConnector getConnector() {
        return _commonRealityConnector;
    }

    public void setConnector(IConnector connector) {
        _commonRealityConnector = connector;
    }

    public IController getController() {
        return _controller;
    }

    /**
     * will call IController.attach()
     * 
     * @param controller
     */
    public void setController(IController controller) {
        IController oldController = _controller;

        if (oldController == controller) {
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Already attached");
            return;
        }

        if (oldController != null)
            oldController.detach();

        if (controller != null)
            try {
                controller.attach();
            } catch (Exception e) {
                LOGGER.error("Could not attach new controller " + controller, e);
                controller = null;
            }

        _controller = controller;
    }

    /**
     * return the clock for the model in this runtime. originally this was a zero
     * parameter method but since when connected to common reality, each model has
     * its own clock instance, we use the proxy clock to return a valid clock if
     * connected to common reality, otherwise it returns a default shared clock
     * 
     * @param model
     *            if null will always return the default shared clock
     * @return
     */
    public IClock getClock(IModel model) {
        return getConnector().getClock(model);
    }

    /**
     * add a model to this runtime. if the runtime is already actively running,
     * this model will be added and immediately started. The model should have had
     * all of its listeners attached before being added to the runtime. this will
     * ensure that if the model is suspended that all events are delivered
     * appropriately
     * 
     * @param model
     */
    public void addModel(IModel model) {
        _allModels.add(model);

        /*
         * fire the event
         */
        if (hasListeners())
            dispatch(new ACTRRuntimeEvent(model, ACTRRuntimeEvent.Type.MODEL_ADDED));
    }

    /**
     * remove this model, assuming that it is not running. If it is, a runtime
     * excepiton will be thrown
     * 
     * @param model
     */
    public void removeModel(IModel model) {
        try {
            /*
             * why wrap this? when the event fires, the controller, which will receive
             * the event may throw an exception if you are removing from a running
             * runtime
             */
            if (hasListeners())
                dispatch(new ACTRRuntimeEvent(model, ACTRRuntimeEvent.Type.MODEL_REMOVED));

            _allModels.remove(model);
        } catch (Exception e) {

        }
    }

    /**
     * return all the models associated with the runtime
     * 
     * @return
     */
    public Collection<IModel> getModels() {
        return Collections.unmodifiableCollection(_allModels);
    }

    /**
     * runnable to be executed after the runtime is started by the controller
     * 
     * @param onStart
     */
    public void setOnStart(Runnable onStart) {
        _onStart = onStart;
    }

    public Runnable getOnStart() {
        return _onStart;
    }

    /**
     * runnable to be executed after the runtime has stopped. ie. all models
     * terminated
     */
    public void setOnStop(Runnable onStop) {
        _onStop = onStop;
    }

    /**
     * called by controller
     * 
     * @return
     */
    public Runnable getOnStop() {
        return _onStop;
    }

    /**
     * @param applicationData
     */
    public void setApplicationData(Object applicationData) {
        _applicationData = applicationData;
    }

    public Object getApplicationData() {
        return _applicationData;
    }

    public boolean hasListeners() {
        return _eventDispatcher.hasListeners();
    }

    public Collection<IACTRRuntimeListener> getListeners() {
        return _eventDispatcher.getListeners();
    }

    public void addListener(IACTRRuntimeListener listener, Executor executor) {
        _eventDispatcher.addListener(listener, executor);
    }

    public void removeListener(IACTRRuntimeListener listener) {
        _eventDispatcher.removeListener(listener);
    }

    public void dispatch(ACTRRuntimeEvent event) {
        if (_eventDispatcher.hasListeners())
            _eventDispatcher.fire(event);
    }
}