Skip to content

Commit e729852

Browse files
Refactor metadata logic (#41)
* Add numbers to procedures and functions titles * Store underlying result as record, not as map * Use the underlying Record value * Create metadata class for indexes
1 parent 8dafd68 commit e729852

File tree

20 files changed

+271
-256
lines changed

20 files changed

+271
-256
lines changed

database/api/src/main/java/com/albertoventurini/graphdbplugin/database/api/query/GraphQueryResultRow.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.albertoventurini.graphdbplugin.database.api.data.GraphRelationship;
1111

1212
import java.util.List;
13+
import java.util.Optional;
1314

1415
public interface GraphQueryResultRow {
1516

@@ -20,12 +21,4 @@ public interface GraphQueryResultRow {
2021
List<GraphNode> getNodes();
2122

2223
List<GraphRelationship> getRelationships();
23-
24-
default <T> T getValue(final String columnName, final Class<T> clazz) {
25-
final Object value = getValue(columnName);
26-
if (clazz.isInstance(value)) {
27-
return clazz.cast(value);
28-
}
29-
throw new ClassCastException("Unable to cast value to " + clazz.getName() + " at column " + columnName);
30-
}
3124
}

database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/Neo4jBoltBuffer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResultColumn;
1414
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResultRow;
1515
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltQueryNotification;
16-
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltQueryPlan;
17-
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltQueryResultColumn;
18-
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltQueryResultRow;
16+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryPlan;
17+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryResultColumn;
18+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.query.Neo4jBoltQueryResultRow;
1919
import org.neo4j.driver.Record;
2020
import org.neo4j.driver.summary.InputPosition;
2121
import org.neo4j.driver.summary.Plan;
@@ -53,8 +53,8 @@ public void addResultSummary(ResultSummary resultSummary) {
5353
this.resultSummary = resultSummary;
5454
}
5555

56-
public void addRow(final Map<String, Object> row) {
57-
this.rows.add(new Neo4jBoltQueryResultRow(row));
56+
public void addRow(final Record record) {
57+
this.rows.add(new Neo4jBoltQueryResultRow(record));
5858
}
5959

6060
public List<GraphQueryResultColumn> getColumns() {

database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/Neo4jBoltDatabase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public GraphQueryResult execute(String query) {
7878
@Override
7979
public GraphQueryResult execute(String query, Map<String, Object> statementParameters) {
8080
try {
81-
// TODO: driver can be instantiated when this object is constructed. No need to create a new driver every time a query is executed.
81+
// TODO: driver might be instantiated when this object is constructed. No need to create a new driver every time a query is executed.
8282
Driver driver = GraphDatabase.driver(url, auth);
8383
try {
8484
try (Session session = driver.session(dbConfig)) {
@@ -91,7 +91,7 @@ public GraphQueryResult execute(String query, Map<String, Object> statementParam
9191

9292
for (Record record : statementResult.list()) {
9393
// Add row
94-
buffer.addRow(record.asMap());
94+
buffer.addRow(record);
9595
}
9696
buffer.addResultSummary(statementResult.consume());
9797
long endTime = System.currentTimeMillis();

database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/data/Neo4jBoltQueryResultRow.java

Lines changed: 0 additions & 108 deletions
This file was deleted.

database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/data/Neo4jBoltQueryPlan.java renamed to database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/query/Neo4jBoltQueryPlan.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* by Neueda Technologies, Ltd.
55
* Modified by Alberto Venturini, 2022
66
*/
7-
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.data;
7+
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.query;
88

99
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryPlan;
1010

database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/data/Neo4jBoltQueryResultColumn.java renamed to database/neo4j/src/main/java/com/albertoventurini/graphdbplugin/database/neo4j/bolt/query/Neo4jBoltQueryResultColumn.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* by Neueda Technologies, Ltd.
55
* Modified by Alberto Venturini, 2022
66
*/
7-
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.data;
7+
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.query;
88

99
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResultColumn;
1010

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Copied and adapted from plugin
3+
* <a href="https://github.com/neueda/jetbrains-plugin-graph-database-support">Graph Database Support</a>
4+
* by Neueda Technologies, Ltd.
5+
* Modified by Alberto Venturini, 2022
6+
*/
7+
package com.albertoventurini.graphdbplugin.database.neo4j.bolt.query;
8+
9+
import com.albertoventurini.graphdbplugin.database.api.data.GraphNode;
10+
import com.albertoventurini.graphdbplugin.database.api.data.GraphRelationship;
11+
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResultColumn;
12+
import com.albertoventurini.graphdbplugin.database.api.query.GraphQueryResultRow;
13+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltNode;
14+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltPath;
15+
import com.albertoventurini.graphdbplugin.database.neo4j.bolt.data.Neo4jBoltRelationship;
16+
import org.neo4j.driver.Record;
17+
import org.neo4j.driver.Value;
18+
import org.neo4j.driver.internal.util.Iterables;
19+
import org.neo4j.driver.types.Node;
20+
import org.neo4j.driver.types.Path;
21+
import org.neo4j.driver.types.Relationship;
22+
23+
import java.util.ArrayList;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.stream.Collectors;
28+
29+
public class Neo4jBoltQueryResultRow implements GraphQueryResultRow {
30+
31+
private final Record record;
32+
private final List<GraphNode> nodes;
33+
private final List<GraphRelationship> relationships;
34+
35+
public Neo4jBoltQueryResultRow(final Record record) {
36+
this.record = record;
37+
this.nodes = new ArrayList<>();
38+
this.relationships = new ArrayList<>();
39+
40+
record.asMap().forEach((k, v) -> {
41+
collectNodesAndRelationships(k);
42+
collectNodesAndRelationships(v);
43+
});
44+
}
45+
46+
public Value getValue(final String columnName) {
47+
return record.get(columnName);
48+
}
49+
50+
@Override
51+
public Object getValue(GraphQueryResultColumn column) {
52+
return record.get(column.getName()).asObject();
53+
}
54+
55+
@Override
56+
public List<GraphNode> getNodes() {
57+
return nodes;
58+
}
59+
60+
@Override
61+
public List<GraphRelationship> getRelationships() {
62+
return relationships;
63+
}
64+
65+
@SuppressWarnings("unchecked")
66+
private void collectNodesAndRelationships(Object o) {
67+
if (o instanceof Map<?,?> map) {
68+
map.forEach((key, value) -> {
69+
collectNodesAndRelationships(key);
70+
collectNodesAndRelationships(value);
71+
});
72+
}
73+
if (o instanceof List<?> list) {
74+
list.forEach(this::collectNodesAndRelationships);
75+
}
76+
if (o instanceof Node node) {
77+
nodes.add(new Neo4jBoltNode(node));
78+
}
79+
if (o instanceof Relationship rel) {
80+
relationships.add(new Neo4jBoltRelationship(rel));
81+
}
82+
if (o instanceof Path path) {
83+
path.nodes().forEach(n -> nodes.add(new Neo4jBoltNode(n)));
84+
path.relationships().forEach(r -> relationships.add(new Neo4jBoltRelationship(r)));
85+
}
86+
}
87+
}

ui/jetbrains/src/main/java/com/albertoventurini/graphdbplugin/jetbrains/component/datasource/metadata/DataSourceMetadata.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ public interface DataSourceMetadata {
1717

1818
List<Neo4jProcedureMetadata> getProcedures();
1919

20+
List<Neo4jIndexMetadata> getIndexes();
21+
2022
boolean isMetadataExists(String metadataKey);
2123
}

ui/jetbrains/src/main/java/com/albertoventurini/graphdbplugin/jetbrains/component/datasource/metadata/DataSourcesComponentMetadata.java

Lines changed: 3 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,17 @@
3333

3434
public class DataSourcesComponentMetadata {
3535

36-
private static final Logger LOG = Logger.getInstance(DataSourcesComponentMetadata.class);
37-
38-
private final Map<DataSourceType, Function<DataSourceApi, DataSourceMetadata>> handlers = new HashMap<>();
36+
private final Map<DataSourceType, MetadataBuilder> handlers = new HashMap<>();
3937
private CypherMetadataProviderService cypherMetadataProviderService;
4038
private ExecutorService executorService;
41-
private DatabaseManagerService databaseManager;
4239
private MessageBus messageBus;
4340

4441
public DataSourcesComponentMetadata(final Project project) {
4542
messageBus = project.getMessageBus();
46-
databaseManager = ApplicationManager.getApplication().getService(DatabaseManagerService.class);
4743
cypherMetadataProviderService = project.getService(CypherMetadataProviderService.class);
4844
executorService = ApplicationManager.getApplication().getService(ExecutorService.class);
4945

50-
handlers.put(DataSourceType.NEO4J_BOLT, this::getNeo4jBoltMetadata);
46+
handlers.put(DataSourceType.NEO4J_BOLT, new Neo4jMetadataBuilder());
5147
}
5248

5349
public CompletableFuture<Optional<DataSourceMetadata>> getMetadata(DataSourceApi dataSource) {
@@ -59,7 +55,7 @@ public CompletableFuture<Optional<DataSourceMetadata>> getMetadata(DataSourceApi
5955
DataSourceType sourceType = dataSource.getDataSourceType();
6056
if (handlers.containsKey(sourceType)) {
6157
executorService.runInBackground(
62-
() -> handlers.get(sourceType).apply(dataSource),
58+
() -> handlers.get(sourceType).buildMetadata(dataSource),
6359
(metadata) -> {
6460
updateNeo4jBoltMetadata(dataSource, (Neo4jBoltCypherDataSourceMetadata) metadata);
6561
metadataRetrieveEvent.metadataRefreshSucceed(dataSource, metadata);
@@ -77,76 +73,6 @@ public CompletableFuture<Optional<DataSourceMetadata>> getMetadata(DataSourceApi
7773
return future;
7874
}
7975

80-
private DataSourceMetadata getNeo4jBoltMetadata(DataSourceApi dataSource) {
81-
GraphDatabaseApi db = databaseManager.getDatabaseFor(dataSource);
82-
Neo4jBoltCypherDataSourceMetadata metadata = new Neo4jBoltCypherDataSourceMetadata();
83-
84-
try {
85-
GraphQueryResult indexesResult = db.execute("SHOW INDEXES");
86-
GraphQueryResult constraintsResult = db.execute("SHOW CONSTRAINTS");
87-
GraphQueryResult storedProceduresResult = db.execute("SHOW PROCEDURES YIELD name, signature, description");
88-
89-
metadata.addIndexes(indexesResult);
90-
metadata.addConstraints(constraintsResult);
91-
metadata.addProcedures(storedProceduresResult);
92-
} catch (Exception e) {
93-
LOG.warn("Unable to load indexes, constraints and procedures from the current database. Please upgrade to Neo4j 4 or 5 to fix this.");
94-
}
95-
96-
GraphQueryResult labelsQueryResult = db.execute("CALL db.labels()");
97-
GraphQueryResult relationshipQueryResult = db.execute("CALL db.relationshipTypes()");
98-
GraphQueryResult propertyKeysResult = db.execute("CALL db.propertyKeys()");
99-
100-
List<String> listOfLabels = extractLabels(labelsQueryResult);
101-
if (!listOfLabels.isEmpty()) {
102-
GraphQueryResult labelCount = db.execute(queryLabelCount(listOfLabels));
103-
metadata.addLabels(labelCount, listOfLabels);
104-
}
105-
106-
List<String> listOfRelationshipTypes = extractRelationshipTypes(relationshipQueryResult);
107-
if (!listOfRelationshipTypes.isEmpty()) {
108-
GraphQueryResult relationshipTypeCountResult = db.execute(queryRelationshipTypeCount(listOfRelationshipTypes));
109-
metadata.addRelationshipTypes(relationshipTypeCountResult, listOfRelationshipTypes);
110-
}
111-
112-
metadata.addPropertyKeys(propertyKeysResult);
113-
114-
final GraphQueryResult functionsResult = db.execute("SHOW FUNCTIONS YIELD name, signature, description");
115-
metadata.addFunctions(functionsResult);
116-
117-
return metadata;
118-
}
119-
120-
private List<String> extractRelationshipTypes(GraphQueryResult relationshipQueryResult) {
121-
GraphQueryResultColumn column = relationshipQueryResult.getColumns().get(0);
122-
return relationshipQueryResult.getRows()
123-
.stream()
124-
.map(row -> (String) row.getValue(column))
125-
.collect(toList());
126-
}
127-
128-
private List<String> extractLabels(GraphQueryResult labelsQueryResult) {
129-
GraphQueryResultColumn column = labelsQueryResult.getColumns().get(0);
130-
return labelsQueryResult.getRows()
131-
.stream()
132-
.map(row -> (String) row.getValue(column))
133-
.collect(toList());
134-
}
135-
136-
private String queryRelationshipTypeCount(List<String> relationshipTypes) {
137-
return relationshipTypes
138-
.stream()
139-
.map(relationshipType -> "MATCH ()-[r:`" + relationshipType + "`]->() RETURN count(r)")
140-
.collect(Collectors.joining(" UNION ALL "));
141-
}
142-
143-
private String queryLabelCount(List<String> labels) {
144-
return labels
145-
.stream()
146-
.map(label -> "MATCH (n:`" + label + "`) RETURN count(n)")
147-
.collect(Collectors.joining(" UNION ALL "));
148-
}
149-
15076
private void updateNeo4jBoltMetadata(DataSourceApi dataSource, Neo4jBoltCypherDataSourceMetadata metadata) {
15177
// Refresh cypher metadata provider
15278
cypherMetadataProviderService.wipeContainer(dataSource.getName());

0 commit comments

Comments
 (0)