├── src
└── main
│ ├── resources
│ ├── open.gif
│ ├── save.gif
│ ├── pinned.gif
│ ├── icon_plus.gif
│ ├── note_edit.png
│ ├── page_edit.png
│ ├── export_wiz.gif
│ ├── icon_export.gif
│ ├── image_edit.png
│ ├── comment_edit.png
│ ├── viewconfig-ontograf.xml
│ └── readme.html
│ └── java
│ └── org
│ └── protege
│ └── ontograf
│ ├── common
│ ├── util
│ │ ├── NodeOWLClassTooltipType.java
│ │ ├── NodeOWLIndividualTooltipType.java
│ │ ├── IconConstants.java
│ │ └── OWLIconProviderImpl.java
│ ├── ProtegeInputEventHandler.java
│ ├── GraphController.java
│ └── ProtegeGraphModel.java
│ ├── actions
│ ├── ConfigTooltipsAction.java
│ ├── SaveGraphAction.java
│ ├── ExportAsDotAction.java
│ ├── PinTooltipsAction.java
│ ├── OpenGraphAction.java
│ └── ExportImageAction.java
│ ├── OntoGrafImportView.java
│ ├── ui
│ ├── TooltipConfigurationDialog.java
│ ├── OntoGrafFileFilter.java
│ └── FrameTooltipNode.java
│ └── OntoGrafView.java
├── .gitignore
├── update-info
├── protege-4
│ └── update.properties
└── protege-5
│ └── update.properties
├── README.md
├── plugin.xml
├── META-INF
└── MANIFEST.MF
└── pom.xml
/src/main/resources/open.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/open.gif
--------------------------------------------------------------------------------
/src/main/resources/save.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/save.gif
--------------------------------------------------------------------------------
/src/main/resources/pinned.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/pinned.gif
--------------------------------------------------------------------------------
/src/main/resources/icon_plus.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/icon_plus.gif
--------------------------------------------------------------------------------
/src/main/resources/note_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/note_edit.png
--------------------------------------------------------------------------------
/src/main/resources/page_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/page_edit.png
--------------------------------------------------------------------------------
/src/main/resources/export_wiz.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/export_wiz.gif
--------------------------------------------------------------------------------
/src/main/resources/icon_export.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/icon_export.gif
--------------------------------------------------------------------------------
/src/main/resources/image_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/image_edit.png
--------------------------------------------------------------------------------
/src/main/resources/comment_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/protegeproject/ontograf/HEAD/src/main/resources/comment_edit.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Maven
2 | target/
3 |
4 | # Eclipse
5 | .classpath
6 | .project
7 | .settings/
8 | META-INF/
9 |
10 | #intelliJ
11 | *.iws
12 | *.ipr
13 | .idea
14 | *.iml
15 | build/
16 |
--------------------------------------------------------------------------------
/update-info/protege-4/update.properties:
--------------------------------------------------------------------------------
1 | name=OntoGraf
2 | id=org.protege.ontograf
3 | version=1.0.3
4 | download=https://github.com/protegeproject/ontograf/releases/download/ontograf-1.0.3/org.protege.ontograf.jar
5 | readme=https://raw.githubusercontent.com/protegeproject/ontograf/master/src/main/resources/readme.html
6 | license=http://www.gnu.org/licenses/lgpl.html
7 | author=CO-ODE, The University of Manchester
--------------------------------------------------------------------------------
/update-info/protege-5/update.properties:
--------------------------------------------------------------------------------
1 | name=OntoGraf
2 | id=org.protege.ontograf
3 | version=2.0.3
4 | download=https://github.com/protegeproject/ontograf/releases/download/ontograf-2.0.3/ontograf-2.0.3.jar
5 | readme=https://raw.githubusercontent.com/protegeproject/ontograf/master/src/main/resources/readme.html
6 | license=http://www.gnu.org/licenses/lgpl.html
7 | author=CO-ODE, The University of Manchester
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | OntoGraf
2 | ====================
3 |
4 | Protege Desktop plug-in that allows visual, interactive navigation of the relationships in OWL ontologies.
5 |
6 | OntoGraf is bundled with the default installation of Protege Desktop. There are no additional installation steps required. Enable OntoGraf from the Window | Tabs menu. More user documentation is available on the Protege wiki:
7 |
8 | http://protegewiki.stanford.edu/wiki/OntoGraf
9 |
--------------------------------------------------------------------------------
/src/main/resources/viewconfig-ontograf.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/util/NodeOWLClassTooltipType.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.common.util;
2 |
3 | public enum NodeOWLClassTooltipType {
4 | TITLE("Title"), URI("URI"), SUPERCLASSES("Superclasses"), EQUIVALENT_CLASSES("Equivalent classes"),
5 | DISJOINT_CLASSES("Disjoint classes"), ANNOTATIONS("Annotations");
6 |
7 | private final String value;
8 | private boolean enabled;
9 |
10 | NodeOWLClassTooltipType(String value) {
11 | this.value = value;
12 | this.enabled = true;
13 | }
14 |
15 | public boolean isEnabled() {
16 | return enabled;
17 | }
18 |
19 | public void setEnabled(boolean enabled) {
20 | this.enabled = enabled;
21 | }
22 |
23 | public String toString() {
24 | return value;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/resources/readme.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | OntoGraf
9 | by Sean Falconer
10 |
11 | OntoGraf gives support for interactively navigating the relationships
12 | of your OWL ontologies. Various layouts are supported for
13 | automatically organizing the structure of your ontology. Different
14 | relationships are supported: subclass, individual, domain/range object
15 | properties, and equivalence. Relationships and node types can be
16 | filtered to help you create the view you desire. For more infomration
17 | look on the
18 | the wiki page .
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/util/NodeOWLIndividualTooltipType.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.common.util;
2 |
3 | public enum NodeOWLIndividualTooltipType {
4 | TITLE("Title"), URI("URI"), SAME_INDIVIDUALS("Same individuals"), DIFFERENT_INDIVIDUALS("Different individuals"),
5 | OBJECT_PROPERTY_ASSERTIONS("Object property assertions"), DATA_PROPERTY_ASSERTIONS("Data property assertions"),
6 | NEGATIVE_OBJECT_PROPERTY_ASSERTIONS("Negative object property assertions"), NEGATIVE_DATA_PROPERTY_ASSERTIONS("Negative data property assertions"), ANNOTATIONS("Annotations");
7 |
8 | private final String value;
9 | private boolean enabled;
10 |
11 | NodeOWLIndividualTooltipType(String value) {
12 | this.value = value;
13 | this.enabled = true;
14 | }
15 |
16 | public boolean isEnabled() {
17 | return enabled;
18 | }
19 |
20 | public void setEnabled(boolean enabled) {
21 | this.enabled = enabled;
22 | }
23 |
24 | public String toString() {
25 | return value;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/ConfigTooltipsAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.Component;
4 |
5 | import javax.swing.Action;
6 |
7 | import org.protege.ontograf.common.util.IconConstants;
8 | import org.protege.ontograf.ui.TooltipConfigurationDialog;
9 |
10 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
11 | import edu.umd.cs.piccolo.PCanvas;
12 |
13 | public class ConfigTooltipsAction extends CajunAction {
14 | private static final long serialVersionUID = 7241297162054742885L;
15 |
16 | private static final String ACTION_NAME = "Configure Node Tooltips";
17 |
18 | private TooltipConfigurationDialog tooltipDialog;
19 |
20 | public ConfigTooltipsAction(Component parent, PCanvas canvas) {
21 | super(ACTION_NAME, IconConstants.ICON_EDIT_NODE_TOOLTIP);
22 |
23 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
24 |
25 | tooltipDialog = new TooltipConfigurationDialog();
26 | }
27 |
28 | @Override
29 | public void doAction() {
30 | tooltipDialog.setVisible(true);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: OntoGraf Plug-in
4 | Bundle-SymbolicName: org.protege.ontograf;singleton:=true
5 | Bundle-Category: protege
6 | Bundle-Description: A plugin for visualizing ontologies
7 | Bundle-Vendor: The Protege Team
8 | Bundle-DocURL: http://protege.stanford.edu/
9 | Bundle-ClassPath: .,
10 | lib/layouts.jar,
11 | lib/org.eclipse.draw2d_3.2.100.v20070522.jar,
12 | lib/piccolo.jar,
13 | lib/piccolox.jar
14 | Import-Package: javax.imageio,
15 | javax.swing,
16 | javax.swing.border,
17 | javax.swing.colorchooser,
18 | javax.swing.event,
19 | javax.swing.filechooser,
20 | javax.swing.plaf,
21 | javax.swing.plaf.basic,
22 | javax.swing.plaf.metal,
23 | javax.swing.plaf.multi,
24 | javax.swing.plaf.synth,
25 | javax.swing.table,
26 | javax.swing.text,
27 | javax.swing.text.html,
28 | javax.swing.text.html.parser,
29 | javax.swing.text.rtf,
30 | javax.swing.tree,
31 | javax.swing.undo,
32 | javax.xml.parsers,
33 | org.apache.log4j,
34 | org.osgi.framework,
35 | org.w3c.dom,
36 | org.w3c.dom.bootstrap,
37 | org.w3c.dom.events,
38 | org.w3c.dom.ls,
39 | org.xml.sax,
40 | org.xml.sax.ext,
41 | org.xml.sax.helpers
42 | Bundle-Version: 1.0.3
43 | Bundle-Activator: org.protege.editor.core.plugin.DefaultPluginActivator
44 | Require-Bundle: org.protege.common,
45 | org.protege.editor.core.application,
46 | org.protege.editor.owl,
47 | org.semanticweb.owl.owlapi,
48 | ca.uvic.cs.chisel.cajun
49 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/util/IconConstants.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 1998-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
3 | * All rights reserved.
4 | */
5 | package org.protege.ontograf.common.util;
6 |
7 | import java.net.URL;
8 |
9 | import javax.swing.Icon;
10 | import javax.swing.ImageIcon;
11 |
12 | import org.protege.ontograf.common.GraphController;
13 |
14 |
15 | /**
16 | * Interface for storing icons used by this tool.
17 | *
18 | * @author Sean Falconer
19 | */
20 | public abstract class IconConstants {
21 | public static final Icon ICON_PLUS = loadImageIcon(GraphController.class, "/icon_plus.gif");
22 |
23 | public static final Icon ICON_EXPORT_IMAGE = loadImageIcon(GraphController.class, "/icon_export.gif");
24 | public static final Icon ICON_EDIT_NODE_TOOLTIP = loadImageIcon(GraphController.class, "/image_edit.png");
25 | public static final Icon ICON_SAVE_GRAPH = loadImageIcon(GraphController.class, "/save.gif");
26 | public static final Icon ICON_EXPORT_DOT_GRAPH = loadImageIcon(GraphController.class, "/export_wiz.gif");
27 | public static final Icon ICON_OPEN_GRAPH = loadImageIcon(GraphController.class, "/open.gif");
28 | public static final Icon ICON_PIN_TOOLTIPS = loadImageIcon(GraphController.class, "/pinned.gif");
29 |
30 | @SuppressWarnings("unchecked")
31 | public static ImageIcon loadImageIcon(Class clas, String iconPath) {
32 | ImageIcon icon = null;
33 | URL url = clas.getResource(iconPath);
34 | if (url != null) {
35 | icon = new ImageIcon(url);
36 | }
37 | else {
38 | icon = new ImageIcon(iconPath);
39 | }
40 | return icon;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/SaveGraphAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.Component;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.PrintStream;
7 |
8 | import javax.swing.Action;
9 | import javax.swing.JFileChooser;
10 | import javax.swing.JOptionPane;
11 |
12 | import org.protege.editor.owl.model.OWLModelManager;
13 | import org.protege.ontograf.common.GraphController;
14 | import org.protege.ontograf.common.util.IconConstants;
15 | import org.protege.ontograf.ui.OntoGrafFileFilter;
16 | import org.semanticweb.owlapi.model.OWLEntity;
17 |
18 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
19 | import ca.uvic.cs.chisel.cajun.graph.GraphModel;
20 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNode;
21 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
22 |
23 | public class SaveGraphAction extends CajunAction {
24 | private static final long serialVersionUID = 7241297162054742885L;
25 |
26 | private static final String ACTION_NAME = "Save Current Graph";
27 |
28 | private JFileChooser fileChooser;
29 |
30 | private Component parent;
31 | private GraphController controller;
32 |
33 | public SaveGraphAction(Component parent, GraphController controller) {
34 | super(ACTION_NAME, IconConstants.ICON_SAVE_GRAPH);
35 |
36 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
37 |
38 | this.parent = parent;
39 | this.controller = controller;
40 |
41 | fileChooser = new JFileChooser();
42 | fileChooser.setDialogTitle("Save graph configuration to a file");
43 | fileChooser.addChoosableFileFilter(new OntoGrafFileFilter(new String[] { "graph" }, "OntoGraf File"));
44 | }
45 |
46 | @Override
47 | public void doAction() {
48 | int result = fileChooser.showSaveDialog(parent);
49 |
50 | if(result == JFileChooser.CANCEL_OPTION) return;
51 |
52 | String filePath = fileChooser.getSelectedFile().getPath();
53 | if(!filePath.contains(".graph")) {
54 | filePath += ".graph";
55 | }
56 | File file = new File(filePath);
57 |
58 | if(file.exists()) {
59 | String msg = "The file " + file.toString() + " already exists.\nDo you want to overwrite this existing file?";
60 | int opt = JOptionPane.showConfirmDialog(parent, msg,
61 | "Export Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
62 |
63 | if(opt == JOptionPane.NO_OPTION) return;
64 | }
65 |
66 | try {
67 | PrintStream out = new PrintStream(file);
68 |
69 | GraphModel model = controller.getGraph().getModel();
70 | OWLModelManager owlModelManager = controller.getModel().getOwlModelManager();
71 |
72 | out.println(owlModelManager.getActiveOntology().getOntologyID().getOntologyIRI().toString());
73 |
74 | for(GraphNode node : model.getAllNodes()) {
75 | if(node instanceof DefaultGraphNode) {
76 | DefaultGraphNode graphNode = (DefaultGraphNode)node;
77 | OWLEntity entity = (OWLEntity)graphNode.getUserObject();
78 |
79 | out.println(entity.getIRI().toString() + "," + graphNode.getX() + "," + graphNode.getY());
80 | }
81 | }
82 | out.close();
83 | } catch (FileNotFoundException e) {
84 | // TODO Auto-generated catch block
85 | e.printStackTrace();
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/ExportAsDotAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.Component;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.PrintStream;
7 |
8 | import javax.swing.Action;
9 | import javax.swing.JFileChooser;
10 | import javax.swing.JOptionPane;
11 |
12 | import org.protege.ontograf.common.GraphController;
13 | import org.protege.ontograf.common.util.IconConstants;
14 | import org.protege.ontograf.ui.OntoGrafFileFilter;
15 |
16 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
17 | import ca.uvic.cs.chisel.cajun.graph.GraphModel;
18 | import ca.uvic.cs.chisel.cajun.graph.arc.DefaultGraphArc;
19 | import ca.uvic.cs.chisel.cajun.graph.arc.GraphArc;
20 |
21 | public class ExportAsDotAction extends CajunAction {
22 | private static final long serialVersionUID = 7241297162054742885L;
23 |
24 | private static final String ACTION_NAME = "Export Graph to DOT";
25 |
26 | private JFileChooser fileChooser;
27 |
28 | private Component parent;
29 | private GraphController controller;
30 |
31 | public ExportAsDotAction(Component parent, GraphController controller) {
32 | super(ACTION_NAME, IconConstants.ICON_EXPORT_DOT_GRAPH);
33 |
34 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
35 |
36 | this.parent = parent;
37 | this.controller = controller;
38 |
39 | fileChooser = new JFileChooser();
40 | fileChooser.setDialogTitle("Save graph as DOT file");
41 | fileChooser.addChoosableFileFilter(new OntoGrafFileFilter(new String[] { "dot" }, "DOT File"));
42 | }
43 |
44 | @Override
45 | public void doAction() {
46 | int result = fileChooser.showSaveDialog(parent);
47 |
48 | if(result == JFileChooser.CANCEL_OPTION) return;
49 |
50 | String filePath = fileChooser.getSelectedFile().getPath();
51 | if(!filePath.contains(".dot")) {
52 | filePath += ".dot";
53 | }
54 | File file = new File(filePath);
55 |
56 | if(file.exists()) {
57 | String msg = "The file " + file.toString() + " already exists.\nDo you want to overwrite this existing file?";
58 | int opt = JOptionPane.showConfirmDialog(parent, msg,
59 | "Export Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
60 |
61 | if(opt == JOptionPane.NO_OPTION) return;
62 | }
63 |
64 | try {
65 | PrintStream out = new PrintStream(file);
66 |
67 | GraphModel model = controller.getGraph().getModel();
68 |
69 | out.println("digraph g {");
70 | //out.println("\tnode [shape=");
71 |
72 | for(GraphArc arc : model.getAllArcs()) {
73 | if(arc instanceof DefaultGraphArc) {
74 | DefaultGraphArc graphArc = (DefaultGraphArc)arc;
75 | out.println("\t\"" + graphArc.getSource().getText() + "\" -> \"" + graphArc.getDestination().getText()
76 | + "\" [label=\"" + graphArc.getType() + "\"]");
77 | }
78 | }
79 |
80 | // for(GraphNode node : model.getAllNodes()) {
81 | // if(node instanceof DefaultGraphNode) {
82 | // DefaultGraphNode graphNode = (DefaultGraphNode)node;
83 | // graphNode.
84 | //
85 | // //OWLEntity entity = (OWLEntity)graphNode.getUserObject();
86 | //
87 | // //out.println(entity.getIRI().toString() + "," + graphNode.getX() + "," + graphNode.getY());
88 | // }
89 | // }
90 | out.println("}");
91 | out.close();
92 | } catch (FileNotFoundException e) {
93 | // TODO Auto-generated catch block
94 | e.printStackTrace();
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/ProtegeInputEventHandler.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.common;
2 |
3 | import org.protege.ontograf.ui.FrameTooltipNode;
4 | import org.semanticweb.owlapi.model.OWLEntity;
5 |
6 | import ca.uvic.cs.chisel.cajun.graph.AbstractGraph;
7 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNode;
8 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
9 | import edu.umd.cs.piccolo.PCamera;
10 | import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
11 | import edu.umd.cs.piccolo.event.PInputEvent;
12 | import edu.umd.cs.piccolo.event.PInputEventFilter;
13 |
14 | /**
15 | * Handles input events on the graph.
16 | *
17 | * @author seanf
18 | */
19 | public class ProtegeInputEventHandler extends PBasicInputEventHandler {
20 | private static final int DOUBLE_CLICK = 2;
21 |
22 | private ProtegeGraphModel graphModel;
23 | private AbstractGraph graph;
24 |
25 | private FrameTooltipNode toolTip;
26 | private DefaultGraphNode currentNode;
27 |
28 | public ProtegeInputEventHandler(ProtegeGraphModel graphModel, AbstractGraph graph) {
29 | this.graphModel = graphModel;
30 | this.graph = graph;
31 |
32 | PInputEventFilter filter = new PInputEventFilter();
33 | filter.rejectAllEventTypes();
34 | filter.setAcceptsMousePressed(true);
35 | filter.setAcceptsMouseMoved(true);
36 |
37 | this.setEventFilter(filter);
38 | }
39 |
40 | public void mouseMoved(PInputEvent event) {
41 | if(event.getPickedNode() instanceof GraphNode) {
42 | if(!event.getPickedNode().equals(currentNode)) {
43 | showToolTip((DefaultGraphNode)event.getPickedNode());
44 | }
45 | }
46 | else if(currentNode != null) {
47 | hideToolTip(currentNode);
48 | currentNode = null;
49 | }
50 | }
51 |
52 | public void mousePressed(PInputEvent event) {
53 | hideToolTip(currentNode);
54 |
55 | if (event.isLeftMouseButton()) {
56 | if (event.getClickCount() == DOUBLE_CLICK) {
57 | if (event.getPickedNode() instanceof GraphNode) {
58 | expandCollapseNode((GraphNode) event.getPickedNode());
59 | //((FlatGraph) graph).getAnimationHandler().moveViewToCenterBounds(graph.getBounds(), false, 1000, true);
60 | }
61 | }
62 | else if(event.getClickCount() == 1 && event.isControlDown()) {
63 | showToolTip((DefaultGraphNode)event.getPickedNode());
64 | currentNode = null;
65 | }
66 | }
67 | }
68 |
69 | private void hideToolTip(DefaultGraphNode node) {
70 | PCamera camera = graph.getCanvas().getCamera();
71 | if(toolTip != null) {
72 | camera.removeChild(toolTip);
73 | camera.repaint();
74 | toolTip = null;
75 | }
76 | }
77 |
78 | private void showToolTip(DefaultGraphNode node) {
79 | PCamera camera = graph.getCanvas().getCamera();
80 | hideToolTip(node);
81 |
82 | toolTip = new FrameTooltipNode(graphModel.getOwlModelManager(), graph, node, (OWLEntity)node.getUserObject());
83 | camera.addChild(toolTip);
84 | camera.repaint();
85 |
86 | currentNode = node;
87 | }
88 |
89 | /**
90 | * Expands a node if it is not already expanded, otherwise it collapses it.
91 | *
92 | * @param graphNode The node to expand or collapse.
93 | */
94 | private void expandCollapseNode(GraphNode graphNode) {
95 | graphNode.setHighlighted(false);
96 | graphNode.moveToFront();
97 |
98 | if (graphModel.isExpanded(graphNode)) {
99 | graphModel.collapseNode(graphNode);
100 | } else {
101 | graphModel.expandNode(graphNode);
102 | }
103 |
104 | graph.performLayout();
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/PinTooltipsAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.Component;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 | import java.util.Map.Entry;
7 |
8 | import javax.swing.Action;
9 | import javax.swing.event.ChangeEvent;
10 | import javax.swing.event.ChangeListener;
11 |
12 | import org.protege.ontograf.common.GraphController;
13 | import org.protege.ontograf.common.util.IconConstants;
14 | import org.protege.ontograf.ui.FrameTooltipNode;
15 | import org.semanticweb.owlapi.model.OWLEntity;
16 |
17 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
18 | import ca.uvic.cs.chisel.cajun.graph.AbstractGraph;
19 | import ca.uvic.cs.chisel.cajun.graph.GraphModelAdapter;
20 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNode;
21 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
22 | import edu.umd.cs.piccolo.PNode;
23 |
24 | public class PinTooltipsAction extends CajunAction {
25 | private static final long serialVersionUID = 7241297162054742885L;
26 |
27 | private static final String ACTION_NAME = "Pin Node Tooltips";
28 |
29 | private GraphController graphController;
30 |
31 | private boolean show = true;
32 |
33 | private Map existingTooltipsMap;
34 | private Map changeListenerMap;
35 |
36 | public PinTooltipsAction(Component parent, GraphController graphController) {
37 | super(ACTION_NAME, IconConstants.ICON_PIN_TOOLTIPS);
38 |
39 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
40 |
41 | this.existingTooltipsMap = new HashMap();
42 | this.changeListenerMap = new HashMap();
43 |
44 | this.graphController = graphController;
45 |
46 | graphController.getModel().addGraphModelListener(new GraphModelAdapter() {
47 | @Override
48 | public void graphNodeAdded(GraphNode arg0) {
49 | if(!show) {
50 | showAllTooltips();
51 | }
52 | }
53 | });
54 | }
55 |
56 | public void doAction() {
57 | if(show) {
58 | showAllTooltips();
59 | show = false;
60 | }
61 | else {
62 | hideAllTooltips();
63 | show = true;
64 | }
65 | }
66 |
67 | private void hideAllTooltips() {
68 | for(Entry entry : existingTooltipsMap.entrySet()) {
69 | entry.getKey().removeChild(entry.getValue());
70 |
71 | ChangeListener changeListener = changeListenerMap.get(entry.getValue());
72 | ((DefaultGraphNode)entry.getKey()).removeChangeListener(changeListener);
73 |
74 | entry.getKey().repaint();
75 | }
76 |
77 | existingTooltipsMap.clear();
78 | changeListenerMap.clear();
79 | }
80 |
81 | private void showAllTooltips() {
82 | for(GraphNode node : graphController.getModel().getAllNodes()) {
83 | // make sure there isn't already a tooltip showing
84 | if(existingTooltipsMap.get((PNode)node) == null) {
85 | FrameTooltipNode toolTip = new FrameTooltipNode(graphController.getModel().getOwlModelManager(), (AbstractGraph)graphController.getGraph(), (PNode)node, (OWLEntity)node.getUserObject());
86 | ((PNode)node).addChild(toolTip);
87 |
88 | existingTooltipsMap.put((PNode)node, toolTip);
89 |
90 | ChangeListener changeListener = new ChangeListener() {
91 | public void stateChanged(ChangeEvent e) {
92 | PNode targetNode = existingTooltipsMap.get((PNode)e.getSource());
93 | if(targetNode != null) {
94 | FrameTooltipNode toolTip = (FrameTooltipNode)targetNode;
95 | toolTip.updateLocation((AbstractGraph)graphController.getGraph(), toolTip.getParent());
96 | }
97 | }
98 | };
99 |
100 | ((DefaultGraphNode)node).addChangeListener(changeListener);
101 | changeListenerMap.put(toolTip, changeListener);
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/OpenGraphAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.Component;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.util.Scanner;
7 | import java.util.Set;
8 |
9 | import javax.swing.Action;
10 | import javax.swing.JFileChooser;
11 | import javax.swing.JOptionPane;
12 |
13 | import org.protege.editor.owl.model.OWLModelManager;
14 | import org.protege.ontograf.common.GraphController;
15 | import org.protege.ontograf.common.ProtegeGraphModel;
16 | import org.protege.ontograf.common.util.IconConstants;
17 | import org.protege.ontograf.ui.OntoGrafFileFilter;
18 | import org.semanticweb.owlapi.model.IRI;
19 | import org.semanticweb.owlapi.model.OWLEntity;
20 |
21 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
22 | import ca.uvic.cs.chisel.cajun.graph.FlatGraph;
23 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
24 |
25 | public class OpenGraphAction extends CajunAction {
26 | private static final long serialVersionUID = 7241297162054742885L;
27 |
28 | private static final String ACTION_NAME = "Open Saved Graph";
29 |
30 | private JFileChooser fileChooser;
31 |
32 | private Component parent;
33 | private GraphController controller;
34 |
35 | public OpenGraphAction(Component parent, GraphController controller) {
36 | super(ACTION_NAME, IconConstants.ICON_OPEN_GRAPH);
37 |
38 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
39 |
40 | this.parent = parent;
41 | this.controller = controller;
42 |
43 | fileChooser = new JFileChooser();
44 | fileChooser.setDialogTitle("Open graph configuration file");
45 | fileChooser.addChoosableFileFilter(new OntoGrafFileFilter(new String[] { "graph" }, "OntoGraf File"));
46 | }
47 |
48 | @Override
49 | public void doAction() {
50 | int result = fileChooser.showOpenDialog(parent);
51 |
52 | if(result == JFileChooser.CANCEL_OPTION) return;
53 |
54 | File file = fileChooser.getSelectedFile();
55 | loadFromFile(file);
56 | }
57 |
58 | public void loadFromFile(File file) {
59 | controller.clear();
60 |
61 | ProtegeGraphModel model = controller.getModel();
62 | FlatGraph graph = (FlatGraph)controller.getGraph();
63 | OWLModelManager owlModelManager = controller.getModel().getOwlModelManager();
64 | boolean found = true;
65 |
66 | try (Scanner scanner = new Scanner(file)) {
67 |
68 | // make sure the stored graph is for the active ontology
69 | if(scanner.hasNextLine()) {
70 | String ontologyUri = scanner.nextLine();
71 | String activeOntologyUri = owlModelManager.getActiveOntology().getOntologyID().getOntologyIRI().toString();
72 |
73 | if(!ontologyUri.equals(activeOntologyUri)) {
74 | JOptionPane.showMessageDialog(parent, "Sorry, but the graph description does not correspond to your active ontology.");
75 | return;
76 | }
77 | }
78 |
79 | // attempt to read the csv file and display the elements
80 | while(scanner.hasNextLine()) {
81 | String line = scanner.nextLine();
82 | String items[] = line.split(",");
83 | if(items.length == 3) {
84 | String uri = items[0];
85 | double x = Double.parseDouble(items[1]);
86 | double y = Double.parseDouble(items[2]);
87 |
88 | Set entities = owlModelManager.getOWLEntityFinder().getEntities(IRI.create(uri));
89 | if(entities != null && entities.size() > 0) {
90 | for(OWLEntity owlEntity : entities) {
91 | model.show(owlEntity, graph.getFilterManager());
92 |
93 | GraphNode node = model.getNode(owlEntity);
94 | node.setLocation(x, y);
95 | }
96 | }
97 | else {
98 | found = false;
99 | }
100 | }
101 | }
102 | } catch (FileNotFoundException e) {
103 | e.printStackTrace();
104 | }
105 |
106 | if(!found) {
107 | JOptionPane.showMessageDialog(parent, "Some of the graph entities in the file could not be found within your currenlty loaded ontology.\nPlease make sure this saved graph corresponds to your active ontology.");
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/OntoGrafImportView.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Dimension;
5 | import java.awt.event.ComponentAdapter;
6 | import java.awt.event.ComponentEvent;
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 |
10 | import javax.swing.Icon;
11 |
12 | import org.eclipse.zest.layouts.algorithms.HorizontalDirectedGraphLayoutAlgorithm;
13 | import org.protege.editor.owl.OWLEditorKit;
14 | import org.protege.editor.owl.model.OWLModelManager;
15 | import org.protege.editor.owl.ui.view.cls.AbstractOWLClassViewComponent;
16 | import org.protege.ontograf.common.util.OWLIconProviderImpl;
17 | import org.semanticweb.owlapi.model.OWLClass;
18 | import org.semanticweb.owlapi.model.OWLOntology;
19 |
20 | import ca.uvic.cs.chisel.cajun.actions.LayoutAction;
21 | import ca.uvic.cs.chisel.cajun.constants.LayoutConstants;
22 | import ca.uvic.cs.chisel.cajun.graph.DefaultGraphModel;
23 | import ca.uvic.cs.chisel.cajun.graph.FlatGraph;
24 | import ca.uvic.cs.chisel.cajun.graph.arc.DefaultGraphArc;
25 | import ca.uvic.cs.chisel.cajun.graph.arc.GraphArc;
26 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
27 | import ca.uvic.cs.chisel.cajun.graph.ui.DefaultFlatGraphView;
28 |
29 | /**
30 | * Plugin extension point for the OntoGraf imports view.
31 | *
32 | * @author seanf
33 | */
34 | public class OntoGrafImportView extends AbstractOWLClassViewComponent {
35 | private static final long serialVersionUID = -6969495880634875570L;
36 |
37 | /** the graph object, performs layouts and renders the model */
38 | private FlatGraph graph;
39 |
40 | private ImportsGraphModel model;
41 |
42 | /** the panel that renders the graph view */
43 | private DefaultFlatGraphView view;
44 |
45 | @Override
46 | public void initialiseClassView() throws Exception {
47 | setLayout(new BorderLayout());
48 |
49 | this.addComponentListener(new ComponentAdapter() {
50 | @Override
51 | public void componentResized(ComponentEvent e) {
52 | // TODO Auto-generated method stub
53 | super.componentResized(e);
54 |
55 | }
56 | });
57 |
58 | this.model = new ImportsGraphModel(this.getOWLEditorKit());
59 | this.graph = new FlatGraph(model);
60 | this.view = new DefaultFlatGraphView(graph);
61 |
62 | this.add(this.view, BorderLayout.CENTER);
63 |
64 | Dimension d = new Dimension(800, 600);
65 | setPreferredSize(d);
66 | setSize(d);
67 | setLocation(100, 50);
68 |
69 | setVisible(true);
70 |
71 | for (LayoutAction layoutAction : graph.getLayouts()) {
72 | if (layoutAction.getName().equals(LayoutConstants.LAYOUT_SPRING)) {
73 | layoutAction.setLayout(new HorizontalDirectedGraphLayoutAlgorithm());
74 | this.graph.setLastLayout(layoutAction);
75 | }
76 | }
77 |
78 | this.graph.performLayout();
79 | }
80 |
81 | @Override
82 | protected OWLClass updateView(OWLClass owlClass) {
83 | return null;
84 | }
85 |
86 | @Override
87 | public void disposeView() {
88 | // TODO Auto-generated method stub
89 |
90 | }
91 | }
92 |
93 | class ImportsGraphModel extends DefaultGraphModel {
94 | private static final String IMPORTS = "imports";
95 | private static final String ONTOLOGY = "ontology";
96 |
97 | private OWLEditorKit owlEditorKit;
98 |
99 | public ImportsGraphModel(OWLEditorKit owlEditorKit) {
100 | super();
101 |
102 | this.owlEditorKit = owlEditorKit;
103 |
104 | loadData(owlEditorKit.getOWLWorkspace().getOWLModelManager().getActiveOntology());
105 | }
106 |
107 | private void loadData(OWLOntology owlOntology) {
108 | GraphNode parentNode = addNode(owlEditorKit.getOWLWorkspace().getOWLModelManager().getRendering(owlOntology));
109 |
110 | for(OWLOntology importedOntology : owlOntology.getDirectImports()) {
111 | GraphNode childNode = addNode(owlEditorKit.getOWLWorkspace().getOWLModelManager().getRendering(importedOntology));
112 | addArc(parentNode, childNode);
113 |
114 | loadData(importedOntology);
115 | }
116 | }
117 |
118 | private GraphNode addNode(String name) {
119 | OWLModelManager modelManager = owlEditorKit.getOWLWorkspace().getOWLModelManager();
120 | OWLIconProviderImpl iconProvider = new OWLIconProviderImpl(modelManager);
121 | Icon icon = iconProvider.getIcon(modelManager.getActiveOntology());
122 | return addNode(name, name, icon, ONTOLOGY);
123 | }
124 |
125 | public Collection getNodeTypes() {
126 | ArrayList types = new ArrayList(2);
127 | types.add(ONTOLOGY);
128 |
129 | return types;
130 | }
131 |
132 | private GraphArc addArc(GraphNode src, GraphNode dest) {
133 | String arcId = src.getText() + "->" + dest.getText();
134 |
135 | DefaultGraphArc arc = (DefaultGraphArc) addArc(arcId, src, dest, IMPORTS);
136 |
137 | arc.setInverted(false);
138 | return arc;
139 | }
140 |
141 | public Collection getArcTypes() {
142 | ArrayList types = new ArrayList(3);
143 | types.add(IMPORTS);
144 |
145 | return types;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/ui/TooltipConfigurationDialog.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.ui;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Color;
5 | import java.awt.GridLayout;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.TreeSet;
11 |
12 | import javax.swing.BorderFactory;
13 | import javax.swing.JButton;
14 | import javax.swing.JDialog;
15 | import javax.swing.JPanel;
16 | import javax.swing.JScrollPane;
17 | import javax.swing.JSplitPane;
18 | import javax.swing.border.TitledBorder;
19 |
20 | import org.protege.ontograf.common.util.NodeOWLClassTooltipType;
21 | import org.protege.ontograf.common.util.NodeOWLIndividualTooltipType;
22 |
23 | import ca.uvic.cs.chisel.cajun.graph.ui.FilterCheckBox;
24 |
25 | public class TooltipConfigurationDialog extends JDialog {
26 | private static final long serialVersionUID = -5081919405096749260L;
27 |
28 | private Map owlClassTooltipTypes;
29 | private Map owlIndividualTooltipTypes;
30 |
31 | public TooltipConfigurationDialog() {
32 | setSize(600, 300);
33 |
34 | owlClassTooltipTypes = new HashMap();
35 | for(NodeOWLClassTooltipType tooltipType : NodeOWLClassTooltipType.values()) {
36 | owlClassTooltipTypes.put(tooltipType.toString(), tooltipType.isEnabled());
37 | }
38 |
39 | owlIndividualTooltipTypes = new HashMap();
40 | for(NodeOWLIndividualTooltipType tooltipType : NodeOWLIndividualTooltipType.values()) {
41 | owlIndividualTooltipTypes.put(tooltipType.toString(), tooltipType.isEnabled());
42 | }
43 |
44 | init();
45 | }
46 |
47 | private void init() {
48 | setLayout(new BorderLayout());
49 | setTitle("Node tooltip configuration");
50 |
51 | JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
52 |
53 | splitPane.add(getTypeScrollPanel(getTypesPanel("Class Tooltip Options:"), owlClassTooltipTypes));
54 | splitPane.add(getTypeScrollPanel(getTypesPanel("Individual Tooltip Options:"), owlIndividualTooltipTypes));
55 |
56 | splitPane.setDividerLocation(300);
57 |
58 | add(splitPane, BorderLayout.CENTER);
59 | add(getButtonPanel(), BorderLayout.SOUTH);
60 | }
61 |
62 | private JScrollPane getTypeScrollPanel(JPanel typesPanel, Map types) {
63 | JPanel holder = new JPanel(new BorderLayout());
64 | holder.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
65 | holder.add(typesPanel, BorderLayout.NORTH);
66 | holder.setBackground(Color.white);
67 | //add(getHeaderPanel(), BorderLayout.NORTH);
68 |
69 | JScrollPane scroll = new JScrollPane(holder, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
70 |
71 | loadTypes(typesPanel, types);
72 |
73 | return scroll;
74 | }
75 |
76 | private JPanel getButtonPanel() {
77 | JPanel panel = new JPanel(new BorderLayout());
78 | JButton closeButton = new JButton("Close");
79 | closeButton.addActionListener(new ActionListener() {
80 | public void actionPerformed(ActionEvent e) {
81 | TooltipConfigurationDialog.this.setVisible(false);
82 | }
83 | });
84 |
85 | JPanel buttonContainerPanel = new JPanel();
86 | buttonContainerPanel.add(closeButton);
87 |
88 | panel.add(buttonContainerPanel, BorderLayout.EAST);
89 |
90 | return panel;
91 | }
92 |
93 | private void typeVisibilityChanged(Object type, boolean visible) {
94 | for(NodeOWLClassTooltipType tooltipType : NodeOWLClassTooltipType.values()) {
95 | if(tooltipType.toString().equals(type.toString())) {
96 | tooltipType.setEnabled(visible);
97 | break;
98 | }
99 | }
100 | }
101 |
102 | private void typeIndividualVisibilityChanged(Object type, boolean visible) {
103 | for(NodeOWLIndividualTooltipType tooltipType : NodeOWLIndividualTooltipType.values()) {
104 | if(tooltipType.toString().equals(type.toString())) {
105 | tooltipType.setEnabled(visible);
106 | break;
107 | }
108 | }
109 | }
110 |
111 | public void loadTypes(final JPanel panel, Map items) {
112 | panel.removeAll();
113 | if (items.size() > 0) {
114 | // sort the types alphabetically
115 | TreeSet sortedTypes = new TreeSet();
116 | sortedTypes.addAll(items.keySet());
117 | for (Object type : sortedTypes) {
118 | boolean selected = items.get(type);
119 | FilterCheckBox checkbox = new FilterCheckBox(type, null, selected){
120 | private static final long serialVersionUID = -861175558062891232L;
121 |
122 | public void typeVisibilityChanged(Object type, boolean visible) {
123 | String title = ((TitledBorder)panel.getBorder()).getTitle();
124 | if(title.equals("Class Tooltip Options:")) {
125 | TooltipConfigurationDialog.this.typeVisibilityChanged(type, visible);
126 | }
127 | else {
128 | typeIndividualVisibilityChanged(type, visible);
129 | }
130 | }
131 | };
132 |
133 | panel.add(checkbox);
134 | }
135 | }
136 | this.invalidate();
137 | this.validate();
138 | this.repaint();
139 | }
140 |
141 | private JPanel getTypesPanel(String title) {
142 | //if (typesPanel == null) {
143 |
144 | JPanel typesPanel = new JPanel(new GridLayout(0, 1, 0, 1));
145 | typesPanel.setBorder(BorderFactory.createTitledBorder(title));
146 | typesPanel.setOpaque(false);
147 | //}
148 | return typesPanel;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/ui/OntoGrafFileFilter.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.ui;
2 |
3 | import java.io.File;
4 | import java.util.Enumeration;
5 | import java.util.Hashtable;
6 |
7 | import javax.swing.filechooser.FileFilter;
8 |
9 | /**
10 | * This class was copied and slightly modified from the Shrimp code base from UVic.
11 | *
12 | * A convenience implementation of FileFilter that filters out
13 | * all files except for those type extensions that it knows about.
14 | *
15 | * Example - create a new filter that filters out all files
16 | * but gif and jpg image files:
17 | *
18 | * JFileChooser chooser = new JFileChooser();
19 | * ShrimpFileFilter filter = new ShrimpFileFilter(
20 | * new String{"gif", "jpg"}, "JPEG and GIF Images")
21 | * chooser.addChoosableFileFilter(filter);
22 | * chooser.showOpenDialog(this);
23 | *
24 | * @version 1.8 08/26/98
25 | * @author Jeff Dinkins
26 | */
27 | public class OntoGrafFileFilter extends FileFilter implements java.io.FileFilter {
28 | private Hashtable filters = null;
29 | private String description = null;
30 | private String fullDescription = null;
31 | private boolean useExtensionsInDescription = true;
32 |
33 | /**
34 | * Creates a file filter. If no filters are added, then all
35 | * files are accepted.
36 | *
37 | * @see #addExtension
38 | */
39 | public OntoGrafFileFilter() {
40 | this.filters = new Hashtable();
41 | }
42 |
43 | /**
44 | * Creates a file filter that accepts files with the given extension.
45 | * Example: new ShrimpFileFilter("jpg");
46 | *
47 | * @see #addExtension
48 | */
49 | public OntoGrafFileFilter(String extension) {
50 | this(extension, null);
51 | }
52 |
53 | /**
54 | * Creates a file filter that accepts the given file type.
55 | * Example: new ShrimpFileFilter("jpg", "JPEG Image Images");
56 | *
57 | * Note that the "." before the extension is not needed. If
58 | * provided, it will be ignored.
59 | *
60 | * @see #addExtension
61 | */
62 | public OntoGrafFileFilter(String extension, String description) {
63 | this();
64 | if (extension != null)
65 | addExtension(extension);
66 | if (description != null)
67 | setDescription(description);
68 | }
69 |
70 | /**
71 | * Creates a file filter from the given string array.
72 | * Example: new ShrimpFileFilter(String {"gif", "jpg"});
73 | *
74 | * Note that the "." before the extension is not needed adn
75 | * will be ignored.
76 | *
77 | * @see #addExtension
78 | */
79 | public OntoGrafFileFilter(String[] filters) {
80 | this(filters, null);
81 | }
82 |
83 | /**
84 | * Creates a file filter from the given string array and description.
85 | * Example: new ShrimpFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
86 | *
87 | * Note that the "." before the extension is not needed and will be ignored.
88 | *
89 | * @see #addExtension
90 | */
91 | public OntoGrafFileFilter(String[] filters, String description) {
92 | this();
93 | for (int i = 0; i < filters.length; i++) {
94 | // add filters one by one
95 | addExtension(filters[i]);
96 | }
97 | if (description != null)
98 | setDescription(description);
99 | }
100 |
101 | /**
102 | * Return true if this file should be shown in the directory pane,
103 | * false if it shouldn't.
104 | *
105 | * Files that begin with "." are ignored.
106 | *
107 | * @see #getExtension
108 | */
109 | public boolean accept(File f) {
110 | if (f != null) {
111 | if (f.isDirectory()) {
112 | return true;
113 | }
114 | String extension = getExtension(f);
115 | if (extension != null && filters.get(getExtension(f)) != null) {
116 | return true;
117 | }
118 | }
119 | return false;
120 | }
121 |
122 | /**
123 | * Return the extension portion of the file's name .
124 | *
125 | * @see #getExtension
126 | * @see FileFilter#accept
127 | */
128 | public String getExtension(File f) {
129 | if (f != null) {
130 | String filename = f.getName();
131 | int i = filename.lastIndexOf('.');
132 | if (i > 0 && i < filename.length() - 1) {
133 | return filename.substring(i + 1).toLowerCase();
134 | }
135 | }
136 | return null;
137 | }
138 |
139 | /**
140 | * Adds a filetype "dot" extension to filter against.
141 | *
142 | * For example: the following code will create a filter that filters
143 | * out all files except those that end in ".jpg" and ".tif":
144 | *
145 | * ShrimpFileFilter filter = new ShrimpFileFilter();
146 | * filter.addExtension("jpg");
147 | * filter.addExtension("tif");
148 | *
149 | * Note that the "." before the extension is not needed and will be ignored.
150 | */
151 | public void addExtension(String extension) {
152 | if (filters == null) {
153 | filters = new Hashtable(5);
154 | }
155 | filters.put(extension.toLowerCase(), this);
156 | fullDescription = null;
157 | }
158 |
159 | /**
160 | * Returns the human readable description of this filter. For
161 | * example: "JPEG and GIF Image Files (*.jpg, *.gif)"
162 | *
163 | * @see #setDescription
164 | * @see #setExtensionListInDescription
165 | * @see #isExtensionListInDescription
166 | * @see FileFilter#getDescription
167 | */
168 | public String getDescription() {
169 | if (fullDescription == null) {
170 | if (description == null || isExtensionListInDescription()) {
171 | fullDescription = description == null ? "(" : description + " (";
172 | // build the description from the extension list
173 | Enumeration extensions = filters.keys();
174 | if (extensions != null) {
175 | fullDescription += "." + (String) extensions.nextElement();
176 | while (extensions.hasMoreElements()) {
177 | fullDescription += ", ." + extensions.nextElement();
178 | }
179 | }
180 | fullDescription += ")";
181 | } else {
182 | fullDescription = description;
183 | }
184 | }
185 | return fullDescription;
186 | }
187 |
188 | /**
189 | * Sets the human readable description of this filter. For
190 | * example: filter.setDescription("Gif and JPG Images");
191 | *
192 | * @see #setDescription
193 | * @see #setExtensionListInDescription
194 | * @see #isExtensionListInDescription
195 | */
196 | public void setDescription(String description) {
197 | this.description = description;
198 | fullDescription = null;
199 | }
200 |
201 | /**
202 | * Determines whether the extension list (.jpg, .gif, etc) should
203 | * show up in the human readable description.
204 | *
205 | * Only relevent if a description was provided in the constructor
206 | * or using setDescription();
207 | *
208 | * @see #getDescription
209 | * @see #setDescription
210 | * @see #isExtensionListInDescription
211 | */
212 | public void setExtensionListInDescription(boolean b) {
213 | useExtensionsInDescription = b;
214 | fullDescription = null;
215 | }
216 |
217 | /**
218 | * Returns whether the extension list (.jpg, .gif, etc) should
219 | * show up in the human readable description.
220 | *
221 | * Only relevent if a description was provided in the constructor
222 | * or using setDescription();
223 | *
224 | * @see #getDescription
225 | * @see #setDescription
226 | * @see #setExtensionListInDescription
227 | */
228 | public boolean isExtensionListInDescription() {
229 | return useExtensionsInDescription;
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/OntoGrafView.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Color;
5 | import java.awt.Cursor;
6 | import java.awt.Dimension;
7 | import java.awt.Font;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 | import java.awt.event.ComponentAdapter;
11 | import java.awt.event.ComponentEvent;
12 | import java.awt.event.KeyEvent;
13 | import java.awt.event.KeyListener;
14 |
15 | import javax.swing.Action;
16 | import javax.swing.JButton;
17 | import javax.swing.JComboBox;
18 | import javax.swing.JFrame;
19 | import javax.swing.JLabel;
20 | import javax.swing.JOptionPane;
21 | import javax.swing.JPanel;
22 | import javax.swing.JTextField;
23 | import javax.swing.JToggleButton;
24 | import javax.swing.JToolBar;
25 | import javax.swing.SwingUtilities;
26 |
27 | import org.protege.editor.owl.ui.view.cls.AbstractOWLClassViewComponent;
28 | import org.protege.ontograf.actions.ConfigTooltipsAction;
29 | import org.protege.ontograf.actions.ExportAsDotAction;
30 | import org.protege.ontograf.actions.ExportImageAction;
31 | import org.protege.ontograf.actions.OpenGraphAction;
32 | import org.protege.ontograf.actions.PinTooltipsAction;
33 | import org.protege.ontograf.actions.SaveGraphAction;
34 | import org.protege.ontograf.common.GraphController;
35 | import org.semanticweb.owlapi.model.OWLClass;
36 | import org.semanticweb.owlapi.model.OWLEntity;
37 |
38 | import ca.uvic.cs.chisel.cajun.graph.AbstractGraph;
39 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
40 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNodeCollectionEvent;
41 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNodeCollectionListener;
42 | import ca.uvic.cs.chisel.cajun.util.GradientPainter;
43 | import ca.uvic.cs.chisel.cajun.util.GradientPanel;
44 |
45 | /**
46 | * Plugin extension point for the OntoGraf view.
47 | *
48 | * @author seanf
49 | */
50 | public class OntoGrafView extends AbstractOWLClassViewComponent {
51 | private static final long serialVersionUID = -6969495880634875570L;
52 |
53 | private static final Color BACKGROUND_COLOR = new Color(0, 46, 123);
54 |
55 | // search modes available
56 | private static final String[] MODES = { GraphController.CONTAINS, GraphController.STARTS_WITH, GraphController.ENDS_WITH, GraphController.EXACT_MATCH, GraphController.REGEXP };
57 |
58 | // reference to the graph controller object, gives access to graph model and graph functions
59 | private GraphController graphController;
60 |
61 | // search related UI controls
62 | private JComboBox searchTypeBox;
63 | private JTextField searchField;
64 | private JLabel searchResults;
65 |
66 | // flag for cancelling updateView call, this is for managing synchronization between
67 | // the graph and the class tree
68 | private boolean cancelSelectionUpdate;
69 |
70 | private JPanel getSearchPanel() {
71 | JPanel searchPanel = new GradientPanel(GradientPanel.BG_START, BACKGROUND_COLOR.darker(), GradientPainter.TOP_TO_BOTTOM);
72 |
73 | JLabel searchLabel = new JLabel("Search:");
74 | searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
75 | searchLabel.setForeground(Color.white);
76 |
77 | searchField = new JTextField();
78 | searchField.setMinimumSize(new Dimension(300, 22));
79 | searchField.setSize(new Dimension(300, 22));
80 | searchField.setPreferredSize(new Dimension(300, 22));
81 | searchField.setFocusable(true);
82 | searchField.requestFocus();
83 |
84 | searchTypeBox = new JComboBox(MODES);
85 |
86 | JButton searchButton = new JButton("Search");
87 | searchButton.addActionListener(new ActionListener() {
88 | public void actionPerformed(ActionEvent e) {
89 | performSearch();
90 | }
91 | });
92 | searchButton.setMinimumSize(new Dimension(80, 22));
93 | searchButton.setSize(new Dimension(80, 22));
94 | searchButton.setPreferredSize(new Dimension(80, 22));
95 |
96 | searchField.addKeyListener(new KeyListener() {
97 | public void keyTyped(KeyEvent e) {}
98 | public void keyPressed(KeyEvent e) {}
99 |
100 | public void keyReleased(KeyEvent e) {
101 | if (e.getKeyCode() == KeyEvent.VK_ENTER) {
102 | performSearch();
103 | }
104 | }
105 | });
106 |
107 | JButton clearButton = new JButton("Clear");
108 | clearButton.addActionListener(new ActionListener() {
109 | public void actionPerformed(ActionEvent e) {
110 | graphController.clear();
111 | searchResults.setText("");
112 | }
113 | });
114 | clearButton.setMinimumSize(new Dimension(80, 22));
115 | clearButton.setSize(new Dimension(80, 22));
116 | clearButton.setPreferredSize(new Dimension(80, 22));
117 |
118 | searchResults = new JLabel();
119 | searchResults.setFont(searchResults.getFont().deriveFont(Font.BOLD));
120 | searchResults.setForeground(Color.white);
121 | searchResults.setOpaque(false);
122 |
123 | searchPanel.add(searchLabel);
124 | searchPanel.add(searchField);
125 | searchPanel.add(searchTypeBox);
126 | searchPanel.add(searchButton);
127 | searchPanel.add(clearButton);
128 | searchPanel.add(searchResults);
129 |
130 | return searchPanel;
131 | }
132 |
133 | private void performSearch() {
134 | if (searchField.getText().length() > 0) {
135 | this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
136 | int numOfResults = graphController.search(searchField.getText(), getSearchMode());
137 | searchResults.setText(numOfResults + " result(s) found.");
138 | this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
139 |
140 | syncNodeSelection();
141 | } else {
142 | JOptionPane.showMessageDialog(this, "You must enter a valid search term", "Invalid search term", JOptionPane.INFORMATION_MESSAGE);
143 | }
144 | }
145 |
146 | /**
147 | * When a node gets selected in the graph, we want to update the global class selection for Protege.
148 | */
149 | private void syncNodeSelection() {
150 | GraphNode node = ((AbstractGraph)graphController.getGraph()).getFirstSelectedNode();
151 | if(node != null) {
152 | cancelSelectionUpdate = true;
153 | setGlobalSelection((OWLEntity)node.getUserObject());
154 | }
155 | }
156 |
157 | private String getSearchMode() {
158 | return MODES[searchTypeBox.getSelectedIndex()];
159 | }
160 |
161 | @Override
162 | public void initialiseClassView() throws Exception {
163 | setLayout(new BorderLayout());
164 |
165 | this.addComponentListener(new ComponentAdapter() {
166 | @Override
167 | public void componentResized(ComponentEvent e) {
168 | // TODO Auto-generated method stub
169 | super.componentResized(e);
170 |
171 | }
172 | });
173 |
174 | graphController = new GraphController(this, this.getOWLEditorKit());
175 |
176 | graphController.getGraph().addNodeSelectionListener(new GraphNodeCollectionListener() {
177 | public void collectionChanged(GraphNodeCollectionEvent arg0) {
178 | syncNodeSelection();
179 | }
180 | });
181 |
182 | add(getSearchPanel(), BorderLayout.NORTH);
183 |
184 | initToolbar();
185 |
186 | Dimension d = new Dimension(800, 600);
187 | setPreferredSize(d);
188 | setSize(d);
189 | setLocation(100, 50);
190 |
191 | setVisible(true);
192 | }
193 |
194 | private void initToolbar() {
195 | JToolBar toolBar = graphController.getToolBar();
196 |
197 | JFrame mainWindow = (javax.swing.JFrame)SwingUtilities.windowForComponent(this);
198 |
199 | toolBar.addSeparator();
200 | toolBar.add(new ExportImageAction(mainWindow, graphController.getGraph().getCanvas()));
201 | toolBar.add(new ConfigTooltipsAction(mainWindow, graphController.getGraph().getCanvas()));
202 | toolBar.addSeparator();
203 | toolBar.add(new SaveGraphAction(mainWindow, graphController));
204 | toolBar.add(new OpenGraphAction(mainWindow, graphController));
205 | toolBar.addSeparator();
206 | toolBar.add(new ExportAsDotAction(mainWindow, graphController));
207 |
208 | Action action = new PinTooltipsAction(mainWindow, graphController);
209 | JToggleButton btn = new JToggleButton(action);
210 | btn.setText(null);
211 | btn.setToolTipText((String) action.getValue(Action.NAME));
212 |
213 | toolBar.add(btn);
214 | }
215 |
216 | @Override
217 | protected OWLClass updateView(OWLClass owlClass) {
218 | if(owlClass != null && !cancelSelectionUpdate) {
219 | graphController.showOWLClass(owlClass);
220 | }
221 |
222 | cancelSelectionUpdate = false;
223 |
224 | return null;
225 | }
226 |
227 | @Override
228 | public void disposeView() {
229 | // TODO Auto-generated method stub
230 |
231 | }
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | org.sonatype.oss
7 | oss-parent
8 | 7
9 |
10 |
11 | edu.stanford.protege
12 | ontograf
13 | 2.0.4-SNAPSHOT
14 | bundle
15 |
16 | OntoGraf
17 | A plug-in for the Protege Desktop ontology editor that allows visual, interactive navigation of the relationships in OWL ontologies.
18 | https://github.com/protegeproject/ontograf
19 |
20 |
21 | GNU Lesser General Public License
22 | http://www.gnu.org/copyleft/lesser.html
23 |
24 |
25 |
26 |
27 |
28 | Sean Falconer
29 | falconer.sean@gmail.com
30 |
31 |
32 |
33 |
34 |
35 |
36 | protege-user
37 | https://mailman.stanford.edu/mailman/listinfo/protege-user
38 | https://mailman.stanford.edu/mailman/listinfo/protege-user
39 | protege-user@lists.stanford.edu
40 | http://protege-project.136.n4.nabble.com/
41 |
42 | https://mailman.stanford.edu/pipermail/protege-user/
43 |
44 |
45 |
46 |
47 |
48 | protege-dev
49 | https://mailman.stanford.edu/mailman/listinfo/protege-dev
50 | https://mailman.stanford.edu/mailman/listinfo/protege-dev
51 | protege-dev@lists.stanford.edu
52 | http://protege-project.136.n4.nabble.com/
53 |
54 | https://mailman.stanford.edu/pipermail/protege-dev/
55 |
56 |
57 |
58 |
59 |
60 | scm:git:git@github.com:protegeproject/ontograf.git
61 | scm:git:git@github.com:protegeproject/ontograf.git
62 | https://github.com/protegeproject/ontograf
63 | HEAD
64 |
65 |
66 |
67 |
68 | edu.stanford.protege
69 | ca.uvic.cs.chisel.cajun
70 | 1.0.2
71 |
72 |
73 | edu.stanford.protege
74 | protege-editor-owl
75 | 5.0.0-RC1
76 |
77 |
78 |
79 |
80 |
81 |
82 | org.apache.maven.plugins
83 | maven-compiler-plugin
84 | 3.3
85 |
86 | 1.8
87 | 1.8
88 |
89 |
90 |
91 | org.apache.felix
92 | maven-bundle-plugin
93 | 2.5.3
94 | true
95 |
96 |
97 | org.protege.editor.owl.ProtegeOWL
98 | .
99 | org.protege.ontograf;singleton:=true
100 | The Protege Development Team
101 |
102 | ca.uvic.cs.chisel.cajun
103 |
104 |
105 | com.ibm.icu.*;resolution:=optional,
106 | org.eclipse.swt.*;resolution:=optional,
107 | org.eclipse.jface.*;resolution:=optional,
108 | org.protege.editor.core.*;version="5.0.0",
109 | org.protege.editor.owl.*;version="5.0.0",
110 | *
111 |
112 | plugin.xml, {maven-resources}
113 |
114 |
115 |
116 | bundle-manifest
117 | install
118 |
119 | manifest
120 |
121 |
122 |
123 |
124 |
125 |
126 | maven-eclipse-plugin
127 | 2.9
128 |
129 | true
130 |
131 |
132 |
133 | maven-release-plugin
134 | 2.5
135 |
136 |
137 | org.apache.maven.scm
138 | maven-scm-provider-gitexe
139 | 1.9
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | release
150 |
151 | false
152 |
153 |
154 |
155 |
156 | org.apache.maven.plugins
157 | maven-source-plugin
158 | 2.2.1
159 |
160 |
161 | attach-sources
162 |
163 | jar
164 |
165 |
166 |
167 |
168 |
169 | org.apache.maven.plugins
170 | maven-javadoc-plugin
171 | 2.10.3
172 |
173 |
174 | attach-javadocs
175 |
176 | jar
177 |
178 |
179 | false
180 | true
181 |
182 |
183 |
184 |
185 |
186 | org.apache.maven.plugins
187 | maven-gpg-plugin
188 | 1.6
189 |
190 |
191 | sign-artifacts
192 | verify
193 |
194 | sign
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/actions/ExportImageAction.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.actions;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Component;
5 | import java.awt.Dimension;
6 | import java.awt.Graphics;
7 | import java.awt.Point;
8 | import java.awt.Rectangle;
9 | import java.awt.image.BufferedImage;
10 | import java.io.File;
11 | import java.io.IOException;
12 |
13 | import javax.imageio.ImageIO;
14 | import javax.swing.Action;
15 | import javax.swing.JComponent;
16 | import javax.swing.JFileChooser;
17 | import javax.swing.JOptionPane;
18 | import javax.swing.JPanel;
19 | import javax.swing.JViewport;
20 | import javax.swing.filechooser.FileFilter;
21 |
22 | import org.protege.ontograf.common.util.IconConstants;
23 | import org.protege.ontograf.ui.OntoGrafFileFilter;
24 |
25 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
26 | import edu.umd.cs.piccolo.PCanvas;
27 |
28 | public class ExportImageAction extends CajunAction {
29 | private static final long serialVersionUID = 7241297162054742885L;
30 |
31 | private static final String ACTION_NAME = "Export Graph as Image";
32 |
33 | private JFileChooser fileChooser;
34 | private Component parent;
35 | private PCanvas canvas;
36 |
37 | // booleans indicating whether the different formats are available
38 | private boolean jpegAvailable;
39 | private boolean pngAvailable;
40 | private boolean gifAvailable;
41 |
42 | // file filters for showing only a given type of file in the file dialog
43 | private OntoGrafFileFilter pngFileFilter;
44 | private OntoGrafFileFilter gifFileFilter;
45 | private OntoGrafFileFilter jpegFileFilter;
46 |
47 | public ExportImageAction(Component parent, PCanvas canvas) {
48 | super(ACTION_NAME, IconConstants.ICON_EXPORT_IMAGE);
49 |
50 | putValue(Action.SHORT_DESCRIPTION, ACTION_NAME);
51 |
52 | this.parent = parent;
53 | this.canvas = canvas;
54 | this.fileChooser = new JFileChooser();
55 |
56 | String[] formats = ImageIO.getWriterFormatNames();
57 | String allFormats = "";
58 | for (int i = 0; i < formats.length; i++) {
59 | String format = formats[i];
60 | if (!jpegAvailable && (format.toLowerCase().equals("jpeg") || format.toLowerCase().equals("jpg"))) {
61 | jpegAvailable = true;
62 | allFormats += "JPG ";
63 | } else if (!pngAvailable && format.toLowerCase().equals("png")) {
64 | pngAvailable = true;
65 | allFormats += "PNG ";
66 | } else if (!gifAvailable && format.toLowerCase().equals("gif")) {
67 | gifAvailable = true;
68 | allFormats += "GIF";
69 | }
70 | }
71 |
72 | fileChooser.setDialogTitle("Export to Image File (" + allFormats + ")");
73 | //File dir = (lastDirectory != null ? lastDirectory : new File(System.getProperty("user.dir")));
74 | //chooser.setCurrentDirectory(dir);
75 | // chooser.setAcceptAllFileFilterUsed(true);
76 |
77 | if (pngAvailable) {
78 | pngFileFilter = new OntoGrafFileFilter(new String[] { "png" }, "PNG Images");
79 | fileChooser.addChoosableFileFilter(pngFileFilter);
80 | }
81 | if (gifAvailable) {
82 | gifFileFilter = new OntoGrafFileFilter(new String[] { "gif" }, "GIF Images");
83 | fileChooser.addChoosableFileFilter(gifFileFilter);
84 | }
85 | if (jpegAvailable) {
86 | jpegFileFilter = new OntoGrafFileFilter(new String[] { "jpg", "jpeg" }, "JPEG Images");
87 | fileChooser.addChoosableFileFilter(jpegFileFilter);
88 | }
89 | }
90 |
91 | @Override
92 | public void doAction() {
93 | int result = fileChooser.showSaveDialog(parent);
94 |
95 | if(result == JFileChooser.CANCEL_OPTION) return;
96 |
97 | File file = fileChooser.getSelectedFile();
98 | FileFilter fileFilter = fileChooser.getFileFilter();
99 | String filePath = file.toString();
100 | String formatName = "";
101 | if (jpegFileFilter != null && jpegFileFilter.equals(fileFilter)) {
102 | formatName = "jpg";
103 | if (!filePath.toLowerCase().endsWith(".jpg") && !filePath.toLowerCase().endsWith(".jpeg")) {
104 | filePath += ".jpg";
105 | file = new File(filePath);
106 | }
107 | }
108 | if (pngFileFilter != null && pngFileFilter.equals(fileFilter)) {
109 | formatName = "png";
110 | if (!filePath.toLowerCase().endsWith(".png")) {
111 | filePath += ".png";
112 | file = new File(filePath);
113 | }
114 | }
115 | if (gifFileFilter != null && gifFileFilter.equals(fileFilter)) {
116 | formatName = "gif";
117 | if (!filePath.toLowerCase().endsWith(".gif")) {
118 | filePath += ".gif";
119 | file = new File(filePath);
120 | }
121 | }
122 |
123 | boolean saveImage = false;
124 | if (file.exists()) {
125 | String msg = "The file " + file.toString() + " already exists.\nDo you want to overwrite this existing file?";
126 | int opt = JOptionPane.showConfirmDialog(parent, msg,
127 | "Export Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
128 | saveImage = (opt == JOptionPane.YES_OPTION);
129 | } else {
130 | try {
131 | file.createNewFile();
132 | saveImage = true;
133 | } catch (IOException e) {
134 | e.printStackTrace();
135 | String msg = "There was a problem creating " + file.toString() + ". The image has not been exported.";
136 | JOptionPane.showMessageDialog(parent, msg, "Export Error", JOptionPane.ERROR_MESSAGE);
137 | }
138 | }
139 |
140 | if (saveImage) {
141 | exportGraphAsImage(file, formatName);
142 | }
143 | }
144 |
145 | private void exportGraphAsImage(File file, String formatName) {
146 | boolean saved = false;
147 | // if the parent is a viewport then save the entire canvas, not just the visible part
148 | if (canvas.getParent() instanceof JViewport) {
149 | saved = saveViewport(file, formatName, canvas, (JViewport)canvas.getParent());
150 | } else {
151 | // save only the visible region of the canvas
152 | saved = paintComponent(canvas, file, formatName);
153 | }
154 | if (saved) {
155 | JOptionPane.showMessageDialog(parent,
156 | file.toString() + " has been saved successfully.");
157 | }
158 | }
159 |
160 | /**
161 | * Prompts the user to save the entire canvas or just the visible region.
162 | * If the entire canvas is selected then the canvas is removed from the viewport and resized, then
163 | * painted into the image and returned to the viewport.
164 | *
165 | * @return true if the image is saved
166 | */
167 | private boolean saveViewport(File file, String formatName, PCanvas canvas, JViewport viewport) {
168 | boolean saved = false;
169 |
170 | Dimension fullSize = viewport.getViewSize();
171 | Point viewPosition = viewport.getViewPosition();
172 |
173 | // ask the user if they want an image of the whole canvas or just the visible area
174 | // check if the canvas is smaller than the viewport view size
175 | if ((fullSize.width > canvas.getWidth()) || (fullSize.height > canvas.getHeight())) {
176 | String msg = "Do you want to save the visible region of the canvas " + dimToString(canvas.getSize()) +
177 | " or the entire canvas " + dimToString(fullSize) + "?\n" +
178 | "Warning: saving the entire canvas can cause an out of memory error if it is too large.";
179 | String[] options = new String[] { " Just The Visible Region ",
180 | " The Entire Canvas ", " Cancel " };
181 | int choice = JOptionPane.showOptionDialog(viewport,
182 | msg, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
183 | null, options, options[0]);
184 |
185 | if (choice == JOptionPane.CANCEL_OPTION) {
186 | // do nothing, false will be returned
187 | } else if (choice == JOptionPane.YES_OPTION) {
188 | // just save the visible region of the canvas
189 | saved = paintComponent(canvas, file, formatName);
190 | } else if (choice == JOptionPane.NO_OPTION) {
191 | // save the entire canvas, need to start in the top left corner
192 | viewport.setViewPosition(new Point(0, 0));
193 |
194 | JPanel fullPanel = new JPanel(new BorderLayout());
195 | fullPanel.add(canvas, BorderLayout.CENTER);
196 | Rectangle oldBounds = canvas.getBounds();
197 | // make this panel use the entire view
198 | fullPanel.setBounds(0, 0, fullSize.width, fullSize.height);
199 | // have to make the canvas use all the size
200 | canvas.setBounds(0, 0, fullSize.width, fullSize.height);
201 |
202 | saved = paintComponent(fullPanel, file, formatName);
203 |
204 | // restore the canvas as the original view with original position and bounds
205 | viewport.setView(canvas);
206 | viewport.setViewPosition(viewPosition);
207 | canvas.setBounds(oldBounds);
208 | }
209 | } else {
210 | // just save the visible region of the canvas
211 | saved = paintComponent(canvas, file, formatName);
212 | }
213 | return saved;
214 | }
215 |
216 | private boolean paintComponent(JComponent comp, File file, String formatName) {
217 | try {
218 | BufferedImage bufferedImage = new BufferedImage(comp.getWidth(), comp.getHeight(), BufferedImage.TYPE_INT_RGB);
219 | Graphics g = bufferedImage.getGraphics();
220 | comp.paint(g); // paint the canvas to the image
221 | ImageIO.write(bufferedImage, formatName, file);
222 | } catch (Throwable t) {
223 | // sometimes an out of memory error will occur!
224 | JOptionPane.showMessageDialog(parent,
225 | "There was a problem saving " + file.toString() +
226 | ". The image has not been exported.\nReason: " + t.getMessage(),
227 | "Export Error", JOptionPane.ERROR_MESSAGE);
228 | t.printStackTrace();
229 | return false;
230 | }
231 | return true;
232 | }
233 |
234 | private static String dimToString(Dimension d) {
235 | return "(" + d.width + "x" + d.height + ")";
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/GraphController.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 1998-2007, CHISEL Group, University of Victoria, Victoria, BC, Canada.
3 | * All rights reserved.
4 | */
5 | package org.protege.ontograf.common;
6 |
7 | import java.awt.BasicStroke;
8 | import java.awt.BorderLayout;
9 | import java.awt.Container;
10 | import java.awt.Stroke;
11 | import java.awt.event.ActionEvent;
12 | import java.util.ArrayList;
13 | import java.util.Collection;
14 | import java.util.HashSet;
15 | import java.util.List;
16 | import java.util.Set;
17 |
18 | import javax.swing.Action;
19 | import javax.swing.Icon;
20 | import javax.swing.JMenu;
21 | import javax.swing.JPopupMenu;
22 | import javax.swing.JToolBar;
23 | import javax.swing.event.PopupMenuEvent;
24 | import javax.swing.event.PopupMenuListener;
25 |
26 | import org.eclipse.zest.layouts.algorithms.DirectedGraphLayoutAlgorithm;
27 | import org.eclipse.zest.layouts.algorithms.HorizontalDirectedGraphLayoutAlgorithm;
28 | import org.eclipse.zest.layouts.progress.ProgressEvent;
29 | import org.eclipse.zest.layouts.progress.ProgressListener;
30 | import org.protege.editor.owl.OWLEditorKit;
31 | import org.protege.ontograf.common.util.IconConstants;
32 | import org.semanticweb.owlapi.model.OWLClass;
33 | import org.semanticweb.owlapi.model.OWLEntity;
34 |
35 | import ca.uvic.cs.chisel.cajun.actions.CajunAction;
36 | import ca.uvic.cs.chisel.cajun.actions.LayoutAction;
37 | import ca.uvic.cs.chisel.cajun.constants.LayoutConstants;
38 | import ca.uvic.cs.chisel.cajun.filter.FilterChangedEvent;
39 | import ca.uvic.cs.chisel.cajun.filter.FilterChangedListener;
40 | import ca.uvic.cs.chisel.cajun.graph.FlatGraph;
41 | import ca.uvic.cs.chisel.cajun.graph.Graph;
42 | import ca.uvic.cs.chisel.cajun.graph.arc.DefaultGraphArcStyle;
43 | import ca.uvic.cs.chisel.cajun.graph.arc.GraphArc;
44 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNode;
45 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNodeStyle;
46 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
47 | import ca.uvic.cs.chisel.cajun.graph.ui.DefaultFlatGraphView;
48 | import edu.umd.cs.piccolo.util.PBounds;
49 |
50 | /**
51 | * Controller for the graph and model elements. This controller ties the appropriate graph model
52 | * representation (Protege OWL) to the graph.
53 | *
54 | * @author seanf
55 | */
56 | public class GraphController {
57 | /** duration to animate the zoom in and zoom out */
58 | private static final int ANIMATION_DURATION = 700;
59 |
60 | /** the graph object, performs layouts and renders the model */
61 | private FlatGraph graph;
62 |
63 | /** the model representation of the graph, nodes and edges */
64 | private ProtegeGraphModel model;
65 |
66 | /** the panel that renders the graph view */
67 | private DefaultFlatGraphView view;
68 |
69 | private Action expandAction;
70 | private Action collapseAction;
71 | private Set expandBasedOnActions;
72 | public static final String REGEXP = "regexp";
73 | public static final String EXACT_MATCH = "exact match";
74 | public static final String ENDS_WITH = "ends with";
75 | public static final String STARTS_WITH = "starts with";
76 | public static final String CONTAINS = "contains";
77 |
78 | private OWLEntity owlClass;
79 |
80 | public GraphController(Container parentContainer, OWLEditorKit owlEditorKit) {
81 | model = new ProtegeGraphModel(owlEditorKit);
82 |
83 | this.graph = new FlatGraph(model);
84 | this.graph.setShowNodeTooltips(false);
85 |
86 | // show the plus icon for expandable nodes
87 | DefaultGraphNodeStyle nodeStyle = new DefaultGraphNodeStyle() {
88 | public Collection getOverlayIcons(GraphNode graphNode) {
89 | if (model.isExpandable(graphNode) && !model.isExpanded(graphNode)) {
90 | Collection icons = new ArrayList();
91 | icons.add(IconConstants.ICON_PLUS);
92 |
93 | return icons;
94 | }
95 |
96 | return null;
97 | }
98 | };
99 | nodeStyle.setNodeTypes(model.getNodeTypes());
100 | this.graph.setGraphNodeStyle(nodeStyle);
101 |
102 | // color the arcs based on arc type
103 | DefaultGraphArcStyle arcStyle = new DefaultGraphArcStyle() {
104 | public Stroke getStroke(GraphArc arc) {
105 | if (arc.getType().toString().contains(ProtegeGraphModel.DIRECT_SUBCLASS_SLOT_TYPE) || arc.getType().toString().contains(ProtegeGraphModel.DIRECT_INDIVIDUAL_SLOT_TYPE)) {
106 | setDashed(false);
107 | } else {
108 | setDashed(true);
109 | if (arc.getType().toString().contains("Equivalent")) {
110 | setDashedCapSquare(BasicStroke.CAP_ROUND);
111 | setDashWidth(2f);
112 | }
113 | else {
114 | setDashedCapSquare(BasicStroke.CAP_SQUARE);
115 | setDashWidth(10f);
116 | }
117 | }
118 |
119 | return super.getStroke(arc);
120 | }
121 | };
122 | arcStyle.setArcTypes(model.getArcTypes());
123 | this.graph.setGraphArcStyle(arcStyle);
124 |
125 | initialize(parentContainer);
126 |
127 | this.graph.addLayoutListener(new ProgressListener() {
128 | public void progressEnded(ProgressEvent arg0) {
129 | // make sure the node is visible
130 | DefaultGraphNode node = (DefaultGraphNode)model.getNode(owlClass);
131 | panTo(node);
132 | }
133 |
134 | public void progressStarted(ProgressEvent arg0) {}
135 | public void progressUpdated(ProgressEvent arg0) {}
136 | });
137 |
138 | this.graph.getFilterManager().addFilterChangedListener(new FilterChangedListener() {
139 | public void filtersChanged(FilterChangedEvent fce) {
140 | // have to update the relationship counts when a filter is applied
141 | model.resetNodeToArcCount();
142 | }
143 | });
144 | }
145 |
146 | public ProtegeGraphModel getModel() {
147 | return model;
148 | }
149 |
150 | public Graph getGraph() {
151 | return graph;
152 | }
153 |
154 | public void refresh() {
155 | graph.repaint();
156 | }
157 |
158 | public void clear() {
159 | graph.clear();
160 | model.clear();
161 | model.restrictToArcType = "";
162 | }
163 |
164 | public void display(OWLClass cls) {
165 | model.showNeighborhood(cls, true);
166 | graph.performLayout();
167 | }
168 |
169 | public void displayAsSingleNode(OWLEntity entity) {
170 | model.show(entity, graph.getFilterManager());
171 | graph.performLayout();
172 | }
173 |
174 | public JToolBar getToolBar() {
175 | return view.getToolBar();
176 | }
177 |
178 | /**
179 | * Performs a search on the ontology with the given string.
180 | *
181 | * @param searchString The entered string to search on
182 | * @param searchMode The search type mode that determines how to match the searchString
183 | */
184 | public int search(String searchString, String searchMode) {
185 | searchString = prepareSearchString(searchString, searchMode);
186 |
187 | for(GraphNode node : model.getAllNodes()) node.setSelected(false);
188 |
189 | Collection matchingNodes = new ArrayList();
190 | Collection extends OWLEntity> searchResults = model.search(searchString, graph.getFilterManager());
191 | for (OWLEntity owlEntity : searchResults) {
192 | GraphNode node = model.getNode(owlEntity);
193 | if(node != null) {
194 | matchingNodes.add(model.getNode(owlEntity));
195 | }
196 | }
197 |
198 | graph.setSelectedNodes(matchingNodes);
199 | graph.setMatchingNodes(matchingNodes);
200 | graph.performLayout();
201 |
202 | //model.recalculateArcTypes();
203 |
204 | return searchResults.size();
205 | }
206 |
207 | /**
208 | * Shows the class as a node and any arcs that exist between this new node and the
209 | * existing nodes on the canvas.
210 | *
211 | * @param owlClass
212 | */
213 | public void showOWLClass(OWLClass owlClass) {
214 | // set all the current nodes to a fixed location
215 | for(GraphNode node : model.getAllNodes()) {
216 | node.setFixedLocation(true);
217 | }
218 |
219 | boolean panToNode = true;
220 | if(model.getNode(owlClass) == null) {
221 | panToNode = false;
222 | }
223 |
224 | model.restrictToArcType = "";
225 | model.show(owlClass, graph.getFilterManager());
226 |
227 | Collection matchingNodes = new ArrayList();
228 | matchingNodes.add(model.getNode(owlClass));
229 |
230 | graph.setMatchingNodes(matchingNodes);
231 | graph.performLayout();
232 |
233 | // unset the fixed location on all nodes
234 | for(GraphNode node : model.getAllNodes()) {
235 | node.setFixedLocation(false);
236 | }
237 |
238 | this.owlClass = owlClass;
239 |
240 | if(panToNode) {
241 | // make sure the node is visible
242 | DefaultGraphNode node = (DefaultGraphNode)model.getNode(owlClass);
243 | panTo(node);
244 | }
245 | }
246 |
247 | private void panTo(DefaultGraphNode node) {
248 | if(node != null) {
249 | double x = node.getFullBoundsReference().getX();
250 | double y = node.getFullBoundsReference().getY();
251 | double w = node.getFullBoundsReference().getWidth();
252 | double h = node.getFullBoundsReference().getHeight();
253 | PBounds bounds = new PBounds(x - w * .01, y - h * .02, w + w * .02, h + h * .04);
254 | // only pan to the bounds if the node is not already visible
255 | if(!graph.getCamera().getViewBounds().contains(bounds.getBounds2D())) {
256 | graph.getRoot().getActivityScheduler().addActivity(
257 | graph.getCamera().animateViewToCenterBounds(bounds.getBounds2D(), false, ANIMATION_DURATION)
258 | );
259 | }
260 | }
261 | }
262 |
263 | /**
264 | * Adds appropriate query parameters to the searchString based on the selected searchMode.
265 | */
266 | private String prepareSearchString(String searchString, String searchMode) {
267 | if (searchMode.equals(CONTAINS)) {
268 | return searchString;
269 | } else if (searchMode.equals(STARTS_WITH)) {
270 | return "^" + searchString;
271 | } else if (searchMode.equals(ENDS_WITH)) {
272 | return searchString + "$";
273 | } else if(searchMode.equals(EXACT_MATCH)) {
274 | return "^" + searchString + "$";
275 | }
276 |
277 | return searchString;
278 | }
279 |
280 | private void initialize(Container parentContainer) {
281 | // setup the layouts
282 | List layoutRelTypes = new ArrayList();
283 | layoutRelTypes.add(ProtegeGraphModel.DIRECT_SUBCLASS_SLOT_TYPE);
284 | layoutRelTypes.add(ProtegeGraphModel.DIRECT_INDIVIDUAL_SLOT_TYPE);
285 | for (LayoutAction layoutAction : graph.getLayouts()) {
286 | if (layoutAction.getName().equals(LayoutConstants.LAYOUT_TREE_HORIZONTAL)) {
287 | layoutAction.setLayout(new HorizontalDirectedGraphLayoutAlgorithm());
288 | this.graph.setLastLayout(layoutAction);
289 | layoutAction.setLayoutRelTypes(layoutRelTypes);
290 | } else if (layoutAction.getName().equals(LayoutConstants.LAYOUT_TREE_VERTICAL)) {
291 | layoutAction.setLayout(new DirectedGraphLayoutAlgorithm());
292 | layoutAction.setLayoutRelTypes(layoutRelTypes);
293 | }
294 | }
295 |
296 | view = new DefaultFlatGraphView(graph);
297 |
298 | parentContainer.add(view, BorderLayout.CENTER);
299 |
300 | initNodeMenu(graph.getNodeContextMenu());
301 | graph.addInputEventListener(new ProtegeInputEventHandler(model, graph));
302 | }
303 |
304 | /**
305 | * Initializes the menu for the right-click operation on a graph node.
306 | *
307 | * @param graphMenu
308 | */
309 | private void initNodeMenu(JPopupMenu graphMenu) {
310 | graphMenu.add(new CajunAction("Show neighborhood", "Show neighborhood") {
311 | private static final long serialVersionUID = 4234994986788687910L;
312 |
313 | public void actionPerformed(ActionEvent e) {
314 | owlClass = (OWLEntity) graph.getFirstSelectedNode().getUserObject();
315 | model.showNeighborhood(owlClass, true);
316 | graph.performLayout();
317 | }
318 | });
319 |
320 | graphMenu.add(new CajunAction("Set as focus", "Set as focus") {
321 | private static final long serialVersionUID = -68720636770886830L;
322 |
323 | public void actionPerformed(ActionEvent e) {
324 | owlClass = (OWLEntity)graph.getFirstSelectedNode().getUserObject();
325 | model.hideAscendants(graph.getFirstSelectedNode());
326 | graph.performLayout();
327 | }
328 | });
329 |
330 | graphMenu.addSeparator();
331 |
332 | expandAction = new CajunAction("Expand", "Expand") {
333 | private static final long serialVersionUID = -8044342001264176639L;
334 |
335 | public void actionPerformed(ActionEvent e) {
336 | owlClass = (OWLEntity)graph.getFirstSelectedNode().getUserObject();
337 | model.expandNode(graph.getFirstSelectedNode());
338 | graph.performLayout();
339 | }
340 | };
341 |
342 | collapseAction = new CajunAction("Collapse", "Collapse") {
343 | private static final long serialVersionUID = 815274665395852446L;
344 |
345 | public void actionPerformed(ActionEvent e) {
346 | owlClass = (OWLEntity)graph.getFirstSelectedNode().getUserObject();
347 | model.collapseNode(graph.getFirstSelectedNode());
348 | graph.performLayout();
349 | }
350 | };
351 |
352 | graphMenu.add(expandAction);
353 | graphMenu.add(collapseAction);
354 | graphMenu.addSeparator();
355 |
356 | final JMenu expandBasedOnMenu = new JMenu("Expand on");
357 | graphMenu.add(expandBasedOnMenu);
358 |
359 | expandBasedOnActions = new HashSet();
360 | // initialize the actions with the defaults
361 | // for(Object o : model.getArcTypes()) {
362 | // Action action = getNodeExpansionAction(o.toString());
363 | // expandBasedOnActions.add(action);
364 | // expandBasedOnMenu.add(action);
365 | // }
366 |
367 | // add any new arc types
368 | // model.addGraphModelListener(new GraphModelAdapter() {
369 | // public void graphArcTypeAdded(Object arcType) {
370 | // Action action = getNodeExpansionAction(arcType.toString());
371 | // if(!expandBasedOnActions.contains(action)) {
372 | // expandBasedOnActions.add(action);
373 | // expandBasedOnMenu.add(action);
374 | // }
375 | // }
376 | // });
377 |
378 | graphMenu.add(expandBasedOnMenu);
379 |
380 | graphMenu.addPopupMenuListener(new PopupMenuListener() {
381 | public void popupMenuCanceled(PopupMenuEvent e) {}
382 | public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {}
383 |
384 | public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
385 | GraphNode node = graph.getFirstSelectedNode();
386 | if (node != null) {
387 | prepareNodeSpecificActions(node, expandBasedOnMenu);
388 | initNodeActionConditions(node);
389 | }
390 | }
391 |
392 | });
393 | }
394 |
395 | /**
396 | * Sets the expansion menu options enabled/disabled flag based on the current state of the
397 | * node. If the node has already been expanded, everything is disabled. Otherwise, all the
398 | * non-filtered arc types are enabled.
399 | * @param node
400 | */
401 | private void initNodeActionConditions(GraphNode node) {
402 | if (model.isExpanded(node)) {
403 | expandAction.setEnabled(false);
404 | for (Action action : expandBasedOnActions) {
405 | action.setEnabled(false);
406 | }
407 | } else {
408 | expandAction.setEnabled(true);
409 | for (Action action : expandBasedOnActions) {
410 | if(graph.getFilterManager().isArcTypeVisible(((CajunAction)action).getName())) {
411 | action.setEnabled(true);
412 | }
413 | else {
414 | action.setEnabled(false);
415 | }
416 | }
417 | }
418 | }
419 |
420 | /**
421 | * Uses the arc cache to get all the unique arc types for the given node.
422 | */
423 | private void prepareNodeSpecificActions(GraphNode node, JMenu expandBasedOnMenu) {
424 | expandBasedOnActions.clear();
425 | expandBasedOnMenu.removeAll();
426 | for(GraphArc arc : model.getCachedArcsForEntity((OWLEntity)node.getUserObject())) {
427 | Action action = getNodeExpansionAction(arc.getType().toString());
428 | if(!expandBasedOnActions.contains(action)) {
429 | expandBasedOnActions.add(action);
430 | expandBasedOnMenu.add(action);
431 | }
432 | }
433 | }
434 |
435 | private CajunAction getNodeExpansionAction(String arcType) {
436 | return new CajunAction(arcType, arcType) {
437 | private static final long serialVersionUID = -4658385618425759291L;
438 |
439 | public void actionPerformed(ActionEvent e) {
440 | model.expandNode(graph.getFirstSelectedNode(), e.getActionCommand());
441 | graph.performLayout();
442 | }
443 | };
444 | }
445 | }
446 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/util/OWLIconProviderImpl.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.common.util;
2 |
3 | import javax.swing.Icon;
4 |
5 | import org.protege.editor.owl.model.OWLModelManager;
6 | import org.protege.editor.owl.ui.OWLIcons;
7 | import org.protege.editor.owl.ui.renderer.OWLIconProvider;
8 | import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
9 | import org.semanticweb.owlapi.model.OWLAnnotationProperty;
10 | import org.semanticweb.owlapi.model.OWLAnnotationPropertyDomainAxiom;
11 | import org.semanticweb.owlapi.model.OWLAnnotationPropertyRangeAxiom;
12 | import org.semanticweb.owlapi.model.OWLAnonymousIndividual;
13 | import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom;
14 | import org.semanticweb.owlapi.model.OWLClass;
15 | import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
16 | import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
17 | import org.semanticweb.owlapi.model.OWLDataExactCardinality;
18 | import org.semanticweb.owlapi.model.OWLDataHasValue;
19 | import org.semanticweb.owlapi.model.OWLDataMaxCardinality;
20 | import org.semanticweb.owlapi.model.OWLDataMinCardinality;
21 | import org.semanticweb.owlapi.model.OWLDataOneOf;
22 | import org.semanticweb.owlapi.model.OWLDataProperty;
23 | import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
24 | import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom;
25 | import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom;
26 | import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
27 | import org.semanticweb.owlapi.model.OWLDatatype;
28 | import org.semanticweb.owlapi.model.OWLDatatypeDefinitionAxiom;
29 | import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
30 | import org.semanticweb.owlapi.model.OWLDifferentIndividualsAxiom;
31 | import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
32 | import org.semanticweb.owlapi.model.OWLDisjointDataPropertiesAxiom;
33 | import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom;
34 | import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom;
35 | import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
36 | import org.semanticweb.owlapi.model.OWLEquivalentDataPropertiesAxiom;
37 | import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom;
38 | import org.semanticweb.owlapi.model.OWLFunctionalDataPropertyAxiom;
39 | import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
40 | import org.semanticweb.owlapi.model.OWLHasKeyAxiom;
41 | import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
42 | import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
43 | import org.semanticweb.owlapi.model.OWLIrreflexiveObjectPropertyAxiom;
44 | import org.semanticweb.owlapi.model.OWLNamedIndividual;
45 | import org.semanticweb.owlapi.model.OWLNegativeDataPropertyAssertionAxiom;
46 | import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom;
47 | import org.semanticweb.owlapi.model.OWLObject;
48 | import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
49 | import org.semanticweb.owlapi.model.OWLObjectComplementOf;
50 | import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
51 | import org.semanticweb.owlapi.model.OWLObjectHasSelf;
52 | import org.semanticweb.owlapi.model.OWLObjectHasValue;
53 | import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
54 | import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
55 | import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
56 | import org.semanticweb.owlapi.model.OWLObjectOneOf;
57 | import org.semanticweb.owlapi.model.OWLObjectProperty;
58 | import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
59 | import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
60 | import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
61 | import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
62 | import org.semanticweb.owlapi.model.OWLObjectUnionOf;
63 | import org.semanticweb.owlapi.model.OWLOntology;
64 | import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom;
65 | import org.semanticweb.owlapi.model.OWLSameIndividualAxiom;
66 | import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
67 | import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
68 | import org.semanticweb.owlapi.model.OWLSubDataPropertyOfAxiom;
69 | import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
70 | import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
71 | import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom;
72 | import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
73 | import org.semanticweb.owlapi.search.EntitySearcher;
74 | import org.semanticweb.owlapi.util.OWLObjectVisitorAdapter;
75 |
76 | public class OWLIconProviderImpl extends OWLObjectVisitorAdapter implements OWLIconProvider {
77 |
78 | private Icon icon;
79 |
80 | private final Icon primitiveClassIcon = OWLIcons.getIcon("class.primitive.png");
81 |
82 | private final Icon definedClassIcon = OWLIcons.getIcon("class.defined.png");
83 |
84 | private final Icon objectPropertyIcon = OWLIcons.getIcon("property.object.png");
85 |
86 | private final Icon dataPropertyIcon = OWLIcons.getIcon("property.data.png");
87 |
88 | private final Icon annotationPropertyIcon = OWLIcons.getIcon("property.annotation.png");
89 |
90 | private final Icon individualIcon = OWLIcons.getIcon("individual.png");
91 |
92 | private final Icon dataTypeIcon = OWLIcons.getIcon("datarange.png");
93 |
94 | private final Icon ontologyIcon = OWLIcons.getIcon("ontology.png");
95 |
96 | private OWLModelManager owlModelManager;
97 |
98 | public OWLIconProviderImpl(OWLModelManager owlModelManager) {
99 | this.owlModelManager = owlModelManager;
100 | }
101 |
102 | public Icon getIcon() {
103 | return icon;
104 | }
105 |
106 | @Override
107 | public Icon getIcon(OWLObject owlObject) {
108 | try {
109 | icon = null;
110 | owlObject.accept(this);
111 | return icon;
112 | }
113 | catch (Exception e) {
114 | return null;
115 | }
116 | }
117 |
118 | @Override
119 | public void visit(OWLObjectIntersectionOf owlAnd) {
120 | icon = primitiveClassIcon;
121 | }
122 |
123 | @Override
124 | public void visit(OWLDatatype owlDatatype) {
125 | icon = dataTypeIcon;
126 | }
127 |
128 | @Override
129 | public void visit(OWLDataOneOf owlDataEnumeration) {
130 | icon = dataTypeIcon;
131 | }
132 |
133 |
134 | @Override
135 | public void visit(OWLDataAllValuesFrom owlDataAllRestriction) {
136 | icon = primitiveClassIcon;
137 | }
138 |
139 | @Override
140 | public void visit(OWLDataProperty owlDataProperty) {
141 | icon = dataPropertyIcon;
142 | }
143 |
144 | @Override
145 | public void visit(OWLDataSomeValuesFrom owlDataSomeValuesFrom) {
146 | icon = primitiveClassIcon;
147 | }
148 |
149 | @Override
150 | public void visit(OWLDataHasValue owlDataValueRestriction) {
151 | icon = primitiveClassIcon;
152 | }
153 |
154 | @Override
155 | public void visit(OWLDifferentIndividualsAxiom owlDifferentIndividualsAxiom) {
156 | icon = individualIcon;
157 | }
158 |
159 | @Override
160 | public void visit(OWLDisjointDataPropertiesAxiom owlDisjointDataPropertiesAxiom) {
161 | icon = dataPropertyIcon;
162 | }
163 |
164 | @Override
165 | public void visit(OWLFunctionalObjectPropertyAxiom axiom) {
166 | icon = objectPropertyIcon;
167 | }
168 |
169 | @Override
170 | public void visit(OWLDisjointObjectPropertiesAxiom axiom) {
171 | icon = objectPropertyIcon;
172 | }
173 |
174 | @Override
175 | public void visit(OWLInverseObjectPropertiesAxiom axiom) {
176 | icon = objectPropertyIcon;
177 | }
178 |
179 | @Override
180 | public void visit(OWLHasKeyAxiom owlHasKeyAxiom) {
181 | icon = primitiveClassIcon;
182 | }
183 |
184 | @Override
185 | public void visit(OWLDatatypeDefinitionAxiom owlDatatypeDefinitionAxiom) {
186 | icon = dataTypeIcon;
187 | }
188 |
189 | @Override
190 | public void visit(OWLInverseFunctionalObjectPropertyAxiom axiom) {
191 | icon = objectPropertyIcon;
192 | }
193 |
194 | @Override
195 | public void visit(OWLObjectPropertyDomainAxiom axiom) {
196 | icon = objectPropertyIcon;
197 | }
198 |
199 | @Override
200 | public void visit(OWLEquivalentObjectPropertiesAxiom owlEquivalentObjectPropertiesAxiom) {
201 | icon = objectPropertyIcon;
202 | }
203 |
204 | @Override
205 | public void visit(OWLNegativeDataPropertyAssertionAxiom owlNegativeDataPropertyAssertionAxiom) {
206 | icon = individualIcon;
207 | }
208 |
209 | @Override
210 | public void visit(OWLObjectPropertyRangeAxiom axiom) {
211 | icon = objectPropertyIcon;
212 | }
213 |
214 | @Override
215 | public void visit(OWLObjectPropertyAssertionAxiom owlObjectPropertyAssertionAxiom) {
216 | icon = individualIcon;
217 | }
218 |
219 | @Override
220 | public void visit(OWLSubObjectPropertyOfAxiom axiom) {
221 | icon = objectPropertyIcon;
222 | }
223 |
224 | @Override
225 | public void visit(OWLNamedIndividual owlIndividual) {
226 | icon = individualIcon;
227 | }
228 |
229 | @Override
230 | public void visit(OWLAnonymousIndividual individual) {
231 | icon = individualIcon;
232 | }
233 |
234 | @Override
235 | public void visit(OWLObjectAllValuesFrom owlObjectAllRestriction) {
236 | icon = primitiveClassIcon;
237 | }
238 |
239 | @Override
240 | public void visit(OWLObjectMinCardinality desc) {
241 | icon = primitiveClassIcon;
242 | }
243 |
244 | @Override
245 | public void visit(OWLObjectExactCardinality desc) {
246 | icon = primitiveClassIcon;
247 | }
248 |
249 | @Override
250 | public void visit(OWLObjectMaxCardinality desc) {
251 | icon = primitiveClassIcon;
252 | }
253 |
254 | @Override
255 | public void visit(OWLObjectHasSelf desc) {
256 | icon = primitiveClassIcon;
257 | }
258 |
259 | @Override
260 | public void visit(OWLDataMinCardinality desc) {
261 | icon = primitiveClassIcon;
262 | }
263 |
264 | @Override
265 | public void visit(OWLDataExactCardinality desc) {
266 | icon = primitiveClassIcon;
267 | }
268 |
269 | @Override
270 | public void visit(OWLDataMaxCardinality desc) {
271 | icon = primitiveClassIcon;
272 | }
273 |
274 | @Override
275 | public void visit(OWLObjectProperty owlObjectProperty) {
276 | icon = objectPropertyIcon;
277 | }
278 |
279 | @Override
280 | public void visit(OWLObjectSomeValuesFrom owlObjectSomeValuesFrom) {
281 | icon = primitiveClassIcon;
282 | }
283 |
284 | @Override
285 | public void visit(OWLObjectHasValue owlObjectValueRestriction) {
286 | icon = primitiveClassIcon;
287 | }
288 |
289 | @Override
290 | public void visit(OWLObjectComplementOf owlNot) {
291 | icon = primitiveClassIcon;
292 | }
293 |
294 | @Override
295 | public void visit(OWLOntology owlOntology) {
296 | icon = ontologyIcon;
297 | }
298 |
299 | @Override
300 | public void visit(OWLObjectUnionOf owlOr) {
301 | icon = primitiveClassIcon;
302 | }
303 |
304 | @Override
305 | public void visit(OWLDeclarationAxiom owlDeclarationAxiom) {
306 | owlDeclarationAxiom.getEntity().accept(this);
307 | }
308 |
309 | @Override
310 | public void visit(OWLSubClassOfAxiom owlSubClassAxiom) {
311 | icon = primitiveClassIcon;
312 | }
313 |
314 | @Override
315 | public void visit(OWLNegativeObjectPropertyAssertionAxiom owlNegativeObjectPropertyAssertionAxiom) {
316 | icon = individualIcon;
317 | }
318 |
319 | @Override
320 | public void visit(OWLAsymmetricObjectPropertyAxiom owlAntiSymmetricObjectPropertyAxiom) {
321 | icon = objectPropertyIcon;
322 | }
323 |
324 | @Override
325 | public void visit(OWLReflexiveObjectPropertyAxiom owlReflexiveObjectPropertyAxiom) {
326 | icon = objectPropertyIcon;
327 | }
328 |
329 | @Override
330 | public void visit(OWLDisjointClassesAxiom owlDisjointClassesAxiom) {
331 | icon = primitiveClassIcon;
332 | }
333 |
334 | @Override
335 | public void visit(OWLDataPropertyDomainAxiom owlDataPropertyDomainAxiom) {
336 | icon = dataPropertyIcon;
337 | }
338 |
339 | @Override
340 | public void visit(OWLDisjointUnionAxiom owlDisjointUnionAxiom) {
341 | icon = primitiveClassIcon;
342 | }
343 |
344 | @Override
345 | public void visit(OWLSymmetricObjectPropertyAxiom owlSymmetricObjectPropertyAxiom) {
346 | icon = objectPropertyIcon;
347 | }
348 |
349 | @Override
350 | public void visit(OWLDataPropertyRangeAxiom owlDataPropertyRangeAxiom) {
351 | icon = dataPropertyIcon;
352 | }
353 |
354 | @Override
355 | public void visit(OWLFunctionalDataPropertyAxiom owlFunctionalDataPropertyAxiom) {
356 | icon = dataPropertyIcon;
357 | }
358 |
359 | @Override
360 | public void visit(OWLEquivalentDataPropertiesAxiom owlEquivalentDataPropertiesAxiom) {
361 | icon = dataPropertyIcon;
362 | }
363 |
364 | @Override
365 | public void visit(OWLEquivalentClassesAxiom owlEquivalentClassesAxiom) {
366 | icon = primitiveClassIcon;
367 | }
368 |
369 | @Override
370 | public void visit(OWLDataPropertyAssertionAxiom owlDataPropertyAssertionAxiom) {
371 | icon = individualIcon;
372 | }
373 |
374 | @Override
375 | public void visit(OWLTransitiveObjectPropertyAxiom owlTransitiveObjectPropertyAxiom) {
376 | icon = objectPropertyIcon;
377 | }
378 |
379 | @Override
380 | public void visit(OWLIrreflexiveObjectPropertyAxiom owlIrreflexiveObjectPropertyAxiom) {
381 | icon = objectPropertyIcon;
382 | }
383 |
384 | @Override
385 | public void visit(OWLSubDataPropertyOfAxiom owlDataSubPropertyAxiom) {
386 | icon = dataPropertyIcon;
387 | }
388 |
389 | @Override
390 | public void visit(OWLSameIndividualAxiom owlSameIndividualsAxiom) {
391 | icon = individualIcon;
392 | }
393 |
394 | @Override
395 | public void visit(OWLClassAssertionAxiom owlClassAssertionAxiom) {
396 | icon = individualIcon;
397 | }
398 |
399 | @Override
400 | public void visit(OWLSubPropertyChainOfAxiom axiom) {
401 | icon = objectPropertyIcon;
402 | }
403 |
404 | @Override
405 | public void visit(OWLClass owlClass) {
406 | for (OWLOntology ont : owlModelManager.getActiveOntologies()) {
407 | if (EntitySearcher.isDefined(owlClass, ont)) {
408 | icon = definedClassIcon;
409 | return;
410 | }
411 | }
412 | icon = primitiveClassIcon;
413 | }
414 |
415 | @Override
416 | public void visit(OWLObjectOneOf owlEnumeration) {
417 | icon = primitiveClassIcon;
418 | }
419 |
420 | @Override
421 | public void visit(OWLAnnotationProperty owlAnnotationProperty) {
422 | icon = annotationPropertyIcon;
423 | }
424 |
425 | @Override
426 | public void visit(OWLAnnotationAssertionAxiom owlAnnotationAssertionAxiom) {
427 | icon = annotationPropertyIcon;
428 | }
429 |
430 | @Override
431 | public void visit(OWLSubAnnotationPropertyOfAxiom owlSubAnnotationPropertyOfAxiom) {
432 | icon = annotationPropertyIcon;
433 | }
434 |
435 | @Override
436 | public void visit(OWLAnnotationPropertyDomainAxiom owlAnnotationPropertyDomainAxiom) {
437 | icon = annotationPropertyIcon;
438 | }
439 |
440 | @Override
441 | public void visit(OWLAnnotationPropertyRangeAxiom owlAnnotationPropertyRangeAxiom) {
442 | icon = annotationPropertyIcon;
443 | }
444 | }
445 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/ui/FrameTooltipNode.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.ui;
2 |
3 | import java.awt.BasicStroke;
4 | import java.awt.Color;
5 | import java.awt.Font;
6 | import java.awt.Graphics2D;
7 | import java.awt.Paint;
8 | import java.awt.Rectangle;
9 | import java.awt.RenderingHints;
10 | import java.awt.Shape;
11 | import java.awt.Stroke;
12 | import java.awt.geom.Point2D;
13 | import java.awt.geom.Rectangle2D;
14 | import java.util.ArrayList;
15 | import java.util.Collection;
16 | import java.util.HashSet;
17 | import java.util.List;
18 | import java.util.Map;
19 | import java.util.Map.Entry;
20 | import java.util.Set;
21 |
22 | import org.protege.editor.owl.model.OWLModelManager;
23 | import org.protege.ontograf.common.util.NodeOWLClassTooltipType;
24 | import org.protege.ontograf.common.util.NodeOWLIndividualTooltipType;
25 | import org.semanticweb.owlapi.model.OWLAnnotation;
26 | import org.semanticweb.owlapi.model.OWLClass;
27 | import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
28 | import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
29 | import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
30 | import org.semanticweb.owlapi.model.OWLEntity;
31 | import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
32 | import org.semanticweb.owlapi.model.OWLIndividual;
33 | import org.semanticweb.owlapi.model.OWLLiteral;
34 | import org.semanticweb.owlapi.model.OWLObject;
35 | import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
36 | import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
37 | import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
38 | import org.semanticweb.owlapi.search.EntitySearcher;
39 |
40 | import ca.uvic.cs.chisel.cajun.graph.AbstractGraph;
41 | import edu.umd.cs.piccolo.PCamera;
42 | import edu.umd.cs.piccolo.PNode;
43 | import edu.umd.cs.piccolo.nodes.PText;
44 | import edu.umd.cs.piccolo.util.PBounds;
45 | import edu.umd.cs.piccolo.util.PPaintContext;
46 | import edu.umd.cs.piccolox.util.PFixedWidthStroke;
47 |
48 | public class FrameTooltipNode extends PNode {
49 | private static final long serialVersionUID = 1171088034485980559L;
50 |
51 | private static final Color BACKGROUND_COLOR = new Color(255, 255, 203);
52 |
53 | private static final int PADDING_X = 12;
54 | private static final int PADDING_Y = 6;
55 | protected static final int MAX_TEXT_CHARS = 75;
56 | protected static final int MAX_LINES = 3;
57 |
58 | private List textNodes;
59 |
60 | protected Stroke borderStroke;
61 |
62 | private OWLModelManager owlModelManager;
63 | private OWLEntity owlEntity;
64 |
65 | private boolean isCameraNode;
66 |
67 | public FrameTooltipNode(OWLModelManager owlModelManager, AbstractGraph graph, PNode owner, OWLEntity owlEntity) {
68 | borderStroke = new PFixedWidthStroke(1f);
69 |
70 | this.owlModelManager = owlModelManager;
71 | this.owlEntity = owlEntity;
72 |
73 | isCameraNode = true;
74 |
75 | initLocation(graph, owner);
76 | initText();
77 | adjustX(graph, owner);
78 |
79 | repaint();
80 | }
81 |
82 | public void updateLocation(AbstractGraph graph, PNode owner) {
83 | removeAllChildren();
84 |
85 | isCameraNode = false;
86 |
87 | initLocation(graph, owner);
88 | initText();
89 | adjustX(graph, owner);
90 |
91 | repaint();
92 | }
93 |
94 | public void setText(GraphTextNode textNode, String s) {
95 | if (s == null) {
96 | s = "";
97 | }
98 |
99 | textNode.setText(splitTextIntoLines(s, MAX_LINES, MAX_TEXT_CHARS));
100 | }
101 |
102 | /**
103 | * Moves the tooltip to the left if the owner is on the right hand side
104 | * of the screen.
105 | */
106 | private void adjustX(AbstractGraph graph, PNode owner) {
107 | Rectangle2D rect = owner.getBounds();
108 | if(isCameraNode) {
109 | rect = graph.getCamera().viewToLocal(owner.getBounds());
110 | }
111 |
112 | double maxX = graph.getWidth() / 3;
113 | maxX *= 2;
114 | if(getX() > maxX) {
115 | translate(-1 * (getWidth() + rect.getWidth()), 0);
116 | }
117 | }
118 |
119 | private void initText() {
120 | double x = getX() + 5, y = getY() + 5;
121 |
122 | textNodes = new ArrayList();
123 |
124 | Font font = PText.DEFAULT_FONT.deriveFont(10f);
125 |
126 | Point2D currentPos = new Point2D.Double(x, y);
127 |
128 | if(owlEntity instanceof OWLClass) {
129 | currentPos = initClassTooltips(currentPos, font);
130 | }
131 | else if(owlEntity instanceof OWLIndividual) {
132 | currentPos = initIndividualTooltips(currentPos, font);
133 | }
134 |
135 | updateBounds();
136 | }
137 |
138 | private Point2D createTitleText(Point2D currentPos, Font font) {
139 | textNodes.add(createTextNode(currentPos.getX(), currentPos.getY(), owlModelManager.getRendering(owlEntity), font));
140 | double y = currentPos.getY() + textNodes.get(textNodes.size()-1).getHeight() + 2;
141 |
142 | return new Point2D.Double(currentPos.getX(), y);
143 | }
144 |
145 | private Point2D createURIText(Point2D currentPos, Font font) {
146 | double x = currentPos.getX();
147 | double y = currentPos.getY();
148 | textNodes.add(createTextNode(x, y, "URI:", font.deriveFont(Font.BOLD)));
149 | x += textNodes.get(textNodes.size()-1).getWidth() + 5;
150 | textNodes.add(createTextNode(x, y, owlEntity.getIRI().toString(), font));
151 |
152 | y += textNodes.get(textNodes.size()-1).getHeight() + 2;
153 | x = textNodes.get(0).getX();
154 |
155 | return new Point2D.Double(x, y);
156 | }
157 |
158 | private Point2D initIndividualTooltips(Point2D currentPos, Font font) {
159 | OWLIndividual individual = (OWLIndividual)owlEntity;
160 |
161 | if(NodeOWLIndividualTooltipType.TITLE.isEnabled()) {
162 | currentPos = createTitleText(currentPos, font);
163 | }
164 |
165 | if(NodeOWLIndividualTooltipType.URI.isEnabled()) {
166 | currentPos = createURIText(currentPos, font);
167 | }
168 |
169 | if(NodeOWLIndividualTooltipType.DIFFERENT_INDIVIDUALS.isEnabled()) {
170 | Collection individuals = EntitySearcher
171 | .getDifferentIndividuals(individual,
172 | owlModelManager.getActiveOntology());
173 | if(individuals.size() > 0) {
174 | currentPos = addCollectionTextValues(individuals, "Different individuals:", font, currentPos);
175 | }
176 | }
177 |
178 | if(NodeOWLIndividualTooltipType.SAME_INDIVIDUALS.isEnabled()) {
179 | Collection individuals = EntitySearcher
180 | .getSameIndividuals(individual,
181 | owlModelManager.getActiveOntology());
182 | if(individuals.size() > 0) {
183 | currentPos = addCollectionTextValues(individuals, "Same individuals:", font, currentPos);
184 | }
185 | }
186 |
187 | if(NodeOWLIndividualTooltipType.OBJECT_PROPERTY_ASSERTIONS.isEnabled()) {
188 | Set properties = owlModelManager.getActiveOntology().getObjectPropertyAssertionAxioms(individual);
189 | if(properties.size() > 0) {
190 | currentPos = addCollectionTextValues(properties, "Object property assertions:", font, currentPos);
191 | }
192 | }
193 |
194 | if(NodeOWLIndividualTooltipType.DATA_PROPERTY_ASSERTIONS.isEnabled()) {
195 | Set dataProperties = owlModelManager.getActiveOntology().getDataPropertyAssertionAxioms(individual);
196 | if(dataProperties.size() > 0) {
197 | currentPos = addCollectionTextValues(dataProperties, "Data property assertions:", font, currentPos);
198 | }
199 | }
200 |
201 | if(NodeOWLIndividualTooltipType.NEGATIVE_DATA_PROPERTY_ASSERTIONS.isEnabled()) {
202 | Map> map = EntitySearcher
203 | .getNegativeDataPropertyValues(individual,
204 | owlModelManager.getActiveOntology()).asMap();
205 | Set negativeDataProperties = new HashSet();
206 | for (Entry> entry : map
207 | .entrySet()) {
208 | String property = owlModelManager.getRendering(entry.getKey());
209 | for(OWLLiteral literal : entry.getValue()) {
210 | property += " " + owlModelManager.getRendering(literal);
211 | }
212 | negativeDataProperties.add(property);
213 | }
214 |
215 | if(negativeDataProperties.size() > 0) {
216 | currentPos = addStringValues(negativeDataProperties, "Negative data property assertions:", font, currentPos);
217 | }
218 | }
219 |
220 |
221 | if(NodeOWLIndividualTooltipType.NEGATIVE_OBJECT_PROPERTY_ASSERTIONS.isEnabled()) {
222 | Map> negativeObjectPropertiesMap = EntitySearcher
223 | .getNegativeObjectPropertyValues(individual,
224 | owlModelManager.getActiveOntology()).asMap();
225 | Set negativeObjectProperties = new HashSet();
226 | for (Entry> entry : negativeObjectPropertiesMap
227 | .entrySet()) {
228 | String property = owlModelManager.getRendering(entry.getKey());
229 | for(OWLIndividual owlIndividual : entry.getValue()) {
230 | property += " " + owlModelManager.getRendering(owlIndividual);
231 | }
232 | negativeObjectProperties.add(property);
233 | }
234 |
235 | if(negativeObjectProperties.size() > 0) {
236 | currentPos = addStringValues(negativeObjectProperties, "Negative object property assertions:", font, currentPos);
237 | }
238 | }
239 |
240 | if(NodeOWLIndividualTooltipType.ANNOTATIONS.isEnabled()) {
241 | Collection annotations = EntitySearcher
242 | .getAnnotations(owlEntity,
243 | owlModelManager.getActiveOntology());
244 | if(annotations.size() > 0) {
245 | currentPos = addCollectionTextValues(annotations, "Annotations:", font, currentPos);
246 | }
247 | }
248 |
249 | return currentPos;
250 | }
251 |
252 | private Point2D initClassTooltips(Point2D currentPos, Font font) {
253 | if(NodeOWLClassTooltipType.TITLE.isEnabled()) {
254 | currentPos = createTitleText(currentPos, font);
255 | }
256 |
257 | if(NodeOWLClassTooltipType.URI.isEnabled()) {
258 | currentPos = createURIText(currentPos, font);
259 | }
260 |
261 | if(NodeOWLClassTooltipType.SUPERCLASSES.isEnabled()) {
262 | Set superClasses = owlModelManager.getActiveOntology().getSubClassAxiomsForSubClass((OWLClass)owlEntity);
263 | if(superClasses.size() > 0) {
264 | currentPos = addCollectionTextValues(superClasses, "Superclasses:", font, currentPos);
265 | }
266 | }
267 |
268 | if(NodeOWLClassTooltipType.EQUIVALENT_CLASSES.isEnabled()) {
269 | Set equivalentAxioms = owlModelManager.getActiveOntology().getEquivalentClassesAxioms((OWLClass)owlEntity);
270 | if(equivalentAxioms.size() > 0) {
271 | currentPos = addCollectionTextValues(equivalentAxioms, "Equivalent classes:", font, currentPos);
272 | }
273 | }
274 |
275 | if(NodeOWLClassTooltipType.DISJOINT_CLASSES.isEnabled()) {
276 | Set disjointAxioms = owlModelManager.getActiveOntology().getDisjointClassesAxioms((OWLClass)owlEntity);
277 | if(disjointAxioms.size() > 0) {
278 | currentPos = addCollectionTextValues(disjointAxioms, "Disjoint classes:", font, currentPos);
279 | }
280 | }
281 |
282 | if(NodeOWLClassTooltipType.ANNOTATIONS.isEnabled()) {
283 | Collection annotations = EntitySearcher
284 | .getAnnotations(owlEntity,
285 | owlModelManager.getActiveOntology());
286 | if(annotations.size() > 0) {
287 | currentPos = addCollectionTextValues(annotations, "Annotations:", font, currentPos);
288 | }
289 | }
290 |
291 | return currentPos;
292 | }
293 |
294 | private Point2D addStringValues(Set entities, String title, Font font, Point2D point) {
295 | double x = point.getX();
296 | double y = point.getY();
297 | textNodes.add(createTextNode(x, y, title, font.deriveFont(Font.BOLD)));
298 | y += textNodes.get(textNodes.size()-1).getHeight() + 2;
299 | x += 10;
300 | for(String entry : entities) {
301 | textNodes.add(createTextNode(x, y, entry, font));
302 | y += textNodes.get(textNodes.size()-1).getHeight() + 2;
303 | }
304 |
305 | return new Point2D.Double(x-10, y);
306 | }
307 |
308 | private Point2D addCollectionTextValues(
309 | Collection extends OWLObject> entities, String title, Font font,
310 | Point2D point) {
311 | double x = point.getX();
312 | double y = point.getY();
313 | textNodes.add(createTextNode(x, y, title, font.deriveFont(Font.BOLD)));
314 | y += textNodes.get(textNodes.size()-1).getHeight() + 2;
315 | x += 10;
316 | for(OWLObject annotation : entities) {
317 | textNodes.add(createTextNode(x, y, owlModelManager.getRendering(annotation), font));
318 | y += textNodes.get(textNodes.size()-1).getHeight() + 2;
319 | }
320 |
321 | return new Point2D.Double(x-10, y);
322 | }
323 |
324 | private GraphTextNode createTextNode(double x, double y, String text, Font font) {
325 | GraphTextNode textNode = new GraphTextNode();
326 | // make this node match the text size
327 | textNode.setConstrainWidthToTextWidth(true);
328 | textNode.setConstrainHeightToTextHeight(true);
329 | textNode.setPickable(false);
330 | textNode.setFont(font);
331 | addChild(textNode);
332 | setText(textNode, text);
333 | textNode.setX(x);
334 | textNode.setY(y);
335 |
336 | return textNode;
337 | }
338 |
339 | /**
340 | * Sets the tooltip location relative the owner's position in the global coordinate system.
341 | */
342 | private void initLocation(AbstractGraph graph, PNode owner) {
343 | PCamera camera = graph.getCanvas().getCamera();
344 | Rectangle bounds = graph.getCanvas().getBounds();
345 |
346 | Rectangle2D rect = owner.getBounds(); //camera.viewToLocal(owner.getBounds());
347 | if(isCameraNode) {
348 | rect = camera.viewToLocal(owner.getBounds());
349 | }
350 |
351 | double x = rect.getX();
352 | double y = rect.getY();
353 |
354 | x += rect.getWidth();
355 | x = Math.min(x, bounds.getWidth() - getWidth());
356 |
357 | y = Math.max(y, 0);
358 |
359 | setX(x);
360 | setY(y);
361 | }
362 |
363 | /**
364 | * Restricts the number of characters in the text node. If the string is too long it is chopped
365 | * and appended with "...".
366 | *
367 | * @param text the string to possibly elide
368 | * @return the elided string, or the original if text isn't longer than the max allowed chars
369 | */
370 | protected String elideText(String text, int maxCharsPerLine) {
371 | if (text.length() > maxCharsPerLine) {
372 | return new String(text.substring(0, maxCharsPerLine).trim() + "...");
373 | }
374 | return text;
375 | }
376 |
377 | /**
378 | * Splits the text into lines. Attempts to split at word breaks if possible. Also puts a cap on
379 | * the max number of lines.
380 | */
381 | protected String splitTextIntoLines(String text, int maxLines, int maxCharsPerLine) {
382 | text = text.trim();
383 | StringBuffer buffer = new StringBuffer(text.length() + 10);
384 | if (text.length() > maxCharsPerLine) {
385 | int lines = 0;
386 | while (text.length() > 0 && lines < maxLines) {
387 | // base case #1 - text is short
388 | if (text.length() < maxCharsPerLine) {
389 | buffer.append(text);
390 | break;
391 | }
392 | // base case #2 - added max lines
393 | if (lines + 1 == maxLines) {
394 | // elide the remaining text (s) instead of just the current line
395 | buffer.append(elideText(text, maxCharsPerLine));
396 | break;
397 | }
398 |
399 | // find a space and break on it
400 | int end = findWhiteSpace(text, maxCharsPerLine);
401 | if (end == -1) {
402 | end = Math.min(text.length(), maxCharsPerLine);
403 | }
404 | String line = text.substring(0, end).trim();
405 | if (line.length() == 0) {
406 | break;
407 | }
408 |
409 | buffer.append(line);
410 | buffer.append('\n');
411 | lines++;
412 | text = text.substring(end).trim();
413 | }
414 | return buffer.toString().trim();
415 | }
416 | return text;
417 | }
418 |
419 | private int findWhiteSpace(String s, int end) {
420 | int ws = -1;
421 | // look 2 characters past the end for a space character
422 | // and work backwards
423 | for (int i = Math.min(s.length() - 1, end + 2); i >= 0; i--) {
424 | if (Character.isWhitespace(s.charAt(i))) {
425 | ws = i;
426 | break;
427 | }
428 | }
429 | return ws;
430 | }
431 |
432 | /**
433 | * Sets the bounds of this node based on the text size. Takes into consideration the
434 | * maximum node width too.
435 | */
436 | private void updateBounds() {
437 | double w = 0, minY = Double.MAX_VALUE, maxY = 0;
438 | double h = 0;
439 | for(GraphTextNode textNode : textNodes) {
440 | PBounds textBounds = textNode.getBounds();
441 | w = Math.max(w, 3 * PADDING_X + textBounds.getWidth());
442 | minY = Math.min(minY, textBounds.getY());
443 | if(maxY < textBounds.getY()) {
444 | maxY = textBounds.getY();
445 | h = textBounds.getHeight();
446 | }
447 | maxY = Math.max(maxY, textBounds.getY());
448 | }
449 |
450 | h += maxY - minY + PADDING_Y;
451 | setBounds(getX(), getY(), w, h);
452 | }
453 |
454 | @Override
455 | public boolean setBounds(double x, double y, double width, double height) {
456 | // TODO handle maximum width?
457 | boolean changed = super.setBounds(x, y, width, height);
458 |
459 | if (changed) {
460 | invalidatePaint();
461 | }
462 | return changed;
463 | }
464 |
465 | private static Color getMixedColor(Color c1, float pct1, Color c2, float pct2) {
466 | float[] clr1 = c1.getComponents(null);
467 | float[] clr2 = c2.getComponents(null);
468 | for (int i = 0; i < clr1.length; i++) {
469 | clr1[i] = clr1[i] * pct1 + clr2[i] * pct2;
470 | }
471 | return new Color(clr1[0], clr1[1], clr1[2], clr1[3]);
472 | }
473 |
474 | private void paintBorderShadow(Graphics2D g2, int shadowWidth, Shape shape) {
475 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
476 | RenderingHints.VALUE_ANTIALIAS_ON);
477 | int sw = shadowWidth*2;
478 | for (int i=sw; i >= 2; i-=2) {
479 | float pct = (float)(sw - i) / (sw - 1);
480 | g2.setColor(getMixedColor(Color.LIGHT_GRAY, pct,
481 | Color.WHITE, 1.0f-pct));
482 | g2.setStroke(new BasicStroke(i));
483 | g2.draw(shape);
484 | }
485 | }
486 |
487 | @Override
488 | protected void paint(PPaintContext paintContext) {
489 | Graphics2D g2 = paintContext.getGraphics();
490 |
491 | Shape shape = getBounds();
492 |
493 | g2.setPaint(BACKGROUND_COLOR);
494 |
495 | Rectangle r = shape.getBounds();
496 | g2.fillRect(r.x, r.y, r.width, r.height);
497 |
498 | paintBorderShadow(g2, 2, shape);
499 |
500 | g2.setPaint(Color.black);
501 | g2.setStroke(borderStroke);
502 | g2.draw(shape);
503 | }
504 |
505 | class GraphTextNode extends PText {
506 | private static final long serialVersionUID = -871571524212274580L;
507 |
508 | private boolean ignoreInvalidatePaint = false;
509 |
510 | // @Override
511 | // public Font getFont() {
512 | // Font font = PText.DEFAULT_FONT;
513 | // if (font == null) {
514 | // font = DEFAULT_FONT;
515 | // }
516 | // return font;
517 | // }
518 |
519 | @Override
520 | public Paint getTextPaint() {
521 | Paint paint = Color.black;
522 | if (paint == null) {
523 | paint = Color.black;
524 | }
525 | return paint;
526 | }
527 |
528 | @Override
529 | protected void paint(PPaintContext paintContext) {
530 | // update the text paint - the super paint method doesn't call our getTextPaint() method
531 | Paint p = getTextPaint();
532 | if (!p.equals(super.getTextPaint())) {
533 | ignoreInvalidatePaint = true;
534 | setTextPaint(getTextPaint());
535 | ignoreInvalidatePaint = false;
536 | }
537 | // the font is never set in the super paint class?
538 | paintContext.getGraphics().setFont(getFont());
539 | super.paint(paintContext);
540 | }
541 |
542 | @Override
543 | public void invalidatePaint() {
544 | if (!ignoreInvalidatePaint) {
545 | super.invalidatePaint();
546 | }
547 | }
548 | }
549 | }
550 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/ontograf/common/ProtegeGraphModel.java:
--------------------------------------------------------------------------------
1 | package org.protege.ontograf.common;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.HashMap;
6 | import java.util.HashSet;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.Map.Entry;
10 | import java.util.Set;
11 | import java.util.regex.Pattern;
12 |
13 | import javax.swing.Icon;
14 |
15 | import org.protege.editor.owl.OWLEditorKit;
16 | import org.protege.editor.owl.model.OWLModelManager;
17 | import org.protege.ontograf.common.util.OWLIconProviderImpl;
18 | import org.semanticweb.owlapi.model.AxiomType;
19 | import org.semanticweb.owlapi.model.ClassExpressionType;
20 | import org.semanticweb.owlapi.model.IRI;
21 | import org.semanticweb.owlapi.model.OWLAxiom;
22 | import org.semanticweb.owlapi.model.OWLClass;
23 | import org.semanticweb.owlapi.model.OWLClassExpression;
24 | import org.semanticweb.owlapi.model.OWLEntity;
25 | import org.semanticweb.owlapi.model.OWLIndividual;
26 | import org.semanticweb.owlapi.model.OWLNamedIndividual;
27 | import org.semanticweb.owlapi.model.OWLObjectProperty;
28 | import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
29 | import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
30 | import org.semanticweb.owlapi.model.OWLOntology;
31 | import org.semanticweb.owlapi.model.OWLQuantifiedRestriction;
32 | import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
33 | import org.semanticweb.owlapi.search.EntitySearcher;
34 |
35 | import ca.uvic.cs.chisel.cajun.filter.FilterManager;
36 | import ca.uvic.cs.chisel.cajun.graph.DefaultGraphModel;
37 | import ca.uvic.cs.chisel.cajun.graph.arc.DefaultGraphArc;
38 | import ca.uvic.cs.chisel.cajun.graph.arc.GraphArc;
39 | import ca.uvic.cs.chisel.cajun.graph.node.DefaultGraphNode;
40 | import ca.uvic.cs.chisel.cajun.graph.node.GraphNode;
41 |
42 | /**
43 | * Graph model representation of Protege OWL API. Converts OWL relationships and entities
44 | * into GraphArc's and GraphNode's.
45 | *
46 | * @author seanf
47 | */
48 | public class ProtegeGraphModel extends DefaultGraphModel {
49 | /** Protege specific relationships */
50 | protected static final String DIRECT_SUBCLASS_SLOT_TYPE = "has subclass";
51 | protected static final String DIRECT_INDIVIDUAL_SLOT_TYPE = "has individual";
52 | protected static final String SUFFIX_DOMAIN_RANGE = " (Domain>Range)";
53 | protected static final String SUB_CLASS_SOME_VALUE_OF = "(Subclass some)";
54 | protected static final String SUB_CLASS_ALL_VALUES = "(Subclass all)";
55 | protected static final String EQUIVALENT_CLASS_SOME_VALUE_OF = "(Equivalent class some)";
56 | protected static final String EQUIVALENT_CLASS_ALL_VALUES = "(Equivalent class all)";
57 |
58 | /** Protege specific node types */
59 | protected static final String UNKNOWN_ART_TYPE = "unknown";
60 | protected static final String CLASS_ART_TYPE = "class";
61 | protected static final String INDIVIDUAL_ART_TYPE = "individual";
62 |
63 | /** used to restrict an expansion to a specific arc type */
64 | protected String restrictToArcType;
65 |
66 | /** map to store the number of arcs associated with a given frame object */
67 | private Map> frameToArcCount;
68 |
69 | /** collections for caching frame to arc relationships based on reified relationships */
70 | private Map> artifactToUnreifiedRels;
71 |
72 | /** set of domain/range constraints for the OWL file */
73 | private Set domainRangeRelsBuffer;
74 |
75 | /** current set of arc types available */
76 | private Collection arcTypes;
77 |
78 | private Set owlOntologies;
79 | private OWLModelManager owlModelManager;
80 | private OWLEditorKit owlEditorKit;
81 |
82 | private FilterManager filterManager;
83 |
84 | public ProtegeGraphModel(OWLEditorKit owlEditorKit) {
85 | super();
86 |
87 | owlModelManager = owlEditorKit.getModelManager();
88 | this.owlEditorKit = owlEditorKit;
89 | owlOntologies = owlModelManager.getActiveOntologies();
90 |
91 | frameToArcCount = new HashMap>();
92 | }
93 |
94 | public OWLModelManager getOwlModelManager() {
95 | return owlModelManager;
96 | }
97 |
98 | /**
99 | * Adds the entity as a node and adds any arcs that exist between this new node and the
100 | * existing nodes on the canvas.
101 | *
102 | * @param entity
103 | */
104 | public void show(OWLEntity entity, FilterManager filterManager) {
105 | this.filterManager = filterManager;
106 |
107 | List arcs = new ArrayList();
108 |
109 | addNode(entity);
110 |
111 | arcs.addAll(createIncomingRelationships(entity, true));
112 | arcs.addAll(createOutgoingRelationships(entity, true));
113 |
114 | addArcsToModel(arcs, false);
115 | recalculateArcStyles();
116 | }
117 |
118 | /**
119 | * Shows the neighborhood for a given Frame.
120 | *
121 | * @param entity The entity object to get the neighborhood for.
122 | * @param removeOldNodes True if current visible nodes should be removed.
123 | */
124 | public void showNeighborhood(OWLEntity entity, boolean removeOldNodes) {
125 | List singleItemList = new ArrayList(1);
126 | singleItemList.add(entity);
127 |
128 | showNeighborhood(singleItemList, removeOldNodes);
129 | }
130 |
131 | /**
132 | * Shows the neighborhood for a collection of Frame objects.
133 | *
134 | * @param nodes The collection of OWLEntity objects to get the neighborhood for.
135 | * @param removeOldNodes True if current visible nodes should be removed.
136 | */
137 | public void showNeighborhood(Collection extends OWLEntity> nodes, boolean removeOldNodes) {
138 | List arcs = new ArrayList();
139 | for (OWLEntity entity : nodes) {
140 | arcs.addAll(createIncomingRelationships(entity, false));
141 | arcs.addAll(createOutgoingRelationships(entity, false));
142 | }
143 |
144 | addArcsToModel(arcs, removeOldNodes);
145 | recalculateArcStyles();
146 | }
147 |
148 | /**
149 | * Adds the list of arcs to the graph model. All nodes included in the arc relationships are
150 | * also added to the model if necessary.
151 | *
152 | * @param arcs
153 | */
154 | private void addArcsToModel(Collection arcs, boolean removeOldNodes) {
155 | Set newGraphNodes = new HashSet();
156 |
157 | for (GraphArc arc : arcs) {
158 | GraphArc createdArc = addArc((OWLEntity) arc.getSource().getUserObject(), (OWLEntity) arc.getDestination().getUserObject(), arc.getType().toString(), arc.getIcon());
159 | if (createdArc != null) {
160 | newGraphNodes.add(createdArc.getSource());
161 | newGraphNodes.add(createdArc.getDestination());
162 | createdArc.setInverted(arc.isInverted());
163 |
164 | //PNode n = (PNode)createdArc.getDestination();
165 | //System.out.println(n.getRoot().getClass());
166 | }
167 | }
168 |
169 | if (removeOldNodes) {
170 | // remove all old nodes
171 | GraphNode[] allNodes = getAllNodes().toArray(new GraphNode[getAllNodes().size()]);
172 | for (GraphNode node : allNodes) {
173 | if (!newGraphNodes.contains(node)) {
174 | removeNode(node.getUserObject());
175 | }
176 | }
177 | }
178 | }
179 |
180 | /**
181 | * Adds an OWLEntity object as a GraphNode to the model.
182 | *
183 | * @return The newly created GraphNode.
184 | */
185 | protected GraphNode addNode(OWLEntity entity) {
186 | OWLIconProviderImpl iconProvider = new OWLIconProviderImpl(owlModelManager);
187 | Icon icon = iconProvider.getIcon(entity);
188 | return addNode(entity, owlModelManager.getRendering(entity), icon, getNodeType(entity));
189 | }
190 |
191 | /**
192 | * Gets the node type as a string based on the OWLEntity object.
193 | *
194 | * @return The node type as a string.
195 | */
196 | protected String getNodeType(OWLEntity entity) {
197 | if(entity instanceof OWLClass) {
198 | return CLASS_ART_TYPE;
199 | } else if(entity instanceof OWLIndividual) {
200 | return INDIVIDUAL_ART_TYPE;
201 | }
202 | return UNKNOWN_ART_TYPE;
203 | }
204 |
205 | /**
206 | * Adds a GraphArc to the model if it doesn't already exist.
207 | *
208 | * @return The created or found GraphArc.
209 | */
210 | protected GraphArc addArc(OWLEntity srcEntity, OWLEntity destEntity, String relType, Icon icon) {
211 | if (!relType.contains(restrictToArcType)) {
212 | return null;
213 | }
214 |
215 | boolean newNode = true;
216 | if (getNode(destEntity) != null) {
217 | newNode = false;
218 | }
219 |
220 | GraphNode srcNode = addNode(srcEntity);
221 | GraphNode destNode = addNode(destEntity);
222 |
223 | if (newNode) {
224 | destNode.setLocation(srcNode.getBounds().getX(), srcNode.getBounds().getY());
225 | }
226 |
227 | String key = srcEntity.toString() + relType + destEntity.toString();
228 | DefaultGraphArc arc = (DefaultGraphArc) addArc(key, srcNode, destNode, relType, icon);
229 | //arc.setType(relType);
230 | // for this sample the arc types work backworks (is_a, etc)
231 | arc.setInverted(true);
232 | return arc;
233 | }
234 |
235 | /**
236 | * Determines if the given node is displayable, meaning that it if mustBeVisible is true, then
237 | * the entity must exist in the graph model.
238 | *
239 | * @return True if this node should be displayed.
240 | */
241 | protected boolean isDisplayableNode(OWLEntity entity, boolean mustBeVisible) {
242 | return !mustBeVisible || mustBeVisible && getNode(entity) != null;
243 | }
244 |
245 | /**
246 | * Creates all incoming relationships for the entityOfInterest.
247 | *
248 | * @param entityOfInterest
249 | * @param mustBeVisible True if we only want to create relationships between existing nodes.
250 | * @return The list of GraphArcs created.
251 | */
252 | protected Set createIncomingRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
253 | Set incomingArcs = new HashSet();
254 |
255 | incomingArcs.addAll(loadParents(entityOfInterest, mustBeVisible));
256 | incomingArcs.addAll(loadDomainRangeRels(entityOfInterest, false, mustBeVisible));
257 | incomingArcs.addAll(findIncomingIndividualRelationships(entityOfInterest, mustBeVisible));
258 | incomingArcs.addAll(loadUnreifiedRelations(entityOfInterest, mustBeVisible));
259 | incomingArcs.addAll(findIncomingConditionsRelationships(entityOfInterest, mustBeVisible));
260 |
261 | return incomingArcs;
262 | }
263 |
264 | /**
265 | * Creates all outgoing relationships for a given OWLEntity.
266 | *
267 | * @param entityOfInterest
268 | * @param mustBeVisible True if we only want to create relationships between existing nodes.
269 | * @return The list of GraphArcs created.
270 | */
271 | protected Set createOutgoingRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
272 | Set outgoingRels = new HashSet();
273 |
274 | outgoingRels.addAll(loadChildren(entityOfInterest, mustBeVisible));
275 | outgoingRels.addAll(loadDomainRangeRels(entityOfInterest, true, mustBeVisible));
276 | outgoingRels.addAll(findOutgoingIndividualRelationships(entityOfInterest, mustBeVisible));
277 | outgoingRels.addAll(findOutgoingConditionsRelationships(entityOfInterest, mustBeVisible));
278 |
279 | return outgoingRels;
280 | }
281 |
282 | /**
283 | * Finds relationships between an artifact as a item in the domain, and the ranges of its
284 | * properties
285 | */
286 | private Set loadDomainRangeRels(OWLEntity entityOfInterest, boolean outgoing, boolean mustBeVisible) {
287 | Set domainRangeArcs = new HashSet();
288 |
289 | getDomainRangeRelationships(); // ensures that domain range rels are created
290 | for (GraphArc relationship : domainRangeRelsBuffer) {
291 | if(!filterManager.isArcTypeVisible(relationship.getType())) {
292 | continue;
293 | }
294 |
295 | OWLEntity sourceObject = (OWLEntity) relationship.getSource().getUserObject();
296 | OWLEntity destObject = (OWLEntity) relationship.getDestination().getUserObject();
297 |
298 | if (!isDisplayableNode(sourceObject, mustBeVisible) || !isDisplayableNode(destObject, mustBeVisible)) {
299 | continue;
300 | }
301 | if (outgoing && sourceObject.equals(entityOfInterest) || destObject.equals(entityOfInterest)) {
302 | if(outgoing) {
303 | relationship.setInverted(false);
304 | }
305 |
306 | domainRangeArcs.add(relationship);
307 | }
308 |
309 | }
310 |
311 | return domainRangeArcs;
312 | }
313 |
314 | private Set loadUnreifiedRelations(OWLEntity entityOfInterest, boolean mustBeVisible) {
315 | unreifyRelationInstances();
316 |
317 | Set unreifiedRels = artifactToUnreifiedRels.get(entityOfInterest);
318 | if(unreifiedRels != null) {
319 | for(GraphArc arc : unreifiedRels) {
320 | if(!filterManager.isArcTypeVisible(arc.getType())) {
321 | unreifiedRels.remove(arc);
322 | }
323 | else {
324 | if(!isDisplayableNode((OWLEntity)arc.getDestination().getUserObject(), mustBeVisible)) {
325 | unreifiedRels.remove(arc);
326 | }
327 | }
328 | }
329 | }
330 | return unreifiedRels == null ? new HashSet() : unreifiedRels;
331 | }
332 |
333 | private void unreifyRelationInstances() {
334 | if (artifactToUnreifiedRels != null) {
335 | return;
336 | }
337 |
338 | artifactToUnreifiedRels = new HashMap>();
339 |
340 | for (OWLOntology owlOntology : owlOntologies) {
341 | for(OWLNamedIndividual individual : owlOntology.getIndividualsInSignature()) {
342 | for (Entry> entry : EntitySearcher
343 | .getObjectPropertyValues(individual, owlOntology).asMap()
344 | .entrySet()) {
345 | for(OWLIndividual refIndividual : entry.getValue()) {
346 | GraphArc arc = createArc(individual, (OWLNamedIndividual)refIndividual, owlModelManager.getRendering(entry.getKey()));
347 |
348 | Set outgoingUnreifiedRels = artifactToUnreifiedRels.get(individual);
349 | if (outgoingUnreifiedRels == null) {
350 | outgoingUnreifiedRels = new HashSet();
351 | artifactToUnreifiedRels.put(individual, outgoingUnreifiedRels);
352 | }
353 | outgoingUnreifiedRels.add(arc);
354 |
355 | Set incomingUnreifiedRels = artifactToUnreifiedRels.get(refIndividual);
356 | if (incomingUnreifiedRels == null) {
357 | incomingUnreifiedRels = new HashSet();
358 | artifactToUnreifiedRels.put((OWLNamedIndividual)refIndividual, incomingUnreifiedRels);
359 | }
360 | incomingUnreifiedRels.add(arc);
361 | }
362 | }
363 | }
364 | }
365 | }
366 |
367 | private Set findIncomingIndividualRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
368 | Set arcs = new HashSet();
369 |
370 | if (!(entityOfInterest instanceof OWLNamedIndividual)) {
371 | return arcs;
372 | }
373 | if(!filterManager.isArcTypeVisible(DIRECT_INDIVIDUAL_SLOT_TYPE)) {
374 | return arcs;
375 | }
376 |
377 | OWLNamedIndividual destIndiv = (OWLNamedIndividual) entityOfInterest;
378 | for (OWLClassExpression refNode : EntitySearcher.getTypes(destIndiv,
379 | owlOntologies)) {
380 | if(refNode instanceof OWLClass) {
381 | OWLClass clsOwner = (OWLClass)refNode;
382 | if (isDisplayableNode(clsOwner, mustBeVisible)) {
383 | String relType = DIRECT_INDIVIDUAL_SLOT_TYPE;
384 |
385 | arcs.add(createArc(clsOwner, destIndiv, relType));
386 | }
387 | }
388 | }
389 |
390 | return arcs;
391 | }
392 |
393 | private Set findIncomingConditionsRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
394 | Set arcs = new HashSet();
395 |
396 | if (!(entityOfInterest instanceof OWLClass)) {
397 | return arcs;
398 | }
399 |
400 | for (OWLOntology owlOntology : owlOntologies) {
401 | OWLClass owlClass = (OWLClass) entityOfInterest;
402 | Collection axioms = EntitySearcher.getReferencingAxioms(
403 | owlClass, owlOntology, true);
404 | for(OWLAxiom axiom : axioms) {
405 | if(axiom.getAxiomType().equals(AxiomType.SUBCLASS_OF)) {
406 | OWLSubClassOfAxiom subClassAxiom = (OWLSubClassOfAxiom)axiom;
407 | OWLClassExpression subClassExpression = subClassAxiom.getSubClass();
408 |
409 | if(subClassExpression instanceof OWLClass) {
410 | OWLClassExpression superClassExpression = subClassAxiom.getSuperClass();
411 | if(superClassExpression instanceof OWLQuantifiedRestriction) {
412 | OWLQuantifiedRestriction restriction = (OWLQuantifiedRestriction)superClassExpression;
413 | if(restriction.getFiller() instanceof OWLClass) {
414 | String relType = owlModelManager.getRendering(restriction.getProperty());
415 | if(restriction instanceof OWLObjectSomeValuesFrom) {
416 | relType += SUB_CLASS_SOME_VALUE_OF;
417 | } else {
418 | relType += SUB_CLASS_ALL_VALUES;
419 | }
420 |
421 | if(!filterManager.isArcTypeVisible(relType)) {
422 | continue;
423 | }
424 |
425 | OWLEntity source = (OWLClass)subClassExpression;
426 | OWLEntity target = (OWLClass)restriction.getFiller();
427 |
428 | if(isDisplayableNode(source, mustBeVisible) && isDisplayableNode(target, mustBeVisible)) {
429 | arcs.add(createArc(source, target, relType));
430 | }
431 | }
432 | }
433 | }
434 | }
435 | }
436 | }
437 |
438 | return arcs;
439 | }
440 |
441 | private Set findOutgoingConditionsRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
442 | Set arcs = new HashSet();
443 |
444 | if (!(entityOfInterest instanceof OWLClass)) {
445 | return arcs;
446 | }
447 |
448 | OWLClass owlClass = (OWLClass) entityOfInterest;
449 |
450 | convertOWLClassExpressionsToArcs(owlClass,
451 | EntitySearcher.getSuperClasses(owlClass, owlOntologies), arcs,
452 | null, mustBeVisible);
453 |
454 | OWLIconProviderImpl iconProvider = new OWLIconProviderImpl(owlModelManager);
455 | Icon icon = iconProvider.getIcon(owlClass);
456 | convertOWLClassExpressionsToArcs(owlClass,
457 | EntitySearcher.getEquivalentClasses(owlClass, owlOntologies),
458 | arcs, icon, mustBeVisible);
459 |
460 | return arcs;
461 | }
462 |
463 | private void convertOWLClassExpressionsToArcs(OWLClass owlClass,
464 | Collection expressions, Set arcs,
465 | Icon icon, boolean mustBeVisible) {
466 | for(OWLClassExpression expression : expressions) {
467 | if(expression.getClassExpressionType().equals(ClassExpressionType.OBJECT_SOME_VALUES_FROM)
468 | || expression.getClassExpressionType().equals(ClassExpressionType.OBJECT_ALL_VALUES_FROM)) {
469 | convertOWLClassExpressionToArcs(owlClass, expression, arcs, icon, mustBeVisible);
470 | }
471 | else if(expression.getClassExpressionType().equals(ClassExpressionType.OBJECT_INTERSECTION_OF)) {
472 | for(OWLClassExpression e : expression.asConjunctSet()) {
473 | convertOWLClassExpressionToArcs(owlClass, e, arcs, icon, mustBeVisible);
474 | }
475 | }
476 | }
477 | }
478 |
479 | private void convertOWLClassExpressionToArcs(OWLClass owlClass, OWLClassExpression expression, Set arcs, Icon icon, boolean mustBeVisible) {
480 | boolean isSubClass = true;
481 | if(icon != null) {
482 | isSubClass = false;
483 | }
484 |
485 | for(OWLClassExpression e : expression.asConjunctSet()) {
486 | if(e instanceof OWLQuantifiedRestriction) {
487 | OWLQuantifiedRestriction restriction = (OWLQuantifiedRestriction)e;
488 | if(restriction.getFiller() instanceof OWLClass) {
489 | String relType = owlModelManager.getRendering(restriction.getProperty());
490 | if(isSubClass) {
491 | if(restriction instanceof OWLObjectSomeValuesFrom) {
492 | relType += SUB_CLASS_SOME_VALUE_OF;
493 | } else {
494 | relType += SUB_CLASS_ALL_VALUES;
495 | }
496 | }
497 | else {
498 | if(restriction instanceof OWLObjectSomeValuesFrom) {
499 | relType += EQUIVALENT_CLASS_SOME_VALUE_OF;
500 | } else {
501 | relType += EQUIVALENT_CLASS_ALL_VALUES;
502 | }
503 | }
504 |
505 | if(!filterManager.isArcTypeVisible(relType)) {
506 | continue;
507 | }
508 |
509 | if(isDisplayableNode( (OWLClass)restriction.getFiller(), mustBeVisible)) {
510 | arcs.add(createArc(owlClass, (OWLClass)restriction.getFiller(), relType, icon));
511 | }
512 | }
513 | }
514 | }
515 | }
516 |
517 | /**
518 | * Creates relationships between entityOfInterest and its' direct parents.
519 | *
520 | * @return A list of child to parent relationships.
521 | */
522 | protected Set loadParents(OWLEntity entityOfInterest, boolean mustBeVisible) {
523 | Set parents = new HashSet();
524 |
525 | if(!(entityOfInterest instanceof OWLClass)) {
526 | return parents;
527 | }
528 | if(!filterManager.isArcTypeVisible(DIRECT_SUBCLASS_SLOT_TYPE)) {
529 | return parents;
530 | }
531 |
532 | OWLClass clsOfInterest = (OWLClass)entityOfInterest;
533 |
534 | for(OWLClass parentCls : owlEditorKit.getOWLModelManager().getOWLHierarchyManager().getOWLClassHierarchyProvider().getParents(clsOfInterest)) {
535 | if (isDisplayableNode(parentCls, mustBeVisible)) {
536 | GraphArc arc = createArc(parentCls, clsOfInterest, DIRECT_SUBCLASS_SLOT_TYPE);
537 | arc.setInverted(false);
538 | parents.add(arc);
539 | }
540 | }
541 |
542 | return parents;
543 | }
544 |
545 | /**
546 | * Creates relationships between entityOfInterest and its' direct children.
547 | *
548 | * @return A list of parent to child relationships.
549 | */
550 | protected Set loadChildren(OWLEntity entityOfInterest, boolean mustBeVisible) {
551 | Set children = new HashSet();
552 |
553 | if(!(entityOfInterest instanceof OWLClass)) {
554 | return children;
555 | }
556 | if(!filterManager.isArcTypeVisible(DIRECT_SUBCLASS_SLOT_TYPE)) {
557 | return children;
558 | }
559 |
560 | OWLClass clsOfInterest = (OWLClass)entityOfInterest;
561 |
562 | for(OWLClass childCls : owlEditorKit.getOWLModelManager().getOWLHierarchyManager().getOWLClassHierarchyProvider().getChildren(clsOfInterest)) {
563 | if (isDisplayableNode(childCls, mustBeVisible)) {
564 | GraphArc arc = createArc(clsOfInterest, childCls, DIRECT_SUBCLASS_SLOT_TYPE);
565 | children.add(arc);
566 | }
567 | }
568 |
569 | return children;
570 | }
571 |
572 | private Set findOutgoingIndividualRelationships(OWLEntity entityOfInterest, boolean mustBeVisible) {
573 | Set incomingInstanceRels = new HashSet();
574 |
575 | if (!(entityOfInterest instanceof OWLClass)) {
576 | return incomingInstanceRels;
577 | }
578 | if(!filterManager.isArcTypeVisible(DIRECT_INDIVIDUAL_SLOT_TYPE)) {
579 | return incomingInstanceRels;
580 | }
581 |
582 | OWLClass owlClass = (OWLClass) entityOfInterest;
583 | for (OWLIndividual individual : EntitySearcher.getIndividuals(owlClass,
584 | owlOntologies)) {
585 | if(individual instanceof OWLNamedIndividual) {
586 | OWLNamedIndividual namedIndividual = (OWLNamedIndividual)individual;
587 | if(isDisplayableNode(namedIndividual, mustBeVisible)) {
588 | String relType = DIRECT_INDIVIDUAL_SLOT_TYPE;
589 | GraphArc arc = createArc(owlClass, namedIndividual, relType);
590 | incomingInstanceRels.add(arc);
591 | }
592 | }
593 | }
594 |
595 | return incomingInstanceRels;
596 | }
597 |
598 | private Set getOWLClasses(
599 | Collection owlExpressions) {
600 | Set domains = new HashSet();
601 | for(OWLClassExpression expression : owlExpressions) {
602 | if(expression instanceof OWLClass) {
603 | domains.add((OWLClass)expression);
604 | }
605 | }
606 |
607 | return domains;
608 | }
609 |
610 | private void createDomainRangeRels(Set domains, Set ranges, OWLObjectProperty property) {
611 | // make relationships between all named classes in the domain and all named classes in the range
612 | for(OWLEntity domainClass : domains) {
613 | GraphNode srcNode = new DefaultGraphNode(domainClass);
614 | for (OWLEntity rangeClass : ranges) {
615 | GraphNode destNode = new DefaultGraphNode(rangeClass);
616 | String relType = owlModelManager.getRendering(property) + SUFFIX_DOMAIN_RANGE;
617 |
618 | GraphArc arc = createArc(srcNode, destNode, relType, null);
619 | if(!domainRangeRelsBuffer.contains(arc)) {
620 | domainRangeRelsBuffer.add(arc);
621 | }
622 | }
623 | }
624 | }
625 |
626 | private void createDomainRangeRels() {
627 | domainRangeRelsBuffer = new HashSet();
628 |
629 | for (OWLOntology owlOntology : owlOntologies) {
630 | Set properties = owlOntology.getObjectPropertiesInSignature();
631 |
632 | for(OWLObjectProperty property : properties) {
633 | for(OWLObjectProperty owlObjectProperty : property.getObjectPropertiesInSignature()) {
634 | Collection domainVals = EntitySearcher
635 | .getDomains(owlObjectProperty, owlOntology);
636 | Collection rangeVals = EntitySearcher
637 | .getRanges(owlObjectProperty, owlOntology);
638 |
639 | if (domainVals.isEmpty() && !rangeVals.isEmpty()) {
640 | domainVals.add(owlModelManager.getOWLEntityFinder().getOWLClass("Thing"));
641 | } else if (rangeVals.isEmpty() && !domainVals.isEmpty()) {
642 | rangeVals.add(owlModelManager.getOWLEntityFinder().getOWLClass("Thing"));
643 | }
644 |
645 | Set domains = getOWLClasses(domainVals);
646 | Set ranges = getOWLClasses(rangeVals);
647 |
648 | createDomainRangeRels(domains, ranges, owlObjectProperty);
649 | }
650 | }
651 | }
652 | }
653 |
654 | private Collection getDomainRangeRelationships() {
655 | if (domainRangeRelsBuffer == null) {
656 | createDomainRangeRels();
657 | }
658 | return domainRangeRelsBuffer;
659 | }
660 |
661 | /**
662 | * Creates a GraphArc with the given parameters without actually adding the GraphNodes or
663 | * GraphArc to the model.
664 | *
665 | * @return A GraphArc object.
666 | */
667 | protected GraphArc createArc(OWLEntity srcCls, OWLEntity targetCls, String relType) {
668 | return createArc(srcCls, targetCls, relType, null);
669 | }
670 |
671 | protected GraphArc createArc(OWLEntity srcCls, OWLEntity targetCls, String relType, Icon icon) {
672 | GraphNode srcNode = new DefaultGraphNode(srcCls);
673 | GraphNode destNode = new DefaultGraphNode(targetCls);
674 |
675 | return createArc(srcNode, destNode, relType, icon);
676 | }
677 |
678 | /**
679 | * Creates a GraphArc with the given parameters without actually adding the GraphNodes or
680 | * GraphArc to the model.
681 | *
682 | * @return A GraphArc object.
683 | */
684 | protected GraphArc createArc(GraphNode srcNode, GraphNode destNode, String relType, Icon icon) {
685 | String key = srcNode.getUserObject().toString() + relType + destNode.getUserObject().toString();
686 |
687 | return new DefaultGraphArc(key, srcNode, destNode, icon, relType);
688 | }
689 |
690 | /**
691 | * Performs a search against the knowledge base and displays the neighborhood for the results.
692 | *
693 | * @param searchString
694 | */
695 | public Collection extends OWLEntity> search(String searchString, FilterManager filterManager) {
696 | restrictToArcType = "";
697 | this.filterManager = filterManager;
698 |
699 | Set searchResults = new HashSet();
700 | Set extends OWLEntity> matchingClasses = owlModelManager.getOWLEntityFinder().getMatchingOWLClasses(searchString, true, Pattern.CASE_INSENSITIVE);
701 | Set extends OWLEntity> matchingIndividuals = owlModelManager.getOWLEntityFinder().getMatchingOWLIndividuals(searchString, true, Pattern.CASE_INSENSITIVE);
702 |
703 | searchResults.addAll(matchingClasses);
704 | searchResults.addAll(matchingIndividuals);
705 |
706 | if (searchResults != null) {
707 | showNeighborhood(searchResults, true);
708 | }
709 |
710 | return searchResults;
711 | }
712 |
713 | /**
714 | * Hides all ascendants of the given node.
715 | */
716 | public void hideAscendants(GraphNode graphNode) {
717 | Set seen = new HashSet();
718 |
719 | hideAscendants(graphNode, seen);
720 | }
721 |
722 | /**
723 | * Hides all incoming arcs and attempts to hide any nodes and their arcs.
724 | *
725 | * @param graphNode
726 | * @param seen The list of recursively visited items, need this to avoid cycles
727 | */
728 | private void hideAscendants(GraphNode graphNode, Set seen) {
729 | GraphArc[] arcs = graphNode.getArcs().toArray(new GraphArc[graphNode.getArcs().size()]);
730 | seen.add(((OWLEntity) graphNode.getUserObject()).getIRI());
731 |
732 | for (GraphArc arc : arcs) {
733 | Object userObject = arc.getSource().getUserObject();
734 | GraphNode node = getNode(userObject);
735 |
736 | // recursively collapse the child node, check our seen object in order to avoid cycles
737 | if (node != null && !node.equals(graphNode)) {
738 | removeArc(arc.getUserObject());
739 | if (!seen.contains(((OWLEntity) userObject).getIRI())) {
740 | hideAll(node, seen);
741 | }
742 |
743 | if (isRemovable(node)) {
744 | removeNode(userObject);
745 | }
746 | } else {
747 | userObject = arc.getDestination().getUserObject();
748 | seen.add(((OWLEntity) userObject).getIRI());
749 | }
750 | }
751 | }
752 |
753 | /**
754 | * Hides all arcs recursively from the given graphNode.
755 | *
756 | * @param graphNode
757 | * @param seen Set of URIs that have already been recursed on
758 | */
759 | private void hideAll(GraphNode graphNode, Set seen) {
760 | GraphArc[] arcs = graphNode.getArcs().toArray(new GraphArc[graphNode.getArcs().size()]);
761 | seen.add(((OWLEntity) graphNode.getUserObject()).getIRI());
762 |
763 | for (GraphArc arc : arcs) {
764 | Object userObject = arc.getDestination().getUserObject();
765 | GraphNode node = getNode(userObject);
766 | if (node == null || node.equals(graphNode)) {
767 | continue;
768 | }
769 |
770 | // recursively collapse the child node, check our seen object in order to avoid cycles
771 | removeArc(arc.getUserObject());
772 | if (!seen.contains(((OWLEntity) userObject).getIRI())) {
773 | hideAll(node, seen);
774 | }
775 |
776 | if (node != null && isRemovable(node)) {
777 | removeNode(userObject);
778 | }
779 | }
780 | }
781 |
782 | private Collection generateArcTypes() {
783 | Set types = new HashSet();
784 | types.add(ProtegeGraphModel.DIRECT_SUBCLASS_SLOT_TYPE);
785 | types.add(ProtegeGraphModel.DIRECT_INDIVIDUAL_SLOT_TYPE);
786 | types.addAll(super.getArcTypes());
787 |
788 | return types;
789 | }
790 |
791 | @Override
792 | public Collection getArcTypes() {
793 | if(arcTypes == null) {
794 | arcTypes = generateArcTypes();
795 | }
796 | else {
797 | Collection types = generateArcTypes();
798 | if(types.size() != arcTypes.size()) {
799 | arcTypes.addAll(types);
800 | }
801 | }
802 | return arcTypes;
803 | }
804 |
805 | /**
806 | * Expands the given graphNode by showing it's neighborhood and keeping existing nodes.
807 | *
808 | * @param graphNode
809 | */
810 | public void expandNode(GraphNode graphNode) {
811 | showNeighborhood((OWLEntity) graphNode.getUserObject(), false);
812 | }
813 |
814 | /**
815 | * Expands the given graphNode based on a specific arcType and keeping existing nodes.
816 | *
817 | * @param graphNode
818 | */
819 | public void expandNode(GraphNode graphNode, String arcType) {
820 | graphNode.setHighlighted(false);
821 |
822 | restrictToArcType = arcType;
823 | showNeighborhood((OWLEntity) graphNode.getUserObject(), false);
824 | restrictToArcType = "";
825 | }
826 |
827 | /**
828 | * Collapses the given graphNode.
829 | */
830 | public void collapseNode(GraphNode graphNode) {
831 | Set seen = new HashSet();
832 |
833 | graphNode.setHighlighted(false);
834 |
835 | collapseNode(graphNode, seen);
836 | }
837 |
838 | /**
839 | * Gets all the incoming and outgoing arcs for a given OWLEntity.
840 | *
841 | * @return All associated arcs for a given OWLEntity.
842 | */
843 | private Collection getArcsForEntity(OWLEntity entity) {
844 | Set arcs = new HashSet();
845 |
846 | arcs.addAll(createIncomingRelationships(entity, false));
847 | arcs.addAll(createOutgoingRelationships(entity, false));
848 |
849 | return arcs;
850 | }
851 |
852 | public void resetNodeToArcCount() {
853 | for(OWLEntity owlEntity : frameToArcCount.keySet()) {
854 | frameToArcCount.put(owlEntity, (Set)getArcsForEntity(owlEntity));
855 | }
856 | }
857 |
858 | /**
859 | * Gets the number of relationships for a given OWLEntity. If the entity doesn't exist in the cache,
860 | * then it calculates the count.
861 | *
862 | * @return The number of incoming and outgoing relationships for the frame.
863 | */
864 | private Integer getNodeToArcCount(OWLEntity entity) {
865 | Set arcs = getCachedArcsForEntity(entity);
866 |
867 | return arcs.size();
868 | }
869 |
870 | public Set getCachedArcsForEntity(OWLEntity entity) {
871 | Set arcs = frameToArcCount.get(entity);
872 | if (arcs == null) {
873 | arcs = (Set)getArcsForEntity(entity);
874 | frameToArcCount.put(entity, arcs);
875 | }
876 |
877 | return arcs;
878 | }
879 |
880 | /**
881 | * Collapses the given graphNode by recursively removing all outgoing relationships and nodes
882 | * that become separate components.
883 | *
884 | * @param graphNode
885 | * @param seen The list of recursively visited items, need this to avoid cycles
886 | */
887 | private void collapseNode(GraphNode graphNode, Set seen) {
888 | GraphArc[] arcs = graphNode.getArcs().toArray(new GraphArc[graphNode.getArcs().size()]); //createOutgoingRelationships((Frame) graphNode.getUserObject(), true);
889 | seen.add(((OWLEntity) graphNode.getUserObject()).getIRI());
890 |
891 | for (GraphArc arc : arcs) {
892 | Object userObject = arc.getDestination().getUserObject();
893 | GraphNode node = getNode(userObject);
894 |
895 | // recursively collapse the child node, check our seen object in order to avoid cycles
896 | if (node != null && !node.equals(graphNode)) {
897 | removeArc(arc.getUserObject());
898 | if (isRecursableArc(seen, userObject, arc)) {
899 | collapseNode(node, seen);
900 | }
901 |
902 | if (isRemovable(node)) {
903 | removeNode(userObject);
904 | }
905 | }
906 | }
907 | }
908 |
909 | /**
910 | * Determines whether the given GraphNode is removable. It is removable if it does not have any
911 | * arcs or the only arcs it has are self loops.
912 | *
913 | * @param node
914 | * @return True if removable.
915 | */
916 | private boolean isRemovable(GraphNode node) {
917 | for (GraphArc arc : node.getArcs()) {
918 | if (!arc.getDestination().equals(arc.getSource())) {
919 | return false;
920 | }
921 | }
922 |
923 | return true;
924 | }
925 |
926 | private boolean isRecursableArc(Set seen, Object userObject, GraphArc arc) {
927 | return !seen.contains(((OWLEntity) userObject).getIRI()) && (arc.getType().equals(DIRECT_SUBCLASS_SLOT_TYPE) || arc.getType().equals(DIRECT_INDIVIDUAL_SLOT_TYPE));
928 | }
929 |
930 | /**
931 | * Checks if the given graphNode can be expanded, i.e. has relationships.
932 | *
933 | */
934 | public boolean isExpandable(GraphNode graphNode) {
935 | return getNodeToArcCount((OWLEntity) graphNode.getUserObject()) > 0;
936 | }
937 |
938 | /**
939 | * Determines if the given graphNode is expanded.
940 | *
941 | * @return True if already expanded.
942 | */
943 | public boolean isExpanded(GraphNode graphNode) {
944 | int modelArcsSize = graphNode.getArcs().size();
945 | int frameArcsSize = getNodeToArcCount((OWLEntity) graphNode.getUserObject());
946 |
947 | return modelArcsSize >= frameArcsSize;
948 | }
949 | }
950 |
--------------------------------------------------------------------------------