java: Add the JNI support for WatchChange.EntityType

The https://v.io/c/23042 is where the new EntityType was added.

MultiPart: 1/2
Change-Id: Id457589332d02b78785342582bb32d84cfd3201d
diff --git a/services/syncbase/bridge/cgo/impl.go b/services/syncbase/bridge/cgo/impl.go
index aa78bed..25cceef 100644
--- a/services/syncbase/bridge/cgo/impl.go
+++ b/services/syncbase/bridge/cgo/impl.go
@@ -553,15 +553,10 @@
 	if wireWC.State == watch.InitialStateSkipped {
 		return nil
 	}
-	wc := syncbase.ToWatchChange(wireWC)
-	if wc.EntityType != syncbase.EntityRow {
-		// TODO(ivanpi): Pipe collection and initial changes through.
-		return nil
-	}
 	// C.CallDbWatchPatternsCallbacksOnChange() blocks until the client acks the
 	// previous invocation, thus providing flow control.
 	cWatchChange := C.v23_syncbase_WatchChange{}
-	cWatchChange.init(*wc)
+	cWatchChange.init(*syncbase.ToWatchChange(wireWC))
 	C.CallDbWatchPatternsCallbacksOnChange(s.cbs, cWatchChange)
 	return nil
 }
diff --git a/services/syncbase/bridge/cgo/jni.go b/services/syncbase/bridge/cgo/jni.go
index 3b9dec8..2493d23 100644
--- a/services/syncbase/bridge/cgo/jni.go
+++ b/services/syncbase/bridge/cgo/jni.go
@@ -51,6 +51,7 @@
 	arrayListClass              jArrayListClass
 	changeTypeClass             jChangeType
 	collectionRowPatternClass   jCollectionRowPattern
+	entityTypeClass             jEntityType
 	hashMapClass                jHashMap
 	idClass                     jIdClass
 	keyValueClass               jKeyValue
@@ -80,6 +81,7 @@
 	arrayListClass = newJArrayListClass(env)
 	changeTypeClass = newJChangeType(env)
 	collectionRowPatternClass = newJCollectionRowPattern(env)
+	entityTypeClass = newJEntityType(env)
 	hashMapClass = newJHashMap(env)
 	idClass = newJIdClass(env)
 	keyValueClass = newJKeyValue(env)
@@ -656,6 +658,19 @@
 	return obj
 }
 
+func (x *C.v23_syncbase_EntityType) extractToJava(env *C.JNIEnv) C.jobject {
+	var obj C.jobject
+	switch *x {
+	case C.v23_syncbase_EntityTypeRoot:
+		obj = C.GetStaticObjectField(env, entityTypeClass.class, entityTypeClass.root)
+	case C.v23_syncbase_EntityTypeCollection:
+		obj = C.GetStaticObjectField(env, entityTypeClass.class, entityTypeClass.collection)
+	case C.v23_syncbase_EntityTypeRow:
+		obj = C.GetStaticObjectField(env, entityTypeClass.class, entityTypeClass.row)
+	}
+	return obj
+}
+
 func (x *C.v23_syncbase_Id) extractToJava(env *C.JNIEnv) C.jobject {
 	obj := C.NewObjectA(env, idClass.class, idClass.init, nil)
 	C.SetObjectField(env, obj, idClass.blessing, x.blessing.extractToJava(env))
@@ -821,6 +836,7 @@
 
 func (x *C.v23_syncbase_WatchChange) extractToJava(env *C.JNIEnv) C.jobject {
 	obj := C.NewObjectA(env, watchChangeClass.class, watchChangeClass.init, nil)
+	C.SetObjectField(env, obj, watchChangeClass.entityType, x.entityType.extractToJava(env))
 	C.SetObjectField(env, obj, watchChangeClass.collection, x.collection.extractToJava(env))
 	C.SetObjectField(env, obj, watchChangeClass.row, x.row.extractToJava(env))
 	C.SetObjectField(env, obj, watchChangeClass.changeType, x.changeType.extractToJava(env))
diff --git a/services/syncbase/bridge/cgo/jni_lib.go b/services/syncbase/bridge/cgo/jni_lib.go
index 1169ef6..45aa6b3 100644
--- a/services/syncbase/bridge/cgo/jni_lib.go
+++ b/services/syncbase/bridge/cgo/jni_lib.go
@@ -46,6 +46,23 @@
 	}
 }
 
+type jEntityType struct {
+	class      C.jclass
+	root       C.jfieldID
+	collection C.jfieldID
+	row        C.jfieldID
+}
+
+func newJEntityType(env *C.JNIEnv) jEntityType {
+	cls := findClass(env, "io/v/syncbase/core/WatchChange$EntityType")
+	return jEntityType{
+		class:      cls,
+		root:       jGetStaticFieldID(env, cls, "ROOT", "Lio/v/syncbase/core/WatchChange$EntityType;"),
+		collection: jGetStaticFieldID(env, cls, "COLLECTION", "Lio/v/syncbase/core/WatchChange$EntityType;"),
+		row:        jGetStaticFieldID(env, cls, "ROW", "Lio/v/syncbase/core/WatchChange$EntityType;"),
+	}
+}
+
 type jHashMap struct {
 	class C.jclass
 	init  C.jmethodID
@@ -250,6 +267,7 @@
 type jWatchChange struct {
 	class        C.jclass
 	init         C.jmethodID
+	entityType   C.jfieldID
 	collection   C.jfieldID
 	row          C.jfieldID
 	changeType   C.jfieldID
@@ -264,6 +282,7 @@
 	return jWatchChange{
 		class:        cls,
 		init:         init,
+		entityType:   jGetFieldID(env, cls, "entityType", "Lio/v/syncbase/core/WatchChange$EntityType;"),
 		collection:   jGetFieldID(env, cls, "collection", "Lio/v/syncbase/core/Id;"),
 		row:          jGetFieldID(env, cls, "row", "Ljava/lang/String;"),
 		changeType:   jGetFieldID(env, cls, "changeType", "Lio/v/syncbase/core/WatchChange$ChangeType;"),
diff --git a/services/syncbase/bridge/cgo/lib.h b/services/syncbase/bridge/cgo/lib.h
index 748661d..553eadc 100644
--- a/services/syncbase/bridge/cgo/lib.h
+++ b/services/syncbase/bridge/cgo/lib.h
@@ -88,8 +88,16 @@
   v23_syncbase_ChangeTypeDelete = 1
 } v23_syncbase_ChangeType;
 
+// syncbase.EntityType
+typedef enum v23_syncbase_EntityType {
+  v23_syncbase_EntityTypeRoot = 0,
+  v23_syncbase_EntityTypeCollection = 1,
+  v23_syncbase_EntityTypeRow = 2
+} v23_syncbase_EntityType;
+
 // syncbase.WatchChange
 typedef struct {
+  v23_syncbase_EntityType entityType;
   v23_syncbase_Id collection;
   v23_syncbase_String row;
   v23_syncbase_ChangeType changeType;
diff --git a/services/syncbase/bridge/cgo/types.go b/services/syncbase/bridge/cgo/types.go
index 0188d17..680011d 100644
--- a/services/syncbase/bridge/cgo/types.go
+++ b/services/syncbase/bridge/cgo/types.go
@@ -412,23 +412,31 @@
 // C.v23_syncbase_WatchChange
 
 func (x *C.v23_syncbase_WatchChange) init(wc syncbase.WatchChange) error {
+	x.entityType = C.v23_syncbase_EntityType(wc.EntityType)
 	x.collection.init(wc.Collection)
 	x.row.init(wc.Row)
 	x.changeType = C.v23_syncbase_ChangeType(wc.ChangeType)
 	var value []byte
-	if wc.ChangeType != syncbase.DeleteChange {
-		var valueAsRawBytes vom.RawBytes
-		var err error
-		if err = wc.Value(&valueAsRawBytes); err != nil {
-			return err
-		}
-		if clientUnderstandsVOM {
-			value, err = vom.Encode(valueAsRawBytes)
-		} else {
-			err = valueAsRawBytes.ToValue(&value)
-		}
-		if err != nil {
-			return err
+	switch wc.EntityType {
+	case syncbase.EntityRoot:
+		// Nothing to do.
+	case syncbase.EntityCollection:
+		// TODO(razvanm): Pass the CollectionInfo from wc.value.
+	case syncbase.EntityRow:
+		if wc.ChangeType != syncbase.DeleteChange {
+			var valueAsRawBytes vom.RawBytes
+			var err error
+			if err = wc.Value(&valueAsRawBytes); err != nil {
+				return err
+			}
+			if clientUnderstandsVOM {
+				value, err = vom.Encode(valueAsRawBytes)
+			} else {
+				err = valueAsRawBytes.ToValue(&value)
+			}
+			if err != nil {
+				return err
+			}
 		}
 	}
 	x.value.init(value)