diff --git a/README.md b/README.md index ab10a46..3c1b675 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -StockService +Facebook Service ============ -Get the latest information about stocks. +Get your latest Facebook posts. diff --git a/java/.classpath b/java/.classpath new file mode 100644 index 0000000..a88bac2 --- /dev/null +++ b/java/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/java/.gitattributes b/java/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/java/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/java/.gitignore b/java/.gitignore new file mode 100644 index 0000000..00d612c --- /dev/null +++ b/java/.gitignore @@ -0,0 +1,44 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +/bin/ diff --git a/java/.project b/java/.project new file mode 100644 index 0000000..ec906e3 --- /dev/null +++ b/java/.project @@ -0,0 +1,17 @@ + + + FacebookService + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/java/build.xml b/java/build.xml new file mode 100644 index 0000000..2d6524d --- /dev/null +++ b/java/build.xml @@ -0,0 +1,79 @@ + + + + A build file to generate a distributable .jar for the RealTimeWeb Facebook Service. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/cache.json b/java/cache.json new file mode 100644 index 0000000..71c7f43 --- /dev/null +++ b/java/cache.json @@ -0,0 +1 @@ +{"metadata":{},"data":{}} \ No newline at end of file diff --git a/java/facebook_spec.json b/java/facebook_spec.json new file mode 100644 index 0000000..be357ea --- /dev/null +++ b/java/facebook_spec.json @@ -0,0 +1,176 @@ +{ + "metadata": { + "name": "Facebook Service", + "description": "Online Social Network", + "version": 1, + "author": "Peeratham Techapalokul", + "contact": "tpeera4@vt.edu" + }, + "objects": { + "Post": { + "description": "An individual entry in a profile's feed.", + "format": "json", + "comment": "https://developers.facebook.com/docs/graph-api/reference/v2.2/post", + "fields": { + "id": { + "type": "string", + "path": "id", + "description": "The post ID", + "order": 0 + }, + "from": { + "type": "User", + "path": "from", + "description": "Information about the user that posted the message.", + "order": 1 + }, + "to": { + "type": "User[]", + "path": "to.data", + "description": "Users mentioned or targeted in this post.", + "order": 2 + }, + "message": { + "type": "string", + "path": "message", + "description": "The main body of the post, otherwise called the status message.", + "order": 3 + }, + "picture": { + "type": "string", + "path": "picture", + "description": "The picture scraped from any link included with the post.", + "order": 4 + }, + "link": { + "type": "string", + "path": "link", + "description": "The link attached to this post.", + "order": 5 + }, + "video": { + "type": "string", + "path": "source", + "description": "A URL to any Flash movie or video file attached to the post.", + "order": 6 + }, + "name": { + "type": "string", + "path": "name", + "description": "The name of the link.", + "order": 7 + }, + "description": { + "type": "string", + "path": "description", + "description": "A description of a link in the post (appears beneath the caption).", + "order": 8 + }, + "type": { + "type": "string", + "path": "type", + "description": "A string indicating the object type of this post.", + "order": 9 + }, + "createdTime": { + "type": "string", + "path": "type", + "description": "The time the post was initially published.", + "order": 10 + }, + "updatedTime": { + "type": "string", + "path": "updated_time", + "description": "The time of the last change to this post, or the comments on it.", + "order": 11 + }, + "likes": { + "type": "User[]", + "path": "likes.data", + "description": "People who like this post.", + "order": 12 + }, + "comments": { + "type": "Comment[]", + "path": "comments.data", + "description": "Comments on this post.", + "order": 13 + } + } + }, + "User": { + "description": "A user represents a person on Facebook.", + "comment": "https://developers.facebook.com/docs/graph-api/reference/v2.2/user", + "format": "json", + "fields": { + "id": { + "type": "string", + "path": "id", + "description": "The id of this person's user account.", + "order": 0 + }, + "name": { + "type": "string", + "path": "name", + "description": "The person's full name", + "order": 1 + } + } + }, + "Comment": { + "description": "A comment to a post.", + "comment": "https://developers.facebook.com/docs/graph-api/reference/v2.2/comment", + "format": "json", + "fields": { + "id": { + "type": "string", + "path": "id", + "description": "The comment ID", + "order": 0 + }, + "from": { + "type": "User", + "path": "from", + "description": "The person that made this comment", + "order": 1 + }, + "message": { + "type": "string", + "path": "message", + "description": "The comment text", + "order": 2 + } + } + } + }, + "functions": { + "get feed": { + "url": "https://graph.facebook.com/v1.0/me?fields=feed.limit()&access_token=", + "verb": "get", + "description": "The feed of posts (including status updates) and links published by this person, or by others on this person's profile.", + "comment": "https://developers.facebook.com/docs/graph-api/reference/v2.2/user/feed", + "output": "Post[]", + "format": "json", + "post": "feed.data", + "inputs": { + "limit": { + "path": "limit", + "type": "integer", + "description": "Specify how many posts will be retrieved", + "hidden": false, + "indexable": true, + "order": 0 + }, + "access token": { + "path": "access_token", + "type": "string", + "comment": "A user access token with read_stream permission is required.", + "description": "The user's access token. Need Extended Permission: read_stream", + "hidden": false, + "indexable": true, + "order": 1 + } + } + } + } +} \ No newline at end of file diff --git a/java/libs/StickyWeb-doc-2.5.jar b/java/libs/StickyWeb-doc-2.5.jar new file mode 100644 index 0000000..e23c97c Binary files /dev/null and b/java/libs/StickyWeb-doc-2.5.jar differ diff --git a/java/src/realtimeweb/facebookservice/FacebookService.java b/java/src/realtimeweb/facebookservice/FacebookService.java new file mode 100644 index 0000000..21480d1 --- /dev/null +++ b/java/src/realtimeweb/facebookservice/FacebookService.java @@ -0,0 +1,180 @@ +package realtimeweb.facebookservice; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import realtimeweb.facebookservice.domain.*; +import realtimeweb.stickyweb.EditableCache; +import realtimeweb.stickyweb.StickyWeb; +import realtimeweb.stickyweb.StickyWebRequest; +import realtimeweb.stickyweb.StickyWebResponse; +import realtimeweb.stickyweb.exceptions.StickyWebDataSourceNotFoundException; +import realtimeweb.stickyweb.exceptions.StickyWebDataSourceParseException; +import realtimeweb.stickyweb.exceptions.StickyWebInternetException; +import realtimeweb.stickyweb.exceptions.StickyWebInvalidPostArguments; +import realtimeweb.stickyweb.exceptions.StickyWebInvalidQueryString; +import realtimeweb.stickyweb.exceptions.StickyWebJsonResponseParseException; +import realtimeweb.stickyweb.exceptions.StickyWebLoadDataSourceException; +import realtimeweb.stickyweb.exceptions.StickyWebNotInCacheException; + +/** + * Online Social Network + */ +public class FacebookService { + private StickyWeb connection; + private boolean online; + + public static void main(String[] args) { + FacebookService facebookService = new FacebookService(); + + // The following pre-generated code demonstrates how you can + // use StickyWeb's EditableCache to create data files. + try { + // First, you create a new EditableCache, possibly passing in an FileInputStream to an existing cache + EditableCache recording = new EditableCache(); + // You can add a Request object directly to the cache. + // recording.addData(facebookService.getFeedRequest(...)); + // Then you can save the expanded cache, possibly over the original + recording.saveToStream(new FileOutputStream("cache.json")); + } catch (StickyWebDataSourceNotFoundException e) { + System.err.println("The given FileStream was not able to be found."); + } catch (StickyWebDataSourceParseException e) { + System.err.println("The given FileStream could not be parsed; possibly the structure is incorrect."); + } catch (StickyWebLoadDataSourceException e) { + System.err.println("The given data source could not be loaded."); + } catch (FileNotFoundException e) { + System.err.println("The given cache.json file was not found, or could not be opened."); + } + // ** End of how to use the EditableCache + } + + /** + * Create a new, online connection to the service + */ + public FacebookService() { + this.online = true; + try { + this.connection = new StickyWeb(null); + } catch (StickyWebDataSourceNotFoundException e) { + System.err.println("The given datastream could not be loaded."); + } catch (StickyWebDataSourceParseException e) { + System.err.println("The given datastream could not be parsed"); + } catch (StickyWebLoadDataSourceException e) { + System.err.println("The given data source could not be loaded"); + } + } + + /** + * Create a new, offline connection to the service. + * @param cache The filename of the cache to be used. + */ + public FacebookService(String cache) { + // TODO: You might consider putting the cache directly into the jar file, + // and not even exposing filenames! + try { + this.online = false; + this.connection = new StickyWeb(new FileInputStream(cache)); + } catch (StickyWebDataSourceNotFoundException e) { + System.err.println("The given data source could not be found."); + System.exit(1); + } catch (StickyWebDataSourceParseException e) { + System.err.println("Could not read the data source. Perhaps its format is incorrect?"); + System.exit(1); + } catch (StickyWebLoadDataSourceException e) { + System.err.println("The given data source could not be read."); + System.exit(1); + } catch (FileNotFoundException e) { + System.err.println("The given cache file could not be found. Make sure it is in the right folder."); + System.exit(1); + } + } + + + /** + * The feed of posts (including status updates) and links published by this person, or by others on this person's profile. + * + * This version of the function meant for instructors to capture a + * StickyWebRequest object which can be put into an EditableCache and then + * stored to a "cache.json" file. + * + * @param limit Specify how many posts will be retrieved + * @return a StickyWebRequest + * @param accessToken The user's access token + * @return a StickyWebRequest + */ + public StickyWebRequest getFeedRequest(Integer limit, String accessToken) { + try { + /* + * Perform any user parameter validation here. E.g., + * if the first argument can't be zero, or they give an empty string. + */ + + // Build up query string + final String url = String.format("https://graph.facebook.com/v1.0/me?fields=feed.limit(%s)&access_token=%s", String.valueOf(limit), String.valueOf(accessToken)); + + // Build up the query arguments that will be sent to the server + HashMap parameters = new HashMap(); + + // Build up the list of actual arguments that should be used to + // create the local cache hash key + ArrayList indexList = new ArrayList(); + + + // Build and return the connection object. + return connection.get(url, parameters) + .setOnline(online) + .setIndexes(indexList); + + } catch (StickyWebDataSourceNotFoundException e) { + System.err.println("Could not find the data source."); + } + return null; + } + + /** + * The feed of posts (including status updates) and links published by this person, or by others on this person's profile. + + * @param limit Specify how many posts will be retrieved + * @param accessToken The user's access token. Need Extended Permission: read_stream + * @return a Post[] + */ + public ArrayList getFeed(Integer limit, String accessToken) { + + // https://developers.facebook.com/docs/graph-api/reference/v2.2/user/feed + try { + StickyWebRequest request = getFeedRequest(limit, accessToken); + + ArrayList result = new ArrayList(); + StickyWebResponse response = request.execute(); + // TODO: Validate the output here using response.isNull, response.asText, etc. + if (response.isNull()) + return result; + Iterator resultIter = ((ArrayList) ((Map) ((Map) response.asJSON()).get("feed")).get("data")).iterator(); + while (resultIter.hasNext()) { + result.add(new Post((Map)resultIter.next())); + } + return result; + } catch (StickyWebNotInCacheException e) { + System.err.println("There is no query in the cache for the given inputs. Perhaps something was mispelled?"); + } catch (StickyWebInternetException e) { + System.err.println("Could not connect to the web service. It might be your internet connection, or a problem with the web service."); + } catch (StickyWebInvalidQueryString e) { + System.err.println("The given arguments were invalid, and could not be turned into a query."); + } catch (StickyWebInvalidPostArguments e) { + System.err.println("The given arguments were invalid, and could not be turned into a query."); + + } catch (StickyWebJsonResponseParseException e) { + System.err.println("The response from the server couldn't be understood."); + + } + return null; + } + +} \ No newline at end of file diff --git a/java/src/realtimeweb/facebookservice/domain/Comment.java b/java/src/realtimeweb/facebookservice/domain/Comment.java new file mode 100644 index 0000000..16e913a --- /dev/null +++ b/java/src/realtimeweb/facebookservice/domain/Comment.java @@ -0,0 +1,103 @@ +package realtimeweb.facebookservice.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + + + +import realtimeweb.facebookservice.domain.User; + +/** + * A comment to a post. + */ +public class Comment { + + // https://developers.facebook.com/docs/graph-api/reference/v2.2/comment + + private String id; + private User from; + private String message; + + + /* + * @return The comment ID + */ + public String getId() { + return this.id; + } + + /* + * @param The comment ID + * @return String + */ + public void setId(String id) { + this.id = id; + } + + /* + * @return The person that made this comment + */ + public User getFrom() { + return this.from; + } + + /* + * @param The person that made this comment + * @return User + */ + public void setFrom(User from) { + this.from = from; + } + + /* + * @return The comment text + */ + public String getMessage() { + return this.message; + } + + /* + * @param The comment text + * @return String + */ + public void setMessage(String message) { + this.message = message; + } + + + /** + * Creates a string based representation of this Comment. + + * @return String + */ + public String toString() { + return "Comment[" +id+", "+from+", "+message+"]"; + } + + /** + * Internal constructor to create a Comment from a json representation. + * @param map The raw json data that will be parsed. + * @return + */ + public Comment(Map raw) { + // TODO: Check that the data has the correct schema. + // NOTE: It's much safer to check the Map for fields than to catch a runtime exception. + try { + this.id = raw.get("id").toString(); + this.from = new User((Map)raw.get("from")); + this.message = raw.get("message").toString(); + } catch (NullPointerException e) { + System.err.println("Could not convert the response to a Comment; a field was missing."); + e.printStackTrace(); + } catch (ClassCastException e) { + System.err.println("Could not convert the response to a Comment; a field had the wrong structure."); + e.printStackTrace(); + } + + } +} \ No newline at end of file diff --git a/java/src/realtimeweb/facebookservice/domain/Post.java b/java/src/realtimeweb/facebookservice/domain/Post.java new file mode 100644 index 0000000..15bee7a --- /dev/null +++ b/java/src/realtimeweb/facebookservice/domain/Post.java @@ -0,0 +1,317 @@ +package realtimeweb.facebookservice.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + + + + + + + +import realtimeweb.facebookservice.domain.User; + +/** + * An individual entry in a User's feed. + */ +public class Post { + + // https://developers.facebook.com/docs/graph-api/reference/v2.2/post + + private String id; + private User from; + private ArrayList to; + private String message; + private String picture; + private String link; + private String video; + private String name; + private String description; + private String type; + private String createdTime; + private String updatedTime; + private ArrayList likes; + private ArrayList comments; + + + /* + * @return The post ID + */ + public String getId() { + return this.id; + } + + /* + * @param The post ID + * @return String + */ + public void setId(String id) { + this.id = id; + } + + /* + * @return Information about the User that posted the message. + */ + public User getFrom() { + return this.from; + } + + /* + * @param Information about the User that posted the message. + * @return User + */ + public void setFrom(User from) { + this.from = from; + } + + /* + * @return Users mentioned or targeted in this post. + */ + public ArrayList getTo() { + return this.to; + } + + /* + * @param Users mentioned or targeted in this post. + * @return ArrayList + */ + public void setTo(ArrayList to) { + this.to = to; + } + + /* + * @return The main body of the post, otherwise called the status message. + */ + public String getMessage() { + return this.message; + } + + /* + * @param The main body of the post, otherwise called the status message. + * @return String + */ + public void setMessage(String message) { + this.message = message; + } + + /* + * @return The picture scraped from any link included with the post. + */ + public String getPicture() { + return this.picture; + } + + /* + * @param The picture scraped from any link included with the post. + * @return String + */ + public void setPicture(String picture) { + this.picture = picture; + } + + /* + * @return The link attached to this post. + */ + public String getLink() { + return this.link; + } + + /* + * @param The link attached to this post. + * @return String + */ + public void setLink(String link) { + this.link = link; + } + + /* + * @return A URL to any Flash movie or video file attached to the post. + */ + public String getVideo() { + return this.video; + } + + /* + * @param A URL to any Flash movie or video file attached to the post. + * @return String + */ + public void setVideo(String video) { + this.video = video; + } + + /* + * @return The name of the link. + */ + public String getName() { + return this.name; + } + + /* + * @param The name of the link. + * @return String + */ + public void setName(String name) { + this.name = name; + } + + /* + * @return A description of a link in the post (appears beneath the caption). + */ + public String getDescription() { + return this.description; + } + + /* + * @param A description of a link in the post (appears beneath the caption). + * @return String + */ + public void setDescription(String description) { + this.description = description; + } + + /* + * @return A string indicating the object type of this post. + */ + public String getType() { + return this.type; + } + + /* + * @param A string indicating the object type of this post. + * @return String + */ + public void setType(String type) { + this.type = type; + } + + /* + * @return The time the post was initially published. + */ + public String getCreatedTime() { + return this.createdTime; + } + + /* + * @param The time the post was initially published. + * @return String + */ + public void setCreated_Time(String created_Time) { + this.createdTime = created_Time; + } + + /* + * @return The time of the last change to this post, or the comments on it. + */ + public String getUpdatedTime() { + return this.updatedTime; + } + + /* + * @param The time of the last change to this post, or the comments on it. + * @return String + */ + public void setUpdated_Time(String updated_Time) { + this.updatedTime = updated_Time; + } + + /* + * @return People who like this post. + */ + public ArrayList getLikes() { + return this.likes; + } + + /* + * @param People who like this post. + * @return ArrayList + */ + public void setLikes(ArrayList likes) { + this.likes = likes; + } + + /* + * @return Comments on this post. + */ + public ArrayList getComments() { + return this.comments; + } + + /* + * @param Comments on this post. + * @return ArrayList + */ + public void setComments(ArrayList comments) { + this.comments = comments; + } + + + /** + * Creates a string based representation of this Post. + + * @return String + */ + public String toString() { + return "Post[" +id+", "+from+", "+to+", "+message+", "+picture+", "+link+", "+video+", "+name+", "+description+", "+type+", "+createdTime+", "+updatedTime+", "+likes+", "+comments+"]"; + } + + /** + * Internal constructor to create a Post from a json representation. + * @param map The raw json data that will be parsed. + * @return + */ + public Post(Map raw) { + // TODO: Check that the data has the correct schema. + // NOTE: It's much safer to check the Map for fields than to catch a runtime exception. + try { + this.id = raw.get("id").toString(); + this.from = new User((Map)raw.get("from")); + this.to = new ArrayList(); + + Map to = (Map) raw.get("to"); + if(to!=null){ + Iterator toIter = ((List)((Map) raw.get("to")).get("data")).iterator(); + while (toIter.hasNext()) { + this.to.add(new User((Map)toIter.next())); + } + } + if(raw.get("message") != null){this.message = raw.get("message").toString();} else{this.message="";}; + if(raw.get("picture") != null){this.picture = raw.get("picture").toString();} else{this.picture="";}; + if(raw.get("link") != null){this.link = raw.get("link").toString();} else{this.link="";}; + if(raw.get("source") != null){this.video = raw.get("source").toString();} else{this.video="";}; + if(raw.get("name") != null){this.name = raw.get("name").toString();} else{this.name="";}; + if(raw.get("description") != null){this.description = raw.get("description").toString();} else{this.description="";}; + if(raw.get("type") != null){this.type = raw.get("type").toString();} else{this.type="";}; + if(raw.get("created_time") != null){this.createdTime = raw.get("created_time").toString();} else{this.createdTime="";}; + if(raw.get("updated_time") != null){this.updatedTime = raw.get("updated_time").toString();} else{this.updatedTime="";}; + + this.likes = new ArrayList(); + if((Map) raw.get("likes")!=null){ + Iterator likesIter = ((List)((Map) raw.get("likes")).get("data")).iterator(); + while (likesIter.hasNext()) { + this.likes.add(new User((Map)likesIter.next())); + } + } + + this.comments = new ArrayList(); + if((Map) raw.get("comments")!=null){ + Iterator commentsIter = ((List)((Map) raw.get("comments")).get("data")).iterator(); + while (commentsIter.hasNext()) { + this.comments.add(new Comment((Map)commentsIter.next())); + } + } + + } catch (NullPointerException e) { + System.err.println("Could not convert the response to a Post; a field was missing."); + e.printStackTrace(); + } catch (ClassCastException e) { + System.err.println("Could not convert the response to a Post; a field had the wrong structure."); + e.printStackTrace(); + } + + } +} \ No newline at end of file diff --git a/java/src/realtimeweb/facebookservice/domain/User.java b/java/src/realtimeweb/facebookservice/domain/User.java new file mode 100644 index 0000000..a70f407 --- /dev/null +++ b/java/src/realtimeweb/facebookservice/domain/User.java @@ -0,0 +1,84 @@ +package realtimeweb.facebookservice.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + + + + +/** + * A user represents a person on Facebook. + */ +public class User { + + // https://developers.facebook.com/docs/graph-api/reference/v2.2/user + + private String id; + private String name; + + + /* + * @return The id of this person's user account. + */ + public String getId() { + return this.id; + } + + /* + * @param The id of this person's user account. + * @return String + */ + public void setId(String id) { + this.id = id; + } + + /* + * @return The person's full name + */ + public String getName() { + return this.name; + } + + /* + * @param The person's full name + * @return String + */ + public void setName(String name) { + this.name = name; + } + + + /** + * Creates a string based representation of this User. + + * @return String + */ + public String toString() { + return "User[" +id+", "+name+"]"; + } + + /** + * Internal constructor to create a User from a json representation. + * @param map The raw json data that will be parsed. + * @return + */ + public User(Map raw) { + // TODO: Check that the data has the correct schema. + // NOTE: It's much safer to check the Map for fields than to catch a runtime exception. + try { + this.id = raw.get("id").toString(); + this.name = raw.get("name").toString(); + } catch (NullPointerException e) { + System.err.println("Could not convert the response to a User; a field was missing."); + e.printStackTrace(); + } catch (ClassCastException e) { + System.err.println("Could not convert the response to a User; a field had the wrong structure."); + e.printStackTrace(); + } + + } +} \ No newline at end of file diff --git a/java/src/realtimeweb/facebookservice/tests/FacebookServiceTest.java b/java/src/realtimeweb/facebookservice/tests/FacebookServiceTest.java new file mode 100644 index 0000000..764c668 --- /dev/null +++ b/java/src/realtimeweb/facebookservice/tests/FacebookServiceTest.java @@ -0,0 +1,85 @@ +package realtimeweb.facebookservice.tests; + +import static org.junit.Assert.assertNotNull; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.util.ArrayList; + +import org.junit.Test; + +import realtimeweb.facebookservice.FacebookService; +import realtimeweb.facebookservice.domain.Post; +import realtimeweb.stickyweb.EditableCache; +import realtimeweb.stickyweb.exceptions.StickyWebDataSourceNotFoundException; +import realtimeweb.stickyweb.exceptions.StickyWebDataSourceParseException; +import realtimeweb.stickyweb.exceptions.StickyWebInternetException; +import realtimeweb.stickyweb.exceptions.StickyWebInvalidPostArguments; +import realtimeweb.stickyweb.exceptions.StickyWebInvalidQueryString; +import realtimeweb.stickyweb.exceptions.StickyWebLoadDataSourceException; +import realtimeweb.stickyweb.exceptions.StickyWebNotInCacheException; + +public class FacebookServiceTest { + //Need access token with Extended Permission: read_stream; see https://developers.facebook.com/tools/explorer/ + String token = ""; + FacebookService facebookService = new FacebookService(); + + private void assertPostNotNull(Post p) { + assertNotNull(p.getId()); + assertNotNull(p.getFrom()); + assertNotNull(p.getTo()); + assertNotNull(p.getMessage()); + assertNotNull(p.getPicture()); + assertNotNull(p.getLink()); + assertNotNull(p.getVideo()); + assertNotNull(p.getName()); + assertNotNull(p.getDescription()); + assertNotNull(p.getType()); + assertNotNull(p.getCreatedTime()); + assertNotNull(p.getUpdatedTime()); + assertNotNull(p.getLikes()); + assertNotNull(p.getComments()); + } + + @Test + public void testFacebookServiceOnline() { + + ArrayList posts = facebookService.getFeed(10, token); + for(Post p: posts){ + System.out.println(p); + assertPostNotNull(p); + } + } + + @Test + public void testFacebookServiceCache() { + EditableCache recording = new EditableCache(); + //recording + try { + recording.addData(facebookService.getFeedRequest(10, token)); + } catch (StickyWebNotInCacheException | StickyWebInternetException + | StickyWebInvalidQueryString + | StickyWebInvalidPostArguments e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //saving + try { + recording.saveToStream(new FileOutputStream("test-cache.json")); + } catch (StickyWebDataSourceNotFoundException + | StickyWebDataSourceParseException + | StickyWebLoadDataSourceException + | FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //test retrieving from cache + FacebookService facebookServiceFromCache = new FacebookService("test-cache.json"); + ArrayList posts = facebookServiceFromCache.getFeed(10, token); + for(Post p: posts){ + assertPostNotNull(p); + } + } + + +} diff --git a/java/test-cache.json b/java/test-cache.json new file mode 100644 index 0000000..71c7f43 --- /dev/null +++ b/java/test-cache.json @@ -0,0 +1 @@ +{"metadata":{},"data":{}} \ No newline at end of file