Skip to content

Commit e43de9c

Browse files
committed
Decouple loading the JUngraph dependency from loading the SVG class.
Prevents a `NoClassDefFoundError` when referencing a `CommunityModules` release that does *not* include its dependencies (i.e., the version without the `-deps.jar` suffix). [Refactor] Signed-off-by: Markus Alexander Kuppe <[email protected]>
1 parent 1531742 commit e43de9c

File tree

1 file changed

+62
-68
lines changed

1 file changed

+62
-68
lines changed

modules/tlc2/overrides/SVG.java

Lines changed: 62 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,6 @@
2828
import java.util.Map;
2929
import java.util.stream.Collectors;
3030

31-
import org.jgrapht.Graph;
32-
import org.jgrapht.graph.DefaultGraphType;
33-
import org.jgrapht.graph.builder.GraphTypeBuilder;
34-
import org.jgrapht.util.SupplierUtil;
35-
import org.jungrapht.visualization.layout.algorithms.EiglspergerLayoutAlgorithm;
36-
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
37-
import org.jungrapht.visualization.layout.algorithms.SugiyamaLayoutAlgorithm;
38-
import org.jungrapht.visualization.layout.algorithms.TreeLayoutAlgorithm;
39-
import org.jungrapht.visualization.layout.algorithms.sugiyama.Layering;
40-
import org.jungrapht.visualization.layout.model.LayoutModel;
41-
import org.jungrapht.visualization.layout.model.Point;
42-
import org.jungrapht.visualization.layout.model.Rectangle;
43-
4431
import tlc2.tool.EvalControl;
4532
import tlc2.value.impl.FcnLambdaValue;
4633
import tlc2.value.impl.FcnRcdValue;
@@ -180,65 +167,72 @@ public static Value directedMultiGraph(final Value n, final Value e, final Value
180167
final SetEnumValue edges = (SetEnumValue) e.toSetEnum();
181168
final RecordValue opts = (RecordValue) o.toRcd();
182169

183-
// https://jgrapht.org/guide/UserOverview#graph-structures
184-
final Graph<Value, Integer> graph = GraphTypeBuilder
185-
.<Value, Integer>forGraphType(DefaultGraphType.directedMultigraph())
186-
.edgeSupplier(SupplierUtil.createIntegerSupplier()).allowingSelfLoops(false).buildGraph();
187-
188-
ValueVec elems = nodes.elems;
189-
for (int i = 0; i < elems.size(); i++) {
190-
graph.addVertex(elems.elementAt(i));
191-
}
192-
elems = edges.elems;
193-
for (int i = 0; i < elems.size(); i++) {
194-
TupleValue tuple = (TupleValue) elems.elementAt(i);
195-
graph.addEdge(tuple.elems[0], tuple.elems[1]);
196-
}
197-
198-
// Layout
199-
final IntValue viewH = (IntValue) opts.apply(new StringValue("view_width"), EvalControl.Clear);
200-
final IntValue viewW = (IntValue) opts.apply(new StringValue("view_height"), EvalControl.Clear);
201-
final LayoutModel<Value> layoutModel = LayoutModel.<Value>builder().size(viewW.val, viewH.val).graph(graph)
202-
.build();
203-
204-
// Algorithm
205-
final StringValue algo = (StringValue) opts.apply(new StringValue("algo"), EvalControl.Clear);
206-
getAlgo(algo.val.toString(), opts).visit(layoutModel);
207-
208-
// Get the node's coordinates from the algorithm.
209-
final Map <Value, Point> locations = layoutModel.getLocations();
210-
211-
// convert to TLC values.
212-
return new FcnRcdValue(locations.entrySet().stream()
213-
.collect(Collectors.toMap(entry -> entry.getKey(), entry -> point2Value(entry.getValue()))));
170+
return JUngraph.toGraph(nodes, edges, opts);
214171
}
172+
173+
private static class JUngraph {
174+
175+
private static Value toGraph(final SetEnumValue nodes, final SetEnumValue edges, final RecordValue opts) {
176+
// https://jgrapht.org/guide/UserOverview#graph-structures
177+
final org.jgrapht.Graph<Value, Integer> graph = org.jgrapht.graph.builder.GraphTypeBuilder
178+
.<Value, Integer>forGraphType(org.jgrapht.graph.DefaultGraphType.directedMultigraph())
179+
.edgeSupplier(org.jgrapht.util.SupplierUtil.createIntegerSupplier()).allowingSelfLoops(false).buildGraph();
180+
181+
ValueVec elems = nodes.elems;
182+
for (int i = 0; i < elems.size(); i++) {
183+
graph.addVertex(elems.elementAt(i));
184+
}
185+
elems = edges.elems;
186+
for (int i = 0; i < elems.size(); i++) {
187+
TupleValue tuple = (TupleValue) elems.elementAt(i);
188+
graph.addEdge(tuple.elems[0], tuple.elems[1]);
189+
}
190+
191+
// Layout
192+
final IntValue viewH = (IntValue) opts.apply(new StringValue("view_width"), EvalControl.Clear);
193+
final IntValue viewW = (IntValue) opts.apply(new StringValue("view_height"), EvalControl.Clear);
194+
final org.jungrapht.visualization.layout.model.LayoutModel<Value> layoutModel = org.jungrapht.visualization.layout.model.LayoutModel.<Value>builder().size(viewW.val, viewH.val).graph(graph)
195+
.build();
215196

216-
private static Value point2Value(final Point p) {
217-
final int x = ((Double) p.x).intValue();
218-
final int y = ((Double) p.y).intValue();
219-
return new RecordValue(new UniqueString[] { UniqueString.of("x"), UniqueString.of("y") },
220-
new Value[] { IntValue.gen(x), IntValue.gen(y) }, false);
221-
}
197+
// Algorithm
198+
final StringValue algo = (StringValue) opts.apply(new StringValue("algo"), EvalControl.Clear);
199+
JUngraph.getAlgo(algo.val.toString(), opts).visit(layoutModel);
200+
201+
// Get the node's coordinates from the algorithm.
202+
final Map <Value, org.jungrapht.visualization.layout.model.Point> locations = layoutModel.getLocations();
203+
204+
// convert to TLC values.
205+
return new FcnRcdValue(locations.entrySet().stream()
206+
.collect(Collectors.toMap(entry -> entry.getKey(), entry -> JUngraph.point2Value(entry.getValue()))));
207+
}
222208

223-
private static LayoutAlgorithm<Value> getAlgo(final String algo, final RecordValue opts) {
224-
final IntValue nodeH = (IntValue) opts.apply(new StringValue("node_width"), EvalControl.Clear);
225-
final IntValue nodeW = (IntValue) opts.apply(new StringValue("node_height"), EvalControl.Clear);
209+
private static Value point2Value(final org.jungrapht.visualization.layout.model.Point p) {
210+
final int x = ((Double) p.x).intValue();
211+
final int y = ((Double) p.y).intValue();
212+
return new RecordValue(new UniqueString[] { UniqueString.of("x"), UniqueString.of("y") },
213+
new Value[] { IntValue.gen(x), IntValue.gen(y) }, false);
214+
}
226215

227-
switch (algo) {
228-
case "Sugiyama":
229-
// https://github.com/tomnelson/jungrapht-visualization/blob/afd155bf0246e5185f054ba1429bbcfbd429292a/jungrapht-layout/src/main/java/org/jungrapht/visualization/layout/algorithms/sugiyama/Layering.java#L4-L7
230-
String l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString();
231-
return SugiyamaLayoutAlgorithm.<Value, Integer>edgeAwareBuilder()
232-
.layering(Layering.valueOf(l)).vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false)
233-
.build();
234-
case "Eiglsperger":
235-
l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString();
236-
return EiglspergerLayoutAlgorithm.<Value, Integer>edgeAwareBuilder()
237-
.layering(Layering.valueOf(l)).vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false)
238-
.build();
239-
default:
240-
return TreeLayoutAlgorithm.<Value>builder()
241-
.vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).build();
216+
private static org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm<Value> getAlgo(final String algo, final RecordValue opts) {
217+
final IntValue nodeH = (IntValue) opts.apply(new StringValue("node_width"), EvalControl.Clear);
218+
final IntValue nodeW = (IntValue) opts.apply(new StringValue("node_height"), EvalControl.Clear);
219+
220+
switch (algo) {
221+
case "Sugiyama":
222+
// https://github.com/tomnelson/jungrapht-visualization/blob/afd155bf0246e5185f054ba1429bbcfbd429292a/jungrapht-layout/src/main/java/org/jungrapht/visualization/layout/algorithms/sugiyama/Layering.java#L4-L7
223+
String l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString();
224+
return org.jungrapht.visualization.layout.algorithms.SugiyamaLayoutAlgorithm.<Value, Integer>edgeAwareBuilder()
225+
.layering(org.jungrapht.visualization.layout.algorithms.sugiyama.Layering.valueOf(l)).vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false)
226+
.build();
227+
case "Eiglsperger":
228+
l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString();
229+
return org.jungrapht.visualization.layout.algorithms.EiglspergerLayoutAlgorithm.<Value, Integer>edgeAwareBuilder()
230+
.layering(org.jungrapht.visualization.layout.algorithms.sugiyama.Layering.valueOf(l)).vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false)
231+
.build();
232+
default:
233+
return org.jungrapht.visualization.layout.algorithms.TreeLayoutAlgorithm.<Value>builder()
234+
.vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).build();
235+
}
242236
}
243237
}
244238

0 commit comments

Comments
 (0)