de.rinderle.softvis3d.layout.bottomup.SnapshotVisitorBean.java Source code

Java tutorial

Introduction

Here is the source code for de.rinderle.softvis3d.layout.bottomup.SnapshotVisitorBean.java

Source

/*
 * SoftVis3D Sonar plugin
 * Copyright (C) 2014 Stefan Rinderle
 * stefan@rinderle.info
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package de.rinderle.softvis3d.layout.bottomup;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
import att.grappa.Graph;
import att.grappa.GrappaBox;
import att.grappa.Node;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import de.rinderle.softvis3d.dao.DaoService;
import de.rinderle.softvis3d.domain.LayoutViewType;
import de.rinderle.softvis3d.domain.MinMaxValue;
import de.rinderle.softvis3d.domain.ScmInfoType;
import de.rinderle.softvis3d.domain.SoftVis3DConstants;
import de.rinderle.softvis3d.domain.VisualizationRequest;
import de.rinderle.softvis3d.domain.graph.ResultPlatform;
import de.rinderle.softvis3d.domain.layout.LayeredLayoutElement;
import de.rinderle.softvis3d.domain.tree.DependencyTreeNode;
import de.rinderle.softvis3d.domain.tree.Edge;
import de.rinderle.softvis3d.domain.tree.TreeNode;
import de.rinderle.softvis3d.domain.tree.TreeNodeType;
import de.rinderle.softvis3d.domain.tree.ValueTreeNode;
import de.rinderle.softvis3d.layout.bottomup.grappa.GrappaEdgeFactory;
import de.rinderle.softvis3d.layout.bottomup.grappa.GrappaNodeFactory;
import de.rinderle.softvis3d.layout.dot.DotExecutor;
import de.rinderle.softvis3d.layout.dot.DotExecutorException;
import de.rinderle.softvis3d.layout.dot.GraphvizPath;
import de.rinderle.softvis3d.layout.format.LayerFormatter;
import de.rinderle.softvis3d.layout.helper.HexaColor;

public class SnapshotVisitorBean implements SnapshotVisitor {

    private static final Logger LOGGER = LoggerFactory.getLogger(SnapshotVisitorBean.class);

    // getting injected - see constructor
    private final DotExecutor dotExecutor;
    private final LayerFormatter formatter;
    private final GrappaNodeFactory nodeFactory;
    private final GrappaEdgeFactory edgeFactory;

    private final GraphvizPath graphvizPath;

    private final MinMaxValue minMaxMetricFootprint;
    private final MinMaxValue minMaxMetricHeight;
    private final int dependenciesCount;

    private final Map<Integer, ResultPlatform> resultingGraphList = new ConcurrentHashMap<Integer, ResultPlatform>();

    private final LayoutViewType viewType;
    private final ScmInfoType scmInfoType;
    private final int maxScmInfo;

    @Inject
    public SnapshotVisitorBean(final LayerFormatter formatter, final DotExecutor dotExecutor,
            final GrappaNodeFactory nodeFactory, final GrappaEdgeFactory edgeFactory, final DaoService daoService,
            @Assisted final Settings settings, @Assisted final VisualizationRequest requestDTO) {

        this.graphvizPath = new GraphvizPath(settings.getString(SoftVis3DConstants.DOT_BIN_KEY),
                SystemUtils.IS_OS_WINDOWS);

        this.dotExecutor = dotExecutor;
        this.formatter = formatter;
        this.nodeFactory = nodeFactory;
        this.edgeFactory = edgeFactory;

        this.minMaxMetricFootprint = daoService.getMinMaxMetricValuesByRootSnapshotId(
                requestDTO.getRootSnapshotId(), requestDTO.getFootprintMetricId());
        this.minMaxMetricHeight = daoService.getMinMaxMetricValuesByRootSnapshotId(requestDTO.getRootSnapshotId(),
                requestDTO.getHeightMetricId());

        this.dependenciesCount = daoService.getDependencies(requestDTO.getRootSnapshotId()).size();
        this.maxScmInfo = daoService.getMaxScmInfo(requestDTO);

        LOGGER.info("minMaxValues for " + requestDTO.getRootSnapshotId() + " : " + minMaxMetricFootprint.toString()
                + " " + minMaxMetricHeight.toString() + " Dependencies: " + this.dependenciesCount);

        this.viewType = requestDTO.getViewType();
        this.scmInfoType = requestDTO.getScmInfoType();
    }

    @Override
    public Map<Integer, ResultPlatform> getResultingGraphList() {
        return this.resultingGraphList;
    }

    @Override
    public LayeredLayoutElement visitNode(final TreeNode node, final List<LayeredLayoutElement> elements)
            throws DotExecutorException {

        LOGGER.debug("LayoutVisitor.visitNode " + node.getId() + " " + node.getName());

        // create layout graph
        final Graph inputGraph = createGrappaInputGraph(node, elements);

        // run dot layout for this layer
        final Graph outputGraph = this.dotExecutor.run(inputGraph, this.graphvizPath, this.viewType);

        final ResultPlatform resultPlatform = new ResultPlatform(outputGraph);

        // adjust graph
        this.formatter.format(resultPlatform, node.getDepth(), this.viewType);

        this.resultingGraphList.put(node.getId(), resultPlatform);

        // adjusted graph has a bounding box !
        final GrappaBox bb = resultPlatform.getBoundingBox();

        /**
         * The dot output of the bb is given in DPI. The actual width and height of the representing element has to be
         * scaled back to normal
         */
        final Double width = bb.getWidth() / SoftVis3DConstants.DPI_DOT_SCALE;
        final Double height = bb.getHeight() / SoftVis3DConstants.DPI_DOT_SCALE;

        final double platformHeight = SoftVis3DConstants.PLATFORM_DEFAULT_HEIGHT;

        final HexaColor platformColor = this.formatter.getPlatformBaseColor(node.getDepth());

        /**
         * this will be the representation node of this layer in the upper layer. Currently, the "building" is the
         * deleted if the city view is enabled.
         */
        return LayeredLayoutElement.createLayeredLayoutElement(node, width, height, platformHeight, platformColor);
    }

    private Graph createGrappaInputGraph(final TreeNode node, final List<LayeredLayoutElement> elements) {
        final Graph inputGraph = new Graph(node.getId().toString());

        for (final LayeredLayoutElement element : elements) {
            final Node elementNode = this.nodeFactory.transformToGrappaNode(inputGraph, element);
            inputGraph.addNode(elementNode);
        }

        for (final LayeredLayoutElement element : elements) {
            for (final Edge edge : element.getEdges().values()) {
                inputGraph.addEdge(this.edgeFactory.createGrappaEdge(inputGraph, edge));
            }
        }
        return inputGraph;
    }

    @Override
    public LayeredLayoutElement visitFile(final TreeNode leaf) {
        LOGGER.debug("Leaf : " + leaf.getId() + " " + leaf.getName());

        final boolean isDependencyNode = TreeNodeType.DEPENDENCY_GENERATED.equals(leaf.getType())
                && LayoutViewType.DEPENDENCY.equals(this.viewType);

        double sideLength;
        double buildingHeight;

        final HexaColor color;

        if (isDependencyNode) {
            final DependencyTreeNode leafNode = (DependencyTreeNode) leaf;
            final MinMaxValue minMaxDependencies = new MinMaxValue(0.0,
                    Integer.valueOf(dependenciesCount).doubleValue());
            sideLength = this.formatter.calcSideLength(Integer.valueOf(leafNode.getCounter()).doubleValue(),
                    minMaxDependencies);

            buildingHeight = SoftVis3DConstants.LAYER_HEIGHT;

            // not used, will be overriden somewhere
            color = new HexaColor(255, 255, 255);
        } else {
            final ValueTreeNode leafNode = (ValueTreeNode) leaf;
            sideLength = this.formatter.calcSideLength(leafNode.getFootprintMetricValue(),
                    this.minMaxMetricFootprint);

            buildingHeight = this.formatter.calcBuildingHeight(leafNode.getHeightMetricValue(),
                    this.minMaxMetricHeight);
            /**
             * building height is in percent with min size. multiplier to get higher buildings in the view.
             */
            buildingHeight = buildingHeight * SoftVis3DConstants.BUILDING_HEIGHT_MULTIPLIER;
            buildingHeight = Math.round(buildingHeight);

            color = this.formatter.getScmColorInfo(this.scmInfoType, leafNode.getScmMetricValue(), this.maxScmInfo);
        }

        sideLength = sideLength / SoftVis3DConstants.DPI_DOT_SCALE;

        return LayeredLayoutElement.createLayeredLayoutElement(leaf, sideLength, sideLength, buildingHeight, color);
    }

}