Package de.arago.rike.svg

Source Code of de.arago.rike.svg.SVGGraphCreator

/**
* Copyright (c) 2010 arago AG, http://www.arago.de/
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package de.arago.rike.svg;

import de.arago.rike.commons.data.Artifact;
import de.arago.rike.commons.data.DataHelperRike;
import de.arago.rike.commons.data.Dependency;
import de.arago.rike.commons.data.Milestone;
import de.arago.rike.commons.data.Task;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

public class SVGGraphCreator {

    private static final ConcurrentHashMap<String, SVGContainer> cache = new ConcurrentHashMap<String, SVGContainer>();
    private static final long ONE_MINUTE = 0L;

    private static final class SVGContainer {

        private final String data;
        private final Date created;

        public SVGContainer(String data) {
            this.data = data;
            created = new Date();
        }

        public String getData() {
            return data;
        }

        public boolean isExpired() {
            return created.getTime() < (System.currentTimeMillis() - ONE_MINUTE);
        }
    }

    public static void clearCache() {
        cache.clear();
    }

    /**
     * Create an svg graph for the node with its dependent node in parent and
     * child directions
     *
     * @param id
     * @return SVG content
     */
    public static String getGraph(SvgFilter filter) throws IOException, InterruptedException {

        SVGContainer container = cache.get(filter.getId());

        if (container == null || container.isExpired()) {
            StringBuilder content = createDotNotation(filter);

//      container = new SVGContainer(content.toString());
            container = new SVGContainer(transformDotToSVG(content));

            cache.put(filter.getId(), container);
        }

        return container.getData();
    }

    static StringBuilder createDotNotation(SvgFilter filter) {
        DataHelperRike<Task> helper = new DataHelperRike<Task>(Task.class);

        TreeSet<String> dates = new TreeSet<String>();
        for (Task task : helper.list(makeCriteria(filter, helper))) {
            if (task.getStart() != null) {
                dates.add(String.format("%1$tY-%1$tm-%1$td", task.getStart()));
            }
        }

        StringBuilder content = new StringBuilder();
        content.append("digraph G {\n    rankdir=LR;\n");

        TreeSet<Long> tasks = new TreeSet<Long>();
        String artifact_id = "";
        for (Task task : helper.list(makeCriteria(filter, helper))) {
            if (task.getArtifact() != null && !artifact_id.equals("" + task.getArtifact().getId())) {
                if (artifact_id.length() > 0) {
                    content.append("}\n\n");
                }
                artifact_id = "" + task.getArtifact().getId();
                content.append(String.format("subgraph cluster_%1$s{\n", artifact_id));
                content.append("  labeljust=r\n");
                content.append(String.format("  label=\"%1$s\"\n\n", task.getArtifact().getName()));

                for (String date : dates) {
                    content.append(String.format("  \"%1$s.%2$s\" [label=\"%2$s\",style=filled,fillcolor=beige,shape=invhouse]\n", artifact_id, date));
                }
                content.append(String.format("  \"%1$s.NEXT\" [label=\"Next\",style=filled,fillcolor=beige,shape=invhouse]\n\n", artifact_id));
                for (String date : dates) {
                    content.append(String.format("\"%1$s.%2$s\"->", artifact_id, date));
                }
                content.append(String.format("\"%1$s.NEXT\" [weight=8]\n\n", artifact_id));
            }

            String color = "dodgerblue";
            if ("open".equals(task.getStatus())) {
                color = "red";
            } else if ("done".equals(task.getStatus())) {
                color = "green";
            } else if ("in_progress".equals(task.getStatus())) {
                color = "yellow";
            }

            String name = formatName(task.getTitle());

            content.append(String.format("  %1$d [label=\"%2$s\",target=_parent,URL=\"%3$s\",style=filled,shape=note,fillcolor=%4$s]\n",
                                         task.getId(), name, "javascript:top.openRikeTask(" + task.getId() + ")", color));
            String start = "NEXT";
            if (task.getStart() != null) {
                start = String.format("%1$tY-%1$tm-%1$td", task.getStart());
            }
            content.append(String.format("  \"%1$s.%2$s\"->%3$d [color=invis]\n", artifact_id, start, task.getId()));

            tasks.add(task.getId());
        }

        if (artifact_id.length() > 0) {
            content.append("}\n\n");
        }

        DataHelperRike<Dependency> deps = new DataHelperRike<Dependency>(Dependency.class);
        for (Dependency d : deps.list()) {
            if (tasks.contains(d.getPremise()) && tasks.contains(d.getSequel())) {
                content.append(String.format("%1$d->%2$d\n", d.getPremise(), d.getSequel()));
            }
        }

        content.append("}\n");
        return content;
    }

    private static String formatName(String rawName) {
        String nameFixed = rawName.replace("\"", "\\\"").replaceAll("\\s", " ");
        String name = "";
        while(nameFixed.length()>30) {
            int pos = nameFixed.indexOf(" ",25);
            if (pos>0) {
                name += nameFixed.substring(0,pos)+"\\n";
                nameFixed = nameFixed.substring(pos+1);
            } else
                break;
        }
        name += nameFixed;
        return name;
    }

    private static Criteria makeCriteria(SvgFilter filter,
                                         DataHelperRike<Task> helper) {
        Criteria crit = helper.filter();

        if (filter.getUser() != null && filter.getUser().length() > 0) {
            crit.add(Restrictions.eq("owner", filter.getUser()));
        }

        if (filter.getArtifact() != null && filter.getArtifact() >= 0) {
            Artifact a = new DataHelperRike<Artifact>(Artifact.class).find(filter.getArtifact());
            crit.add(Restrictions.eq("artifact", a));
        }

        if (filter.getMilestone() != null && !filter.getMilestone().isEmpty()) {

            String tmp = filter.getMilestone();

            if (tmp.startsWith("milestone_")) {
                Milestone m = new DataHelperRike<Milestone>(Milestone.class).find(filter.getMilestone().substring(10));

                crit.add(Restrictions.eq("milestone", m));
            } else if (tmp.startsWith("release_")) {
                DataHelperRike<Milestone> milestoneHelper = new DataHelperRike<Milestone>(Milestone.class);

                List<Milestone> list = milestoneHelper.list(milestoneHelper.filter().add(Restrictions.eq("release", filter.getMilestone().substring(8))));

                crit.add(Restrictions.in("milestone", list));
            }

        }

        crit.addOrder(Order.asc("artifact"));
        return crit;
    }

    private static String transformDotToSVG(StringBuilder content) throws IOException, InterruptedException {
        File file = File.createTempFile("pattern", ".dot");

        new FileWriter(file).append(content.toString()).close();

        Process p = Runtime.getRuntime().exec(new String[] {
                                                  "dot",
                                                  "-Tsvg",
                                                  "-Gsplines=true",
                                                  "-Goverlap=false",
                                                  "-Grankdir=LR",
                                                  "-o" + file.getAbsolutePath() + ".svg",
                                                  file.getAbsolutePath()
                                              });

        p.waitFor();

        file.delete();

        StringBuilder b = new StringBuilder();
        BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath() + ".svg"));

        String part;
        while ((part = reader.readLine()) != null) {
            b.append(part);
        }

        reader.close();

        new File(file.getAbsolutePath() + ".svg").delete();

        return b.toString();
    }
}
TOP

Related Classes of de.arago.rike.svg.SVGGraphCreator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.