eu.smartenit.unada.sm.MonitorRunner.java Source code

Java tutorial

Introduction

Here is the source code for eu.smartenit.unada.sm.MonitorRunner.java

Source

/**
 * Copyright (C) 2014 The SmartenIT consortium (http://www.smartenit.eu)
 *
 * Licensed 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 eu.smartenit.unada.sm;

import com.restfb.Connection;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.types.Post;
import com.restfb.types.User;
import eu.smartenit.unada.db.dao.impl.FeedItemDAO;
import eu.smartenit.unada.db.dao.impl.FriendDAO;
import eu.smartenit.unada.db.dao.impl.TrustedUserDAO;
import eu.smartenit.unada.db.dao.impl.VideoInfoDAO;
import eu.smartenit.unada.db.dao.util.DAOFactory;
import eu.smartenit.unada.db.dto.*;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.joda.time.LocalDateTime;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * This class retrieves the relevant content from facebook and vimeo and stores the relevant parts in the database.
 */
class MonitorRunner implements Runnable {

    /**
     * The logger for this class.
     */
    private static final Logger logger = LoggerFactory.getLogger(MonitorRunner.class);

    /**
     * The owner object representing the user for which data is to be retrieved
     */
    private final Owner owner;

    /**
     * Creates a new MonitorRunner instance.
     *
     * @param owner The owner object representing the user for which data is to be retrieved.
     */
    MonitorRunner(Owner owner) {
        this.owner = owner;
    }

    /**
     * Returns the owner object representing the user for which data is retrieved.
     * @return Returns the owner object representing the user for which data is retrieved.
     */
    public Owner getOwner() {
        return owner;
    }

    /**
     * Method that invokes the MonitorRunner.
     */
    @Override
    public void run() {

        logger.debug("Retrieving friends from facebook...");
        List<Friend> friendList = getFriends(owner);
        logger.debug(friendList.size() + " friends found.");
        storeFriends(friendList);

        logger.debug("Exctracting trusted users from friends...");
        List<TrustedUser> trustedUserList = getTrustedUsers(friendList);
        logger.debug(trustedUserList.size() + " trusted users found.");
        storeTrustedUsers(trustedUserList);

        logger.debug("Retrieving feed items from facebook...");
        List<FeedItem> feedItemList = getFeedItems(owner);
        logger.debug(feedItemList.size() + " feed items received.");
        storeFeedItems(feedItemList);

        logger.debug("Exctracting relevant content IDs from feed items...");
        Set<Long> contentIDSet = createContentIDSet(feedItemList);
        logger.debug(contentIDSet.size() + " relevant content IDs found.");

        logger.debug("Retrieving video info from vimeo...");
        List<VideoInfo> videoInfoList = retrieveVideoInfo(contentIDSet);
        logger.debug(videoInfoList.size() + " video infos found.");
        storeVideoInfos(videoInfoList);
    }

    /**
     * Method that creates TrustedUsers from friend list
     *
     * @param friendList A List of Friends.
     * @return Returns TrustedUsers.
     */
    private List<TrustedUser> getTrustedUsers(List<Friend> friendList) {
        List<TrustedUser> trustedUserList = new ArrayList<TrustedUser>();
        for (Friend friend : friendList) {
            TrustedUser trustedUser = new TrustedUser();
            trustedUser.setFacebookID(friend.getFacebookID());
            trustedUserList.add(trustedUser);
        }
        return trustedUserList;
    }

    /**
     * Returns a List of Friends for a given owner
     * @param owner The owner object which represents the user for which data is to be downloaded
     * @return Returns a List of Friends for a given owner
     */
    List<Friend> getFriends(Owner owner) {
        FacebookClient facebookClient = new DefaultFacebookClient(owner.getOauthToken());
        return getFriends(facebookClient, owner);
    }

    /**
     * Returns a List of Friends for a given owner
     *
     * @param facebookClient The client object used to retrieve data from facebook
     * @param owner The owner object which represents the user for which data is to be downloaded
     * @return Returns a List of Friends for a given owner
     */
    List<Friend> getFriends(FacebookClient facebookClient, Owner owner) {
        Connection<User> friends = facebookClient.fetchConnection("me/friends", User.class);
        List<Friend> friendList = new ArrayList<Friend>();

        for (int i = 0; i < friends.getData().size(); i++) {
            for (User facebookFriend : friends.getData()) {
                Friend friend = new Friend();
                friend.setFacebookID(facebookFriend.getId());
                friend.setFacebookName(facebookFriend.getName());
                friendList.add(friend);
            }
        }

        return friendList;
    }

    /**
     * Returns a list of feed items from facebook for a given owner.
     * @param owner The owner object for which the feed items are to be retrieved.
     * @return Returns a list of feed items from facebook for a given owner.
     */
    public List<FeedItem> getFeedItems(Owner owner) {
        FacebookClient facebookClient = new DefaultFacebookClient(owner.getOauthToken());
        return getFeedItems(facebookClient, owner);
    }

    /**
     * Returns a list of feed items from facebook for a given owner.
     *
     * @param facebookClient The client object used to retrieve data from facebook
     * @param owner The owner object for which the feed items are to be retrieved.
     * @return Returns a list of feed items from facebook for a given owner.
     */
    List<FeedItem> getFeedItems(FacebookClient facebookClient, Owner owner) {
        Connection<Post> feeds = facebookClient.fetchConnection("me/feed", Post.class);
        List<FeedItem> feedItemList = new ArrayList<FeedItem>();

        for (int i = 0; i < feeds.getData().size(); i++) {
            Post facebookFeedItem = feeds.getData().get(i);
            FeedItem feedItem = createFeedItem(facebookFeedItem, FeedItem.FeedType.FEED);
            feedItemList.add(feedItem);
        }

        List<Friend> friendList = getFriendsFromDB();
        for (int i = 0; i < friendList.size(); i++) {
            Connection<Post> feedsOfFriend = facebookClient
                    .fetchConnection(friendList.get(i).getFacebookID() + "/feed", Post.class);
            for (int j = 0; j < feedsOfFriend.getData().size(); j++) {
                Post feedOfFriend = feedsOfFriend.getData().get(j);
                //if(String.valueOf(friendList.get(i).getFacebookID()).equals(feedOfFriend.getFrom().getId())) {
                FeedItem feedItem = createFeedItem(feedOfFriend, FeedItem.FeedType.FEED);
                feedItemList.add(feedItem);
                //}
            }
        }

        return feedItemList;
    }

    List<Friend> getFriendsFromDB() {
        FriendDAO friendDAO = DAOFactory.getFriendDAO();
        return friendDAO.findAll();
    }

    /**
     * Creates a FeedItem from a Post.
     * @param post The Post from which the data is to be extracted
     * @param feedType The feed item type
     * @return The created FeedItem object
     */
    private FeedItem createFeedItem(Post post, FeedItem.FeedType feedType) {
        FeedItem feedItem = new FeedItem();
        feedItem.setContentID(extractContentID(post));
        feedItem.setFeedType(feedType);
        feedItem.setFeedItemID(post.getId());
        feedItem.setTime(post.getCreatedTime());
        feedItem.setType(post.getType());
        feedItem.setUserID(post.getFrom().getId());
        return feedItem;
    }

    /**
     * Extracts the relevant feed items from the feed item list provided and returns it in a Set.
     *
     * @param feedItemList A List of FeedItems from which the relevant ids shall be extracted.
     * @return Returns the relevant feed items from the feed item list provided in a Set.
     */
    private Set<Long> createContentIDSet(List<FeedItem> feedItemList) {
        Set<Long> contentIDSet = new HashSet<Long>();
        for (FeedItem item : feedItemList) {
            if (item.getContentID() != -1) {
                contentIDSet.add(item.getContentID());
            }
        }
        return contentIDSet;
    }

    /**
     * Extracts the content id from a given Post object.
     *
     * @param post The post object from which the id is to be extracted
     * @return Returns the content id in a given Post object.
     */
    private long extractContentID(Post post) {
        long contentID = -1;
        if (post.getLink() != null) {
            contentID = extractContentID(post.getLink());
        }
        if (contentID == -1 && post.getDescription() != null) {
            contentID = extractContentID(post.getDescription());
        }
        return contentID;
    }

    /**
     * Extracts the content ID from a given String
     *
     * @param string The string from which the content ID is to be extracted.
     * @return The content ID extracted from a given String.
     */
    private long extractContentID(String string) {
        if (string.contains("vimeo.com")) {
            String[] splitURL = string.split("/");
            String contentID = splitURL[splitURL.length - 1];
            return Long.parseLong(contentID);
        }
        //-1 is for not a vimeo video
        return -1;
    }

    /**
     * Returns video meta information for a given content ID
     *
     * @param contentID The content ID for which video information is to be retrieved
     * @return Returns video meta information for a given content ID
     */
    VideoInfo getVideoInfo(long contentID) {
        JSONObject response = vimeoRequest(contentID);
        VideoInfo videoInfo = new VideoInfo();

        videoInfo.setContentID(contentID);
        List<String> namesList = getNamesList(response);
        if (namesList.contains("upload_date")) {
            videoInfo.setPublishDate(toDate(response.get("upload_date")));
        } else {
            videoInfo.setPublishDate(null);
        }
        if (namesList.contains("stats_number_of_plays")) {
            videoInfo.setViewsNumber(toLong(response.get("stats_number_of_plays")));
        } else {
            videoInfo.setViewsNumber(-1);
        }

        return videoInfo;
    }

    /**
     * Extracts the element names of the JSONObject and places them in a List
     *
     * @param response The response object from which the element names are to be extracted
     * @return The element names of the JSONObject in a List
     */
    private List<String> getNamesList(JSONObject response) {
        JSONArray names = response.names();
        List<String> namesList = new ArrayList<String>();
        if (response != null) {
            for (int i = 0; i < names.length(); i++) {
                namesList.add(names.getString(i));
            }
        }
        return namesList;
    }

    /**
     * Convenience method that casts an Object to an Integer.
     *
     * @param stats_number_of_plays The object to be casted.
     * @return A long value representing the casted object.
     */
    private long toLong(Object stats_number_of_plays) {

        return (Integer) stats_number_of_plays;
    }

    /**
     * Returns the upload date of a given object.
     *
     * @param upload_date The upload date object.
     * @return The upload date of the given object.
     */
    private Date toDate(Object upload_date) {
        String sourceDate = (String) upload_date;
        sourceDate = sourceDate.replaceAll("-", ":");
        sourceDate = sourceDate.replaceAll(" ", ":");
        String[] splitDate = sourceDate.split(":");

        int year = Integer.parseInt(splitDate[0]);
        int month = Integer.parseInt(splitDate[1]);
        int day = Integer.parseInt(splitDate[2]);
        int hour = Integer.parseInt(splitDate[3]);
        int minute = Integer.parseInt(splitDate[4]);
        int second = Integer.parseInt(splitDate[5]);

        LocalDateTime dateTime = new LocalDateTime(year, month, day, hour, minute, second);
        return dateTime.toDate();
    }

    /**
     * Issues a request to vimeo and converts the result to a suitable JSONObject.
     *
     * @param contentID The content ID for which metadata is to be retrieved.
     * @return The JSONObject created from the response of the request.
     */
    private JSONObject vimeoRequest(long contentID) {
        String responseAsString = null;
        CloseableHttpResponse response = null;
        ByteArrayOutputStream out = null;
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            String url = createURL(contentID);
            logger.debug("Sending request to " + url);
            HttpGet httpGet = new HttpGet(url);
            response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            out = new ByteArrayOutputStream();
            entity.writeTo(out);
            responseAsString = out.toString("UTF-8");
            out.close();

        } catch (IOException e) {
            logger.error(e.getMessage(), e.getStackTrace());
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e.getStackTrace());
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e.getStackTrace());
                }
            }

        }
        if (responseAsString == null) {
            return toJSON("{}");
        } else {
            responseAsString = responseAsString.substring(1, responseAsString.length() - 1);
            logger.debug("Converting response to JSON...");
            JSONObject JSONResponse = toJSON(responseAsString);
            logger.debug("Done.");
            return JSONResponse;
        }
    }

    /**
     * Converts a String to a JSONObject.
     *
     * @param responseAsString The string to be converted to a JSONObject.
     * @return The JSONObject created from a String.
     */
    private JSONObject toJSON(String responseAsString) {
        return new JSONObject(responseAsString);
    }

    /**
     * Creates the vimeo URL from a given content ID that is used to retrieve metainformation.
     *
     * @param contentID The content ID for which meatadata is to be retrieved.
     * @return Returns the URL for which metadata is to be retrieved.
     */
    private String createURL(long contentID) {
        return "http://vimeo.com/api/v2/video/" + contentID + ".json";
    }

    /**
     * Stores posts of friends in the database.
     *
     * @param friendPostList The posts of friends to be stored
     */
    private void storeFriendPosts(List<FeedItem> friendPostList) {
        logger.info("Storing friend posts in database...");
        FeedItemDAO feedItemDAO = DAOFactory.getFeedItemDAO();
        try {
            feedItemDAO.insertAll(friendPostList.iterator());
        } catch (Exception e) {
            logger.error("Error while inserting friend posts");
            logger.error(e.getMessage(), e.getStackTrace());
        }
        logger.info("Done.");
    }

    /**
     * Stores friends in the database.
     *
     * @param friendList List containint the friends to be stored.
     */
    private void storeFriends(List<Friend> friendList) {
        logger.info("Storing friends in database...");
        FriendDAO friendDAO = DAOFactory.getFriendDAO();
        try {
            friendDAO.insertAll(friendList.iterator());
        } catch (Exception e) {
            logger.error("Error while inserting friends");
            logger.error(e.getMessage(), e);
        }
        logger.info("Done.");
    }

    /**
     * Creates trusted users from List and stores them in the database
     *
     * @param trustedUserList The friend list to be stored as trusted users.
     */
    private void storeTrustedUsers(List<TrustedUser> trustedUserList) {
        logger.info("Storing trusted users in database...");
        TrustedUserDAO trustedUserDAO = DAOFactory.getTrustedUserDAO();

        try {
            trustedUserDAO.insertAll(trustedUserList.iterator());
        } catch (Exception e) {
            logger.error("Error while inserting trusted users");
            logger.error(e.getMessage(), e);
        }
        logger.info("Done.");
    }

    /**
     * Stores video meta information in the database.
     *
     * @param videoInfoList List containing the video metadata.
     */
    private void storeVideoInfos(List<VideoInfo> videoInfoList) {
        logger.info("Storing video info in database...");
        VideoInfoDAO videoInfoDAO = DAOFactory.getVideoInfoDAO();
        videoInfoDAO.insertAll(videoInfoList.iterator());
        logger.info("Done.");
    }

    /**
     * Returns video metadata for a given Set of contentIDs
     *
     * @param contentIDSet Set of content IDs for which metadata is to be stored.
     * @return Returns video metadata for a given Set of contentIDs
     */
    private List<VideoInfo> retrieveVideoInfo(Set<Long> contentIDSet) {
        List<VideoInfo> videoInfoList = new ArrayList<VideoInfo>();
        for (long contentID : contentIDSet) {
            VideoInfo videoInfo = getVideoInfo(contentID);
            videoInfoList.add(videoInfo);
        }
        return videoInfoList;
    }

    /**
     * Stores feed items in the database.
     *
     * @param feedItemList List of feed items to be stored in the database.
     */
    private void storeFeedItems(List<FeedItem> feedItemList) {
        logger.info("Storing " + feedItemList.size() + " feed items in database...");
        FeedItemDAO feedItemDAO = DAOFactory.getFeedItemDAO();
        try {
            feedItemDAO.insertAll(feedItemList.iterator());
        } catch (Exception e) {
            logger.error("Error while inserting feed items");
            logger.error(e.getMessage(), e);
        }
        logger.info("Done.");
    }
}