diff --git a/reporting/api/src/main/java/org/jboss/windup/reporting/model/TaggableModel.java b/reporting/api/src/main/java/org/jboss/windup/reporting/model/TaggableModel.java index c18e531e68..f542cc11ae 100644 --- a/reporting/api/src/main/java/org/jboss/windup/reporting/model/TaggableModel.java +++ b/reporting/api/src/main/java/org/jboss/windup/reporting/model/TaggableModel.java @@ -11,6 +11,7 @@ import com.tinkerpop.frames.modules.javahandler.JavaHandler; import com.tinkerpop.frames.modules.javahandler.JavaHandlerContext; import com.tinkerpop.frames.modules.typedgraph.TypeValue; +import org.jboss.windup.reporting.TagUtil; /** * @author Jesse Sightler @@ -38,9 +39,21 @@ public interface TaggableModel extends WindupVertexFrame @Adjacency(label = TAG, direction = Direction.OUT) TagSetModel getTagModel(); + /** + * Gets the {@link Set} of tags associated with this vertex. + */ @JavaHandler Set getTags(); + /** + * Returns true if this {@link TaggableModel} matches the provided inclusion and exclusion tags. + * + * {@see TagUtil} + */ + @JavaHandler + boolean matchesTags(Set includeTags, Set excludeTags); + + abstract class Impl implements TaggableModel, JavaHandlerContext { @Override @@ -51,5 +64,10 @@ public Set getTags() return Collections.emptySet(); return tagSetModel.getTags(); } + + public boolean matchesTags(Set includeTags, Set excludeTags) + { + return TagUtil.checkMatchingTags(this.getTags(), includeTags, excludeTags); + } } } diff --git a/reporting/api/src/main/java/org/jboss/windup/reporting/service/ClassificationService.java b/reporting/api/src/main/java/org/jboss/windup/reporting/service/ClassificationService.java index aa57f97e1d..50319837dd 100644 --- a/reporting/api/src/main/java/org/jboss/windup/reporting/service/ClassificationService.java +++ b/reporting/api/src/main/java/org/jboss/windup/reporting/service/ClassificationService.java @@ -1,8 +1,5 @@ package org.jboss.windup.reporting.service; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -13,10 +10,8 @@ import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.graph.model.WindupVertexFrame; import org.jboss.windup.graph.model.resource.FileModel; -import org.jboss.windup.graph.service.FileService; import org.jboss.windup.graph.service.GraphService; import org.jboss.windup.graph.traversal.ProjectModelTraversal; -import org.jboss.windup.reporting.TagUtil; import org.jboss.windup.reporting.model.ClassificationModel; import org.jboss.windup.reporting.model.EffortReportModel; import org.jboss.windup.reporting.model.Severity; @@ -29,13 +24,13 @@ import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.frames.structures.FramedVertexIterable; import com.tinkerpop.gremlin.java.GremlinPipeline; -import com.tinkerpop.pipes.PipeFunction; +import org.apache.tools.ant.taskdefs.Length.FileMode; /** * Adds methods for loading and querying ClassificationModel related data. - * + * * @author Jesse Sightler - * + * */ public class ClassificationService extends GraphService { @@ -91,7 +86,8 @@ public Iterable getClassificationByName(FileModel model, St /** *

- * Returns the total effort points in all of the {@link ClassificationModel}s associated with the files in this project. + * Returns the total effort points in all of the {@link ClassificationModel}s + * associated with the {@link FileMode} instances in the given {@link ProjectModelTraversal}. *

*

* If set to recursive, then also include the effort points from child projects. @@ -100,109 +96,71 @@ public Iterable getClassificationByName(FileModel model, St * The result is a Map, the key contains the effort level and the value contains the number of incidents. *

*/ - public Map getMigrationEffortByPoints(ProjectModelTraversal initialProject, Set includeTags, Set excludeTags, + public Map getMigrationEffortByPoints(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive, boolean includeZero) { - final Map results = new HashMap<>(); - - EffortAccumulatorFunction accumulator = new EffortAccumulatorFunction() - { - @Override - public void accumulate(Vertex effortReportVertex) - { + MapSumEffortAccumulatorFunction accumulator = new MapSumEffortAccumulatorFunction(){ + public Integer vertexToKey(Vertex effortReportVertex) { Integer migrationEffort = effortReportVertex.getProperty(EffortReportModel.EFFORT); - if (!results.containsKey(migrationEffort)) - results.put(migrationEffort, 1); - else - results.put(migrationEffort, results.get(migrationEffort) + 1); + return migrationEffort; } }; - - getMigrationEffortDetails(initialProject, includeTags, excludeTags, recursive, includeZero, accumulator); - - return results; + getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, includeZero, accumulator); + return accumulator.getResults(); } /** - *

* Returns the total incidents in all of the {@link ClassificationModel}s associated with the files in this project by severity. - *

*/ - public Map getMigrationEffortBySeverity(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, - boolean recursive) + public Map getMigrationEffortBySeverity( + ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive) { - final Map results = new HashMap<>(); - - EffortAccumulatorFunction accumulator = new EffortAccumulatorFunction() - { - @Override - public void accumulate(Vertex effortReportVertex) - { - Severity severity = frame(effortReportVertex).getSeverity(); - if (!results.containsKey(severity)) - results.put(severity, 1); - else - results.put(severity, results.get(severity) + 1); + MapSumEffortAccumulatorFunction accumulator = new MapSumEffortAccumulatorFunction(){ + public Severity vertexToKey(Vertex effortReportVertex) { + return frame(effortReportVertex).getSeverity(); } }; - - getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, true, accumulator); - - return results; + this.getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, true, accumulator); + return accumulator.getResults(); } private void getMigrationEffortDetails(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive, boolean includeZero, EffortAccumulatorFunction accumulatorFunction) { - FileService fileService = new FileService(getGraphContext()); - final Set initialVertices = traversal.getAllProjectsAsVertices(recursive); - GremlinPipeline classificationPipeline = new GremlinPipeline<>(getGraphContext().getGraph()); - classificationPipeline.V(); + GremlinPipeline pipeline = new GremlinPipeline<>(this.getGraphContext().getGraph()); + pipeline.V(); + // If the multivalue index is not 1st, then it doesn't work - https://github.com/thinkaurelius/titan/issues/403 if (!includeZero) { - classificationPipeline.has(EffortReportModel.EFFORT, Compare.GREATER_THAN, 0); - classificationPipeline.has(WindupVertexFrame.TYPE_PROP, Text.CONTAINS, ClassificationModel.TYPE); + pipeline.has(EffortReportModel.EFFORT, Compare.GREATER_THAN, 0); + pipeline.has(WindupVertexFrame.TYPE_PROP, Text.CONTAINS, ClassificationModel.TYPE); } else { - classificationPipeline.has(WindupVertexFrame.TYPE_PROP, ClassificationModel.TYPE); + pipeline.has(WindupVertexFrame.TYPE_PROP, ClassificationModel.TYPE); } - - classificationPipeline.as("classification"); - classificationPipeline.out(ClassificationModel.FILE_MODEL); - classificationPipeline.in(ProjectModel.PROJECT_MODEL_TO_FILE); - classificationPipeline.filter(new PipeFunction() + pipeline.as("classification"); + // For each classification, count it repeatedly for each file that is within given set of Projects (from the traversal). + pipeline.out(ClassificationModel.FILE_MODEL); + pipeline.in(ProjectModel.PROJECT_MODEL_TO_FILE); + pipeline.filter(new SetMembersFilter(initialVertices)); + pipeline.back("classification"); + + boolean checkTags = !includeTags.isEmpty() || !excludeTags.isEmpty(); + for (Vertex v : pipeline) { - @Override - public Boolean compute(Vertex argument) - { - return initialVertices.contains(argument); - } - }); - classificationPipeline.back("classification"); - - for (Vertex v : classificationPipeline) - { - Integer migrationEffort = v.getProperty(EffortReportModel.EFFORT); - if (migrationEffort == null) - continue; - // only check tags if we have some passed in - if (!includeTags.isEmpty() || !excludeTags.isEmpty()) - { - ClassificationModel classificationModel = frame(v); - if (!TagUtil.checkMatchingTags(classificationModel.getTags(), includeTags, excludeTags)) - continue; - } + if (checkTags && !frame(v).matchesTags(includeTags, excludeTags)) + continue; + // For each classification, count it repeatedly for each file. + // TODO: .accumulate(v, count); + // TODO: This could be all done just within the query (provided that the tags would be taken care of). + // Accumulate could be a PipeFunction. for (Vertex fileVertex : v.getVertices(Direction.OUT, ClassificationModel.FILE_MODEL)) - { - FileModel fileModel = fileService.frame(fileVertex); - if (initialVertices.contains(fileModel.getProjectModel().asVertex())) - accumulatorFunction.accumulate(v); - } + accumulatorFunction.accumulate(v); } } diff --git a/reporting/api/src/main/java/org/jboss/windup/reporting/service/InlineHintService.java b/reporting/api/src/main/java/org/jboss/windup/reporting/service/InlineHintService.java index 932588a3f4..a5583479e3 100644 --- a/reporting/api/src/main/java/org/jboss/windup/reporting/service/InlineHintService.java +++ b/reporting/api/src/main/java/org/jboss/windup/reporting/service/InlineHintService.java @@ -33,6 +33,7 @@ import com.tinkerpop.pipes.PipeFunction; import javax.annotation.Nullable; +import org.jboss.windup.reporting.model.ClassificationModel; /** * This provides helper functions for finding and creating {@link InlineHintModel} instances within the graph. @@ -145,8 +146,8 @@ private Iterable getInlineHintModels(Iterable initialPr /** *

- * Returns the total effort points in all of the {@link InlineHintModel} instances associated with the {@link FileMode} instances in the given - * {@link ProjectModel}. + * Returns the total effort points in all of the {@link InlineHintModel}s + * associated with the {@link FileMode} instances in the given {@link ProjectModelTraversal}. *

*

* If set to recursive, then also include the effort points from child projects. @@ -155,98 +156,64 @@ private Iterable getInlineHintModels(Iterable initialPr * The result is a Map, the key contains the effort level and the value contains the number of incidents. *

*/ - public Map getMigrationEffortByPoints(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, - boolean recursive, boolean includeZero) + public Map getMigrationEffortByPoints( + ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive, boolean includeZero) { - final Map results = new HashMap<>(); - - EffortAccumulatorFunction accumulator = new EffortAccumulatorFunction() - { - @Override - public void accumulate(Vertex effortReportVertex) - { + MapSumEffortAccumulatorFunction accumulator = new MapSumEffortAccumulatorFunction(){ + public Object vertexToKey(Vertex effortReportVertex) { Integer migrationEffort = effortReportVertex.getProperty(EffortReportModel.EFFORT); - if (!results.containsKey(migrationEffort)) - results.put(migrationEffort, 1); - else - results.put(migrationEffort, results.get(migrationEffort) + 1); + return migrationEffort; } }; - getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, includeZero, accumulator); - - return results; + return accumulator.getResults(); } /** - *

* Returns the total incidents in all of the {@link InlineHintModel}s associated with the files in this project by severity. - *

*/ public Map getMigrationEffortBySeverity(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive) { - final Map results = new HashMap<>(); - - EffortAccumulatorFunction accumulator = new EffortAccumulatorFunction() - { - @Override - public void accumulate(Vertex effortReportVertex) - { - Severity severity = frame(effortReportVertex).getSeverity(); - if (!results.containsKey(severity)) - results.put(severity, 1); - else - results.put(severity, results.get(severity) + 1); + MapSumEffortAccumulatorFunction accumulator = new MapSumEffortAccumulatorFunction(){ + public Severity vertexToKey(Vertex effortReportVertex) { + return frame(effortReportVertex).getSeverity(); } }; - - getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, true, accumulator); - - return results; + this.getMigrationEffortDetails(traversal, includeTags, excludeTags, recursive, true, accumulator); + return accumulator.getResults(); } private void getMigrationEffortDetails(ProjectModelTraversal traversal, Set includeTags, Set excludeTags, boolean recursive, boolean includeZero, EffortAccumulatorFunction accumulatorFunction) { - final Set initialVertices = traversal.getAllProjectsAsVertices(recursive); - GremlinPipeline inlineHintPipeline = new GremlinPipeline<>(getGraphContext().getGraph()); - inlineHintPipeline.V(); + GremlinPipeline pipeline = new GremlinPipeline<>(this.getGraphContext().getGraph()); + pipeline.V(); + // If the multivalue index is not 1st, then it doesn't work - https://github.com/thinkaurelius/titan/issues/403 if (!includeZero) { - inlineHintPipeline.has(EffortReportModel.EFFORT, Compare.GREATER_THAN, 0); - inlineHintPipeline.has(WindupVertexFrame.TYPE_PROP, Text.CONTAINS, InlineHintModel.TYPE); + pipeline.has(EffortReportModel.EFFORT, Compare.GREATER_THAN, 0); + pipeline.has(WindupVertexFrame.TYPE_PROP, Text.CONTAINS, InlineHintModel.TYPE); } else { - inlineHintPipeline.has(WindupVertexFrame.TYPE_PROP, InlineHintModel.TYPE); + pipeline.has(WindupVertexFrame.TYPE_PROP, InlineHintModel.TYPE); } - - inlineHintPipeline.as("hint"); - inlineHintPipeline.out(InlineHintModel.FILE_MODEL); - inlineHintPipeline.in(ProjectModel.PROJECT_MODEL_TO_FILE); - inlineHintPipeline.filter(new PipeFunction() - { - @Override - public Boolean compute(Vertex argument) - { - return initialVertices.contains(argument); - } - }); - inlineHintPipeline.back("hint"); - - for (Vertex v : inlineHintPipeline) + pipeline.as("hint"); + pipeline.out(InlineHintModel.FILE_MODEL); + pipeline.in(ProjectModel.PROJECT_MODEL_TO_FILE); + pipeline.filter(new SetMembersFilter(initialVertices)); + pipeline.back("hint"); + + boolean checkTags = !includeTags.isEmpty() || !excludeTags.isEmpty(); + for (Vertex v : pipeline) { // only check tags if we have some passed in - if (!includeTags.isEmpty() || !excludeTags.isEmpty()) - { - InlineHintModel hintModel = frame(v); - if (!TagUtil.checkMatchingTags(hintModel.getTags(), includeTags, excludeTags)) - continue; + if (checkTags && !frame(v).matchesTags(includeTags, excludeTags)) + continue; - } accumulatorFunction.accumulate(v); } } diff --git a/reporting/api/src/main/java/org/jboss/windup/reporting/service/MapSumEffortAccumulatorFunction.java b/reporting/api/src/main/java/org/jboss/windup/reporting/service/MapSumEffortAccumulatorFunction.java new file mode 100644 index 0000000000..f624477f9c --- /dev/null +++ b/reporting/api/src/main/java/org/jboss/windup/reporting/service/MapSumEffortAccumulatorFunction.java @@ -0,0 +1,57 @@ +package org.jboss.windup.reporting.service; + + +import com.tinkerpop.blueprints.Vertex; +import java.util.HashMap; +import java.util.Map; + +/** + * This implementation holds a Map, and for each vertex, it increases the key + * that is determined from the vertex by supplied implementation of vertexToKey({@link Vertex}). + * + * @author Ondrej Zizka, zizka@seznam.cz + */ +abstract class MapSumEffortAccumulatorFunction implements EffortAccumulatorFunction +{ + private final Map results; + + /** + * Create a new instance of {@link MapSumEffortAccumulatorFunction} with no starting values. + */ + public MapSumEffortAccumulatorFunction() + { + this(new HashMap()); + } + + /** + * Creates a new instance of the accumulator with the given baseline values. + */ + public MapSumEffortAccumulatorFunction(Map results) + { + this.results = results; + } + + @Override + public void accumulate(Vertex effortReportVertex) + { + T key = vertexToKey(effortReportVertex); + if (!results.containsKey(key)) + results.put(key, 1); + else + results.put(key, results.get(key) + 1); + } + + /** + * Gets the current results. + */ + public Map getResults() + { + return results; + } + + /** + * This extracts the accumulator key from the provided {@link Vertex}. For example, this might be "Severity" + * or the number of effort points, depending upon what data is being accumulated. + */ + public abstract T vertexToKey(Vertex vertex); +} diff --git a/reporting/api/src/main/java/org/jboss/windup/reporting/service/SetMembersFilter.java b/reporting/api/src/main/java/org/jboss/windup/reporting/service/SetMembersFilter.java new file mode 100644 index 0000000000..8b67dace4d --- /dev/null +++ b/reporting/api/src/main/java/org/jboss/windup/reporting/service/SetMembersFilter.java @@ -0,0 +1,29 @@ +package org.jboss.windup.reporting.service; + +import com.tinkerpop.blueprints.Vertex; +import com.tinkerpop.pipes.PipeFunction; +import java.util.Set; + +/** + * Filters the pipeline based upon a {@link Set} of vertices. + * + * @author Ondrej Zizka, zizka@seznam.cz + */ +public final class SetMembersFilter implements PipeFunction +{ + private final Set initialVertices; + + /** + * Only items that match the provided set of vertices will be passed through the pipeline. + */ + public SetMembersFilter(Set initialVertices) + { + this.initialVertices = initialVertices; + } + + @Override + public Boolean compute(Vertex argument) + { + return initialVertices.contains(argument); + } +}