Package org.jboss.mbui.gui.behaviour

Source Code of org.jboss.mbui.gui.behaviour.InteractionCoordinator

package org.jboss.mbui.gui.behaviour;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.user.client.Window;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.SimpleEventBus;
import org.jboss.mbui.gui.behaviour.as7.ActivationProcedure;
import org.jboss.mbui.gui.behaviour.as7.BehaviourMap;
import org.jboss.mbui.gui.behaviour.as7.NavigationProcedure;
import org.jboss.mbui.gui.behaviour.as7.SelectStatementProcedure;
import org.jboss.mbui.model.Dialog;
import org.jboss.mbui.model.behaviour.Resource;
import org.jboss.mbui.model.behaviour.ResourceType;
import org.jboss.mbui.model.structure.InteractionUnit;
import org.jboss.mbui.model.structure.QName;

import java.util.Map;
import java.util.Set;

/**
* A coordinator acts as the middleman between a framework (i.e. GWTP), the structure (interface model)
* and the behaviour (interaction model). <p/>
*
* It wires the {@link org.jboss.mbui.model.behaviour.Resource} input/output of interaction units to certain behaviour and vice versa.
* It's available at reification time to interaction units and provides an API to register {@link Procedure}'s.
*
*
* @author Heiko Braun
* @date 11/15/12
*/
public class InteractionCoordinator implements KernelContract,
        InteractionEvent.InteractionHandler, NavigationEvent.NavigationHandler,
        StatementEvent.StatementHandler, BehaviourExecution {

    private static final String PROJECT_NAMESPACE = "org.jboss.as";
    final static SystemEvent RESET = new SystemEvent(new QName(PROJECT_NAMESPACE, "reset"));

    final static SystemEvent REVEAL = new SystemEvent(new QName(PROJECT_NAMESPACE, "reveal"));

    // a bus scoped to this coordinator and the associated models
    private EventBus bus;
    private BehaviourMap<Procedure> procedures = new BehaviourMap<Procedure>();
    private Dialog dialog;
    private StatementScope statementScope;
    private final NavigationDelegate navigationDelegate;

    @Inject
    public InteractionCoordinator(Dialog dialog, StatementContext parentContext, NavigationDelegate navigationDelegate) {
        this.dialog = dialog;
        this.bus = new SimpleEventBus();
        this.navigationDelegate = navigationDelegate;
        this.statementScope = new StatementScope(dialog, parentContext);

        // coordinator handles all events except presentation & system events
        bus.addHandler(InteractionEvent.TYPE, this);
        bus.addHandler(NavigationEvent.TYPE, this);
        bus.addHandler(StatementEvent.TYPE, this);

        // global procedures
        procedures.add(new SelectStatementProcedure(this));
        procedures.add(new ActivationProcedure(this));
        procedures.add(new NavigationProcedure(this));
    }

    public StatementScope getStatementScope() {
        return statementScope;
    }

    public EventBus getLocalBus()
    {
        return this.bus;
    }

    /**
     * Procedures of same kind (same ID) can coexist if they can be further distinguished.<br/>
     * A typical example stock procedures (save, load, etc) that are registered for different origins (interaction units).
     *
     * @param procedure
     */
    @Override
    public void addProcedure(Procedure procedure)
    {

        // TODO: verification of behaviour model
        // known behaviour -> accept
        // unknown behaviour -> issue warning

        // provide context
        procedure.setCoordinator(this);
        procedure.setStatementScope(statementScope);

        procedures.add(procedure);
    }

    @Override
    public Map<QName, Set<Procedure>> listProcedures() {
        return procedures.list();
    }

    /**
     * Command entry point
     *
     * @param event
     */
    public void fireEvent(final Event<?> event)
    {
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                bus.fireEventFromSource(event, this);
            }
        });

    }


    @Override
    public void activate() {

    }

    @Override
    public void reset() {
        bus.fireEvent(RESET);
    }

    @Override
    public void passivate() {

    }

    //  ----- Event handling ------

    @Override
    public boolean accepts(InteractionEvent event) {
        return true;
    }

    /**
     * Find the corresponding procedures and execute it.
     *
     * @param event
     */
    @Override
    public void onInteractionEvent(final InteractionEvent event) {
        QName id = event.getId();
        QName source = (QName)event.getSource();

        final Set<Procedure> collection = procedures.get(id);
        Procedure execution = null;

        if(collection!=null)
        {
            for(Procedure consumer : collection) {
                Resource<ResourceType> resource = new Resource<ResourceType>(id, ResourceType.Interaction);
                resource.setSource(source);

                if(consumer.doesConsume(resource))
                {
                    execution = consumer;
                    break;
                }
            }
        }

        if(null==execution)
        {
            Window.alert("No procedure for " + event);
            Log.warn("No procedure for " + event);
        }
        else if(execution.getPrecondition().isMet(getStatementContext(source)))   // guarded
        {
            try {
                execution.getCommand().execute(InteractionCoordinator.this.dialog, event.getPayload());
            } catch (Throwable e) {
                Log.error("Failed to execute procedure "+execution, e);
            }
        }

    }

    /**
     * Resolve the statement context for an interaction unit
     * @param interactionUnitId
     * @return
     */
    private StatementContext getStatementContext(QName interactionUnitId) {
        return statementScope.getContext(interactionUnitId);
    }

    @Override
    public boolean accepts(NavigationEvent event) {
        return true;
    }


    /**
     * Find and activate another IU.
     * Can delegate to another context (i.e. gwtp placemanager) or handle it internally (same dialog)
     *
     * @param event
     */
    @Override
    public void onNavigationEvent(NavigationEvent event) {

        QName source = (QName)event.getSource();
        QName target = event.getTarget();

        InteractionUnit targetUnit = dialog.findUnit(target);
        if(targetUnit!=null// local to dialog
        {
            String suffix = target.getSuffix();
            if(suffix !=null) // relative, local (#prev, #next)
            {
                if(NavigationEvent.RELATION.next.equals(suffix))
                {

                }
                else if(NavigationEvent.RELATION.prev.equals(suffix))
                {

                }
            }
            else // absolute, local
            {
                Procedure activateProcedure = procedures.getSingle(ActivationProcedure.ID);
                activateProcedure.getCommand().execute(dialog, targetUnit.getId());
            }
        }
        else // absolute, external
        {
            navigationDelegate.onNavigation(dialog.getId(), target); // TODO: dialog || unit as source?
        }

    }


    @Override
    public boolean accepts(StatementEvent event) {
        return true; // all statement are processed by the coordinator
    }

    @Override
    public void onStatementEvent(StatementEvent event) {

        Log.debug("StatementEvent " + event.getKey() + "=" + event.getValue());

        Procedure stmtProcedure = procedures.getSingle(SelectStatementProcedure.ID);
        stmtProcedure.getCommand().execute(dialog, event);

    }

    @Override
    public void setStatement(QName sourceId, String key, String value) {

        statementScope.setStatement(sourceId, key, value);
    }

    @Override
    public void clearStatement(QName sourceId, String key, String value) {
        statementScope.clearStatement(sourceId, key);
    }
}
TOP

Related Classes of org.jboss.mbui.gui.behaviour.InteractionCoordinator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.