You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streams.apache.org by sb...@apache.org on 2014/07/21 17:45:01 UTC

[15/47] git commit: STREAMS-122 | Updated the InstagramActivityUtil class to fully map Instagram MediaFeedData objects to Activities. Updated tests so that this deserialization and mapping can be tested

STREAMS-122 | Updated the InstagramActivityUtil class to fully map Instagram MediaFeedData objects to Activities. Updated tests so that this deserialization and mapping can be tested


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

Branch: refs/heads/STREAMS-46
Commit: 116365355dad985da52092c85378b5bd7497e907
Parents: 7b301ce
Author: Robert Douglas <rd...@w2odigital.com>
Authored: Tue Jul 1 17:12:57 2014 -0500
Committer: Robert Douglas <rd...@w2odigital.com>
Committed: Tue Jul 1 17:12:57 2014 -0500

----------------------------------------------------------------------
 streams-contrib/pom.xml                         |   1 +
 .../InstagramJsonActivitySerializer.java        |  22 ++-
 .../serializer/util/InstagramActivityUtil.java  | 170 ++++++++++++++++---
 .../test/InstagramActivitySerDeTest.java        |  24 ++-
 .../src/test/resources/testMediaFeedObjects.txt |   2 +
 5 files changed, 181 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/11636535/streams-contrib/pom.xml
----------------------------------------------------------------------
diff --git a/streams-contrib/pom.xml b/streams-contrib/pom.xml
index 620f68e..699274e 100644
--- a/streams-contrib/pom.xml
+++ b/streams-contrib/pom.xml
@@ -47,6 +47,7 @@
 		<module>streams-amazon-aws</module>
         <!--<module>streams-processor-lucene</module>-->
         <!--<module>streams-processor-tika</module>-->
+        <module>streams-provider-instagram</module>
         <module>streams-processor-json</module>
         <module>streams-processor-urls</module>
         <module>streams-provider-datasift</module>

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/11636535/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/InstagramJsonActivitySerializer.java
----------------------------------------------------------------------
diff --git a/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/InstagramJsonActivitySerializer.java b/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/InstagramJsonActivitySerializer.java
index 8d92641..c5bbdf1 100644
--- a/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/InstagramJsonActivitySerializer.java
+++ b/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/InstagramJsonActivitySerializer.java
@@ -18,14 +18,21 @@
 
 package org.apache.streams.instagram.serializer;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.streams.data.ActivitySerializer;
 import org.apache.streams.exceptions.ActivitySerializerException;
+import org.apache.streams.jackson.StreamsJacksonMapper;
 import org.apache.streams.pojo.json.Activity;
+import org.jinstagram.entity.users.feed.MediaFeedData;
 
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.List;
 
+import static org.apache.streams.instagram.serializer.util.InstagramActivityUtil.updateActivity;
+
 public class InstagramJsonActivitySerializer implements ActivitySerializer<String>, Serializable
 {
 
@@ -46,9 +53,20 @@ public class InstagramJsonActivitySerializer implements ActivitySerializer<Strin
     @Override
     public Activity deserialize(String serialized) throws ActivitySerializerException {
 
-        Activity activity = null;
+        ObjectMapper mapper = StreamsJacksonMapper.getInstance();
+        MediaFeedData mediaFeedData = null;
+
+        try {
+            mediaFeedData = mapper.readValue(serialized, MediaFeedData.class);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        Activity activity = new Activity();
 
-        // implement
+        updateActivity(mediaFeedData, activity);
 
         return activity;
     }

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/11636535/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/util/InstagramActivityUtil.java
----------------------------------------------------------------------
diff --git a/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/util/InstagramActivityUtil.java b/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/util/InstagramActivityUtil.java
index e71c43e..0561ba7 100644
--- a/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/util/InstagramActivityUtil.java
+++ b/streams-contrib/streams-provider-instagram/src/main/java/org/apache/streams/instagram/serializer/util/InstagramActivityUtil.java
@@ -19,16 +19,21 @@
 
 package org.apache.streams.instagram.serializer.util;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
 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.ActivityObject;
-import org.apache.streams.pojo.json.Actor;
-import org.apache.streams.pojo.json.Provider;
+import org.apache.streams.pojo.json.*;
+import org.jinstagram.entity.common.ImageData;
+import org.jinstagram.entity.common.Images;
+import org.jinstagram.entity.common.VideoData;
+import org.jinstagram.entity.common.Videos;
 import org.jinstagram.entity.users.feed.MediaFeedData;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -39,7 +44,7 @@ import static org.apache.streams.data.util.ActivityUtil.ensureExtensions;
  * Provides utilities for working with Activity objects within the context of Instagram
  */
 public class InstagramActivityUtil {
-
+    private static final Logger LOGGER = LoggerFactory.getLogger(InstagramActivityUtil.class);
     /**
      * Updates the given Activity object with the values from the item
      * @param item the object to use as the source
@@ -47,7 +52,22 @@ public class InstagramActivityUtil {
      * @throws ActivitySerializerException
      */
     public static void updateActivity(MediaFeedData item, Activity activity) throws ActivitySerializerException {
+        activity.setActor(buildActor(item));
+        activity.setPublished(new DateTime(Long.parseLong(item.getCreatedTime()) * 1000));
+
+        activity.setId(formatId(activity.getVerb(),
+            Optional.fromNullable(
+                    item.getId())
+                        .orNull()));
+
+        activity.setProvider(getProvider());
+        activity.setUrl(item.getLink());
+        activity.setObject(buildActivityObject(item));
 
+        if(item.getCaption() != null)
+            activity.setContent(item.getCaption().getText());
+
+        addInstagramExtensions(activity, item);
     }
 
     /**
@@ -57,6 +77,18 @@ public class InstagramActivityUtil {
      */
     public static  Actor buildActor(MediaFeedData item) {
         Actor actor = new Actor();
+
+        Image image = new Image();
+        image.setUrl(item.getUser().getProfilePictureUrl());
+
+        Map<String, Object> extensions = new HashMap<String, Object>();
+        extensions.put("screenName", item.getUser().getUserName());
+
+        actor.setId(formatId(String.valueOf(item.getUser().getId())));
+        actor.setImage(image);
+        actor.setAdditionalProperty("extensions", extensions);
+        actor.setAdditionalProperty("handle", item.getUser().getUserName());
+
         return actor;
     }
 
@@ -67,18 +99,90 @@ public class InstagramActivityUtil {
      */
     public static ActivityObject buildActivityObject(MediaFeedData item) {
         ActivityObject actObj = new ActivityObject();
+
+        actObj.setObjectType(item.getType());
+        actObj.setAttachments(buildActivityObjectAttachments(item));
+
         return actObj;
     }
 
+    /**
+     * Builds all of the attachments associated with a MediaFeedData object
+     *
+     * @param item
+     * @return
+     */
+    public static List<ActivityObject> buildActivityObjectAttachments(MediaFeedData item) {
+        List<ActivityObject> attachments = new ArrayList<ActivityObject>();
+
+        addImageObjects(attachments, item);
+        addVideoObjects(attachments, item);
+
+        return attachments;
+    }
 
     /**
-     * Updates the content, and associated fields, with those from the given tweet
-     * @param activity the target of the updates.  Will receive all values from the tweet.
-     * @param item the object to use as the source
-     * @param verb the verb for the given activity's type
+     * Adds any image objects to the attachment field
+     * @param attachments
+     * @param item
+     */
+    public static void addImageObjects(List<ActivityObject> attachments, MediaFeedData item) {
+        Images images = item.getImages();
+
+        if(images != null) {
+            try {
+                ImageData thumbnail = images.getThumbnail();
+                ImageData lowResolution = images.getLowResolution();
+
+                ActivityObject thumbnailObject = new ActivityObject();
+                Image thumbnailImage = new Image();
+                thumbnailImage.setUrl(thumbnail.getImageUrl());
+                thumbnailImage.setHeight((double) thumbnail.getImageHeight());
+                thumbnailImage.setWidth((double) thumbnail.getImageWidth());
+                thumbnailObject.setImage(thumbnailImage);
+                thumbnailObject.setObjectType("image");
+
+                ActivityObject lowResolutionObject = new ActivityObject();
+                Image lowResolutionImage = new Image();
+                lowResolutionImage.setUrl(lowResolution.getImageUrl());
+                lowResolutionImage.setHeight((double) lowResolution.getImageHeight());
+                lowResolutionImage.setWidth((double) lowResolution.getImageWidth());
+                lowResolutionObject.setImage(lowResolutionImage);
+                lowResolutionObject.setObjectType("image");
+
+                attachments.add(thumbnailObject);
+                attachments.add(lowResolutionObject);
+            } catch (Exception e) {
+                LOGGER.error("Failed to add image objects: {}", e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Adds any video objects to the attachment field
+     * @param attachments
+     * @param item
      */
-    public static void updateActivityContent(Activity activity, MediaFeedData item, String verb) {
+    public static void addVideoObjects(List<ActivityObject> attachments, MediaFeedData item) {
+        Videos videos = item.getVideos();
+
+        if(videos != null) {
+            try {
+                VideoData lowResolutionVideo = videos.getLowResolution();
+
+                ActivityObject lowResolutionVideoObject = new ActivityObject();
+                Image lowResolutionVideoImage = new Image();
+                lowResolutionVideoImage.setUrl(lowResolutionVideo.getUrl());
+                lowResolutionVideoImage.setHeight((double) lowResolutionVideo.getHeight());
+                lowResolutionVideoImage.setWidth((double) lowResolutionVideo.getWidth());
+                lowResolutionVideoObject.setImage(lowResolutionVideoImage);
+                lowResolutionVideoObject.setObjectType("video");
 
+                attachments.add(lowResolutionVideoObject);
+            } catch (Exception e) {
+                LOGGER.error("Failed to add video objects: {}", e.getMessage());
+            }
+        }
     }
 
     /**
@@ -98,7 +202,14 @@ public class InstagramActivityUtil {
      */
     public static void addLocationExtension(Activity activity, MediaFeedData item) {
         Map<String, Object> extensions = ensureExtensions(activity);
-        Map<String, Object> location = new HashMap<String, Object>();
+
+        if(item.getLocation() != null) {
+            Map<String, Object> coordinates = new HashMap<String, Object>();
+            coordinates.put("type", "Point");
+            coordinates.put("coordinates", "[" + item.getLocation().getLatitude() + "," + item.getLocation().getLongitude() + "]");
+
+            extensions.put("coordinates", coordinates);
+        }
 
     }
 
@@ -112,15 +223,7 @@ public class InstagramActivityUtil {
         provider.setDisplayName("Instagram");
         return provider;
     }
-    /**
-     * Adds the given Instagram event to the activity as an extension
-     * @param activity the Activity object to update
-     * @param event the Instagram event to add as the extension
-     */
-    public static void addInstagramExtension(Activity activity, ObjectNode event) {
-        Map<String, Object> extensions = org.apache.streams.data.util.ActivityUtil.ensureExtensions(activity);
-        extensions.put("instagram", event);
-    }
+
     /**
      * Formats the ID to conform with the Apache Streams activity ID convention
      * @param idparts the parts of the ID to join
@@ -138,5 +241,28 @@ public class InstagramActivityUtil {
      */
     public static void addInstagramExtensions(Activity activity, MediaFeedData item) {
         Map<String, Object> extensions = ensureExtensions(activity);
+
+        addLocationExtension(activity, item);
+
+        Map<String, Object> likes = new HashMap<String, Object>();
+        likes.put("count", item.getLikes().getCount());
+        extensions.put("likes", likes);
+
+        extensions.put("hashtags", item.getTags());
+
+        Image standardResolution = new Image();
+        if(item.getType() == "image" && item.getImages() != null) {
+            ImageData standardResolutionData = item.getImages().getStandardResolution();
+            standardResolution.setHeight((double)standardResolutionData.getImageHeight());
+            standardResolution.setWidth((double)standardResolutionData.getImageWidth());
+            standardResolution.setUrl(standardResolutionData.getImageUrl());
+        } else if(item.getType() == "video" && item.getVideos() != null) {
+            VideoData standardResolutionData = item.getVideos().getStandardResolution();
+            standardResolution.setHeight((double)standardResolutionData.getHeight());
+            standardResolution.setWidth((double)standardResolutionData.getWidth());
+            standardResolution.setUrl(standardResolutionData.getUrl());
+        }
+
+        extensions.put("image", standardResolution);
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/11636535/streams-contrib/streams-provider-instagram/src/test/java/org/apache/streams/twitter/test/InstagramActivitySerDeTest.java
----------------------------------------------------------------------
diff --git a/streams-contrib/streams-provider-instagram/src/test/java/org/apache/streams/twitter/test/InstagramActivitySerDeTest.java b/streams-contrib/streams-provider-instagram/src/test/java/org/apache/streams/twitter/test/InstagramActivitySerDeTest.java
index fcf5e81..075da80 100644
--- a/streams-contrib/streams-provider-instagram/src/test/java/org/apache/streams/twitter/test/InstagramActivitySerDeTest.java
+++ b/streams-contrib/streams-provider-instagram/src/test/java/org/apache/streams/twitter/test/InstagramActivitySerDeTest.java
@@ -20,11 +20,12 @@ package org.apache.streams.twitter.test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.commons.lang.StringUtils;
+import org.apache.streams.instagram.serializer.util.InstagramDeserializer;
 import org.apache.streams.instagram.serializer.InstagramJsonActivitySerializer;
 import org.apache.streams.jackson.StreamsJacksonMapper;
 import org.apache.streams.pojo.json.Activity;
+import org.jinstagram.entity.users.feed.MediaFeedData;
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,6 +34,7 @@ import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 
+import static org.apache.streams.instagram.serializer.util.InstagramActivityUtil.updateActivity;
 import static org.hamcrest.CoreMatchers.*;
 import static org.junit.Assert.assertThat;
 
@@ -46,16 +48,11 @@ import static org.junit.Assert.assertThat;
 public class InstagramActivitySerDeTest {
 
     private final static Logger LOGGER = LoggerFactory.getLogger(InstagramActivitySerDeTest.class);
-    private ObjectMapper mapper = StreamsJacksonMapper.getInstance();
 
-    private InstagramJsonActivitySerializer instagramJsonActivitySerializer = new InstagramJsonActivitySerializer();
-
-    // remove @Ignore after implementation
-    @Ignore
     @Test
-    public void Tests()
-    {
-        InputStream is = InstagramActivitySerDeTest.class.getResourceAsStream("/test.txt");
+    public void Tests() {
+        InstagramDeserializer instagramDeserializer = new InstagramDeserializer("");
+        InputStream is = InstagramActivitySerDeTest.class.getResourceAsStream("/testMediaFeedObjects.txt");
         InputStreamReader isr = new InputStreamReader(is);
         BufferedReader br = new BufferedReader(isr);
 
@@ -66,13 +63,13 @@ public class InstagramActivitySerDeTest {
                 {
                     LOGGER.info("raw: {}", line);
 
-                    // convert to MediaFeedData?
-                    Activity activity = instagramJsonActivitySerializer.deserialize(line);
+                    MediaFeedData mediaFeedData = instagramDeserializer.createObjectFromResponse(MediaFeedData.class, line);
 
-                    String activitystring = mapper.writeValueAsString(activity);
+                    Activity activity = new Activity();
 
-                    LOGGER.info("activity: {}", activitystring);
+                    LOGGER.info("activity: {}", activity.toString());
 
+                    updateActivity(mediaFeedData, activity);
                     assertThat(activity, is(not(nullValue())));
 
                     assertThat(activity.getId(), is(not(nullValue())));
@@ -80,7 +77,6 @@ public class InstagramActivitySerDeTest {
                     assertThat(activity.getActor().getId(), is(not(nullValue())));
                     assertThat(activity.getVerb(), is(not(nullValue())));
                     assertThat(activity.getProvider(), is(not(nullValue())));
-
                 }
             }
         } catch( Exception e ) {

http://git-wip-us.apache.org/repos/asf/incubator-streams/blob/11636535/streams-contrib/streams-provider-instagram/src/test/resources/testMediaFeedObjects.txt
----------------------------------------------------------------------
diff --git a/streams-contrib/streams-provider-instagram/src/test/resources/testMediaFeedObjects.txt b/streams-contrib/streams-provider-instagram/src/test/resources/testMediaFeedObjects.txt
index e69de29..b62e599 100644
--- a/streams-contrib/streams-provider-instagram/src/test/resources/testMediaFeedObjects.txt
+++ b/streams-contrib/streams-provider-instagram/src/test/resources/testMediaFeedObjects.txt
@@ -0,0 +1,2 @@
+{ "attribution":null, "tags":[ ], "type":"image", "location":null, "comments":{ "count":0, "data":[ ] }, "filter":"X-Pro II", "created_time":"1404162054", "link":"http://instagram.com/p/p4ez__syJi/", "likes":{ "count":0, "data":[ ] }, "images":{ "low_resolution":{ "url":"http://scontent-a.cdninstagram.com/hphotos-xpa1/t51.2885-15/10518155_283164271863608_1534480525_a.jpg", "width":306, "height":306 }, "thumbnail":{ "url":"http://scontent-a.cdninstagram.com/hphotos-xpa1/t51.2885-15/10518155_283164271863608_1534480525_s.jpg", "width":150, "height":150 }, "standard_resolution":{ "url":"http://scontent-a.cdninstagram.com/hphotos-xpa1/t51.2885-15/10518155_283164271863608_1534480525_n.jpg", "width":640, "height":640 } }, "users_in_photo":[ ], "caption":{ "created_time":"1404162054", "text":"Testing streams", "from":{ "username":"ktsafford", "profile_picture":"http://images.ak.instagram.com/profiles/anonymousUser.jpg", "id":"1412068271", "full_name":"ktsafford" }, "id":"754488452958068751"
  }, "user_has_liked":false, "id":"754488452387644002_1412068271", "user":{ "username":"ktsafford", "website":"", "profile_picture":"http://images.ak.instagram.com/profiles/anonymousUser.jpg", "full_name":"ktsafford", "bio":"", "id":"1412068271" } }
+{ "type":"image", "users_in_photo":[ { "user":{ "username":"kevin", "full_name":"Kevin S", "id":"3", "profile_picture":"..." }, "position":{ "x":0.315, "y":0.9111 } } ], "filter":"Walden", "tags":[ ], "comments":{ "data":[ { "created_time":"1279332030", "text":"Love the sign here", "from":{ "username":"mikeyk", "full_name":"Mikey Krieger", "id":"4", "profile_picture":"http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg" }, "id":"8" }, { "created_time":"1279341004", "text":"Chilako taco", "from":{ "username":"kevin", "full_name":"Kevin S", "id":"3", "profile_picture":"..." }, "id":"3" } ], "count":2 }, "caption":null, "likes":{ "count":1, "data":[ { "username":"mikeyk", "full_name":"Mikeyk", "id":"4", "profile_picture":"..." } ] }, "link":"http://instagr.am/p/D/", "user":{ "username":"kevin", "full_name":"Kevin S", "profile_picture":"...", "bio":"...", "website":"...", "id":"3" }, "created_time":"1279340983", "images":{ "low_resolution":{ "url":"http://dis
 tillery.s3.amazonaws.com/media/2010/07/16/4de37e03aa4b4372843a7eb33fa41cad_6.jpg", "width":306, "height":306 }, "thumbnail":{ "url":"http://distillery.s3.amazonaws.com/media/2010/07/16/4de37e03aa4b4372843a7eb33fa41cad_5.jpg", "width":150, "height":150 }, "standard_resolution":{ "url":"http://distillery.s3.amazonaws.com/media/2010/07/16/4de37e03aa4b4372843a7eb33fa41cad_7.jpg", "width":612, "height":612 } }, "id":"3", "location":null }