Coverage Report - net.spy.digg.Digg
 
Classes in this File Line Coverage Branch Coverage Complexity
Digg
6%
11/189
2%
2/82
0
 
<
 1  
 package net.spy.digg;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.io.InputStream;
 5  
 import java.net.URI;
 6  
 import java.net.URISyntaxException;
 7  
 import java.util.ArrayList;
 8  
 import java.util.Collection;
 9  
 import java.util.HashMap;
 10  
 import java.util.Map;
 11  
 
 12  
 import org.apache.commons.httpclient.HttpClient;
 13  
 import org.apache.commons.httpclient.HttpStatus;
 14  
 import org.apache.commons.httpclient.NameValuePair;
 15  
 import org.apache.commons.httpclient.methods.GetMethod;
 16  
 
 17  
 import net.spy.digg.parsers.BaseParser;
 18  
 import net.spy.digg.parsers.ErrorParser;
 19  
 import net.spy.digg.parsers.ErrorsParser;
 20  
 import net.spy.digg.parsers.EventsParser;
 21  
 import net.spy.digg.parsers.GalleriesParser;
 22  
 import net.spy.digg.parsers.StoriesParser;
 23  
 import net.spy.digg.parsers.TopicsParser;
 24  
 import net.spy.digg.parsers.UsersParser;
 25  
 
 26  
 /**
 27  
  * Interface to Digg.
 28  
  */
 29  3
 public class Digg {
 30  
 
 31  
         private static final String BASE_URL="http://services.digg.com/";
 32  
 
 33  9
         private HttpClientFactory clientFactory=new DefaultHttpClientFactory();
 34  
 
 35  9
         private Map<Integer, String> errors=null;
 36  9
         private Map<String, TopicContainer> containers=null;
 37  
 
 38  
         private final String appKey;
 39  
 
 40  
         /**
 41  
          * Construct a Digg interface with the given app key.
 42  
          *
 43  
          * @throws IllegalArgumentException if k is not a valid URL
 44  
          */
 45  
         public Digg(String k) {
 46  9
                 super();
 47  
                 try {
 48  9
                         final URI u=new URI(k);
 49  9
                         if(u.getScheme() == null) {
 50  3
                                 throw new IllegalArgumentException("Invalid URI (no scheme): "
 51  
                                         + k);
 52  
                         }
 53  0
                 } catch(final URISyntaxException e) {
 54  0
                         throw new IllegalArgumentException("Invalid URI:  " + k, e);
 55  6
                 }
 56  6
                 appKey=k;
 57  6
         }
 58  
 
 59  
         /**
 60  
          * Set the http client factory that will be used to construct HttpClient
 61  
          * instances for digg service requests.
 62  
          */
 63  
         public void setHttpClientFactory(HttpClientFactory to) {
 64  0
                 if(to == null) {
 65  0
                         throw new NullPointerException("HttpClientFactory may not be null");
 66  
                 }
 67  0
                 clientFactory=to;
 68  0
         }
 69  
 
 70  
         /**
 71  
          * Get all known errors.
 72  
          */
 73  
         public Map<Integer, String> getErrors() throws DiggException {
 74  0
                 if(errors == null) {
 75  0
                         final ErrorsParser ep=
 76  
                                 fetchParsed(ErrorsParser.class, "errors");
 77  0
                         errors=ep.getErrors();
 78  
                 }
 79  0
                 return errors;
 80  
         }
 81  
 
 82  
         /**
 83  
          * Get an error string for the given ID.
 84  
          */
 85  
         public String getError(int id) throws DiggException {
 86  0
                 return getErrors().get(id);
 87  
         }
 88  
 
 89  
         /**
 90  
          * Get all topics and topic containers.
 91  
          */
 92  
         public Map<String, TopicContainer> getTopics() throws DiggException {
 93  0
                 if(containers == null) {
 94  0
                         final TopicsParser tp=fetchParsed(TopicsParser.class, "topics");
 95  0
                         containers=tp.getContainers();
 96  
                 }
 97  0
                 return containers;
 98  
         }
 99  
 
 100  
         /**
 101  
          * Get the named topic.
 102  
          */
 103  
         public Topic getTopic(String top) throws DiggException {
 104  0
                 Topic rv=null;
 105  0
                 final Map<String, TopicContainer> topics = getTopics();
 106  0
                 for(final Map.Entry<String, TopicContainer> me : topics.entrySet()) {
 107  0
                         for(final Topic t : me.getValue()) {
 108  0
                                 if(t.getName().equals(top) || t.getShortName().equals(top)) {
 109  0
                                         assert rv == null : "Found duplicate topic match";
 110  0
                                         rv=t;
 111  
                                 }
 112  
                         }
 113  
                 }
 114  0
                 return rv;
 115  
         }
 116  
 
 117  
         private PagedItems<User> getUsers(String root, UserParameters p)
 118  
                 throws DiggException {
 119  0
                 final Map<String, String> m=new HashMap<String, String>();
 120  0
                 if(p != null) {
 121  0
                         applyPagingParams(p, m);
 122  
                 }
 123  0
                 final UsersParser up=fetchParsed(UsersParser.class, root, m);
 124  0
                 return new PagedItems<User>(up);
 125  
         }
 126  
 
 127  
         private void applyPagingParams(PagingParameters p, Map<String, String> m) {
 128  0
                 if(p.getSort() != null) {
 129  0
                         m.put("sort", p.getSort());
 130  
                 }
 131  0
                 if(p.getOffset() != null) {
 132  0
                         m.put("offset", String.valueOf(p.getOffset()));
 133  
                 }
 134  0
                 if(p.getCount() !=  null) {
 135  0
                         m.put("count", String.valueOf(p.getCount()));
 136  
                 }
 137  0
         }
 138  
 
 139  
         /**
 140  
          * Get users.
 141  
          *
 142  
          * @param p an optional UserParameters object indicating additional fetch
 143  
          *    stuff
 144  
          */
 145  
         public PagedItems<User> getUsers(UserParameters p) throws DiggException {
 146  0
                 return getUsers("users", p);
 147  
         }
 148  
 
 149  
         /**
 150  
          * Get the friends of the given user.
 151  
          */
 152  
         public PagedItems<User> getFriends(String u, UserParameters p)
 153  
                 throws DiggException {
 154  0
                 return getUsers("user/" + u + "/friends", p);
 155  
         }
 156  
 
 157  
         /**
 158  
          * Get the fans of the given user.
 159  
          */
 160  
         public PagedItems<User> getFans(String u, UserParameters p)
 161  
                 throws DiggException {
 162  0
                 return getUsers("user/" + u + "/fans", p);
 163  
         }
 164  
 
 165  
         /**
 166  
          * Get the specific user.
 167  
          */
 168  
         public User getUser(String name) throws DiggException {
 169  0
                 final UsersParser up=fetchParsed(UsersParser.class, "user/" + name);
 170  0
                 final Map<String, User> users = up.getUsers();
 171  0
                 assert users.size() < 2 : "Too many users returned.";
 172  0
                 User rv=null;
 173  0
                 if(!users.isEmpty()) {
 174  0
                         rv=users.values().iterator().next();
 175  
                 }
 176  0
                 return rv;
 177  
         }
 178  
 
 179  
 
 180  
         private void applyDateParam(Map<String, String> m, String k, Long d) {
 181  0
                 if(d != null) {
 182  0
                         m.put(k, String.valueOf(d/1000));
 183  
                 }
 184  0
         }
 185  
 
 186  
         private PagedItems<Event> getEvents(String root, EventParameters p)
 187  
                 throws DiggException {
 188  0
                 final Map<String, String> m=new HashMap<String, String>();
 189  0
                 if(p != null) {
 190  0
                         applyPagingParams(p, m);
 191  0
                         applyDateParam(m, "max_date", p.getMaxDate());
 192  0
                         applyDateParam(m, "min_date", p.getMinDate());
 193  
                 }
 194  0
                 final EventsParser up=fetchParsed(EventsParser.class, root, m);
 195  0
                 return new PagedItems<Event>(up);
 196  
         }
 197  
 
 198  
         /**
 199  
          * Get all digg events.
 200  
          */
 201  
         public PagedItems<Event> getDiggs(EventParameters p) throws DiggException {
 202  0
                 return getEvents("stories/diggs", p);
 203  
         }
 204  
 
 205  
         /**
 206  
          * Get digg events on popular stories.
 207  
          */
 208  
         public PagedItems<Event> getPopularDiggs(EventParameters p)
 209  
                 throws DiggException {
 210  0
                 return getEvents("stories/popular/diggs", p);
 211  
         }
 212  
 
 213  
         /**
 214  
          * Get digg events on popular stories.
 215  
          */
 216  
         public PagedItems<Event> getUpcomingDiggs(EventParameters p)
 217  
                 throws DiggException {
 218  0
                 return getEvents("stories/upcoming/diggs", p);
 219  
         }
 220  
 
 221  
         /**
 222  
          * Get digg events for the given story id.
 223  
          */
 224  
         public PagedItems<Event> getStoryDiggs(int storyId, EventParameters p)
 225  
                 throws DiggException {
 226  0
                 return getEvents("story/" + storyId + "/diggs", p);
 227  
         }
 228  
 
 229  
         /**
 230  
          * Get digg events for the given story id.
 231  
          */
 232  
         public PagedItems<Event> getStoryDiggs(Collection<Integer> stories,
 233  
                         EventParameters p) throws DiggException {
 234  0
                 return getEvents("stories/" + join(",", stories) + "/diggs", p);
 235  
         }
 236  
 
 237  
         /**
 238  
          * Get the diggs from the given user.
 239  
          */
 240  
         public PagedItems<Event> getUserDiggs(String u, EventParameters p)
 241  
                 throws DiggException {
 242  0
                 return getEvents("user/" + u + "/diggs", p);
 243  
         }
 244  
 
 245  
         /**
 246  
          * Get the diggs from the given users.
 247  
          */
 248  
         public PagedItems<Event> getUserDiggs(Collection<String> users,
 249  
                         EventParameters p) throws DiggException {
 250  0
                 return getEvents("users/" + join(",", users) + "/diggs", p);
 251  
         }
 252  
 
 253  
         private PagedItems<Comment> getComments(String root, EventParameters p)
 254  
                 throws DiggException {
 255  0
                 final Collection<Comment> c=new ArrayList<Comment>();
 256  0
                 for(final Event e : getEvents(root, p)) {
 257  0
                         assert e instanceof Comment : "Expected a comment, got " + e;
 258  0
                         c.add((Comment)e);
 259  
                 }
 260  0
                 return new PagedItems<Comment>(c);
 261  
         }
 262  
 
 263  
         /**
 264  
          * Get all comment events.
 265  
          */
 266  
         public PagedItems<Comment> getComments(EventParameters p)
 267  
                 throws DiggException {
 268  0
                 return getComments("stories/comments", p);
 269  
         }
 270  
 
 271  
         /**
 272  
          * Get comments on popular stories.
 273  
          */
 274  
         public PagedItems<Comment> getPopularComments(EventParameters p)
 275  
                 throws DiggException {
 276  0
                 return getComments("stories/popular/comments", p);
 277  
         }
 278  
 
 279  
         /**
 280  
          * Get comments on upcoming stories.
 281  
          */
 282  
         public PagedItems<Comment> getUpcomingComments(EventParameters p)
 283  
                 throws DiggException {
 284  0
                 return getComments("stories/upcoming/comments", p);
 285  
         }
 286  
 
 287  
         /**
 288  
          * Get comments for the given stories.
 289  
          */
 290  
         public PagedItems<Comment> getComments(Collection<Integer> stories,
 291  
                         EventParameters p) throws DiggException {
 292  0
                 return getComments("stories/" + join(",", stories) + "/comments", p);
 293  
         }
 294  
 
 295  
         /**
 296  
          * Get comments for the given story.
 297  
          */
 298  
         public PagedItems<Comment> getComments(int story, EventParameters p)
 299  
                 throws DiggException {
 300  0
                 return getComments("story/" + story + "/comments", p);
 301  
         }
 302  
 
 303  
         /**
 304  
          * Get comments for the given user.
 305  
          */
 306  
         public PagedItems<Comment> getUserComments(String user, EventParameters p)
 307  
                 throws DiggException {
 308  0
                 return getComments("user/" + user + "/comments", p);
 309  
         }
 310  
 
 311  
         /**
 312  
          * Get comments for the given user.
 313  
          */
 314  
         public PagedItems<Comment> getUserComments(Collection<String> users,
 315  
                         EventParameters p) throws DiggException {
 316  0
                 return getComments("users/" + join(",", users) + "/comments", p);
 317  
         }
 318  
 
 319  
         /**
 320  
          * Get the replies to the given comment on the given story.
 321  
          */
 322  
         public PagedItems<Comment> getCommentReplies(int storyId, int commentId,
 323  
                         EventParameters p) throws DiggException {
 324  0
                 return getComments("story/" + storyId + "/comment/"
 325  
                                 + commentId + "/replies", p);
 326  
         }
 327  
 
 328  
         private PagedItems<Story> getStories(String root, StoryParameters p)
 329  
                 throws DiggException {
 330  0
                 final Map<String, String> m=new HashMap<String, String>();
 331  0
                 if(p != null) {
 332  0
                         applyTimedPagingParameters(p, m);
 333  0
                         applyDateParam(m, "max_promote_date", p.getMaxPromoteDate());
 334  0
                         applyDateParam(m, "min_promote_date", p.getMinPromoteDate());
 335  0
                         if(p.getDomain() != null) {
 336  0
                                 m.put("domain", p.getDomain());
 337  
                         }
 338  0
                         if(p.getLink() != null) {
 339  0
                                 m.put("link", p.getLink());
 340  
                         }
 341  
                 }
 342  0
                 final StoriesParser up=fetchParsed(StoriesParser.class, root, m);
 343  0
                 return new PagedItems<Story>(up);
 344  
         }
 345  
 
 346  
         private void applyTimedPagingParameters(TimestampedPagingParameters p,
 347  
                         final Map<String, String> m) {
 348  0
                 applyPagingParams(p, m);
 349  0
                 applyDateParam(m, "max_submit_date", p.getMaxSubmitDate());
 350  0
                 applyDateParam(m, "min_submit_date", p.getMinSubmitDate());
 351  0
         }
 352  
 
 353  
         /**
 354  
          * Get all stories.
 355  
          */
 356  
         public PagedItems<Story> getStories(StoryParameters p)
 357  
                 throws DiggException {
 358  0
                 return getStories("stories", p);
 359  
         }
 360  
 
 361  
         /**
 362  
          * Get the popular stories.
 363  
          */
 364  
         public PagedItems<Story> getPopularStories(StoryParameters p)
 365  
                 throws DiggException {
 366  0
                 return getStories("stories/popular", p);
 367  
         }
 368  
 
 369  
         /**
 370  
          * Get the upcoming stories.
 371  
          */
 372  
         public PagedItems<Story> getUpcomingStories(StoryParameters p)
 373  
                 throws DiggException {
 374  0
                 return getStories("stories/upcoming", p);
 375  
         }
 376  
 
 377  
         /**
 378  
          * Get the stories in the given container.
 379  
          */
 380  
         public PagedItems<Story> getStories(TopicContainer container,
 381  
                         StoryParameters p) throws DiggException {
 382  0
                 return getStories("stories/container/" + container.getShortName(), p);
 383  
         }
 384  
 
 385  
         /**
 386  
          * Get the popular stories in the given container.
 387  
          */
 388  
         public PagedItems<Story> getPopularStories(TopicContainer container,
 389  
                         StoryParameters p) throws DiggException {
 390  0
                 return getStories("stories/container/" + container.getShortName()
 391  
                                 + "/popular", p);
 392  
         }
 393  
 
 394  
         /**
 395  
          * Get the upcoming stories in the given container.
 396  
          */
 397  
         public PagedItems<Story> getUpcomingStories(TopicContainer container,
 398  
                         StoryParameters p) throws DiggException {
 399  0
                 return getStories("stories/container/" + container.getShortName()
 400  
                                 + "/upcoming", p);
 401  
         }
 402  
 
 403  
         /**
 404  
          * Get all of the stories within the given topic.
 405  
          */
 406  
         public PagedItems<Story> getStories(Topic topic, StoryParameters p)
 407  
                 throws DiggException {
 408  0
                 return getStories("stories/topic/" + topic.getShortName(), p);
 409  
         }
 410  
 
 411  
         /**
 412  
          * Get all of the popular stories within the given topic.
 413  
          */
 414  
         public PagedItems<Story> getPopularStories(Topic topic, StoryParameters p)
 415  
                 throws DiggException {
 416  0
                 return getStories("stories/topic/" + topic.getShortName()
 417  
                                 + "/popular", p);
 418  
         }
 419  
 
 420  
         /**
 421  
          * Get all of the upcoming stories within the given topic.
 422  
          */
 423  
         public PagedItems<Story> getUpcomingStories(Topic topic, StoryParameters p)
 424  
                 throws DiggException {
 425  0
                 return getStories("stories/topic/" + topic.getShortName()
 426  
                                 + "/upcoming", p);
 427  
         }
 428  
 
 429  
         /**
 430  
          * Get the specified stories.
 431  
          */
 432  
         public PagedItems<Story> getStories(Collection<Integer> ids,
 433  
                         StoryParameters p) throws DiggException {
 434  0
                 return getStories("stories/" + join(",", ids), p);
 435  
         }
 436  
 
 437  
         /**
 438  
          * Stories submitted by given user friends.
 439  
          *
 440  
          * @param username the user
 441  
          * @param p story parameters
 442  
          * @return the submitted stories
 443  
          */
 444  
         public PagedItems<Story> getFriendsSubmissions(String username,
 445  
                         StoryParameters p) throws DiggException {
 446  0
                 return getStories("/user/" + username + "/friends/submissions", p);
 447  
         }
 448  
 
 449  
         /**
 450  
          * Popular stories submitted by given user friends.
 451  
          *
 452  
          * @param username the user
 453  
          * @param p story parameters
 454  
          * @return the popular stories
 455  
          */
 456  
         public PagedItems<Story> getFriendsPopularStories(String username,
 457  
                         StoryParameters p) throws DiggException {
 458  0
                 return getStories("/user/" + username + "/friends/popular", p);
 459  
         }
 460  
 
 461  
         /**
 462  
          * Upcoming stories submitted by given user friends.
 463  
          *
 464  
          * @param username the user
 465  
          * @param p story parameters
 466  
          * @return the upcoming stories
 467  
          */
 468  
         public PagedItems<Story> getFriendsUpcomingStories(String username,
 469  
                         StoryParameters p) throws DiggException {
 470  0
                 return getStories("/user/" + username + "/friends/upcoming", p);
 471  
         }
 472  
 
 473  
         /**
 474  
          * Stories dugg by given user friends.
 475  
          *
 476  
          * @param username the user
 477  
          * @param p story parameters
 478  
          * @return the dugg stories
 479  
          */
 480  
         public PagedItems<Story> getFriendsDuggStories(String username,
 481  
                         StoryParameters p) throws DiggException {
 482  0
                 return getStories("/user/" + username + "/friends/dugg", p);
 483  
         }
 484  
 
 485  
         /**
 486  
          * Stories commented by given user friends.
 487  
          *
 488  
          * @param username the user
 489  
          * @param p story parameters
 490  
          * @return the commented stories
 491  
          */
 492  
         public PagedItems<Story> getFriendsCommentedStories(String username,
 493  
                         StoryParameters p) throws DiggException {
 494  0
                 return getStories("/user/" + username + "/friends/commented", p);
 495  
         }
 496  
 
 497  
         /**
 498  
          * Get the story with the given id.
 499  
          */
 500  
         public Story getStory(int id) throws DiggException {
 501  0
                 final PagedItems<Story> c=getStories("story/" + id, null);
 502  0
                 assert c.size() < 2 : "Too many results for " + id;
 503  0
                 Story rv=null;
 504  0
                 if(!c.isEmpty()) {
 505  0
                         rv=c.iterator().next();
 506  
                 }
 507  0
                 return rv;
 508  
         }
 509  
 
 510  
         /**
 511  
          * Get the story with the given clean URL.
 512  
          */
 513  
         public Story getStory(String cleanUrl) throws DiggException {
 514  0
                 final PagedItems<Story> c=getStories("story/" + cleanUrl, null);
 515  0
                 assert c.size() < 2 : "Too many results for " + cleanUrl;
 516  0
                 Story rv=null;
 517  0
                 if(!c.isEmpty()) {
 518  0
                         rv=c.iterator().next();
 519  
                 }
 520  0
                 return rv;
 521  
         }
 522  
 
 523  
         /**
 524  
          * Get the stories submitted by the given user.
 525  
          */
 526  
         public PagedItems<Story> getUserStories(String u, StoryParameters p)
 527  
                 throws DiggException {
 528  0
                 return getStories("user/" + u + "/submissions", p);
 529  
         }
 530  
 
 531  
         private PagedItems<GalleryPhoto> getGalleryPhotos(String root,
 532  
                         GalleryPhotoParameters p) throws DiggException {
 533  
 
 534  0
                 final Map<String, String> m=new HashMap<String, String>();
 535  0
                 if(p != null) {
 536  0
                         applyTimedPagingParameters(p, m);
 537  
                 }
 538  0
                 final GalleriesParser up=fetchParsed(GalleriesParser.class, root, m);
 539  0
                 return new PagedItems<GalleryPhoto>(up);
 540  
         }
 541  
 
 542  
         /**
 543  
          * Get all gallery photos.
 544  
          */
 545  
         public PagedItems<GalleryPhoto> getAllGalleryPhotos(
 546  
                 GalleryPhotoParameters params) throws DiggException {
 547  0
                 return getGalleryPhotos("galleryphotos", params);
 548  
         }
 549  
 
 550  
         /**
 551  
          * Get the gallery photos with the given IDs.
 552  
          */
 553  
         public PagedItems<GalleryPhoto> getAllGalleryPhotos(
 554  
                 GalleryPhotoParameters params, Collection<Integer> ids)
 555  
                 throws DiggException {
 556  0
                 return getGalleryPhotos("galleryphotos/" + join(",", ids), params);
 557  
         }
 558  
 
 559  
         /**
 560  
          * Get the gallery photo with the given ID.
 561  
          */
 562  
         public GalleryPhoto getAllGalleryPhotos(
 563  
                 GalleryPhotoParameters params, int id)
 564  
                 throws DiggException {
 565  0
                 Collection<GalleryPhoto> photos=getGalleryPhotos(
 566  
                         "galleryphotos/" + id, params);
 567  
                 assert photos.size() == 1 : "Incorrect number of photos returned:  "
 568  0
                         + photos.size();
 569  0
                 return photos.iterator().next();
 570  
         }
 571  
 
 572  
         /**
 573  
          * Get all comments for gallery photos.
 574  
          */
 575  
         public PagedItems<Comment> getGalleryComments(EventParameters p)
 576  
                 throws DiggException {
 577  0
                 return getComments("galleryphotos/comments", p);
 578  
         }
 579  
 
 580  
         /**
 581  
          * Get all comments for all gallery photos.
 582  
          */
 583  
         public PagedItems<Comment> getGalleryComments(Collection<Integer> ids,
 584  
                         EventParameters p)
 585  
                 throws DiggException {
 586  0
                 return getComments("galleryphotos/" + join(",", ids) + "/comments", p);
 587  
         }
 588  
 
 589  
         /**
 590  
          * Get all comments for the given photo.
 591  
          */
 592  
         public PagedItems<Comment> getGalleryComments(int id,
 593  
                         EventParameters p)
 594  
                 throws DiggException {
 595  0
                 return getComments("galleryphotos/" + id + "/comments", p);
 596  
         }
 597  
 
 598  
         /**
 599  
          * Get a specific comment for the given photo.
 600  
          */
 601  
         public Comment getGalleryComments(int gid, int cid, EventParameters p)
 602  
                 throws DiggException {
 603  0
                 Collection<Comment>  comments=getComments(
 604  
                         "galleryphotos/" + gid + "/comment/" + cid, p);
 605  
                 assert comments.size() == 1 : "Wrong number of comments returned: "
 606  0
                         + comments.size();
 607  0
                 return comments.iterator().next();
 608  
         }
 609  
 
 610  
         /**
 611