/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project 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.0 of the License, or (at your option) any later version.
* This library 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 project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore.generating.templateengine.reporting.artifacts.formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import de.monticore.generating.templateengine.reporting.artifacts.model.APkg;
import de.monticore.generating.templateengine.reporting.artifacts.model.Element;
import de.monticore.generating.templateengine.reporting.artifacts.model.ElementType;
import de.monticore.generating.templateengine.reporting.artifacts.model.Pkg;
import de.monticore.generating.templateengine.reporting.artifacts.model.RootPkg;
/**
* TODO: Write me!
*
* @author (last commit) $Author$
* @version $Revision$, $Date$
*/
public class GMLFormatter extends AFormatter {
private Map<Element, Integer> elementIds = new HashMap<Element, Integer>();
private Map<APkg, Integer> packageIds = new HashMap<APkg, Integer>();
private int nodeIdCounter = 0;
private int edgeIdCounter = 0;
private long maxEdgeCalls = 0;
private double edgeSizeRange = 0;
/**
* @see AFormatter.printer.APrinter#print(visualization.model.RootPkg)
*/
@Override
public List<String> getContent(RootPkg rootPkg) {
List<String> lines = Lists.newArrayList();
calculateMaxEdgeCalls(rootPkg);
edgeSizeRange = maxEdgeCalls / 7;
addLine(lines, "graph [");
indent();
addLine(lines, "directed 1");
lines.addAll(getAllPkgContent(rootPkg));
lines.addAll(getAllLinkContent(rootPkg));
unindent();
addLine(lines, "]");
return lines;
}
private void calculateMaxEdgeCalls(APkg pkg) {
for (Element e : pkg.getElements()) {
for (Element link : e.getLinks()) {
Long linkCalls = e.getNumberOfLinkCalls(link);
if (linkCalls > maxEdgeCalls) {
maxEdgeCalls = linkCalls;
}
}
}
for (Pkg p : pkg.getSubPkgs()) {
calculateMaxEdgeCalls(p);
}
}
/**
* @param pkg
*/
private List<String> getAllLinkContent(APkg pkg) {
List<String> lines = Lists.newArrayList();
for (Element e : pkg.getElements()) {
lines.addAll(getLinkContent(e));
}
for (Pkg p : pkg.getSubPkgs()) {
lines.addAll(getAllLinkContent(p));
}
return lines;
}
private List<String> getAllPkgContent(APkg pkg) {
List<String> lines = Lists.newArrayList();
if (pkg.hasElements()) {
lines.addAll(getPkgContent(pkg));
}
for (Pkg subPkg : pkg.getSubPkgs()) {
lines.addAll(getAllPkgContent(subPkg));
}
for (Element e : pkg.getElements()) {
lines.addAll(getElementContent(e));
}
return lines;
}
private List<String> getPkgContent(APkg pkg) {
List<String> lines = Lists.newArrayList();
if (!pkg.containsNonFileElement()) {
return lines;
}
addLine(lines, "node [");
indent();
addLine(lines, "id " + getGroupIDByPackage(pkg));
addLine(lines, "label " + "\"" + pkg.getQualifiedName() + "\"");
addLine(lines, "graphics [");
indent();
addLine(lines, "type \"roundrectangle\"");
addLine(lines, "fill \"#F5F5F5\"");
addLine(lines, "outline \"#000000\"");
addLine(lines, "outlineStyle \"dashed\"");
addLine(lines, "topBorderInset 0.0");
addLine(lines, "bottomBorderInset 0.0");
addLine(lines, "leftBorderInset 0.0");
addLine(lines, "rightBorderInset 0.0");
unindent();
addLine(lines, "]");
addLine(lines, "LabelGraphics [");
indent();
addLine(lines, "fill \"#EBEBEB\"");
addLine(lines, "fontSize 15");
addLine(lines, "fontName \"Dialog\"");
addLine(lines, "alignment \"right\"");
addLine(lines, "autoSizePolicy \"node_width\"");
addLine(lines, "anchor \"t\"");
addLine(lines, "borderDistance 0.0");
unindent();
addLine(lines, "]");
addLine(lines, "isGroup 1");
APkg ancestor = pkg.resolveAncestorWithElements();
if (ancestor != null) {
addLine(lines, "gid " + getGroupIDByPackage(ancestor));
}
unindent();
addLine(lines, "]");
return lines;
}
/**
* Print the dot graph representation of this element
*
* @param o Open file to write to
* @param space Space for indentation
*/
public List<String> getElementContent(Element element) {
List<String> lines = Lists.newArrayList();
if (element.getType() == ElementType.FILE) {
return lines;
}
addLine(lines, "node [");
indent();
addLine(lines, "id " + getID(element));
addLine(lines, "label " + "\"" + element.getFullName() + " (" + element.getNumberOfCalls()
+ ")\"");
addLine(lines, "graphics [");
indent();
if (element.hasLinkToFile()) {
addLine(lines, "fill \"#00FF00\"");
}
addLine(lines, "type " + "\"" + getShape(element.getType()) + "\"");
unindent();
addLine(lines, "]");
addLine(lines, "gid " + getGroupIDByPackage(element.getPkg()));
unindent();
addLine(lines, "]");
return lines;
}
/**
*
* @param name
* @return
*/
private String getShape(ElementType type) {
switch (type) {
case HELPER:
return "diamond";
case MODEL:
return "hexagon";
case TEMPLATE:
return "ellipse";
default:
return "octagon";
}
}
/**
* @param pkg
* @return
*/
private Integer getGroupIDByPackage(APkg pkg) {
if (packageIds.containsKey(pkg)) {
return packageIds.get(pkg);
}
nodeIdCounter++;
packageIds.put(pkg, nodeIdCounter);
return nodeIdCounter;
}
/**
* @param element
* @return
*/
private Integer getID(Element element) {
if (elementIds.containsKey(element)) {
return elementIds.get(element);
}
nodeIdCounter++;
elementIds.put(element, nodeIdCounter);
return nodeIdCounter;
}
/**
* write all links to supplied open file
*/
public List<String> getLinkContent(Element element) {
List<String> lines = Lists.newArrayList();
Integer elementId = elementIds.get(element);
for (Element link : element.getLinks()) {
if (link.getType() == ElementType.FILE) {
continue;
}
long calls = element.getNumberOfLinkCalls(link);
edgeIdCounter++;
addLine(lines, "edge [");
indent();
addLine(lines, "id " + edgeIdCounter);
addLine(lines, "source " + elementId);
addLine(lines, "target " + elementIds.get(link));
addLine(lines, "label " + "\"(" + calls + ")\"");
addLine(lines, "graphics [");
indent();
addLine(lines, "targetArrow \"standard\"");
addLine(lines, "width " + getEdgeWith(calls));
unindent();
addLine(lines, "]");
unindent();
addLine(lines, "]");
}
return lines;
}
/**
* TODO: Write me!
* @param calls
* @return
*/
private int getEdgeWith(long calls) {
return Math.min((int) (calls/edgeSizeRange) + 1, 7);
}
}