diff --git a/flink/src/test/java/org/apache/zeppelin/flink/FlinkInterpreterTest.java b/flink/src/test/java/org/apache/zeppelin/flink/FlinkInterpreterTest.java index 264008adb21..4469c3ee5c8 100644 --- a/flink/src/test/java/org/apache/zeppelin/flink/FlinkInterpreterTest.java +++ b/flink/src/test/java/org/apache/zeppelin/flink/FlinkInterpreterTest.java @@ -38,7 +38,7 @@ public static void setUp() { Properties p = new Properties(); flink = new FlinkInterpreter(p); flink.open(); - context = new InterpreterContext(null, null, null, null, null, null, null); + context = new InterpreterContext(null, null, null, null, null, null, null, null); } @AfterClass diff --git a/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteInterpreterTest.java b/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteInterpreterTest.java index 3d3f50bdd73..ad393a7b12a 100644 --- a/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteInterpreterTest.java +++ b/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteInterpreterTest.java @@ -40,7 +40,7 @@ public class IgniteInterpreterTest { private static final String HOST = "127.0.0.1:47500..47509"; private static final InterpreterContext INTP_CONTEXT = - new InterpreterContext(null, null, null, null, null, null, null); + new InterpreterContext(null, null, null, null, null, null, null, null); private IgniteInterpreter intp; private Ignite ignite; diff --git a/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteSqlInterpreterTest.java b/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteSqlInterpreterTest.java index de1e7609cb5..b5eff965ced 100644 --- a/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteSqlInterpreterTest.java +++ b/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteSqlInterpreterTest.java @@ -43,7 +43,7 @@ public class IgniteSqlInterpreterTest { private static final String HOST = "127.0.0.1:47500..47509"; private static final InterpreterContext INTP_CONTEXT = - new InterpreterContext(null, null, null, null, null, null, null); + new InterpreterContext(null, null, null, null, null, null, null, null); private Ignite ignite; private IgniteSqlInterpreter intp; diff --git a/spark/src/main/java/org/apache/zeppelin/spark/ZeppelinContext.java b/spark/src/main/java/org/apache/zeppelin/spark/ZeppelinContext.java index 2c03f1cd91b..6cb94d9e927 100644 --- a/spark/src/main/java/org/apache/zeppelin/spark/ZeppelinContext.java +++ b/spark/src/main/java/org/apache/zeppelin/spark/ZeppelinContext.java @@ -466,45 +466,232 @@ public List listParagraphs() { } + private AngularObject getAngularObject(String name, InterpreterContext interpreterContext) { + AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); + String noteId = interpreterContext.getNoteId(); + // try get local object + AngularObject ao = registry.get(name, interpreterContext.getNoteId()); + if (ao == null) { + // then global object + ao = registry.get(name, null); + } + return ao; + } + + /** + * Get angular object. Look up local registry first and then global registry + * @param name variable name + * @return value + */ public Object angular(String name) { + AngularObject ao = getAngularObject(name, interpreterContext); + if (ao == null) { + return null; + } else { + return ao.get(); + } + } + + /** + * Get angular object. Look up global registry + * @param name variable name + * @return value + */ + public Object angularGlobal(String name) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - AngularObject ao = registry.get(name); + AngularObject ao = registry.get(name, null); if (ao == null) { return null; } else { return ao.get(); } + } + + /** + * Create angular variable in local registry and bind with front end Angular display system. + * If variable exists, it'll be overwritten. + * @param name name of the variable + * @param o value + */ + public void angularBind(String name, Object o) { + angularBind(name, o, interpreterContext.getNoteId()); + } + + /** + * Create angular variable in global registry and bind with front end Angular display system. + * If variable exists, it'll be overwritten. + * @param name name of the variable + * @param o value + */ + public void angularBindGlobal(String name, Object o) { + angularBind(name, o, (String) null); + } + + /** + * Create angular variable in local registry and bind with front end Angular display system. + * If variable exists, value will be overwritten and watcher will be added. + * @param name name of variable + * @param o value + * @param watcher watcher of the variable + */ + public void angularBind(String name, Object o, AngularObjectWatcher watcher) { + angularBind(name, o, interpreterContext.getNoteId(), watcher); + } + + /** + * Create angular variable in global registry and bind with front end Angular display system. + * If variable exists, value will be overwritten and watcher will be added. + * @param name name of variable + * @param o value + * @param watcher watcher of the variable + */ + public void angularBindGlobal(String name, Object o, AngularObjectWatcher watcher) { + angularBind(name, o, null, watcher); } - public void angularBind(String name, Object o) { + /** + * Add watcher into angular variable (local registry) + * @param name name of the variable + * @param watcher watcher + */ + public void angularWatch(String name, AngularObjectWatcher watcher) { + angularWatch(name, interpreterContext.getNoteId(), watcher); + } + + /** + * Add watcher into angular variable (global registry) + * @param name name of the variable + * @param watcher watcher + */ + public void angularWatchGlobal(String name, AngularObjectWatcher watcher) { + angularWatch(name, null, watcher); + } + + + public void angularWatch(String name, + final scala.Function2 func) { + angularWatch(name, interpreterContext.getNoteId(), func); + } + + public void angularWatchGlobal(String name, + final scala.Function2 func) { + angularWatch(name, null, func); + } + + public void angularWatch( + String name, + final scala.Function3 func) { + angularWatch(name, interpreterContext.getNoteId(), func); + } + + public void angularWatchGlobal( + String name, + final scala.Function3 func) { + angularWatch(name, null, func); + } + + /** + * Remove watcher from angular variable (local) + * @param name + * @param watcher + */ + public void angularUnwatch(String name, AngularObjectWatcher watcher) { + angularUnwatch(name, interpreterContext.getNoteId(), watcher); + } + + /** + * Remove watcher from angular variable (global) + * @param name + * @param watcher + */ + public void angularUnwatchGlobal(String name, AngularObjectWatcher watcher) { + angularUnwatch(name, null, watcher); + } + + + /** + * Remove all watchers for the angular variable (local) + * @param name + */ + public void angularUnwatch(String name) { + angularUnwatch(name, interpreterContext.getNoteId()); + } + + /** + * Remove all watchers for the angular variable (global) + * @param name + */ + public void angularUnwatchGlobal(String name) { + angularUnwatch(name, (String) null); + } + + /** + * Remove angular variable and all the watchers. + * @param name + */ + public void angularUnbind(String name) { + String noteId = interpreterContext.getNoteId(); + angularUnbind(name, noteId); + } + + /** + * Remove angular variable and all the watchers. + * @param name + */ + public void angularUnbindGlobal(String name) { + angularUnbind(name, null); + } + + /** + * Create angular variable in local registry and bind with front end Angular display system. + * If variable exists, it'll be overwritten. + * @param name name of the variable + * @param o value + */ + private void angularBind(String name, Object o, String noteId) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - if (registry.get(name) == null) { - registry.add(name, o); + + if (registry.get(name, noteId) == null) { + registry.add(name, o, noteId); } else { - registry.get(name).set(o); + registry.get(name, noteId).set(o); } } - - public void angularBind(String name, Object o, AngularObjectWatcher w) { + + /** + * Create angular variable in local registry and bind with front end Angular display system. + * If variable exists, value will be overwritten and watcher will be added. + * @param name name of variable + * @param o value + * @param watcher watcher of the variable + */ + private void angularBind(String name, Object o, String noteId, AngularObjectWatcher watcher) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - if (registry.get(name) == null) { - registry.add(name, o); + + if (registry.get(name, noteId) == null) { + registry.add(name, o, noteId); } else { - registry.get(name).set(o); + registry.get(name, noteId).set(o); } - angularWatch(name, w); + angularWatch(name, watcher); } - public void angularWatch(String name, AngularObjectWatcher w) { + /** + * Add watcher into angular binding variable + * @param name name of the variable + * @param watcher watcher + */ + private void angularWatch(String name, String noteId, AngularObjectWatcher watcher) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - if (registry.get(name) != null) { - registry.get(name).addWatcher(w); + + if (registry.get(name, noteId) != null) { + registry.get(name, noteId).addWatcher(watcher); } } - public void angularWatch(String name, + private void angularWatch(String name, String noteId, final scala.Function2 func) { AngularObjectWatcher w = new AngularObjectWatcher(getInterpreterContext()) { @Override @@ -513,11 +700,12 @@ public void watch(Object oldObject, Object newObject, func.apply(newObject, newObject); } }; - angularWatch(name, w); + angularWatch(name, noteId, w); } - public void angularWatch( + private void angularWatch( String name, + String noteId, final scala.Function3 func) { AngularObjectWatcher w = new AngularObjectWatcher(getInterpreterContext()) { @Override @@ -526,25 +714,38 @@ public void watch(Object oldObject, Object newObject, func.apply(oldObject, newObject, context); } }; - angularWatch(name, w); - } + angularWatch(name, noteId, w); + } - public void angularUnwatch(String name, AngularObjectWatcher w) { + /** + * Remove watcher + * @param name + * @param watcher + */ + private void angularUnwatch(String name, String noteId, AngularObjectWatcher watcher) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - if (registry.get(name) != null) { - registry.get(name).removeWatcher(w); + if (registry.get(name, noteId) != null) { + registry.get(name, noteId).removeWatcher(watcher); } } - public void angularUnwatch(String name) { + /** + * Remove all watchers for the angular variable + * @param name + */ + private void angularUnwatch(String name, String noteId) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - if (registry.get(name) != null) { - registry.get(name).clearAllWatchers(); + if (registry.get(name, noteId) != null) { + registry.get(name, noteId).clearAllWatchers(); } } - public void angularUnbind(String name) { + /** + * Remove angular variable and all the watchers. + * @param name + */ + private void angularUnbind(String name, String noteId) { AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry(); - registry.remove(name); + registry.remove(name, noteId); } } diff --git a/spark/src/test/java/org/apache/zeppelin/spark/DepInterpreterTest.java b/spark/src/test/java/org/apache/zeppelin/spark/DepInterpreterTest.java index 2f8254d198b..6adaa14f7b4 100644 --- a/spark/src/test/java/org/apache/zeppelin/spark/DepInterpreterTest.java +++ b/spark/src/test/java/org/apache/zeppelin/spark/DepInterpreterTest.java @@ -58,7 +58,7 @@ public void setUp() throws Exception { intpGroup.add(dep); dep.setInterpreterGroup(intpGroup); - context = new InterpreterContext("id", "title", "text", new HashMap(), new GUI(), + context = new InterpreterContext("note", "id", "title", "text", new HashMap(), new GUI(), new AngularObjectRegistry(intpGroup.getId(), null), new LinkedList()); } diff --git a/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java b/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java index c97e824f5b3..daa7eeda81d 100644 --- a/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java +++ b/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java @@ -75,7 +75,7 @@ public void setUp() throws Exception { } InterpreterGroup intpGroup = new InterpreterGroup(); - context = new InterpreterContext("id", "title", "text", + context = new InterpreterContext("note", "id", "title", "text", new HashMap(), new GUI(), new AngularObjectRegistry( intpGroup.getId(), null), new LinkedList()); diff --git a/spark/src/test/java/org/apache/zeppelin/spark/SparkSqlInterpreterTest.java b/spark/src/test/java/org/apache/zeppelin/spark/SparkSqlInterpreterTest.java index 30166a7848f..bb818fd2c56 100644 --- a/spark/src/test/java/org/apache/zeppelin/spark/SparkSqlInterpreterTest.java +++ b/spark/src/test/java/org/apache/zeppelin/spark/SparkSqlInterpreterTest.java @@ -63,7 +63,7 @@ public void setUp() throws Exception { sql.setInterpreterGroup(intpGroup); sql.open(); } - context = new InterpreterContext("id", "title", "text", new HashMap(), new GUI(), + context = new InterpreterContext("note", "id", "title", "text", new HashMap(), new GUI(), new AngularObjectRegistry(intpGroup.getId(), null), new LinkedList()); } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObject.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObject.java index bbfcd1b184d..cebe4cc4911 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObject.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObject.java @@ -33,13 +33,17 @@ public class AngularObject { private String name; private T object; + private transient AngularObjectListener listener; private transient List watchers = new LinkedList(); + + private String noteId; // noteId belonging to. null for global scope - protected AngularObject(String name, T o, + protected AngularObject(String name, T o, String noteId, AngularObjectListener listener) { this.name = name; + this.noteId = noteId; this.listener = listener; object = o; } @@ -47,14 +51,29 @@ protected AngularObject(String name, T o, public String getName() { return name; } + + public void setNoteId(String noteId) { + this.noteId = noteId; + } + + public String getNoteId() { + return noteId; + } + + public boolean isGlobal() { + return noteId == null; + } @Override public boolean equals(Object o) { if (o instanceof AngularObject) { - return name.equals(((AngularObject) o).name); - } else { - return false; + AngularObject ao = (AngularObject) o; + if (noteId == null && ao.noteId == null || + (noteId != null && ao.noteId != null && noteId.equals(ao.noteId))) { + return name.equals(ao.name); + } } + return false; } public Object get() { @@ -66,7 +85,7 @@ public void emit(){ listener.updated(this); } } - + public void set(T o) { set(o, true); } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistry.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistry.java index 56eca22d895..d6bab7b732c 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistry.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistry.java @@ -17,19 +17,26 @@ package org.apache.zeppelin.display; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** - * - * + * AngularObjectRegistry keeps all the object that binded to Angular Display System. + * AngularObjectRegistry is created per interpreter group. + * It keeps two different set of AngularObjects : + * - globalRegistry: Shared to all notebook that uses the same interpreter group + * - localRegistry: AngularObject is valid only inside of a single notebook */ public class AngularObjectRegistry { - Map registry = new HashMap(); + Map> registry = + new HashMap>(); + private final String GLOBAL_KEY = "_GLOBAL_"; private AngularObjectRegistryListener listener; private String interpreterId; + AngularObjectListener angularObjectListener; @@ -51,15 +58,42 @@ public AngularObjectRegistryListener getListener() { return listener; } - public AngularObject add(String name, Object o) { - return add(name, o, true); + /** + * Add object into registry + * @param name + * @param o + * @param noteId noteId belonging to. null for global object. + * @return + */ + public AngularObject add(String name, Object o, String noteId) { + return add(name, o, noteId, true); } - public AngularObject add(String name, Object o, boolean emit) { - AngularObject ao = createNewAngularObject(name, o); + private String getRegistryKey(String noteId) { + if (noteId == null) { + return GLOBAL_KEY; + } else { + return noteId; + } + } + + private Map getRegistryForKey(String noteId) { + synchronized (registry) { + String key = getRegistryKey(noteId); + if (!registry.containsKey(key)) { + registry.put(key, new HashMap()); + } + + return registry.get(key); + } + } + + public AngularObject add(String name, Object o, String noteId, boolean emit) { + AngularObject ao = createNewAngularObject(name, o, noteId); synchronized (registry) { - registry.put(name, ao); + Map noteLocalRegistry = getRegistryForKey(noteId); + noteLocalRegistry.put(name, ao); if (listener != null && emit) { listener.onAdd(interpreterId, ao); } @@ -68,34 +102,72 @@ public AngularObject add(String name, Object o, boolean emit) { return ao; } - protected AngularObject createNewAngularObject(String name, Object o) { - return new AngularObject(name, o, angularObjectListener); + protected AngularObject createNewAngularObject(String name, Object o, String noteId) { + return new AngularObject(name, o, noteId, angularObjectListener); } protected AngularObjectListener getAngularObjectListener() { return angularObjectListener; } - public AngularObject remove(String name) { + public AngularObject remove(String name, String noteId) { + return remove(name, noteId, true); + } + + public AngularObject remove(String name, String noteId, boolean emit) { synchronized (registry) { - AngularObject o = registry.remove(name); - if (listener != null) { - listener.onRemove(interpreterId, o);; + Map r = getRegistryForKey(noteId); + AngularObject o = r.remove(name); + if (listener != null && emit) { + listener.onRemove(interpreterId, name, noteId);; } return o; } } - public AngularObject get(String name) { + public void removeAll(String noteId) { + synchronized (registry) { + List all = getAll(noteId); + for (AngularObject ao : all) { + remove(ao.getName(), noteId); + } + } + } + + public AngularObject get(String name, String noteId) { synchronized (registry) { - return registry.get(name); + Map r = getRegistryForKey(noteId); + return r.get(name); } } - public List getAll() { + public List getAll(String noteId) { + List all = new LinkedList(); + synchronized (registry) { + Map r = getRegistryForKey(noteId); + if (r != null) { + all.addAll(r.values()); + } + } + return all; + } + + /** + * Get all object with global merged + * @param noteId + * @return + */ + public List getAllWithGlobal(String noteId) { List all = new LinkedList(); synchronized (registry) { - all.addAll(registry.values()); + Map global = getRegistryForKey(null); + if (global != null) { + all.addAll(global.values()); + } + Map local = getRegistryForKey(noteId); + if (local != null) { + all.addAll(local.values()); + } } return all; } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistryListener.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistryListener.java index 3f08efae4a2..3ba57d7b1af 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistryListener.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistryListener.java @@ -24,5 +24,5 @@ public interface AngularObjectRegistryListener { public void onAdd(String interpreterGroupId, AngularObject object); public void onUpdate(String interpreterGroupId, AngularObject object); - public void onRemove(String interpreterGroupId, AngularObject object); + public void onRemove(String interpreterGroupId, String name, String noteId); } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java index 2e4564e09ef..7c2f6c0d726 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java @@ -27,6 +27,7 @@ * Interpreter context */ public class InterpreterContext { + private final String noteId; private final String paragraphTitle; private final String paragraphId; private final String paragraphText; @@ -35,7 +36,8 @@ public class InterpreterContext { private AngularObjectRegistry angularObjectRegistry; private List runners; - public InterpreterContext(String paragraphId, + public InterpreterContext(String noteId, + String paragraphId, String paragraphTitle, String paragraphText, Map config, @@ -43,6 +45,7 @@ public InterpreterContext(String paragraphId, AngularObjectRegistry angularObjectRegistry, List runners ) { + this.noteId = noteId; this.paragraphId = paragraphId; this.paragraphTitle = paragraphTitle; this.paragraphText = paragraphText; @@ -52,6 +55,11 @@ public InterpreterContext(String paragraphId, this.runners = runners; } + + public String getNoteId() { + return noteId; + } + public String getParagraphId() { return paragraphId; } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObject.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObject.java index 3abd7644ef6..351a2bb1b4a 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObject.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObject.java @@ -27,10 +27,10 @@ public class RemoteAngularObject extends AngularObject { private transient RemoteInterpreterProcess remoteInterpreterProcess; - RemoteAngularObject(String name, Object o, String interpreterGroupId, + RemoteAngularObject(String name, Object o, String noteId, String interpreterGroupId, AngularObjectListener listener, RemoteInterpreterProcess remoteInterpreterProcess) { - super(name, o, listener); + super(name, o, noteId, listener); this.remoteInterpreterProcess = remoteInterpreterProcess; } @@ -44,7 +44,7 @@ public void set(Object o, boolean emitWeb, boolean emitRemoteProcess) { if (emitRemoteProcess) { // send updated value to remote interpreter - remoteInterpreterProcess.updateRemoteAngularObject(getName(), o); + remoteInterpreterProcess.updateRemoteAngularObject(getName(), getNoteId(), o); } } } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectRegistry.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectRegistry.java index c711f69009f..b7ac014c2e8 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectRegistry.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectRegistry.java @@ -17,18 +17,25 @@ package org.apache.zeppelin.interpreter.remote; +import java.util.List; + import org.apache.zeppelin.display.AngularObject; import org.apache.zeppelin.display.AngularObjectRegistry; import org.apache.zeppelin.display.AngularObjectRegistryListener; import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.InterpreterGroup; import org.apache.zeppelin.interpreter.WrappedInterpreter; +import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService.Client; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; /** * */ public class RemoteAngularObjectRegistry extends AngularObjectRegistry { - + Logger logger = LoggerFactory.getLogger(RemoteAngularObjectRegistry.class); private InterpreterGroup interpreterGroup; public RemoteAngularObjectRegistry(String interpreterId, @@ -54,13 +61,79 @@ private RemoteInterpreterProcess getRemoteInterpreterProcess() { } } + /** + * When ZeppelinServer side code want to add angularObject to the registry, + * this method should be used instead of add() + * @param name + * @param o + * @param noteId + * @return + */ + public AngularObject addAndNotifyRemoteProcess(String name, Object o, String noteId) { + Gson gson = new Gson(); + RemoteInterpreterProcess remoteInterpreterProcess = getRemoteInterpreterProcess(); + if (!remoteInterpreterProcess.isRunning()) { + return null; + } + + Client client = null; + try { + client = remoteInterpreterProcess.getClient(); + client.angularObjectAdd(name, noteId, gson.toJson(o)); + return super.add(name, o, noteId, true); + } catch (Exception e) { + logger.error("Error", e); + } finally { + if (client != null) { + remoteInterpreterProcess.releaseClient(client); + } + } + return null; + } + + /** + * When ZeppelinServer side code want to remove angularObject from the registry, + * this method should be used instead of remove() + * @param name + * @param noteId + * @param emit + * @return + */ + public AngularObject removeAndNotifyRemoteProcess(String name, String noteId) { + RemoteInterpreterProcess remoteInterpreterProcess = getRemoteInterpreterProcess(); + if (!remoteInterpreterProcess.isRunning()) { + return null; + } + + Client client = null; + try { + client = remoteInterpreterProcess.getClient(); + client.angularObjectRemove(name, noteId); + return super.remove(name, noteId); + } catch (Exception e) { + logger.error("Error", e); + } finally { + if (client != null) { + remoteInterpreterProcess.releaseClient(client); + } + } + return null; + } + + public void removeAllAndNotifyRemoteProcess(String noteId) { + List all = getAll(noteId); + for (AngularObject ao : all) { + removeAndNotifyRemoteProcess(ao.getName(), noteId); + } + } + @Override - protected AngularObject createNewAngularObject(String name, Object o) { + protected AngularObject createNewAngularObject(String name, Object o, String noteId) { RemoteInterpreterProcess remoteInterpreterProcess = getRemoteInterpreterProcess(); if (remoteInterpreterProcess == null) { throw new RuntimeException("Remote Interpreter process not found"); } - return new RemoteAngularObject(name, o, getInterpreterGroupId(), + return new RemoteAngularObject(name, o, noteId, getInterpreterGroupId(), getAngularObjectListener(), getRemoteInterpreterProcess()); } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java index 8992f5507ed..d5d92c83c01 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java @@ -356,6 +356,7 @@ private String getInterpreterGroupKey(InterpreterGroup interpreterGroup) { private RemoteInterpreterContext convert(InterpreterContext ic) { return new RemoteInterpreterContext( + ic.getNoteId(), ic.getParagraphId(), ic.getParagraphTitle(), ic.getParagraphText(), diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterEventPoller.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterEventPoller.java index 4997b0eb10b..f39f6a6aa10 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterEventPoller.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterEventPoller.java @@ -85,10 +85,13 @@ public void run() { continue; } else if (event.getType() == RemoteInterpreterEventType.ANGULAR_OBJECT_ADD) { AngularObject angularObject = gson.fromJson(event.getData(), AngularObject.class); - angularObjectRegistry.add(angularObject.getName(), angularObject.get()); + angularObjectRegistry.add(angularObject.getName(), + angularObject.get(), angularObject.getNoteId()); } else if (event.getType() == RemoteInterpreterEventType.ANGULAR_OBJECT_UPDATE) { - AngularObject angularObject = gson.fromJson(event.getData(), AngularObject.class); - AngularObject localAngularObject = angularObjectRegistry.get(angularObject.getName()); + AngularObject angularObject = gson.fromJson(event.getData(), + AngularObject.class); + AngularObject localAngularObject = angularObjectRegistry.get( + angularObject.getName(), angularObject.getNoteId()); if (localAngularObject instanceof RemoteAngularObject) { // to avoid ping-pong loop ((RemoteAngularObject) localAngularObject).set( @@ -98,7 +101,7 @@ public void run() { } } else if (event.getType() == RemoteInterpreterEventType.ANGULAR_OBJECT_REMOVE) { AngularObject angularObject = gson.fromJson(event.getData(), AngularObject.class); - angularObjectRegistry.remove(angularObject.getName()); + angularObjectRegistry.remove(angularObject.getName(), angularObject.getNoteId()); } else if (event.getType() == RemoteInterpreterEventType.RUN_INTERPRETER_CONTEXT_RUNNER) { InterpreterContextRunner runnerFromRemote = gson.fromJson( event.getData(), RemoteInterpreterContextRunner.class); @@ -106,6 +109,7 @@ public void run() { interpreterProcess.getInterpreterContextRunnerPool().run( runnerFromRemote.getNoteId(), runnerFromRemote.getParagraphId()); } + logger.debug("Event from remoteproceess {}", event.getType()); } catch (Exception e) { logger.error("Can't handle event " + event, e); } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java index 91edd41d88d..534af271d2f 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java @@ -236,7 +236,7 @@ public int getNumIdleClient() { * @param name * @param o */ - public void updateRemoteAngularObject(String name, Object o) { + public void updateRemoteAngularObject(String name, String noteId, Object o) { Client client = null; try { client = getClient(); @@ -249,7 +249,7 @@ public void updateRemoteAngularObject(String name, Object o) { try { Gson gson = new Gson(); - client.angularObjectUpdate(name, gson.toJson(o)); + client.angularObjectUpdate(name, noteId, gson.toJson(o)); } catch (TException e) { logger.error("Can't update angular object", e); } finally { diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java index 33baf9ac0bd..16b188394d0 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java @@ -21,6 +21,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URL; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -320,6 +321,7 @@ private InterpreterContext convert(RemoteInterpreterContext ric) { } return new InterpreterContext( + ric.getNoteId(), ric.getParagraphId(), ric.getParagraphTitle(), ric.getParagraphText(), @@ -395,9 +397,13 @@ public void onUpdate(String interpreterGroupId, AngularObject object) { } @Override - public void onRemove(String interpreterGroupId, AngularObject object) { + public void onRemove(String interpreterGroupId, String name, String noteId) { + Map removeObject = new HashMap(); + removeObject.put("name", name); + removeObject.put("noteId", noteId); + sendEvent(new RemoteInterpreterEvent( - RemoteInterpreterEventType.ANGULAR_OBJECT_REMOVE, gson.toJson(object))); + RemoteInterpreterEventType.ANGULAR_OBJECT_REMOVE, gson.toJson(removeObject))); } private void sendEvent(RemoteInterpreterEvent event) { @@ -429,14 +435,16 @@ public RemoteInterpreterEvent getEvent() throws TException { * called when object is updated in client (web) side. * @param className * @param name + * @param noteId noteId where the update issues * @param object * @throws TException */ @Override - public void angularObjectUpdate(String name, String object) + public void angularObjectUpdate(String name, String noteId, String object) throws TException { AngularObjectRegistry registry = interpreterGroup.getAngularObjectRegistry(); - AngularObject ao = registry.get(name); + // first try local objects + AngularObject ao = registry.get(name, noteId); if (ao == null) { logger.error("Angular object {} not exists", name); return; @@ -448,8 +456,8 @@ public void angularObjectUpdate(String name, String object) } Object oldObject = ao.get(); + Object value = null; if (oldObject != null) { // first try with previous object's type - Object value; try { value = gson.fromJson(object, oldObject.getClass()); ao.set(value, false); @@ -460,9 +468,60 @@ public void angularObjectUpdate(String name, String object) } // Generic java object type for json. - Map value = gson.fromJson(object, - new TypeToken>() { - }.getType()); + if (value == null) { + try { + value = gson.fromJson(object, + new TypeToken>() { + }.getType()); + } catch (Exception e) { + // no lock + } + } + + // try string object type at last + if (value == null) { + value = gson.fromJson(object, String.class); + } + ao.set(value, false); } + + /** + * When zeppelinserver initiate angular object add. + * Dont't need to emit event to zeppelin server + */ + @Override + public void angularObjectAdd(String name, String noteId, String object) + throws TException { + AngularObjectRegistry registry = interpreterGroup.getAngularObjectRegistry(); + // first try local objects + AngularObject ao = registry.get(name, noteId); + if (ao != null) { + angularObjectUpdate(name, noteId, object); + return; + } + + // Generic java object type for json. + Object value = null; + try { + value = gson.fromJson(object, + new TypeToken>() { + }.getType()); + } catch (Exception e) { + // nolock + } + + // try string object type at last + if (value == null) { + value = gson.fromJson(object, String.class); + } + + registry.add(name, value, noteId, false); + } + + @Override + public void angularObjectRemove(String name, String noteId) throws TException { + AngularObjectRegistry registry = interpreterGroup.getAngularObjectRegistry(); + registry.remove(name, noteId, false); + } } diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java index 9827a45fdb0..7a757ab4f42 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java @@ -33,12 +33,13 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterContext"); - private static final org.apache.thrift.protocol.TField PARAGRAPH_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphId", org.apache.thrift.protocol.TType.STRING, (short)1); - private static final org.apache.thrift.protocol.TField PARAGRAPH_TITLE_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphTitle", org.apache.thrift.protocol.TType.STRING, (short)2); - private static final org.apache.thrift.protocol.TField PARAGRAPH_TEXT_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphText", org.apache.thrift.protocol.TType.STRING, (short)3); - private static final org.apache.thrift.protocol.TField CONFIG_FIELD_DESC = new org.apache.thrift.protocol.TField("config", org.apache.thrift.protocol.TType.STRING, (short)4); - private static final org.apache.thrift.protocol.TField GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("gui", org.apache.thrift.protocol.TType.STRING, (short)5); - private static final org.apache.thrift.protocol.TField RUNNERS_FIELD_DESC = new org.apache.thrift.protocol.TField("runners", org.apache.thrift.protocol.TType.STRING, (short)6); + private static final org.apache.thrift.protocol.TField NOTE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("noteId", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField PARAGRAPH_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphId", org.apache.thrift.protocol.TType.STRING, (short)2); + private static final org.apache.thrift.protocol.TField PARAGRAPH_TITLE_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphTitle", org.apache.thrift.protocol.TType.STRING, (short)3); + private static final org.apache.thrift.protocol.TField PARAGRAPH_TEXT_FIELD_DESC = new org.apache.thrift.protocol.TField("paragraphText", org.apache.thrift.protocol.TType.STRING, (short)4); + private static final org.apache.thrift.protocol.TField CONFIG_FIELD_DESC = new org.apache.thrift.protocol.TField("config", org.apache.thrift.protocol.TType.STRING, (short)5); + private static final org.apache.thrift.protocol.TField GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("gui", org.apache.thrift.protocol.TType.STRING, (short)6); + private static final org.apache.thrift.protocol.TField RUNNERS_FIELD_DESC = new org.apache.thrift.protocol.TField("runners", org.apache.thrift.protocol.TType.STRING, (short)7); private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); static { @@ -46,6 +47,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase byName = new HashMap(); @@ -75,17 +78,19 @@ public enum _Fields implements org.apache.thrift.TFieldIdEnum { */ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { - case 1: // PARAGRAPH_ID + case 1: // NOTE_ID + return NOTE_ID; + case 2: // PARAGRAPH_ID return PARAGRAPH_ID; - case 2: // PARAGRAPH_TITLE + case 3: // PARAGRAPH_TITLE return PARAGRAPH_TITLE; - case 3: // PARAGRAPH_TEXT + case 4: // PARAGRAPH_TEXT return PARAGRAPH_TEXT; - case 4: // CONFIG + case 5: // CONFIG return CONFIG; - case 5: // GUI + case 6: // GUI return GUI; - case 6: // RUNNERS + case 7: // RUNNERS return RUNNERS; default: return null; @@ -130,6 +135,8 @@ public String getFieldName() { public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.NOTE_ID, new org.apache.thrift.meta_data.FieldMetaData("noteId", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.PARAGRAPH_ID, new org.apache.thrift.meta_data.FieldMetaData("paragraphId", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.PARAGRAPH_TITLE, new org.apache.thrift.meta_data.FieldMetaData("paragraphTitle", org.apache.thrift.TFieldRequirementType.DEFAULT, @@ -150,6 +157,7 @@ public RemoteInterpreterContext() { } public RemoteInterpreterContext( + String noteId, String paragraphId, String paragraphTitle, String paragraphText, @@ -158,6 +166,7 @@ public RemoteInterpreterContext( String runners) { this(); + this.noteId = noteId; this.paragraphId = paragraphId; this.paragraphTitle = paragraphTitle; this.paragraphText = paragraphText; @@ -170,6 +179,9 @@ public RemoteInterpreterContext( * Performs a deep copy on other. */ public RemoteInterpreterContext(RemoteInterpreterContext other) { + if (other.isSetNoteId()) { + this.noteId = other.noteId; + } if (other.isSetParagraphId()) { this.paragraphId = other.paragraphId; } @@ -196,6 +208,7 @@ public RemoteInterpreterContext deepCopy() { @Override public void clear() { + this.noteId = null; this.paragraphId = null; this.paragraphTitle = null; this.paragraphText = null; @@ -204,6 +217,30 @@ public void clear() { this.runners = null; } + public String getNoteId() { + return this.noteId; + } + + public RemoteInterpreterContext setNoteId(String noteId) { + this.noteId = noteId; + return this; + } + + public void unsetNoteId() { + this.noteId = null; + } + + /** Returns true if field noteId is set (has been assigned a value) and false otherwise */ + public boolean isSetNoteId() { + return this.noteId != null; + } + + public void setNoteIdIsSet(boolean value) { + if (!value) { + this.noteId = null; + } + } + public String getParagraphId() { return this.paragraphId; } @@ -350,6 +387,14 @@ public void setRunnersIsSet(boolean value) { public void setFieldValue(_Fields field, Object value) { switch (field) { + case NOTE_ID: + if (value == null) { + unsetNoteId(); + } else { + setNoteId((String)value); + } + break; + case PARAGRAPH_ID: if (value == null) { unsetParagraphId(); @@ -403,6 +448,9 @@ public void setFieldValue(_Fields field, Object value) { public Object getFieldValue(_Fields field) { switch (field) { + case NOTE_ID: + return getNoteId(); + case PARAGRAPH_ID: return getParagraphId(); @@ -432,6 +480,8 @@ public boolean isSet(_Fields field) { } switch (field) { + case NOTE_ID: + return isSetNoteId(); case PARAGRAPH_ID: return isSetParagraphId(); case PARAGRAPH_TITLE: @@ -461,6 +511,15 @@ public boolean equals(RemoteInterpreterContext that) { if (that == null) return false; + boolean this_present_noteId = true && this.isSetNoteId(); + boolean that_present_noteId = true && that.isSetNoteId(); + if (this_present_noteId || that_present_noteId) { + if (!(this_present_noteId && that_present_noteId)) + return false; + if (!this.noteId.equals(that.noteId)) + return false; + } + boolean this_present_paragraphId = true && this.isSetParagraphId(); boolean that_present_paragraphId = true && that.isSetParagraphId(); if (this_present_paragraphId || that_present_paragraphId) { @@ -531,6 +590,16 @@ public int compareTo(RemoteInterpreterContext other) { int lastComparison = 0; RemoteInterpreterContext typedOther = (RemoteInterpreterContext)other; + lastComparison = Boolean.valueOf(isSetNoteId()).compareTo(typedOther.isSetNoteId()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNoteId()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteId, typedOther.noteId); + if (lastComparison != 0) { + return lastComparison; + } + } lastComparison = Boolean.valueOf(isSetParagraphId()).compareTo(typedOther.isSetParagraphId()); if (lastComparison != 0) { return lastComparison; @@ -611,6 +680,14 @@ public String toString() { StringBuilder sb = new StringBuilder("RemoteInterpreterContext("); boolean first = true; + sb.append("noteId:"); + if (this.noteId == null) { + sb.append("null"); + } else { + sb.append(this.noteId); + } + first = false; + if (!first) sb.append(", "); sb.append("paragraphId:"); if (this.paragraphId == null) { sb.append("null"); @@ -701,7 +778,15 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo break; } switch (schemeField.id) { - case 1: // PARAGRAPH_ID + case 1: // NOTE_ID + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // PARAGRAPH_ID if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.paragraphId = iprot.readString(); struct.setParagraphIdIsSet(true); @@ -709,7 +794,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 2: // PARAGRAPH_TITLE + case 3: // PARAGRAPH_TITLE if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.paragraphTitle = iprot.readString(); struct.setParagraphTitleIsSet(true); @@ -717,7 +802,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 3: // PARAGRAPH_TEXT + case 4: // PARAGRAPH_TEXT if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.paragraphText = iprot.readString(); struct.setParagraphTextIsSet(true); @@ -725,7 +810,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 4: // CONFIG + case 5: // CONFIG if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.config = iprot.readString(); struct.setConfigIsSet(true); @@ -733,7 +818,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 5: // GUI + case 6: // GUI if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.gui = iprot.readString(); struct.setGuiIsSet(true); @@ -741,7 +826,7 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, RemoteInterpreterCo org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 6: // RUNNERS + case 7: // RUNNERS if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.runners = iprot.readString(); struct.setRunnersIsSet(true); @@ -764,6 +849,11 @@ public void write(org.apache.thrift.protocol.TProtocol oprot, RemoteInterpreterC struct.validate(); oprot.writeStructBegin(STRUCT_DESC); + if (struct.noteId != null) { + oprot.writeFieldBegin(NOTE_ID_FIELD_DESC); + oprot.writeString(struct.noteId); + oprot.writeFieldEnd(); + } if (struct.paragraphId != null) { oprot.writeFieldBegin(PARAGRAPH_ID_FIELD_DESC); oprot.writeString(struct.paragraphId); @@ -812,25 +902,31 @@ private static class RemoteInterpreterContextTupleScheme extends TupleScheme resultHandler) throws org.apache.thrift.TException; - public void angularObjectUpdate(String name, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + public void angularObjectUpdate(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + + public void angularObjectAdd(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; + + public void angularObjectRemove(String name, String noteId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; } @@ -351,16 +359,17 @@ public RemoteInterpreterEvent recv_getEvent() throws org.apache.thrift.TExceptio throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getEvent failed: unknown result"); } - public void angularObjectUpdate(String name, String object) throws org.apache.thrift.TException + public void angularObjectUpdate(String name, String noteId, String object) throws org.apache.thrift.TException { - send_angularObjectUpdate(name, object); + send_angularObjectUpdate(name, noteId, object); recv_angularObjectUpdate(); } - public void send_angularObjectUpdate(String name, String object) throws org.apache.thrift.TException + public void send_angularObjectUpdate(String name, String noteId, String object) throws org.apache.thrift.TException { angularObjectUpdate_args args = new angularObjectUpdate_args(); args.setName(name); + args.setNoteId(noteId); args.setObject(object); sendBase("angularObjectUpdate", args); } @@ -372,6 +381,49 @@ public void recv_angularObjectUpdate() throws org.apache.thrift.TException return; } + public void angularObjectAdd(String name, String noteId, String object) throws org.apache.thrift.TException + { + send_angularObjectAdd(name, noteId, object); + recv_angularObjectAdd(); + } + + public void send_angularObjectAdd(String name, String noteId, String object) throws org.apache.thrift.TException + { + angularObjectAdd_args args = new angularObjectAdd_args(); + args.setName(name); + args.setNoteId(noteId); + args.setObject(object); + sendBase("angularObjectAdd", args); + } + + public void recv_angularObjectAdd() throws org.apache.thrift.TException + { + angularObjectAdd_result result = new angularObjectAdd_result(); + receiveBase(result, "angularObjectAdd"); + return; + } + + public void angularObjectRemove(String name, String noteId) throws org.apache.thrift.TException + { + send_angularObjectRemove(name, noteId); + recv_angularObjectRemove(); + } + + public void send_angularObjectRemove(String name, String noteId) throws org.apache.thrift.TException + { + angularObjectRemove_args args = new angularObjectRemove_args(); + args.setName(name); + args.setNoteId(noteId); + sendBase("angularObjectRemove", args); + } + + public void recv_angularObjectRemove() throws org.apache.thrift.TException + { + angularObjectRemove_result result = new angularObjectRemove_result(); + receiveBase(result, "angularObjectRemove"); + return; + } + } public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface { public static class Factory implements org.apache.thrift.async.TAsyncClientFactory { @@ -757,19 +809,21 @@ public RemoteInterpreterEvent getResult() throws org.apache.thrift.TException { } } - public void angularObjectUpdate(String name, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { + public void angularObjectUpdate(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { checkReady(); - angularObjectUpdate_call method_call = new angularObjectUpdate_call(name, object, resultHandler, this, ___protocolFactory, ___transport); + angularObjectUpdate_call method_call = new angularObjectUpdate_call(name, noteId, object, resultHandler, this, ___protocolFactory, ___transport); this.___currentMethod = method_call; ___manager.call(method_call); } public static class angularObjectUpdate_call extends org.apache.thrift.async.TAsyncMethodCall { private String name; + private String noteId; private String object; - public angularObjectUpdate_call(String name, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { + public angularObjectUpdate_call(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { super(client, protocolFactory, transport, resultHandler, false); this.name = name; + this.noteId = noteId; this.object = object; } @@ -777,6 +831,7 @@ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apa prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("angularObjectUpdate", org.apache.thrift.protocol.TMessageType.CALL, 0)); angularObjectUpdate_args args = new angularObjectUpdate_args(); args.setName(name); + args.setNoteId(noteId); args.setObject(object); args.write(prot); prot.writeMessageEnd(); @@ -792,6 +847,79 @@ public void getResult() throws org.apache.thrift.TException { } } + public void angularObjectAdd(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { + checkReady(); + angularObjectAdd_call method_call = new angularObjectAdd_call(name, noteId, object, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class angularObjectAdd_call extends org.apache.thrift.async.TAsyncMethodCall { + private String name; + private String noteId; + private String object; + public angularObjectAdd_call(String name, String noteId, String object, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.name = name; + this.noteId = noteId; + this.object = object; + } + + public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException { + prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("angularObjectAdd", org.apache.thrift.protocol.TMessageType.CALL, 0)); + angularObjectAdd_args args = new angularObjectAdd_args(); + args.setName(name); + args.setNoteId(noteId); + args.setObject(object); + args.write(prot); + prot.writeMessageEnd(); + } + + public void getResult() throws org.apache.thrift.TException { + if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new IllegalStateException("Method call not finished!"); + } + org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + (new Client(prot)).recv_angularObjectAdd(); + } + } + + public void angularObjectRemove(String name, String noteId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { + checkReady(); + angularObjectRemove_call method_call = new angularObjectRemove_call(name, noteId, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class angularObjectRemove_call extends org.apache.thrift.async.TAsyncMethodCall { + private String name; + private String noteId; + public angularObjectRemove_call(String name, String noteId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.name = name; + this.noteId = noteId; + } + + public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException { + prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("angularObjectRemove", org.apache.thrift.protocol.TMessageType.CALL, 0)); + angularObjectRemove_args args = new angularObjectRemove_args(); + args.setName(name); + args.setNoteId(noteId); + args.write(prot); + prot.writeMessageEnd(); + } + + public void getResult() throws org.apache.thrift.TException { + if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new IllegalStateException("Method call not finished!"); + } + org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + (new Client(prot)).recv_angularObjectRemove(); + } + } + } public static class Processor extends org.apache.thrift.TBaseProcessor implements org.apache.thrift.TProcessor { @@ -817,6 +945,8 @@ protected Processor(I iface, Map extends org.apache.thrift.ProcessFunction { + public angularObjectAdd() { + super("angularObjectAdd"); + } + + public angularObjectAdd_args getEmptyArgsInstance() { + return new angularObjectAdd_args(); + } + + protected boolean isOneway() { + return false; + } + + public angularObjectAdd_result getResult(I iface, angularObjectAdd_args args) throws org.apache.thrift.TException { + angularObjectAdd_result result = new angularObjectAdd_result(); + iface.angularObjectAdd(args.name, args.noteId, args.object); + return result; + } + } + + public static class angularObjectRemove extends org.apache.thrift.ProcessFunction { + public angularObjectRemove() { + super("angularObjectRemove"); + } + + public angularObjectRemove_args getEmptyArgsInstance() { + return new angularObjectRemove_args(); + } + + protected boolean isOneway() { + return false; + } + + public angularObjectRemove_result getResult(I iface, angularObjectRemove_args args) throws org.apache.thrift.TException { + angularObjectRemove_result result = new angularObjectRemove_result(); + iface.angularObjectRemove(args.name, args.noteId); return result; } } @@ -8937,7 +9107,8 @@ public static class angularObjectUpdate_args implements org.apache.thrift.TBase< private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("angularObjectUpdate_args"); private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); - private static final org.apache.thrift.protocol.TField OBJECT_FIELD_DESC = new org.apache.thrift.protocol.TField("object", org.apache.thrift.protocol.TType.STRING, (short)2); + private static final org.apache.thrift.protocol.TField NOTE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("noteId", org.apache.thrift.protocol.TType.STRING, (short)2); + private static final org.apache.thrift.protocol.TField OBJECT_FIELD_DESC = new org.apache.thrift.protocol.TField("object", org.apache.thrift.protocol.TType.STRING, (short)3); private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); static { @@ -8946,12 +9117,14 @@ public static class angularObjectUpdate_args implements org.apache.thrift.TBase< } public String name; // required + public String noteId; // required public String object; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { NAME((short)1, "name"), - OBJECT((short)2, "object"); + NOTE_ID((short)2, "noteId"), + OBJECT((short)3, "object"); private static final Map byName = new HashMap(); @@ -8968,7 +9141,9 @@ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { case 1: // NAME return NAME; - case 2: // OBJECT + case 2: // NOTE_ID + return NOTE_ID; + case 3: // OBJECT return OBJECT; default: return null; @@ -9015,6 +9190,8 @@ public String getFieldName() { Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.NOTE_ID, new org.apache.thrift.meta_data.FieldMetaData("noteId", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); tmpMap.put(_Fields.OBJECT, new org.apache.thrift.meta_data.FieldMetaData("object", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); metaDataMap = Collections.unmodifiableMap(tmpMap); @@ -9026,10 +9203,12 @@ public angularObjectUpdate_args() { public angularObjectUpdate_args( String name, + String noteId, String object) { this(); this.name = name; + this.noteId = noteId; this.object = object; } @@ -9040,6 +9219,9 @@ public angularObjectUpdate_args(angularObjectUpdate_args other) { if (other.isSetName()) { this.name = other.name; } + if (other.isSetNoteId()) { + this.noteId = other.noteId; + } if (other.isSetObject()) { this.object = other.object; } @@ -9052,6 +9234,7 @@ public angularObjectUpdate_args deepCopy() { @Override public void clear() { this.name = null; + this.noteId = null; this.object = null; } @@ -9079,6 +9262,30 @@ public void setNameIsSet(boolean value) { } } + public String getNoteId() { + return this.noteId; + } + + public angularObjectUpdate_args setNoteId(String noteId) { + this.noteId = noteId; + return this; + } + + public void unsetNoteId() { + this.noteId = null; + } + + /** Returns true if field noteId is set (has been assigned a value) and false otherwise */ + public boolean isSetNoteId() { + return this.noteId != null; + } + + public void setNoteIdIsSet(boolean value) { + if (!value) { + this.noteId = null; + } + } + public String getObject() { return this.object; } @@ -9113,6 +9320,14 @@ public void setFieldValue(_Fields field, Object value) { } break; + case NOTE_ID: + if (value == null) { + unsetNoteId(); + } else { + setNoteId((String)value); + } + break; + case OBJECT: if (value == null) { unsetObject(); @@ -9129,6 +9344,9 @@ public Object getFieldValue(_Fields field) { case NAME: return getName(); + case NOTE_ID: + return getNoteId(); + case OBJECT: return getObject(); @@ -9145,6 +9363,8 @@ public boolean isSet(_Fields field) { switch (field) { case NAME: return isSetName(); + case NOTE_ID: + return isSetNoteId(); case OBJECT: return isSetObject(); } @@ -9173,6 +9393,15 @@ public boolean equals(angularObjectUpdate_args that) { return false; } + boolean this_present_noteId = true && this.isSetNoteId(); + boolean that_present_noteId = true && that.isSetNoteId(); + if (this_present_noteId || that_present_noteId) { + if (!(this_present_noteId && that_present_noteId)) + return false; + if (!this.noteId.equals(that.noteId)) + return false; + } + boolean this_present_object = true && this.isSetObject(); boolean that_present_object = true && that.isSetObject(); if (this_present_object || that_present_object) { @@ -9208,6 +9437,16 @@ public int compareTo(angularObjectUpdate_args other) { return lastComparison; } } + lastComparison = Boolean.valueOf(isSetNoteId()).compareTo(typedOther.isSetNoteId()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNoteId()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteId, typedOther.noteId); + if (lastComparison != 0) { + return lastComparison; + } + } lastComparison = Boolean.valueOf(isSetObject()).compareTo(typedOther.isSetObject()); if (lastComparison != 0) { return lastComparison; @@ -9246,6 +9485,14 @@ public String toString() { } first = false; if (!first) sb.append(", "); + sb.append("noteId:"); + if (this.noteId == null) { + sb.append("null"); + } else { + sb.append(this.noteId); + } + first = false; + if (!first) sb.append(", "); sb.append("object:"); if (this.object == null) { sb.append("null"); @@ -9304,7 +9551,15 @@ public void read(org.apache.thrift.protocol.TProtocol iprot, angularObjectUpdate org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; - case 2: // OBJECT + case 2: // NOTE_ID + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // OBJECT if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.object = iprot.readString(); struct.setObjectIsSet(true); @@ -9332,6 +9587,11 @@ public void write(org.apache.thrift.protocol.TProtocol oprot, angularObjectUpdat oprot.writeString(struct.name); oprot.writeFieldEnd(); } + if (struct.noteId != null) { + oprot.writeFieldBegin(NOTE_ID_FIELD_DESC); + oprot.writeString(struct.noteId); + oprot.writeFieldEnd(); + } if (struct.object != null) { oprot.writeFieldBegin(OBJECT_FIELD_DESC); oprot.writeString(struct.object); @@ -9358,13 +9618,19 @@ public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectUpdate if (struct.isSetName()) { optionals.set(0); } - if (struct.isSetObject()) { + if (struct.isSetNoteId()) { optionals.set(1); } - oprot.writeBitSet(optionals, 2); + if (struct.isSetObject()) { + optionals.set(2); + } + oprot.writeBitSet(optionals, 3); if (struct.isSetName()) { oprot.writeString(struct.name); } + if (struct.isSetNoteId()) { + oprot.writeString(struct.noteId); + } if (struct.isSetObject()) { oprot.writeString(struct.object); } @@ -9373,12 +9639,16 @@ public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectUpdate @Override public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectUpdate_args struct) throws org.apache.thrift.TException { TTupleProtocol iprot = (TTupleProtocol) prot; - BitSet incoming = iprot.readBitSet(2); + BitSet incoming = iprot.readBitSet(3); if (incoming.get(0)) { struct.name = iprot.readString(); struct.setNameIsSet(true); } if (incoming.get(1)) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } + if (incoming.get(2)) { struct.object = iprot.readString(); struct.setObjectIsSet(true); } @@ -9633,4 +9903,1504 @@ public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectUpdate_ } + public static class angularObjectAdd_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("angularObjectAdd_args"); + + private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField NOTE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("noteId", org.apache.thrift.protocol.TType.STRING, (short)2); + private static final org.apache.thrift.protocol.TField OBJECT_FIELD_DESC = new org.apache.thrift.protocol.TField("object", org.apache.thrift.protocol.TType.STRING, (short)3); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new angularObjectAdd_argsStandardSchemeFactory()); + schemes.put(TupleScheme.class, new angularObjectAdd_argsTupleSchemeFactory()); + } + + public String name; // required + public String noteId; // required + public String object; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + NAME((short)1, "name"), + NOTE_ID((short)2, "noteId"), + OBJECT((short)3, "object"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // NAME + return NAME; + case 2: // NOTE_ID + return NOTE_ID; + case 3: // OBJECT + return OBJECT; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.NOTE_ID, new org.apache.thrift.meta_data.FieldMetaData("noteId", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.OBJECT, new org.apache.thrift.meta_data.FieldMetaData("object", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(angularObjectAdd_args.class, metaDataMap); + } + + public angularObjectAdd_args() { + } + + public angularObjectAdd_args( + String name, + String noteId, + String object) + { + this(); + this.name = name; + this.noteId = noteId; + this.object = object; + } + + /** + * Performs a deep copy on other. + */ + public angularObjectAdd_args(angularObjectAdd_args other) { + if (other.isSetName()) { + this.name = other.name; + } + if (other.isSetNoteId()) { + this.noteId = other.noteId; + } + if (other.isSetObject()) { + this.object = other.object; + } + } + + public angularObjectAdd_args deepCopy() { + return new angularObjectAdd_args(this); + } + + @Override + public void clear() { + this.name = null; + this.noteId = null; + this.object = null; + } + + public String getName() { + return this.name; + } + + public angularObjectAdd_args setName(String name) { + this.name = name; + return this; + } + + public void unsetName() { + this.name = null; + } + + /** Returns true if field name is set (has been assigned a value) and false otherwise */ + public boolean isSetName() { + return this.name != null; + } + + public void setNameIsSet(boolean value) { + if (!value) { + this.name = null; + } + } + + public String getNoteId() { + return this.noteId; + } + + public angularObjectAdd_args setNoteId(String noteId) { + this.noteId = noteId; + return this; + } + + public void unsetNoteId() { + this.noteId = null; + } + + /** Returns true if field noteId is set (has been assigned a value) and false otherwise */ + public boolean isSetNoteId() { + return this.noteId != null; + } + + public void setNoteIdIsSet(boolean value) { + if (!value) { + this.noteId = null; + } + } + + public String getObject() { + return this.object; + } + + public angularObjectAdd_args setObject(String object) { + this.object = object; + return this; + } + + public void unsetObject() { + this.object = null; + } + + /** Returns true if field object is set (has been assigned a value) and false otherwise */ + public boolean isSetObject() { + return this.object != null; + } + + public void setObjectIsSet(boolean value) { + if (!value) { + this.object = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case NAME: + if (value == null) { + unsetName(); + } else { + setName((String)value); + } + break; + + case NOTE_ID: + if (value == null) { + unsetNoteId(); + } else { + setNoteId((String)value); + } + break; + + case OBJECT: + if (value == null) { + unsetObject(); + } else { + setObject((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case NAME: + return getName(); + + case NOTE_ID: + return getNoteId(); + + case OBJECT: + return getObject(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case NAME: + return isSetName(); + case NOTE_ID: + return isSetNoteId(); + case OBJECT: + return isSetObject(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof angularObjectAdd_args) + return this.equals((angularObjectAdd_args)that); + return false; + } + + public boolean equals(angularObjectAdd_args that) { + if (that == null) + return false; + + boolean this_present_name = true && this.isSetName(); + boolean that_present_name = true && that.isSetName(); + if (this_present_name || that_present_name) { + if (!(this_present_name && that_present_name)) + return false; + if (!this.name.equals(that.name)) + return false; + } + + boolean this_present_noteId = true && this.isSetNoteId(); + boolean that_present_noteId = true && that.isSetNoteId(); + if (this_present_noteId || that_present_noteId) { + if (!(this_present_noteId && that_present_noteId)) + return false; + if (!this.noteId.equals(that.noteId)) + return false; + } + + boolean this_present_object = true && this.isSetObject(); + boolean that_present_object = true && that.isSetObject(); + if (this_present_object || that_present_object) { + if (!(this_present_object && that_present_object)) + return false; + if (!this.object.equals(that.object)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + public int compareTo(angularObjectAdd_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + angularObjectAdd_args typedOther = (angularObjectAdd_args)other; + + lastComparison = Boolean.valueOf(isSetName()).compareTo(typedOther.isSetName()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetName()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, typedOther.name); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetNoteId()).compareTo(typedOther.isSetNoteId()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNoteId()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteId, typedOther.noteId); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetObject()).compareTo(typedOther.isSetObject()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetObject()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.object, typedOther.object); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + schemes.get(iprot.getScheme()).getScheme().read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + schemes.get(oprot.getScheme()).getScheme().write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("angularObjectAdd_args("); + boolean first = true; + + sb.append("name:"); + if (this.name == null) { + sb.append("null"); + } else { + sb.append(this.name); + } + first = false; + if (!first) sb.append(", "); + sb.append("noteId:"); + if (this.noteId == null) { + sb.append("null"); + } else { + sb.append(this.noteId); + } + first = false; + if (!first) sb.append(", "); + sb.append("object:"); + if (this.object == null) { + sb.append("null"); + } else { + sb.append(this.object); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class angularObjectAdd_argsStandardSchemeFactory implements SchemeFactory { + public angularObjectAdd_argsStandardScheme getScheme() { + return new angularObjectAdd_argsStandardScheme(); + } + } + + private static class angularObjectAdd_argsStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, angularObjectAdd_args struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // NAME + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // NOTE_ID + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // OBJECT + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.object = iprot.readString(); + struct.setObjectIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, angularObjectAdd_args struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.name != null) { + oprot.writeFieldBegin(NAME_FIELD_DESC); + oprot.writeString(struct.name); + oprot.writeFieldEnd(); + } + if (struct.noteId != null) { + oprot.writeFieldBegin(NOTE_ID_FIELD_DESC); + oprot.writeString(struct.noteId); + oprot.writeFieldEnd(); + } + if (struct.object != null) { + oprot.writeFieldBegin(OBJECT_FIELD_DESC); + oprot.writeString(struct.object); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class angularObjectAdd_argsTupleSchemeFactory implements SchemeFactory { + public angularObjectAdd_argsTupleScheme getScheme() { + return new angularObjectAdd_argsTupleScheme(); + } + } + + private static class angularObjectAdd_argsTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectAdd_args struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetName()) { + optionals.set(0); + } + if (struct.isSetNoteId()) { + optionals.set(1); + } + if (struct.isSetObject()) { + optionals.set(2); + } + oprot.writeBitSet(optionals, 3); + if (struct.isSetName()) { + oprot.writeString(struct.name); + } + if (struct.isSetNoteId()) { + oprot.writeString(struct.noteId); + } + if (struct.isSetObject()) { + oprot.writeString(struct.object); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectAdd_args struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(3); + if (incoming.get(0)) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } + if (incoming.get(1)) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } + if (incoming.get(2)) { + struct.object = iprot.readString(); + struct.setObjectIsSet(true); + } + } + } + + } + + public static class angularObjectAdd_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("angularObjectAdd_result"); + + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new angularObjectAdd_resultStandardSchemeFactory()); + schemes.put(TupleScheme.class, new angularObjectAdd_resultTupleSchemeFactory()); + } + + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(angularObjectAdd_result.class, metaDataMap); + } + + public angularObjectAdd_result() { + } + + /** + * Performs a deep copy on other. + */ + public angularObjectAdd_result(angularObjectAdd_result other) { + } + + public angularObjectAdd_result deepCopy() { + return new angularObjectAdd_result(this); + } + + @Override + public void clear() { + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof angularObjectAdd_result) + return this.equals((angularObjectAdd_result)that); + return false; + } + + public boolean equals(angularObjectAdd_result that) { + if (that == null) + return false; + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + public int compareTo(angularObjectAdd_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + angularObjectAdd_result typedOther = (angularObjectAdd_result)other; + + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + schemes.get(iprot.getScheme()).getScheme().read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + schemes.get(oprot.getScheme()).getScheme().write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("angularObjectAdd_result("); + boolean first = true; + + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class angularObjectAdd_resultStandardSchemeFactory implements SchemeFactory { + public angularObjectAdd_resultStandardScheme getScheme() { + return new angularObjectAdd_resultStandardScheme(); + } + } + + private static class angularObjectAdd_resultStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, angularObjectAdd_result struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, angularObjectAdd_result struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class angularObjectAdd_resultTupleSchemeFactory implements SchemeFactory { + public angularObjectAdd_resultTupleScheme getScheme() { + return new angularObjectAdd_resultTupleScheme(); + } + } + + private static class angularObjectAdd_resultTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectAdd_result struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectAdd_result struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + } + } + + } + + public static class angularObjectRemove_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("angularObjectRemove_args"); + + private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField NOTE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("noteId", org.apache.thrift.protocol.TType.STRING, (short)2); + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new angularObjectRemove_argsStandardSchemeFactory()); + schemes.put(TupleScheme.class, new angularObjectRemove_argsTupleSchemeFactory()); + } + + public String name; // required + public String noteId; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + NAME((short)1, "name"), + NOTE_ID((short)2, "noteId"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // NAME + return NAME; + case 2: // NOTE_ID + return NOTE_ID; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.NOTE_ID, new org.apache.thrift.meta_data.FieldMetaData("noteId", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(angularObjectRemove_args.class, metaDataMap); + } + + public angularObjectRemove_args() { + } + + public angularObjectRemove_args( + String name, + String noteId) + { + this(); + this.name = name; + this.noteId = noteId; + } + + /** + * Performs a deep copy on other. + */ + public angularObjectRemove_args(angularObjectRemove_args other) { + if (other.isSetName()) { + this.name = other.name; + } + if (other.isSetNoteId()) { + this.noteId = other.noteId; + } + } + + public angularObjectRemove_args deepCopy() { + return new angularObjectRemove_args(this); + } + + @Override + public void clear() { + this.name = null; + this.noteId = null; + } + + public String getName() { + return this.name; + } + + public angularObjectRemove_args setName(String name) { + this.name = name; + return this; + } + + public void unsetName() { + this.name = null; + } + + /** Returns true if field name is set (has been assigned a value) and false otherwise */ + public boolean isSetName() { + return this.name != null; + } + + public void setNameIsSet(boolean value) { + if (!value) { + this.name = null; + } + } + + public String getNoteId() { + return this.noteId; + } + + public angularObjectRemove_args setNoteId(String noteId) { + this.noteId = noteId; + return this; + } + + public void unsetNoteId() { + this.noteId = null; + } + + /** Returns true if field noteId is set (has been assigned a value) and false otherwise */ + public boolean isSetNoteId() { + return this.noteId != null; + } + + public void setNoteIdIsSet(boolean value) { + if (!value) { + this.noteId = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case NAME: + if (value == null) { + unsetName(); + } else { + setName((String)value); + } + break; + + case NOTE_ID: + if (value == null) { + unsetNoteId(); + } else { + setNoteId((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case NAME: + return getName(); + + case NOTE_ID: + return getNoteId(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case NAME: + return isSetName(); + case NOTE_ID: + return isSetNoteId(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof angularObjectRemove_args) + return this.equals((angularObjectRemove_args)that); + return false; + } + + public boolean equals(angularObjectRemove_args that) { + if (that == null) + return false; + + boolean this_present_name = true && this.isSetName(); + boolean that_present_name = true && that.isSetName(); + if (this_present_name || that_present_name) { + if (!(this_present_name && that_present_name)) + return false; + if (!this.name.equals(that.name)) + return false; + } + + boolean this_present_noteId = true && this.isSetNoteId(); + boolean that_present_noteId = true && that.isSetNoteId(); + if (this_present_noteId || that_present_noteId) { + if (!(this_present_noteId && that_present_noteId)) + return false; + if (!this.noteId.equals(that.noteId)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + public int compareTo(angularObjectRemove_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + angularObjectRemove_args typedOther = (angularObjectRemove_args)other; + + lastComparison = Boolean.valueOf(isSetName()).compareTo(typedOther.isSetName()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetName()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, typedOther.name); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetNoteId()).compareTo(typedOther.isSetNoteId()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNoteId()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteId, typedOther.noteId); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + schemes.get(iprot.getScheme()).getScheme().read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + schemes.get(oprot.getScheme()).getScheme().write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("angularObjectRemove_args("); + boolean first = true; + + sb.append("name:"); + if (this.name == null) { + sb.append("null"); + } else { + sb.append(this.name); + } + first = false; + if (!first) sb.append(", "); + sb.append("noteId:"); + if (this.noteId == null) { + sb.append("null"); + } else { + sb.append(this.noteId); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class angularObjectRemove_argsStandardSchemeFactory implements SchemeFactory { + public angularObjectRemove_argsStandardScheme getScheme() { + return new angularObjectRemove_argsStandardScheme(); + } + } + + private static class angularObjectRemove_argsStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, angularObjectRemove_args struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // NAME + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // NOTE_ID + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, angularObjectRemove_args struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.name != null) { + oprot.writeFieldBegin(NAME_FIELD_DESC); + oprot.writeString(struct.name); + oprot.writeFieldEnd(); + } + if (struct.noteId != null) { + oprot.writeFieldBegin(NOTE_ID_FIELD_DESC); + oprot.writeString(struct.noteId); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class angularObjectRemove_argsTupleSchemeFactory implements SchemeFactory { + public angularObjectRemove_argsTupleScheme getScheme() { + return new angularObjectRemove_argsTupleScheme(); + } + } + + private static class angularObjectRemove_argsTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectRemove_args struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetName()) { + optionals.set(0); + } + if (struct.isSetNoteId()) { + optionals.set(1); + } + oprot.writeBitSet(optionals, 2); + if (struct.isSetName()) { + oprot.writeString(struct.name); + } + if (struct.isSetNoteId()) { + oprot.writeString(struct.noteId); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectRemove_args struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(2); + if (incoming.get(0)) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } + if (incoming.get(1)) { + struct.noteId = iprot.readString(); + struct.setNoteIdIsSet(true); + } + } + } + + } + + public static class angularObjectRemove_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("angularObjectRemove_result"); + + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new angularObjectRemove_resultStandardSchemeFactory()); + schemes.put(TupleScheme.class, new angularObjectRemove_resultTupleSchemeFactory()); + } + + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(angularObjectRemove_result.class, metaDataMap); + } + + public angularObjectRemove_result() { + } + + /** + * Performs a deep copy on other. + */ + public angularObjectRemove_result(angularObjectRemove_result other) { + } + + public angularObjectRemove_result deepCopy() { + return new angularObjectRemove_result(this); + } + + @Override + public void clear() { + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof angularObjectRemove_result) + return this.equals((angularObjectRemove_result)that); + return false; + } + + public boolean equals(angularObjectRemove_result that) { + if (that == null) + return false; + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + public int compareTo(angularObjectRemove_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + angularObjectRemove_result typedOther = (angularObjectRemove_result)other; + + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + schemes.get(iprot.getScheme()).getScheme().read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + schemes.get(oprot.getScheme()).getScheme().write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("angularObjectRemove_result("); + boolean first = true; + + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class angularObjectRemove_resultStandardSchemeFactory implements SchemeFactory { + public angularObjectRemove_resultStandardScheme getScheme() { + return new angularObjectRemove_resultStandardScheme(); + } + } + + private static class angularObjectRemove_resultStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, angularObjectRemove_result struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, angularObjectRemove_result struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class angularObjectRemove_resultTupleSchemeFactory implements SchemeFactory { + public angularObjectRemove_resultTupleScheme getScheme() { + return new angularObjectRemove_resultTupleScheme(); + } + } + + private static class angularObjectRemove_resultTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, angularObjectRemove_result struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, angularObjectRemove_result struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + } + } + + } + } diff --git a/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift b/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift index f9cd181e17e..144784c539e 100644 --- a/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift +++ b/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift @@ -20,12 +20,13 @@ namespace java org.apache.zeppelin.interpreter.thrift struct RemoteInterpreterContext { - 1: string paragraphId, - 2: string paragraphTitle, - 3: string paragraphText, - 4: string config, // json serialized config - 5: string gui, // json serialized gui - 6: string runners // json serialized runner + 1: string noteId, + 2: string paragraphId, + 3: string paragraphTitle, + 4: string paragraphText, + 5: string config, // json serialized config + 6: string gui, // json serialized gui + 7: string runners // json serialized runner } struct RemoteInterpreterResult { @@ -64,5 +65,7 @@ service RemoteInterpreterService { string getStatus(1:string jobId); RemoteInterpreterEvent getEvent(); - void angularObjectUpdate(1: string name, 2: string object); + void angularObjectUpdate(1: string name, 2: string noteId, 3: string object); + void angularObjectAdd(1: string name, 2: string noteId, 3: string object); + void angularObjectRemove(1: string name, 2: string noteId); } \ No newline at end of file diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectRegistryTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectRegistryTest.java index b0ed45f3a94..43aca62c497 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectRegistryTest.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectRegistryTest.java @@ -45,23 +45,32 @@ public void onUpdate(String interpreterGroupId, AngularObject object) { } @Override - public void onRemove(String interpreterGroupId, AngularObject object) { + public void onRemove(String interpreterGroupId, String name, String noteId) { onRemove.incrementAndGet(); } }); - registry.add("name1", "value1"); - assertEquals(1, registry.getAll().size()); + registry.add("name1", "value1", "note1"); + assertEquals(1, registry.getAll("note1").size()); assertEquals(1, onAdd.get()); assertEquals(0, onUpdate.get()); - registry.get("name1").set("newValue"); + registry.get("name1", "note1").set("newValue"); assertEquals(1, onUpdate.get()); - registry.remove("name1"); - assertEquals(0, registry.getAll().size()); + registry.remove("name1", "note1"); + assertEquals(0, registry.getAll("note1").size()); assertEquals(1, onRemove.get()); - assertEquals(null, registry.get("name1")); + assertEquals(null, registry.get("name1", "note1")); + + // namespace + registry.add("name1", "value11", "note2"); + assertEquals("value11", registry.get("name1", "note2").get()); + assertEquals(null, registry.get("name1", "note1")); + + // null namespace + registry.add("name1", "global1", null); + assertEquals("global1", registry.get("name1", null).get()); } } diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectTest.java index 7ccc934c170..acb93d041b6 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectTest.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/AngularObjectTest.java @@ -29,7 +29,7 @@ public class AngularObjectTest { @Test public void testListener() { final AtomicInteger updated = new AtomicInteger(0); - AngularObject ao = new AngularObject("name", "value", new AngularObjectListener() { + AngularObject ao = new AngularObject("name", "value", "note1", new AngularObjectListener() { @Override public void updated(AngularObject updatedObject) { @@ -55,7 +55,7 @@ public void updated(AngularObject updatedObject) { public void testWatcher() throws InterruptedException { final AtomicInteger updated = new AtomicInteger(0); final AtomicInteger onWatch = new AtomicInteger(0); - AngularObject ao = new AngularObject("name", "value", new AngularObjectListener() { + AngularObject ao = new AngularObject("name", "value", "note1", new AngularObjectListener() { @Override public void updated(AngularObject updatedObject) { updated.incrementAndGet(); diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectTest.java index e6da1ec1df0..29a1fb11972 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectTest.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectTest.java @@ -76,6 +76,7 @@ public void setUp() throws Exception { intp.setInterpreterGroup(intpGroup); context = new InterpreterContext( + "note", "id", "title", "text", @@ -95,7 +96,7 @@ public void tearDown() throws Exception { } @Test - public void testAngularObjectCRUD() throws InterruptedException { + public void testAngularObjectInterpreterSideCRUD() throws InterruptedException { InterpreterResult ret = intp.interpret("get", context); Thread.sleep(500); // waitFor eventpoller pool event String[] result = ret.message().split(" "); @@ -108,7 +109,7 @@ public void testAngularObjectCRUD() throws InterruptedException { result = ret.message().split(" "); assertEquals("1", result[0]); // size of registry assertEquals("0", result[1]); // num watcher called - assertEquals("v1", localRegistry.get("n1").get()); + assertEquals("v1", localRegistry.get("n1", "note").get()); // update object ret = intp.interpret("update n1 v11", context); @@ -116,7 +117,7 @@ public void testAngularObjectCRUD() throws InterruptedException { Thread.sleep(500); assertEquals("1", result[0]); // size of registry assertEquals("1", result[1]); // num watcher called - assertEquals("v11", localRegistry.get("n1").get()); + assertEquals("v11", localRegistry.get("n1", "note").get()); // remove object ret = intp.interpret("remove n1", context); @@ -124,7 +125,52 @@ public void testAngularObjectCRUD() throws InterruptedException { Thread.sleep(500); assertEquals("0", result[0]); // size of registry assertEquals("1", result[1]); // num watcher called - assertEquals(null, localRegistry.get("n1")); + assertEquals(null, localRegistry.get("n1", "note")); + } + + @Test + public void testAngularObjectRemovalOnZeppelinServerSide() throws InterruptedException { + // test if angularobject removal from server side propagate to interpreter process's registry. + // will happen when notebook is removed. + + InterpreterResult ret = intp.interpret("get", context); + Thread.sleep(500); // waitFor eventpoller pool event + String[] result = ret.message().split(" "); + assertEquals("0", result[0]); // size of registry + + // create object + ret = intp.interpret("add n1 v1", context); + Thread.sleep(500); + result = ret.message().split(" "); + assertEquals("1", result[0]); // size of registry + assertEquals("v1", localRegistry.get("n1", "note").get()); + + // remove object in local registry. + localRegistry.removeAndNotifyRemoteProcess("n1", "note"); + ret = intp.interpret("get", context); + Thread.sleep(500); // waitFor eventpoller pool event + result = ret.message().split(" "); + assertEquals("0", result[0]); // size of registry + } + + @Test + public void testAngularObjectAddOnZeppelinServerSide() throws InterruptedException { + // test if angularobject add from server side propagate to interpreter process's registry. + // will happen when zeppelin server loads notebook and restore the object into registry + + InterpreterResult ret = intp.interpret("get", context); + Thread.sleep(500); // waitFor eventpoller pool event + String[] result = ret.message().split(" "); + assertEquals("0", result[0]); // size of registry + + // create object + localRegistry.addAndNotifyRemoteProcess("n1", "v1", "note"); + + // get from remote registry + ret = intp.interpret("get", context); + Thread.sleep(500); // waitFor eventpoller pool event + result = ret.message().split(" "); + assertEquals("1", result[0]); // size of registry } @Override @@ -138,7 +184,7 @@ public void onUpdate(String interpreterGroupId, AngularObject object) { } @Override - public void onRemove(String interpreterGroupId, AngularObject object) { + public void onRemove(String interpreterGroupId, String name, String noteId) { onRemove.incrementAndGet(); } diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterTest.java index 4338c50fdc4..0c74cea54d4 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterTest.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterTest.java @@ -110,6 +110,7 @@ public void testRemoteInterperterCall() throws TTransportException, IOException intpA.interpret("1", new InterpreterContext( + "note", "id", "title", "text", @@ -149,6 +150,7 @@ public void testRemoteInterperterErrorStatus() throws TTransportException, IOExc intpA.open(); InterpreterResult ret = intpA.interpret("non numeric value", new InterpreterContext( + "noteId", "id", "title", "text", @@ -194,6 +196,7 @@ public void testRemoteSchedulerSharing() throws TTransportException, IOException long start = System.currentTimeMillis(); InterpreterResult ret = intpA.interpret("500", new InterpreterContext( + "note", "id", "title", "text", @@ -205,6 +208,7 @@ public void testRemoteSchedulerSharing() throws TTransportException, IOException ret = intpB.interpret("500", new InterpreterContext( + "note", "id", "title", "text", @@ -272,6 +276,7 @@ public Map info() { protected Object jobRun() throws Throwable { return intpA.interpret("500", new InterpreterContext( + "note", "jobA", "title", "text", @@ -305,6 +310,7 @@ public Map info() { protected Object jobRun() throws Throwable { return intpB.interpret("500", new InterpreterContext( + "note", "jobB", "title", "text", @@ -379,6 +385,7 @@ public Map info() { @Override protected Object jobRun() throws Throwable { InterpreterResult ret = intpA.interpret(getJobName(), new InterpreterContext( + "note", jobId, "title", "text", @@ -462,6 +469,7 @@ public Map info() { protected Object jobRun() throws Throwable { String stmt = Integer.toString(timeToSleep); InterpreterResult ret = intpA.interpret(stmt, new InterpreterContext( + "note", jobId, "title", "text", diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java index ff1b8edeea0..3024f13b92b 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java @@ -71,8 +71,8 @@ public InterpreterResult interpret(String st, InterpreterContext context) { AngularObjectRegistry registry = context.getAngularObjectRegistry(); if (cmd.equals("add")) { - registry.add(name, value); - registry.get(name).addWatcher(new AngularObjectWatcher(null) { + registry.add(name, value, context.getNoteId()); + registry.get(name, context.getNoteId()).addWatcher(new AngularObjectWatcher(null) { @Override public void watch(Object oldObject, Object newObject, @@ -82,9 +82,9 @@ public void watch(Object oldObject, Object newObject, }); } else if (cmd.equalsIgnoreCase("update")) { - registry.get(name).set(value); + registry.get(name, context.getNoteId()).set(value); } else if (cmd.equals("remove")) { - registry.remove(name); + registry.remove(name, context.getNoteId()); } try { @@ -92,7 +92,7 @@ public void watch(Object oldObject, Object newObject, } catch (InterruptedException e) { } - String msg = registry.getAll().size() + " " + Integer.toString(numWatch.get()); + String msg = registry.getAll(context.getNoteId()).size() + " " + Integer.toString(numWatch.get()); return new InterpreterResult(Code.SUCCESS, msg); } diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/scheduler/RemoteSchedulerTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/scheduler/RemoteSchedulerTest.java index 2a1075a4173..3c9a4759265 100644 --- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/scheduler/RemoteSchedulerTest.java +++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/scheduler/RemoteSchedulerTest.java @@ -90,6 +90,7 @@ public Map info() { @Override protected Object jobRun() throws Throwable { intpA.interpret("1000", new InterpreterContext( + "note", "jobId", "title", "text", 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 659d4df470f..3e051f3ef5a 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 @@ -353,7 +353,6 @@ private void removeNote(WebSocket conn, Notebook notebook, Message fromMessage) return; } Note note = notebook.getNote(noteId); - note.unpersist(); notebook.removeNote(noteId); removeNote(noteId); broadcastNoteList(); @@ -422,6 +421,10 @@ private void angularObjectUpdated(WebSocket conn, Notebook notebook, String varName = (String) fromMessage.get("name"); Object varValue = fromMessage.get("value"); + AngularObject ao = null; + boolean global = false; + + // propagate change to (Remote) AngularObjectRegistry Note note = notebook.getNote(noteId); if (note != null) { @@ -434,37 +437,54 @@ private void angularObjectUpdated(WebSocket conn, Notebook notebook, if (interpreterGroupId.equals(setting.getInterpreterGroup().getId())) { AngularObjectRegistry angularObjectRegistry = setting .getInterpreterGroup().getAngularObjectRegistry(); - AngularObject ao = angularObjectRegistry.get(varName); + + // first trying to get local registry + ao = angularObjectRegistry.get(varName, noteId); if (ao == null) { - LOG.warn("Object {} is not binded", varName); + // then try global registry + ao = angularObjectRegistry.get(varName, null); + if (ao == null) { + LOG.warn("Object {} is not binded", varName); + } else { + // path from client -> server + ao.set(varValue, false); + global = true; + } } else { // path from client -> server ao.set(varValue, false); + global = false; } break; } } } - - // broadcast change to all web session that uses related interpreter. - for (Note n : notebook.getAllNotes()) { - List settings = note.getNoteReplLoader().getInterpreterSettings(); - for (InterpreterSetting setting : settings) { - if (setting.getInterpreterGroup() == null) { - continue; - } - - if (interpreterGroupId.equals(setting.getInterpreterGroup().getId())) { - AngularObjectRegistry angularObjectRegistry = setting - .getInterpreterGroup().getAngularObjectRegistry(); - AngularObject ao = angularObjectRegistry.get(varName); - this.broadcast(n.id(), new Message(OP.ANGULAR_OBJECT_UPDATE) - .put("angularObject", ao) - .put("interpreterGroupId", interpreterGroupId) - .put("noteId", n.id())); + + if (global) { // broadcast change to all web session that uses related interpreter. + for (Note n : notebook.getAllNotes()) { + List settings = note.getNoteReplLoader().getInterpreterSettings(); + for (InterpreterSetting setting : settings) { + if (setting.getInterpreterGroup() == null) { + continue; + } + + if (interpreterGroupId.equals(setting.getInterpreterGroup().getId())) { + AngularObjectRegistry angularObjectRegistry = setting + .getInterpreterGroup().getAngularObjectRegistry(); + this.broadcast(n.id(), new Message(OP.ANGULAR_OBJECT_UPDATE) + .put("angularObject", ao) + .put("interpreterGroupId", interpreterGroupId) + .put("noteId", n.id())); + } } } + } else { // broadcast to all web session for the note + this.broadcast( + note.id(), + new Message(OP.ANGULAR_OBJECT_UPDATE).put("angularObject", ao) + .put("interpreterGroupId", interpreterGroupId) + .put("noteId", note.id())); } } @@ -600,7 +620,7 @@ private void sendAllAngularObjects(Note note, WebSocket conn) { for (InterpreterSetting intpSetting : settings) { AngularObjectRegistry registry = intpSetting.getInterpreterGroup().getAngularObjectRegistry(); - List objects = registry.getAll(); + List objects = registry.getAllWithGlobal(note.id()); for (AngularObject object : objects) { conn.send(serializeMessage(new Message(OP.ANGULAR_OBJECT_UPDATE) .put("angularObject", object) @@ -618,9 +638,16 @@ public void onAdd(String interpreterGroupId, AngularObject object) { @Override public void onUpdate(String interpreterGroupId, AngularObject object) { Notebook notebook = notebook(); + if (notebook == null) { + return; + } List notes = notebook.getAllNotes(); for (Note note : notes) { + if (object.getNoteId() != null && !note.id().equals(object.getNoteId())) { + continue; + } + List intpSettings = note.getNoteReplLoader() .getInterpreterSettings(); @@ -634,21 +661,26 @@ public void onUpdate(String interpreterGroupId, AngularObject object) { .put("noteId", note.id())); } } - } + } } + @Override - public void onRemove(String interpreterGroupId, AngularObject object) { + public void onRemove(String interpreterGroupId, String name, String noteId) { Notebook notebook = notebook(); List notes = notebook.getAllNotes(); for (Note note : notes) { + if (noteId != null && !note.id().equals(noteId)) { + continue; + } + List ids = note.getNoteReplLoader().getInterpreters(); for (String id : ids) { if (id.equals(interpreterGroupId)) { broadcast( note.id(), - new Message(OP.ANGULAR_OBJECT_REMOVE).put("name", - object.getName())); + new Message(OP.ANGULAR_OBJECT_REMOVE).put("name", name).put( + "noteId", noteId)); } } } diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java index 08d3238f400..779396cb917 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java @@ -17,12 +17,20 @@ package org.apache.zeppelin; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.Keys; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxBinary; import org.openqa.selenium.firefox.FirefoxDriver; @@ -31,308 +39,274 @@ import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; +/** + * Test Zeppelin with web brower. + * + * To test, ZeppelinServer should be running on port 8080 + * On OSX, you'll need firefox 31.0 installed. + * + */ public class ZeppelinIT { - private WebDriver getWebDriver(){ - WebDriver driver = null; - - if (driver==null){ - try { - FirefoxBinary ffox = new FirefoxBinary(); - if ("true".equals(System.getenv("TRAVIS"))) { - ffox.setEnvironmentProperty("DISPLAY", ":99"); // xvfb is supposed to run with DISPLAY 99 - } - FirefoxProfile profile = new FirefoxProfile(); - driver = new FirefoxDriver(ffox, profile); - } catch (Exception e){ - } - } - - if (driver==null){ - try { - driver = new ChromeDriver(); - } catch (Exception e){ - } - } - - if (driver==null){ - try { - driver = new SafariDriver(); - } catch (Exception e){ - } - } - - String url; - if (System.getProperty("url")!=null) { - url = System.getProperty("url"); - } else { - url = "http://localhost:8080"; - } - - long start = System.currentTimeMillis(); - boolean loaded = false; - driver.get(url); - - while (System.currentTimeMillis() - start < 60*1000) { - // wait for page load - try { - (new WebDriverWait(driver, 5)).until(new ExpectedCondition() { - @Override - public Boolean apply(WebDriver d) { - return d.findElement(By.partialLinkText("Start")).isDisplayed(); - } - }); - loaded = true; - break; - } catch (TimeoutException e){ - driver.navigate().to(url); - } - } - - if (loaded==false) { - fail(); - } - - return driver; - } + private WebDriver driver; - @Test - public void testDisableIT(){ - // - } - - /* - @Test - public void testRunSimpleQueryInNewSession() { - // Notice that the remainder of the code relies on the interface, - // not the implementation. - WebDriver driver = getWebDriver(); - - try { - // click start - WebElement start = driver.findElement(By.partialLinkText("Start")); - start.click(); - - // Wait for the page to load, timeout after 10 seconds - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.linkText("Create new Job")).isDisplayed(); - } - }); - - // click new - driver.findElement(By.linkText("Create new Job")).click(); - - // wait for run button appears - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.linkText("Run")).isDisplayed(); - } - }); - - // type some query - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys("create table if not exists test "+Keys.chord(Keys.SHIFT, "9")+"id STRING);\n"); - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys("\nshow tables;"); - - // press run button - driver.findElement(By.linkText("Run")).click(); - - // wait for button becomes Running ... - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//a[text()='Running ...']")).isDisplayed(); - } - }); - - // wait for button becomes Run - (new WebDriverWait(driver, 60)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//a[text()='Run']")).isDisplayed(); - } - }); - - WebElement msg = driver.findElement(By.id("msgBox")); - if (msg!=null) { - System.out.println("msgBox="+msg.getText()); - } - - // wait for visualization - (new WebDriverWait(driver, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div[@id='visualizationContainer']//iframe")).isDisplayed(); - } - }); - - WebDriver iframe = driver.switchTo().frame(driver.findElement(By.xpath("//div[@id='visualizationContainer']//iframe"))); - - // wait for result displayed - (new WebDriverWait(iframe, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//table//td[text()='test']")).isDisplayed(); - } - }); - } catch (WebDriverException e){ - File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); - System.out.println("Screenshot in: " + scrFile.getAbsolutePath()); - throw e; - } finally { - // Close the browser - driver.quit(); + private WebDriver getWebDriver() { + WebDriver driver = null; + + if (driver == null) { + try { + FirefoxBinary ffox = new FirefoxBinary(); + if ("true".equals(System.getenv("TRAVIS"))) { + ffox.setEnvironmentProperty("DISPLAY", ":99"); // xvfb is supposed to + // run with DISPLAY 99 } + FirefoxProfile profile = new FirefoxProfile(); + driver = new FirefoxDriver(ffox, profile); + } catch (Exception e) { + } } -*/ + if (driver == null) { + try { + driver = new ChromeDriver(); + } catch (Exception e) { + } + } + + if (driver == null) { + try { + driver = new SafariDriver(); + } catch (Exception e) { + } + } - /** - * Get the url of Zeppelin - * - * @param path to add to the url ex: HOST/myPath - * @return Zeppelin url HOST:PORT{/PATH} - */ - private String getUrl(String path) { String url; if (System.getProperty("url") != null) { url = System.getProperty("url"); } else { url = "http://localhost:8080"; } - if (path != null) - url += path; - return url; + + long start = System.currentTimeMillis(); + boolean loaded = false; + driver.get(url); + + while (System.currentTimeMillis() - start < 60 * 1000) { + // wait for page load + try { + (new WebDriverWait(driver, 5)).until(new ExpectedCondition() { + @Override + public Boolean apply(WebDriver d) { + return d.findElement(By.partialLinkText("Create new note")) + .isDisplayed(); + } + }); + loaded = true; + break; + } catch (TimeoutException e) { + driver.navigate().to(url); + } + } + + if (loaded == false) { + fail(); + } + + return driver; } -/* - @Test - public void testZAN() { - WebDriver driver = getWebDriver(); - - try { - // goto ZAN menu - driver.findElement(By.xpath("//ul//a[text()='ZAN']")).click(); - - // wait for ZAN page loaded - (new WebDriverWait(driver, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//a[text()='Update Catalog']")).isDisplayed(); - } - }); - } catch (WebDriverException e) { - File scrFile = ((TakesScreenshot) driver) - .getScreenshotAs(OutputType.FILE); - System.out.println("Screenshot in: " + scrFile.getAbsolutePath()); - throw e; - } finally { - // Close the browser - driver.quit(); - } - } -*/ - - - /** - * Test is swagger-ui is started - */ - /* - @Test - public void testSwaggerDocumentation() { - WebDriver driver = getWebDriver(); - try { + @Before + public void startUp() { + if (!endToEndTestEnabled()) { + return; + } - driver.get(getUrl("/docs")); - // wait for Swagger page loaded - (new WebDriverWait(driver, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//input[@id='input_apiKey']")).isDisplayed(); - } - }); - - } catch (WebDriverException ex) { - File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); - System.out.println("Screenshot in: " + scrFile.getAbsolutePath()); - throw ex; - } finally { - driver.close(); + driver = getWebDriver(); + } + + @After + public void tearDown() { + if (!endToEndTestEnabled()) { + return; } + + driver.quit(); } - @Test - public void testAnnotationStmt() { - // Notice that the remainder of the code relies on the interface, - // not the implementation. - WebDriver driver = getWebDriver(); - - try { - // click start - WebElement start = driver.findElement(By.partialLinkText("Start")); - start.click(); - - // Wait for the page to load, timeout after 10 seconds - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.linkText("Create new Job")).isDisplayed(); - } - }); - - // click new - driver.findElement(By.linkText("Create new Job")).click(); - - // wait for run button appears - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.linkText("Run")).isDisplayed(); - } - }); - - // type some query with default driver - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys("@driver set exec;"); - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys("\necho 'hello world';"); - - // press run button - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys(Keys.chord(Keys.COMMAND, Keys.ENTER)); - driver.findElement(By.xpath("//div[@id='zqlEditor']//textarea")).sendKeys(Keys.chord(Keys.CONTROL, Keys.ENTER)); - driver.findElement(By.linkText("Run")).click(); - - // wait for button becomes Running ... - (new WebDriverWait(driver, 10)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//a[text()='Running ...']")).isDisplayed(); - } - }); - - // wait for button becomes Run - (new WebDriverWait(driver, 60)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div//a[text()='Run']")).isDisplayed(); - } - }); - - WebElement msg = driver.findElement(By.id("msgBox")); - if (msg!=null) { - System.out.println("msgBox="+msg.getText()); - } - - // wait for visualization - (new WebDriverWait(driver, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//div[@id='visualizationContainer']//iframe")).isDisplayed(); - } - }); - - WebDriver iframe = driver.switchTo().frame(driver.findElement(By.xpath("//div[@id='visualizationContainer']//iframe"))); - - // wait for result displayed - (new WebDriverWait(iframe, 20)).until(new ExpectedCondition() { - public Boolean apply(WebDriver d) { - return d.findElement(By.xpath("//table//td[text()='hello world']")).isDisplayed(); - } - }); - } catch (WebDriverException e){ - File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); - System.out.println("Screenshot in: " + scrFile.getAbsolutePath()); - throw e; - } finally { - // Close the browser - driver.quit(); - } - } -*/ + String getParagraphXPath(int paragraphNo) { + return "//div[@ng-controller=\"ParagraphCtrl\"][" + paragraphNo +"]"; + } + + void waitForParagraph(final int paragraphNo, final String state) { + (new WebDriverWait(driver, 60)).until(new ExpectedCondition() { + public Boolean apply(WebDriver d) { + return driver.findElement(By.xpath(getParagraphXPath(paragraphNo) + + "//div[@class=\"control\"]//span[1][text()=\" " + state + " \"]")) + .isDisplayed(); + }; + }); + } + + boolean endToEndTestEnabled() { + return null != System.getenv("CI"); + } + + @Test + public void testAngularDisplay() throws InterruptedException{ + if (!endToEndTestEnabled()) { + return; + } + + String noteName = createNewNoteAndGetName(); + driver.findElement(By.partialLinkText(noteName)).click(); + + // wait for first paragraph's " READY " status text + waitForParagraph(1, "READY"); + + /* + * print angular template + * %angular
BindingTest_{{myVar}}_
+ */ + WebElement paragraph1Editor = driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea")); + paragraph1Editor.sendKeys("println" + Keys.chord(Keys.SHIFT, "9") + "\"" + + Keys.chord(Keys.SHIFT, "5") + + "angular
" + + "BindingTest_{{myVar}}_
\")"); + paragraph1Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(1, "FINISHED"); + + // check expected text + assertEquals("BindingTest__", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + + /* + * Bind variable + * z.angularBind("myVar", 1) + */ + assertEquals(1, driver.findElements(By.xpath(getParagraphXPath(2) + "//textarea")).size()); + WebElement paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea")); + paragraph2Editor.sendKeys("z.angularBind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", 1)"); + paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(2, "FINISHED"); + + // check expected text + assertEquals("BindingTest_1_", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + + + /* + * print variable + * print("myVar="+z.angular("myVar")) + */ + WebElement paragraph3Editor = driver.findElement(By.xpath(getParagraphXPath(3) + "//textarea")); + paragraph3Editor.sendKeys( + "print" + Keys.chord(Keys.SHIFT, "9") + "\"myVar=\"" + Keys.chord(Keys.ADD) + + "z.angular" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\"))"); + paragraph3Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(3, "FINISHED"); + + // check expected text + assertEquals("myVar=1", driver.findElement(By.xpath( + getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]")).getText()); + + /* + * Click element + */ + driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click(); + + // check expected text + assertEquals("BindingTest_2_", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + + /* + * Register watcher + * z.angularWatch("myVar", (before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext) => { + * z.run(2, context) + * } + */ + WebElement paragraph4Editor = driver.findElement(By.xpath(getParagraphXPath(4) + "//textarea")); + paragraph4Editor.sendKeys( + "z.angularWatch" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", " + + Keys.chord(Keys.SHIFT, "9") + + "before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext)" + + Keys.EQUALS + ">{ z.run" +Keys.chord(Keys.SHIFT, "9") + "2, context)}"); + paragraph4Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(4, "FINISHED"); + + + /* + * Click element, again and see watcher works + */ + driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click(); + + // check expected text + assertEquals("BindingTest_3_", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + waitForParagraph(3, "FINISHED"); + + // check expected text by watcher + assertEquals("myVar=3", driver.findElement(By.xpath( + getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]")).getText()); + + /* + * Unbind + * z.angularUnbind("myVar") + */ + WebElement paragraph5Editor = driver.findElement(By.xpath(getParagraphXPath(5) + "//textarea")); + paragraph5Editor.sendKeys( + "z.angularUnbind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\")"); + paragraph5Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(5, "FINISHED"); + + // check expected text + assertEquals("BindingTest__", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + + /* + * Bind again and see rebind works. + */ + paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea")); + paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER)); + waitForParagraph(2, "FINISHED"); + + // check expected text + assertEquals("BindingTest_1_", driver.findElement(By.xpath( + getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).getText()); + + System.out.println("testCreateNotebook Test executed"); + } + + private String createNewNoteAndGetName() { + List notebookLinks = driver.findElements(By + .xpath("//div[contains(@class, \"col-md-4\")]/div/ul/li")); + List notebookTitles = new LinkedList(); + for (WebElement el : notebookLinks) { + notebookTitles.add(el.getText()); + } + + WebElement createNoteLink = driver.findElement(By.partialLinkText("Create new note")); + createNoteLink.click(); + + try { + Thread.sleep(500); // wait for notebook list updated + } catch (InterruptedException e) { + } + + List notebookLinksAfterCreate = driver.findElements(By + .xpath("//div[contains(@class, \"col-md-4\")]/div/ul/li")); + + Iterator it = notebookLinksAfterCreate.iterator(); + while (it.hasNext()) { + WebElement newEl = it.next(); + if (notebookTitles.contains(newEl.getText())) { + + it.remove(); + } + } + + assertEquals(1, notebookLinksAfterCreate.size()); + return notebookLinksAfterCreate.get(0).getText(); + } } diff --git a/zeppelin-web/src/app/notebook/notebook.controller.js b/zeppelin-web/src/app/notebook/notebook.controller.js index 0d01c370ab3..6286da63d25 100644 --- a/zeppelin-web/src/app/notebook/notebook.controller.js +++ b/zeppelin-web/src/app/notebook/notebook.controller.js @@ -465,6 +465,22 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl', function($scope, $ro }); + $scope.$on('angularObjectRemove', function(event, data) { + if (!data.noteId || data.noteId === $scope.note.id) { + var scope = $rootScope.compiledScope; + var varName = data.name; + + // clear watcher + if (angularObjectRegistry[varName]) { + angularObjectRegistry[varName].clearWatcher(); + angularObjectRegistry[varName] = undefined; + } + + // remove scope variable + scope[varName] = undefined; + } + }); + var isFunction = function(functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; diff --git a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js index 0757d0aaea3..731266f8071 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js +++ b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js @@ -51,6 +51,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope, $rootScope.$broadcast('completionList', data); } else if (op === 'ANGULAR_OBJECT_UPDATE') { $rootScope.$broadcast('angularObjectUpdate', data); + } else if (op === 'ANGULAR_OBJECT_REMOVE') { + $rootScope.$broadcast('angularObjectRemove', data); } }); @@ -65,4 +67,4 @@ angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope, }); return websocketCalls; -}); \ No newline at end of file +}); 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 46b4c1addc5..20cfa969c7b 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 @@ -295,11 +295,12 @@ private void snapshotAngularObjectRegistry() { for (InterpreterSetting setting : settings) { InterpreterGroup intpGroup = setting.getInterpreterGroup(); AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry(); - angularObjects.put(intpGroup.getId(), registry.getAll()); + angularObjects.put(intpGroup.getId(), registry.getAllWithGlobal(id)); } } public void persist() throws IOException { + snapshotAngularObjectRegistry(); repo.save(this); } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java index 1b29509b322..5383d270efb 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java @@ -31,8 +31,11 @@ import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars; import org.apache.zeppelin.display.AngularObject; +import org.apache.zeppelin.display.AngularObjectRegistry; import org.apache.zeppelin.interpreter.InterpreterFactory; +import org.apache.zeppelin.interpreter.InterpreterGroup; import org.apache.zeppelin.interpreter.InterpreterSetting; +import org.apache.zeppelin.interpreter.remote.RemoteAngularObjectRegistry; import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.scheduler.SchedulerFactory; import org.quartz.CronScheduleBuilder; @@ -153,6 +156,17 @@ public void removeNote(String id) { synchronized (notes) { note = notes.remove(id); } + + // remove from all interpreter instance's angular object registry + for (InterpreterSetting settings : replFactory.get()) { + AngularObjectRegistry registry = settings.getInterpreterGroup().getAngularObjectRegistry(); + if (registry instanceof RemoteAngularObjectRegistry) { + ((RemoteAngularObjectRegistry) registry).removeAllAndNotifyRemoteProcess(id); + } else { + registry.removeAll(id); + } + } + try { note.unpersist(); } catch (IOException e) { @@ -220,6 +234,24 @@ private Note loadNoteFromRepo(String id) { notes.put(note.id(), note); refreshCron(note.id()); } + + for (String name : angularObjectSnapshot.keySet()) { + SnapshotAngularObject snapshot = angularObjectSnapshot.get(name); + List settings = replFactory.get(); + for (InterpreterSetting setting : settings) { + InterpreterGroup intpGroup = setting.getInterpreterGroup(); + if (intpGroup.getId().equals(snapshot.getIntpGroupId())) { + AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry(); + String noteId = snapshot.getAngularObject().getNoteId(); + // at this point, remote interpreter process is not created. + // so does not make sense add it to the remote. + // + // therefore instead of addAndNotifyRemoteProcess(), need to use add() + // that results add angularObject only in ZeppelinServer side not remoteProcessSide + registry.add(name, snapshot.getAngularObject().get(), noteId); + } + } + } return note; } 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 79dfc3dc079..5a431986bb5 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 @@ -233,7 +233,9 @@ private InterpreterContext getInterpreterContext() { runners.add(new ParagraphRunner(note, note.id(), p.getId())); } - InterpreterContext interpreterContext = new InterpreterContext(getId(), + InterpreterContext interpreterContext = new InterpreterContext( + note.id(), + getId(), this.getTitle(), this.getText(), this.getConfig(), 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 d7f4ab11d8f..585880b0110 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 @@ -55,7 +55,7 @@ public void setUp() throws Exception { System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), "org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2"); conf = new ZeppelinConfiguration(); factory = new InterpreterFactory(conf, new InterpreterOption(false), null); - context = new InterpreterContext("id", "title", "text", null, null, null, null); + context = new InterpreterContext("note", "id", "title", "text", null, null, null, null); } 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 0d4d1113370..08a00985594 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 @@ -28,6 +28,7 @@ import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars; +import org.apache.zeppelin.display.AngularObjectRegistry; import org.apache.zeppelin.interpreter.InterpreterFactory; import org.apache.zeppelin.interpreter.InterpreterOption; import org.apache.zeppelin.interpreter.mock.MockInterpreter1; @@ -160,6 +161,59 @@ public void testSchedule() throws InterruptedException, IOException{ assertEquals(dateFinished, p.getDateFinished()); } + @Test + public void testAngularObjectRemovalOnNotebookRemove() throws InterruptedException, + IOException { + // create a note and a paragraph + Note note = notebook.createNote(); + note.getNoteReplLoader().setInterpreters(factory.getDefaultInterpreterSettingList()); + + AngularObjectRegistry registry = note.getNoteReplLoader() + .getInterpreterSettings().get(0).getInterpreterGroup() + .getAngularObjectRegistry(); + + // add local scope object + registry.add("o1", "object1", note.id()); + // add global scope object + registry.add("o2", "object2", null); + + // remove notebook + notebook.removeNote(note.id()); + + // local object should be removed + assertNull(registry.get("o1", note.id())); + // global object sould be remained + assertNotNull(registry.get("o2", null)); + } + + @Test + public void testAngularObjectRemovalOnInterpreterRestart() throws InterruptedException, + IOException { + // create a note and a paragraph + Note note = notebook.createNote(); + note.getNoteReplLoader().setInterpreters(factory.getDefaultInterpreterSettingList()); + + AngularObjectRegistry registry = note.getNoteReplLoader() + .getInterpreterSettings().get(0).getInterpreterGroup() + .getAngularObjectRegistry(); + + // add local scope object + registry.add("o1", "object1", note.id()); + // add global scope object + registry.add("o2", "object2", null); + + // restart interpreter + factory.restart(note.getNoteReplLoader().getInterpreterSettings().get(0).id()); + registry = note.getNoteReplLoader() + .getInterpreterSettings().get(0).getInterpreterGroup() + .getAngularObjectRegistry(); + + // local and global scope object should be removed + assertNull(registry.get("o1", note.id())); + assertNull(registry.get("o2", null)); + notebook.removeNote(note.id()); + } + private void delete(File file){ if(file.isFile()) file.delete(); else if(file.isDirectory()){