///usr/bin/env jbang "$0" "$@" ; exit $? //JAVA 17 //DEPS org.neo4j:neo4j:5.24.1 import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import org.neo4j.dbms.api.DatabaseManagementServiceBuilder; class GoCyclingWithNeo4j { static class A { static String s = "Wurst"; static int lb = B.s.length(); } static class B { static int la = A.s.length(); static String s = "Salat"; } public static void main(String... a) throws IOException { if (a.length != 1) { System.err.println(""" This program will crash, run with ``` jbang -R-Xlog:class+resolve=trace:file=jvm.log ``` to log the resolving of classes. After that, run ``` jbang GoCyclingWithNeo4j.java jvm.log ``` and see the circle between static inner classes A and B. """); new B(); } var parameters = new ArrayList>(); try (var reader = new BufferedReader(Files.newBufferedReader(Path.of(a[0]))); var lines = reader.lines() ) { var cnt = new AtomicLong(0); lines.forEach(l -> { var columns = l.split(" "); parameters.add(Map.of("source", columns[1], "target", columns[2], "at", columns.length >= 4 ? columns[3] : "n/a", "idx", cnt.incrementAndGet())); }); } var dbms = new DatabaseManagementServiceBuilder(Files.createTempDirectory("neo4j")) .build(); var db = dbms.database("neo4j"); // Create graph db.executeTransactionally(""" UNWIND $parameters AS r MERGE (f:Class {name: r.source}) MERGE (t:Class {name: r.target}) CREATE (f)-[:RESOLVED {at: r.at, idx: r.idx}]->(t) """, Map.of("parameters", parameters)); // Query graph var candidates = db.executeTransactionally(""" MATCH (start:Class WHERE start.name <> 'resolve')-[r:RESOLVED]->(end:Class) WHERE EXISTS { (start)((a)-[:RESOLVED]-(b) WHERE (a = start AND b = end) OR (a = end AND b = start) ){3,}(end) } AND start <> end RETURN start.name AS source, end.name AS target, r.at AS at ORDER BY r.idx """, Map.of(), rows -> rows.stream().toList()); candidates.forEach(System.out::println); dbms.shutdown(); } }