de.uni_potsdam.hpi.asg.delaymatch.trace.ParallelTraceDetector.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_potsdam.hpi.asg.delaymatch.trace.ParallelTraceDetector.java

Source

package de.uni_potsdam.hpi.asg.delaymatch.trace;

/*
 * Copyright (C) 2016 Norman Kluge
 * 
 * This file is part of ASGdelaymatch.
 * 
 * ASGdelaymatch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ASGdelaymatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ASGdelaymatch.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.google.common.collect.Lists;

import de.uni_potsdam.hpi.asg.common.stg.model.Transition;
import de.uni_potsdam.hpi.asg.delaymatch.trace.helper.TempTrace;
import de.uni_potsdam.hpi.asg.delaymatch.trace.model.Box;
import de.uni_potsdam.hpi.asg.delaymatch.trace.model.ParallelBox;
import de.uni_potsdam.hpi.asg.delaymatch.trace.model.SequenceBox;
import de.uni_potsdam.hpi.asg.delaymatch.trace.model.Trace;
import de.uni_potsdam.hpi.asg.delaymatch.trace.model.TransitionBox;

public class ParallelTraceDetector {
    private static final Logger logger = LogManager.getLogger();

    private List<Trace> traces;

    public ParallelTraceDetector() {
        this.traces = new ArrayList<>();
    }

    public boolean detect(SortedSet<TempTrace> tmptraces) {
        Map<Integer, List<TempTrace>> equalTransitionTraces = new HashMap<>();
        for (TempTrace trace : tmptraces) {
            int hash = trace.getTransitions().hashCode();
            if (!equalTransitionTraces.containsKey(hash)) {
                equalTransitionTraces.put(hash, new ArrayList<TempTrace>());
            }
            equalTransitionTraces.get(hash).add(trace);
        }
        for (List<TempTrace> list : equalTransitionTraces.values()) {
            Map<Transition, TransitionBox> transmap = new HashMap<>();

            if (list.size() == 1) {
                SequenceBox box = new SequenceBox(null);
                TransitionBox prev = null;
                for (Transition tx : list.get(0).getTrace()) {
                    TransitionBox tb = new TransitionBox(box, tx, prev);
                    box.getContent().add(tb);
                    transmap.put(tx, tb);
                    prev = tb;
                }
                traces.add(new Trace(box, transmap));
                continue;
            }

            Map<Transition, Set<Transition>> commonPredecessors = new HashMap<>();
            Map<Transition, Set<Transition>> directPredecessors = new HashMap<>();
            Map<Transition, Set<Transition>> predecessors = new HashMap<>();
            for (Transition tx : list.get(0).getTransitions()) {
                commonPredecessors.put(tx, new HashSet<Transition>());
                for (Transition tx2 : list.get(0).getTransitions()) {
                    commonPredecessors.get(tx).add(tx2);
                }
                directPredecessors.put(tx, new HashSet<Transition>());
            }
            for (TempTrace ttrace : list) {
                for (int i = 0; i < ttrace.getTrace().size(); i++) {
                    Transition curr = ttrace.getTrace().get(i);
                    commonPredecessors.get(curr).retainAll(ttrace.getTrace().subList(0, i));
                    if (i > 0) {
                        directPredecessors.get(curr).add(ttrace.getTrace().get(i - 1));
                    }
                }
            }
            for (Transition tx : list.get(0).getTransitions()) {
                predecessors.put(tx, new HashSet<>(commonPredecessors.get(tx)));
                predecessors.get(tx).retainAll(directPredecessors.get(tx));
            }

            SequenceBox rootbox = new SequenceBox(null);
            Set<Transition> transitionsleft = new HashSet<>(list.get(0).getTransitions());
            Map<Transition, SequenceBox> boxmap = new HashMap<>();
            while (true) {
                Set<Transition> currEmpty = new HashSet<>();
                for (Transition tx : transitionsleft) {
                    if (commonPredecessors.get(tx).isEmpty()) {
                        currEmpty.add(tx);
                    }
                }

                if (currEmpty.isEmpty()) {
                    if (!transitionsleft.isEmpty()) {
                        logger.error("Not all transitions placed!");
                        return false;
                    }
                    break;
                } else if (currEmpty.size() == 1) {
                    //sequential
                    Transition trans = currEmpty.iterator().next();
                    if (predecessors.get(trans).isEmpty()) {
                        // first
                        TransitionBox prev = null;
                        TransitionBox tb = new TransitionBox(rootbox, trans, prev);
                        rootbox.getContent().add(tb);
                        boxmap.put(trans, rootbox);
                        transmap.put(trans, tb);
                    } else if (predecessors.get(trans).size() == 1) {
                        // sequential
                        SequenceBox box = boxmap.get(predecessors.get(trans).iterator().next());
                        TransitionBox prev = transmap.get(predecessors.get(trans).iterator().next());
                        TransitionBox tb = new TransitionBox(box, trans, prev);
                        box.getContent().add(tb);
                        boxmap.put(trans, box);
                        transmap.put(trans, tb);
                    } else {
                        // join
                        List<List<Box>> boxhier = new ArrayList<>();
                        int min = -1;
                        for (Transition predecessor : predecessors.get(trans)) {
                            List<Box> boxlist = getTransitiveBox(boxmap.get(predecessor));
                            boxhier.add(boxlist);
                            if (min == -1) {
                                min = boxlist.size();
                            }
                            if (boxlist.size() < min) {
                                min = boxlist.size();
                            }
                        }
                        int firstuncommon = -1;
                        for (int i = 0; i < min; i++) {
                            Box value = null;
                            for (List<Box> boxes : boxhier) {
                                if (value == null) {
                                    value = boxes.get(i);
                                    continue;
                                }
                                if (value != boxes.get(i)) {
                                    firstuncommon = i;
                                }
                            }
                        }
                        Set<TransitionBox> prevs = new HashSet<>();
                        for (Transition predecessor : predecessors.get(trans)) {
                            prevs.add(transmap.get(predecessor));
                        }

                        if (firstuncommon == -1) {
                            logger.error("Common sublist -1");
                            return false;
                        } else if (firstuncommon == 0) {
                            TransitionBox tb = new TransitionBox(rootbox, trans, prevs);
                            rootbox.getContent().add(tb);
                            boxmap.put(trans, rootbox);
                            transmap.put(trans, tb);
                        } else {
                            Box box = boxhier.get(0).get(firstuncommon - 2); //PBox is last common (-1) -but we need SBox in front of it (-1) = (-2)
                            if (box instanceof SequenceBox) {
                                SequenceBox sbox = (SequenceBox) box;
                                TransitionBox tb = new TransitionBox(sbox, trans, prevs);
                                sbox.getContent().add(tb);
                                boxmap.put(trans, sbox);
                                transmap.put(trans, tb);
                            } else {
                                logger.error("Box is not a SequenceBox. But it should");
                                return false;
                            }
                        }
                    }
                } else {
                    Map<Transition, ParallelBox> parallelBoxes = new HashMap<>();
                    for (Transition trans : currEmpty) {
                        if (predecessors.get(trans).isEmpty()) {
                            logger.error("Parallel trans with empty predecessor");
                            return false;
                        } else if (predecessors.get(trans).size() == 1) {
                            Transition predecessor = predecessors.get(trans).iterator().next();
                            SequenceBox prebox = boxmap.get(predecessor);
                            if (!parallelBoxes.containsKey(predecessor)) {
                                ParallelBox pbox = new ParallelBox(prebox);
                                parallelBoxes.put(predecessor, pbox);
                                prebox.getContent().add(pbox);
                            }
                            ParallelBox pbox = parallelBoxes.get(predecessor);
                            SequenceBox sbox = new SequenceBox(pbox);
                            pbox.getParallelLines().add(sbox);
                            TransitionBox prev = transmap.get(predecessor);
                            TransitionBox tb = new TransitionBox(sbox, trans, prev);
                            sbox.getContent().add(tb);
                            boxmap.put(trans, sbox);
                            transmap.put(trans, tb);
                        } else {
                            logger.error("Parallel Trans with multiple predecessors");
                            return false;
                        }
                    }
                }

                for (Transition tx : currEmpty) {
                    for (Set<Transition> set : commonPredecessors.values()) {
                        set.remove(tx);
                    }
                    transitionsleft.remove(tx);
                }
            }
            traces.add(new Trace(rootbox, transmap));
        }
        return true;
    }

    private List<Box> getTransitiveBox(SequenceBox start) {
        List<Box> retVal = new ArrayList<>();
        Box next = start;
        while (next != null) {
            retVal.add(next);
            next = next.getSuperBox();
        }
        return Lists.reverse(retVal);
    }

    public List<Trace> getTraces() {
        return traces;
    }
}