Skip to content

Provide query example for metadata using context menu #19

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 10 commits into from
Jan 12, 2017
Merged
Show file tree
Hide file tree
Changes from 7 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 @@ -3,12 +3,18 @@
import com.intellij.openapi.editor.Editor;
import org.jetbrains.annotations.NotNull;

import java.util.Optional;

public class ExecuteQueryPayload {

private final String content;

private final Editor editor;

public ExecuteQueryPayload(String content) {
this.content = content;
this.editor = null;
}

public ExecuteQueryPayload(String content, Editor editor) {
this.content = content;
this.editor = editor;
Expand All @@ -20,8 +26,8 @@ public String getContent() {
}

@NotNull
public Editor getEditor() {
return editor;
public Optional<Editor> getEditor() {
return Optional.ofNullable(editor);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@ private void addDataSourceMetadata(GraphQueryResult graphQueryResult, String key

dataReceiver.put(key, dataSourceMetadata);
}

public void addDataSourceMetadata(List<Map<String, String>> data, String key) {
dataReceiver.put(key, data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@
import java.awt.event.MouseEvent;
import java.util.Enumeration;

import static com.neueda.jetbrains.plugin.graphdb.visualization.util.DisplayUtil.*;
import static com.neueda.jetbrains.plugin.graphdb.visualization.util.DisplayUtil.getTooltipText;
import static com.neueda.jetbrains.plugin.graphdb.visualization.util.DisplayUtil.getTooltipTitle;

public class GraphPanel {

private static final int TYPES_DEPTH = 2;
private static final int PROPERTY_DEPTH = 3;

private PrefuseVisualization visualization;
private LookAndFeelService lookAndFeelService;
private BalloonBuilder balloonPopupBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void postResultReceived(ExecuteQueryPayload payload) {
@Override
public void handleError(ExecuteQueryPayload payload, Exception exception) {
String errorMessage = exception.getMessage() == null ? "Error occurred" : "Error occurred: " + exception.getMessage();
HintManager.getInstance().showErrorHint(payload.getEditor(), errorMessage);
payload.getEditor().ifPresent(editor -> HintManager.getInstance().showErrorHint(editor, errorMessage));

visualization.stop();
visualization.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.actions.RefreshDataSourcesAction;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.interactions.DataSourceInteractions;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.DataSourceMetadataUi;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.GraphColoredTreeCellRenderer;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.*;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.util.FileUtil;
import com.neueda.jetbrains.plugin.graphdb.language.cypher.completion.metadata.CypherMetadataProviderService;

Expand All @@ -30,9 +30,12 @@
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;

public class DataSourcesView implements Disposable {

public static final String ROOT_NAME = "treeRoot";

private boolean initialized;

private DataSourcesComponent component;
Expand Down Expand Up @@ -62,7 +65,7 @@ public void initToolWindow(Project project, ToolWindow toolWindow) {
componentMetadata = project.getComponent(DataSourcesComponentMetadata.class);
cypherMetadataProviderService = ServiceManager.getService(project, CypherMetadataProviderService.class);
dataSourceMetadataUi = new DataSourceMetadataUi(componentMetadata);
treeRoot = new PatchedDefaultMutableTreeNode("treeRoot");
treeRoot = new PatchedDefaultMutableTreeNode(new TreeNodeModel(Neo4jTreeNodeType.ROOT, ROOT_NAME));
treeModel = new DefaultTreeModel(treeRoot, false);
decorator = ToolbarDecorator.createDecorator(dataSourceTree);
decorator.addExtraAction(new RefreshDataSourcesAction(this));
Expand Down Expand Up @@ -110,6 +113,7 @@ private void configureDataSourceTree() {
dataSourceTree.setModel(treeModel);
dataSourceTree.setRootVisible(false);
dataSourceTree.setToggleClickCount(0);
dataSourceTree.addMouseListener(new DataSourcesTreeMouseAdapter());
}

private void decorateDataSourceTree() {
Expand All @@ -124,7 +128,7 @@ private void replaceTreeWithDecorated() {

private void showDataSources() {
component.getDataSourceContainer().getDataSources()
.forEach((dataSource) -> treeRoot.add(new PatchedDefaultMutableTreeNode(dataSource)));
.forEach((dataSource) -> treeRoot.add(new PatchedDefaultMutableTreeNode(new TreeNodeModel(Neo4jTreeNodeType.DATASOURCE, dataSource))));
treeModel.reload();
}

Expand All @@ -143,15 +147,17 @@ public void refreshDataSourcesMetadata() {
}

public boolean refreshDataSourceMetadata(PatchedDefaultMutableTreeNode treeNode) {
DataSourceApi nodeDataSource = (DataSourceApi) treeNode.getUserObject();
TreeNodeModelApi userObject = (TreeNodeModelApi) treeNode.getUserObject();
DataSourceApi nodeDataSource = userObject.getDataSourceApi();
Analytics.event(nodeDataSource, "refreshMetadata");
return dataSourceMetadataUi.updateDataSourceMetadataUi(treeNode, nodeDataSource);
}

public void createDataSource(DataSourceApi dataSource) {
Analytics.event(dataSource, "create");
component.getDataSourceContainer().addDataSource(dataSource);
PatchedDefaultMutableTreeNode treeNode = new PatchedDefaultMutableTreeNode(dataSource);
TreeNodeModel model = new TreeNodeModel(Neo4jTreeNodeType.DATASOURCE, dataSource);
PatchedDefaultMutableTreeNode treeNode = new PatchedDefaultMutableTreeNode(model);
treeRoot.add(treeNode);
refreshDataSourceMetadata(treeNode);
treeModel.reload();
Expand All @@ -160,7 +166,7 @@ public void createDataSource(DataSourceApi dataSource) {
public void updateDataSource(PatchedDefaultMutableTreeNode treeNode, DataSourceApi oldDataSource, DataSourceApi newDataSource) {
Analytics.event(newDataSource, "update");
component.getDataSourceContainer().updateDataSource(oldDataSource, newDataSource);
treeNode.setUserObject(newDataSource);
treeNode.setUserObject(new TreeNodeModel(Neo4jTreeNodeType.DATASOURCE, newDataSource));
refreshDataSourceMetadata(treeNode);
treeModel.reload();
}
Expand All @@ -184,14 +190,15 @@ public void removeDataSources(Project project, List<DataSourceApi> dataSourcesFo
Enumeration enumeration = treeRoot.children();
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode element = (DefaultMutableTreeNode) enumeration.nextElement();
DataSourceApi dataSource = (DataSourceApi) element.getUserObject();
TreeNodeModelApi userObject = (TreeNodeModelApi) element.getUserObject();
DataSourceApi dataSource = userObject.getDataSourceApi();
if (dataSource.getName().equals(name)) {
return element;
}
}
return null;
})
.filter(ds -> ds != null)
.filter(Objects::nonNull)
.forEach(treeRoot::remove);

treeModel.reload();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
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.*;
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.dto.ValueWithIcon;
import com.neueda.jetbrains.plugin.graphdb.platform.GraphIcons;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.TreeNodeModel;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.TreeNodeModelApi;

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 PROPERTY_KEYS_TITLE = "property keys";
private static final String LABELS_TITLE = "labels";
private static final String STORED_PROCEDURES_TITLE = "stored procedures";
private static final String USER_FUNCTIONS_TITLE = "user functions";

private final DataSourcesComponentMetadata dataSourcesComponent;

public DataSourceMetadataUi(DataSourcesComponentMetadata dataSourcesComponent) {
Expand All @@ -26,43 +36,45 @@ public boolean updateDataSourceMetadataUi(PatchedDefaultMutableTreeNode node, Da
}

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

// Labels
PatchedDefaultMutableTreeNode labelsTreeNode = new PatchedDefaultMutableTreeNode(
new ValueWithIcon(GraphIcons.Nodes.LABEL, "labels"));
new TreeNodeModel(LABELS, dataSourceApi, LABELS_TITLE));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.LABELS)
.forEach((row) -> labelsTreeNode.add(new PatchedDefaultMutableTreeNode(row.get("label"))));
.forEach((row) -> labelsTreeNode.add(of(new TreeNodeModel(LABEL, dataSourceApi, row.get("label")))));
dataSourceRootTreeNode.add(labelsTreeNode);

// RelTypes
PatchedDefaultMutableTreeNode relationshipTypesTreeNode = new PatchedDefaultMutableTreeNode(
new ValueWithIcon(GraphIcons.Nodes.RELATIONSHIP_TYPE, "relationship types"));
new TreeNodeModel(RELATIONSHIPS, dataSourceApi, RELATIONSHIP_TYPES_TITLE));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.RELATIONSHIP_TYPES)
.forEach((row) -> relationshipTypesTreeNode.add(new PatchedDefaultMutableTreeNode(row.get("relationshipType"))));
.forEach((row) -> relationshipTypesTreeNode.add(of(new TreeNodeModel(RELATIONSHIP, dataSourceApi, row.get("relationshipType")))));
dataSourceRootTreeNode.add(relationshipTypesTreeNode);

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

// Stored procedures
PatchedDefaultMutableTreeNode storedProceduresTreeNode = new PatchedDefaultMutableTreeNode(
new ValueWithIcon(GraphIcons.Nodes.STORED_PROCEDURE, "stored procedures"));
new TreeNodeModel(STORED_PROCEDURES, dataSourceApi, STORED_PROCEDURES_TITLE));
dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.STORED_PROCEDURES)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = new PatchedDefaultMutableTreeNode(row.get("name"));
PatchedDefaultMutableTreeNode descriptionNode = new PatchedDefaultMutableTreeNode(row.get("signature"));
PatchedDefaultMutableTreeNode nameNode = of(new TreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new TreeNodeModel(STORED_PROCEDURE, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
storedProceduresTreeNode.add(nameNode);
});
Expand All @@ -71,13 +83,13 @@ private boolean updateNeo4jBoltCypherMetadataUi(PatchedDefaultMutableTreeNode da
// User Functions
if (dataSourceMetadata.isMetadataExists(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS)) {
PatchedDefaultMutableTreeNode userFunctionTreeNode = new PatchedDefaultMutableTreeNode(
new ValueWithIcon(GraphIcons.Nodes.USER_FUNCTION, "user functions"));
new TreeNodeModel(USER_FUNCTIONS, dataSourceApi, USER_FUNCTIONS_TITLE));

dataSourceMetadata
.getMetadata(Neo4jBoltCypherDataSourceMetadata.USER_FUNCTIONS)
.forEach((row) -> {
PatchedDefaultMutableTreeNode nameNode = new PatchedDefaultMutableTreeNode(row.get("name"));
PatchedDefaultMutableTreeNode descriptionNode = new PatchedDefaultMutableTreeNode(row.get("signature"));
PatchedDefaultMutableTreeNode nameNode = of(new TreeNodeModel(LABEL, dataSourceApi, row.get("name")));
PatchedDefaultMutableTreeNode descriptionNode = of(new TreeNodeModel(LABEL, dataSourceApi, row.get("signature")));
nameNode.add(descriptionNode);
userFunctionTreeNode.add(nameNode);
});
Expand All @@ -87,4 +99,8 @@ private boolean updateNeo4jBoltCypherMetadataUi(PatchedDefaultMutableTreeNode da

return true;
}

private PatchedDefaultMutableTreeNode of(TreeNodeModel model) {
return new PatchedDefaultMutableTreeNode(model);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.actions;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.util.messages.MessageBus;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.actions.execute.ExecuteQueryEvent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.actions.execute.ExecuteQueryPayload;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.DataSourcesComponent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.state.DataSourceApi;

import javax.swing.*;
import java.util.Optional;

public abstract class MetadataAction extends AnAction {

private String data;
private String dataSourceUuid;

MetadataAction(String data, String dataSourceUuid, String title, String description, Icon icon) {
super(title, description, icon);
this.data = data;
this.dataSourceUuid = dataSourceUuid;
}

protected abstract String getQuery(String data);

@Override
public void actionPerformed(AnActionEvent e) {
Project project = getEventProject(e);
MessageBus messageBus = project.getMessageBus();

ExecuteQueryEvent executeQueryEvent = messageBus.syncPublisher(ExecuteQueryEvent.EXECUTE_QUERY_TOPIC);

ExecuteQueryPayload payload = new ExecuteQueryPayload(getQuery(data));

DataSourcesComponent dataSourcesComponent = project.getComponent(DataSourcesComponent.class);
Optional<DataSourceApi> dataSource = dataSourcesComponent.getDataSourceContainer().findDataSource(dataSourceUuid);

dataSource.ifPresent(dataSourceApi -> executeQueryEvent.executeQuery(dataSourceApi, payload));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.actions;

import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.Neo4jTreeNodeType;
import com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.tree.NodeType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.neueda.jetbrains.plugin.graphdb.platform.GraphIcons.Database.NEO4J;

public class MetadataActionGroup extends ActionGroup {

private final NodeType type;
private final String data;
private final String dataSourceUuid;

public MetadataActionGroup(NodeType type, String data, String dataSourceUuid) {
this.type = type;
this.data = data;
this.dataSourceUuid = dataSourceUuid;
}

@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent e) {
if (type == Neo4jTreeNodeType.RELATIONSHIP) {
return new AnAction[]{new MetadataRelationshipAction(data, dataSourceUuid, "Query this relationship", "", NEO4J)};
} else if (type == Neo4jTreeNodeType.LABEL) {
return new AnAction[]{new MetadataLabelAction(data, dataSourceUuid, "Query this label", "", NEO4J)};
} else if (type == Neo4jTreeNodeType.PROPERTY_KEY) {
return new AnAction[]{new MetadataPropertyKeyAction(data, dataSourceUuid, "Query this property", "", NEO4J)};
} else {
return new AnAction[]{};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.actions;

import javax.swing.*;

public class MetadataLabelAction extends MetadataAction {

private static final String QUERY = "MATCH (n:%s) RETURN n LIMIT 25";

MetadataLabelAction(String data, String dataSourceUuid, String title, String description, Icon icon) {
super(data, dataSourceUuid, title, description, icon);
}

@Override
protected String getQuery(String data) {
return String.format(QUERY, data);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.neueda.jetbrains.plugin.graphdb.jetbrains.ui.datasource.metadata.actions;

import javax.swing.*;

public class MetadataPropertyKeyAction extends MetadataAction {

private static final String QUERY = "MATCH (n) WHERE EXISTS(n.%1$s) "
+ "RETURN DISTINCT \"node\" as element, n.%1$s AS %1$s LIMIT 25 "
+ "UNION ALL MATCH ()-[r]-() WHERE EXISTS(r.%1$s) "
+ "RETURN DISTINCT \"relationship\" AS element, r.%1$s AS %1$s LIMIT 25";

MetadataPropertyKeyAction(String data, String dataSourceUuid, String title, String description, Icon icon) {
super(data, dataSourceUuid, title, description, icon);
}

@Override
protected String getQuery(String data) {
return String.format(QUERY, data);
}
}
Loading