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