Package org.useware.kernel.gui.behaviour

Source Code of org.useware.kernel.gui.behaviour.DialogState$MutableContext

package org.useware.kernel.gui.behaviour;

import org.useware.kernel.model.Dialog;
import org.useware.kernel.model.mapping.Node;
import org.useware.kernel.model.mapping.NodePredicate;
import org.useware.kernel.model.scopes.BranchActivation;
import org.useware.kernel.model.scopes.Scope;
import org.useware.kernel.model.structure.QName;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Reflects the dialog state. Breaks down into statements and scopes.
*
* @author Heiko Braun
* @date 1/22/13
*/
public class DialogState {

    private final StateCoordination stateCoordination;
    private Dialog dialog;
    private final StatementContext externalContext;
    private Map<Integer, MutableContext> scope2context;
    private Map<Integer, Scope> parent2childScopes = new HashMap<Integer, Scope>();
    private Map<Integer, Boolean> scopeActivationState = new HashMap<Integer, Boolean>();

    public DialogState(Dialog dialog, StatementContext parentContext, StateCoordination coordination) {
        this.stateCoordination = coordination;
        this.dialog = dialog;
        this.externalContext = parentContext;
        this.scope2context = new HashMap<Integer, MutableContext>();
    }


    public void resetActivation() {

        parent2childScopes.clear();

        BranchActivation activation = new BranchActivation();
        dialog.getInterfaceModel().accept(activation);
        for(QName unitId : activation.getActiveItems().values())
        {
            // notify actual unit implementation
            stateCoordination.notifyActivation(unitId);
        }
    }

    public void clearStatement(QName sourceId, String key) {
        ((MutableContext)getContext(sourceId)).clearStatement(key);
    }

    public void setStatement(QName interactionUnitId, String key, String value) {
        MutableContext context = (MutableContext) getContext(interactionUnitId);
        assert context!=null : "No context for " + interactionUnitId;

        System.out.println(">> Set '"+key+"' on scope ["+context.getScope().getScopeId()+"]: "+value);
        context.setStatement(key, value);
    }

    public StatementContext getContext(QName interactionUnitId) {

        final Node<Scope> self = dialog.getScopeModel().findNode(interactionUnitId);
        assert self!=null : "Unit not present in shim: "+ interactionUnitId;

        Scope scope = self.getData();

        // lazy initialisation
        if(!scope2context.containsKey(scope.getScopeId()))
        {

            // extract parent scopes

            List<Node<Scope>> parentScopeNodes = self.collectParents(new NodePredicate<Scope>() {
                Set<Integer> tracked = new HashSet<Integer>();

                @Override
                public boolean appliesTo(Node<Scope> candidate) {
                    if (self.getData().getScopeId() != candidate.getData().getScopeId()) {
                        if (!tracked.contains(candidate.getData().getScopeId())) {
                            tracked.add(candidate.getData().getScopeId());
                            return true;
                        }

                        return false;
                    }

                    return false;
                }
            });

            // delegation scheme
            List<Integer> parentScopeIds = new LinkedList<Integer>();
            for(Node<Scope> parentNode : parentScopeNodes)
            {
                parentScopeIds.add(parentNode.getData().getScopeId());
            }

            scope2context.put(scope.getScopeId(),
                    new ParentDelegationContextImpl(scope, externalContext, parentScopeIds,
                            new Scopes() {
                                @Override
                                public StatementContext get(Integer scopeId) {
                                    return scope2context.get(scopeId);
                                }
                            })
            );
        }

        return scope2context.get(scope.getScopeId());
    }

    /**
     * Deactivates a previously active sibling scope and activate a new one.
     * (Only a single sibling scope can be active at a time)
     *
     * @param targetUnit the unit from which the scope will be derived
     */
    public void activateScope(QName targetUnit) {

        // TODO: If branch has not been activated yet,
        // then redo branch activation from targetUnit

        Scope nextScope = getScope(targetUnit);
        int parentScopeId = getParentScopeId(targetUnit);

        Scope activeScope = parent2childScopes.get(parentScopeId);
        if(!nextScope.equals(activeScope))
        {
            System.out.println("Replace activation of scope "+activeScope+" with "+ nextScope);

            // root elements might not have an active scope
            if(activeScope!=null)scopeActivationState.put(activeScope.getScopeId(), false);

            scopeActivationState.put(nextScope.getScopeId(), true);
            parent2childScopes.put(parentScopeId, nextScope);
        }
    }

    /**
     * A unit can be activated if the parent is a demarcation type
     * or it is a root element
     *
     * @param interactionUnit
     * @return
     */
    public boolean canBeActivated(QName interactionUnit) {

        Node<Scope> node = dialog.getScopeModel().findNode(interactionUnit);
        assert node!=null : "Unit doesn't exist in shim: "+interactionUnit;
        boolean isRootElement = node.getParent() == null;
        boolean parentIsDemarcationType = node.getParent()!=null && node.getParent().getData().isDemarcationType();
        return isRootElement || parentIsDemarcationType;
    }

    public boolean isWithinActiveScope(final QName unitId) {
        final Scope scopeOfUnit = getScope(unitId);
        int parentScopeId = getParentScopeId(unitId);
        Scope activeScope = parent2childScopes.get(parentScopeId);
        boolean selfIsActive = activeScope != null && activeScope.equals(scopeOfUnit);

        if(selfIsActive) // only verify parents if necessary
        {
            Node<Scope> inactiveParentScope = dialog.getScopeModel().findNode(unitId).findParent(
                    new InActiveParentPredicate(unitId)
            );

            return inactiveParentScope==null;
        }

        return selfIsActive;
    }

    private int getParentScopeId(QName targetUnit) {
        final Scope scope = getScope(targetUnit);
        Node<Scope> parent = dialog.getScopeModel().findNode(targetUnit).findParent(new NodePredicate<Scope>() {
            @Override
            public boolean appliesTo(Node<Scope> node) {
                return node.getData().getScopeId() != scope.getScopeId();
            }
        });

        // fallback to root scope if none found
        return parent!= null ?
                parent.getData().getScopeId() : 0;
    }

    private Scope getScope(QName targetUnit) {
        MutableContext context = (MutableContext)getContext(targetUnit);
        assert context!=null : "No context for "+targetUnit;
        return context.getScope();
    }

    interface MutableContext extends StatementContext {
        Scope getScope();
        String get(String key);
        String[] getTuple(String key);
        void setStatement(String key, String value);
        void clearStatement(String key);
    }

    interface Scopes {
        StatementContext get(Integer scopeId);
    }

    class InActiveParentPredicate implements NodePredicate<Scope> {

        private final Scope scopeOfUnit;
        private QName unitId;

        InActiveParentPredicate(QName unitId) {
            this.unitId = unitId;
            this.scopeOfUnit = getScope(unitId);
        }

        @Override
        public boolean appliesTo(Node<Scope> node) {

            Scope parentScope = node.getData();
            boolean isParent = parentScope.getScopeId() != scopeOfUnit.getScopeId();
            boolean isActive = scopeActivationState.get(parentScope.getScopeId())!=null
                    ? scopeActivationState.get(parentScope.getScopeId()) : false;

            if(!isActive)
            {
                System.out.println("Inactive parent scope: "+ parentScope.getScopeId() +" for "+ unitId);
            }

            return isParent && !isActive;
        }
    }
}
TOP

Related Classes of org.useware.kernel.gui.behaviour.DialogState$MutableContext

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.