Package com.puppetlabs.geppetto.graph.catalog

Source Code of com.puppetlabs.geppetto.graph.catalog.CatalogGraphProducer

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.graph.catalog;

import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import com.puppetlabs.geppetto.catalog.Catalog;
import com.puppetlabs.geppetto.catalog.CatalogEdge;
import com.puppetlabs.geppetto.catalog.CatalogResource;
import com.puppetlabs.geppetto.catalog.CatalogResourceParameter;
import com.puppetlabs.graph.ICancel;
import com.puppetlabs.graph.elements.Edge;
import com.puppetlabs.graph.elements.RootGraph;
import com.puppetlabs.graph.elements.Vertex;
import com.puppetlabs.graph.graphcss.GraphCSS;
import com.puppetlabs.graph.graphcss.StyleSet;
import com.puppetlabs.graph.style.Span;
import com.puppetlabs.graph.style.labels.LabelRow;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;

import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
* Produces a Catalog graph in DOT format.
*
*/
public class CatalogGraphProducer extends AbstractCatalogGraphProducer implements CatalogGraphStyles {

  private Vertex createVertexFor(CatalogResource resource, IPath root) {
    Vertex v = new Vertex("", STYLE_Resource);
    v.setStyles(labelStyleForResource(resource, root));
    return v;
  }

  private StyleSet labelStyleForResource(CatalogResource r, final IPath root) {

    // Produce a sorted list of parameters (that skips parameters that are really dependencies)
    List<LabelRow> labelRows = Lists.newArrayList();
    CatalogResourceParameter[] sortedProperties = Iterables.toArray(
      Iterables.filter(getParameterIterable(r), regularParameterPredicate), CatalogResourceParameter.class);

    Arrays.sort(sortedProperties, new Comparator<CatalogResourceParameter>() {

      @Override
      public int compare(CatalogResourceParameter o1, CatalogResourceParameter o2) {
        return o1.getName().compareTo(o2.getName());
      }

    });

    // Add a labelRow for the type[id]
    StringBuilder builder = new StringBuilder();
    builder.append(r.getType());
    builder.append("[");
    builder.append(r.getTitle());
    builder.append("]");

    int width = 0;
    boolean hasParameters = sortedProperties.length > 0;
    boolean hasFooter = r.getFile() != null;
    if(hasParameters || hasFooter)
      labelRows.add(getStyles().labelRow(
        "RowSeparator", getStyles().labelCell("SpacingCell", "", Span.colSpan(3))));

    labelRows.add(getStyles().labelRow(STYLE_ResourceTitleRow, //
      getStyles().labelCell(STYLE_ResourceTitleCell, builder.toString(), Span.colSpan(3))));
    width += builder.length();

    // Rendering of separator line fails in graphviz 2.28 with an error
    // labelRows.add(getStyles().rowSeparator());
    if(hasParameters || hasFooter) {
      labelRows.add(getStyles().labelRow(
        "RowSeparator", getStyles().labelCell("SpacingCell", "", Span.colSpan(3))));
      labelRows.add(getStyles().labelRow("RowSeparator", getStyles().labelCell("HRCell", "", Span.colSpan(3))));
      labelRows.add(getStyles().labelRow(
        "RowSeparator", getStyles().labelCell("SpacingCell", "", Span.colSpan(3))));
    }
    // parameters
    for(CatalogResourceParameter a : sortedProperties) {
      final String aName = a.getName();

      // output file contents as "DATA" as we can't fit the entire contents into a cell.
      List<String> values = "content".equals(aName)
          ? Lists.newArrayList("DATA")
          : a.getValue();
      builder = new StringBuilder();
      for(String v : values) {
        builder.append(v);
        builder.append(" ");
      }
      // remove trailing space
      builder.deleteCharAt(builder.length() - 1);
      String value = builder.toString();

      labelRows.add(getStyles().labelRow(STYLE_ResourcePropertyRow, //
        getStyles().labelCell(STYLE_ResourcePropertyName, a.getName()), //
        getStyles().labelCell(STYLE_ResourcePropertyValue, DOUBLE_RIGHT_ARROW + value, Span.colSpan(2)) //
      ));

      int tmpWidth = a.getName().length() + value.length() + 2;
      if(tmpWidth > width)
        width = tmpWidth;
    }

    // A footer with filename[line]
    // (is not always present)
    if(hasFooter) {
      builder = new StringBuilder();
      // shorten the text by making it relative to root if possible
      if(root != null)
        builder.append(new Path(r.getFile()).makeRelativeTo(root).toString());
      else
        builder.append(r.getFile());
      if(r.getLine() != null) {
        builder.append("[");
        builder.append(r.getLine());
        builder.append("]");
      }
      String tooltip = builder.toString();
      if(builder.length() > width) {
        builder.delete(0, builder.length() - width);
        builder.insert(0, "[...]");
      }

      if(hasParameters)
        labelRows.add(getStyles().labelRow(
          "RowSeparator", getStyles().labelCell("SpacingCell", "", Span.colSpan(3))));
      int line = -1;
      try {
        line = Integer.valueOf(r.getLine());
      }
      catch(NumberFormatException e) {
        line = -1;
      }

      labelRows.add(getStyles().labelRow(STYLE_ResourceFileInfoRow, //
        getStyles().labelCell(STYLE_ResourceFileInfoCell, builder.toString(), Span.colSpan(3)).withStyles(//
          getStyles().tooltip(tooltip), //
          getStyles().href(getHrefProducer().hrefToManifest(new Path(r.getFile()), root, line)) //
        )) //
      );
    }
    else if(hasParameters) {
      // add a bit of padding at the bottom if there is no footer
      labelRows.add(getStyles().labelRow(
        "RowSeparator", getStyles().labelCell("SpacingCell", "", Span.colSpan(3))));
    }

    return StyleSet.withStyle(//
    getStyles().labelFormat(//
      getStyles().labelTable(STYLE_ResourceTable, //
        labelRows.toArray(new LabelRow[labelRows.size()]))));

  }

  /**
   * Produces a graph in DOT format for the given catalog on the given output stream.
   *
   * @param cancel
   *        enables cancellation of long running job
   * @param catalog
   *        the catalog for which a graph is produced
   * @param out
   *        where output in DOT format should be written
   * @param root
   *        the path to the root of file references in catalogs
   * @param moduleData
   *        Name -> 0* MetadataInfo representing one version of a module with given name
   */
  public void produceGraph(ICancel cancel, Catalog catalog, String catalogName, OutputStream out, IPath root) {
    if(cancel == null || catalog == null || out == null)
      throw new IllegalArgumentException("one or more parameters are null");

    RootGraph g = produceRootGraph(cancel, catalog, catalogName, root);
    GraphCSS instanceRules = getInstanceRules();
    instanceRules.addAll(getTheme().getInstanceRules());
    getDotRenderer().write(cancel, out, g, getTheme().getDefaultRules(), instanceRules);
  }

  /**
   * Produces the graph data structure (RootGraph, Vertexes, Edges).
   *
   */
  private RootGraph produceRootGraph(ICancel cancel, Catalog catalog, String catalogName, final IPath root) {

    RootGraph g = new RootGraph(catalogName, "RootGraph", "root");

    // Iterate the catalog
    // What to do with these? Are they of any value?
    // catalog.getClasses(); // list of classnames
    // catalog.getTags(); // don't know if these have any value...

    Map<String, Vertex> vertexMap = Maps.newHashMap();
    Map<CatalogResource, Vertex> resourceVertexMap = Maps.newHashMap();

    for(CatalogResource r : catalog.getResources()) {
      StringBuilder builder = new StringBuilder();
      builder.append(r.getType().toLowerCase());
      builder.append("[");
      builder.append(r.getTitle().toLowerCase());
      builder.append("]");

      Vertex v = createVertexFor(r, root);
      g.addVertex(v);
      vertexMap.put(builder.toString(), v);
      resourceVertexMap.put(r, v);
    }

    for(CatalogResource r : catalog.getResources()) {
      final Vertex source = resourceVertexMap.get(r);
      for(CatalogResourceParameter p : Iterables.filter(
        getParameterIterable(r), Predicates.not(regularParameterPredicate))) {
        String aName = p.getName();
        String style = null;
        if("subscribe".equals(aName))
          style = CatalogGraphStyles.STYLE_SubscribeEdge;
        else if("before".equals(aName))
          style = CatalogGraphStyles.STYLE_BeforeEdge;
        else if("notify".equals(aName))
          style = CatalogGraphStyles.STYLE_NotifyEdge;
        else
          style = CatalogGraphStyles.STYLE_RequireEdge;
        for(String ref : p.getValue()) {
          Vertex target = vertexMap.get(ref.toLowerCase());
          if(target == null) {
            target = createVertexForMissingResource(ref);
            vertexMap.put(ref.toLowerCase(), target); // keep it if there are more references
            g.addVertex(target);
          }
          Edge edge = new Edge(aName, style, source, target);
          g.addEdge(edge);
        }
      }
    }
    for(CatalogEdge e : catalog.getEdges()) {
      Vertex source = vertexMap.get(e.getSource().toLowerCase());
      Vertex target = vertexMap.get(e.getTarget().toLowerCase());
      Edge edge = new Edge("", STYLE_ResourceEdge, source, target);
      g.addEdge(edge);
    }

    return g;
  }
}
TOP

Related Classes of com.puppetlabs.geppetto.graph.catalog.CatalogGraphProducer

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.