Skip to content

Count labels and relationship types #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.intellij.util.messages.MessageBus;
import com.neueda.jetbrains.plugin.graphdb.database.api.GraphDatabaseApi;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResult;
import com.neueda.jetbrains.plugin.graphdb.database.api.query.GraphQueryResultColumn;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.state.DataSourceApi;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.database.DatabaseManagerService;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.MetadataRetrieveEvent;
Expand All @@ -16,6 +17,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public class DataSourcesComponentMetadata implements ProjectComponent {

Expand All @@ -37,7 +39,7 @@ public Optional<DataSourceMetadata> getMetadata(DataSourceApi dataSource) {
case NEO4J_BOLT:
try {
DataSourceMetadata metadata = getNeo4jBoltMetadata(dataSource);
updateNeo4jBoltMetadata(dataSource, metadata);
updateNeo4jBoltMetadata(dataSource, (Neo4jBoltCypherDataSourceMetadata) metadata);
metadataRetrieveEvent.metadataRefreshSucceed(dataSource);
return Optional.of(metadata);
} catch (Exception exception) {
Expand All @@ -60,14 +62,24 @@ private DataSourceMetadata getNeo4jBoltMetadata(DataSourceApi dataSource) {
GraphQueryResult propertyKeysResult = db.execute("CALL db.propertyKeys()");
GraphQueryResult storedProceduresResult = db.execute("CALL dbms.procedures()");

metadata.addLabels(labelsQueryResult);
metadata.addRelationshipTypes(relationshipQueryResult);
List<String> listOfLabels = extractLabels(labelsQueryResult);
if (!listOfLabels.isEmpty()) {
GraphQueryResult labelCount = db.execute(queryLabelCount(listOfLabels));
metadata.addLabels(labelCount, listOfLabels);
}

List<String> listOfRelationshipTypes = extractRelationshipTypes(relationshipQueryResult);
if (!listOfRelationshipTypes.isEmpty()) {
GraphQueryResult relationshipTypeCountResult = db.execute(queryRelationshipTypeCount(listOfRelationshipTypes));
metadata.addRelationshipTypes(relationshipTypeCountResult, listOfRelationshipTypes);
}

metadata.addPropertyKeys(propertyKeysResult);
metadata.addStoredProcedures(storedProceduresResult);

boolean supportsUserFunctions = metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.STORED_PROCEDURES)
.stream()
.anyMatch((map) -> map.get("name").equals("dbms.functions"));
.stream()
.anyMatch((map) -> map.get("name").equals("dbms.functions"));

if (supportsUserFunctions) {
GraphQueryResult userFunctionsResult = db.execute("CALL dbms.functions()");
Expand All @@ -77,27 +89,59 @@ private DataSourceMetadata getNeo4jBoltMetadata(DataSourceApi dataSource) {
return metadata;
}

private void updateNeo4jBoltMetadata(DataSourceApi dataSource, DataSourceMetadata metadata) {
private List<String> extractRelationshipTypes(GraphQueryResult relationshipQueryResult) {
GraphQueryResultColumn column = relationshipQueryResult.getColumns().get(0);
return relationshipQueryResult.getRows()
.stream()
.map(row -> (String) row.getValue(column))
.collect(Collectors.toList());
}

private List<String> extractLabels(GraphQueryResult labelsQueryResult) {
GraphQueryResultColumn column = labelsQueryResult.getColumns().get(0);
return labelsQueryResult.getRows()
.stream()
.map(row -> (String) row.getValue(column))
.collect(Collectors.toList());
}

private String queryRelationshipTypeCount(List<String> relationshipTypes) {
return relationshipTypes
.stream()
.map(relationshipType -> "MATCH ()-[r:" + relationshipType + "]->() RETURN count(r)")
.collect(Collectors.joining(" UNION "));
}

private String queryLabelCount(List<String> labels) {
return labels
.stream()
.map(label -> "MATCH (n:" + label + ") RETURN count(n)")
.collect(Collectors.joining(" UNION "));
}

private void updateNeo4jBoltMetadata(DataSourceApi dataSource, Neo4jBoltCypherDataSourceMetadata metadata) {
// Refresh cypher metadata provider
cypherMetadataProviderService.wipeContainer(dataSource.getName());
CypherMetadataContainer container = cypherMetadataProviderService.getContainer(dataSource.getName());

metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.LABELS).stream()
.map((row) -> row.get("label"))
.forEach(container::addLabel);
metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.RELATIONSHIP_TYPES).stream()
.map((row) -> row.get("relationshipType"))
.forEach(container::addRelationshipType);
metadata.getLabels()
.stream()
.map(Neo4jLabelMetadata::getName)
.forEach(container::addLabel);
metadata.getRelationshipTypes()
.stream()
.map(Neo4jRelationshipTypeMetadata::getName)
.forEach(container::addRelationshipType);
metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.PROPERTY_KEYS).stream()
.map((row) -> row.get("propertyKey"))
.forEach(container::addPropertyKey);
.map((row) -> row.get("propertyKey"))
.forEach(container::addPropertyKey);
metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.STORED_PROCEDURES)
.forEach(row -> container.addProcedure(row.get("name"), row.get("signature"), row.get("description")));
.forEach(row -> container.addProcedure(row.get("name"), row.get("signature"), row.get("description")));

List<Map<String, String>> userFunctionMetadata = metadata.getMetadata(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS);
if (userFunctionMetadata != null) {
userFunctionMetadata
.forEach(row -> container.addUserFunction(row.get("name"), row.get("signature"), row.get("description")));
.forEach(row -> container.addUserFunction(row.get("name"), row.get("signature"), row.get("description")));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@

public class Neo4jBoltCypherDataSourceMetadata implements DataSourceMetadata {

public static final String LABELS = "labels";
public static final String RELATIONSHIP_TYPES = "relationships";
public static final String PROPERTY_KEYS = "propertyKeys";
public static final String STORED_PROCEDURES = "procedures";
public static final String USER_FUNCTIONS = "functions";

private Map<String, List<Map<String, String>>> dataReceiver = new HashMap<>();

private List<Neo4jLabelMetadata> labels = new ArrayList<>();
private List<Neo4jRelationshipTypeMetadata> relationshipTypes = new ArrayList<>();

@Override
public List<Map<String, String>> getMetadata(String metadataKey) {
return dataReceiver.get(metadataKey);
Expand All @@ -29,14 +30,6 @@ public boolean isMetadataExists(final String metadataKey) {
return dataReceiver.containsKey(metadataKey);
}

public void addLabels(GraphQueryResult labelsQueryResult) {
addDataSourceMetadata(LABELS, labelsQueryResult);
}

public void addRelationshipTypes(GraphQueryResult relationshipQueryResult) {
addDataSourceMetadata(RELATIONSHIP_TYPES, relationshipQueryResult);
}

public void addPropertyKeys(GraphQueryResult propertyKeysResult) {
addDataSourceMetadata(PROPERTY_KEYS, propertyKeysResult);
}
Expand Down Expand Up @@ -69,4 +62,36 @@ private void addDataSourceMetadata(String key, GraphQueryResult graphQueryResult
public void addDataSourceMetadata(String key, List<Map<String, String>> data) {
dataReceiver.put(key, data);
}

public void addLabels(GraphQueryResult labelCountResult, List<String> labelNames) {
GraphQueryResultColumn column = labelCountResult.getColumns().get(0);
for (int i = 0; i < labelCountResult.getRows().size(); i++) {
GraphQueryResultRow row = labelCountResult.getRows().get(i);
labels.add(new Neo4jLabelMetadata(labelNames.get(i), (Long) row.getValue(column)));
}
}

public void addLabel(Neo4jLabelMetadata labelMetadata) {
labels.add(labelMetadata);
}

public List<Neo4jLabelMetadata> getLabels() {
return labels;
}

public void addRelationshipTypes(GraphQueryResult relationshipTypeCountResult, List<String> relationshipTypeNames) {
GraphQueryResultColumn column = relationshipTypeCountResult.getColumns().get(0);
for (int i = 0; i < relationshipTypeCountResult.getRows().size(); i++) {
GraphQueryResultRow row = relationshipTypeCountResult.getRows().get(i);
relationshipTypes.add(new Neo4jRelationshipTypeMetadata(relationshipTypeNames.get(i), (Long) row.getValue(column)));
}
}

public void addRelationshipType(Neo4jRelationshipTypeMetadata relationshipTypeMetadata) {
relationshipTypes.add(relationshipTypeMetadata);
}

public List<Neo4jRelationshipTypeMetadata> getRelationshipTypes() {
return relationshipTypes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata;

public class Neo4jLabelMetadata {
private String name;
private Long count;

public Neo4jLabelMetadata(String name, Long count) {
this.name = name;
this.count = count;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getCount() {
return count;
}

public void setCount(Long count) {
this.count = count;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata;

public class Neo4jRelationshipTypeMetadata {
private String name;
private Long count;

public Neo4jRelationshipTypeMetadata(String name, Long count) {
this.name = name;
this.count = count;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getCount() {
return count;
}

public void setCount(Long count) {
this.count = count;
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata;

import com.intellij.ui.treeStructure.PatchedDefaultMutableTreeNode;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata.DataSourceMetadata;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata.DataSourcesComponentMetadata;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata.Neo4jBoltCypherDataSourceMetadata;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.state.DataSourceApi;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.LabelTreeNodeModel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.MetadataTreeNodeModel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.RelationshipTypeTreeNodeModel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.TreeNodeModelApi;
import com.neueda.jetbrains.plugin.graphdb.platform.GraphIcons;

import static com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.Neo4jTreeNodeType.*;

public class DataSourceMetadataUi {

private static final String RELATIONSHIP_TYPES_TITLE = "relationship types";
private static final String RELATIONSHIP_TYPES_TITLE = "relationship types (%s)";
private static final String PROPERTY_KEYS_TITLE = "property keys";
private static final String LABELS_TITLE = "labels";
private static final String LABELS_TITLE = "labels (%s)";
private static final String STORED_PROCEDURES_TITLE = "stored procedures";
private static final String USER_FUNCTIONS_TITLE = "user functions";

Expand All @@ -29,71 +30,77 @@ public boolean updateDataSourceMetadataUi(PatchedDefaultMutableTreeNode node, Da
switch (nodeDataSource.getDataSourceType()) {
case NEO4J_BOLT:
return dataSourcesComponent.getMetadata(nodeDataSource)
.map(dataSourceMetadata -> updateNeo4jBoltCypherMetadataUi(node, dataSourceMetadata))
.orElse(false);
.map(genericMetadata -> (Neo4jBoltCypherDataSourceMetadata) genericMetadata)
.map(neo4jMetadata -> updateNeo4jBoltCypherMetadataUi(node, neo4jMetadata))
.orElse(false);
default:
return false;
}
}

// ui
boolean updateNeo4jBoltCypherMetadataUi(PatchedDefaultMutableTreeNode dataSourceRootTreeNode,
DataSourceMetadata dataSourceMetadata) {
Neo4jBoltCypherDataSourceMetadata dataSourceMetadata) {
// Remove existing metadata from ui
dataSourceRootTreeNode.removeAllChildren();
TreeNodeModelApi model = (TreeNodeModelApi) dataSourceRootTreeNode.getUserObject();
DataSourceApi dataSourceApi = model.getDataSourceApi();

// Labels
int labelCount = dataSourceMetadata.getLabels().size();
PatchedDefaultMutableTreeNode labelsTreeNode = new PatchedDefaultMutableTreeNode(
new MetadataTreeNodeModel(LABELS, dataSourceApi, LABELS_TITLE, GraphIcons.Nodes.LABEL));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.LABELS)
.forEach((row) -> labelsTreeNode.add(of(new MetadataTreeNodeModel(LABEL, dataSourceApi, row.get("label")))));
new MetadataTreeNodeModel(LABELS, dataSourceApi, String.format(LABELS_TITLE, labelCount), GraphIcons.Nodes.LABEL));
dataSourceMetadata.getLabels()
.stream()
.map(label -> new LabelTreeNodeModel(LABEL, dataSourceApi, label.getName(), label.getCount()))
.forEach(labelModel -> labelsTreeNode.add(of(labelModel)));
dataSourceRootTreeNode.add(labelsTreeNode);

// RelTypes
int relationshipTypesCount = dataSourceMetadata.getRelationshipTypes().size();
String relationshipTypesName = String.format(RELATIONSHIP_TYPES_TITLE, relationshipTypesCount);
PatchedDefaultMutableTreeNode relationshipTypesTreeNode = new PatchedDefaultMutableTreeNode(
new MetadataTreeNodeModel(RELATIONSHIPS, dataSourceApi, RELATIONSHIP_TYPES_TITLE, GraphIcons.Nodes.RELATIONSHIP_TYPE));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.RELATIONSHIP_TYPES)
.forEach((row) -> relationshipTypesTreeNode.add(of(new MetadataTreeNodeModel(RELATIONSHIP, dataSourceApi, row.get("relationshipType")))));
new MetadataTreeNodeModel(RELATIONSHIPS, dataSourceApi, relationshipTypesName, GraphIcons.Nodes.RELATIONSHIP_TYPE));
dataSourceMetadata.getRelationshipTypes()
.stream()
.map(rel -> new RelationshipTypeTreeNodeModel(RELATIONSHIP, dataSourceApi, rel.getName(), rel.getCount()))
.forEach(relModel -> relationshipTypesTreeNode.add(of(relModel)));
dataSourceRootTreeNode.add(relationshipTypesTreeNode);

// Property Keys
PatchedDefaultMutableTreeNode propertyKeysTreeNode = new PatchedDefaultMutableTreeNode(
new MetadataTreeNodeModel(PROPERTY_KEYS, dataSourceApi, PROPERTY_KEYS_TITLE, GraphIcons.Nodes.PROPERTY_KEY));
new MetadataTreeNodeModel(PROPERTY_KEYS, dataSourceApi, PROPERTY_KEYS_TITLE, GraphIcons.Nodes.PROPERTY_KEY));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.PROPERTY_KEYS)
.forEach((row) -> propertyKeysTreeNode.add(of(new MetadataTreeNodeModel(PROPERTY_KEY, dataSourceApi, row.get("propertyKey")))));
.getMetadata(Neo4jBoltCypherDataSourceMetadata.PROPERTY_KEYS)
.forEach((row) -> propertyKeysTreeNode.add(of(new MetadataTreeNodeModel(PROPERTY_KEY, dataSourceApi, row.get("propertyKey")))));
dataSourceRootTreeNode.add(propertyKeysTreeNode);

// Stored procedures
PatchedDefaultMutableTreeNode storedProceduresTreeNode = new PatchedDefaultMutableTreeNode(
new MetadataTreeNodeModel(STORED_PROCEDURES, dataSourceApi, STORED_PROCEDURES_TITLE, GraphIcons.Nodes.STORED_PROCEDURE));
new MetadataTreeNodeModel(STORED_PROCEDURES, dataSourceApi, STORED_PROCEDURES_TITLE, GraphIcons.Nodes.STORED_PROCEDURE));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.STORED_PROCEDURES)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = of(new MetadataTreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new MetadataTreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
storedProceduresTreeNode.add(nameNode);
});
.getMetadata(Neo4jBoltCypherDataSourceMetadata.STORED_PROCEDURES)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = of(new MetadataTreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new MetadataTreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
storedProceduresTreeNode.add(nameNode);
});
dataSourceRootTreeNode.add(storedProceduresTreeNode);

// User Functions
if (dataSourceMetadata.isMetadataExists(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS)) {
PatchedDefaultMutableTreeNode userFunctionTreeNode = new PatchedDefaultMutableTreeNode(
new MetadataTreeNodeModel(USER_FUNCTIONS, dataSourceApi, USER_FUNCTIONS_TITLE, GraphIcons.Nodes.USER_FUNCTION));
new MetadataTreeNodeModel(USER_FUNCTIONS, dataSourceApi, USER_FUNCTIONS_TITLE, GraphIcons.Nodes.USER_FUNCTION));

dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = of(new MetadataTreeNodeModel(USER_FUNCTION, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new MetadataTreeNodeModel(USER_FUNCTION, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
userFunctionTreeNode.add(nameNode);
});
.getMetadata(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = of(new MetadataTreeNodeModel(USER_FUNCTION, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new MetadataTreeNodeModel(USER_FUNCTION, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
userFunctionTreeNode.add(nameNode);
});

dataSourceRootTreeNode.add(userFunctionTreeNode);
}
Expand Down
Loading