org.eclipse.titanium.graph.gui.layouts.algorithms.MetricLayoutAlgorithm.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.titanium.graph.gui.layouts.algorithms.MetricLayoutAlgorithm.java

Source

/******************************************************************************
 * Copyright (c) 2000-2016 Ericsson Telecom AB
 * 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
 ******************************************************************************/
package org.eclipse.titanium.graph.gui.layouts.algorithms;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.titan.common.logging.ErrorReporter;
import org.eclipse.titanium.error.ErrorMessage;
import org.eclipse.titanium.graph.components.NodeDescriptor;
import org.eclipse.titanium.metrics.IMetricEnum;
import org.eclipse.titanium.metrics.preferences.PreferenceManager;
import org.eclipse.titanium.metrics.utils.ModuleMetricsWrapper;
import org.eclipse.titanium.metrics.utils.WrapperStore;

/**
 * This class implements the ordering of graph nodes needed to
 * generate a layout using metric values measured on TTCN3 modules
 * 
 * @author Gabor Jenei
 */
public class MetricLayoutAlgorithm implements HierarcicalLayoutAlgorithm<NodeDescriptor> {

    private static final int LEVELS = 10;
    private static final double EPSILON = Math.pow(10, -6);

    private Map<NodeDescriptor, Double> values;
    private Map<NodeDescriptor, Integer> levels;
    private final Collection<NodeDescriptor> nodes;
    private Set<NodeDescriptor> badNodes;
    private final IMetricEnum chosenMetric;
    private Double minValue;
    private Double maxValue;
    private int filledLevels;
    private int[] nodeCount;

    /**
     * Constructor. It does the initialization and also the needed calculations
     * @param metric : The chosen metric
     * @param nodes : The graph nodes that should be ordered
     */
    public MetricLayoutAlgorithm(final IMetricEnum metric, final Collection<NodeDescriptor> nodes) {
        this.nodes = new HashSet<NodeDescriptor>(nodes);
        chosenMetric = metric;
    }

    private void init() {
        values = new HashMap<NodeDescriptor, Double>();
        levels = new HashMap<NodeDescriptor, Integer>();
        badNodes = new HashSet<NodeDescriptor>();
        minValue = Double.POSITIVE_INFINITY;
        maxValue = Double.NEGATIVE_INFINITY;
        filledLevels = 0;

        if (!PreferenceManager.isEnabledOnModuleGraph(chosenMetric)) {
            ErrorReporter.logError("Error during metric layout generating: The requested metric is not"
                    + " enabled. Only enabled metrics can be chosen!");
            ErrorMessage.show("Error",
                    "The chosen metric must be enabled for calculation in the properties." + "Have you enabled it?",
                    MessageDialog.ERROR);
            return;
        }

        final Iterator<NodeDescriptor> it = nodes.iterator();
        while (it.hasNext()) {
            final NodeDescriptor node = it.next();
            final ModuleMetricsWrapper wrapper = WrapperStore.getWrapper(node.getProject());
            final Number val = wrapper.getValue(chosenMetric, node.getName());
            if (val == null) {
                it.remove();
                badNodes.add(node);
            } else {
                final Double tempVal = Double.valueOf(val.toString());
                if (tempVal != null) {
                    values.put(node, tempVal);
                    if (minValue > tempVal) {
                        minValue = tempVal;
                    }

                    if (maxValue < tempVal) {
                        maxValue = tempVal;
                    }
                }
            }
        }
    }

    private void genLevels() {
        filledLevels = badNodes.isEmpty() ? 0 : 1;
        final double step = (maxValue - minValue) / LEVELS;
        double actBound = minValue + step;
        for (int actLevel = 0; actLevel < LEVELS; ++actLevel) {
            final Iterator<NodeDescriptor> it = nodes.iterator();
            boolean isEmpty = true;
            while (it.hasNext()) {
                final NodeDescriptor node = it.next();
                final Double value = values.get(node);
                if (value != null && (value < actBound || Math.abs(value - actBound) <= EPSILON)) {
                    levels.put(node, filledLevels);
                    it.remove();
                    isEmpty = false;
                }
            }
            if (!isEmpty) {
                filledLevels++;
            }
            actBound += step;
        }

        genLevelNumbers();
    }

    private void genLevelNumbers() {
        nodeCount = new int[filledLevels];

        for (int i = 0; i < filledLevels; ++i) {
            nodeCount[i] = 0;
        }

        final int badNodeCount = badNodes.size();
        if (badNodeCount != 0) {
            nodeCount[0] = badNodeCount;
        }

        for (final int actIndex : levels.values()) {
            ++nodeCount[actIndex];
        }
    }

    @Override
    public int getNumberOfLevels() {
        return filledLevels;
    }

    @Override
    public Map<NodeDescriptor, Integer> getLevels() {
        return levels;
    }

    @Override
    public int[] getNumberOfNodesPerLevel() {
        return nodeCount;
    }

    @Override
    public Set<NodeDescriptor> getIsolateNodes() {
        return badNodes;
    }

    @Override
    public void run() {
        init();
        genLevels();
    }
}