├── nrepl-clojure
├── doc
│ └── releases.md
├── project.clj
└── src
│ └── protege
│ ├── model.clj
│ ├── nrepl.clj
│ └── dialog.clj
├── .gitignore
├── nrepl-plugin
├── plugin.xml
├── src
│ └── main
│ │ └── java
│ │ └── uk
│ │ └── org
│ │ └── russet
│ │ └── protege
│ │ └── NreplMenu.java
└── pom.xml
└── README.md
/nrepl-clojure/doc/releases.md:
--------------------------------------------------------------------------------
1 | # Releases
2 |
3 | # 1.0
4 |
5 | First full release.
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /nrepl-clojure/.lein-repl-history
2 | /nrepl-clojure/target
3 | /nrepl-plugin/build
4 | /nrepl-plugin/target
5 | /nrepl-clojure/pom.xml
6 | /nrepl-clojure/src/protege/temp.clj
7 | /nrepl-clojure/test/nrepl_clojure/core_test.clj
8 | /nrepl-plugin/build.properties
9 | /nrepl-plugin/lib/nrepl-clojure.jar
10 | /nrepl-plugin/src/.svn/all-wcprops
11 | /nrepl-plugin/src/.svn/entries
12 | /nrepl-clojure/.lein-failures
13 | /nrepl-clojure/pom.xml.asc
14 |
--------------------------------------------------------------------------------
/nrepl-plugin/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/nrepl-clojure/project.clj:
--------------------------------------------------------------------------------
1 | (defproject uk.org.russet/nrepl-clojure "1.1.0-SNAPSHOT"
2 | :description "Launch a nrepl client inside protege"
3 | :license {:name "LGPL"
4 | :url "http://www.gnu.org/licenses/lgpl-3.0.txt"
5 | :distribution :repo}
6 | :scm {:url "https://github.com/phillord/protege-nrepl.git"
7 | :name "git"}
8 | :url "https://github.com/phillord/protege-nrepl"
9 | :dependencies [[org.clojure/clojure "1.6.0"]
10 | [org.clojure/tools.nrepl "0.2.3"]
11 | [edu.stanford.protege/org.protege.editor.core.application
12 | "5.0.0-beta-16-SNAPSHOT"]
13 | [com.cemerick/pomegranate "0.3.0"]]
14 | ;; this is a hack workaround to
15 | ;; https://github.com/technomancy/leiningen/issues/1569 which otherwise adds
16 | ;; nrepl tools as a test dependency in the pom (which means it doesn't get
17 | ;; included in protege-nrepl.
18 | ;; This bug has been fixed in 2.4.3
19 | ;;:profiles {:base {:dependencies ^:replace []}}
20 | )
21 |
--------------------------------------------------------------------------------
/nrepl-clojure/src/protege/model.clj:
--------------------------------------------------------------------------------
1 | ;; The contents of this file are subject to the LGPL License, Version 3.0.
2 | ;;
3 | ;; Copyright (C) 2013, Phillip Lord, Newcastle University
4 | ;;
5 | ;; This program is free software: you can redistribute it and/or modify it
6 | ;; under the terms of the GNU Lesser General Public License as published by
7 | ;; the Free Software Foundation, either version 3 of the License, or (at your
8 | ;; option) any later version.
9 | ;;
10 | ;; This program is distributed in the hope that it will be useful, but WITHOUT
11 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | ;; for more details.
14 | ;;
15 | ;; You should have received a copy of the GNU Lesser General Public License
16 | ;; along with this program. If not, see http://www.gnu.org/licenses/.
17 |
18 | (ns protege.model)
19 |
20 | (def ^{:dynamic true
21 | :doc "The OWLModelManager for the Protege Instance from which the REPL
22 | is launched."}
23 | *owl-model-manager* nil)
24 |
25 | (def ^{:dynamic true
26 | :doc "The OWLEditorKit for the Protege Instance from which the REPL is
27 | launched."}
28 | *owl-editor-kit* nil)
29 |
30 | (def ^{:dynamic true
31 | :doc "The OWLWorkspace for the Protege Instance from which the REPL is
32 | launched."}
33 | *owl-work-space* nil)
34 |
35 | (def auto-connect-on-default (ref false))
36 |
37 | (defn active-ontology
38 | ([]
39 | (.getActiveOntology *owl-model-manager*))
40 | ([o]
41 | (.setActiveOntology *owl-model-manager* o)))
42 |
43 |
44 | (defn selected-object
45 | ([workspace]
46 | (-> workspace
47 | .getOWLSelectionModel
48 | .getSelectedObject))
49 | ([workspace entity]
50 | (-> workspace
51 | .getOWLSelectionModel
52 | (.setSelectedObject entity))))
53 |
--------------------------------------------------------------------------------
/nrepl-clojure/src/protege/nrepl.clj:
--------------------------------------------------------------------------------
1 | (ns protege.nrepl
2 | (:require [clojure.tools.nrepl.server]
3 | [clojure.java.io]
4 | [protege.model]))
5 |
6 |
7 | (def nrepl-handler (ref clojure.tools.nrepl.server/default-handler))
8 |
9 | ;; borrowed from lein
10 | (defn getenv
11 | "Wrap System/getenv for testing purposes."
12 | [name]
13 | (System/getenv name))
14 |
15 | (defn protege-nrepl-home
16 | "Return full path to the user's protege home directory."
17 | []
18 | (let [protege-nrepl-home (getenv "PROTEGE_NREPL_HOME")
19 | protege-nrepl-home (or (and protege-nrepl-home (clojure.java.io/file protege-nrepl-home))
20 | (clojure.java.io/file (System/getProperty "user.home") ".protege-nrepl"))]
21 | (.getAbsolutePath (doto protege-nrepl-home .mkdirs))))
22 |
23 | (def init
24 | "Load the user's ~/.protege-nrepl/init.clj file, if present."
25 | (memoize (fn []
26 | (let [init-file (clojure.java.io/file (protege-nrepl-home) "init.clj")]
27 | (when (.exists init-file)
28 | (try (load-file (.getAbsolutePath init-file))
29 | (catch Exception e
30 | (.printStackTrace e))))))))
31 |
32 | ;; hook system -- identical to tawny.util -- ah well!
33 | (defn make-hook
34 | "Make a hook."
35 | []
36 | (atom []))
37 |
38 | (defn add-hook
39 | "Add func to hook."
40 | [hook func]
41 | (do
42 | (when-not
43 | (some #{func} @hook)
44 | (swap! hook conj func))
45 | @hook))
46 |
47 | (defn remove-hook
48 | "Remove func from hook."
49 | [hook func]
50 | (swap! hook
51 | (partial
52 | remove #{func})))
53 |
54 | (defn clear-hook
55 | "Empty the hook."
56 | [hook]
57 | (reset! hook []))
58 |
59 | (defn run-hook
60 | "Run the hook with optional arguments. Hook functions are run in the order
61 | that they were added."
62 | ([hook]
63 | (doseq [func @hook] (func)))
64 | ([hook & rest]
65 | (doseq [func @hook] (apply func rest))))
66 |
67 |
68 | (def start-server-hook (make-hook))
69 |
70 | (def servers (atom {}))
71 |
72 |
73 | (defn start-server
74 | ([editorkit port]
75 | (binding [protege.model/*owl-editor-kit* editorkit
76 | protege.model/*owl-work-space*
77 | (.getOWLWorkspace editorkit)
78 | protege.model/*owl-model-manager*
79 | (.getOWLModelManager editorkit)]
80 | (run-hook start-server-hook)
81 | (let [server
82 | (clojure.tools.nrepl.server/start-server
83 | :port port
84 | :handler @nrepl-handler)]
85 | (swap! servers assoc editorkit server)))))
86 |
87 | (defn stop-server [editorkit server]
88 | (swap! servers dissoc editorkit)
89 | (clojure.tools.nrepl.server/stop-server server))
90 |
--------------------------------------------------------------------------------
/nrepl-clojure/src/protege/dialog.clj:
--------------------------------------------------------------------------------
1 | (ns protege.dialog
2 | (:require [protege nrepl model])
3 | (:import [java.awt BorderLayout Color]
4 | [java.awt.event ActionListener]
5 | [javax.swing BoxLayout JButton JLabel JPanel
6 | JTextField]))
7 |
8 | (def last-port (ref 7827))
9 | ;; map between model manager and port
10 | (def servers (ref {}))
11 |
12 | (defn action-listener [f]
13 | (proxy [ActionListener] []
14 | (actionPerformed [event]
15 | (f event))))
16 |
17 | (defn start-server-action [editorkit connect disconnect status event]
18 | (dosync
19 | (let [s (protege.nrepl/start-server
20 | editorkit
21 | @last-port)]
22 | (alter servers merge {editorkit s})
23 | (.setEnabled disconnect true)
24 | (.setEnabled connect false)
25 | (.setText status
26 | (str "Connected on port: " @last-port) )
27 | (alter last-port inc))))
28 |
29 | (defn stop-server-action [editorkit connect disconnect status event]
30 | (dosync
31 | (let [s (get @servers editorkit)]
32 | (alter servers dissoc editorkit)
33 | (.setEnabled connect true)
34 | (.setEnabled disconnect false)
35 | (.setText status "Disconnected")
36 | (protege.nrepl/stop-server editorkit s))))
37 |
38 | (defn new-dialog-panel [editorkit]
39 | (let [pn (JPanel.)
40 | ;; this one takes so a text box with next available port
41 | ;; and a status bar saying what, er, the status is
42 | middle (JPanel.)
43 | ;; takes a set of buttons, "Connect", "Disconnect", "Close"
44 | ;; greyed as appopriate
45 | south (JPanel.)
46 | button (JPanel.)
47 | port-label (JLabel. "Port")
48 | port (JTextField. (str @last-port) 20)
49 | status (JLabel. "Disconnected")
50 | connect (JButton. "Connect")
51 | disconnect (JButton. "Disconnect")
52 | connect-fn
53 | (partial start-server-action
54 | editorkit
55 | connect disconnect
56 | status)]
57 | (.addActionListener connect
58 | (action-listener connect-fn))
59 | (doto disconnect
60 | (.setEnabled false)
61 | (.addActionListener
62 | (action-listener
63 | (partial stop-server-action
64 | editorkit connect disconnect
65 | status))))
66 |
67 | (when @protege.model/auto-connect-on-default
68 | (connect-fn nil))
69 |
70 | (doto pn
71 | (.setLayout (BorderLayout.))
72 | (.add middle BorderLayout/CENTER)
73 | (.add south BorderLayout/SOUTH))
74 | (doto south
75 | (.setLayout (BorderLayout.))
76 | (.add button BorderLayout/NORTH)
77 | (.add status BorderLayout/SOUTH))
78 | (doto button
79 | (.setLayout (BoxLayout. button BoxLayout/X_AXIS))
80 | (.add connect)
81 | (.add disconnect))
82 | (doto middle
83 | (.setLayout (BorderLayout.))
84 | (.add port-label BorderLayout/WEST)
85 | (.add port BorderLayout/CENTER))
86 | pn))
87 |
88 |
89 |
90 | (defn new-dialog[manager]
91 | (let [fm (javax.swing.JFrame.)
92 | cp (.getContentPane fm)]
93 | (.add cp (new-dialog-panel manager))
94 | (.pack fm)
95 | (.setVisible fm true)
96 | fm))
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Protege-Nrepl
2 | =============
3 |
4 | This is a plugin for the Protege Ontology Editor, which enables
5 | [nrepl](https://github.com/clojure/tools.nrepl) connection to an existing
6 | editor. The [pomegranate](https://github.com/cemerick/pomegranate) library is
7 | included in the bundle, which means that new maven dependencies or classpath
8 | directories can be added dynamically. Access to the Protege internal data
9 | structures is possible, meaning that the Protege instance can be manipulated
10 | remotely.
11 |
12 | Although, it is not tied to it, Protege-Nrepl is being developed for use
13 | with the [Tawny-OWL](https://github.com/phillord/tawny-owl) library;
14 | currently, the release version of Protege and Tawny use different versions of
15 | the OWL API, so a specialized build of Protege is needed.
16 |
17 | ## Build
18 |
19 | Both maven and leiningen are required to build the plugin. To build,
20 |
21 | cd nrepl-plugin
22 | mvn install
23 |
24 | A small `build.sh` script is included which copies the jar file into protege.
25 |
26 | ## Usage
27 |
28 | Install the plugin as a normal Protege plugin. This adds a single menu item
29 | into "Tools", called NREPL, which can be used to launch a REPL for the current
30 | Protege workspace.
31 |
32 | The `protege.model` Clojure namespace provides a number of different vars,
33 | dynamically scoped to the current workspace which you can use to affect the
34 | running Protege instance (if you don't want to do this, there isn't much point
35 | in launching a REPL within Protege!), as well as some utility functions.
36 |
37 | As Clojure itself and the nrepl server, protege-nrepl packages
38 | [pomegranate](https://github.com/cemerick/pomegranate) which enables the
39 | addition of new dependencies or directories to the classpath in the existing
40 | JVM. The easiest way to do this is to use
41 | [lein-sync](https://github.com/phillord/lein-sync) which creates the relevant
42 | function calls from a leiningen project.
43 |
44 | ## Init
45 |
46 | protege-nrepl loads an init file when launching clojure (this happens when the
47 | NREPL menu item is clicked and *not* when Protege is launched. This file is
48 | found at `~/.protege-nrepl/init.clj`, or equivalent on different OSes.
49 |
50 | My `init.clj` is shown in full at
51 | https://github.com/phillord/tawny-protege/README.md, and enables use with
52 | Tawny-OWL. This setting -- which autoconnects a nrepl once the dialog is
53 | started, is generally useful.
54 |
55 | ;; initing the dialog takes ages -- so auto connect
56 | (dosync (ref-set protege.model/auto-connect-on-default true))
57 |
58 |
59 | ## Mailing List
60 |
61 | There is a [mailing list](mailto:tawny-owl@googlegroups.com)
62 |
63 | ## License
64 |
65 | The contents of this file are subject to the LGPL License, Version 3.0.
66 |
67 | Copyright (C) 2012, 2013, Newcastle University
68 |
69 | This program is free software: you can redistribute it and/or modify it under
70 | the terms of the GNU Lesser General Public License as published by the Free
71 | Software Foundation, either version 3 of the License, or (at your option) any
72 | later version.
73 |
74 | This program is distributed in the hope that it will be useful, but WITHOUT
75 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
76 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
77 |
78 | You should have received a copy of the GNU Lesser General Public License along
79 | with this program. If not, see http://www.gnu.org/licenses/.
80 |
--------------------------------------------------------------------------------
/nrepl-plugin/src/main/java/uk/org/russet/protege/NreplMenu.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The contents of this file are subject to the LGPL License, Version 3.0.
3 | *
4 | * Copyright (C) 2013, Phillip Lord, Newcastle University
5 | *
6 | * This program is free software: you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or (at your
9 | * option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 | * for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program. If not, see http://www.gnu.org/licenses/.
18 | */
19 | package uk.org.russet.protege;
20 |
21 | import clojure.lang.DynamicClassLoader;
22 | import clojure.lang.RT;
23 | import clojure.lang.Var;
24 |
25 | import java.awt.event.ActionEvent;
26 | import java.awt.Container;
27 | import java.awt.BorderLayout;
28 | import javax.swing.JLabel;
29 | import javax.swing.JFrame;
30 |
31 | import javax.swing.JPanel;
32 | import javax.swing.JOptionPane;
33 | import javax.swing.SwingUtilities;
34 | import org.apache.log4j.Logger;
35 | import org.protege.editor.owl.ui.action.ProtegeOWLAction;
36 |
37 |
38 | public class NreplMenu extends ProtegeOWLAction {
39 | private static final long serialVersionUID = -2896209622461162777L;
40 | private static Object lock = new Object();
41 | private static boolean clojureInit = false;
42 |
43 | private final ClassLoader cl = new DynamicClassLoader(this.getClass().getClassLoader());
44 |
45 | public void initialise() throws Exception {
46 | }
47 |
48 |
49 | public void dispose() throws Exception {
50 | }
51 |
52 |
53 |
54 |
55 | public void actionPerformed(ActionEvent event) {
56 | Thread.currentThread().
57 | setContextClassLoader(cl);
58 |
59 | final JFrame frame = new JFrame("REPL connect");
60 | final Container cp = frame.getContentPane();
61 | final JLabel initLabel = new JLabel("Initializing Clojure");
62 |
63 | cp.add(initLabel);
64 | frame.setSize(200,100);
65 | frame.setVisible(true);
66 | frame.validate();
67 | frame.repaint();
68 |
69 | final Runnable after = new Runnable(){
70 | public void run(){
71 | Thread.currentThread().setContextClassLoader(cl);
72 | Var newDialog = RT.var("protege.dialog", "new-dialog-panel");
73 | cp.removeAll();
74 | JPanel dialog = (JPanel)newDialog.
75 | invoke(getOWLEditorKit());
76 |
77 | cp.add(dialog);
78 | frame.pack();
79 | frame.setVisible(true);
80 | frame.validate();
81 | frame.repaint();
82 |
83 | }
84 | };
85 |
86 | final Runnable before = new Runnable(){
87 | public void run(){
88 | Thread.currentThread().setContextClassLoader(cl);
89 | try{
90 | if(!clojureInit){
91 | synchronized(lock){
92 | RT.loadResourceScript("protege/dialog.clj");
93 | RT.loadResourceScript("protege/nrepl.clj");
94 | initLabel.setText("Reading User Init");
95 | Var init = RT.var("protege.nrepl","init");
96 | init.invoke();
97 | clojureInit=true;
98 | }
99 | }
100 | SwingUtilities.invokeAndWait(after);
101 |
102 | }
103 | catch(Exception exp){
104 | throw new RuntimeException(exp);
105 | }
106 | }
107 | };
108 |
109 | new Thread(before).start();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/nrepl-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | org.sonatype.oss
7 | oss-parent
8 | 7
9 |
10 |
11 |
12 |
13 | uk.org.russet
14 | uk.org.russet.protege.nrepl
15 | 0.1.0-SNAPSHOT
16 | protege-nrepl
17 | Provide an NREPL client to use Clojure inside Protege
18 |
19 | bundle
20 |
21 |
22 |
23 | uk.org.russet
24 | nrepl-clojure
25 | 1.1.0-SNAPSHOT
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | edu.stanford.protege
35 | org.protege.editor.core.application
36 | 5.0.0-beta-16-SNAPSHOT
37 | provided
38 |
39 |
40 | edu.stanford.protege
41 | org.protege.editor.owl
42 | 5.0.0-beta-16-SNAPSHOT
43 | provided
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.codehaus.mojo
52 | exec-maven-plugin
53 | 1.1
54 |
55 |
56 | compile-with-lein
57 | initialize
58 |
59 | exec
60 |
61 |
62 |
63 |
64 | lein
65 | install
66 | ../nrepl-clojure
67 |
68 |
69 |
70 | org.apache.maven.plugins
71 | maven-compiler-plugin
72 | 3.0
73 |
74 | 1.6
75 | 1.6
76 |
77 |
78 |
79 | org.apache.felix
80 | maven-bundle-plugin
81 | 2.3.7
82 | true
83 |
84 |
85 | .
86 | Protege NREPL
87 | Integrate with Protege through a Clojure Process
88 | ${project.artifactId};singleton:=true
89 | Phil Lord
90 |
97 |
98 | !javax.servlet*,!junit.*,!org.junit*,!org.apache.*,
99 | !org.testng.*,!sun.misc.*,
100 | *,
101 |
102 |
103 |
104 |
105 |
106 | *
107 | plugin.xml,{maven-resources}
108 | true
109 | *;scope=compile|runtime
110 |
115 |
116 |
117 |
118 | bundle-manifest
119 | install
120 |
121 | manifest
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------