ZEPPELIN-148 Notebook scope AngularObject for Angular display system

Described https://issues.apache.org/jira/browse/ZEPPELIN-148

Author: Lee moon soo <[email protected]>

Closes #143 from Leemoonsoo/localscope and squashes the following commits:

51340d2 [Lee moon soo] Increase paragraph run timeout
e00a9af [Lee moon soo] Fix test
80ff3d4 [Lee moon soo] Fix style
ead4f70 [Lee moon soo] Front end interaction test with angularBind, 
angularUnbind, angularWatch
c7c63d1 [Lee moon soo] make sure test is executed
d74820f [Lee moon soo] Enabling selenium test
b817bd9 [Lee moon soo] Cleanup the message
bcb60f8 [Lee moon soo] Clear object correctly
12bb15a [Lee moon soo] Fix style
699defd [Lee moon soo] Handle ANGULAR_OBJECT_REMOVE event in front-end.
1c695c0 [Lee moon soo] Send angularObject add/remove event from ZeppelinServer 
to remote process
195a8c9 [Lee moon soo] Add Unbind api for global scope object
378df68 [Lee moon soo] Remove angularObject when notebook removal
3548cb5 [Lee moon soo] Fix test
093870c [Lee moon soo] save / load angular object
25cf5da [Lee moon soo] Take all objects
bb757e3 [Lee moon soo] Introduce scope (global/local) for angular object


Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/201ce8de
Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/201ce8de
Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/201ce8de

Branch: refs/heads/master
Commit: 201ce8dee7bfcdb4503ec1761cf666670138f14f
Parents: c46d8a0
Author: Lee moon soo <[email protected]>
Authored: Sun Jul 5 14:26:41 2015 -0700
Committer: Lee moon soo <[email protected]>
Committed: Sun Jul 12 09:16:43 2015 -0700

----------------------------------------------------------------------
 .../zeppelin/flink/FlinkInterpreterTest.java    |    2 +-
 .../zeppelin/ignite/IgniteInterpreterTest.java  |    2 +-
 .../ignite/IgniteSqlInterpreterTest.java        |    2 +-
 .../apache/zeppelin/spark/ZeppelinContext.java  |  255 ++-
 .../zeppelin/spark/DepInterpreterTest.java      |    2 +-
 .../zeppelin/spark/SparkInterpreterTest.java    |    2 +-
 .../zeppelin/spark/SparkSqlInterpreterTest.java |    2 +-
 .../apache/zeppelin/display/AngularObject.java  |   29 +-
 .../zeppelin/display/AngularObjectRegistry.java |  108 +-
 .../display/AngularObjectRegistryListener.java  |    2 +-
 .../interpreter/InterpreterContext.java         |   10 +-
 .../interpreter/remote/RemoteAngularObject.java |    6 +-
 .../remote/RemoteAngularObjectRegistry.java     |   79 +-
 .../interpreter/remote/RemoteInterpreter.java   |    1 +
 .../remote/RemoteInterpreterEventPoller.java    |   12 +-
 .../remote/RemoteInterpreterProcess.java        |    4 +-
 .../remote/RemoteInterpreterServer.java         |   75 +-
 .../thrift/RemoteInterpreterContext.java        |  174 +-
 .../thrift/RemoteInterpreterService.java        | 1802 +++++++++++++++++-
 .../main/thrift/RemoteInterpreterService.thrift |   17 +-
 .../display/AngularObjectRegistryTest.java      |   23 +-
 .../zeppelin/display/AngularObjectTest.java     |    4 +-
 .../remote/RemoteAngularObjectTest.java         |   56 +-
 .../remote/RemoteInterpreterTest.java           |    8 +
 .../remote/mock/MockInterpreterAngular.java     |   10 +-
 .../zeppelin/scheduler/RemoteSchedulerTest.java |    1 +
 .../apache/zeppelin/socket/NotebookServer.java  |   82 +-
 .../java/org/apache/zeppelin/ZeppelinIT.java    |  548 +++---
 .../src/app/notebook/notebook.controller.js     |   16 +
 .../websocketEvents/websocketEvents.factory.js  |    4 +-
 .../java/org/apache/zeppelin/notebook/Note.java |    3 +-
 .../org/apache/zeppelin/notebook/Notebook.java  |   32 +
 .../org/apache/zeppelin/notebook/Paragraph.java |    4 +-
 .../interpreter/InterpreterFactoryTest.java     |    2 +-
 .../apache/zeppelin/notebook/NotebookTest.java  |   54 +
 35 files changed, 2960 insertions(+), 473 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/flink/src/test/java/org/apache/zeppelin/flink/FlinkInterpreterTest.java
----------------------------------------------------------------------
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 37f9c27..64baea4 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 class FlinkInterpreterTest {
     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

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteInterpreterTest.java
----------------------------------------------------------------------
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 3d3f50b..ad393a7 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;

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/ignite/src/test/java/org/apache/zeppelin/ignite/IgniteSqlInterpreterTest.java
----------------------------------------------------------------------
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 de1e760..b5eff96 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;

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/spark/src/main/java/org/apache/zeppelin/spark/ZeppelinContext.java
----------------------------------------------------------------------
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 2c03f1c..6cb94d9 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 class ZeppelinContext extends HashMap<String, 
Object> {
   }
 
 
+  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<Object, Object, Unit> func) {
+    angularWatch(name, interpreterContext.getNoteId(), func);
+  }
+  
+  public void angularWatchGlobal(String name,
+      final scala.Function2<Object, Object, Unit> func) {
+    angularWatch(name, null, func);
+  }
+
+  public void angularWatch(
+      String name,
+      final scala.Function3<Object, Object, InterpreterContext, Unit> func) {
+    angularWatch(name, interpreterContext.getNoteId(), func);
+  }
+  
+  public void angularWatchGlobal(
+      String name,
+      final scala.Function3<Object, Object, InterpreterContext, Unit> 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<Object, Object, Unit> func) {
     AngularObjectWatcher w = new AngularObjectWatcher(getInterpreterContext()) 
{
       @Override
@@ -513,11 +700,12 @@ public class ZeppelinContext extends HashMap<String, 
Object> {
         func.apply(newObject, newObject);
       }
     };
-    angularWatch(name, w);
+    angularWatch(name, noteId, w);
   }
 
-  public void angularWatch(
+  private void angularWatch(
       String name,
+      String noteId,
       final scala.Function3<Object, Object, InterpreterContext, Unit> func) {
     AngularObjectWatcher w = new AngularObjectWatcher(getInterpreterContext()) 
{
       @Override
@@ -526,25 +714,38 @@ public class ZeppelinContext extends HashMap<String, 
Object> {
         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);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/spark/src/test/java/org/apache/zeppelin/spark/DepInterpreterTest.java
----------------------------------------------------------------------
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 2f8254d..6adaa14 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 class DepInterpreterTest {
     intpGroup.add(dep);
     dep.setInterpreterGroup(intpGroup);
 
-    context = new InterpreterContext("id", "title", "text", new 
HashMap<String, Object>(), new GUI(),
+    context = new InterpreterContext("note", "id", "title", "text", new 
HashMap<String, Object>(), new GUI(),
         new AngularObjectRegistry(intpGroup.getId(), null),
         new LinkedList<InterpreterContextRunner>());
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java
----------------------------------------------------------------------
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 c97e824..daa7eed 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 class SparkInterpreterTest {
     }
 
     InterpreterGroup intpGroup = new InterpreterGroup();
-    context = new InterpreterContext("id", "title", "text",
+    context = new InterpreterContext("note", "id", "title", "text",
         new HashMap<String, Object>(), new GUI(), new AngularObjectRegistry(
             intpGroup.getId(), null),
         new LinkedList<InterpreterContextRunner>());

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/spark/src/test/java/org/apache/zeppelin/spark/SparkSqlInterpreterTest.java
----------------------------------------------------------------------
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 30166a7..bb818fd 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 class SparkSqlInterpreterTest {
       sql.setInterpreterGroup(intpGroup);
       sql.open();
     }
-    context = new InterpreterContext("id", "title", "text", new 
HashMap<String, Object>(), new GUI(),
+    context = new InterpreterContext("note", "id", "title", "text", new 
HashMap<String, Object>(), new GUI(),
         new AngularObjectRegistry(intpGroup.getId(), null),
         new LinkedList<InterpreterContextRunner>());
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObject.java
----------------------------------------------------------------------
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 bbfcd1b..cebe4cc 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 @@ import org.slf4j.LoggerFactory;
 public class AngularObject<T> {
   private String name;
   private T object;
+  
   private transient AngularObjectListener listener;
   private transient List<AngularObjectWatcher> watchers
     = new LinkedList<AngularObjectWatcher>();
+  
+  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 @@ public class AngularObject<T> {
   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 class AngularObject<T> {
       listener.updated(this);
     }
   }
-
+  
   public void set(T o) {
     set(o, true);
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistry.java
----------------------------------------------------------------------
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 56eca22..d6bab7b 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<String, AngularObject> registry = new HashMap<String, AngularObject>();
+  Map<String, Map<String, AngularObject>> registry = 
+      new HashMap<String, Map<String, AngularObject>>();
+  private final String GLOBAL_KEY = "_GLOBAL_";
   private AngularObjectRegistryListener listener;
   private String interpreterId;
+  
 
   AngularObjectListener angularObjectListener;
 
@@ -51,15 +58,42 @@ public class AngularObjectRegistry {
     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<String, AngularObject> getRegistryForKey(String noteId) {
+    synchronized (registry) {
+      String key = getRegistryKey(noteId);
+      if (!registry.containsKey(key)) {
+        registry.put(key, new HashMap<String, AngularObject>());
+      }
+      
+      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<String, AngularObject> noteLocalRegistry = getRegistryForKey(noteId);
+      noteLocalRegistry.put(name, ao);
       if (listener != null && emit) {
         listener.onAdd(interpreterId, ao);
       }
@@ -68,34 +102,72 @@ public class AngularObjectRegistry {
     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<String, AngularObject> 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<AngularObject> 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<String, AngularObject> r = getRegistryForKey(noteId);
+      return r.get(name);
     }
   }
 
-  public List<AngularObject> getAll() {
+  public List<AngularObject> getAll(String noteId) {
+    List<AngularObject> all = new LinkedList<AngularObject>();
+    synchronized (registry) {
+      Map<String, AngularObject> r = getRegistryForKey(noteId);
+      if (r != null) {
+        all.addAll(r.values());
+      }
+    }
+    return all;
+  }
+  
+  /**
+   * Get all object with global merged
+   * @param noteId
+   * @return
+   */
+  public List<AngularObject> getAllWithGlobal(String noteId) {
     List<AngularObject> all = new LinkedList<AngularObject>();
     synchronized (registry) {
-      all.addAll(registry.values());
+      Map<String, AngularObject> global = getRegistryForKey(null);
+      if (global != null) {
+        all.addAll(global.values());
+      }
+      Map<String, AngularObject> local = getRegistryForKey(noteId);
+      if (local != null) {
+        all.addAll(local.values());
+      }
     }
     return all;
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/AngularObjectRegistryListener.java
----------------------------------------------------------------------
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 3f08efa..3ba57d7 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 @@ package org.apache.zeppelin.display;
 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);
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java
----------------------------------------------------------------------
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 2e4564e..7c2f6c0 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 @@ import org.apache.zeppelin.display.GUI;
  * 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<InterpreterContextRunner> runners;
 
-  public InterpreterContext(String paragraphId,
+  public InterpreterContext(String noteId,
+                            String paragraphId,
                             String paragraphTitle,
                             String paragraphText,
                             Map<String, Object> config,
@@ -43,6 +45,7 @@ public class InterpreterContext {
                             AngularObjectRegistry angularObjectRegistry,
                             List<InterpreterContextRunner> runners
                             ) {
+    this.noteId = noteId;
     this.paragraphId = paragraphId;
     this.paragraphTitle = paragraphTitle;
     this.paragraphText = paragraphText;
@@ -52,6 +55,11 @@ public class InterpreterContext {
     this.runners = runners;
   }
 
+  
+  public String getNoteId() {
+    return noteId;
+  }
+
   public String getParagraphId() {
     return paragraphId;
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObject.java
----------------------------------------------------------------------
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 3abd764..351a2bb 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 class RemoteAngularObject extends AngularObject {
 
     if (emitRemoteProcess) {
       // send updated value to remote interpreter
-      remoteInterpreterProcess.updateRemoteAngularObject(getName(), o);
+      remoteInterpreterProcess.updateRemoteAngularObject(getName(), 
getNoteId(), o);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectRegistry.java
----------------------------------------------------------------------
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 c711f69..b7ac014 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 @@ public class RemoteAngularObjectRegistry extends 
AngularObjectRegistry {
     }
   }
 
+  /**
+   * 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<AngularObject> 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());
   }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java
----------------------------------------------------------------------
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 8992f55..d5d92c8 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 @@ public class RemoteInterpreter extends Interpreter {
 
   private RemoteInterpreterContext convert(InterpreterContext ic) {
     return new RemoteInterpreterContext(
+        ic.getNoteId(),
         ic.getParagraphId(),
         ic.getParagraphTitle(),
         ic.getParagraphText(),

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterEventPoller.java
----------------------------------------------------------------------
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 4997b0e..f39f6a6 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 class RemoteInterpreterEventPoller extends Thread {
           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 class RemoteInterpreterEventPoller extends Thread {
           }
         } 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 class RemoteInterpreterEventPoller extends Thread {
           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);
       }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
----------------------------------------------------------------------
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 91edd41..534af27 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 class RemoteInterpreterProcess implements 
ExecuteResultHandler {
    * @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 class RemoteInterpreterProcess implements 
ExecuteResultHandler {
 
     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 {

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java
----------------------------------------------------------------------
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 33baf9a..16b1883 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 @@ package org.apache.zeppelin.interpreter.remote;
 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 @@ public class RemoteInterpreterServer
     }
 
     return new InterpreterContext(
+        ric.getNoteId(),
         ric.getParagraphId(),
         ric.getParagraphTitle(),
         ric.getParagraphText(),
@@ -395,9 +397,13 @@ public class RemoteInterpreterServer
   }
 
   @Override
-  public void onRemove(String interpreterGroupId, AngularObject object) {
+  public void onRemove(String interpreterGroupId, String name, String noteId) {
+    Map<String, String> removeObject = new HashMap<String, String>();
+    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 class RemoteInterpreterServer
    * 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 class RemoteInterpreterServer
     }
 
     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 class RemoteInterpreterServer
     }
 
     // Generic java object type for json.
-    Map<String, Object> value = gson.fromJson(object,
-        new TypeToken<Map<String, Object>>() {
-        }.getType());
+    if (value == null) {
+      try {
+        value = gson.fromJson(object,
+          new TypeToken<Map<String, Object>>() {
+          }.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<Map<String, Object>>() {
+          }.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);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/201ce8de/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java
----------------------------------------------------------------------
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 9827a45..7a757ab 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 @@ import org.slf4j.LoggerFactory;
 public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteInterpreterContext, 
RemoteInterpreterContext._Fields>, 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<Class<? extends IScheme>, SchemeFactory> schemes = 
new HashMap<Class<? extends IScheme>, SchemeFactory>();
   static {
@@ -46,6 +47,7 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     schemes.put(TupleScheme.class, new 
RemoteInterpreterContextTupleSchemeFactory());
   }
 
+  public String noteId; // required
   public String paragraphId; // required
   public String paragraphTitle; // required
   public String paragraphText; // required
@@ -55,12 +57,13 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
 
   /** The set of fields this struct contains, along with convenience methods 
for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-    PARAGRAPH_ID((short)1, "paragraphId"),
-    PARAGRAPH_TITLE((short)2, "paragraphTitle"),
-    PARAGRAPH_TEXT((short)3, "paragraphText"),
-    CONFIG((short)4, "config"),
-    GUI((short)5, "gui"),
-    RUNNERS((short)6, "runners");
+    NOTE_ID((short)1, "noteId"),
+    PARAGRAPH_ID((short)2, "paragraphId"),
+    PARAGRAPH_TITLE((short)3, "paragraphTitle"),
+    PARAGRAPH_TEXT((short)4, "paragraphText"),
+    CONFIG((short)5, "config"),
+    GUI((short)6, "gui"),
+    RUNNERS((short)7, "runners");
 
     private static final Map<String, _Fields> byName = new HashMap<String, 
_Fields>();
 
@@ -75,17 +78,19 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
      */
     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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
   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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
   }
 
   public RemoteInterpreterContext(
+    String noteId,
     String paragraphId,
     String paragraphTitle,
     String paragraphText,
@@ -158,6 +166,7 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     String runners)
   {
     this();
+    this.noteId = noteId;
     this.paragraphId = paragraphId;
     this.paragraphTitle = paragraphTitle;
     this.paragraphText = paragraphText;
@@ -170,6 +179,9 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
    * Performs a deep copy on <i>other</i>.
    */
   public RemoteInterpreterContext(RemoteInterpreterContext other) {
+    if (other.isSetNoteId()) {
+      this.noteId = other.noteId;
+    }
     if (other.isSetParagraphId()) {
       this.paragraphId = other.paragraphId;
     }
@@ -196,6 +208,7 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
 
   @Override
   public void clear() {
+    this.noteId = null;
     this.paragraphId = null;
     this.paragraphTitle = null;
     this.paragraphText = null;
@@ -204,6 +217,30 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
 
   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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
 
   public Object getFieldValue(_Fields field) {
     switch (field) {
+    case NOTE_ID:
+      return getNoteId();
+
     case PARAGRAPH_ID:
       return getParagraphId();
 
@@ -432,6 +480,8 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     }
 
     switch (field) {
+    case NOTE_ID:
+      return isSetNoteId();
     case PARAGRAPH_ID:
       return isSetParagraphId();
     case PARAGRAPH_TITLE:
@@ -461,6 +511,15 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
           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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
               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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
               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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
               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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
               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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
               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 class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
       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 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     public void write(org.apache.thrift.protocol.TProtocol prot, 
RemoteInterpreterContext struct) throws org.apache.thrift.TException {
       TTupleProtocol oprot = (TTupleProtocol) prot;
       BitSet optionals = new BitSet();
-      if (struct.isSetParagraphId()) {
+      if (struct.isSetNoteId()) {
         optionals.set(0);
       }
-      if (struct.isSetParagraphTitle()) {
+      if (struct.isSetParagraphId()) {
         optionals.set(1);
       }
-      if (struct.isSetParagraphText()) {
+      if (struct.isSetParagraphTitle()) {
         optionals.set(2);
       }
-      if (struct.isSetConfig()) {
+      if (struct.isSetParagraphText()) {
         optionals.set(3);
       }
-      if (struct.isSetGui()) {
+      if (struct.isSetConfig()) {
         optionals.set(4);
       }
-      if (struct.isSetRunners()) {
+      if (struct.isSetGui()) {
         optionals.set(5);
       }
-      oprot.writeBitSet(optionals, 6);
+      if (struct.isSetRunners()) {
+        optionals.set(6);
+      }
+      oprot.writeBitSet(optionals, 7);
+      if (struct.isSetNoteId()) {
+        oprot.writeString(struct.noteId);
+      }
       if (struct.isSetParagraphId()) {
         oprot.writeString(struct.paragraphId);
       }
@@ -854,28 +950,32 @@ public class RemoteInterpreterContext implements 
org.apache.thrift.TBase<RemoteI
     @Override
     public void read(org.apache.thrift.protocol.TProtocol prot, 
RemoteInterpreterContext struct) throws org.apache.thrift.TException {
       TTupleProtocol iprot = (TTupleProtocol) prot;
-      BitSet incoming = iprot.readBitSet(6);
+      BitSet incoming = iprot.readBitSet(7);
       if (incoming.get(0)) {
+        struct.noteId = iprot.readString();
+        struct.setNoteIdIsSet(true);
+      }
+      if (incoming.get(1)) {
         struct.paragraphId = iprot.readString();
         struct.setParagraphIdIsSet(true);
       }
-      if (incoming.get(1)) {
+      if (incoming.get(2)) {
         struct.paragraphTitle = iprot.readString();
         struct.setParagraphTitleIsSet(true);
       }
-      if (incoming.get(2)) {
+      if (incoming.get(3)) {
         struct.paragraphText = iprot.readString();
         struct.setParagraphTextIsSet(true);
       }
-      if (incoming.get(3)) {
+      if (incoming.get(4)) {
         struct.config = iprot.readString();
         struct.setConfigIsSet(true);
       }
-      if (incoming.get(4)) {
+      if (incoming.get(5)) {
         struct.gui = iprot.readString();
         struct.setGuiIsSet(true);
       }
-      if (incoming.get(5)) {
+      if (incoming.get(6)) {
         struct.runners = iprot.readString();
         struct.setRunnersIsSet(true);
       }

Reply via email to