1515
1616import com .ibm .cldk .entities .AbstractGraphEdge ;
1717import com .ibm .cldk .entities .CallEdge ;
18- import com .ibm .cldk .entities .Callable ;
18+ import com .ibm .cldk .entities .CallableVertex ;
1919import com .ibm .cldk .entities .SystemDepEdge ;
2020import com .ibm .cldk .utils .AnalysisUtils ;
2121import com .ibm .cldk .utils .Log ;
4040import com .ibm .wala .util .graph .Graph ;
4141import com .ibm .wala .util .graph .GraphSlicer ;
4242import com .ibm .wala .util .graph .traverse .DFS ;
43+ import lombok .Data ;
44+ import lombok .EqualsAndHashCode ;
4345import org .apache .commons .io .output .NullOutputStream ;
44- import org .apache .commons .lang3 .tuple .Pair ;
4546import org .jgrapht .graph .DefaultDirectedGraph ;
4647import org .jgrapht .nio .json .JSONExporter ;
4748
4849import java .io .IOException ;
4950import java .io .PrintStream ;
50- import java .io .StringWriter ;
5151import java .util .*;
5252import java .util .function .BiFunction ;
5353import java .util .function .Supplier ;
54-
55- import static com .ibm .cldk .CodeAnalyzer .gson ;
56- import static com .ibm .cldk .utils .AnalysisUtils .*;
54+ import java .util .stream .Collectors ;
55+
56+ import static com .ibm .cldk .utils .AnalysisUtils .createAndPutNewCallableInSymbolTable ;
57+ import static com .ibm .cldk .utils .AnalysisUtils .getCallableFromSymbolTable ;
58+
59+
60+ @ Data
61+ abstract class Dependency {
62+ public CallableVertex source ;
63+ public CallableVertex target ;
64+ }
65+
66+ @ Data
67+ @ EqualsAndHashCode (callSuper = true )
68+ class SDGDependency extends Dependency {
69+ public String sourceKind ;
70+ public String destinationKind ;
71+ public String type ;
72+ public String weight ;
73+
74+ public SDGDependency (CallableVertex source , CallableVertex target , SystemDepEdge edge ) {
75+ super .source = source ;
76+ super .target = target ;
77+ this .sourceKind = edge .getSourceKind ();
78+ this .destinationKind = edge .getDestinationKind ();
79+ this .type = edge .getType ();
80+ this .weight = String .valueOf (edge .getWeight ());
81+ }
82+ }
83+
84+ @ Data
85+ @ EqualsAndHashCode (callSuper = true )
86+ class CallDependency extends Dependency {
87+ public String type ;
88+ public String weight ;
89+
90+ public CallDependency (CallableVertex source , CallableVertex target , AbstractGraphEdge edge ) {
91+ this .source = source ;
92+ this .target = target ;
93+ this .type = edge .toString ();
94+ this .weight = String .valueOf (edge .getWeight ());
95+ }
96+ }
5797
5898/**
5999 * The type Sdg 2 json.
@@ -66,18 +106,10 @@ public class SystemDependencyGraph {
66106 * @return the graph exporter
67107 */
68108
69-
70- private static JSONExporter <Pair <String , Callable >, AbstractGraphEdge > getGraphExporter () {
71- JSONExporter <Pair <String , Callable >, AbstractGraphEdge > exporter = new JSONExporter <>(
72- pair -> {
73- Map <String , String > vertex = new HashMap <>();
74- vertex .put ("class_interface_declarations" , pair .getLeft ());
75- vertex .put ("callable" , gson .toJson (pair .getRight ()));
76- return gson .toJson (vertex );
77- }
78- );
79- // exporter.setVertexAttributeProvider(v -> v.getRight().getAttributes());
109+ private static JSONExporter <CallableVertex , AbstractGraphEdge > getGraphExporter () {
110+ JSONExporter <CallableVertex , AbstractGraphEdge > exporter = new JSONExporter <>();
80111 exporter .setEdgeAttributeProvider (AbstractGraphEdge ::getAttributes );
112+ exporter .setVertexAttributeProvider (CallableVertex ::getAttributes );
81113 return exporter ;
82114 }
83115
@@ -90,12 +122,12 @@ private static JSONExporter<Pair<String, Callable>, AbstractGraphEdge> getGraphE
90122 * @param edgeLabels
91123 * @return
92124 */
93- private static org .jgrapht .Graph <Pair < String , Callable > , AbstractGraphEdge > buildGraph (
125+ private static org .jgrapht .Graph <CallableVertex , AbstractGraphEdge > buildGraph (
94126 Supplier <Iterator <Statement >> entryPoints ,
95127 Graph <Statement > sdg , CallGraph callGraph ,
96128 BiFunction <Statement , Statement , String > edgeLabels ) {
97129
98- org .jgrapht .Graph <Pair < String , Callable > , AbstractGraphEdge > graph = new DefaultDirectedGraph <>(
130+ org .jgrapht .Graph <CallableVertex , AbstractGraphEdge > graph = new DefaultDirectedGraph <>(
99131 AbstractGraphEdge .class );
100132
101133 // We'll use forward and backward search on the DFS to identify which CFG nodes
@@ -130,21 +162,22 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
130162 && !p .getNode ().getMethod ().equals (s .getNode ().getMethod ())) {
131163
132164 // Add the source nodes to the graph as vertices
133- Pair <String , Callable > source = Optional .ofNullable (getCallableFromSymbolTable (p .getNode ().getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (p .getNode ().getMethod ()));
134- graph .addVertex (source );
135-
165+ Map <String , String > source = Optional .ofNullable (getCallableFromSymbolTable (p .getNode ().getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (p .getNode ().getMethod ()));
136166 // Add the target nodes to the graph as vertices
137- Pair <String , Callable > target = Optional .ofNullable (getCallableFromSymbolTable (s .getNode ().getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (s .getNode ().getMethod ()));
138- graph .addVertex (target );
139-
140- String edgeType = edgeLabels .apply (p , s );
141- SystemDepEdge graphEdge = new SystemDepEdge (p , s , edgeType );
142- SystemDepEdge cgEdge = (SystemDepEdge ) graph .getEdge (source , target );
143- if (source .getRight () != null && target .getRight () != null ) {
167+ Map <String , String > target = Optional .ofNullable (getCallableFromSymbolTable (s .getNode ().getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (s .getNode ().getMethod ()));
168+
169+ if (source != null && target != null ) {
170+ CallableVertex source_vertex = new CallableVertex (source );
171+ CallableVertex target_vertex = new CallableVertex (target );
172+ graph .addVertex (source_vertex );
173+ graph .addVertex (target_vertex );
174+ String edgeType = edgeLabels .apply (p , s );
175+ SystemDepEdge graphEdge = new SystemDepEdge (p , s , edgeType );
176+ SystemDepEdge cgEdge = (SystemDepEdge ) graph .getEdge (source_vertex , target_vertex );
144177 if (cgEdge == null || !cgEdge .equals (graphEdge )) {
145178 graph .addEdge (
146- source ,
147- target ,
179+ source_vertex ,
180+ target_vertex ,
148181 graphEdge );
149182 } else {
150183 graphEdge .incrementWeight ();
@@ -163,21 +196,22 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
163196 .forEach (o -> {
164197
165198 // Add the source nodes to the graph as vertices
166- Pair <String , Callable > source = Optional .ofNullable (getCallableFromSymbolTable (p .getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (p .getMethod ()));
167- graph . addVertex (source );
199+ Map <String , String > source = Optional .ofNullable (getCallableFromSymbolTable (p .getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (p .getMethod ()));
200+ CallableVertex source_vertex = new CallableVertex (source );
168201
169202 // Add the target nodes to the graph as vertices
170- Pair <String , Callable > target = Optional .ofNullable (getCallableFromSymbolTable (o .getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (o .getMethod ()));
171- graph .addVertex (target );
172-
173- if (!source .equals (target ) && source .getRight () != null && target .getRight () != null ) {
203+ Map <String , String > target = Optional .ofNullable (getCallableFromSymbolTable (o .getMethod ())).orElseGet (() -> createAndPutNewCallableInSymbolTable (o .getMethod ()));
204+ CallableVertex target_vertex = new CallableVertex (target );
174205
206+ if (!source .equals (target ) && target != null ) {
175207 // Get the edge between the source and the target
176- AbstractGraphEdge cgEdge = graph .getEdge (source , target );
208+ graph .addVertex (source_vertex );
209+ graph .addVertex (target_vertex );
210+ AbstractGraphEdge cgEdge = graph .getEdge (source_vertex , target_vertex );
177211 if (cgEdge instanceof CallEdge ) {
178212 ((CallEdge ) cgEdge ).incrementWeight ();
179213 } else {
180- graph .addEdge (source , target , new CallEdge ());
214+ graph .addEdge (source_vertex , target_vertex , new CallEdge ());
181215 }
182216 }
183217 });
@@ -192,15 +226,15 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
192226 *
193227 * @param input the input
194228 * @param dependencies the dependencies
195- * @param build The build options
229+ * @param build The build options
196230 * @return A List of triples containing the source, destination, and edge type
197231 * @throws IOException the io exception
198232 * @throws ClassHierarchyException the class hierarchy exception
199233 * @throws IllegalArgumentException the illegal argument exception
200234 * @throws CallGraphBuilderCancelException the call graph builder cancel
201235 * exception
202236 */
203- public static String construct (
237+ public static List < Dependency > construct (
204238 String input , String dependencies , String build )
205239 throws IOException , ClassHierarchyException , IllegalArgumentException , CallGraphBuilderCancelException {
206240
@@ -243,12 +277,7 @@ public static String construct(
243277 + Math .ceil ((double ) (System .currentTimeMillis () - start_time ) / 1000 ) + " seconds." );
244278
245279 // set cyclomatic complexity for callables in the symbol table
246- callGraph .forEach (cgNode -> {
247- Callable callable = getCallableFromSymbolTable (cgNode .getMethod ()).getRight ();
248- if (callable != null ) {
249- callable .setCyclomaticComplexity (getCyclomaticComplexity (cgNode .getIR ()));
250- }
251- });
280+ AnalysisUtils .setCyclomaticComplexity (callGraph );
252281
253282 // Build SDG graph
254283 Log .info ("Building System Dependency Graph." );
@@ -266,22 +295,31 @@ public static String construct(
266295 .getDeclaringClass ()
267296 .getClassLoader ()
268297 .getReference ()
269- .equals (ClassLoaderReference .Application )));
298+ .equals (ClassLoaderReference .Application ))
299+ );
270300
271301 // A supplier to get entries
272302 Supplier <Iterator <Statement >> sdgEntryPointsSupplier = () -> callGraph .getEntrypointNodes ().stream ()
273303 .map (n -> (Statement ) new MethodEntryStatement (n )).iterator ();
274304
275- org .jgrapht .Graph <Pair < String , Callable > , AbstractGraphEdge > sdgGraph = buildGraph (
305+ org .jgrapht .Graph <CallableVertex , AbstractGraphEdge > sdgGraph = buildGraph (
276306 sdgEntryPointsSupplier ,
277307 prunedGraph , callGraph ,
278- (p , s ) -> String .valueOf (sdg .getEdgeLabels (p , s ).iterator ().next ()));
279-
280- JSONExporter <Pair <String , Callable >, AbstractGraphEdge > graphExporter = getGraphExporter ();
308+ (p , s ) -> String .valueOf (sdg .getEdgeLabels (p , s ).iterator ().next ())
309+ );
281310
282- StringWriter sdgWriter = new StringWriter ();
283- graphExporter .exportGraph (sdgGraph , sdgWriter );
311+ List <Dependency > edges = sdgGraph .edgeSet ().stream ()
312+ .map (abstractGraphEdge -> {
313+ CallableVertex source = sdgGraph .getEdgeSource (abstractGraphEdge );
314+ CallableVertex target = sdgGraph .getEdgeTarget (abstractGraphEdge );
315+ if (abstractGraphEdge instanceof CallEdge ) {
316+ return new CallDependency (source , target , abstractGraphEdge );
317+ } else {
318+ return new SDGDependency (source , target , (SystemDepEdge ) abstractGraphEdge );
319+ }
320+ })
321+ .collect (Collectors .toList ());
284322
285- return sdgWriter . toString () ;
323+ return edges ;
286324 }
287325}
0 commit comments