modula.executor.core.ModulaExecutor.java Source code

Java tutorial

Introduction

Here is the source code for modula.executor.core.ModulaExecutor.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 modula.executor.core;

import modula.executor.core.context.Context;
import modula.executor.core.context.ModulaExecutionContext;
import modula.executor.core.dispatcher.EventDispatcher;
import modula.executor.core.event.TriggerEvent;
import modula.executor.core.invoke.Invoker;
import modula.executor.core.reporter.ErrorReporter;
import modula.executor.core.semantics.ModulaSemantics;
import modula.listener.NotificationRegistry;
import modula.parser.model.ModelException;
import modula.parser.model.EnterableState;
import modula.parser.model.Modula;
import modula.parser.model.Observable;
import modula.executor.core.semantics.ModulaSemanticsImpl;
import modula.listener.ModulaListener;
import modula.parser.ModulaIOProcessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 
 */
public class ModulaExecutor implements ModulaIOProcessor {
    private static final String ERR_NO_STATE_MACHINE = "SCXMLExecutor: State machine not set";

    private Log log = LogFactory.getLog(ModulaExecutor.class);

    /**
     * Modula
     */
    private ModulaSemantics semantics;

    /**
     * ?
     */
    private ModulaExecutionContext exctx;

    /**
     * 
     */
    private final Queue<TriggerEvent> externalEventQueue = new ConcurrentLinkedQueue<TriggerEvent>();

    public ModulaExecutor() {
        this(null, null, null);
    }

    public ModulaExecutor(final EventDispatcher evtDisp, final ErrorReporter errRep) {
        this(evtDisp, errRep, null);
    }

    public ModulaExecutor(final EventDispatcher evtDisp, final ErrorReporter errRep,
            final ModulaSemantics semantics) {
        this.semantics = semantics != null ? semantics : new ModulaSemanticsImpl();
        this.exctx = new ModulaExecutionContext(this, evtDisp, errRep);
    }

    /**
     * ????
     */
    public synchronized Status getCurrentStatus() {
        return exctx.getScInstance().getCurrentStatus();
    }

    /**
     * Get the root context for the state machine execution.
     *
     * @return Context The root context.
     */
    public Context getRootContext() {
        return exctx.getScInstance().getRootContext();
    }

    /**
     * Set the root context for the state machine execution.
     * <b>NOTE:</b> Should only be used before the executor is set in motion.
     */
    public void setRootContext(final Context rootContext) {
        exctx.getScInstance().setRootContext(rootContext);
    }

    /**
     * ???
     *
     * @return Returns the stateMachine.
     */
    public Modula getStateMachine() {
        return exctx.getStateMachine();
    }

    /**
     * ?????
     */
    public void setStateMachine(final Modula stateMachine) throws ModelException {
        exctx.setStateMachine(semantics.normalizeStateMachine(stateMachine, exctx.getErrorReporter()));
        externalEventQueue.clear();
    }

    public ErrorReporter getErrorReporter() {
        return exctx.getErrorReporter();
    }

    public void setErrorReporter(final ErrorReporter errorReporter) {
        exctx.setErrorReporter(errorReporter);
    }

    public EventDispatcher getEventdispatcher() {
        return exctx.getEventDispatcher();
    }

    public void setEventdispatcher(final EventDispatcher eventdispatcher) {
        exctx.setEventdispatcher(eventdispatcher);
    }

    public NotificationRegistry getNotificationRegistry() {
        return exctx.getNotificationRegistry();
    }

    public void addListener(final Observable observable, final ModulaListener listener) {
        exctx.getNotificationRegistry().addListener(observable, listener);
    }

    public void removeListener(final Observable observable, final ModulaListener listener) {
        exctx.getNotificationRegistry().removeListener(observable, listener);
    }

    /**
     * Invoker type?
     */
    public void registerInvokerClass(final String type, final Class<? extends Invoker> invokerClass) {
        exctx.registerInvokerClass(type, invokerClass);
    }

    public void unregisterInvokerClass(final String type) {
        exctx.unregisterInvokerClass(type);
    }

    /**
     * ?????attach??
     */
    public SCInstance detachInstance() {
        return exctx.detachInstance();
    }

    /**
     * ????
     */
    public void attachInstance(SCInstance instance) {
        exctx.attachInstance(instance);
    }

    public boolean isRunning() {
        return exctx.isRunning();
    }

    /**
     * ?
     */
    public void go() throws ModelException {
        // same as reset
        this.reset();
    }

    /**
     * ???firstStep
     */
    public void reset() throws ModelException {
        // clear any pending external events
        externalEventQueue.clear();

        // go
        semantics.firstStep(exctx);

        if (!exctx.isRunning()) {
            semantics.finalStep(exctx);
        }

        logState();
    }

    /**
     * 
     */
    public void addEvent(final TriggerEvent evt) {
        if (evt != null) {
            externalEventQueue.add(evt);
        }
    }

    /**
     * ?
     */
    public boolean hasPendingEvents() {
        return !externalEventQueue.isEmpty();
    }

    /**
     * ?
     */
    public int getPendingEvents() {
        return externalEventQueue.size();
    }

    /**
     * ?
     */
    public void triggerEvent(final TriggerEvent evt) throws ModelException {
        if (evt != null) {
            externalEventQueue.add(evt);
        }
        triggerEvents();
    }

    /**
     * ?
     */
    public void triggerEvents(final TriggerEvent[] evts) throws ModelException {
        if (evts != null) {
            for (TriggerEvent evt : evts) {
                if (evt != null) {
                    externalEventQueue.add(evt);
                }
            }
        }
        triggerEvents();
    }

    /**
     * ?nextStep
     */
    public void triggerEvents() throws ModelException {
        TriggerEvent evt;
        while (exctx.isRunning() && (evt = externalEventQueue.poll()) != null) {
            eventStep(evt);
        }
    }

    protected void eventStep(TriggerEvent event) throws ModelException {
        semantics.nextStep(exctx, event);

        if (!exctx.isRunning()) {
            semantics.finalStep(exctx);
        }

        logState();
    }

    /**
     * ?SCInstance
     */
    protected SCInstance getSCInstance() {
        return exctx.getScInstance();
    }

    /**
     * ??State
     */
    protected void logState() {
        if (log.isDebugEnabled()) {
            StringBuilder sb = new StringBuilder("Current States: [ ");
            for (EnterableState es : getCurrentStatus().getStates()) {
                sb.append(es.getId()).append(", ");
            }
            int length = sb.length();
            sb.delete(length - 2, length).append(" ]");
            log.debug(sb.toString());
        }
    }
}