com.che.software.testato.util.jung.DiagramGraphistUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.che.software.testato.util.jung.DiagramGraphistUtil.java

Source

package com.che.software.testato.util.jung;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Paint;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.io.Serializable;

import org.apache.commons.collections15.Transformer;
import org.apache.log4j.Logger;

import com.che.software.testato.domain.entity.Element;
import com.che.software.testato.domain.entity.Intention;
import com.che.software.testato.domain.entity.MapArrow;
import com.che.software.testato.domain.entity.ProceduralArrow;
import com.che.software.testato.util.ColorUtil;
import com.che.software.testato.util.jung.enumeration.DrawingAlgorithm;

import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.FRLayout2;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.algorithms.layout.KKLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.SpringLayout;
import edu.uci.ics.jung.algorithms.layout.SpringLayout2;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.Context;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;

/**
 * Static class used to colorize the JUNG diagrams.
 * 
 * @author Clement HELIOU (clement.heliou@che-software.com).
 * @copyright Che Software.
 * @license GNU General Public License.
 * @see Serializable.
 * @since July, 2011.
 * 
 *        This file is part of Testato.
 * 
 *        Testato 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.
 * 
 *        Testato 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 Testato. If not, see <http://www.gnu.org/licenses/>.
 * 
 *        Testato's logo is a creation of Arrioch
 *        (http://arrioch.deviantart.com/) and it's distributed under the terms
 *        of the Creative Commons License.
 */
public class DiagramGraphistUtil implements Serializable {

    /**
     * Constants.
     */
    private static final double DEFAULT_CHOICE_SHAPE_ROTATION = 0.7854; // Radians.
    private static final double[] DEFAULT_CIRCLE_SIZE = { -5, -20, 80, 80 },
            DEFAULT_ELLIPSE_SIZE = { -5, -20, 100, 40 }, DEFAULT_RECTANGLE_SIZE = { -5, -20, 100, 40, 10, 10 };
    private static final int LABEL_OFFSET = 20;
    private static final int[] DEFAULT_DIAMOND_SIZE = { -5, -20, 50, 50 },
            DEFAULT_POLYGON_X_POINTS = { -15, 15, 30, 30, 15, -15, -30, -30 },
            DEFAULT_POLYGON_Y_POINTS = { 30, 30, 15, -15, -30, -30, -15, 15, 30 };
    private static final Logger LOGGER = Logger.getLogger(DiagramGraphistUtil.class);
    private static final long serialVersionUID = 989685570695060055L;
    private static final String BLUE_HEXA = "92CDDC", DARK_BLUE_HEXA = "17365D", ORANGE_HEXA = "FF9900";
    private static final Stroke DEFAULT_MAP_STROKE = new BasicStroke(2, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_ROUND);
    private static final Stroke DEFAULT_PROC_STROKE = new BasicStroke(2, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_BEVEL);
    private static final Transformer<Element, Font> PROC_ELEMENT_FONT = new Transformer<Element, Font>() {
        @Override
        public Font transform(Element arg0) {
            return ColorUtil.DEFAULT_FONT;
        }
    };
    private static final Transformer<Element, Paint> PROC_BORDER_ELEMENT_PAINT = new Transformer<Element, Paint>() {
        @Override
        public Paint transform(Element element) {
            return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1],
                    ColorUtil.DARK_BLUE_COLOR[2]);
        }
    };
    private static final Transformer<Element, Paint> PROC_ELEMENT_PAINT = new Transformer<Element, Paint>() {
        @Override
        public Paint transform(Element element) {
            return ColorUtil.getHSBColor(ColorUtil.GREY_COLOR[0], ColorUtil.GREY_COLOR[1], ColorUtil.GREY_COLOR[2]);
        }
    };
    private static final Transformer<Element, Shape> PROC_ELEMENT_SHAPE = new Transformer<Element, Shape>() {
        @Override
        public Shape transform(Element element) {
            if (0 != element.getActivityId()) {
                return new RoundRectangle2D.Double(DEFAULT_RECTANGLE_SIZE[0], DEFAULT_RECTANGLE_SIZE[1],
                        DEFAULT_RECTANGLE_SIZE[2], DEFAULT_RECTANGLE_SIZE[3], DEFAULT_RECTANGLE_SIZE[4],
                        DEFAULT_RECTANGLE_SIZE[5]);
            }
            switch (element.getPointType()) {
            case CHOICE:
                AffineTransform at = new AffineTransform();
                at.rotate(DEFAULT_CHOICE_SHAPE_ROTATION);
                return at.createTransformedShape(new Rectangle(DEFAULT_DIAMOND_SIZE[0], DEFAULT_DIAMOND_SIZE[1],
                        DEFAULT_DIAMOND_SIZE[2], DEFAULT_DIAMOND_SIZE[3]));
            case JOIN:
                return new Polygon(DEFAULT_POLYGON_X_POINTS, DEFAULT_POLYGON_Y_POINTS,
                        DEFAULT_POLYGON_X_POINTS.length);
            case NEGATIVE_END:
            case POSITIVE_END:
            case START:
                return new Ellipse2D.Double(DEFAULT_CIRCLE_SIZE[0], DEFAULT_CIRCLE_SIZE[1], DEFAULT_CIRCLE_SIZE[2],
                        DEFAULT_CIRCLE_SIZE[3]);
            default:
                return null; // Doesn't happened.
            }
        }
    };
    private static final Transformer<Element, String> PROC_ELEMENT_LABEL = new Transformer<Element, String>() {
        @Override
        public String transform(Element element) {
            return "<html><font color=\"#" + DARK_BLUE_HEXA + "\">" + element + "</font></html>";
        }
    };
    private static final Transformer<Element, Stroke> PROC_ELEMENT_STROKE = new Transformer<Element, Stroke>() {
        @Override
        public Stroke transform(Element arg0) {
            return DEFAULT_PROC_STROKE;
        }
    };
    private static final Transformer<Intention, Font> MAP_NODE_FONT = new Transformer<Intention, Font>() {
        @Override
        public Font transform(Intention arg0) {
            return ColorUtil.DEFAULT_FONT;
        }
    };
    private static final Transformer<Intention, Paint> MAP_NODE_PAINT = new Transformer<Intention, Paint>() {
        @Override
        public Paint transform(Intention intention) {
            return ColorUtil.getHSBColor(ColorUtil.GREY_COLOR[0], ColorUtil.GREY_COLOR[1], ColorUtil.GREY_COLOR[2]);
        }
    };
    private static final Transformer<Intention, Paint> MAP_BORDER_NODE_PAINT = new Transformer<Intention, Paint>() {
        @Override
        public Paint transform(Intention intention) {
            return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1],
                    ColorUtil.DARK_BLUE_COLOR[2]);
        }
    };
    private static final Transformer<Intention, Shape> MAP_NODE_SHAPE = new Transformer<Intention, Shape>() {
        @Override
        public Shape transform(Intention intention) {
            return new Ellipse2D.Double(DEFAULT_ELLIPSE_SIZE[0], DEFAULT_ELLIPSE_SIZE[1], DEFAULT_ELLIPSE_SIZE[2],
                    DEFAULT_ELLIPSE_SIZE[3]);
        }
    };
    private static final Transformer<Intention, String> MAP_NODE_LABEL = new Transformer<Intention, String>() {
        @Override
        public String transform(Intention intention) {
            return "<html><font color=\"#" + DARK_BLUE_HEXA + "\">" + intention + "</font></html>";
        }
    };
    private static final Transformer<Intention, Stroke> MAP_NODE_STROKE = new Transformer<Intention, Stroke>() {
        @Override
        public Stroke transform(Intention intention) {
            return DEFAULT_MAP_STROKE;
        }
    };
    private static final Transformer<MapArrow, Font> MAP_ARROW_FONT = new Transformer<MapArrow, Font>() {
        @Override
        public Font transform(MapArrow arrow) {
            return ColorUtil.DEFAULT_FONT;
        }
    };
    private static final Transformer<MapArrow, Paint> MAP_ARROW_PAINT = new Transformer<MapArrow, Paint>() {
        @Override
        public Paint transform(MapArrow arrow) {
            return (arrow.isOperationalized())
                    ? ColorUtil.getHSBColor(ColorUtil.ORANGE_COLOR[0], ColorUtil.ORANGE_COLOR[1],
                            ColorUtil.ORANGE_COLOR[2])
                    : (arrow.isRefined())
                            ? ColorUtil.getHSBColor(ColorUtil.BLUE_COLOR[0], ColorUtil.BLUE_COLOR[1],
                                    ColorUtil.BLUE_COLOR[2])
                            : ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1],
                                    ColorUtil.DARK_BLUE_COLOR[2]);
        }
    };
    private static final Transformer<MapArrow, String> MAP_ARROW_LABEL = new Transformer<MapArrow, String>() {
        @Override
        public String transform(MapArrow arrow) {
            return "<html><font color=\"#"
                    + ((arrow.isOperationalized()) ? ORANGE_HEXA : (arrow.isRefined()) ? BLUE_HEXA : DARK_BLUE_HEXA)
                    + "\">" + arrow + "</font></html>";
        }
    };
    private static final Transformer<MapArrow, Stroke> MAP_ARROW_STROKE = new Transformer<MapArrow, Stroke>() {
        @Override
        public Stroke transform(MapArrow arrow) {
            return DEFAULT_MAP_STROKE;
        }
    };
    private static final Transformer<ProceduralArrow, Font> PROC_ARROW_FONT = new Transformer<ProceduralArrow, Font>() {
        @Override
        public Font transform(ProceduralArrow arrow) {
            return ColorUtil.DEFAULT_FONT;
        }
    };
    private static final Transformer<ProceduralArrow, Paint> PROC_ARROW_PAINT = new Transformer<ProceduralArrow, Paint>() {
        @Override
        public Paint transform(ProceduralArrow arrow) {
            return ColorUtil.getHSBColor(ColorUtil.DARK_BLUE_COLOR[0], ColorUtil.DARK_BLUE_COLOR[1],
                    ColorUtil.DARK_BLUE_COLOR[2]);
        }
    };
    private static final Transformer<ProceduralArrow, String> PROC_ARROW_LABEL = new Transformer<ProceduralArrow, String>() {
        @Override
        public String transform(ProceduralArrow arrow) {
            return "<html><font color=\"#"
                    + ((null != arrow.getLabel() && !"".equals(arrow.getLabel())) ? BLUE_HEXA : DARK_BLUE_HEXA)
                    + "\">" + arrow + "</font></html>";
        }
    };
    private static final Transformer<ProceduralArrow, Stroke> PROC_ARROW_STROKE = new Transformer<ProceduralArrow, Stroke>() {
        @Override
        public Stroke transform(ProceduralArrow arrow) {
            return DEFAULT_PROC_STROKE;
        }
    };
    private static final Transformer<Context<Graph<Intention, MapArrow>, MapArrow>, Shape> MAP_ARROW_SHAPE = new Transformer<Context<Graph<Intention, MapArrow>, MapArrow>, Shape>() {
        @Override
        public Shape transform(Context<Graph<Intention, MapArrow>, MapArrow> context) {
            return new EdgeShape.QuadCurve<Intention, MapArrow>().transform(context);
        }
    };
    private static final Transformer<Context<Graph<Element, ProceduralArrow>, ProceduralArrow>, Shape> PROC_ARROW_SHAPE = new Transformer<Context<Graph<Element, ProceduralArrow>, ProceduralArrow>, Shape>() {
        @Override
        public Shape transform(Context<Graph<Element, ProceduralArrow>, ProceduralArrow> context) {
            return new EdgeShape.BentLine<Element, ProceduralArrow>().transform(context);
        }
    };

    /**
     * Private default builder; the class can't be instancied.
     */
    private DiagramGraphistUtil() {
    }

    /**
     * Returns the object containing the colorized version of a map diagram.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param mapDiagram the map diagram to colorized.
     * @return the resulting object.
     * @since July, 2011.
     */
    public static VisualizationImageServer<Intention, MapArrow> getColorizedMapDiagram(
            DirectedGraph<Intention, MapArrow> mapDiagram) {
        LOGGER.debug("getColorizedMapDiagram(" + mapDiagram + ").");
        return DiagramGraphistUtil.getColorizedMapDiagramFromAlgorithmAndSize(mapDiagram, DrawingAlgorithm.KK,
                ColorUtil.REDUCE_SIZE);
    }

    /**
     * Returns the object containing the colorized version of a map diagram with
     * given algorithm and size.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param mapDiagram the map diagram to colorized.
     * @param algorithm the algorithm to used.
     * @param imageSize the desired image size.
     * @return the resulting object.
     * @since July, 2011.
     */
    public static VisualizationImageServer<Intention, MapArrow> getColorizedMapDiagramFromAlgorithmAndSize(
            DirectedGraph<Intention, MapArrow> mapDiagram, DrawingAlgorithm algorithm, Dimension imageSize) {
        LOGGER.debug("getColorizedMapDiagramFromAlgorithmAndSize(" + mapDiagram + "," + algorithm + ").");
        Layout<Intention, MapArrow> layout = DiagramGraphistUtil.getMapLayoutFromAlgorithmAndSize(mapDiagram,
                algorithm, imageSize);
        VisualizationImageServer<Intention, MapArrow> vis = new VisualizationImageServer<Intention, MapArrow>(
                layout, imageSize);
        vis.getRenderContext().setArrowDrawPaintTransformer(MAP_ARROW_PAINT);
        vis.getRenderContext().setEdgeArrowStrokeTransformer(MAP_ARROW_STROKE);
        vis.getRenderContext().setEdgeDrawPaintTransformer(MAP_ARROW_PAINT);
        vis.getRenderContext().setEdgeFontTransformer(MAP_ARROW_FONT);
        vis.getRenderContext().setEdgeLabelTransformer(MAP_ARROW_LABEL);
        vis.getRenderContext().setEdgeShapeTransformer(MAP_ARROW_SHAPE);
        vis.getRenderContext().setEdgeStrokeTransformer(MAP_ARROW_STROKE);
        vis.getRenderContext().setLabelOffset(LABEL_OFFSET);
        vis.getRenderContext().setVertexDrawPaintTransformer(MAP_BORDER_NODE_PAINT);
        vis.getRenderContext().setVertexFillPaintTransformer(MAP_NODE_PAINT);
        vis.getRenderContext().setVertexFontTransformer(MAP_NODE_FONT);
        vis.getRenderContext().setVertexLabelTransformer(MAP_NODE_LABEL);
        vis.getRenderContext().setVertexShapeTransformer(MAP_NODE_SHAPE);
        vis.getRenderContext().setVertexStrokeTransformer(MAP_NODE_STROKE);
        vis.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
        vis.setBackground(Color.WHITE);
        vis.validate();
        return vis;
    }

    /**
     * Returns the object containing the colorized version of a procedural
     * diagram.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param proceduralDiagram the procedural diagram to colorized.
     * @return the resulting object.
     * @since July, 2011.
     */
    public static VisualizationImageServer<Element, ProceduralArrow> getColorizedProceduralDiagram(
            DirectedGraph<Element, ProceduralArrow> proceduralDiagram) {
        LOGGER.debug("getColorizedProceduralDiagram(" + proceduralDiagram + ").");
        return DiagramGraphistUtil.getColorizedProceduralDiagramFromAlgorithmAndSize(proceduralDiagram,
                DrawingAlgorithm.ISOM, ColorUtil.REDUCE_SIZE);
    }

    /**
     * Returns the object containing the colorized version of a procedural
     * diagram with given algorithm and size.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param proceduralDiagram the procedural diagram to colorized.
     * @param algorithm the algorithm to used.
     * @param imageSize the desired image size.
     * @return the resulting object.
     * @since July, 2011.
     */
    public static VisualizationImageServer<Element, ProceduralArrow> getColorizedProceduralDiagramFromAlgorithmAndSize(
            DirectedGraph<Element, ProceduralArrow> proceduralDiagram, DrawingAlgorithm algorithm,
            Dimension imageSize) {
        LOGGER.debug("getColorizedProceduralDiagramFromAlgorithmAndSize(" + proceduralDiagram + "," + algorithm
                + "," + imageSize.getHeight() + "," + imageSize.getWidth() + ").");
        Layout<Element, ProceduralArrow> layout = DiagramGraphistUtil
                .getProceduralLayoutFromAlgorithmAndSize(proceduralDiagram, algorithm, imageSize);
        VisualizationImageServer<Element, ProceduralArrow> vis = new VisualizationImageServer<Element, ProceduralArrow>(
                layout, imageSize);
        vis.getRenderContext().setArrowDrawPaintTransformer(PROC_ARROW_PAINT);
        vis.getRenderContext().setArrowFillPaintTransformer(PROC_ARROW_PAINT);
        vis.getRenderContext().setEdgeArrowStrokeTransformer(PROC_ARROW_STROKE);
        vis.getRenderContext().setEdgeDrawPaintTransformer(PROC_ARROW_PAINT);
        vis.getRenderContext().setEdgeFontTransformer(PROC_ARROW_FONT);
        vis.getRenderContext().setEdgeLabelTransformer(PROC_ARROW_LABEL);
        vis.getRenderContext().setEdgeShapeTransformer(PROC_ARROW_SHAPE);
        vis.getRenderContext().setEdgeStrokeTransformer(PROC_ARROW_STROKE);
        vis.getRenderContext().setLabelOffset(LABEL_OFFSET);
        vis.getRenderContext().setVertexDrawPaintTransformer(PROC_BORDER_ELEMENT_PAINT);
        vis.getRenderContext().setVertexFillPaintTransformer(PROC_ELEMENT_PAINT);
        vis.getRenderContext().setVertexFontTransformer(PROC_ELEMENT_FONT);
        vis.getRenderContext().setVertexLabelTransformer(PROC_ELEMENT_LABEL);
        vis.getRenderContext().setVertexShapeTransformer(PROC_ELEMENT_SHAPE);
        vis.getRenderContext().setVertexStrokeTransformer(PROC_ELEMENT_STROKE);
        vis.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
        vis.setBackground(Color.WHITE);
        vis.validate();
        return vis;
    }

    /**
     * Return the layout corresponding to the parameters.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param mapDiagram the map diagram to put into the layout.
     * @param algorithm the desired algorithm.
     * @param imageSize the desired image size.
     * @return the resulting layout object.
     * @since July, 2011.
     */
    private static Layout<Intention, MapArrow> getMapLayoutFromAlgorithmAndSize(
            DirectedGraph<Intention, MapArrow> mapDiagram, DrawingAlgorithm algorithm, Dimension imageSize) {
        LOGGER.debug("getMapLayoutFromAlgorithmAndSize(" + algorithm + "," + imageSize.getHeight() + ","
                + imageSize.getWidth() + ").");
        Layout<Intention, MapArrow> layout = null;
        switch (algorithm) {
        case CIRCLE:
            layout = new CircleLayout<Intention, MapArrow>(mapDiagram);
            break;
        case FR:
            layout = new FRLayout<Intention, MapArrow>(mapDiagram);
            break;
        case FR2:
            layout = new FRLayout2<Intention, MapArrow>(mapDiagram);
            break;
        case ISOM:
            layout = new ISOMLayout<Intention, MapArrow>(mapDiagram);
            break;
        case KK:
            layout = new KKLayout<Intention, MapArrow>(mapDiagram);
            break;
        case SPRING:
            layout = new SpringLayout<Intention, MapArrow>(mapDiagram);
            break;
        case SPRING2:
            layout = new SpringLayout2<Intention, MapArrow>(mapDiagram);
            break;
        default: // Doesn't happened.
            break;
        }
        layout.setSize(imageSize);
        return layout;
    }

    /**
     * Return the layout corresponding to the parameters.
     * 
     * @author Clement HELIOU (clement.heliou@che-software.com).
     * @param proceduralDiagram the procedural diagram to put into the layout.
     * @param algorithm the desired algorithm.
     * @param imageSize the desired image size.
     * @return the resulting layout object.
     * @since July, 2011.
     */
    private static Layout<Element, ProceduralArrow> getProceduralLayoutFromAlgorithmAndSize(
            DirectedGraph<Element, ProceduralArrow> proceduralDiagram, DrawingAlgorithm algorithm,
            Dimension imageSize) {
        LOGGER.debug("getProceduralLayoutFromAlgorithmAndSize(" + proceduralDiagram + "," + algorithm + ","
                + imageSize.getHeight() + "," + imageSize.getWidth() + ").");
        Layout<Element, ProceduralArrow> layout = null;
        switch (algorithm) {
        case CIRCLE:
            layout = new CircleLayout<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case FR:
            layout = new FRLayout<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case FR2:
            layout = new FRLayout2<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case ISOM:
            layout = new ISOMLayout<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case KK:
            layout = new KKLayout<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case SPRING:
            layout = new SpringLayout<Element, ProceduralArrow>(proceduralDiagram);
            break;
        case SPRING2:
            layout = new SpringLayout2<Element, ProceduralArrow>(proceduralDiagram);
            break;
        default: // Doesn't happened.
            break;

        }
        layout.setSize(imageSize);
        return layout;
    }
}