workcraft/workcraft

View on GitHub
workcraft/SonPlugin/src/org/workcraft/plugins/son/tasks/BSONStructureTask.java

Summary

Maintainability
B
5 hrs
Test Coverage
package org.workcraft.plugins.son.tasks;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.workcraft.dom.Node;
import org.workcraft.dom.math.MathNode;
import org.workcraft.plugins.son.ONGroup;
import org.workcraft.plugins.son.SON;
import org.workcraft.plugins.son.algorithm.ASONAlg;
import org.workcraft.plugins.son.algorithm.BSONAlg;
import org.workcraft.plugins.son.algorithm.BSONCycleAlg;
import org.workcraft.plugins.son.algorithm.Path;
import org.workcraft.plugins.son.connections.SONConnection.Semantics;
import org.workcraft.plugins.son.elements.ChannelPlace;
import org.workcraft.plugins.son.elements.Condition;
import org.workcraft.plugins.son.exception.UnboundedException;
import org.workcraft.plugins.son.util.Marking;
import org.workcraft.plugins.son.util.Phase;

public class BSONStructureTask extends AbstractStructuralVerification {

    private final SON net;

    private final Collection<Node> relationErrors = new ArrayList<>();
    private final Collection<Path> cycleErrors = new ArrayList<>();
    private final Collection<ONGroup> groupErrors = new HashSet<>();

    private final BSONAlg bsonAlg;
    private final BSONCycleAlg bsonCycleAlg;
    private final Map<Condition, Collection<Phase>> allPhases;
    private final ArrayList<String> phaseCutTask = new ArrayList<>();

    private int errNumber = 0;
    private static final int warningNumber = 0;

    public BSONStructureTask(SON net, Map<ONGroup, List<Marking>> allMarkings) {
        super(net);
        this.net = net;

        bsonAlg = new BSONAlg(net);
        if (allMarkings == null) {
            allPhases = bsonAlg.getAllPhases(getReachableMarking());
        } else {
            allPhases = bsonAlg.getAllPhases(allMarkings);
        }
        bsonCycleAlg = new BSONCycleAlg(net, allPhases);
    }

    @Override
    public void task(Collection<ONGroup> groups) {

        infoMsg("-----------------Behavioral-SON Structure Verification-----------------");

        // group info
        infoMsg("Initialising selected groups and components...");
        ArrayList<MathNode> components = new ArrayList<>();

        for (ONGroup group : groups) {
            components.addAll(group.getComponents());
        }

        infoMsg("Selected Groups : " + net.toString(groups));

        if (!net.getSONConnectionTypes(components).contains(Semantics.BHVLINE)) {
            infoMsg("Task terminated: no behavioural abstraction in selected groups.");
            return;
        }

        ArrayList<ChannelPlace> relatedCPlaces = new ArrayList<>();
        relatedCPlaces.addAll(getRelationAlg().getRelatedChannelPlace(groups));
        components.addAll(relatedCPlaces);

        // Upper-level group structure task
        infoMsg("Running model structure and component relation tasks...");
        infoMsg("Running Upper-level ON structure task...");
        groupErrors.addAll(groupTask1(groups));
        if (groupErrors.isEmpty()) {
            infoMsg("Valid upper-level ON structure.");
        } else {
            for (ONGroup group : groupErrors) {
                errMsg("Invalid Upper-level ON structure (not line-like/has both input and output behavioural relations).",
                        group);
            }
        }
        infoMsg("Upper-level ON structure task complete.");

        // a/synchronous relation group task
        infoMsg("Running a/synchronous relation task...");
        Collection<ChannelPlace> task2 = groupTask2(groups);
        relationErrors.addAll(task2);
        if (relationErrors.isEmpty()) {
            infoMsg("Valid a/synchronous relation.");
        } else {
            for (ChannelPlace cPlace : task2) {
                errMsg("Invalid BSON structure " + "(A/Synchronous communication between upper and lower level ONs).",
                        cPlace);
            }
        }
        infoMsg("A/synchronous relation task complete.");

        // phase decomposition task
        infoMsg("Running phase structure task...");
        Collection<ONGroup> upperGroups = getBSONAlg().getUpperGroups(groups);

        Map<Condition, String> phaseResult = phaseMainTask(upperGroups);
        if (!phaseResult.keySet().isEmpty()) {
            for (Condition c : phaseResult.keySet()) {
                errMsg(phaseResult.get(c));
                relationErrors.add(c);
            }
        } else if (!phaseCutTask.isEmpty()) {
            for (String str : phaseCutTask) {
                infoMsg(str);
            }
        } else {
            infoMsg("Valid phase structure.");
        }

        infoMsg("Phase checking tasks complete.");

        // BSON cycle task
        infoMsg("Running cycle detection task...");
        cycleErrors.addAll(getBSONCycleAlg().cycleTask(components));

        if (cycleErrors.isEmpty()) {
            infoMsg("Behavioral-SON is cycle free.");
        } else {
            errNumber++;
            errMsg("Model involves BSCON cycle paths = " + cycleErrors.size() + ".");
            int i = 1;
            for (Path cycle : cycleErrors) {
                infoMsg("Cycle " + i + ": " + cycle.toString(net));
                i++;
            }
        }

        infoMsg("Cycle detection task complete.");
        infoMsg("Model strucuture and component relation tasks complete.\n");

        errNumber += relationErrors.size();
        errNumber += groupErrors.size();
    }

    private Collection<ONGroup> groupTask1(Collection<ONGroup> groups) {
        Collection<ONGroup> result = new HashSet<>();

        for (ONGroup group : groups) {
            if (getBSONAlg().isLineLikeGroup(group)) {

                boolean isInput = false;
                boolean isOutput = false;

                for (MathNode node : group.getComponents()) {
                    if (net.getInputSONConnectionTypes(node).contains(Semantics.BHVLINE)) {
                        isInput = true;
                    }
                    if (net.getOutputSONConnectionTypes(node).contains(Semantics.BHVLINE)) {
                        isOutput = true;
                    }
                }

                if (isInput && isOutput) {
                    result.add(group);
                }
            } else {
                for (MathNode node : group.getComponents()) {
                    if (net.getInputSONConnectionTypes(node).contains(Semantics.BHVLINE)) {
                        result.add(group);
                    }
                }
            }
        }
        return result;
    }

    // correctness of A/SYN communication between upper and lower level ONs
    private Collection<ChannelPlace> groupTask2(Collection<ONGroup> groups) {
        Collection<ChannelPlace> result = new HashSet<>();
        Collection<ONGroup> upperGroups = getBSONAlg().getUpperGroups(groups);

        for (ChannelPlace cPlace : getRelationAlg().getRelatedChannelPlace(groups)) {
            int inUpperGroup = 0;

            Collection<Node> connectedNodes = new HashSet<>();
            connectedNodes.addAll(net.getPostset(cPlace));
            connectedNodes.addAll(net.getPreset(cPlace));

            for (Node node : connectedNodes) {
                for (ONGroup group : upperGroups) {
                    if (group.getComponents().contains(node)) {
                        inUpperGroup++;
                    }
                }
            }

            if (inUpperGroup < connectedNodes.size() && inUpperGroup != 0) {
                result.add(cPlace);
            }
        }

        return result;
    }

    private Map<Condition, String> phaseMainTask(Collection<ONGroup> upperGroups) {
        Map<Condition, String> result = new HashMap<>();

        for (ONGroup uGroup : upperGroups) {
            result.putAll(phaseTask1(uGroup));
            result.putAll(phaseTask2(uGroup));
            result.putAll(phaseTask3(uGroup));

            result.putAll(bsonAlg.getPhaseCutErr());
        }

        return result;
    }

    // check for upper level condition
    private Map<Condition, String> phaseTask1(ONGroup upperGroup) {
        Map<Condition, String> result = new HashMap<>();

        for (Condition c : upperGroup.getConditions()) {
            String ref = net.getNodeReference(c);
            if (!getBSONAlg().isUpperCondition(c)) {
                result.put(c, "Upper level condition does not has phase: " + ref);
            }
        }
        return result;
    }

    // check for upper level initial/final state
    private Map<Condition, String> phaseTask2(ONGroup upperGroup) {
        Map<Condition, String> result = new HashMap<>();

        for (Condition c : upperGroup.getConditions()) {
            Collection<Phase> phases = getAllPhases().get(c);
            String ref = net.getNodeReference(c);
            // the minimal phases of every initial state of upper group must
            // also be the initial state of lower group
            if (getRelationAlg().isInitial(c)) {
                Collection<Condition> minSet = getBSONAlg().getMinimalPhase(phases);

                for (Condition min : minSet) {
                    if (!getRelationAlg().isInitial(min)) {
                        result.put(c, "The minimal phase of " + ref + " does not reach initial state.");
                        break;
                    }
                }
            }
            // the maximal phases of every final state of upper group must also
            // be the final state of lower group
            if (getRelationAlg().isFinal(c)) {
                Collection<Condition> maxSet = getBSONAlg().getMaximalPhase(getAllPhases().get(c));

                for (Condition max : maxSet) {
                    if (!getRelationAlg().isFinal(max)) {
                        result.put(c, "The maximal phase of " + ref + " does not reach final state.");
                        break;
                    }
                }
            }
        }
        return result;
    }

    // check for joint
    private Map<Condition, String> phaseTask3(ONGroup upperGroup) {
        Map<Condition, String> result = new HashMap<>();

        for (Condition c : upperGroup.getConditions()) {
            Condition pre = null;
            Collection<Phase> phases = getAllPhases().get(c);

            if (!getRelationAlg().getPrePNCondition(c).isEmpty()) {
                pre = getRelationAlg().getPrePNCondition(c).iterator().next();
            }

            if (pre != null) {
                Collection<Phase> prePhases = getAllPhases().get(pre);
                Collection<Condition> preMax = getBSONAlg().getMaximalPhase(prePhases);
                System.out.println("premax+" + net.toString(preMax));

                for (Phase phase : phases) {
                    boolean match = false;
                    Collection<Condition> min = getBSONAlg().getMinimalPhase(phase);
                    System.out.println("min+" + net.toString(min));
                    if (preMax.containsAll(min)) {
                        match = true;
                    }

                    if (!match) {
                        match = true;
                        ONGroup lowGroup = net.getGroup(phase.iterator().next());
                        boolean containFinal = false;

                        if (!min.containsAll(getRelationAlg().getONInitial(lowGroup))) {
                            match = false;
                        }
                        for (ONGroup group : getBSONAlg().getLowerGroups(pre)) {
                            if (preMax.containsAll(getRelationAlg().getONFinal(group))) {
                                containFinal = true;
                                break;
                            }
                        }
                        if (!containFinal) {
                            match = false;
                        }
                    }

                    if (!match) {
                        String ref = net.getNodeReference(c);
                        String ref2 = net.getNodeReference(pre);
                        result.put(c, "Disjoint phases between " + ref + " and " + ref2);
                    }
                }
            }
        }
        return result;
    }

    public Map<ONGroup, List<Marking>> getReachableMarking() {
        Map<ONGroup, List<Marking>> result = new HashMap<>();

        ASONAlg alg = new ASONAlg(net);
        Collection<ONGroup> lowerGroups = bsonAlg.getLowerGroups(net.getGroups());

        for (ONGroup group : lowerGroups) {
            try {
                result.put(group, alg.getReachableMarkings(group));
            } catch (UnboundedException e) {
            }
            break;
        }

        return result;
    }

    public boolean equals(Marking m, Collection<Condition> b) {

        if (m.size() != b.size()) {
            return false;
        }

        for (Node node : m) {
            if (!b.contains(node)) {
                return false;
            }
        }

        for (Node node : b) {
            if (!m.contains(node)) {
                return false;
            }
        }

        return true;
    }

    public BSONAlg getBSONAlg() {
        return this.bsonAlg;
    }

    public BSONCycleAlg getBSONCycleAlg() {
        return bsonCycleAlg;
    }

    public Map<Condition, Collection<Phase>> getAllPhases() {
        return allPhases;
    }

    @Override
    public Collection<String> getRelationErrors() {
        return getRelationErrorsSetRefs(relationErrors);
    }

    @Override
    public Collection<ArrayList<String>> getCycleErrors() {
        return getCycleErrorsSetRefs(cycleErrors);
    }

    @Override
    public Collection<String> getGroupErrors() {
        return getGroupErrorsSetRefs(groupErrors);
    }

    @Override
    public int getErrNumber() {
        return this.errNumber;
    }

    @Override
    public int getWarningNumber() {
        return this.warningNumber;
    }

}