nz.ac.massey.cs.gql4jung.browser.resultviews.GraphBasedResultView.java Source code

Java tutorial

Introduction

Here is the source code for nz.ac.massey.cs.gql4jung.browser.resultviews.GraphBasedResultView.java

Source

/**
 * Copyright 2009 Jens Dietrich Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
 * Unless required by applicable law or agreed to in writing, software distributed under the 
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific language governing permissions 
 * and limitations under the License.
 */

package nz.ac.massey.cs.gql4jung.browser.resultviews;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.apache.commons.collections15.Transformer;
import nz.ac.massey.cs.gql4jung.Edge;
import nz.ac.massey.cs.gql4jung.Motif;
import nz.ac.massey.cs.gql4jung.MotifInstance;
import nz.ac.massey.cs.gql4jung.Path;
import nz.ac.massey.cs.gql4jung.Vertex;
import nz.ac.massey.cs.gql4jung.browser.PropertyBean;
import nz.ac.massey.cs.gql4jung.browser.ResultView;
import edu.uci.ics.jung.algorithms.layout.*;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;

/**
 * Result view based on the jung 2 visualisation engine.
 * @author jens dietrich
 */

public class GraphBasedResultView extends ResultView {

    private JPanel graphPane = new JPanel();
    private GraphBasedResultViewSettings settings = GraphBasedResultViewSettings.DEFAULT_INSTANCE;

    public GraphBasedResultView() {
        super();
        this.setLayout(new GridLayout(1, 1));
        graphPane.setLayout(new GridLayout(1, 1));
        this.add(new JScrollPane(graphPane));
    }

    public PropertyBean getSettings() {
        return settings;
    }

    @Override
    public void display(final MotifInstance instance, DirectedGraph<Vertex, Edge> graph) {
        DirectedGraph<VisualVertex, VisualEdge> g = instance == null
                ? new DirectedSparseGraph<VisualVertex, VisualEdge>()
                : this.asGraph(instance);
        //SimpleGraphView sgv = new SimpleGraphView(); //We create our graph in here
        // The Layout<V, E> is parameterized by the vertex and edge types
        Layout<VisualVertex, VisualEdge> layout = settings.getLayout(g);
        layout.setSize(graphPane.getSize());
        VisualizationViewer<VisualVertex, VisualEdge> vv = new VisualizationViewer<VisualVertex, VisualEdge>(
                layout);

        if (!settings.isUseAntiAliasing()) {
            Map hints = new HashMap();
            hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
            vv.setRenderingHints(hints);
        }

        configureRenderer(vv.getRenderContext(), instance);
        vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
        vv.setPreferredSize(graphPane.getSize()); //Sets the viewing area size
        vv.setBackground(settings.getBackground());

        graphPane.removeAll();
        graphPane.add(vv);
        graphPane.revalidate();

        // pick the vertices that are part of the pattern - this brings them into the foreground

        /*
        for (VisualVertex v:g.getVertices()){
           if (v.isInMotif()) {
        vv.getPickedVertexState().pick(v,true);
           }
        }
        */

        //vv.addMouseListener(popupListener);
        // Create a graph mouse and add it to the visualization component
        DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
        gm.setMode(edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode.PICKING);
        vv.setGraphMouse(gm);
        vv.setVertexToolTipTransformer(new Transformer<VisualVertex, String>() {
            @Override
            public String transform(VisualVertex v) {
                return getToolTip(v);
            }
        });
    }

    private String getToolTip(Vertex v) {
        StringBuffer b = new StringBuffer();
        b.append("<html>");
        print(b, "container", v.getContainer(), false);
        print(b, "namespace", v.getNamespace(), false);
        print(b, "name", v.getName(), false);
        print(b, "type", v.getType(), false);
        print(b, "is abstract", v.isAbstract(), true);
        b.append("</html>");
        return b.toString();
    }

    private void print(StringBuffer b, String key, Object value, boolean last) {
        b.append("<i>");
        b.append(key);
        b.append("</i>:");
        b.append(value);
        if (!last)
            b.append("<br/>");
    }

    @Override
    public String getName() {
        return "query results as graph";
    }

    private void configureRenderer(RenderContext context, final MotifInstance instance) {
        final Map<String, Color> colMap = createColorMap(instance);

        context.setEdgeDrawPaintTransformer(new Transformer<VisualEdge, Paint>() {
            @Override
            public Paint transform(VisualEdge e) {
                return e.isInMotif() ? new Color(0, 0, 0, 100) : new Color(100, 100, 100, 50);
            }
        });

        context.setVertexLabelTransformer(new Transformer<VisualVertex, String>() {
            @Override
            public String transform(VisualVertex v) {
                String role = v.getRole();
                StringBuffer b = new StringBuffer().append("<html>");
                if (role != null) {
                    b.append("&lt;&lt;").append(role).append("&gt;&gt").append("<br/>");
                }
                b.append(v.getName()).append("</html>");
                return b.toString();
            }
        });
        context.setEdgeLabelTransformer(new Transformer<VisualEdge, String>() {
            @Override
            public String transform(VisualEdge e) {
                return "<<" + e.getType() + ">>";
            }
        });
        context.setVertexFillPaintTransformer(new Transformer<VisualVertex, Paint>() {
            @Override
            public Paint transform(VisualVertex v) {
                Color c = colMap.get(v.getNamespace());
                if (c != null)
                    return c;
                else
                    return Color.white;
            }
        });
        context.setVertexDrawPaintTransformer(new Transformer<VisualVertex, Paint>() {
            @Override
            public Paint transform(VisualVertex v) {
                return v.isInMotif() ? Color.black : Color.gray;
            }
        });

        context.setVertexStrokeTransformer(new Transformer<VisualVertex, Stroke>() {
            public Stroke transform(VisualVertex v) {
                if (v.isInMotif()) {
                    if (v.getRole() != null)
                        return GraphRendererConstants.STROKE_BOLD;
                    else
                        return GraphRendererConstants.STROKE_NORMAL;
                } else {
                    return GraphRendererConstants.STROKE_NONE;
                }
            }
        });

        context.setVertexShapeTransformer(new Transformer<VisualVertex, Shape>() {
            @Override
            public Shape transform(VisualVertex v) {
                String longLabel = v.getName();
                Font f = settings.getFont4Participants();
                FontMetrics FM = GraphBasedResultView.this.getGraphics().getFontMetrics(f);
                int W = Math.max(settings.getMinBoxWidth(), FM.stringWidth(longLabel) + 10);
                int H = v.getRole() != null ? settings.getBoxHeight4Participants()
                        : settings.getBoxHeight4NonParticipants();

                return new Rectangle2D.Float(-W / 2, -H / 2, W, H);
            }

        });

        context.setVertexFontTransformer(new Transformer<VisualVertex, Font>() {
            @Override
            public Font transform(VisualVertex v) {
                return v.getRole() != null ? settings.getFont4Participants() : settings.getFont4NonParticipants();
            }
        });
        context.setEdgeFontTransformer(new Transformer<VisualEdge, Font>() {
            @Override
            public Font transform(VisualEdge e) {
                return settings.getFont4Edges();
            }
        });

    }

    private Map<String, Color> createColorMap(MotifInstance instance) {
        if (instance == null)
            return new HashMap<String, Color>(0);
        Set<Vertex> vertices = instance.getVertices();
        Set<String> packages = new HashSet<String>(vertices.size());
        for (Vertex v : vertices) {
            packages.add(v.getNamespace());
        }
        int count = 0;
        Map<String, Color> pmap = new HashMap<String, Color>(packages.size());
        float offset = 100 / packages.size();
        offset = offset / 100;
        for (String p : packages) {
            Color hsb = Color.getHSBColor(count * offset, settings.getVertexSaturation(),
                    settings.getVertexBrightness());
            pmap.put(p, new Color(hsb.getRed(), hsb.getGreen(), hsb.getBlue(), settings.getVertexTransparency())); // transparency
            //pmap.put(p,hsb);
            count = count + 1;
        }
        return pmap;
    }

    private DirectedGraph<VisualVertex, VisualEdge> asGraph(MotifInstance instance) {
        DirectedGraph<VisualVertex, VisualEdge> g = new DirectedSparseGraph<VisualVertex, VisualEdge>();
        Motif motif = instance.getMotif();
        // vertices
        Map<String, VisualVertex> vertices = new HashMap<String, VisualVertex>();
        Map<Vertex, VisualVertex> originalVertices = new HashMap<Vertex, VisualVertex>();
        for (String role : motif.getRoles()) {
            Vertex v = instance.getVertex(role);
            if (v != null && !vertices.containsKey(v.getId())) { // the second check is necessary in case there are multiple roles for one vertex
                VisualVertex vv = toVisual(v, 0);
                g.addVertex(vv);
                vv.setRole(role);
                vertices.put(v.getId(), vv);
                originalVertices.put(v, vv);
            }
        }
        ;
        // edges
        for (String role : motif.getPathRoles()) {
            Path p = instance.getPath(role);
            if (p != null) {
                for (Edge e : p.getEdges()) {
                    Vertex v1 = e.getStart();
                    Vertex v2 = e.getEnd();
                    VisualVertex vv1 = vertices.get(v1.getId());
                    if (vv1 == null) {
                        vv1 = toVisual(v1, 0);
                        vertices.put(v1.getId(), vv1);
                        originalVertices.put(v1, vv1);
                    }
                    VisualVertex vv2 = vertices.get(v2.getId());
                    if (vv2 == null) {
                        vv2 = toVisual(v2, 0);
                        vertices.put(v2.getId(), vv2);
                        originalVertices.put(v2, vv2);
                    }
                    VisualEdge ve = toVisual(e, true);
                    ve.setStart(vv1);
                    ve.setEnd(vv2);
                    g.addEdge(ve, vv1, vv2);
                }
            }
        }
        addContext(g, originalVertices, settings.getContextDepth(), 1);
        return g;
    }

    private void addContext(DirectedGraph<VisualVertex, VisualEdge> g, Map<Vertex, VisualVertex> vertices,
            int contextDepth, int distanceToMotif) {
        if (contextDepth == 0)
            return;
        Set<Vertex> keys = new HashSet<Vertex>();
        keys.addAll(vertices.keySet()); // to prevent a java.util.ConcurrentModificationException
        for (Vertex v : keys) {
            VisualVertex vv = vertices.get(v);
            for (Edge e : v.getInEdges()) {
                Vertex v1 = e.getStart();
                if (!vertices.containsKey(v1)) {
                    VisualVertex vv1 = this.toVisual(v1, distanceToMotif);
                    g.addVertex(vv1);
                    vertices.put(v1, vv1);
                    VisualEdge ve = this.toVisual(e, false);
                    ve.setStart(vv1);
                    ve.setEnd(vv);
                    g.addEdge(ve, vv1, vv);
                }
            }
            for (Edge e : v.getOutEdges()) {
                Vertex v1 = e.getEnd();
                if (!vertices.containsKey(v1)) {
                    VisualVertex vv1 = this.toVisual(v1, distanceToMotif);
                    g.addVertex(vv1);
                    vertices.put(v1, vv1);
                    VisualEdge ve = this.toVisual(e, false);
                    ve.setStart(vv);
                    ve.setEnd(vv1);
                    g.addEdge(ve, vv, vv1);
                }
            }
        }
        addContext(g, vertices, contextDepth - 1, distanceToMotif + 1);
    }

    private VisualVertex toVisual(Vertex v, int distanceFromMotif) {
        VisualVertex vv = new VisualVertex();
        vv.setId(v.getId());
        v.copyValuesTo(vv);
        vv.setInMotif(distanceFromMotif == 0);
        vv.setDistanceFromMotif(distanceFromMotif);
        return vv;
    }

    private VisualEdge toVisual(Edge e, boolean isPartOfMotif) {
        VisualEdge ve = new VisualEdge();
        ve.setId(e.getId());
        e.copyValuesTo(ve);
        ve.setInMotif(isPartOfMotif);
        return ve;
    }

}