com.synflow.cx.internal.compiler.helpers.FsmBeautifier.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.cx.internal.compiler.helpers.FsmBeautifier.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2014 Synflow SAS.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Matthieu Wipliez - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.synflow.cx.internal.compiler.helpers;

import java.util.Iterator;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.synflow.models.dpn.Action;
import com.synflow.models.dpn.Actor;
import com.synflow.models.dpn.FSM;
import com.synflow.models.dpn.State;
import com.synflow.models.dpn.Transition;
import com.synflow.models.graph.Edge;
import com.synflow.models.graph.Vertex;
import com.synflow.models.graph.visit.ReversePostOrder;
import com.synflow.models.ir.Procedure;

/**
 * This class defines a beautifier that renames actions/states of the actor's FSM that it visits. It
 * also sorts by topological order.
 * 
 * @author Matthieu Wipliez
 * 
 */
public class FsmBeautifier {

    private FSM fsm;

    /**
     * Renames the states of the FSM.
     * 
     * @param actorName
     *            base name of the states (simple name of the actor)
     */
    private void renameStates(String actorName) {
        // the "currentName" is set by a state with a name
        String currentName = null;
        for (State state : fsm.getStates()) {
            String stateName = state.getName();
            if (stateName == null) {
                if (currentName == null) {
                    // this is the case for an actor whose first state has no name
                    currentName = "FSM_" + actorName;
                }
                state.setName(currentName);
            } else {
                currentName = stateName;
            }
        }

        // rename consecutive states
        Multiset<String> visited = HashMultiset.create();
        for (State state : fsm.getStates()) {
            String name = state.getName();
            int n = visited.count(name);
            if (n > 0) {
                state.setName(name + "_" + n);
            }

            visited.add(name);
        }
    }

    /**
     * Sorts the FSM by reverse post-order (equivalent to topological order, but cycle tolerant).
     */
    private void sortFsm() {
        ReversePostOrder order = new ReversePostOrder(fsm, fsm.getInitialState());
        int i = 0;
        for (Vertex vertex : order) {
            fsm.getVertices().move(i, vertex);
            i++;
        }
    }

    /**
     * Visits the given actor
     * 
     * @param actor
     *            an actor
     */
    public void visit(Actor actor) {
        fsm = actor.getFsm();

        // if FSM is empty removes it from actor and leave
        if (fsm.getStates().isEmpty()) {
            actor.setFsm(null);
            return;
        }

        sortFsm();
        renameStates(actor.getSimpleName());
        visitTransitions();

        // if there is only one state, removes the FSM
        if (fsm.getStates().size() <= 1) {
            for (Transition transition : fsm.getTransitions()) {
                actor.getActionsOutsideFsm().add(transition.getAction());
            }

            // remove FSM
            actor.setFsm(null);
        }
    }

    /**
     * Visits the given transition, renames actions according to the given name, and set up the line
     * numbers of its body and scheduler procedures.
     * 
     * @param transition
     *            transition
     * @param name
     *            name of the action
     */
    private void visitTransition(Transition transition, String name) {
        Iterator<Integer> it = transition.getLines().iterator();
        int lineNumber = it.hasNext() ? it.next() : 0;

        Action action = transition.getAction();
        action.setName(name);

        Procedure body = action.getBody();
        body.setLineNumber(lineNumber);
        body.setName(name);

        Procedure scheduler = action.getScheduler();
        scheduler.setLineNumber(lineNumber);
        scheduler.setName("isSchedulable_" + name);
    }

    /**
     * Visits all transitions, renaming actions and setting up their line numbers.
     */
    private void visitTransitions() {
        for (State state : fsm.getStates()) {
            int i = 0;
            for (Edge edge : state.getOutgoing()) {
                String name = state.getName();
                name += "_" + (char) ('a' + i);
                i++;

                visitTransition((Transition) edge, name);
            }
        }
    }

}