From 26cbbb825a929065b45eea43e04b58c56e8f8c05 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 24 Aug 2016 15:39:05 +0200 Subject: [PATCH 01/10] Add editor field --- .../src/main/resources/interpreter-setting.json | 3 +++ flink/src/main/resources/interpreter-setting.json | 3 +++ jdbc/src/main/resources/interpreter-setting.json | 3 +++ livy/src/main/resources/interpreter-setting.json | 12 ++++++++++++ .../src/main/resources/interpreter-setting.json | 3 +++ .../src/main/resources/interpreter-setting.json | 3 +++ shell/src/main/resources/interpreter-setting.json | 5 ++++- spark/src/main/resources/interpreter-setting.json | 12 ++++++++++++ .../sparkr-resources/interpreter-setting.json | 15 +++++++++++++++ 9 files changed, 58 insertions(+), 1 deletion(-) diff --git a/bigquery/src/main/resources/interpreter-setting.json b/bigquery/src/main/resources/interpreter-setting.json index 3e524ed8362..fb44063d8bd 100644 --- a/bigquery/src/main/resources/interpreter-setting.json +++ b/bigquery/src/main/resources/interpreter-setting.json @@ -22,6 +22,9 @@ "defaultValue": "100000", "description": "Maximum number of rows to fetch from BigQuery" } + }, + "editor": { + "language": "sql" } } ] diff --git a/flink/src/main/resources/interpreter-setting.json b/flink/src/main/resources/interpreter-setting.json index 067e7b84e44..e9bd126827f 100644 --- a/flink/src/main/resources/interpreter-setting.json +++ b/flink/src/main/resources/interpreter-setting.json @@ -16,6 +16,9 @@ "defaultValue": "6123", "description": "port of running JobManager." } + }, + "editor": { + "language": "scala" } } ] diff --git a/jdbc/src/main/resources/interpreter-setting.json b/jdbc/src/main/resources/interpreter-setting.json index 289d4f89ba6..abdb7190d07 100644 --- a/jdbc/src/main/resources/interpreter-setting.json +++ b/jdbc/src/main/resources/interpreter-setting.json @@ -154,6 +154,9 @@ "defaultValue": "org.postgresql.Driver", "description": "" } + }, + "editor": { + "language": "sql" } } ] diff --git a/livy/src/main/resources/interpreter-setting.json b/livy/src/main/resources/interpreter-setting.json index bc5a27589b2..bad6830af83 100644 --- a/livy/src/main/resources/interpreter-setting.json +++ b/livy/src/main/resources/interpreter-setting.json @@ -87,6 +87,9 @@ "defaultValue": "", "description": "Adding extra libraries to livy interpreter" } + }, + "editor": { + "language": "scala" } }, { @@ -105,6 +108,9 @@ "defaultValue": "false", "description": "Execute multiple SQL concurrently if set true." } + }, + "editor": { + "language": "sql" } }, { @@ -112,6 +118,9 @@ "name": "pyspark", "className": "org.apache.zeppelin.livy.LivyPySparkInterpreter", "properties": { + }, + "editor": { + "language": "python" } }, { @@ -119,6 +128,9 @@ "name": "sparkr", "className": "org.apache.zeppelin.livy.LivySparkRInterpreter", "properties": { + }, + "editor": { + "language": "r" } } ] diff --git a/markdown/src/main/resources/interpreter-setting.json b/markdown/src/main/resources/interpreter-setting.json index 78ad7359117..38a6a760dfa 100644 --- a/markdown/src/main/resources/interpreter-setting.json +++ b/markdown/src/main/resources/interpreter-setting.json @@ -10,6 +10,9 @@ "defaultValue": "markdown4j", "description": "Markdown Parser Type. Available values: markdown4j, pegdown. Default = markdown4j" } + }, + "editor": { + "language": "markdown" } } ] diff --git a/python/src/main/resources/interpreter-setting.json b/python/src/main/resources/interpreter-setting.json index 4b12cad3009..d3df586defd 100644 --- a/python/src/main/resources/interpreter-setting.json +++ b/python/src/main/resources/interpreter-setting.json @@ -16,6 +16,9 @@ "defaultValue": "1000", "description": "Max number of dataframe rows to display." } + }, + "editor": { + "language": "python" } }, { diff --git a/shell/src/main/resources/interpreter-setting.json b/shell/src/main/resources/interpreter-setting.json index 78621df684e..d1996fab7e2 100644 --- a/shell/src/main/resources/interpreter-setting.json +++ b/shell/src/main/resources/interpreter-setting.json @@ -28,6 +28,9 @@ "defaultValue": "", "description": "Kerberos principal" } + }, + "editor": { + "language": "sh" } } -] \ No newline at end of file +] diff --git a/spark/src/main/resources/interpreter-setting.json b/spark/src/main/resources/interpreter-setting.json index d87a6c7ff75..55d25bd66e0 100644 --- a/spark/src/main/resources/interpreter-setting.json +++ b/spark/src/main/resources/interpreter-setting.json @@ -54,6 +54,9 @@ "defaultValue": "local[*]", "description": "Spark master uri. ex) spark://masterhost:7077" } + }, + "editor": { + "language": "scala" } }, { @@ -85,6 +88,9 @@ "defaultValue": "true", "description": "Import implicits, UDF collection, and sql if set true. true by default." } + }, + "editor": { + "language": "sql" } }, { @@ -104,6 +110,9 @@ "defaultValue": "spark-packages,http://dl.bintray.com/spark-packages/maven,false;", "description": "A list of 'id,remote-repository-URL,is-snapshot;' for each remote repository." } + }, + "editor": { + "language": "scala" } }, { @@ -117,6 +126,9 @@ "defaultValue": "python", "description": "Python command to run pyspark with" } + }, + "editor": { + "language": "python" } } ] diff --git a/spark/src/main/sparkr-resources/interpreter-setting.json b/spark/src/main/sparkr-resources/interpreter-setting.json index f884fe48702..338c86147af 100644 --- a/spark/src/main/sparkr-resources/interpreter-setting.json +++ b/spark/src/main/sparkr-resources/interpreter-setting.json @@ -54,6 +54,9 @@ "defaultValue": "local[*]", "description": "Spark master uri. ex) spark://masterhost:7077" } + }, + "editor": { + "language": "scala" } }, { @@ -85,6 +88,9 @@ "defaultValue": "true", "description": "Import implicits, UDF collection, and sql if set true. true by default." } + }, + "editor": { + "language": "sql" } }, { @@ -104,6 +110,9 @@ "defaultValue": "spark-packages,http://dl.bintray.com/spark-packages/maven,false;", "description": "A list of 'id,remote-repository-URL,is-snapshot;' for each remote repository." } + }, + "editor": { + "language": "scala" } }, { @@ -117,6 +126,9 @@ "defaultValue": "python", "description": "Python command to run pyspark with" } + }, + "editor": { + "language": "python" } }, { @@ -148,6 +160,9 @@ "defaultValue": "out.format = 'html', comment = NA, echo = FALSE, results = 'asis', message = F, warning = F", "description": "" } + }, + "editor": { + "language": "r" } } ] From 52f42071d29b030c630d60349c897f348fcab6ef Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 24 Aug 2016 16:04:51 +0200 Subject: [PATCH 02/10] Align comments for readability --- .../zeppelin/notebook/socket/Message.java | 139 +++++++++--------- 1 file changed, 70 insertions(+), 69 deletions(-) diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java index 9175e308c3e..795df3e41c9 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java @@ -21,43 +21,43 @@ import java.util.Map; /** - * Zeppelin websocker massage template class. + * Zeppelin websocket massage template class. */ public class Message { /** * Representation of event type. */ public static enum OP { - GET_HOME_NOTE, // [c-s] load note for home screen + GET_HOME_NOTE, // [c-s] load note for home screen - GET_NOTE, // [c-s] client load note - // @param id note id + GET_NOTE, // [c-s] client load note + // @param id note id - NOTE, // [s-c] note info - // @param note serlialized Note object + NOTE, // [s-c] note info + // @param note serlialized Note object - PARAGRAPH, // [s-c] paragraph info - // @param paragraph serialized paragraph object + PARAGRAPH, // [s-c] paragraph info + // @param paragraph serialized paragraph object - PROGRESS, // [s-c] progress update - // @param id paragraph id - // @param progress percentage progress - - NEW_NOTE, // [c-s] create new notebook - DEL_NOTE, // [c-s] delete notebook - // @param id note id - CLONE_NOTE, // [c-s] clone new notebook - // @param id id of note to clone - // @param name name fpor the cloned note - IMPORT_NOTE, // [c-s] import notebook - // @param object notebook + PROGRESS, // [s-c] progress update + // @param id paragraph id + // @param progress percentage progress + + NEW_NOTE, // [c-s] create new notebook + DEL_NOTE, // [c-s] delete notebook + // @param id note id + CLONE_NOTE, // [c-s] clone new notebook + // @param id id of note to clone + // @param name name fpor the cloned note + IMPORT_NOTE, // [c-s] import notebook + // @param object notebook NOTE_UPDATE, - RUN_PARAGRAPH, // [c-s] run paragraph - // @param id paragraph id - // @param paragraph paragraph content.ie. script - // @param config paragraph config - // @param params paragraph params + RUN_PARAGRAPH, // [c-s] run paragraph + // @param id paragraph id + // @param paragraph paragraph content.ie. script + // @param config paragraph config + // @param params paragraph params COMMIT_PARAGRAPH, // [c-s] commit paragraph // @param id paragraph id @@ -69,72 +69,73 @@ public static enum OP { CANCEL_PARAGRAPH, // [c-s] cancel paragraph run // @param id paragraph id - MOVE_PARAGRAPH, // [c-s] move paragraph order - // @param id paragraph id - // @param index index the paragraph want to go + MOVE_PARAGRAPH, // [c-s] move paragraph order + // @param id paragraph id + // @param index index the paragraph want to go INSERT_PARAGRAPH, // [c-s] create new paragraph below current paragraph // @param target index - COMPLETION, // [c-s] ask completion candidates - // @param id - // @param buf current code - // @param cursor cursor position in code + COMPLETION, // [c-s] ask completion candidates + // @param id + // @param buf current code + // @param cursor cursor position in code - COMPLETION_LIST, // [s-c] send back completion candidates list - // @param id - // @param completions list of string + COMPLETION_LIST, // [s-c] send back completion candidates list + // @param id + // @param completions list of string - LIST_NOTES, // [c-s] ask list of note - RELOAD_NOTES_FROM_REPO, // [c-s] reload notes from repo + LIST_NOTES, // [c-s] ask list of note + RELOAD_NOTES_FROM_REPO, // [c-s] reload notes from repo - NOTES_INFO, // [s-c] list of note infos - // @param notes serialized List object + NOTES_INFO, // [s-c] list of note infos + // @param notes serialized List object PARAGRAPH_REMOVE, PARAGRAPH_CLEAR_OUTPUT, - PARAGRAPH_APPEND_OUTPUT, // [s-c] append output - PARAGRAPH_UPDATE_OUTPUT, // [s-c] update (replace) output + PARAGRAPH_APPEND_OUTPUT, // [s-c] append output + PARAGRAPH_UPDATE_OUTPUT, // [s-c] update (replace) output PING, AUTH_INFO, - ANGULAR_OBJECT_UPDATE, // [s-c] add/update angular object - ANGULAR_OBJECT_REMOVE, // [s-c] add angular object del + ANGULAR_OBJECT_UPDATE, // [s-c] add/update angular object + ANGULAR_OBJECT_REMOVE, // [s-c] add angular object del - ANGULAR_OBJECT_UPDATED, // [c-s] angular object value updated, + ANGULAR_OBJECT_UPDATED, // [c-s] angular object value updated, - ANGULAR_OBJECT_CLIENT_BIND, // [c-s] angular object updated from AngularJS z object + ANGULAR_OBJECT_CLIENT_BIND, // [c-s] angular object updated from AngularJS z object - ANGULAR_OBJECT_CLIENT_UNBIND, // [c-s] angular object unbind from AngularJS z object + ANGULAR_OBJECT_CLIENT_UNBIND, // [c-s] angular object unbind from AngularJS z object - LIST_CONFIGURATIONS, // [c-s] ask all key/value pairs of configurations - CONFIGURATIONS_INFO, // [s-c] all key/value pairs of configurations - // @param settings serialized Map object + LIST_CONFIGURATIONS, // [c-s] ask all key/value pairs of configurations + CONFIGURATIONS_INFO, // [s-c] all key/value pairs of configurations + // @param settings serialized Map object - CHECKPOINT_NOTEBOOK, // [c-s] checkpoint notebook to storage repository - // @param noteId - // @param checkpointName + CHECKPOINT_NOTEBOOK, // [c-s] checkpoint notebook to storage repository + // @param noteId + // @param checkpointName - LIST_REVISION_HISTORY, // [c-s] list revision history of the notebook - // @param noteId - NOTE_REVISION, // [c-s] get certain revision of note - // @param noteId - // @param revisionId + LIST_REVISION_HISTORY, // [c-s] list revision history of the notebook + // @param noteId + NOTE_REVISION, // [c-s] get certain revision of note + // @param noteId + // @param revisionId - APP_APPEND_OUTPUT, // [s-c] append output - APP_UPDATE_OUTPUT, // [s-c] update (replace) output - APP_LOAD, // [s-c] on app load - APP_STATUS_CHANGE, // [s-c] on app status change + APP_APPEND_OUTPUT, // [s-c] append output + APP_UPDATE_OUTPUT, // [s-c] update (replace) output + APP_LOAD, // [s-c] on app load + APP_STATUS_CHANGE, // [s-c] on app status change - LIST_NOTEBOOK_JOBS, // [c-s] get notebook job management infomations - LIST_UPDATE_NOTEBOOK_JOBS, // [s-c] get job management informations + LIST_NOTEBOOK_JOBS, // [c-s] get notebook job management infomations + LIST_UPDATE_NOTEBOOK_JOBS, // [c-s] get job management informations for until unixtime UNSUBSCRIBE_UPDATE_NOTEBOOK_JOBS, // [c-s] unsubscribe job information for job management - GET_INTERPRETER_BINDINGS, // [c-s] get interpreter bindings - // @param noteID - SAVE_INTERPRETER_BINDINGS, // [c-s] save interpreter bindings - // @param noteID - // @param selectedSettingIds - INTERPRETER_BINDINGS // [s-c] interpreter bindings + // @param unixTime + GET_INTERPRETER_BINDINGS, // [c-s] get interpreter bindings + // @param noteID + SAVE_INTERPRETER_BINDINGS, // [c-s] save interpreter bindings + // @param noteID + // @param selectedSettingIds + INTERPRETER_BINDINGS // [s-c] interpreter bindings } public OP op; From 20132ca9fff3daefc2fa689d2e01863cf9b4a4ab Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 24 Aug 2016 22:57:08 +0200 Subject: [PATCH 03/10] Get paragraph editor mode from backend --- .../zeppelin/interpreter/Interpreter.java | 6 ++ .../zeppelin/socket/NotebookServer.java | 22 ++++- zeppelin-web/bower.json | 4 +- .../paragraph/paragraph.controller.js | 93 ++++++++++--------- .../websocketEvents.factory.js | 6 +- .../websocketEvents/websocketMsg.service.js | 9 ++ .../org/apache/zeppelin/notebook/Note.java | 15 +++ .../apache/zeppelin/notebook/Paragraph.java | 2 +- .../zeppelin/notebook/socket/Message.java | 4 + 9 files changed, 111 insertions(+), 50 deletions(-) diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java index 6d7d660eeb9..9678b4691df 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java @@ -251,6 +251,7 @@ public static class RegisteredInterpreter { private String className; private boolean defaultInterpreter; private Map properties; + private Map editor; private String path; public RegisteredInterpreter(String name, String group, String className, @@ -266,6 +267,7 @@ public RegisteredInterpreter(String name, String group, String className, this.className = className; this.defaultInterpreter = defaultInterpreter; this.properties = properties; + this.editor = new HashMap<>(); } public String getName() { @@ -292,6 +294,10 @@ public Map getProperties() { return properties; } + public Map getEditor() { + return editor; + } + public void setPath(String path) { this.path = path; } diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 8b6329a4073..58db005b6bf 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -250,6 +250,9 @@ public void onMessage(NotebookSocket conn, String msg) { case SAVE_INTERPRETER_BINDINGS: saveInterpreterBindings(conn, messagereceived); break; + case EDITOR_SETTING: + getEditorSetting(conn, notebook, messagereceived); + break; default: break; } @@ -1457,7 +1460,7 @@ public void afterStatusChange(Job job, Status before, Status after) { } /** - * This callback is for praragraph that runs on RemoteInterpreterProcess + * This callback is for paragraph that runs on RemoteInterpreterProcess * @param paragraph * @param out * @param output @@ -1569,11 +1572,24 @@ public void onRemove(String interpreterGroupId, String name, String noteId, Stri if (id.equals(interpreterGroupId)) { broadcast( note.getId(), - new Message(OP.ANGULAR_OBJECT_REMOVE).put("name", name).put( - "noteId", noteId).put("paragraphId", paragraphId)); + new Message(OP.ANGULAR_OBJECT_REMOVE) + .put("name", name) + .put("noteId", noteId) + .put("paragraphId", paragraphId)); } } } } + + private void getEditorSetting(NotebookSocket conn, Notebook notebook, Message fromMessage) + throws IOException { + String replName = (String) fromMessage.get("magic"); + String noteId = getOpenNoteId(conn); + Note note = notebook.getNote(noteId); + Message resp = new Message(OP.EDITOR_SETTING); + resp.put("editor", note.getEditorSetting(replName)); + conn.send(serializeMessage(resp)); + return; + } } diff --git a/zeppelin-web/bower.json b/zeppelin-web/bower.json index 5ec18a75bdb..aeabd79dca2 100644 --- a/zeppelin-web/bower.json +++ b/zeppelin-web/bower.json @@ -24,7 +24,7 @@ "angular-elastic": "~2.4.2", "angular-elastic-input": "~2.2.0", "angular-xeditable": "0.1.12", - "highlightjs": "^9.2.0", + "highlightjs": "^9.4.0", "lodash": "~3.9.3", "angular-filter": "~0.5.4", "ngtoast": "~2.0.0", @@ -62,7 +62,7 @@ "highlight.pack.js", "styles/github.css" ], - "version": "8.4.0", + "version": "9.4.0", "name": "highlightjs" } } diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index bd3b6b3c945..ffe4f49d675 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -15,7 +15,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $rootScope, $route, $window, $routeParams, $location, $timeout, $compile, - $http, websocketMsgSrv, baseUrlSrv, ngToast, + $http, $q, websocketMsgSrv, baseUrlSrv, ngToast, saveAsService, esriLoader) { var ANGULAR_FUNCTION_OBJECT_NAME_PREFIX = '_Z_ANGULAR_FUNC_'; $scope.parentNote = null; @@ -78,15 +78,6 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r var angularObjectRegistry = {}; - var editorModes = { - 'ace/mode/python': /^%(\w*\.)?(pyspark|python)\s*$/, - 'ace/mode/scala': /^%(\w*\.)?spark\s*$/, - 'ace/mode/r': /^%(\w*\.)?(r|sparkr|knitr)\s*$/, - 'ace/mode/sql': /^%(\w*\.)?\wql/, - 'ace/mode/markdown': /^%md/, - 'ace/mode/sh': /^%sh/ - }; - // Controller init $scope.init = function(newParagraph, note) { $scope.paragraph = newParagraph; @@ -538,7 +529,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r $scope.aceChanged = function() { $scope.dirtyText = $scope.editor.getSession().getValue(); $scope.startSaveTimer(); - $scope.setParagraphMode($scope.editor.getSession(), $scope.dirtyText, $scope.editor.getCursorPosition()); + setParagraphMode($scope.editor.getSession(), $scope.dirtyText, $scope.editor.getCursorPosition()); }; $scope.aceLoaded = function(_editor) { @@ -576,37 +567,11 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r // not applying emacs key binding while the binding override Ctrl-v. default behavior of paste text on windows. } - $scope.setParagraphMode = function(session, paragraphText, pos) { - // Evaluate the mode only if the first 30 characters of the paragraph have been modified or the the position is undefined. - if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30)) { - // If paragraph loading, use config value if exists - if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode) { - session.setMode($scope.paragraph.config.editorMode); - } else { - // Defaults to spark mode - var newMode = 'ace/mode/scala'; - // Test first against current mode - var oldMode = session.getMode().$id; - if (!editorModes[oldMode] || !editorModes[oldMode].test(paragraphText)) { - for (var key in editorModes) { - if (key !== oldMode) { - if (editorModes[key].test(paragraphText)) { - $scope.paragraph.config.editorMode = key; - session.setMode(key); - return true; - } - } - } - $scope.paragraph.config.editorMode = newMode; - session.setMode(newMode); - } - } - } - }; - var remoteCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { - if (!$scope.editor.isFocused()) { return;} + if (!$scope.editor.isFocused()) { + return; + } pos = session.getTextRange(new Range(0, 0, pos.row, pos.column)).length; var buf = session.getValue(); @@ -662,7 +627,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r autoAdjustEditorHeight(_editor.container.id); }); - $scope.setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue()); + setParagraphMode($scope.editor.getSession(), $scope.editor.getSession().getValue()); // autocomplete on '.' /* @@ -737,6 +702,51 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r } }; + var getEditorSetting = function(interpreterName) { + var deferred = $q.defer(); + websocketMsgSrv.getEditorSetting(interpreterName); + $timeout( + $scope.$on('editorSetting', function(event, data) { + deferred.resolve(data); + } + ), 1000); + return deferred.promise; + }; + + var setParagraphMode = function(session, paragraphText, pos) { + // Evaluate the mode only if the the position is undefined + // or the first 30 characters of the paragraph have been modified + // or cursor position is at beginning of second line.(in case user hit enter after typing %magic) + if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30) || (pos.row === 1 && pos.column === 0)) { + // If paragraph loading, use config value if exists + if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode) { + session.setMode($scope.paragraph.config.editorMode); + } else { + var magic; + // set editor mode to default interpreter syntax if paragraph text doesn't start with '%' + if (!paragraphText.startsWith('%')) { + magic = $scope.$parent.interpreterBindings[0].group; + } else { + var replNameRegexp = /%(.+?)\s/g; + var match = replNameRegexp.exec(paragraphText); + if (match) { + magic = match[1]; + } + } + if (magic) { + var promise = getEditorSetting(magic); + promise.then(function(editorSetting) { + if (!_.isEmpty(editorSetting.editor)) { + var mode = 'ace/mode/' + editorSetting.editor.language; + $scope.paragraph.config.editorMode = mode; + session.setMode(mode); + } + }); + } + } + } + }; + var autoAdjustEditorHeight = function(id) { var editor = $scope.editor; var height = editor.getSession().getScreenLength() * editor.renderer.lineHeight + @@ -2259,7 +2269,6 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r var noteId = $route.current.pathParams.noteId; $http.get(baseUrlSrv.getRestApiBase() + '/helium/suggest/' + noteId + '/' + $scope.paragraph.id) .success(function(data, status, headers, config) { - console.log('Suggested apps %o', data); $scope.suggestion = data.body; }) .error(function(err, status, headers, config) { diff --git a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js index e4f45db0218..36e90b49388 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js +++ b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js @@ -76,8 +76,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents', action: function(dialog) { dialog.close(); angular.element('#loginModal').modal({ - show: 'true' - }); + show: 'true' + }); } }, { label: 'Cancel', @@ -97,6 +97,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents', $rootScope.$broadcast('updateProgress', data); } else if (op === 'COMPLETION_LIST') { $rootScope.$broadcast('completionList', data); + } else if (op === 'EDITOR_SETTING') { + $rootScope.$broadcast('editorSetting', data); } else if (op === 'ANGULAR_OBJECT_UPDATE') { $rootScope.$broadcast('angularObjectUpdate', data); } else if (op === 'ANGULAR_OBJECT_REMOVE') { diff --git a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js index 3dcdc3e3b45..3b27bced484 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js +++ b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js @@ -180,6 +180,15 @@ angular.module('zeppelinWebApp').service('websocketMsgSrv', function($rootScope, }); }, + getEditorSetting: function(replName) { + websocketEvents.sendNewEvent({ + op: 'EDITOR_SETTING', + data: { + magic: replName + } + }); + }, + isConnected: function() { return websocketEvents.isConnected(); }, diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 1281e71589d..cb648295055 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -650,6 +650,21 @@ public void setInfo(Map info) { this.info = info; } + public Interpreter getRepl(String name) { + return factory.getInterpreter(id(), name); + } + + public Map getEditorSetting(String replName) { + Interpreter intp = getRepl(replName); + Map editor = new HashMap<>(); + try { + editor = intp.findRegisteredInterpreterByClassName(intp.getClassName()).getEditor(); + } catch (NullPointerException e) { + editor.put("language", "text"); + } + return editor; + } + @Override public void beforeStatusChange(Job job, Status before, Status after) { if (jobListenerFactory != null) { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java index 7807abba416..1fdc8878ada 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java @@ -193,7 +193,7 @@ public static String getScriptBody(String text) { } public Interpreter getRepl(String name) { - return factory.getInterpreter(note.getId(), name); + return note.getRepl(name); } public Interpreter getCurrentRepl() { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java index 795df3e41c9..b314e6227fa 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java @@ -76,6 +76,10 @@ public static enum OP { INSERT_PARAGRAPH, // [c-s] create new paragraph below current paragraph // @param target index + EDITOR_SETTING, // [c-s] ask paragraph editor setting + // @param magic magic keyword written in paragraph + // ex) spark.spark or spark + COMPLETION, // [c-s] ask completion candidates // @param id // @param buf current code From 565d9d0d9a32096793ea65a7465aaaa28a512c3a Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 24 Aug 2016 22:57:19 +0200 Subject: [PATCH 04/10] [DOC] Setting syntax highlight when writing new interpreter --- docs/development/writingzeppelininterpreter.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/development/writingzeppelininterpreter.md b/docs/development/writingzeppelininterpreter.md index 4ae1cbcca06..c1d3f18376d 100644 --- a/docs/development/writingzeppelininterpreter.md +++ b/docs/development/writingzeppelininterpreter.md @@ -69,6 +69,9 @@ Here is an example of `interpreter-setting.json` on your own interpreter. "defaultValue": "property2DefaultValue", "description": "Property 2 description" }, ... + }, + "editor": { + "language": "your-syntax-highlight-language" } }, { @@ -96,15 +99,20 @@ some interpreter specific code... ``` ## Programming Languages for Interpreter -If the interpreter uses a specific programming language ( like Scala, Python, SQL ), it is generally recommended to add a syntax highlighting supported for that to the notebook paragraph editor. +If the interpreter uses a specific programming language (like Scala, Python, SQL), it is generally recommended to add a syntax highlighting supported for that to the notebook paragraph editor. To check out the list of languages supported, see the `mode-*.js` files under `zeppelin-web/bower_components/ace-builds/src-noconflict` or from [github.com/ajaxorg/ace-builds](https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict). If you want to add a new set of syntax highlighting, 1. Add the `mode-*.js` file to [zeppelin-web/bower.json](https://github.com/apache/zeppelin/blob/master/zeppelin-web/bower.json) ( when built, [zeppelin-web/src/index.html](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/index.html) will be changed automatically. ). -2. Add to the list of `editorMode` in [zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js) - it follows the pattern 'ace/mode/x' where x is the name. -3. Add to the code that checks for `%` prefix and calls `session.setMode(editorMode.x)` in `setParagraphMode` located in [zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js). +2. Add `editor` object to `interpreter-setting.json` file. If you want to set your language to java, add: + + ``` + "editor": { + "language": "java" + } + ``` ## Install your interpreter binary From 75543b3ecfee2615bd4f4add86a52d8ae78d81a0 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 24 Aug 2016 22:57:28 +0200 Subject: [PATCH 05/10] Add test --- .../zeppelin/notebook/NotebookTest.java | 34 +++++++++++++++++-- .../interpreter/mock/interpreter-setting.json | 12 +++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 zeppelin-zengine/src/test/resources/interpreter/mock/interpreter-setting.json diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index 0ec8e7cfdd1..148ff12dc39 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -74,10 +74,15 @@ public void setUp() throws Exception { new File(tmpDir, "conf").mkdirs(); notebookDir = new File(tmpDir + "/notebook"); notebookDir.mkdirs(); + FileUtils.copyDirectory(new File("src/test/resources/interpreter"), new File(tmpDir, "interpreter")); + System.setProperty(ConfVars.ZEPPELIN_CONF_DIR.getVarName(), tmpDir.toString() + "/conf"); System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), tmpDir.getAbsolutePath()); System.setProperty(ConfVars.ZEPPELIN_NOTEBOOK_DIR.getVarName(), notebookDir.getAbsolutePath()); - System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), "org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2"); + System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), + "org.apache.zeppelin.interpreter.mock.MockInterpreter1," + + "org.apache.zeppelin.interpreter.mock.MockInterpreter2," + + "org.apache.zeppelin.interpreter.mock.MockInterpreter11"); conf = ZeppelinConfiguration.create(); @@ -95,8 +100,7 @@ public void setUp() throws Exception { credentials = new Credentials(conf.credentialsPersist(), conf.getCredentialsPath()); notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, this, search, - notebookAuthorization, credentials); - + notebookAuthorization, credentials); } @After @@ -886,6 +890,30 @@ else if(file.isDirectory()){ } } + @Test + public void getEditorSetting() throws IOException, RepositoryException, SchedulerException { + List intpIds = new ArrayList<>(); + for(InterpreterSetting intpSetting: factory.get()) { + if (intpSetting.getName().startsWith("mock1")) { + intpIds.add(intpSetting.getId()); + } + } + Note note = notebook.createNote(intpIds, null); + + // get editor setting from interpreter-setting.json + Map editor = note.getEditorSetting("mock11"); + assertEquals("java", editor.get("language")); + + // when interpreter is not loaded via interpreter-setting.json + // or editor setting doesn't exit + editor = note.getEditorSetting("mock1"); + assertEquals(null, editor.get("language")); + + // when interpreter is not bound to note + editor = note.getEditorSetting("mock2"); + assertEquals("text", editor.get("language")); + } + @Override public ParagraphJobListener getParagraphJobListener(Note note) { return new ParagraphJobListener(){ diff --git a/zeppelin-zengine/src/test/resources/interpreter/mock/interpreter-setting.json b/zeppelin-zengine/src/test/resources/interpreter/mock/interpreter-setting.json new file mode 100644 index 00000000000..65568ef8a5c --- /dev/null +++ b/zeppelin-zengine/src/test/resources/interpreter/mock/interpreter-setting.json @@ -0,0 +1,12 @@ +[ + { + "group": "mock11", + "name": "mock11", + "className": "org.apache.zeppelin.interpreter.mock.MockInterpreter11", + "properties": { + }, + "editor": { + "language": "java" + } + } +] From 9e4f2e93d13f71b5b4595c06a58f99946067dec7 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 8 Sep 2016 15:12:40 +0200 Subject: [PATCH 06/10] Change the way to read interpreter language from interpreter-setting.json after #1145 --- .../interpreter/InterpreterFactory.java | 38 +++++++++++++++---- .../zeppelin/interpreter/InterpreterInfo.java | 15 +++++++- .../org/apache/zeppelin/notebook/Note.java | 29 ++++++++++++-- .../interpreter/InterpreterFactoryTest.java | 4 +- .../zeppelin/notebook/NotebookTest.java | 2 +- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java index 47ff946b604..d23207d8ab9 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java @@ -49,6 +49,7 @@ import java.util.Set; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; @@ -223,7 +224,8 @@ public boolean accept(Path entry) throws IOException { InterpreterInfo interpreterInfo; for (RegisteredInterpreter r : Interpreter.registeredInterpreters.values()) { interpreterInfo = - new InterpreterInfo(r.getClassName(), r.getName(), r.isDefaultInterpreter()); + new InterpreterInfo(r.getClassName(), r.getName(), r.isDefaultInterpreter(), + r.getEditor()); add(r.getGroup(), interpreterInfo, convertInterpreterProperties(r.getProperties()), r.getPath()); } @@ -335,7 +337,7 @@ private void registerInterpreters(List registeredInterpre for (RegisteredInterpreter registeredInterpreter : registeredInterpreters) { InterpreterInfo interpreterInfo = new InterpreterInfo(registeredInterpreter.getClassName(), registeredInterpreter.getName(), - registeredInterpreter.isDefaultInterpreter()); + registeredInterpreter.isDefaultInterpreter(), registeredInterpreter.getEditor()); Properties properties = new Properties(); Map p = registeredInterpreter.getProperties(); @@ -370,10 +372,11 @@ private void loadFromFile() throws IOException { fis.close(); String json = sb.toString(); - InterpreterInfoSaving info = gson.fromJson(json, InterpreterInfoSaving.class); + InterpreterInfoSaving infoSaving = gson.fromJson(json, InterpreterInfoSaving.class); - for (String k : info.interpreterSettings.keySet()) { - InterpreterSetting setting = info.interpreterSettings.get(k); + for (String k : infoSaving.interpreterSettings.keySet()) { + InterpreterSetting setting = infoSaving.interpreterSettings.get(k); + List infos = setting.getInterpreterInfos(); // Always use separate interpreter process // While we decided to turn this feature on always (without providing @@ -391,15 +394,23 @@ private void loadFromFile() throws IOException { depClassPath = interpreterSettingObject.getPath(); setting.setPath(depClassPath); + for (InterpreterInfo info : infos) { + if (info.getEditor() == null) { + Map editor = getEditorFromSettingByClassName(interpreterSettingObject, + info.getClassName()); + info.setEditor(editor); + } + } + setting.setInterpreterGroupFactory(this); loadInterpreterDependencies(setting); interpreterSettings.put(k, setting); } - this.interpreterBindings = info.interpreterBindings; + this.interpreterBindings = infoSaving.interpreterBindings; - if (info.interpreterRepositories != null) { - for (RemoteRepository repo : info.interpreterRepositories) { + if (infoSaving.interpreterRepositories != null) { + for (RemoteRepository repo : infoSaving.interpreterRepositories) { if (!depResolver.getRepos().contains(repo)) { this.interpreterRepositories.add(repo); } @@ -407,6 +418,17 @@ private void loadFromFile() throws IOException { } } + public Map getEditorFromSettingByClassName(InterpreterSetting intpSetting, + String className) { + List intpInfos = intpSetting.getInterpreterInfos(); + for (InterpreterInfo intpInfo : intpInfos) { + if (className.equals(intpInfo.getClassName())) { + return intpInfo.getEditor(); + } + } + return ImmutableMap.of("language", (Object) "text"); + } + private void loadInterpreterDependencies(final InterpreterSetting setting) { setting.setStatus(InterpreterSetting.Status.DOWNLOADING_DEPENDENCIES); diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfo.java index c104b9d7eea..e9088e94c57 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfo.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfo.java @@ -19,6 +19,8 @@ import com.google.gson.annotations.SerializedName; +import java.util.Map; + /** * Information of interpreters in this interpreter setting. * this will be serialized for conf/interpreter.json and REST api response. @@ -27,11 +29,14 @@ public class InterpreterInfo { private String name; @SerializedName("class") private String className; private boolean defaultInterpreter = false; + private Map editor; - InterpreterInfo(String className, String name, boolean defaultInterpreter) { + InterpreterInfo(String className, String name, boolean defaultInterpreter, + Map editor) { this.className = className; this.name = name; this.defaultInterpreter = defaultInterpreter; + this.editor = editor; } public String getName() { @@ -50,6 +55,14 @@ boolean isDefaultInterpreter() { return defaultInterpreter; } + public Map getEditor() { + return editor; + } + + public void setEditor(Map editor) { + this.editor = editor; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof InterpreterInfo)) { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index cb648295055..02b7ee42b98 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -30,6 +30,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.gson.Gson; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -651,16 +653,35 @@ public void setInfo(Map info) { } public Interpreter getRepl(String name) { - return factory.getInterpreter(id(), name); + return factory.getInterpreter(getId(), name); } public Map getEditorSetting(String replName) { Interpreter intp = getRepl(replName); - Map editor = new HashMap<>(); + Map editor = Maps.newHashMap( + ImmutableMap.builder() + .put("language", "text").build()); + String defaultSettingName = factory.getDefaultInterpreterSetting(this.getId()).getName(); + String group = StringUtils.EMPTY; try { - editor = intp.findRegisteredInterpreterByClassName(intp.getClassName()).getEditor(); + List intpSettings = factory.getInterpreterSettings(this.getId()); + for (InterpreterSetting intpSetting : intpSettings) { + String[] replNameSplit = replName.split("\\."); + if (replNameSplit.length == 2) { + group = replNameSplit[0]; + } + // when replName is 'name' of interpreter + if (defaultSettingName.equals(intpSetting.getName())) { + editor = factory.getEditorFromSettingByClassName(intpSetting, intp.getClassName()); + } + // when replName is 'alias name' of interpreter or 'group' of interpreter + if (replName.equals(intpSetting.getName()) || group.equals(intpSetting.getName())) { + editor = factory.getEditorFromSettingByClassName(intpSetting, intp.getClassName()); + break; + } + } } catch (NullPointerException e) { - editor.put("language", "text"); + logger.warn("Couldn't get interpreter editor language"); } return editor; } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java index 5cdda05a499..f85d4c0652c 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java @@ -166,8 +166,8 @@ public void testSaveLoad() throws IOException, RepositoryException { @Test public void testInterpreterAliases() throws IOException, RepositoryException { factory = new InterpreterFactory(conf, null, null, null, depResolver); - final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true); - final InterpreterInfo info2 = new InterpreterInfo("className2", "name1", true); + final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true, null); + final InterpreterInfo info2 = new InterpreterInfo("className2", "name1", true, null); factory.add("group1", new ArrayList(){{ add(info1); }}, new ArrayList(), new InterpreterOption(true), new Properties(), "/path1"); diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index 148ff12dc39..c3bf09c0c1a 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -92,7 +92,7 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver); SearchService search = mock(SearchService.class); notebookRepo = new VFSNotebookRepo(conf); From 0874522154500bd560fa3d48e8b0f25838b3af45 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 8 Sep 2016 16:05:05 +0200 Subject: [PATCH 07/10] Change condition for triggering 'getAndSetEditorSetting' to reduce front-end <-> back-end communication --- .../paragraph/paragraph.controller.js | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index ffe4f49d675..8c4681075f0 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -22,6 +22,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r $scope.paragraph = null; $scope.originalText = ''; $scope.editor = null; + $scope.magic = null; var paragraphScope = $rootScope.$new(true, $rootScope); @@ -702,7 +703,7 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r } }; - var getEditorSetting = function(interpreterName) { + var getAndSetEditorSetting = function(session, interpreterName) { var deferred = $q.defer(); websocketMsgSrv.getEditorSetting(interpreterName); $timeout( @@ -710,7 +711,14 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r deferred.resolve(data); } ), 1000); - return deferred.promise; + + deferred.promise.then(function(editorSetting) { + if (!_.isEmpty(editorSetting.editor)) { + var mode = 'ace/mode/' + editorSetting.editor.language; + $scope.paragraph.config.editorMode = mode; + session.setMode(mode); + } + }); }; var setParagraphMode = function(session, paragraphText, pos) { @@ -724,25 +732,20 @@ angular.module('zeppelinWebApp').controller('ParagraphCtrl', function($scope, $r } else { var magic; // set editor mode to default interpreter syntax if paragraph text doesn't start with '%' - if (!paragraphText.startsWith('%')) { - magic = $scope.$parent.interpreterBindings[0].group; + // TODO(mina): dig into the cause what makes interpreterBindings has no element + if (!paragraphText.startsWith('%') && ((typeof pos !== 'undefined') && pos.row === 0 && pos.column === 1) || + (typeof pos === 'undefined') && $scope.$parent.interpreterBindings.length !== 0) { + magic = $scope.$parent.interpreterBindings[0].name; + getAndSetEditorSetting(session, magic); } else { var replNameRegexp = /%(.+?)\s/g; var match = replNameRegexp.exec(paragraphText); - if (match) { - magic = match[1]; + if (match && $scope.magic !== match[1]) { + magic = match[1].trim(); + $scope.magic = magic; + getAndSetEditorSetting(session, magic); } } - if (magic) { - var promise = getEditorSetting(magic); - promise.then(function(editorSetting) { - if (!_.isEmpty(editorSetting.editor)) { - var mode = 'ace/mode/' + editorSetting.editor.language; - $scope.paragraph.config.editorMode = mode; - session.setMode(mode); - } - }); - } } } }; From 08ccad9bebc88f79289debac214eeb10eb872134 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Mon, 12 Sep 2016 14:13:33 +0200 Subject: [PATCH 08/10] Fix test --- .../zeppelin/notebook/NotebookTest.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index c3bf09c0c1a..a09a6054e56 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -83,6 +83,8 @@ public void setUp() throws Exception { "org.apache.zeppelin.interpreter.mock.MockInterpreter1," + "org.apache.zeppelin.interpreter.mock.MockInterpreter2," + "org.apache.zeppelin.interpreter.mock.MockInterpreter11"); + System.setProperty(ConfVars.ZEPPELIN_INTERPRETER_GROUP_ORDER.getVarName(), + "mock1,mock2,mock11,dev"); conf = ZeppelinConfiguration.create(); @@ -92,7 +94,7 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); SearchService search = mock(SearchService.class); notebookRepo = new VFSNotebookRepo(conf); @@ -113,7 +115,7 @@ public void testSelectingReplImplementation() throws IOException { Note note = notebook.createNote(null); factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); - // run with defatul repl + // run with default repl Paragraph p1 = note.addParagraph(); Map config = p1.getConfig(); config.put("enabled", true); @@ -301,7 +303,7 @@ public void testSchedule() throws InterruptedException, IOException{ config.put("cron", "* * * * * ?"); note.setConfig(config); notebook.refreshCron(note.getId()); - Thread.sleep(1*1000); + Thread.sleep(1 * 1000); // remove cron scheduler. config.put("cron", null); @@ -310,7 +312,7 @@ public void testSchedule() throws InterruptedException, IOException{ Thread.sleep(1000); dateFinished = p.getDateFinished(); assertNotNull(dateFinished); - Thread.sleep(1*1000); + Thread.sleep(1 * 1000); assertEquals(dateFinished, p.getDateFinished()); } @@ -608,26 +610,26 @@ public void testPermissions() throws IOException { new HashSet(Arrays.asList("user1"))); assertEquals(notebookAuthorization.isOwner(note.getId(), - new HashSet(Arrays.asList("user2"))), false); + new HashSet(Arrays.asList("user2"))), false); assertEquals(notebookAuthorization.isOwner(note.getId(), new HashSet(Arrays.asList("user1"))), true); assertEquals(notebookAuthorization.isReader(note.getId(), - new HashSet(Arrays.asList("user3"))), false); + new HashSet(Arrays.asList("user3"))), false); assertEquals(notebookAuthorization.isReader(note.getId(), - new HashSet(Arrays.asList("user2"))), true); + new HashSet(Arrays.asList("user2"))), true); assertEquals(notebookAuthorization.isWriter(note.getId(), - new HashSet(Arrays.asList("user2"))), false); + new HashSet(Arrays.asList("user2"))), false); assertEquals(notebookAuthorization.isWriter(note.getId(), new HashSet(Arrays.asList("user1"))), true); // Test clearing of permssions notebookAuthorization.setReaders(note.getId(), Sets.newHashSet()); assertEquals(notebookAuthorization.isReader(note.getId(), - new HashSet(Arrays.asList("user2"))), true); + new HashSet(Arrays.asList("user2"))), true); assertEquals(notebookAuthorization.isReader(note.getId(), - new HashSet(Arrays.asList("user3"))), true); + new HashSet(Arrays.asList("user3"))), true); notebook.removeNote(note.getId(), null); } From 2d56222140d5ab34ee322536135bcd34a8d9b639 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Tue, 13 Sep 2016 15:09:17 +0200 Subject: [PATCH 09/10] Add description about default syntax highlight in doc --- docs/development/writingzeppelininterpreter.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/development/writingzeppelininterpreter.md b/docs/development/writingzeppelininterpreter.md index c1d3f18376d..acf72e896cb 100644 --- a/docs/development/writingzeppelininterpreter.md +++ b/docs/development/writingzeppelininterpreter.md @@ -48,7 +48,7 @@ There are three locations where you can store your interpreter group, name and o {ZEPPELIN_INTERPRETER_DIR}/{YOUR_OWN_INTERPRETER_DIR}/interpreter-setting.json ``` -Here is an example of `interpreter-setting.json` on your own interpreter. +Here is an example of `interpreter-setting.json` on your own interpreter. Note that if you don't specify editor object, your interpreter will use plain text mode for syntax highlighting. ```json [ @@ -84,8 +84,8 @@ Finally, Zeppelin uses static initialization with the following: ``` static { - Interpreter.register("MyInterpreterName", MyClassName.class.getName()); - } + Interpreter.register("MyInterpreterName", MyClassName.class.getName()); +} ``` **Static initialization is deprecated and will be supported until 0.6.0.** @@ -106,11 +106,11 @@ To check out the list of languages supported, see the `mode-*.js` files under `z If you want to add a new set of syntax highlighting, 1. Add the `mode-*.js` file to [zeppelin-web/bower.json](https://github.com/apache/zeppelin/blob/master/zeppelin-web/bower.json) ( when built, [zeppelin-web/src/index.html](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/index.html) will be changed automatically. ). -2. Add `editor` object to `interpreter-setting.json` file. If you want to set your language to java, add: +2. Add `editor` object to `interpreter-setting.json` file. If you want to set your language to `java` for example, add: ``` "editor": { - "language": "java" + "language": "java" } ``` From c66fb0ed06c1a48fd449cba63879d32327b48407 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Mon, 19 Sep 2016 19:05:39 +0200 Subject: [PATCH 10/10] Move getEditorSetting to InterpreterFactory class --- .../zeppelin/socket/NotebookServer.java | 7 +-- .../interpreter/InterpreterFactory.java | 30 ++++++++++ .../org/apache/zeppelin/notebook/Note.java | 36 ------------ .../apache/zeppelin/notebook/Paragraph.java | 2 +- .../interpreter/InterpreterFactoryTest.java | 56 ++++++++++++++++++- .../apache/zeppelin/notebook/NoteTest.java | 2 - .../zeppelin/notebook/NotebookTest.java | 44 +++------------ 7 files changed, 95 insertions(+), 82 deletions(-) diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 58db005b6bf..3e54e0579ba 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -251,7 +251,7 @@ public void onMessage(NotebookSocket conn, String msg) { saveInterpreterBindings(conn, messagereceived); break; case EDITOR_SETTING: - getEditorSetting(conn, notebook, messagereceived); + getEditorSetting(conn, messagereceived); break; default: break; @@ -1581,13 +1581,12 @@ public void onRemove(String interpreterGroupId, String name, String noteId, Stri } } - private void getEditorSetting(NotebookSocket conn, Notebook notebook, Message fromMessage) + private void getEditorSetting(NotebookSocket conn, Message fromMessage) throws IOException { String replName = (String) fromMessage.get("magic"); String noteId = getOpenNoteId(conn); - Note note = notebook.getNote(noteId); Message resp = new Message(OP.EDITOR_SETTING); - resp.put("editor", note.getEditorSetting(replName)); + resp.put("editor", notebook().getInterpreterFactory().getEditorSetting(noteId, replName)); conn.send(serializeMessage(resp)); return; } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java index d23207d8ab9..40dcc30b36c 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java @@ -50,6 +50,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; @@ -1283,6 +1284,35 @@ public void setEnv(Map env) { this.env = env; } + public Map getEditorSetting(String noteId, String replName) { + Interpreter intp = getInterpreter(noteId, replName); + Map editor = Maps.newHashMap( + ImmutableMap.builder() + .put("language", "text").build()); + String defaultSettingName = getDefaultInterpreterSetting(noteId).getName(); + String group = StringUtils.EMPTY; + try { + List intpSettings = getInterpreterSettings(noteId); + for (InterpreterSetting intpSetting : intpSettings) { + String[] replNameSplit = replName.split("\\."); + if (replNameSplit.length == 2) { + group = replNameSplit[0]; + } + // when replName is 'name' of interpreter + if (defaultSettingName.equals(intpSetting.getName())) { + editor = getEditorFromSettingByClassName(intpSetting, intp.getClassName()); + } + // when replName is 'alias name' of interpreter or 'group' of interpreter + if (replName.equals(intpSetting.getName()) || group.equals(intpSetting.getName())) { + editor = getEditorFromSettingByClassName(intpSetting, intp.getClassName()); + break; + } + } + } catch (NullPointerException e) { + logger.warn("Couldn't get interpreter editor language"); + } + return editor; + } private Interpreter getDevInterpreter() { if (devInterpreter == null) { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 02b7ee42b98..1281e71589d 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -30,8 +30,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import com.google.gson.Gson; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -652,40 +650,6 @@ public void setInfo(Map info) { this.info = info; } - public Interpreter getRepl(String name) { - return factory.getInterpreter(getId(), name); - } - - public Map getEditorSetting(String replName) { - Interpreter intp = getRepl(replName); - Map editor = Maps.newHashMap( - ImmutableMap.builder() - .put("language", "text").build()); - String defaultSettingName = factory.getDefaultInterpreterSetting(this.getId()).getName(); - String group = StringUtils.EMPTY; - try { - List intpSettings = factory.getInterpreterSettings(this.getId()); - for (InterpreterSetting intpSetting : intpSettings) { - String[] replNameSplit = replName.split("\\."); - if (replNameSplit.length == 2) { - group = replNameSplit[0]; - } - // when replName is 'name' of interpreter - if (defaultSettingName.equals(intpSetting.getName())) { - editor = factory.getEditorFromSettingByClassName(intpSetting, intp.getClassName()); - } - // when replName is 'alias name' of interpreter or 'group' of interpreter - if (replName.equals(intpSetting.getName()) || group.equals(intpSetting.getName())) { - editor = factory.getEditorFromSettingByClassName(intpSetting, intp.getClassName()); - break; - } - } - } catch (NullPointerException e) { - logger.warn("Couldn't get interpreter editor language"); - } - return editor; - } - @Override public void beforeStatusChange(Job job, Status before, Status after) { if (jobListenerFactory != null) { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java index 1fdc8878ada..7807abba416 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java @@ -193,7 +193,7 @@ public static String getScriptBody(String text) { } public Interpreter getRepl(String name) { - return note.getRepl(name); + return factory.getInterpreter(note.getId(), name); } public Interpreter getCurrentRepl() { diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java index f85d4c0652c..09031a59351 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java @@ -34,12 +34,22 @@ import org.apache.zeppelin.interpreter.mock.MockInterpreter1; import org.apache.zeppelin.interpreter.mock.MockInterpreter2; import org.apache.zeppelin.interpreter.remote.RemoteInterpreter; +import org.apache.zeppelin.notebook.JobListenerFactory; +import org.apache.zeppelin.notebook.Note; +import org.apache.zeppelin.notebook.Notebook; +import org.apache.zeppelin.notebook.repo.NotebookRepo; +import org.apache.zeppelin.notebook.repo.VFSNotebookRepo; +import org.apache.zeppelin.scheduler.SchedulerFactory; +import org.apache.zeppelin.search.SearchService; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.quartz.SchedulerException; import org.sonatype.aether.RepositoryException; import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import org.mockito.Mock; public class InterpreterFactoryTest { @@ -47,13 +57,19 @@ public class InterpreterFactoryTest { private File tmpDir; private ZeppelinConfiguration conf; private InterpreterContext context; + private Notebook notebook; + private NotebookRepo notebookRepo; private DependencyResolver depResolver; + private SchedulerFactory schedulerFactory; + @Mock + private JobListenerFactory jobListenerFactory; @Before public void setUp() throws Exception { tmpDir = new File(System.getProperty("java.io.tmpdir")+"/ZeppelinLTest_"+System.currentTimeMillis()); tmpDir.mkdirs(); new File(tmpDir, "conf").mkdirs(); + FileUtils.copyDirectory(new File("src/test/resources/interpreter"), new File(tmpDir, "interpreter")); Map propertiesMockInterpreter1 = new HashMap(); propertiesMockInterpreter1.put("PROPERTY_1", new InterpreterProperty("PROPERTY_1", "", "VALUE_1", "desc")); @@ -62,11 +78,22 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), tmpDir.getAbsolutePath()); - System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), "org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2"); + System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), + "org.apache.zeppelin.interpreter.mock.MockInterpreter1," + + "org.apache.zeppelin.interpreter.mock.MockInterpreter2," + + "org.apache.zeppelin.interpreter.mock.MockInterpreter11"); + System.setProperty(ConfVars.ZEPPELIN_INTERPRETER_GROUP_ORDER.getVarName(), + "mock1,mock2,mock11,dev"); conf = new ZeppelinConfiguration(); + schedulerFactory = new SchedulerFactory(); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); context = new InterpreterContext("note", "id", "title", "text", null, null, null, null, null, null, null); + + SearchService search = mock(SearchService.class); + notebookRepo = new VFSNotebookRepo(conf); + notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, jobListenerFactory, search, + null, null); } @After @@ -128,7 +155,7 @@ public void testRemoteRepl() throws Exception { public void testFactoryDefaultList() throws IOException, RepositoryException { // get default settings List all = factory.getDefaultInterpreterSettingList(); - assertTrue(factory.getRegisteredInterpreterList().size() >= all.size()); + assertTrue(factory.get().size() >= all.size()); } @Test @@ -196,4 +223,29 @@ public void testInvalidInterpreterSettingName() { assertEquals("'.' is invalid for InterpreterSetting name.", e.getMessage()); } } + + + @Test + public void getEditorSetting() throws IOException, RepositoryException, SchedulerException { + List intpIds = new ArrayList<>(); + for(InterpreterSetting intpSetting: factory.get()) { + if (intpSetting.getName().startsWith("mock1")) { + intpIds.add(intpSetting.getId()); + } + } + Note note = notebook.createNote(intpIds, null); + + // get editor setting from interpreter-setting.json + Map editor = factory.getEditorSetting(note.getId(), "mock11"); + assertEquals("java", editor.get("language")); + + // when interpreter is not loaded via interpreter-setting.json + // or editor setting doesn't exit + editor = factory.getEditorSetting(note.getId(), "mock1"); + assertEquals(null, editor.get("language")); + + // when interpreter is not bound to note + editor = factory.getEditorSetting(note.getId(), "mock2"); + assertEquals("text", editor.get("language")); + } } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java index 98e301a088e..a44bfad478a 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java @@ -19,7 +19,6 @@ import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.InterpreterFactory; -import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.scheduler.Scheduler; import org.apache.zeppelin.search.SearchService; @@ -28,7 +27,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import static org.junit.Assert.*; diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index a09a6054e56..18d343cdd0e 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -74,17 +74,11 @@ public void setUp() throws Exception { new File(tmpDir, "conf").mkdirs(); notebookDir = new File(tmpDir + "/notebook"); notebookDir.mkdirs(); - FileUtils.copyDirectory(new File("src/test/resources/interpreter"), new File(tmpDir, "interpreter")); System.setProperty(ConfVars.ZEPPELIN_CONF_DIR.getVarName(), tmpDir.toString() + "/conf"); System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), tmpDir.getAbsolutePath()); System.setProperty(ConfVars.ZEPPELIN_NOTEBOOK_DIR.getVarName(), notebookDir.getAbsolutePath()); - System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), - "org.apache.zeppelin.interpreter.mock.MockInterpreter1," + - "org.apache.zeppelin.interpreter.mock.MockInterpreter2," + - "org.apache.zeppelin.interpreter.mock.MockInterpreter11"); - System.setProperty(ConfVars.ZEPPELIN_INTERPRETER_GROUP_ORDER.getVarName(), - "mock1,mock2,mock11,dev"); + System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), "org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2"); conf = ZeppelinConfiguration.create(); @@ -238,7 +232,7 @@ public void testClearParagraphOutput() throws IOException, SchedulerException{ p1.setText("hello world"); note.run(p1.getId()); - while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); + while(p1.isTerminated() == false || p1.getResult() == null) Thread.yield(); assertEquals("repl1: hello world", p1.getResult().message()); // clear paragraph output/result @@ -273,7 +267,7 @@ public void testRunAll() throws IOException { note.runAll(); // wait for finish - while(p3.isTerminated()==false) { + while(p3.isTerminated() == false) { Thread.yield(); } @@ -285,7 +279,7 @@ public void testRunAll() throws IOException { } @Test - public void testSchedule() throws InterruptedException, IOException{ + public void testSchedule() throws InterruptedException, IOException { // create a note and a paragraph Note note = notebook.createNote(null); factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); @@ -482,8 +476,8 @@ public void testResourceRemovealOnParagraphNoteRemove() throws IOException { p2.setText("%mock2 world"); note.runAll(); - while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); - while(p2.isTerminated()==false || p2.getResult()==null) Thread.yield(); + while (p1.isTerminated() == false || p1.getResult() == null) Thread.yield(); + while (p2.isTerminated() == false || p2.getResult() == null) Thread.yield(); assertEquals(2, ResourcePoolUtils.getAllResources().size()); @@ -622,7 +616,7 @@ public void testPermissions() throws IOException { assertEquals(notebookAuthorization.isWriter(note.getId(), new HashSet(Arrays.asList("user2"))), false); assertEquals(notebookAuthorization.isWriter(note.getId(), - new HashSet(Arrays.asList("user1"))), true); + new HashSet(Arrays.asList("user1"))), true); // Test clearing of permssions notebookAuthorization.setReaders(note.getId(), Sets.newHashSet()); @@ -892,30 +886,6 @@ else if(file.isDirectory()){ } } - @Test - public void getEditorSetting() throws IOException, RepositoryException, SchedulerException { - List intpIds = new ArrayList<>(); - for(InterpreterSetting intpSetting: factory.get()) { - if (intpSetting.getName().startsWith("mock1")) { - intpIds.add(intpSetting.getId()); - } - } - Note note = notebook.createNote(intpIds, null); - - // get editor setting from interpreter-setting.json - Map editor = note.getEditorSetting("mock11"); - assertEquals("java", editor.get("language")); - - // when interpreter is not loaded via interpreter-setting.json - // or editor setting doesn't exit - editor = note.getEditorSetting("mock1"); - assertEquals(null, editor.get("language")); - - // when interpreter is not bound to note - editor = note.getEditorSetting("mock2"); - assertEquals("text", editor.get("language")); - } - @Override public ParagraphJobListener getParagraphJobListener(Note note) { return new ParagraphJobListener(){