Repository: incubator-streams
Updated Branches:
  refs/heads/master 3341415d9 -> 9aebd0b1a


STREAMS-203 | Created mechanisms to convert a GooglePlus Activity object to a 
Streams Activity object. Updated serializers and TypeConverters accordingly. 
Added in appropriate unit tests. Updated documentation.


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

Branch: refs/heads/master
Commit: c921f6741804f745e6d4926166bf1cf792603bbd
Parents: 42d0ab3
Author: Robert Douglas <[email protected]>
Authored: Tue Oct 28 17:42:39 2014 -0500
Committer: Robert Douglas <[email protected]>
Committed: Tue Oct 28 17:42:39 2014 -0500

----------------------------------------------------------------------
 .../processor/GooglePlusTypeConverter.java      |   5 +-
 .../gplus/provider/GPlusActivitySerializer.java |  77 +---------
 .../gplus/provider/GPlusEventProcessor.java     |   3 -
 .../util/GPlusActivityDeserializer.java         | 129 +++++++++++++++++
 .../serializer/util/GooglePlusActivityUtil.java | 143 +++++++++++++++++--
 .../processor/GooglePlusActivitySerDeTest.java  | 112 +++++++++++++++
 .../processor/GooglePlusTypeConverterTest.java  |  63 +++++---
 .../resources/google_plus_activity_jsons.txt    |   5 +
 8 files changed, 434 insertions(+), 103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/processor/GooglePlusTypeConverter.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/processor/GooglePlusTypeConverter.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/processor/GooglePlusTypeConverter.java
index 928eec9..b4cf21d 100644
--- 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/processor/GooglePlusTypeConverter.java
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/processor/GooglePlusTypeConverter.java
@@ -58,10 +58,13 @@ public class GooglePlusTypeConverter implements 
StreamsProcessor {
 
             LOGGER.debug("{} processing {}", STREAMS_ID, item.getClass());
             Activity activity = null;
+
             if(item instanceof Person) {
                 activity = new Activity();
-
                 googlePlusActivityUtil.updateActivity((Person)item, activity);
+            } else if(item instanceof 
com.google.api.services.plus.model.Activity) {
+                activity = new Activity();
+                
googlePlusActivityUtil.updateActivity((com.google.api.services.plus.model.Activity)item,
 activity);
             }
 
             if(activity != null) {

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusActivitySerializer.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusActivitySerializer.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusActivitySerializer.java
index 8eaa90a..1659ae3 100644
--- 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusActivitySerializer.java
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusActivitySerializer.java
@@ -18,42 +18,25 @@
 
 package com.google.gplus.provider;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
+import com.google.gplus.serializer.util.GooglePlusActivityUtil;
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.streams.data.ActivitySerializer;
-import org.apache.streams.pojo.json.*;
-import org.joda.time.DateTime;
+import org.apache.streams.pojo.json.Activity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Date;
 import java.util.List;
 
-/**
-* Created with IntelliJ IDEA.
-* User: mdelaet
-* Date: 9/30/13
-* Time: 9:24 AM
-* To change this template use File | Settings | File Templates.
-*/
+
 public class GPlusActivitySerializer implements 
ActivitySerializer<com.google.api.services.plus.model.Activity> {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(GPlusActivitySerializer.class);
 
     GPlusProvider provider;
 
-    ObjectMapper mapper = new ObjectMapper();
-
     public GPlusActivitySerializer(GPlusProvider provider) {
 
         this.provider = provider;
-
-        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, 
Boolean.FALSE);
-
     }
 
     public GPlusActivitySerializer() {
@@ -71,34 +54,9 @@ public class GPlusActivitySerializer implements 
ActivitySerializer<com.google.ap
 
     @Override
     public Activity deserialize(com.google.api.services.plus.model.Activity 
gplusActivity) {
-
-        // There is totally a better way to do this
-        //   1) Deep copy all jackson fields that overlap
-        //   2) Check all objects are present
-        //   3) Check essential fields have values
-        //   4) Any that don't, set them based on other fields that are present
-
         Activity activity = new Activity();
-        activity.setId(formatId(gplusActivity.getId()));
-        activity.setPublished(new 
DateTime(gplusActivity.getPublished().getValue()));
-        Provider provider = new Provider();
-        provider.setId("http://plus.google.com";);
-        provider.setDisplayName("GPlus");
-        activity.setProvider(provider);
-        Actor actor = new Actor();
-        actor.setId(gplusActivity.getActor().getId());
-        actor.setDisplayName(gplusActivity.getActor().getDisplayName());
-        actor.setUrl(gplusActivity.getActor().getUrl());
-        activity.setActor(actor);
-        activity.setVerb(gplusActivity.getVerb());
-        ActivityObject object = new ActivityObject();
-        object.setId(gplusActivity.getObject().getId());
-        object.setUrl(gplusActivity.getObject().getUrl());
-        object.setContent(gplusActivity.getObject().getContent());
-        activity.setTitle(gplusActivity.getTitle());
-        activity.setContent(gplusActivity.getObject().getContent());
-        activity.setObject(object);
 
+        GooglePlusActivityUtil.updateActivity(gplusActivity, activity);
         return activity;
     }
 
@@ -106,31 +64,4 @@ public class GPlusActivitySerializer implements 
ActivitySerializer<com.google.ap
     public List<Activity> 
deserializeAll(List<com.google.api.services.plus.model.Activity> 
serializedList) {
         throw new NotImplementedException("Not currently implemented");
     }
-
-    public static Generator buildGenerator(ObjectNode event) {
-        return null;
-    }
-
-    public static Icon getIcon(ObjectNode event) {
-        return null;
-    }
-
-    public static Provider buildProvider(ObjectNode event) {
-        Provider provider = new Provider();
-        provider.setId("id:providers:gmail");
-        return provider;
-    }
-
-    public static List<Object> getLinks(ObjectNode event) {
-        return null;
-    }
-
-    public static String getUrls(ObjectNode event) {
-        return null;
-    }
-
-    public static String formatId(String... idparts) {
-        return Joiner.on(":").join(Lists.asList("id:gmail", idparts));
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusEventProcessor.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusEventProcessor.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusEventProcessor.java
index 81cac86..6ed2ae1 100644
--- 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusEventProcessor.java
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/provider/GPlusEventProcessor.java
@@ -29,9 +29,6 @@ import java.util.Queue;
 import java.util.Random;
 import java.util.concurrent.BlockingQueue;
 
-/**
- * Created by sblackmon on 12/10/13.
- */
 public class GPlusEventProcessor implements Runnable {
 
     private final static Logger LOGGER = 
LoggerFactory.getLogger(GPlusEventProcessor.class);

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GPlusActivityDeserializer.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GPlusActivityDeserializer.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GPlusActivityDeserializer.java
new file mode 100644
index 0000000..9cb1d61
--- /dev/null
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GPlusActivityDeserializer.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.google.gplus.serializer.util;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.api.client.util.DateTime;
+import com.google.api.client.util.Lists;
+import com.google.api.services.plus.model.Activity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Custom deserializer for GooglePlus' Person model
+ */
+public class GPlusActivityDeserializer extends JsonDeserializer<Activity> {
+    private final static Logger LOGGER = 
LoggerFactory.getLogger(GPlusActivityDeserializer.class);
+
+    /**
+     * Because the GooglePlus Activity object {@link 
com.google.api.services.plus.model.Activity} contains complex objects
+     * within its hierarchy, we have to use a custom deserializer
+     *
+     * @param jsonParser
+     * @param deserializationContext
+     * @return The deserialized {@link 
com.google.api.services.plus.model.Activity} object
+     * @throws IOException
+     * @throws JsonProcessingException
+     */
+    @Override
+    public Activity deserialize(JsonParser jsonParser, DeserializationContext 
deserializationContext) throws IOException, JsonProcessingException {
+
+        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+        Activity activity = new Activity();
+
+        try {
+            activity.setUrl(node.get("url").asText());
+            activity.setEtag(node.get("etag").asText());
+            activity.setTitle(node.get("title").asText());
+            
activity.setPublished(DateTime.parseRfc3339(node.get("published").asText()));
+            
activity.setUpdated(DateTime.parseRfc3339(node.get("updated").asText()));
+            activity.setId(node.get("id").asText());
+            activity.setVerb(node.get("verb").asText());
+
+            Activity.Actor actor = new Activity.Actor();
+            JsonNode actorNode = node.get("actor");
+
+            actor.setId(actorNode.get("id").asText());
+            actor.setDisplayName(actorNode.get("displayName").asText());
+            actor.setUrl(actorNode.get("url").asText());
+
+            Activity.Actor.Image image = new Activity.Actor.Image();
+            JsonNode imageNode = actorNode.get("image");
+            image.setUrl(imageNode.get("url").asText());
+
+            actor.setImage(image);
+            activity.setActor(actor);
+
+            Activity.PlusObject object = new Activity.PlusObject();
+            JsonNode objectNode = node.get("object");
+            object.setObjectType(objectNode.get("objectType").asText());
+            object.setContent(objectNode.get("content").asText());
+            object.setUrl(objectNode.get("url").asText());
+
+            Activity.PlusObject.Replies replies = new 
Activity.PlusObject.Replies();
+            JsonNode repliesNode = objectNode.get("replies");
+            replies.setTotalItems(repliesNode.get("totalItems").asLong());
+            replies.setSelfLink(repliesNode.get("selfLink").asText());
+            object.setReplies(replies);
+
+            Activity.PlusObject.Plusoners plusoners = new 
Activity.PlusObject.Plusoners();
+            JsonNode plusonersNode = objectNode.get("plusoners");
+            plusoners.setTotalItems(plusonersNode.get("totalItems").asLong());
+            plusoners.setSelfLink(plusonersNode.get("selfLink").asText());
+            object.setPlusoners(plusoners);
+
+            Activity.PlusObject.Resharers resharers = new 
Activity.PlusObject.Resharers();
+            JsonNode resharersNode = objectNode.get("resharers");
+            resharers.setTotalItems(resharersNode.get("totalItems").asLong());
+            resharers.setSelfLink(resharersNode.get("selfLink").asText());
+            object.setResharers(resharers);
+
+            List<Activity.PlusObject.Attachments> attachments = 
Lists.newArrayList();
+            for (JsonNode attachmentNode : objectNode.get("attachments")) {
+                Activity.PlusObject.Attachments attachments1 = new 
Activity.PlusObject.Attachments();
+                
attachments1.setObjectType(attachmentNode.get("objectType").asText());
+                
attachments1.setDisplayName(attachmentNode.get("displayName").asText());
+                
attachments1.setContent(attachmentNode.get("content").asText());
+                attachments1.setUrl(attachmentNode.get("url").asText());
+
+                Activity.PlusObject.Attachments.Image image1 = new 
Activity.PlusObject.Attachments.Image();
+                JsonNode imageNode1 = attachmentNode.get("image");
+                image1.setUrl(imageNode1.get("url").asText());
+                attachments1.setImage(image1);
+
+                attachments.add(attachments1);
+            }
+            object.setAttachments(attachments);
+
+            activity.setObject(object);
+        } catch (Exception e) {
+            LOGGER.error("Exception while trying to deserialize activity 
object: {}", e);
+        }
+
+        return activity;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GooglePlusActivityUtil.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GooglePlusActivityUtil.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GooglePlusActivityUtil.java
index 3fce398..73b4b0d 100644
--- 
a/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GooglePlusActivityUtil.java
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/main/java/com/google/gplus/serializer/util/GooglePlusActivityUtil.java
@@ -20,25 +20,26 @@
 package com.google.gplus.serializer.util;
 
 import com.google.api.services.plus.model.Person;
+import org.apache.streams.pojo.json.*;
+import org.apache.streams.pojo.json.Activity;
+import org.joda.time.DateTime;
 import com.google.common.base.Joiner;
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import org.apache.streams.exceptions.ActivitySerializerException;
-import org.apache.streams.pojo.json.Activity;
-import org.apache.streams.pojo.json.Actor;
-import org.apache.streams.pojo.json.Image;
-import org.apache.streams.pojo.json.Provider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
+
+import static org.apache.streams.data.util.ActivityUtil.ensureExtensions;
 
 public class GooglePlusActivityUtil {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(GooglePlusActivityUtil.class);
 
     /**
-     * Given a Person object and an activity, fill out the appropriate actor 
details
+     * Given a {@link com.google.api.services.plus.model.Person} object and an
+     * {@link org.apache.streams.pojo.json.Activity} object, fill out the 
appropriate details
      *
      * @param item
      * @param activity
@@ -57,7 +58,133 @@ public class GooglePlusActivityUtil {
     }
 
     /**
-     * Extract the relevant details from the passed in Person object and build
+     * Given a Google Plus {@link com.google.api.services.plus.model.Activity},
+     * convert that into an Activity streams formatted {@link 
org.apache.streams.pojo.json.Activity}
+     *
+     * @param gPlusActivity
+     * @param activity
+     */
+    public static void 
updateActivity(com.google.api.services.plus.model.Activity gPlusActivity, 
Activity activity) {
+        activity.setActor(buildActor(gPlusActivity.getActor()));
+        activity.setVerb("post");
+        activity.setTitle(gPlusActivity.getTitle());
+        activity.setUrl(gPlusActivity.getUrl());
+        activity.setProvider(getProvider());
+
+        if(gPlusActivity.getObject() != null) {
+            activity.setContent(gPlusActivity.getObject().getContent());
+        }
+
+        activity.setId(formatId(activity.getVerb(),
+                Optional.fromNullable(
+                        gPlusActivity.getId())
+                        .orNull()));
+
+        DateTime published = new 
DateTime(String.valueOf(gPlusActivity.getPublished()));
+        activity.setPublished(published);
+
+        setObject(activity, gPlusActivity.getObject());
+        addGPlusExtensions(activity, gPlusActivity);
+    }
+
+    /**
+     * Add in necessary extensions from the passed in {@link 
com.google.api.services.plus.model.Activity} to the
+     * {@link org.apache.streams.pojo.json.Activity} object
+     *
+     * @param activity
+     * @param gPlusActivity
+     */
+    private static void addGPlusExtensions(Activity activity, 
com.google.api.services.plus.model.Activity gPlusActivity) {
+        Map<String, Object> extensions = ensureExtensions(activity);
+
+        com.google.api.services.plus.model.Activity.PlusObject object = 
gPlusActivity.getObject();
+        extensions.put("googlePlus", gPlusActivity);
+
+        if(object != null) {
+            com.google.api.services.plus.model.Activity.PlusObject.Plusoners 
plusoners = object.getPlusoners();
+            if(plusoners != null) {
+                Map<String, Object> likes = new HashMap<>();
+                likes.put("count", plusoners.getTotalItems());
+                extensions.put("likes", likes);
+            }
+
+            com.google.api.services.plus.model.Activity.PlusObject.Resharers 
resharers = object.getResharers();
+            if(resharers != null) {
+                Map<String, Object> rebroadcasts = new HashMap<>();
+                rebroadcasts.put("count", resharers.getTotalItems());
+                extensions.put("rebroadcasts", rebroadcasts);
+            }
+
+            extensions.put("keywords", object.getContent());
+        }
+    }
+
+    /**
+     * Set the {@link org.apache.streams.pojo.json.ActivityObject} field given 
the passed in
+     * {@link com.google.api.services.plus.model.Activity.PlusObject}
+     *
+     * @param activity
+     * @param object
+     */
+    private static void setObject(Activity activity, 
com.google.api.services.plus.model.Activity.PlusObject object) {
+        if(object != null) {
+            ActivityObject activityObject = new ActivityObject();
+
+            activityObject.setContent(object.getContent());
+            activityObject.setObjectType(object.getObjectType());
+
+            java.util.List<ActivityObject> attachmentsList = 
Lists.newArrayList();
+            for 
(com.google.api.services.plus.model.Activity.PlusObject.Attachments attachments 
: object.getAttachments()) {
+                ActivityObject attach = new ActivityObject();
+
+                attach.setContent(attachments.getContent());
+                attach.setDisplayName(attachments.getDisplayName());
+                attach.setObjectType(attachments.getObjectType());
+                attach.setUrl(attachments.getUrl());
+
+                Image image = new Image();
+                
com.google.api.services.plus.model.Activity.PlusObject.Attachments.Image image1 
= attachments.getImage();
+
+                if (image1 != null) {
+                    image.setUrl(image1.getUrl());
+                    attach.setImage(image);
+                }
+
+                attachmentsList.add(attach);
+            }
+
+            activityObject.setAttachments(attachmentsList);
+
+            activity.setObject(activityObject);
+        }
+    }
+
+    /**
+     * Given a {@link com.google.api.services.plus.model.Activity.Actor} 
object, return a fully fleshed
+     * out {@link org.apache.streams.pojo.json.Actor} object
+     *
+     * @param gPlusActor
+     * @return
+     */
+    private static Actor 
buildActor(com.google.api.services.plus.model.Activity.Actor gPlusActor) {
+        Actor actor = new Actor();
+
+        actor.setDisplayName(gPlusActor.getDisplayName());
+        actor.setId(formatId(String.valueOf(gPlusActor.getId())));
+        actor.setUrl(gPlusActor.getUrl());
+
+        Image image = new Image();
+        com.google.api.services.plus.model.Activity.Actor.Image 
googlePlusImage = gPlusActor.getImage();
+
+        if(googlePlusImage != null) {
+            image.setUrl(googlePlusImage.getUrl());
+        }
+        actor.setImage(image);
+
+        return actor;
+    }
+    /**
+     * Extract the relevant details from the passed in {@link 
com.google.api.services.plus.model.Person} object and build
      * an actor with them
      *
      * @param person

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusActivitySerDeTest.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusActivitySerDeTest.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusActivitySerDeTest.java
new file mode 100644
index 0000000..6babea0
--- /dev/null
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusActivitySerDeTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.google.gplus.processor;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.google.gplus.serializer.util.GPlusActivityDeserializer;
+import com.google.gplus.serializer.util.GooglePlusActivityUtil;
+import org.apache.commons.lang.StringUtils;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.pojo.json.Activity;
+import org.apache.streams.pojo.json.Actor;
+import org.apache.streams.pojo.json.Provider;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class GooglePlusActivitySerDeTest {
+    private final static Logger LOGGER = 
LoggerFactory.getLogger(GooglePlusActivitySerDeTest.class);
+    private ObjectMapper objectMapper;
+    private GooglePlusActivityUtil googlePlusActivityUtil;
+
+    @Before
+    public void setup() {
+        objectMapper = new StreamsJacksonMapper();
+        SimpleModule simpleModule = new SimpleModule();
+        
simpleModule.addDeserializer(com.google.api.services.plus.model.Activity.class, 
new GPlusActivityDeserializer());
+        objectMapper.registerModule(simpleModule);
+        
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 
false);
+
+        googlePlusActivityUtil = new GooglePlusActivityUtil();
+    }
+
+    @Test
+    public void TestActivityObjects() {
+        InputStream is = 
GooglePlusActivitySerDeTest.class.getResourceAsStream("/google_plus_activity_jsons.txt");
+        InputStreamReader isr = new InputStreamReader(is);
+        BufferedReader br = new BufferedReader(isr);
+
+        try {
+            while (br.ready()) {
+                String line = br.readLine();
+                if (!StringUtils.isEmpty(line)) {
+                    LOGGER.info("raw: {}", line);
+                    Activity activity = new Activity();
+
+                    com.google.api.services.plus.model.Activity gPlusActivity 
= objectMapper.readValue(line, 
com.google.api.services.plus.model.Activity.class);
+
+                    googlePlusActivityUtil.updateActivity(gPlusActivity, 
activity);
+                    LOGGER.info("activity: {}", activity);
+
+                    assertNotNull(activity);
+                    assert(activity.getId().contains("id:googleplus:post"));
+                    assertEquals(activity.getVerb(), "post");
+
+                    Provider provider = activity.getProvider();
+                    assertEquals(provider.getId(), "id:providers:googleplus");
+                    assertEquals(provider.getDisplayName(), "GooglePlus");
+
+                    Actor actor = activity.getActor();
+                    assertNotNull(actor.getImage());
+                    assert(actor.getId().contains("id:googleplus:"));
+                    assertNotNull(actor.getUrl());
+
+                    assertNotNull(activity.getPublished());
+                    assertNotNull(activity.getTitle());
+                    assertNotNull(activity.getUrl());
+
+                    Map<String, Object> extensions = (Map<String, 
Object>)activity.getAdditionalProperties().get("extensions");
+                    assertNotNull(extensions);
+                    assertNotNull(extensions.get("googlePlus"));
+
+                    if(activity.getContent() != null) {
+                        assertNotNull(extensions.get("rebroadcasts"));
+                        assertNotNull(extensions.get("keywords"));
+                        assertNotNull(extensions.get("likes"));
+                        assert (((Map<String, Object>) 
extensions.get("rebroadcasts")).containsKey("count"));
+                        assert (((Map<String, Object>) 
extensions.get("likes")).containsKey("count"));
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.error("Exception while testing serializability: {}", e);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusTypeConverterTest.java
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusTypeConverterTest.java
 
b/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusTypeConverterTest.java
index 6fbdf19..a8a44c0 100644
--- 
a/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusTypeConverterTest.java
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/test/java/com/google/gplus/processor/GooglePlusTypeConverterTest.java
@@ -22,10 +22,12 @@ import 
com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.google.api.services.plus.model.Person;
+import com.google.gplus.serializer.util.GPlusActivityDeserializer;
 import com.google.gplus.serializer.util.GPlusPersonDeserializer;
 import com.google.gplus.serializer.util.GooglePlusActivityUtil;
 import org.apache.commons.lang.StringUtils;
 import org.apache.streams.core.StreamsDatum;
+import org.apache.streams.exceptions.ActivitySerializerException;
 import org.apache.streams.jackson.StreamsJacksonMapper;
 import org.apache.streams.pojo.json.Activity;
 import org.junit.Before;
@@ -34,6 +36,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.List;
@@ -51,6 +54,7 @@ public class GooglePlusTypeConverterTest {
         objectMapper = new StreamsJacksonMapper();
         SimpleModule simpleModule = new SimpleModule();
         simpleModule.addDeserializer(Person.class, new 
GPlusPersonDeserializer());
+        
simpleModule.addDeserializer(com.google.api.services.plus.model.Activity.class, 
new GPlusActivityDeserializer());
         objectMapper.registerModule(simpleModule);
         
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 
false);
 
@@ -59,33 +63,56 @@ public class GooglePlusTypeConverterTest {
     }
 
     @Test
-    public void testProcess() {
+    public void testProcessPerson() throws IOException, 
ActivitySerializerException {
         InputStream is = 
GooglePlusTypeConverterTest.class.getResourceAsStream("/google_plus_person_jsons.txt");
         InputStreamReader isr = new InputStreamReader(is);
         BufferedReader br = new BufferedReader(isr);
 
-        try {
-            while (br.ready()) {
-                String line = br.readLine();
-                if (!StringUtils.isEmpty(line)) {
-                    LOGGER.info("raw: {}", line);
-                    Activity activity = new Activity();
+        while (br.ready()) {
+            String line = br.readLine();
+            if (!StringUtils.isEmpty(line)) {
+                LOGGER.info("raw: {}", line);
+                Activity activity = new Activity();
 
-                    Person person = objectMapper.readValue(line, Person.class);
-                    StreamsDatum streamsDatum = new StreamsDatum(person);
+                Person person = objectMapper.readValue(line, Person.class);
+                StreamsDatum streamsDatum = new StreamsDatum(person);
 
-                    assertNotNull(streamsDatum.getDocument());
+                assertNotNull(streamsDatum.getDocument());
 
-                    List<StreamsDatum> retList = 
googlePlusTypeConverter.process(streamsDatum);
-                    GooglePlusActivityUtil.updateActivity(person, activity);
+                List<StreamsDatum> retList = 
googlePlusTypeConverter.process(streamsDatum);
+                GooglePlusActivityUtil.updateActivity(person, activity);
 
-                    assertEquals(retList.size(), 1);
-                    assert(retList.get(0).getDocument() instanceof Activity);
-                    assertEquals(activity, retList.get(0).getDocument());
-                }
+                assertEquals(retList.size(), 1);
+                assert(retList.get(0).getDocument() instanceof Activity);
+                assertEquals(activity, retList.get(0).getDocument());
+            }
+        }
+    }
+
+    @Test
+    public void testProcessActivity() throws IOException, 
ActivitySerializerException{
+        InputStream is = 
GooglePlusTypeConverterTest.class.getResourceAsStream("/google_plus_activity_jsons.txt");
+        InputStreamReader isr = new InputStreamReader(is);
+        BufferedReader br = new BufferedReader(isr);
+
+        while (br.ready()) {
+            String line = br.readLine();
+            if (!StringUtils.isEmpty(line)) {
+                LOGGER.info("raw: {}", line);
+                Activity activity = new Activity();
+
+                com.google.api.services.plus.model.Activity gPlusActivity = 
objectMapper.readValue(line, com.google.api.services.plus.model.Activity.class);
+                StreamsDatum streamsDatum = new StreamsDatum(gPlusActivity);
+
+                assertNotNull(streamsDatum.getDocument());
+
+                List<StreamsDatum> retList = 
googlePlusTypeConverter.process(streamsDatum);
+                GooglePlusActivityUtil.updateActivity(gPlusActivity, activity);
+
+                assertEquals(retList.size(), 1);
+                assert(retList.get(0).getDocument() instanceof Activity);
+                assertEquals(activity, retList.get(0).getDocument());
             }
-        } catch (Exception e) {
-            LOGGER.error("Exception testing the GooglePlusTypeConverter: {}", 
e);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/c921f674/streams-contrib/streams-provider-google/google-gplus/src/test/resources/google_plus_activity_jsons.txt
----------------------------------------------------------------------
diff --git 
a/streams-contrib/streams-provider-google/google-gplus/src/test/resources/google_plus_activity_jsons.txt
 
b/streams-contrib/streams-provider-google/google-gplus/src/test/resources/google_plus_activity_jsons.txt
new file mode 100644
index 0000000..079251b
--- /dev/null
+++ 
b/streams-contrib/streams-provider-google/google-gplus/src/test/resources/google_plus_activity_jsons.txt
@@ -0,0 +1,5 @@
+{ "kind": "plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/NWJTEjOXM_BKuKTTfM8bvWt5c0E\"", "title": "", 
"published": "2014-10-08T15:53:52.703Z", "updated": "2014-10-08T15:53:52.703Z", 
"id": "z130ipoawvulthecp22otlwonv2gutmnm", "url": 
"https://plus.google.com/118376908737486995861/posts/4Zr85DnfdsV";, "actor": { 
"id": "118376908737486995861", "displayName": "Steve Blackmon", "url": 
"https://plus.google.com/118376908737486995861";, "image": { "url": 
"https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg?sz=50";
 } }, "verb": "post", "object": { "objectType": "note", "content": "", "url": 
"https://plus.google.com/118376908737486995861/posts/4Zr85DnfdsV";, "replies": { 
"totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z130ipoawvulthecp22otlwonv2gutmnm/comments";
 }, "plusoners": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z130ipoawvulthecp22otlwonv2gutmnm/people/plusoners";
 }, "resh
 arers": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z130ipoawvulthecp22otlwonv2gutmnm/people/resharers";
 }, "attachments": [ { "objectType": "article", "displayName": "Diction in 
Software Development (i.e. Don't be a d1ck!)", "content": "Over the years, I've 
come to realize how important diction is in software development (and life in 
general). It may mean the difference between a 15 minute meeting where everyone 
nods their heads, and a day long battle of eg...", "url": 
"http://brianoneill.blogspot.com/2014/10/diction-in-software-development-ie-dont.html";,
 "image": { "url": 
"https://lh3.googleusercontent.com/proxy/3BTfJNati40qZ5zdoAK1Zc-udwAMRqYbPX6huwDSHU3HXW9ZlJ2OIaWtoAG3ta1rSy5X=w120-h120";,
 "type": "image/jpeg", "height": 120, "width": 120 }, "fullImage": { "url": 
"http://www.mindrain.com/fishing.jpg";, "type": "image/jpeg" } } ] }, 
"provider": { "title": "Google+" }, "access": { "kind": "plus#acl", 
"description": "Public", "items": [ { "type":
  "public" } ] } }
+{ "kind": "plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/ZRTkaAm2NktNymi4G6PNueqVXV0\"", "title": "I have 
almost all positive thoughts on this phone. Minor concerns on looks (not that 
important I know...", "published": "2014-10-28T16:27:31.774Z", "updated": 
"2014-10-28T16:27:31.774Z", "id": "z12pwxry0qapdj5wr04cedb4bs20ilg55zk0k", 
"url": "https://plus.google.com/116771159471120611293/posts/SHeUgMcXLpz";, 
"actor": { "id": "116771159471120611293", "displayName": "Matt Neithercott", 
"url": "https://plus.google.com/116771159471120611293";, "image": { "url": 
"https://lh6.googleusercontent.com/-C0fiZBxdvw0/AAAAAAAAAAI/AAAAAAAAJ5k/K4pgR3_-_ms/photo.jpg?sz=50";
 } }, "verb": "post", "object": { "objectType": "note", "content": "I have 
almost all positive thoughts on this phone. Minor concerns on looks (not that 
important I know, but I like the Moto X/Nexus 6 look) and more importantly 
I&#39;m wondering if they will be as good with the Droid line with Android 
updates... those seem to ha
 ve lagged a bit more for this line in the past. Mainly I want Android 
Lollipop. <br /><br />Over all this phone looks like a beast and easily one of 
the best phones on the market. Oh, can we talk about the battery?!? \ufeff", 
"url": "https://plus.google.com/116771159471120611293/posts/SHeUgMcXLpz";, 
"replies": { "totalItems": 2, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12pwxry0qapdj5wr04cedb4bs20ilg55zk0k/comments";
 }, "plusoners": { "totalItems": 3, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12pwxry0qapdj5wr04cedb4bs20ilg55zk0k/people/plusoners";
 }, "resharers": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12pwxry0qapdj5wr04cedb4bs20ilg55zk0k/people/resharers";
 }, "attachments": [ { "objectType": "video", "displayName": "Motorola Droid 
Turbo hands-on", "content": "Motorola's partnership with Verizon continues with 
the Droid Turbo, a unique smartphone exclusive to Verizon Wireless. Subscribe: 
http://www.yo
 utube.com/subs...", "url": 
"http://www.youtube.com/attribution_link?a=k_fPNZUvh50&u=/watch?v%3DVo3jj4GvEG0%26feature%3Dshare";,
 "image": { "url": 
"https://lh3.googleusercontent.com/proxy/1MR0ExMhC2wxZj_g0dMnChwzNkg9-eC9N3VVfdfsBAuQZ1Li9U-kZoqPJ8N1YD452vASBH6_6Meh90GyrK1cSdXqZw=w506-h284-n";,
 "type": "image/jpeg", "height": 284, "width": 506 }, "embed": { "url": 
"https://www.youtube.com/embed/Vo3jj4GvEG0";, "type": 
"application/x-shockwave-flash" } } ] }, "provider": { "title": "Google+" }, 
"access": { "kind": "plus#acl", "description": "Public", "items": [ { "type": 
"public" } ] } }
+{ "kind": "plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/U-nMv_RITNj07a6rnKIZ4z6Dk4k\"", "title": "Truth 
hurts...", "published": "2014-10-28T15:36:47.423Z", "updated": 
"2014-10-28T15:36:47.423Z", "id": "z12nwnsbkoivjjwvt22mdt1y0k3of1djw04", "url": 
"https://plus.google.com/116771159471120611293/posts/MPe25pfK4hU";, "actor": { 
"id": "116771159471120611293", "displayName": "Matt Neithercott", "url": 
"https://plus.google.com/116771159471120611293";, "image": { "url": 
"https://lh6.googleusercontent.com/-C0fiZBxdvw0/AAAAAAAAAAI/AAAAAAAAJ5k/K4pgR3_-_ms/photo.jpg?sz=50";
 } }, "verb": "share", "object": { "objectType": "activity", "id": 
"z13tv1wasli0ypjih04cfpk4dti3yrhjawo0k", "actor": { "id": 
"109198125327200245055", "displayName": "Stephani Renteria", "url": 
"https://plus.google.com/109198125327200245055";, "image": { "url": 
"https://lh4.googleusercontent.com/-WJeeS-ny6Ac/AAAAAAAAAAI/AAAAAAAAB5I/zdPCWdOGQuQ/photo.jpg?sz=50";
 } }, "content": "Truth hurts...\ufeff", "url": "https://plus.
 google.com/109198125327200245055/posts/bNSgdkCPmbG", "replies": { 
"totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12nwnsbkoivjjwvt22mdt1y0k3of1djw04/comments";
 }, "plusoners": { "totalItems": 2, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12nwnsbkoivjjwvt22mdt1y0k3of1djw04/people/plusoners";
 }, "resharers": { "totalItems": 1, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12nwnsbkoivjjwvt22mdt1y0k3of1djw04/people/resharers";
 }, "attachments": [ { "objectType": "photo", "displayName": "Truth hurts...", 
"id": "109198125327200245055.6075076220744786466", "content": "16/9/14 - 1", 
"url": 
"https://plus.google.com/photos/109198125327200245055/albums/6075076218164640065/6075076220744786466";,
 "image": { "url": 
"https://lh4.googleusercontent.com/-WjV4kLfSUjo/VE8BorjqYiI/AAAAAAAAC2g/D46Yfy7xO_U/w506-h750/14%2B-%2B1";,
 "type": "image/jpeg" }, "fullImage": { "url": 
"https://lh4.googleusercontent.com/-WjV4kLfSUjo/VE8BorjqYiI/AAAAA
 AAAC2g/D46Yfy7xO_U/w476-h626/14%2B-%2B1", "type": "image/jpeg", "height": 626, 
"width": 476 } } ] }, "provider": { "title": "Reshared Post" }, "access": { 
"kind": "plus#acl", "description": "Public", "items": [ { "type": "public" } ] 
} }
+{ "kind": "plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/Syi_EzWY7OiXcsP6iOpMGjnQnFk\"", "title": "The 
Droid Turbo might be hard to say no to... ", "published": 
"2014-10-28T02:44:40.380Z", "updated": "2014-10-28T02:44:40.380Z", "id": 
"z12bzbxrmlzoxvzl222mdt1y0k3of1djw04", "url": 
"https://plus.google.com/116771159471120611293/posts/6rSySsYPAVL";, "actor": { 
"id": "116771159471120611293", "displayName": "Matt Neithercott", "url": 
"https://plus.google.com/116771159471120611293";, "image": { "url": 
"https://lh6.googleusercontent.com/-C0fiZBxdvw0/AAAAAAAAAAI/AAAAAAAAJ5k/K4pgR3_-_ms/photo.jpg?sz=50";
 } }, "verb": "post", "object": { "objectType": "note", "content": "The Droid 
Turbo might be hard to say no to... \ufeff", "url": 
"https://plus.google.com/116771159471120611293/posts/6rSySsYPAVL";, "replies": { 
"totalItems": 4, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12bzbxrmlzoxvzl222mdt1y0k3of1djw04/comments";
 }, "plusoners": { "totalItems": 1, "selfLink": "https:
 
//content.googleapis.com/plus/v1/activities/z12bzbxrmlzoxvzl222mdt1y0k3of1djw04/people/plusoners"
 }, "resharers": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12bzbxrmlzoxvzl222mdt1y0k3of1djw04/people/resharers";
 } }, "provider": { "title": "Google+" }, "access": { "kind": "plus#acl", 
"description": "Public", "items": [ { "type": "public" } ] } }, { "kind": 
"plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/rQfbBZAN11iZKWdIm2RX3g2kIys\"", "title": "", 
"published": "2014-10-28T01:13:08.582Z", "updated": "2014-10-28T01:13:08.582Z", 
"id": "z12itxgadmqsfpjut22mdt1y0k3of1djw04", "url": 
"https://plus.google.com/116771159471120611293/posts/FyDp4gDoxya";, "actor": { 
"id": "116771159471120611293", "displayName": "Matt Neithercott", "url": 
"https://plus.google.com/116771159471120611293";, "image": { "url": 
"https://lh6.googleusercontent.com/-C0fiZBxdvw0/AAAAAAAAAAI/AAAAAAAAJ5k/K4pgR3_-_ms/photo.jpg?sz=50";
 } }, "verb": "post", "object": { "objectType": "
 note", "content": "", "url": 
"https://plus.google.com/116771159471120611293/posts/FyDp4gDoxya";, "replies": { 
"totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12itxgadmqsfpjut22mdt1y0k3of1djw04/comments";
 }, "plusoners": { "totalItems": 2, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12itxgadmqsfpjut22mdt1y0k3of1djw04/people/plusoners";
 }, "resharers": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z12itxgadmqsfpjut22mdt1y0k3of1djw04/people/resharers";
 }, "attachments": [ { "objectType": "article", "displayName": "iPhone fans and 
Android fans finally find something they hate more than each other", "content": 
"It looks like Walmart, CVS and other merchants have stepped into a major 
hornets' nest. In the wake of news that several major retailers are turning off 
NFC payment sensors in their stores because ...", "url": 
"http://bgr.com/2014/10/27/apple-pay-google-wallet-vs-currentc/";, "image": { 
"url": "htt
 
ps://lh6.googleusercontent.com/proxy/6iMaeS_62HVihJjR77NQXujzcoGwSkSZUsafEp3DJiSyyvp7VyT5KU8-_o6zL3DpXGAjbvAJv3GnEIyKG6gYGg1SU6eCfbYX=w506-h303-p",
 "type": "image/jpeg", "height": 303, "width": 506 }, "fullImage": { "url": 
"http://cdn.bgr.com/2012/09/androidios-e1346785636929.jpg";, "type": 
"image/jpeg" } } ] }, "provider": { "title": "Google+" }, "access": { "kind": 
"plus#acl", "description": "Public", "items": [ { "type": "public" } ] } }
+{ "kind": "plus#activity", "etag": 
"\"Vea_b94Y77GDGgRK7gFNPnolKQw/v1-6aVSBGT4qiStMoz7f2_AN2fM\"", "title": "", 
"published": "2014-10-27T06:26:33.927Z", "updated": "2014-10-27T06:26:33.927Z", 
"id": "z13twrlznpvtzz52w22mdt1y0k3of1djw04", "url": 
"https://plus.google.com/116771159471120611293/posts/GR7CGR8N5VL";, "actor": { 
"id": "116771159471120611293", "displayName": "Matt Neithercott", "url": 
"https://plus.google.com/116771159471120611293";, "image": { "url": 
"https://lh6.googleusercontent.com/-C0fiZBxdvw0/AAAAAAAAAAI/AAAAAAAAJ5k/K4pgR3_-_ms/photo.jpg?sz=50";
 } }, "verb": "share", "object": { "objectType": "activity", "id": 
"z13zgvtiurjgfti1v234iflghvq2c1dge04", "actor": { "id": 
"104954254300557350002", "displayName": "Adam Balm", "url": 
"https://plus.google.com/104954254300557350002";, "image": { "url": 
"https://lh4.googleusercontent.com/-SO1scj4p2LA/AAAAAAAAAAI/AAAAAAAAI-s/efA9LBVe144/photo.jpg?sz=50";
 } }, "content": "", "url": 
"https://plus.google.com/104954254300557350002/posts/AwewX
 htn7ws", "replies": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z13twrlznpvtzz52w22mdt1y0k3of1djw04/comments";
 }, "plusoners": { "totalItems": 9, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z13twrlznpvtzz52w22mdt1y0k3of1djw04/people/plusoners";
 }, "resharers": { "totalItems": 0, "selfLink": 
"https://content.googleapis.com/plus/v1/activities/z13twrlznpvtzz52w22mdt1y0k3of1djw04/people/resharers";
 }, "attachments": [ { "objectType": "photo", "id": 
"104954254300557350002.6074732746360957410", "content": "26/10/2014 - 1", 
"url": 
"https://plus.google.com/photos/104954254300557350002/albums/6074732747132702225/6074732746360957410";,
 "image": { "url": 
"https://lh4.googleusercontent.com/-oO3fnARlDm0/VE3JP1xHKeI/AAAAAAAAeCY/-X2jzc6HruA/w506-h750/2014%2B-%2B1";,
 "type": "image/jpeg" }, "fullImage": { "url": 
"https://lh4.googleusercontent.com/-oO3fnARlDm0/VE3JP1xHKeI/AAAAAAAAeCY/-X2jzc6HruA/w600-h1141/2014%2B-%2B1";,
 "type": "image/jpeg", "heig
 ht": 1141, "width": 600 } } ] }, "annotation": "Truth 😜", "provider": { 
"title": "Reshared Post" }, "access": { "kind": "plus#acl", "description": 
"Public", "items": [ { "type": "public" } ] } }
\ No newline at end of file

Reply via email to