DefinitionGraphInpector.java

  1. /*
  2.  * Copyright © 2017, Salesforce.com, Inc
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are met:
  7.  *     * Redistributions of source code must retain the above copyright
  8.  *       notice, this list of conditions and the following disclaimer.
  9.  *     * Redistributions in binary form must reproduce the above copyright
  10.  *       notice, this list of conditions and the following disclaimer in the
  11.  *       documentation and/or other materials provided with the distribution.
  12.  *     * Neither the name of the <organization> nor the
  13.  *       names of its contributors may be used to endorse or promote products
  14.  *       derived from this software without specific prior written permission.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19.  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  20.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26.  */
  27. package com.salesforce.apt.graph.processing;

  28. import java.util.Collection;
  29. import java.util.List;
  30. import java.util.Set;
  31. import java.util.function.Consumer;
  32. import java.util.stream.Collectors;

  33. import org.jgrapht.Graph;
  34. import org.jgrapht.alg.cycle.SzwarcfiterLauerSimpleCycles;
  35. import org.jgrapht.graph.DefaultDirectedGraph;
  36. import org.jgrapht.graph.DefaultEdge;

  37. import com.salesforce.apt.graph.model.DefinitionModel;
  38. import com.salesforce.apt.graph.model.errors.ErrorModel;
  39. import com.salesforce.apt.graph.model.errors.ErrorType;

  40. public class DefinitionGraphInpector {

  41.   public Set<DefinitionModel> inspectDefinitionGraph(Collection<DefinitionModel> definitions,
  42.       Consumer<ErrorModel> errorListener) {
  43.     Graph<DefinitionModel, DefaultEdge> graph = buildDefinitionGraph(definitions);
  44.     errorForCycles(graph, errorListener);
  45.     //TODO return all DefinitionModel needing re-evaluation
  46.     return graph.vertexSet().stream().filter(dm -> graph.inDegreeOf(dm) == 0).collect(Collectors.toSet());
  47.   }
  48.  
  49.   private void errorForCycles(Graph<DefinitionModel, DefaultEdge> definitionGraph,
  50.       Consumer<ErrorModel> errorListener) {
  51.     SzwarcfiterLauerSimpleCycles<DefinitionModel, DefaultEdge> cycleFind = new SzwarcfiterLauerSimpleCycles<>();
  52.     cycleFind.setGraph(definitionGraph);
  53.     for (List<DefinitionModel> list : cycleFind.findSimpleCycles()) {
  54.       errorListener.accept(new ErrorModel(ErrorType.CYCLE_IN_DEFINITION_SOURCES, list, list));
  55.     }
  56.   }
  57.  
  58.   private Graph<DefinitionModel, DefaultEdge> buildDefinitionGraph(Collection<DefinitionModel> definitions) {
  59.     Graph<DefinitionModel, DefaultEdge> definitionGraph = new DefaultDirectedGraph<>(DefaultEdge.class);
  60.     buildDefinitionGraph(definitions, definitionGraph);
  61.     return definitionGraph;
  62.   }

  63.   private void buildDefinitionGraph(Collection<DefinitionModel> definitions,
  64.       Graph<DefinitionModel, DefaultEdge> definitionGraph) {
  65.     for (DefinitionModel definition : definitions) {
  66.       if (!definitionGraph.containsVertex(definition)) {
  67.         definitionGraph.addVertex(definition);
  68.         buildDefinitionGraph(definition.getDependencies(), definitionGraph);
  69.         for (DefinitionModel dependency : definition.getDependencies()) {
  70.           definitionGraph.addEdge(definition, dependency);
  71.         }
  72.       }
  73.     }
  74.   }
  75.  
  76. }