Package com.github.jreddit.retrieval

Source Code of com.github.jreddit.retrieval.Comments

package com.github.jreddit.retrieval;

import static com.github.jreddit.utils.restclient.JsonUtils.safeJsonToString;

import java.util.LinkedList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.github.jreddit.entity.Comment;
import com.github.jreddit.entity.Kind;
import com.github.jreddit.entity.Submission;
import com.github.jreddit.entity.User;
import com.github.jreddit.exception.RetrievalFailedException;
import com.github.jreddit.exception.RedditError;
import com.github.jreddit.retrieval.params.CommentSort;
import com.github.jreddit.retrieval.params.TimeSpan;
import com.github.jreddit.retrieval.params.UserOverviewSort;
import com.github.jreddit.utils.ApiEndpointUtils;
import com.github.jreddit.utils.ParamFormatter;
import com.github.jreddit.utils.restclient.RestClient;

/**
* This class offers the following functionality:
* 1) Parsing the results of a request into Comment objects (see <code>Comments.parseBreadth()</code> and <code>Comments.parseDepth()</code>).
* 2) The ability to get comments of a user (see <code>Commments.ofUser()</code>).
* 3) The ability to get comments of a submission/article (see <code>Comments.ofSubmission()</code>).
*
* @author Raul Rene Lepsa
* @author Simon Kassing
*/
public class Comments implements ActorDriven {

    private RestClient restClient;
    private User user;

    /**
     * Constructor. Global default user (null) is used.
     * @param restClient REST Client instance
     */
    public Comments(RestClient restClient) {
        this.restClient = restClient;
        this.user = null;
    }
   
    /**
     * Constructor.
     * @param restClient REST Client instance
     * @param actor User instance
     */
    public Comments(RestClient restClient, User actor) {
      this.restClient = restClient;
        this.user = actor;
    }
   
    /**
     * Switch the current user for the new user who will
     * be used when invoking retrieval requests.
     *
     * @param new_actor New user
     */
    public void switchActor(User new_actor) {
      this.user = new_actor;
    }
   
    /**
     * Parses a JSON feed of comments from Reddit (URL) into a nice list of Comment objects
     * maintaining the order. This parses ONLY the first depth of comments. Only call
     * this function to parse shallow comment listings (e.g. of the user overview).
     *
     * @param url    URL for the request
     *
     * @return Parsed list of comments.
     */
    public List<Comment> parseBreadth(String url) throws RetrievalFailedException, RedditError {
     
      // Determine cookie
      String cookie = (user == null) ? null : user.getCookie();
     
      // List of submissions
        List<Comment> comments = new LinkedList<Comment>();
       
        // Send request to reddit server via REST client
        Object response = restClient.get(url, cookie).getResponseObject();

        if (response instanceof JSONObject) {
         
          JSONObject object = (JSONObject) response;
          if (object.get("error") != null) {
            throw new RedditError("Comments response contained error code " + object.get("error") + ".");
          }
         
          JSONArray array = (JSONArray) ((JSONObject) object.get("data")).get("children");
         
          // Iterate over the submission results
          JSONObject data;
          Comment comment;
          for (Object anArray : array) {
              data = (JSONObject) anArray;
             
              // Make sure it is of the correct kind
              String kind = safeJsonToString(data.get("kind"));
              if (kind.equals(Kind.COMMENT.value())) {
               
                // Contents of the comment
                data = ((JSONObject) data.get("data"));
               
                // Create and add the new comment
                comment = new Comment(data);
                comments.add(comment);
               
              }

          }
       
        } else {
          throw new IllegalArgumentException("Parsing failed because JSON is not from a shallow comment listing.");
        }

        // Finally return list of submissions
        return comments;
       
    }

    /**
     * Parses a JSON feed of comments from Reddit (URL) into a nice list of Comment objects
     * maintaining the order. This parses all comments that are defined with their associated values,
     * those that fall outside the (default) limit are omitted.
     *
     * @param user    User
     * @param url    URL for the request
     *
     * @return Parsed list of comments.
     */
    public List<Comment> parseDepth(String url) throws RetrievalFailedException, RedditError {
     
      // Determine cookie
      String cookie = (user == null) ? null : user.getCookie();
     
      // List of submissions
        List<Comment> comments = new LinkedList<Comment>();
       
        // Send request to reddit server via REST client
        Object response = restClient.get(url, cookie).getResponseObject();
       
        if (response instanceof JSONArray) {
         
          JSONObject object =  (JSONObject) ((JSONArray) response).get(1);
          parseRecursive(comments, object);
         
        } else {
          throw new IllegalArgumentException("Parsing failed because JSON input is not from a submission.");
        }
       
        return comments;
         
    }
   
    /**
     * Parse a JSON object consisting of comments and add them
     * to the already existing list of comments. This does NOT create
     * a new comment list.
     *
     * @param comments   List of comments
     * @param object  JSON Object
     */
    protected void parseRecursive(List<Comment> comments, JSONObject object) throws RetrievalFailedException, RedditError {
      assert comments != null : "List of comments must be instantiated.";
      assert object != null : "JSON Object must be instantiated.";
     
      // Get the comments in an array
        JSONArray array = (JSONArray) ((JSONObject) object.get("data")).get("children");
       
        // Iterate over the submission results
        JSONObject data;
        Comment comment;
        for (Object anArray : array) {
            data = (JSONObject) anArray;
           
            // Make sure it is of the correct kind
            String kind = safeJsonToString(data.get("kind"));
            if (kind.equals(Kind.COMMENT.value())) {
             
              // Contents of the comment
              data = ((JSONObject) data.get("data"));
             
              // Create and add the new comment
              comment = new Comment(data);
              comments.add(comment);
             
              Object o = data.get("replies");
              if (o instanceof JSONObject) {
               
                // Dig towards the replies
                JSONObject replies = (JSONObject) o;
                parseRecursive(comment.getReplies(), replies);

              }
             
            } else if (kind.equals(Kind.MORE.value())) {
             
              //data = (JSONObject) data.get("data");
              //JSONArray children = (JSONArray) data.get("children");
              //System.out.println("\t+ More children: " + children);
             
            }

        }
       
    }
   
    /**
     * Get the comment tree of the given user.
     * In this variant all parameters are Strings.
     *
     * @param username       Username of the user you want to retrieve from.
     * @param sort          (Optional, set null if not used) Sorting method.
     * @param time         (Optional, set null is not used) Time window
     * @param count            (Optional, set null if not used) Number at which the counter starts
     * @param limit            (Optional, set null if not used) Integer representing the maximum number of comments to return
     * @param after        (Optional, set null if not used) After which comment to retrieve
     * @param before      (Optional, set null if not used) Before which comment to retrieve
     * @param show        (Optional, set null if not used) Show parameter ('given' is only acceptable value)
     *
     * @return Comments of a user.
     */
    public List<Comment> ofUser(String username, String sort, String time, String count, String limit, String after, String before, String show) throws RetrievalFailedException, RedditError {
       
      // Format parameters
      String params = "";
      params = ParamFormatter.addParameter(params, "sort", sort);
      params = ParamFormatter.addParameter(params, "time", time);
      params = ParamFormatter.addParameter(params, "count", count);
      params = ParamFormatter.addParameter(params, "limit", limit);
      params = ParamFormatter.addParameter(params, "after", after);
      params = ParamFormatter.addParameter(params, "before", before);
      params = ParamFormatter.addParameter(params, "show", show);
     
        // Retrieve submissions from the given URL
        return parseBreadth(String.format(ApiEndpointUtils.USER_COMMENTS, username, params));
       
    }
   
    /**
     * Get the comment tree of the given user (username).
     *
     * @param username       Username of the user you want to retrieve from.
     * @param sort          (Optional, set null if not used) Sorting method.
     * @param time         (Optional, set null is not used) Time window
     * @param count            (Optional, set -1 if not used) Number at which the counter starts
     * @param limit            (Optional, set -1 if not used) Integer representing the maximum number of comments to return
     * @param after        (Optional, set null if not used) After which comment to retrieve
     * @param before      (Optional, set null if not used) Before which comment to retrieve
     * @param show_given    (Optional, set false if not used) Only show the given comments
     *
     * @return Comments of a user.
     */
    public List<Comment> ofUser(String username, UserOverviewSort sort, TimeSpan time, int count, int limit, Comment after, Comment before, boolean show_given) throws RetrievalFailedException, RedditError {
      
      if (username == null || username.isEmpty()) {
        throw new IllegalArgumentException("The username must be set.");
      }
       
      return ofUser(
          username,
          (sort != null) ? sort.value() : null,
          (time != null) ? time.value() : null,
          String.valueOf(count),
          String.valueOf(limit),
          (after != null) ? after.getFullName() : null,
          (before != null) ? before.getFullName() : null,
          (show_given) ? "given" : null
      );
     
    }
   
    /**
     * Get the comment tree of the given user (object).
     *
     * @param target       User you want to retrieve from.
     * @param sort          (Optional, set null if not used) Sorting method.
     * @param time         (Optional, set null is not used) Time window
     * @param count            (Optional, set -1 if not used) Number at which the counter starts
     * @param limit            (Optional, set -1 if not used) Integer representing the maximum number of comments to return
     * @param after        (Optional, set null if not used) After which comment to retrieve
     * @param before      (Optional, set null if not used) Before which comment to retrieve
     * @param show_given    (Optional, set false if not used) Only show the given comments
     *
     * @return Comments of a user.
     */
    public List<Comment> ofUser(User target, UserOverviewSort sort, TimeSpan time, int count, int limit, Comment after, Comment before, boolean show_given) throws RetrievalFailedException, RedditError {
     
      if (target == null) {
        throw new IllegalArgumentException("The user targeted must be set.");
      }
     
      return ofUser(target.getUsername(), sort, time, count, limit, after, before, show_given);
     
    }

    /**
     * Get the comment tree from a given submission.
     * In this variant all parameters are Strings.
     *
     * @param submissionId     Submission ID36 identifier
     * @param commentId        (Optional, set null if not used) ID of a comment. If specified, this comment will be the focal point of the returned view.
     * @param parentsShown     (Optional, set null is not used) An integer between 0 and 8 representing the number of parents shown for the comment identified by <code>commentId</code>
     * @param depth            (Optional, set null if not used) Integer representing the maximum depth of subtrees in the thread
     * @param limit            (Optional, set null if not used) Integer representing the maximum number of comments to return
     * @param sort        (Optional, set null if not used) CommentSort enum indicating the type of sorting to be applied (e.g. HOT, NEW, TOP, etc)
     * @return Comments for an article.
     */
    public List<Comment> ofSubmission(String submissionId, String commentId, String parentsShown, String depth, String limit, String sort) {
     
      // Format parameters
      String params = "";
      params = ParamFormatter.addParameter(params, "comment", commentId);
      params = ParamFormatter.addParameter(params, "context", parentsShown);
      params = ParamFormatter.addParameter(params, "depth", depth);
      params = ParamFormatter.addParameter(params, "limit", limit);
      params = ParamFormatter.addParameter(params, "sort", sort);
     
        // Retrieve submissions from the given URL
        return parseDepth(String.format(ApiEndpointUtils.SUBMISSION_COMMENTS, submissionId, params));
       
    }
   
    /**
     * Get the comment tree from a given submission (ID36)
     *
     * @param submissionId     Submission ID36 identifier
     * @param commentId        (Optional, set null if not used) ID of a comment. If specified, this comment will be the focal point of the returned view.
     * @param parentsShown     (Optional, set -1 is not used) An integer between 0 and 8 representing the number of parents shown for the comment identified by <code>commentId</code>
     * @param depth            (Optional, set -1 if not used) Integer representing the maximum depth of subtrees in the thread
     * @param limit            (Optional, set -1 if not used) Integer representing the maximum number of comments to return
     * @param sort        (Optional, set null if not used) CommentSort enum indicating the type of sorting to be applied (e.g. HOT, NEW, TOP, etc)
     * @return Comments for an article.
     */
    public List<Comment> ofSubmission(String submissionId, String commentId, int parentsShown, int depth, int limit, CommentSort sort) throws RetrievalFailedException, IllegalArgumentException {
      
      if (submissionId == null || submissionId.isEmpty()) {
        throw new IllegalArgumentException("The identifier of the submission must be set.");
      }
     
      if (depth < -1 || depth > 8) {
        throw new IllegalArgumentException("The depth must be between 1 and 8 (or for default -1).");
      }
       
      return ofSubmission(
          submissionId,
          commentId,
          String.valueOf(parentsShown),
          String.valueOf(depth),
          String.valueOf(limit),
          sort.value()
      );
     
    }
   
    /**
     * Get the comment tree from a given submission (object).
     *
     * @param submission     Submission object
     * @param commentId        (Optional, set null if not used) ID of a comment. If specified, this comment will be the focal point of the returned view.
     * @param parentsShown     (Optional, set -1 is not used) An integer between 0 and 8 representing the number of parents shown for the comment identified by <code>commentId</code>
     * @param depth            (Optional, set -1 if not used) Integer representing the maximum depth of subtrees in the thread
     * @param limit            (Optional, set -1 if not used) Integer representing the maximum number of comments to return
     * @param sort        (Optional, set null if not used) CommentSort enum indicating the type of sorting to be applied (e.g. HOT, NEW, TOP, etc)
     * @return Comments for an article.
     */
    public List<Comment> ofSubmission(Submission submission, String commentId, int parentsShown, int depth, int limit, CommentSort sort) throws RetrievalFailedException, RedditError {
       
      if (submission == null) {
        throw new IllegalArgumentException("The submission must be defined.");
      }
     
      return ofSubmission(submission.getIdentifier(), commentId, parentsShown, depth, limit, sort);
    }
   
  /**
   * Flatten the comment tree.
   * The original comment tree is not overwritten.
   *
   * @param cs    List of comments that you get returned from one of the other methods here
   * @param target  List in which to place the flattend comment tree.
   */
  public static void flattenCommentTree(List<Comment> cs, List<Comment> target) {
    for (Comment c : cs) {
      target.add(c);
      flattenCommentTree(c.getReplies(), target);
    }
  }
 
  /**
   * Print the given comment tree.
   * @param cs   List of comments that you get returned from one of the other methods here
   */
  public static void printCommentTree(List<Comment> cs) {
    for (Comment c : cs) {
      printCommentTree(c, 0);
    }
  }
 
  /**
   * Print the comment at a specific level. Recursive function.
   * @param c      Comment
   * @param level    Level to place at
   */
  private static void printCommentTree(Comment c, int level) {
    for (int i = 0; i < level; i++) {
      System.out.print("\t");
    }
    System.out.println(c);
    for (Comment child : c.getReplies()) {
      printCommentTree(child, level + 1);
    }
  }
   
}
TOP

Related Classes of com.github.jreddit.retrieval.Comments

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.