From d4ac8dea1ec86db1f2f2bd01fea635ef96a9c931 Mon Sep 17 00:00:00 2001 From: Antoine Sabot-Durand Date: Tue, 8 May 2012 23:03:23 +0200 Subject: [PATCH] Initial commit --- .gitignore | 11 + LICENSE-2.0.html | 196 ++++++ agorava-twitter-api/pom.xml | 34 + .../agorava/twitter/TwitterBlockService.java | 118 ++++ .../twitter/TwitterDirectMessageService.java | 155 +++++ .../agorava/twitter/TwitterFriendService.java | 418 ++++++++++++ .../agorava/twitter/TwitterGeoService.java | 126 ++++ .../twitter/TwitterTimelineService.java | 635 ++++++++++++++++++ .../agorava/twitter/TwitterUserService.java | 152 +++++ .../agorava/twitter/model/CursoredList.java | 76 +++ .../agorava/twitter/model/DirectMessage.java | 62 ++ .../org/agorava/twitter/model/ImageSize.java | 47 ++ .../InvalidMessageRecipientException.java | 33 + .../model/MessageTooLongException.java | 33 + .../java/org/agorava/twitter/model/Place.java | 80 +++ .../agorava/twitter/model/PlacePrototype.java | 77 +++ .../org/agorava/twitter/model/PlaceType.java | 23 + .../twitter/model/RateLimitStatus.java | 64 ++ .../agorava/twitter/model/SavedSearch.java | 66 ++ .../twitter/model/SavedSearchList.java | 30 + .../agorava/twitter/model/SearchResults.java | 72 ++ .../agorava/twitter/model/SearchService.java | 182 +++++ .../agorava/twitter/model/SimilarPlaces.java | 50 ++ .../twitter/model/SimilarPlacesResponse.java | 54 ++ .../agorava/twitter/model/StatusDetails.java | 114 ++++ .../twitter/model/SuggestionCategory.java | 48 ++ .../twitter/model/SuggestionCategoryList.java | 30 + .../java/org/agorava/twitter/model/Trend.java | 43 ++ .../org/agorava/twitter/model/Trends.java | 45 ++ .../java/org/agorava/twitter/model/Tweet.java | 159 +++++ .../agorava/twitter/model/TwitterProfile.java | 337 ++++++++++ .../twitter/model/TwitterProfileList.java | 30 + .../org/agorava/twitter/model/UserList.java | 91 +++ .../agorava/twitter/model/package-info.java | 22 + agorava-twitter-cdi/pom.xml | 169 +++++ .../src/main/java/org/agorava/Twitter.java | 44 ++ .../java/org/agorava/TwitterBaseService.java | 44 ++ .../main/java/org/agorava/TwitterLiteral.java | 28 + .../java/org/agorava/TwitterServicesHub.java | 58 ++ .../cdi/TwitterTimelineServiceDecorator.java | 58 ++ .../twitter/impl/CursoredLongList.java | 45 ++ .../twitter/impl/TwitterBlockServiceImpl.java | 98 +++ .../impl/TwitterDirectMessageServiceImpl.java | 106 +++ .../impl/TwitterFriendServiceImpl.java | 294 ++++++++ .../twitter/impl/TwitterGeoServiceImpl.java | 129 ++++ .../impl/TwitterTimelineServiceImpl.java | 365 ++++++++++ .../twitter/impl/TwitterUserServiceImpl.java | 155 +++++ .../twitter/jackson/AbstractTrendsList.java | 73 ++ .../twitter/jackson/DailyTrendsList.java | 42 ++ .../twitter/jackson/DirectMessageMixin.java | 40 ++ .../jackson/LocalTrendsDeserializer.java | 73 ++ .../twitter/jackson/LocalTrendsHolder.java | 44 ++ .../agorava/twitter/jackson/PlaceMixin.java | 50 ++ .../jackson/PlaceTypeDeserializer.java | 38 ++ .../agorava/twitter/jackson/PlacesList.java | 62 ++ .../twitter/jackson/RateLimitStatusMixin.java | 37 + .../twitter/jackson/SavedSearchMixin.java | 39 ++ .../twitter/jackson/SearchResultsMixin.java | 40 ++ .../jackson/SimilarPlacesDeserializer.java | 49 ++ .../twitter/jackson/SimilarPlacesMixin.java | 26 + .../jackson/SuggestionCategoryMixin.java | 32 + .../jackson/TimelineDateDeserializer.java | 49 ++ .../agorava/twitter/jackson/TrendMixin.java | 36 + .../agorava/twitter/jackson/TrendsMixin.java | 40 ++ .../twitter/jackson/TweetDeserializer.java | 100 +++ .../agorava/twitter/jackson/TweetMixin.java | 32 + .../twitter/jackson/TwitterModule.java | 63 ++ .../twitter/jackson/TwitterProfileMixin.java | 117 ++++ .../jackson/TwitterProfileUsersList.java | 45 ++ .../agorava/twitter/jackson/UserListList.java | 48 ++ .../twitter/jackson/UserListMixin.java | 54 ++ .../twitter/jackson/WeeklyTrendsList.java | 42 ++ .../agorava/twitter/jackson/package-info.java | 18 + .../src/main/resources/META-INF/beans.xml | 25 + .../org/jboss/seam/social/Twitter.properties | 16 + .../cdi/test/TwitterServiceProducer.java | 43 ++ .../agorava/twitter/cdi/test/TwitterTest.java | 121 ++++ .../src/test/resources/META-INF/beans.xml | 19 + .../src/test/resources/arquillian.xml | 42 ++ pom.xml | 59 ++ 80 files changed, 6920 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE-2.0.html create mode 100644 agorava-twitter-api/pom.xml create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterBlockService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterDirectMessageService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterFriendService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterGeoService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterTimelineService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterUserService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/CursoredList.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/DirectMessage.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/ImageSize.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/InvalidMessageRecipientException.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/MessageTooLongException.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/Place.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlacePrototype.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlaceType.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/RateLimitStatus.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearch.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearchList.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchResults.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchService.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlaces.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlacesResponse.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/StatusDetails.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategory.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategoryList.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trend.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trends.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/Tweet.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfile.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfileList.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/UserList.java create mode 100644 agorava-twitter-api/src/main/java/org/agorava/twitter/model/package-info.java create mode 100644 agorava-twitter-cdi/pom.xml create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/Twitter.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/TwitterBaseService.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/TwitterLiteral.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/TwitterServicesHub.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/cdi/TwitterTimelineServiceDecorator.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/CursoredLongList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterBlockServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterDirectMessageServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterFriendServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterGeoServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterTimelineServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterUserServiceImpl.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/AbstractTrendsList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DailyTrendsList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DirectMessageMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsDeserializer.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsHolder.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceTypeDeserializer.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlacesList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/RateLimitStatusMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SavedSearchMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SearchResultsMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesDeserializer.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SuggestionCategoryMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TimelineDateDeserializer.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendsMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetDeserializer.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterModule.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileUsersList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListMixin.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/WeeklyTrendsList.java create mode 100644 agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/package-info.java create mode 100644 agorava-twitter-cdi/src/main/resources/META-INF/beans.xml create mode 100644 agorava-twitter-cdi/src/main/resources/org/jboss/seam/social/Twitter.properties create mode 100644 agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterServiceProducer.java create mode 100644 agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterTest.java create mode 100644 agorava-twitter-cdi/src/test/resources/META-INF/beans.xml create mode 100644 agorava-twitter-cdi/src/test/resources/arquillian.xml create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75d87e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +target +.classpath +.project +.settings +bin +rebel.xml +*.sw? +*/src/main/java/META-INF +impl/coverage.ec +*.DS_Store +*.iml \ No newline at end of file diff --git a/LICENSE-2.0.html b/LICENSE-2.0.html new file mode 100644 index 0000000..b2760df --- /dev/null +++ b/LICENSE-2.0.html @@ -0,0 +1,196 @@ + + + + + + + + Apache License, Version 2.0 - The Apache Software + Foundation + + +

+ Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/ +

+

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

+

+ 1. Definitions. +

+

"License" shall mean the terms and conditions for use, + reproduction, and distribution as defined by Sections 1 through 9 of + this document.

+

"Licensor" shall mean the copyright owner or entity authorized + by the copyright owner that is granting the License.

+

"Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity.

+

"You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License.

+

"Source" form shall mean the preferred form for making + modifications, including but not limited to software source code, + documentation source, and configuration files.

+

"Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but not + limited to compiled object code, generated documentation, and + conversions to other media types.

+

"Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work (an + example is provided in the Appendix below).

+

"Derivative Works" shall mean any work, whether in Source or + Object form, that is based on (or derived from) the Work and for which + the editorial revisions, annotations, elaborations, or other + modifications represent, as a whole, an original work of authorship. + For the purposes of this License, Derivative Works shall not include + works that remain separable from, or merely link (or bind by name) to + the interfaces of, the Work and Derivative Works thereof.

+

"Contribution" shall mean any work of authorship, including the + original version of the Work and any modifications or additions to + that Work or Derivative Works thereof, that is intentionally submitted + to Licensor for inclusion in the Work by the copyright owner or by an + individual or Legal Entity authorized to submit on behalf of the + copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent to + the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control + systems, and issue tracking systems that are managed by, or on behalf + of, the Licensor for the purpose of discussing and improving the Work, + but excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." +

+

"Contributor" shall mean Licensor and any individual or Legal + Entity on behalf of whom a Contribution has been received by Licensor + and subsequently incorporated within the Work.

+

+ 2. Grant of Copyright License. Subject + to the terms and conditions of this License, each Contributor hereby + grants to You a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable copyright license to reproduce, prepare + Derivative Works of, publicly display, publicly perform, sublicense, + and distribute the Work and such Derivative Works in Source or Object + form. +

+

+ 3. Grant of Patent License. Subject to the + terms and conditions of this License, each Contributor hereby grants + to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable (except as stated in this section) patent license to make, + have made, use, offer to sell, sell, import, and otherwise transfer + the Work, where such license applies only to those patent claims + licensable by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) with + the Work to which such Contribution(s) was submitted. If You institute + patent litigation against any entity (including a cross-claim or + counterclaim in a lawsuit) alleging that the Work or a Contribution + incorporated within the Work constitutes direct or contributory patent + infringement, then any patent licenses granted to You under this + License for that Work shall terminate as of the date such litigation + is filed. +

+

+ 4. Redistribution. You may + reproduce and distribute copies of the Work or Derivative Works + thereof in any medium, with or without modifications, and in Source or + Object form, provided that You meet the following conditions: +

+
    +
  1. You must give any other recipients of the Work or Derivative + Works a copy of this License; and

    +
  2. + +
  3. You must cause any modified files to carry prominent notices + stating that You changed the files; and

    +
  4. + +
  5. You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, excluding those + notices that do not pertain to any part of the Derivative Works; and +

    +
  6. + +
  7. If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained within + such NOTICE file, excluding those notices that do not pertain to any + part of the Derivative Works, in at least one of the following + places: within a NOTICE text file distributed as part of the + Derivative Works; within the Source form or documentation, if + provided along with the Derivative Works; or, within a display + generated by the Derivative Works, if and wherever such third-party + notices normally appear. The contents of the NOTICE file are for + informational purposes only and do not modify the License. You may + add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the + Work, provided that such additional attribution notices cannot be + construed as modifying the License.
  8. +
+ You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated + in this License. + +

+ 5. Submission of Contributions. + Unless You explicitly state otherwise, any Contribution intentionally + submitted for inclusion in the Work by You to the Licensor shall be + under the terms and conditions of this License, without any additional + terms or conditions. Notwithstanding the above, nothing herein shall + supersede or modify the terms of any separate license agreement you + may have executed with Licensor regarding such Contributions. +

+

+ 6. Trademarks. This License does not + grant permission to use the trade names, trademarks, service marks, or + product names of the Licensor, except as required for reasonable and + customary use in describing the origin of the Work and reproducing the + content of the NOTICE file. +

+

+ 7. Disclaimer of Warranty. Unless + required by applicable law or agreed to in writing, Licensor provides + the Work (and each Contributor provides its Contributions) on an "AS + IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied, including, without limitation, any warranties or + conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR + A PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. +

+

+ 8. Limitation of Liability. In no + event and under no legal theory, whether in tort (including + negligence), contract, or otherwise, unless required by applicable law + (such as deliberate and grossly negligent acts) or agreed to in + writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of + any character arising as a result of this License or out of the use or + inability to use the Work (including but not limited to damages for + loss of goodwill, work stoppage, computer failure or malfunction, or + any and all other commercial damages or losses), even if such + Contributor has been advised of the possibility of such damages. +

+

+ 9. Accepting Warranty or Additional + Liability. While redistributing the Work or Derivative Works + thereof, You may choose to offer, and charge a fee for, acceptance of + support, warranty, indemnity, or other liability obligations and/or + rights consistent with this License. However, in accepting such + obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if + You agree to indemnify, defend, and hold each Contributor harmless for + any liability incurred by, or claims asserted against, such + Contributor by reason of your accepting any such warranty or + additional liability. +

+

END OF TERMS AND CONDITIONS

+ + \ No newline at end of file diff --git a/agorava-twitter-api/pom.xml b/agorava-twitter-api/pom.xml new file mode 100644 index 0000000..c60047a --- /dev/null +++ b/agorava-twitter-api/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + agorava-twitter-parent + org.agorava + 1.0.0-SNAPSHOT + + agorava-twitter-api + + + org.agorava + agorava-core-api + + + + agorava-twitter-api + + diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterBlockService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterBlockService.java new file mode 100644 index 0000000..e2a7e03 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterBlockService.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import java.util.List; + +import org.agorava.twitter.model.TwitterProfile; + +/** + * Interface defining the operations for blocking and unblocking users + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface TwitterBlockService { + + /** + * Blocks a user. If a friendship exists with the user, it will be destroyed. + * + * @param userId the ID of the user to block. + * @return The {@link TwitterProfile} of the blocked user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile block(long userId); + + /** + * Blocks a user. If a friendship exists with the user, it will be destroyed. + * + * @param screenName the screen name of the user to block. + * @return The {@link TwitterProfile} of the blocked user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile block(String screenName); + + /** + * Unblocks a user. + * + * @param userId the ID of the user to unblock. + * @return The {@link TwitterProfile} of the unblocked user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile unblock(long userId); + + /** + * Unblocks a user. + * + * @param screenName the screen name of the user to unblock. + * @return The {@link TwitterProfile} of the unblocked user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile unblock(String screenName); + + /** + * Retrieves a list of users that the authenticating user has blocked. + * + * @return a list of {@link TwitterProfile}s for the users that are blocked. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getBlockedUsers(); + + /** + * Retrieves a list of users that the authenticating user has blocked. + * + * @param page the page of blocked users to return + * @param pageSize the number of users per page + * @return a list of {@link TwitterProfile}s for the users that are blocked. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getBlockedUsers(int page, int pageSize); + + /** + * Retrieves a list of user IDs for the users that the authenticating user has blocked. + * + * @return a list of user IDs for the users that are blocked. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getBlockedUserIds(); + + /** + * Determines if the user has blocked a specific user. + * + * @param userId the ID of the user to check for a block. + * @return true if the user is blocked; false otherwise + * @throws ApiException if there is an error while communicating with Twitter. + */ + boolean isBlocking(long userId); + + /** + * Determines if the user has blocked a specific user. + * + * @param screenName the screen name of the user to check for a block. + * @return true if the user is blocked; false otherwise + * @throws ApiException if there is an error while communicating with Twitter. + */ + boolean isBlocking(String screenName); + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterDirectMessageService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterDirectMessageService.java new file mode 100644 index 0000000..914e4e3 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterDirectMessageService.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import java.util.List; + +import org.agorava.twitter.model.DirectMessage; +import org.agorava.twitter.model.InvalidMessageRecipientException; +import org.agorava.twitter.model.MessageTooLongException; + +/** + * Interface defining the Twitter operations for working with direct messages. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface TwitterDirectMessageService { + + /** + * Retrieve the 20 most recently received direct messages for the authenticating user. The most recently received messages + * are listed first. + * + * @return a collection of {@link DirectMessage} with the authenticating user as the recipient. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDirectMessagesReceived(); + + /** + * Retrieve received direct messages for the authenticating user. The most recently received messages are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link DirectMessage}s per page. Should be less than or equal to 200. (Will return at most + * 200 entries, even if pageSize is greater than 200.) + * @return a collection of {@link DirectMessage} with the authenticating user as the recipient. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDirectMessagesReceived(int page, int pageSize); + + /** + * Retrieve received direct messages for the authenticating user. The most recently received messages are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link DirectMessage}s per page. Should be less than or equal to 200. (Will return at most + * 200 entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link DirectMessage} ID to return in the results + * @param maxId The maximum {@link DirectMessage} ID to return in the results + * @return a collection of {@link DirectMessage} with the authenticating user as the recipient. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDirectMessagesReceived(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent direct messages sent by the authenticating user. The most recently sent messages are listed + * first. + * + * @return a collection of {@link DirectMessage} with the authenticating user as the sender. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getDirectMessagesSent(); + + /** + * Retrieve direct messages sent by the authenticating user. The most recently sent messages are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link DirectMessage}s per page. Should be less than or equal to 200. (Will return at most + * 200 entries, even if pageSize is greater than 200.) + * @return a collection of {@link DirectMessage} with the authenticating user as the sender. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getDirectMessagesSent(int page, int pageSize); + + /** + * Retrieve direct messages sent by the authenticating user. The most recently sent messages are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link DirectMessage}s per page. Should be less than or equal to 200. (Will return at most + * 200 entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link DirectMessage} ID to return in the results + * @param maxId The maximum {@link DirectMessage} ID to return in the results + * @return a collection of {@link DirectMessage} with the authenticating user as the sender. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getDirectMessagesSent(int page, int pageSize, long sinceId, long maxId); + + /** + * Gets a direct message by its ID. The message must be readable by the authenticating user. + * + * @param id the message ID + * @return the direct message + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + DirectMessage getDirectMessage(long id); + + /** + * Sends a direct message to another Twitter user. The recipient of the message must follow the authenticated user in order + * for the message to be delivered. If the recipient is not following the authenticated user, an + * {@link InvalidMessageRecipientException} will be thrown. + * + * @param toScreenName the screen name of the recipient of the messages. + * @param text the message text. + * @return the {@link DirectMessage} + * @throws ApiException if there is an error while communicating with Twitter. + * @throws InvalidMessageRecipientException if the recipient is not following the authenticating user. + * @throws DuplicateTweetException if the message duplicates a previously sent message. + * @throws MessageTooLongException if the message length exceeds Twitter's 140 character limit. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + DirectMessage sendDirectMessage(String toScreenName, String text); + + /** + * Sends a direct message to another Twitter user. The recipient of the message must follow the authenticated user in order + * for the message to be delivered. If the recipient is not following the authenticated user, an + * {@link InvalidMessageRecipientException} will be thrown. + * + * @param toUserId the Twitter user ID of the recipient of the messages. + * @param text the message text. + * @return the {@link DirectMessage} + * @throws ApiException if there is an error while communicating with Twitter. + * @throws InvalidMessageRecipientException if the recipient is not following the authenticating user. + * @throws DuplicateTweetException if the message duplicates a previously sent message. + * @throws MessageTooLongException if the message length exceeds Twitter's 140 character limit. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + DirectMessage sendDirectMessage(long toUserId, String text); + + /** + * Deletes a direct message for the authenticated user. + * + * @param messageId the ID of the message to be removed. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void deleteDirectMessage(long messageId); +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterFriendService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterFriendService.java new file mode 100644 index 0000000..5e93faf --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterFriendService.java @@ -0,0 +1,418 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import org.agorava.twitter.model.CursoredList; +import org.agorava.twitter.model.TwitterProfile; + +/** + * Interface defining the operations for working with a user's friends and followers. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface TwitterFriendService { + + /** + * Retrieves a list of up to 5000 users that the authenticated user follows. Note that this method make multiple calls to + * Twitter's REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the + * friend IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFriends(); + + /** + * Retrieves a list of up to 5000 users that the authenticated user follows. Note that this method make multiple calls to + * Twitter's REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the + * friend IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @param cursor the cursor used to fetch the friend IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFriendsInCursor(long cursor); + + /** + * Retrieves a list of up to 5000 users that the given user follows. Note that this method make multiple calls to Twitter's + * REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the friend + * IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @param userId The user's Twitter ID + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriends(long userId); + + /** + * Retrieves a list of up to 5000 users that the given user follows. Note that this method make multiple calls to Twitter's + * REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the friend + * IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @param userId The user's Twitter ID + * @param cursor the cursor used to fetch the friend IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendsInCursor(long userId, long cursor); + + /** + * Retrieves a list of up to 5000 users that the given user follows. Note that this method make multiple calls to Twitter's + * REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the friend + * IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @param screenName The user's Twitter screen name + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriends(String screenName); + + /** + * Retrieves a list of up to 5000 users that the given user follows. Note that this method make multiple calls to Twitter's + * REST API (one call to get a list of the friend IDs and one call for every 100 friends). If all you need is the friend + * IDs, consider calling getFriendIds() instead. Or if you need only a subset of the user's friends, call + * UserOperations.getUsers() passing in the list of friend IDs you need. + * + * @param screenName The user's Twitter screen name + * @param cursor the cursor used to fetch the friend IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendsInCursor(String screenName, long cursor); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the authenticated user follows. Call + * getFriendIdsForCursor() with a cursor value to get the next/previous page of entries. + * + * @return a cursored list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFriendIds(); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the authenticated user follows. + * + * @param cursor The cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFriendIdsInCursor(long cursor); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the given user follows. + * + * @param userId the user's Twitter ID + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendIds(long userId); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the given user follows. + * + * @param userId the user's Twitter ID + * @param cursor the cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendIdsInCursor(long userId, long cursor); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the given user follows. + * + * @param screenName the user's Twitter screen name + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendIds(String screenName); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that the given user follows. + * + * @param screenName the user's Twitter screen name + * @param cursor the cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFriendIdsInCursor(String screenName, long cursor); + + /** + * Retrieves a list of up to 5000 users that the authenticated user is being followed by Note that this method make multiple + * calls to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you + * need is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's + * followers, call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFollowers(); + + /** + * Retrieves a list of up to 5000 users that the authenticated user is being followed by Note that this method make multiple + * calls to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you + * need is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's + * followers, call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @param cursor the cursor used to fetch the follower IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFollowersInCursor(long cursor); + + /** + * Retrieves a list of up to 5000 users that the given user is being followed by Note that this method make multiple calls + * to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you need + * is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's followers, + * call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @param userId The user's Twitter ID + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowers(long userId); + + /** + * Retrieves a list of up to 5000 users that the given user is being followed by Note that this method make multiple calls + * to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you need + * is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's followers, + * call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @param userId The user's Twitter ID + * @param cursor the cursor used to fetch the follower IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowersInCursor(long userId, long cursor); + + /** + * Retrieves a list of up to 5000 users that the given user is being followed by Note that this method make multiple calls + * to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you need + * is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's followers, + * call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @param screenName The user's Twitter screen name + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowers(String screenName); + + /** + * Retrieves a list of up to 5000 users that the given user is being followed by Note that this method make multiple calls + * to Twitter's REST API (one call to get a list of the follower IDs and one call for every 100 followers). If all you need + * is the follower IDs, consider calling getFollowerIds() instead. Or if you need only a subset of the user's followers, + * call UserOperations.getUsers() passing in the list of follower IDs you need. + * + * @param screenName The user's Twitter screen name + * @param cursor the cursor used to fetch the follower IDs + * @return a list of TwitterProfiles + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowersInCursor(String screenName, long cursor); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that follow the authenticated user. + * + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFollowerIds(); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that follow the authenticated user. + * + * @param cursor the cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getFollowerIdsInCursor(long cursor); + + /** + * Retrieves a list of up to 5000IDs for the Twitter users that follow the given user. + * + * @param userId the user's Twitter ID + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowerIds(long userId); + + /** + * Retrieves a list of up to 5000IDs for the Twitter users that follow the given user. + * + * @param userId the user's Twitter ID + * @param cursor the cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowerIdsInCursor(long userId, long cursor); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that follow the given user. + * + * @param screenName the user's Twitter screen name + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowerIds(String screenName); + + /** + * Retrieves a list of up to 5000 IDs for the Twitter users that follow the given user. + * + * @param screenName the user's Twitter screen name + * @param cursor the cursor value to fetch a specific page of entries. Use -1 for the first page of entries. + * @return a list of user IDs + * @throws ApiException if there is an error while communicating with Twitter. + */ + CursoredList getFollowerIdsInCursor(String screenName, long cursor); + + /** + * Allows the authenticated user to follow (create a friendship) with another user. + * + * @param userId The Twitter ID of the user to follow + * @return the name of the followed user if successful + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String follow(long userId); + + /** + * Allows the authenticated user to follow (create a friendship) with another user. + * + * @param screenName The screen name of the user to follow + * @return the name of the followed user if successful + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String follow(String screenName); + + /** + * Allows the authenticated use to unfollow (destroy a friendship) with another user + * + * @param userId the Twitter ID of the user to unfollow + * @return the name of the unfolloed user if successful + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String unfollow(long userId); + + /** + * Allows the authenticated use to unfollow (destroy a friendship) with another user + * + * @param screenName the screen name of the user to unfollow + * @return the name of the unfolloed user if successful + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String unfollow(String screenName); + + /** + * Enable mobile device notifications from Twitter for the specified user. + * + * @param userId the Twitter ID of the user to receive notifications for. + * @return the TwitterProfile for the user + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile enableNotifications(long userId); + + /** + * Enable mobile device notifications from Twitter for the specified user. + * + * @param screenName the Twitter screen name of the user to receive notifications for. + * @return the TwitterProfile for the user + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile enableNotifications(String screenName); + + /** + * Disable mobile device notifications from Twitter for the specified user. + * + * @param userId the Twitter ID of the user to stop notifications for. + * @return the TwitterProfile for the user + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile disableNotifications(long userId); + + /** + * Disable mobile device notifications from Twitter for the specified user. + * + * @param screenName the Twitter screen name of the user to stop notifications for. + * @return the TwitterProfile for the user + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile disableNotifications(String screenName); + + /** + * Checks for a friendship between two users. Returns true if userA follows userB. + * + * @param userA the screen name of userA + * @param userB the screen name of userB + * @throws ApiException if there is an error while communicating with Twitter. + */ + boolean friendshipExists(String userA, String userB); + + /** + * Returns an array of numeric IDs for every user who has a pending request to follow the authenticating user. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getIncomingFriendships(); + + /** + * Returns an array of numeric IDs for every user who has a pending request to follow the authenticating user. + * + * @param cursor the cursor of the page to retrieve. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getIncomingFriendships(long cursor); + + /** + * Returns an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getOutgoingFriendships(); + + /** + * Returns an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request. + * + * @param cursor the cursor of the page to retrieve. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + CursoredList getOutgoingFriendships(long cursor); + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterGeoService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterGeoService.java new file mode 100644 index 0000000..a7f5164 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterGeoService.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import java.util.List; + +import org.agorava.twitter.model.Place; +import org.agorava.twitter.model.PlacePrototype; +import org.agorava.twitter.model.PlaceType; +import org.agorava.twitter.model.SimilarPlaces; + +/** + * Interface defining the Twitter operations for working with locations. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface TwitterGeoService { + + /** + * Retrieves information about a place + * + * @param id the place ID + * @return a {@link Place} + * @throws ApiException if there is an error while communicating with Twitter. + */ + Place getPlace(String id); + + /** + * Retrieves up to 20 places matching the given location. + * + * @param latitude the latitude + * @param longitude the longitude + * @return a list of {@link Place}s that the point is within + * @throws ApiException if there is an error while communicating with Twitter. + */ + List reverseGeoCode(double latitude, double longitude); + + /** + * Retrieves up to 20 places matching the given location and criteria + * + * @param latitude the latitude + * @param longitude the longitude + * @param granularity the minimal granularity of the places to return. If null, the default granularity (neighborhood) is + * assumed. + * @param accuracy a radius of accuracy around the given point. If given a number, the value is assumed to be in meters. The + * number may be qualified with "ft" to indicate feet. If null, the default accuracy (0m) is assumed. + * @return a list of {@link Place}s that the point is within + * @throws ApiException if there is an error while communicating with Twitter. + */ + List reverseGeoCode(double latitude, double longitude, PlaceType granularity, String accuracy); + + /** + * Searches for up to 20 places matching the given location. + * + * @param latitude the latitude + * @param longitude the longitude + * @return a list of {@link Place}s that the point is within + * @throws ApiException if there is an error while communicating with Twitter. + */ + List search(double latitude, double longitude); + + /** + * Searches for up to 20 places matching the given location and criteria + * + * @param latitude the latitude + * @param longitude the longitude + * @param granularity the minimal granularity of the places to return. If null, the default granularity (neighborhood) is + * assumed. + * @param accuracy a radius of accuracy around the given point. If given a number, the value is assumed to be in meters. The + * number may be qualified with "ft" to indicate feet. If null, the default accuracy (0m) is assumed. + * @param query a free form text value to help find places by name. If null, no query will be applied to the search. + * @return a list of {@link Place}s that the point is within + * @throws ApiException if there is an error while communicating with Twitter. + */ + List search(double latitude, double longitude, PlaceType granularity, String accuracy, String query); + + /** + * Finds places similar to a place described in the parameters. Returns a list of places along with a token that is required + * for creating a new place. This method must be called before calling createPlace(). + * + * @param latitude the latitude + * @param longitude the longitude + * @param name the name that the place is known as + * @return a {@link SimilarPlaces} collection, including a token that can be used to create a new place. + * @throws ApiException if there is an error while communicating with Twitter. + */ + SimilarPlaces findSimilarPlaces(double latitude, double longitude, String name); + + /** + * Finds places similar to a place described in the parameters. Returns a list of places along with a token that is required + * for creating a new place. This method must be called before calling createPlace(). + * + * @param latitude the latitude + * @param longitude the longitude + * @param name the name that the place is known as + * @param streetAddress the place's street address. May be null. + * @param containedWithin the ID of the place that the place is contained within + * @return a {@link SimilarPlaces} collection, including a token that can be used to create a new place. + * @throws ApiException if there is an error while communicating with Twitter. + */ + SimilarPlaces findSimilarPlaces(double latitude, double longitude, String name, String streetAddress, String containedWithin); + + /** + * Creates a new place. + * + * @param placePrototype the place prototype returned in a {@link SimilarPlaces} from a call to findSimilarPlaces() + * @return a {@link Place} object with the newly created place data + * @throws ApiException if there is an error while communicating with Twitter. + */ + Place createPlace(PlacePrototype placePrototype); +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterTimelineService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterTimelineService.java new file mode 100644 index 0000000..4de1a8e --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterTimelineService.java @@ -0,0 +1,635 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import java.util.List; + +import org.agorava.twitter.model.MessageTooLongException; +import org.agorava.twitter.model.Tweet; +import org.agorava.twitter.model.TwitterProfile; + +/** + * Interface defining the operations for sending and retrieving tweets. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface TwitterTimelineService { + + /** + * Retrieves the 20 most recently posted tweets from the public timeline. The public timeline is the timeline containing + * tweets from all Twitter users. As this is the public timeline, authentication is not required to use this method. + *

+ * Note that Twitter caches public timeline results for 60 seconds. Calling this method more frequently than that will count + * against rate limits and will not return any new results. + *

+ * + * @return a collection of {@link Tweet}s in the public timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getPublicTimeline(); + + /** + * Retrieves the 20 most recently posted tweets, including retweets, from the authenticating user's home timeline. The home + * timeline includes tweets from the user's timeline and the timeline of anyone that they follow. + * + * @return a collection of {@link Tweet}s in the authenticating user's home timeline. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getHomeTimeline(); + + /** + * Retrieves tweets, including retweets, from the authenticating user's home timeline. The home timeline includes tweets + * from the user's timeline and the timeline of anyone that they follow. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @return a collection of {@link Tweet}s in the authenticating user's home timeline. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getHomeTimeline(int page, int pageSize); + + /** + * Retrieves tweets, including retweets, from the authenticating user's home timeline. The home timeline includes tweets + * from the user's timeline and the timeline of anyone that they follow. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a collection of {@link Tweet}s in the authenticating user's home timeline. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getHomeTimeline(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieves the 20 most recent tweets posted by the authenticating user. + * + * @return a collection of {@link Tweet}s that have been posted by the authenticating user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getUserTimeline(); + + /** + * Retrieves tweets posted by the authenticating user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @return a collection of {@link Tweet}s that have been posted by the authenticating user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getUserTimeline(int page, int pageSize); + + /** + * Retrieves tweets posted by the authenticating user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a collection of {@link Tweet}s that have been posted by the authenticating user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getUserTimeline(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieves the 20 most recent tweets posted by the given user. + * + * @param screenName The screen name of the user whose timeline is being requested. + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(String screenName); + + /** + * Retrieves tweets posted by the given user. The most recent tweets are listed first. + * + * @param screenName The screen name of the user whose timeline is being requested. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(String screenName, int page, int pageSize); + + /** + * Retrieves tweets posted by the given user. The most recent tweets are listed first. + * + * @param screenName The screen name of the user whose timeline is being requested. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(String screenName, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieves the 20 most recent tweets posted by the given user. + * + * @param userId The user ID of the user whose timeline is being requested. + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(long userId); + + /** + * Retrieves tweets posted by the given user. The most recent tweets are listed first. + * + * @param userId The user ID of the user whose timeline is being requested. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(long userId, int page, int pageSize); + + /** + * Retrieves tweets posted by the given user. The most recent tweets are listed first. + * + * @param userId The user ID of the user whose timeline is being requested. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a collection of {@link Tweet}s from the specified user's timeline. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUserTimeline(long userId, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent tweets that mention the authenticated user. + * + * @return a collection of {@link Tweet} objects that mention the authenticated user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getMentions(); + + /** + * Retrieve tweets that mention the authenticated user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @return a collection of {@link Tweet} objects that mention the authenticated user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getMentions(int page, int pageSize); + + /** + * Retrieve tweets that mention the authenticated user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 200. (Will return at most 200 + * entries, even if pageSize is greater than 200.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a collection of {@link Tweet} objects that mention the authenticated user. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getMentions(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets posted by the authenticated user. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByMe(); + + /** + * Retrieve retweets posted by the authenticated user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByMe(int page, int pageSize); + + /** + * Retrieve retweets posted by the authenticated user. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByMe(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets posted by the specified user. + * + * @param userId The user ID to get retweets for. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(long userId); + + /** + * Retrieve retweets posted by the specified user. The most recent tweets are listed first. + * + * @param userId The user ID to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(long userId, int page, int pageSize); + + /** + * Retrieve retweets posted by the specified user. The most recent tweets are listed first. + * + * @param userId The user ID to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(long userId, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets posted by the specified user. + * + * @param screenName The screen name of the user to get retweets for. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(String screenName); + + /** + * Retrieve retweets posted by the specified user. The most recent tweets are listed first. + * + * @param screenName The screen name of the user to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(String screenName, int page, int pageSize); + + /** + * Retrieve retweets posted by the specified user. The most recent tweets are listed first. + * + * @param screenName The screen name of the user to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByUser(String screenName, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets posted by users the authenticating user follow. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToMe(); + + /** + * Retrieve retweets posted by users the authenticating user follow. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToMe(int page, int pageSize); + + /** + * Retrieve retweets posted by users the authenticating user follow. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToMe(int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets posted by users that the specified user follows. + * + * @param userId The user ID to get retweets for. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(long userId); + + /** + * Retrieve retweets posted by users that the specified user follows. The most recent tweets are listed first. + * + * @param userId The user ID to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(long userId, int page, int pageSize); + + /** + * Retrieve retweets posted by users that the specified user follows. The most recent tweets are listed first. + * + * @param userId The user ID to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(long userId, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent retweets by users that the specified user follows. + * + * @param screenName The screen name of the user to get retweets for. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(String screenName); + + /** + * Retrieve retweets by users that the specified user follows. The most recent tweets are listed first. + * + * @param screenName The screen name of the user to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(String screenName, int page, int pageSize); + + /** + * Retrieve retweets by users that the specified user follows. The most recent tweets are listed first. + * + * @param screenName The screen name of the user to get retweets for. + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedToUser(String screenName, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieve the 20 most recent tweets of the authenticated user that have been retweeted by others. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetsOfMe(); + + /** + * Retrieve tweets of the authenticated user that have been retweeted by others. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetsOfMe(int page, int pageSize); + + /** + * Retrieve tweets of the authenticated user that have been retweeted by others. The most recent tweets are listed first. + * + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetsOfMe(int page, int pageSize, long sinceId, long maxId); + + /** + * Returns a single tweet. + * + * @param tweetId the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + */ + Tweet getStatus(long tweetId); + + /** + * Updates the user's status. + * + * @param status The status message + * @throws ApiException if there is an error while communicating with Twitter. + * @throws DuplicateTweetException if the status message duplicates a previously posted status. + * @throws MessageTooLongException if the length of the status message exceeds Twitter's 140 character limit. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + Tweet updateStatus(String status); + + /** + * Updates the user's status along with a picture. + * + * @param status The status message + * @param photo A {@link Resource} for the photo data. The given Resource must implement the getFilename() method (such as + * {@link FileSystemResource} or {@link ClassPathResource}) and must contain GIF, JPG, or PNG data. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws DuplicateTweetException if the status message duplicates a previously posted status. + * @throws MessageTooLongException if the length of the status message exceeds Twitter's 140 character limit. + * @throws OperationNotPermittedException if the photo resource isn't a GIF, JPG, or PNG. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + // TODO: add types for updateStatus(String status, Resource photo); + + /** + * Updates the user's status, including additional metadata concerning the status. + * + * @param status The status message + * @param details Metadata pertaining to the status + * @throws ApiException if there is an error while communicating with Twitter. + * @throws DuplicateTweetException if the status message duplicates a previously posted status. + * @throws MessageTooLongException if the length of the status message exceeds Twitter's 140 character limit. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + + // TODO: add types for Tweet updateStatus(String status, StatusDetails details); + + /** + * Updates the user's status, including a picture and additional metadata concerning the status. + * + * @param status The status message + * @param photo A {@link Resource} for the photo data. The given Resource must implement the getFilename() method (such as + * {@link FileSystemResource} or {@link ClassPathResource}) and must contain GIF, JPG, or PNG data. + * @param details Metadata pertaining to the status + * @throws ApiException if there is an error while communicating with Twitter. + * @throws DuplicateTweetException if the status message duplicates a previously posted status. + * @throws MessageTooLongException if the length of the status message exceeds Twitter's 140 character limit. + * @throws OperationNotPermittedException if the photo resource isn't a GIF, JPG, or PNG. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + // TODO add types for Tweet updateStatus(String status, Resource photo, StatusDetails details); + + /** + * Removes a status entry. + * + * @param tweetId the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void deleteStatus(long tweetId); + + /** + * Posts a retweet of an existing tweet. + * + * @param tweetId The ID of the tweet to be retweeted + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void retweet(long tweetId); + + /** + * Retrieves up to 100 retweets of a specific tweet. + * + * @param tweetId the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getRetweets(long tweetId); + + /** + * Retrieves retweets of a specific tweet. + * + * @param tweetId the tweet's ID + * @param count The maximum number of retweets to return. Should be less than or equal to 100. (Will return at most 100 + * entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getRetweets(long tweetId, int count); + + /** + * Retrieves the profiles of up to 100 users how have retweeted a specific tweet. + * + * @param id the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getRetweetedBy(long id); + + /** + * Retrieves the profiles of users how have retweeted a specific tweet. + * + * @param tweetId the tweet's ID + * @param page The page to return + * @param pageSize The number of {@link TwitterProfile}s per page. Should be less than or equal to 100. (Will return at most + * 100 entries, even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getRetweetedBy(long tweetId, int page, int pageSize); + + /** + * Retrieves the IDs of up to 100 users who have retweeted a specific tweet. + * + * @param tweetId the tweet's ID. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByIds(long tweetId); + + /** + * Retrieves the IDs of users who have retweeted a specific tweet. + * + * @param tweetId the tweet's ID. + * @param page The page to return + * @param pageSize The number of entries per page. Should be less than or equal to 100. (Will return at most 100 entries, + * even if pageSize is greater than 100.) + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getRetweetedByIds(long tweetId, int page, int pageSize); + + /** + * Retrieves the 20 most recent tweets favorited by the authenticated user. + * + * @return a collection of {@link Tweet}s from the specified user's favorite timeline. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getFavorites(); + + /** + * Retrieves tweets favorited by the authenticated user. + * + * @param page The page to return + * @param pageSize The number of entries per page. + * @return a collection of {@link Tweet}s from the specified user's favorite timeline. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getFavorites(int page, int pageSize); + + /** + * Adds a tweet to the user's collection of favorite tweets. + * + * @param id the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void addToFavorites(long id); + + /** + * Removes a tweet from the user's collection of favorite tweets. + * + * @param id the tweet's ID + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void removeFromFavorites(long id); + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterUserService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterUserService.java new file mode 100644 index 0000000..8910a3d --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/TwitterUserService.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter; + +import java.util.List; + +import org.agorava.twitter.model.ImageSize; +import org.agorava.twitter.model.RateLimitStatus; +import org.agorava.twitter.model.SuggestionCategory; +import org.agorava.twitter.model.TwitterProfile; + +/** + * Interface defining the operations for retrieving information about Twitter users. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + * + */ +public interface TwitterUserService { + + /** + * Retrieves the authenticated user's Twitter ID. + * + * @return the user's ID at Twitter + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String getProfileId(); + + /** + * Retrieves the authenticated user's Twitter screen name + * + * @return the user's screen name + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + String getScreenName(); + + /** + * Retrieves the authenticated user's Twitter profile details. + * + * @return a {@link TwitterProfile} object representing the user's profile. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + TwitterProfile getUserProfile(); + + /** + * Retrieves a specific user's Twitter profile details. Note that this method does not require authentication. + * + * @param screenName the screen name for the user whose details are to be retrieved. + * @return a {@link TwitterProfile} object representing the user's profile. + * @throws ApiException if there is an error while communicating with Twitter. + */ + TwitterProfile getUserProfile(String screenName); + + /** + * Retrieves a specific user's Twitter profile details. Note that this method does not require authentication. + * + * @param userId the user ID for the user whose details are to be retrieved. + * @return a {@link TwitterProfile} object representing the user's profile. + * @throws ApiException if there is an error while communicating with Twitter. + */ + TwitterProfile getUserProfile(long userId); + + /** + * Retrieves the user's profile image. Returns the image in Twitter's "normal" size (48px x 48px). + * + * @param screenName the screen name of the user + * @return an array of bytes containing the user's profile image. + * @throws ApiException if there is an error while communicating with Twitter. + */ + byte[] getUserProfileImage(String screenName); + + /** + * Retrieves the user's profile image. Returns the image in Twitter's "normal" type. + * + * @param screenName the screen name of the user + * @param size the size of the image + * @return an array of bytes containing the user's profile image. + * @throws ApiException if there is an error while communicating with Twitter. + */ + byte[] getUserProfileImage(String screenName, ImageSize size); + + /** + * Retrieves a list of Twitter profiles for the given list of user IDs. + * + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUsers(String... userIds); + + /** + * Searches for up to 20 users that match a given query. + * + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List searchForUsers(String query); + + /** + * Searches for users that match a given query. + * + * @param page the page of search results to return + * @param pageSize the number of {@link TwitterProfile}s per page. Maximum of 20 per page. + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List searchForUsers(String query, int page, int pageSize); + + /** + * Retrieves a list of categories from which suggested users to follow may be found. + * + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getSuggestionCategories(); + + /** + * Retrieves a list of suggestions of users to follow for a given category. + * + * @param slug the category's slug + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getSuggestions(String slug); + + /** + * Retrieves the rate limit status. Can be used with either either an authorized or unauthorized TwitterTemplate. If the + * TwitterTemplate is authorized, the rate limits apply to the authenticated user. If the TwitterTemplate is unauthorized, + * the rate limits apply to the IP address from with the request is made. + */ + RateLimitStatus getRateLimitStatus(); + + /** + * Retrieves a list of Twitter profiles for the given list of screen names. + * + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getUsersByName(String... screenNames); +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/CursoredList.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/CursoredList.java new file mode 100644 index 0000000..9f14ebd --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/CursoredList.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * List that includes previous and next cursors for paging through items returned from Twitter in cursored pages. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + * @param the list element type + */ +@SuppressWarnings("serial") +public class CursoredList extends ArrayList { + + private final long previousCursor; + + private final long nextCursor; + + public CursoredList(Collection collection, long previousCursor, long nextCursor) { + super(collection); + this.previousCursor = previousCursor; + this.nextCursor = nextCursor; + } + + public CursoredList(int initialCapacity, long previousCursor, long nextCursor) { + super(initialCapacity); + this.previousCursor = previousCursor; + this.nextCursor = nextCursor; + } + + /** + * The cursor to retrieve the previous page of results. + */ + public long getPreviousCursor() { + return previousCursor; + } + + /** + * The cursor to retrieve the next page of results. + */ + public long getNextCursor() { + return nextCursor; + } + + /** + * Returns true if there is a previous page of results. + */ + public boolean hasPrevious() { + return previousCursor > 0; + } + + /** + * Returns true if there is a next page of results. + */ + public boolean hasNext() { + return nextCursor > 0; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/DirectMessage.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/DirectMessage.java new file mode 100644 index 0000000..a897c56 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/DirectMessage.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; + +/** + * Represents a direct message. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class DirectMessage { + private final long id; + private final String text; + private final TwitterProfile sender; + private final TwitterProfile recipient; + private final Date createdAt; + + public DirectMessage(long id, String text, TwitterProfile sender, TwitterProfile recipient, Date createdAt) { + this.id = id; + this.text = text; + this.sender = sender; + this.recipient = recipient; + this.createdAt = createdAt; + } + + public long getId() { + return id; + } + + public String getText() { + return text; + } + + public TwitterProfile getSender() { + return sender; + } + + public TwitterProfile getRecipient() { + return recipient; + } + + public Date getCreatedAt() { + return createdAt; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/ImageSize.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/ImageSize.java new file mode 100644 index 0000000..c19ec30 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/ImageSize.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Enumeration of image sizes supported by Twitter + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public enum ImageSize { + + /** + * 24px x 24px + */ + MINI, + + /** + * 48px x 48px + */ + NORMAL, + + /** + * 73px x 73px + */ + BIGGER, + + /** + * The original image size + */ + ORIGINAL + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/InvalidMessageRecipientException.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/InvalidMessageRecipientException.java new file mode 100644 index 0000000..17e3b51 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/InvalidMessageRecipientException.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Exception thrown when an attempt is made to send a direct message to an invalid recipient; that is, a recipient who is not + * following the authenticated user. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class InvalidMessageRecipientException extends IllegalArgumentException { + private static final long serialVersionUID = 1L; + + public InvalidMessageRecipientException(String message) { + super(message); + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/MessageTooLongException.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/MessageTooLongException.java new file mode 100644 index 0000000..fd58192 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/MessageTooLongException.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Exception indicating that an attempt was made to post a status or send a direct message where the length exceeds Twitter's + * 140 character limit. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@SuppressWarnings("serial") +public class MessageTooLongException extends IllegalArgumentException { + + public MessageTooLongException(String message) { + super(message); + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Place.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Place.java new file mode 100644 index 0000000..979a4b5 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Place.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Represents a place that a Twitter user may send a tweet from. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class Place { + + private final String id; + + private final String name; + + private final String fullName; + + private final String streetAddress; + + private final String country; + + private final String countryCode; + + private final PlaceType placeType; + + public Place(String id, String name, String fullName, String streetAddress, String country, String countryCode, + PlaceType placeType) { + this.id = id; + this.name = name; + this.fullName = fullName; + this.country = country; + this.streetAddress = streetAddress; + this.countryCode = countryCode; + this.placeType = placeType; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getFullName() { + return fullName; + } + + public String getStreetAddress() { + return streetAddress; + } + + public String getCountry() { + return country; + } + + public String getCountryCode() { + return countryCode; + } + + public PlaceType getPlaceType() { + return placeType; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlacePrototype.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlacePrototype.java new file mode 100644 index 0000000..2b9e873 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlacePrototype.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import org.agorava.twitter.TwitterGeoService; + +/** + * Represents a new place that could be created. This is the type returned from calls to + * {@link TwitterGeoService#findSimilarPlaces(double, double, String)}. It is the only type that can be given to + * {@link TwitterGeoService#createPlace(PlacePrototype)} to create a new place. This guarantees consistency between the query + * performed when finding similar places and when creating a new place so that the create token will be valid. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class PlacePrototype { + + private final double latitude; + + private final double longitude; + + private final String name; + + private final String containedWithin; + + private final String createToken; + + private final String streetAddress; + + public PlacePrototype(String createToken, double latitude, double longitude, String name, String streetAddress, + String containedWithin) { + this.createToken = createToken; + this.latitude = latitude; + this.longitude = longitude; + this.name = name; + this.streetAddress = streetAddress; + this.containedWithin = containedWithin; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + public String getName() { + return name; + } + + public String getStreetAddress() { + return streetAddress; + } + + public String getContainedWithin() { + return containedWithin; + } + + public String getCreateToken() { + return createToken; + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlaceType.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlaceType.java new file mode 100644 index 0000000..8f9201c --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/PlaceType.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +public enum PlaceType { + + POINT_OF_INTEREST, NEIGHBORHOOD, CITY, ADMIN, COUNTRY + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/RateLimitStatus.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/RateLimitStatus.java new file mode 100644 index 0000000..6c1d21b --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/RateLimitStatus.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; + +/** + * Carries data concerning the rate limit status. + */ +public class RateLimitStatus { + + private final int hourlyLimit; + + private final int remainingHits; + + private final long resetTimeInSeconds; + + private final Date resetTime; + + public RateLimitStatus(int hourlyLimit, int remainingHits, long resetTimeInSeconds) { + this.hourlyLimit = hourlyLimit; + this.remainingHits = remainingHits; + this.resetTimeInSeconds = resetTimeInSeconds; + this.resetTime = new Date(resetTimeInSeconds * 1000); + } + + public int getHourlyLimit() { + return hourlyLimit; + } + + public int getRemainingHits() { + return remainingHits; + } + + public long getResetTimeInSeconds() { + return resetTimeInSeconds; + } + + public Date getResetTime() { + return resetTime; + } + + /** + * The approximate number of seconds until the rate limits are reset. Note that this method recalculates the seconds until + * reset on each call. + */ + public int getSecondsUntilReset() { + return (int) (resetTimeInSeconds - System.currentTimeMillis() / 1000); + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearch.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearch.java new file mode 100644 index 0000000..7fab382 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearch.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; + +/** + * Represents a saved search. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class SavedSearch { + private final long id; + + private final String name; + + private final String query; + + private final Date createdAt; + + private final int position; + + public SavedSearch(long id, String name, String query, int position, Date createdAt) { + this.id = id; + this.name = name; + this.query = query; + this.position = position; + this.createdAt = createdAt; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getQuery() { + return query; + } + + public Date getCreatedAt() { + return createdAt; + } + + public int getPosition() { + return position; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearchList.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearchList.java new file mode 100644 index 0000000..79ccac0 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SavedSearchList.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.ArrayList; + + +/** + * Typed list of SavedSearch. This helps Jackson know what type to deserialize the list contents into. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@SuppressWarnings("serial") +class SavedSearchList extends ArrayList { +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchResults.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchResults.java new file mode 100644 index 0000000..c343924 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchResults.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.List; + +/** + * Represents the results of a Twitter search, including matching {@link Tweet}s and any metadata associated with that search. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class SearchResults { + private List tweets; + private long maxId; + private long sinceId; + private boolean lastPage; + + public SearchResults(List tweets, long maxId, long sinceId) { + this(tweets, maxId, sinceId, false); + } + + public SearchResults(List tweets, long maxId, long sinceId, boolean lastPage) { + this.tweets = tweets; + this.maxId = maxId; + this.sinceId = sinceId; + this.lastPage = lastPage; + } + + /** + * Returns the list of matching {@link Tweet}s + */ + public List getTweets() { + return tweets; + } + + /** + * Returns the maximum {@link Tweet} ID in the search results + */ + public long getMaxId() { + return maxId; + } + + /** + * Returns the {@link Tweet} ID after which all of the matching {@link Tweet}s were created + */ + public long getSinceId() { + return sinceId; + } + + /** + * Returns true if this is the last page of matching {@link Tweet}s; false if there are more pages + * that follow this one. + */ + public boolean isLastPage() { + return lastPage; + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchService.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchService.java new file mode 100644 index 0000000..7a711eb --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SearchService.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.List; + +/** + * Interface defining the operations for searching Twitter and retrieving trending data. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public interface SearchService { + + /** + * Searches Twitter, returning the first 50 matching {@link Tweet}s + * + * @param query The search query string + * @return a {@link SearchResults} containing the search results metadata and a list of matching {@link Tweet}s + * @throws ApiException if there is an error while communicating with Twitter. + * @see SearchResults + * @see Tweet + */ + SearchResults search(String query); + + /** + * Searches Twitter, returning a specific page out of the complete set of results. + * + * @param query The search query string + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page + * @return a {@link SearchResults} containing the search results metadata and a list of matching {@link Tweet}s + * @throws ApiException if there is an error while communicating with Twitter. + * @see SearchResults + * @see Tweet + */ + SearchResults search(String query, int page, int pageSize); + + /** + * Searches Twitter, returning a specific page out of the complete set of results. Results are filtered to those whose ID + * falls between sinceId and maxId. + * + * @param query The search query string + * @param page The page to return + * @param pageSize The number of {@link Tweet}s per page + * @param sinceId The minimum {@link Tweet} ID to return in the results + * @param maxId The maximum {@link Tweet} ID to return in the results + * @return a {@link SearchResults} containing the search results metadata and a list of matching {@link Tweet}s + * @throws ApiException if there is an error while communicating with Twitter. + * @see SearchResults + * @see Tweet + */ + SearchResults search(String query, int page, int pageSize, long sinceId, long maxId); + + /** + * Retrieves the authenticating user's saved searches. + * + * @return a list of SavedSearch items + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + List getSavedSearches(); + + /** + * Retrieves a single saved search by the saved search's ID. + * + * @param searchId the ID of the saved search + * @return a SavedSearch + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + SavedSearch getSavedSearch(long searchId); + + /** + * Creates a new saved search for the authenticating user. + * + * @param query the search query to save + * @return the SavedSearch + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + SavedSearch createSavedSearch(String query); + + /** + * Deletes a saved search + * + * @param searchId the ID of the saved search + * @throws ApiException if there is an error while communicating with Twitter. + * @throws MissingAuthorizationException if TwitterTemplate was not created with OAuth credentials. + */ + void deleteSavedSearch(long searchId); + + /** + * Retrieves the top 20 trending topics, hourly for the past 24 hours. This list includes hashtagged topics. + * + * @return a list of Trends objects, one for each hour in the past 24 hours, ordered with the most recent hour first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDailyTrends(); + + /** + * Retrieves the top 20 trending topics, hourly for the past 24 hours. + * + * @param excludeHashtags if true, hashtagged topics will be excluded from the trends list. + * @return a list of Trends objects, one for each hour in the past 24 hours, ordered with the most recent hour first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDailyTrends(boolean excludeHashtags); + + /** + * Retrieves the top 20 trending topics, hourly for a 24-hour period starting at the specified date. + * + * @param excludeHashtags if true, hashtagged topics will be excluded from the trends list. + * @param startDate the date to start retrieving trending data for, in MM-DD-YYYY format. + * @return a list of Trends objects, one for each hour in the given 24 hours, ordered with the most recent hour first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getDailyTrends(boolean excludeHashtags, String startDate); + + /** + * Retrieves the top 30 trending topics for each day in the past week. This list includes hashtagged topics. + * + * @return a list of Trends objects, one for each day in the past week, ordered with the most recent day first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getWeeklyTrends(); + + /** + * Retrieves the top 30 trending topics for each day in the past week. + * + * @param excludeHashtags if true, hashtagged topics will be excluded from the trends list. + * @return a list of Trends objects, one for each day in the past week, ordered with the most recent day first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getWeeklyTrends(boolean excludeHashtags); + + /** + * Retrieves the top 30 trending topics for each day in a given week. + * + * @param excludeHashtags if true, hashtagged topics will be excluded from the trends list. + * @param startDate the date to start retrieving trending data for, in MM-DD-YYYY format. + * @return a list of Trends objects, one for each day in the given week, ordered with the most recent day first. + * @throws ApiException if there is an error while communicating with Twitter. + */ + List getWeeklyTrends(boolean excludeHashtags, String startDate); + + /** + * Retrieves the top 10 trending topics for a given location, identified by its "Where on Earth" (WOE) ID. This includes + * hashtagged topics. See http://developer.yahoo.com/geo/geoplanet/guide/concepts.html for more information on WOE. + * + * @param whereOnEarthId the Where on Earth ID for the location to retrieve trend data. + * @return A Trends object with the top 10 trending topics for the location. + * @throws ApiException if there is an error while communicating with Twitter. + */ + Trends getLocalTrends(long whereOnEarthId); + + /** + * Retrieves the top 10 trending topics for a given location, identified by its "Where on Earth" (WOE) ID. See + * http://developer.yahoo.com/geo/geoplanet/guide/concepts.html for more information on WOE. + * + * @param whereOnEarthId the Where on Earth ID for the location to retrieve trend data. + * @param excludeHashtags if true, hashtagged topics will be excluded from the trends list. + * @return A Trends object with the top 10 trending topics for the given location. + * @throws ApiException if there is an error while communicating with Twitter. + */ + Trends getLocalTrends(long whereOnEarthId, boolean excludeHashtags); + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlaces.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlaces.java new file mode 100644 index 0000000..2ea676e --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlaces.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.ArrayList; +import java.util.List; + +import org.agorava.twitter.TwitterGeoService; + +/** + * Represents the results of a similar places search. Includes places that match the search criteria and a + * {@link PlacePrototype} that can be used to create a new place. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@SuppressWarnings("serial") +public class SimilarPlaces extends ArrayList { + + private final PlacePrototype placePrototype; + + public SimilarPlaces(List places, PlacePrototype placePrototype) { + super(places); + this.placePrototype = placePrototype; + } + + /** + * A prototype place that matches the criteria for the call to + * {@link TwitterGeoService#findSimilarPlaces(double, double, String)}, including a create token that can be used to create + * the place. + */ + public PlacePrototype getPlacePrototype() { + return placePrototype; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlacesResponse.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlacesResponse.java new file mode 100644 index 0000000..1b4815f --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SimilarPlacesResponse.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.List; + + +/** + * Represents the results of a similar places search. Includes places that match the search criteria and a token that may be + * used to create a new place. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class SimilarPlacesResponse { + + private final String token; + private final List places; + + public SimilarPlacesResponse(List places, String token) { + this.places = places; + this.token = token; + } + + /** + * The list of places found in a similar places search. + * + * @return + */ + public List getPlaces() { + return places; + } + + /** + * A token that may be used to create a new place. + */ + public String getToken() { + return token; + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/StatusDetails.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/StatusDetails.java new file mode 100644 index 0000000..6c2a773 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/StatusDetails.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.HashMap; +import java.util.Map; + +/** + * Carries optional metadata pertaining to a Twitter status update. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class StatusDetails { + + private Long inReplyToStatusId; + + private Float latitude; + + private Float longitude; + + private boolean displayCoordinates; + + private boolean wrapLinks; + + /** + * Sets the ID of an existing status that this status is in reply to. Will be ignored unless the text of this status + * includes the author of the existing status (e.g., "@author"). + * + * @param inReplyToStatusId the ID of an existing status that this status is in reply to. + * @return the {@link StatusDetails} object + */ + public StatusDetails setInReplyToStatusId(long inReplyToStatusId) { + this.inReplyToStatusId = inReplyToStatusId; + return this; + } + + /** + * Sets the location of the status update in latitude and longitude. Latitude values must be between -90.0 (south) and +90.0 + * (north). Longitude values must be between -180.0 (west) and +180.0 (east). + * + * For example, latitude=51.502 and longitude=-0.126 are the coordinates for Westminster, London. + * + * @param latitude The latitude element of the location. Must be between -90.0 and +90.0, where positive values are north + * and negative values are south. + * @param longitude The longitude element of the location. Must be between -180.0 and +180.0, where positive values are east + * and negative values are west. + * @return The {@link StatusDetails} object + */ + public StatusDetails setLocation(float latitude, float longitude) { + this.latitude = latitude; + this.longitude = longitude; + return this; + } + + /** + * Indicates that Twitter should pinpoint the location precisely when displaying it on a map. By default, Twitter will + * display the status along with a map showing the general area where the tweet came from. If display coordinates is true, + * however, it will display a map with a pin indicating the precise location of the status update. + * + * @param displayCoordinates If true, will pinpoint the location of the status update. + * @return The {@link StatusDetails} object + */ + public StatusDetails setDisplayCoordinates(boolean displayCoordinates) { + this.displayCoordinates = displayCoordinates; + return this; + } + + public StatusDetails setWrapLinks(boolean wrapLinks) { + this.wrapLinks = wrapLinks; + return this; + } + + /** + * Maps the {@link StatusDetails} values to a Map of Twitter parameters. + * + * @return A {@link Map} of parameters to be passed along in the status update post to Twitter. + */ + public Map toParameterMap() { + Map parameterMap = new HashMap(); + if (latitude != null && longitude != null) { + parameterMap.put("lat", latitude.toString()); + parameterMap.put("long", longitude.toString()); + } + + if (displayCoordinates) { + parameterMap.put("display_coordinates", "true"); + } + + if (inReplyToStatusId != null) { + parameterMap.put("in_reply_to_status_id", inReplyToStatusId.toString()); + } + + if (wrapLinks) { + parameterMap.put("wrap_links", "true"); + } + + return parameterMap; + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategory.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategory.java new file mode 100644 index 0000000..736de99 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategory.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Represents a suggestion category; a category of users that Twitter may suggest that a user follow. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class SuggestionCategory { + private final String name; + private final String slug; + private final int size; + + public SuggestionCategory(String name, String slug, int size) { + this.name = name; + this.slug = slug; + this.size = size; + } + + public String getName() { + return name; + } + + public String getSlug() { + return slug; + } + + public int getSize() { + return size; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategoryList.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategoryList.java new file mode 100644 index 0000000..b6c12bc --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/SuggestionCategoryList.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.ArrayList; + + +/** + * Typed list of SuggestionCategory. This helps Jackson know what type to deserialize the list contents into. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@SuppressWarnings("serial") +class SuggestionCategoryList extends ArrayList { +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trend.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trend.java new file mode 100644 index 0000000..5679a9d --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trend.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Represents a single trending topic. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class Trend { + private final String name; + + private final String query; + + public Trend(String name, String query) { + this.name = name; + this.query = query; + } + + public String getName() { + return name; + } + + public String getQuery() { + return query; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trends.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trends.java new file mode 100644 index 0000000..157e819 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Trends.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; +import java.util.List; + +/** + * Represents a list of trending topics at a specific point in time. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class Trends { + private final Date time; + private final List trends; + + public Trends(Date time, List trends) { + this.time = time; + this.trends = trends; + } + + public Date getTime() { + return time; + } + + public List getTrends() { + return trends; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Tweet.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Tweet.java new file mode 100644 index 0000000..a805d38 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/Tweet.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; + +/** + * Represents a Twitter status update (e.g., a "tweet"). + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class Tweet { + private long id; + private String text; + private Date createdAt; + private String fromUser; + private String profileImageUrl; + private Long toUserId; + private Long inReplyToStatusId; + private long fromUserId; + private boolean favorited; + private String languageCode; + private String source; + private Integer retweetCount; + + public Tweet(long id, String text, Date createdAt, String fromUser, String profileImageUrl, Long toUserId, long fromUserId, + String languageCode, String source) { + this.id = id; + this.text = text; + this.createdAt = createdAt; + this.fromUser = fromUser; + this.profileImageUrl = profileImageUrl; + this.toUserId = toUserId; + this.fromUserId = fromUserId; + this.languageCode = languageCode; + this.source = source; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public String getFromUser() { + return fromUser; + } + + public void setFromUser(String fromUser) { + this.fromUser = fromUser; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getProfileImageUrl() { + return profileImageUrl; + } + + public void setProfileImageUrl(String profileImageUrl) { + this.profileImageUrl = profileImageUrl; + } + + public Long getToUserId() { + return toUserId; + } + + public void setToUserId(Long toUserId) { + this.toUserId = toUserId; + } + + public long getFromUserId() { + return fromUserId; + } + + public void setInReplyToStatusId(Long inReplyToStatusId) { + this.inReplyToStatusId = inReplyToStatusId; + } + + public Long getInReplyToStatusId() { + return inReplyToStatusId; + } + + public void setFromUserId(long fromUserId) { + this.fromUserId = fromUserId; + } + + public String getLanguageCode() { + return languageCode; + } + + public void setLanguageCode(String languageCode) { + this.languageCode = languageCode; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public void setRetweetCount(Integer retweetCount) { + this.retweetCount = retweetCount; + } + + /** + * The number of times this tweet has been retweeted. Only available in timeline results. getRetweetCount() will return null + * for Tweet objects returned in search results. + */ + public Integer getRetweetCount() { + return retweetCount; + } + + /** + * @return the favorited + */ + public boolean isFavorited() { + return favorited; + } + + /** + * @param favorited the favorited to set + */ + public void setFavorited(boolean favorited) { + this.favorited = favorited; + } +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfile.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfile.java new file mode 100644 index 0000000..051a960 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfile.java @@ -0,0 +1,337 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.Date; + +import org.agorava.core.api.UserProfile; + +/** + * Model class representing a Twitter user's profile information. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class TwitterProfile extends UserProfile { + + private static final long serialVersionUID = -6675776414312067618L; + + private final String screenName; + private final String name; + private final String url; + private final String profileImageUrl; + private final String description; + private final String location; + private final Date createdDate; + private String language; + private int statusesCount; + private int friendsCount; + private int followersCount; + private int favoritesCount; + private int listedCount; + private boolean following; + private boolean followRequestSent; + private boolean isProtected; + private boolean notificationsEnabled; + private boolean verified; + private boolean geoEnabled; + private boolean contributorsEnabled; + private boolean translator; + private String timeZone; + private int utcOffset; + private String sidebarBorderColor; + private String sidebarFillColor; + private String backgroundColor; + private boolean useBackgroundImage; + private String backgroundImageUrl; + private boolean backgroundImageTiled; + private String textColor; + private String linkColor; + private boolean showAllInlineMedia; + + public TwitterProfile(String id, String screenName, String name, String url, String profileImageUrl, String description, + String location, Date createdDate) { + super(id); + this.screenName = screenName; + this.name = name; + this.url = url; + this.profileImageUrl = profileImageUrl; + this.description = description; + this.location = location; + this.createdDate = createdDate; + } + + /** + * The user's Twitter screen name + * + * @return The user's Twitter screen name + */ + public String getScreenName() { + return screenName; + } + + /** + * The user's full name + * + * @return The user's full name + */ + public String getName() { + return name; + } + + /** + * The user's URL + * + * @return The user's URL + */ + public String getUrl() { + return url; + } + + /** + * The user's description + * + * @return The user's description + */ + public String getDescription() { + return description; + } + + /** + * The user's location + * + * @return The user's location + */ + public String getLocation() { + return location; + } + + /** + *

+ * The URL of the user's profile image in "normal" size (48x48). + *

+ * + * @return The URL of the user's normal-sized profile image. + */ + @Override + public String getProfileImageUrl() { + return profileImageUrl; + } + + /** + *

+ * The URL of the user's profile. + *

+ * + * @return The URL of the user's profile. + */ + public String getProfileUrl() { + return "http://twitter.com/" + screenName; + } + + /** + * The date that the Twitter profile was created. + * + * @return The date that the Twitter profile was created. + */ + public Date getCreatedDate() { + return createdDate; + } + + /** + * Whether or not the user has mobile notifications enabled. + */ + public boolean isNotificationsEnabled() { + return notificationsEnabled; + } + + /** + * Whether or not the user is verified with Twitter. See + * http://support.twitter.com/groups/31-twitter-basics/topics/111-features/articles/119135-about-verified-accounts. + */ + public boolean isVerified() { + return verified; + } + + /** + * Whether or not the user has enabled their account with geo location. + */ + public boolean isGeoEnabled() { + return geoEnabled; + } + + /** + * The user's preferred language. + */ + public String getLanguage() { + return language; + } + + /** + * The number of tweets this user has posted. + */ + public int getStatusesCount() { + return statusesCount; + } + + /** + * The number of lists the user is listed on. + */ + public int getListedCount() { + return listedCount; + } + + /** + * The number of friends the user has (the number of users this user follows). + */ + public int getFriendsCount() { + return friendsCount; + } + + /** + * The number of followers the user has. + */ + public int getFollowersCount() { + return followersCount; + } + + /** + * Whether or not the authenticated user is following this user. + */ + public boolean isFollowing() { + return following; + } + + /** + * Whether or not a request has been sent by the authenticating user to follow this user. + */ + public boolean isFollowRequestSent() { + return followRequestSent; + } + + /** + * The number of tweets that the user has marked as favorites. + */ + public int getFavoritesCount() { + return favoritesCount; + } + + /** + * Whether or not the user's tweets are protected. + */ + public boolean isProtected() { + return isProtected; + } + + /** + * The user's time zone. + */ + public String getTimeZone() { + return timeZone; + } + + /** + * The user's UTC offset in seconds. + */ + public int getUtcOffset() { + return utcOffset; + } + + /** + * Whether or not this profile is enabled for contributors. + */ + public boolean isContributorsEnabled() { + return contributorsEnabled; + } + + /** + * Whether or not this user is a translator. + */ + public boolean isTranslator() { + return translator; + } + + /** + * The color of the sidebar border on the user's Twitter profile page. + */ + public String getSidebarBorderColor() { + return sidebarBorderColor; + } + + /** + * The color of the sidebar fill on the user's Twitter profile page. + */ + public String getSidebarFillColor() { + return sidebarFillColor; + } + + /** + * The color of the background of the user's Twitter profile page. + */ + public String getBackgroundColor() { + return backgroundColor; + } + + /** + * Whether or not the user's Twitter profile page uses a background image. + */ + public boolean useBackgroundImage() { + return useBackgroundImage; + } + + /** + * The URL to a background image shown on the user's Twitter profile page. + */ + public String getBackgroundImageUrl() { + return backgroundImageUrl; + } + + /** + * Whether or not the background image is tiled. + */ + public boolean isBackgroundImageTiled() { + return backgroundImageTiled; + } + + /** + * The text color on the user's Twitter profile page. + */ + public String getTextColor() { + return textColor; + } + + /** + * The link color on the user's Twitter profile page. + */ + public String getLinkColor() { + return linkColor; + } + + /** + * Whether or not the user has selected to see all inline media from everyone. If false, they will only see inline media + * from the users they follow. + */ + public boolean showAllInlineMedia() { + return showAllInlineMedia; + } + + @Override + public String getFullName() { + return getName(); + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfileList.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfileList.java new file mode 100644 index 0000000..79cfab4 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/TwitterProfileList.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +import java.util.ArrayList; + + +/** + * Typed list of TwitterProfile. This helps Jackson know which type to deserialize list contents into. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@SuppressWarnings("serial") +class TwitterProfileList extends ArrayList { +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/UserList.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/UserList.java new file mode 100644 index 0000000..b7fec01 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/UserList.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * Represents a user-defined list. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +public class UserList { + private final long id; + private final String name; + private final String fullName; + private final String uriPath; + private final String description; + private final String slug; + private final boolean isPublic; + private final boolean isFollowing; + private final int memberCount; + private final int subscriberCount; + + public UserList(long id, String name, String fullName, String uriPath, String description, String slug, boolean isPublic, + boolean isFollowing, int memberCount, int subscriberCount) { + this.id = id; + this.name = name; + this.fullName = fullName; + this.uriPath = uriPath; + this.description = description; + this.slug = slug; + this.isPublic = isPublic; + this.isFollowing = isFollowing; + this.memberCount = memberCount; + this.subscriberCount = subscriberCount; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getFullName() { + return fullName; + } + + public String getUriPath() { + return uriPath; + } + + public String getDescription() { + return description; + } + + public String getSlug() { + return slug; + } + + public boolean isPublic() { + return isPublic; + } + + public boolean isFollowing() { + return isFollowing; + } + + public int getMemberCount() { + return memberCount; + } + + public int getSubscriberCount() { + return subscriberCount; + } + +} diff --git a/agorava-twitter-api/src/main/java/org/agorava/twitter/model/package-info.java b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/package-info.java new file mode 100644 index 0000000..c5a06f5 --- /dev/null +++ b/agorava-twitter-api/src/main/java/org/agorava/twitter/model/package-info.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.model; + +/** + * This package contains API elements to manage interactions with Twitter thru + * CDI Beans + */ diff --git a/agorava-twitter-cdi/pom.xml b/agorava-twitter-cdi/pom.xml new file mode 100644 index 0000000..b0a09cc --- /dev/null +++ b/agorava-twitter-cdi/pom.xml @@ -0,0 +1,169 @@ + + + 4.0.0 + + agorava-twitter-parent + org.agorava + 1.0.0-SNAPSHOT + + agorava-twitter-cdi + + + + javax.enterprise + cdi-api + + + org.agorava + agorava-twitter-api + + + + org.agorava + agorava-core-cdi + + + + + + org.jboss.ejb3 + jboss-ejb3-api + 3.1.0 + test + + + + javax.validation + validation-api + 1.0.0.GA + test + + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + 1.0.1.Final + test + + + + org.glassfish.web + el-impl + 2.1.2-b04 + test + + + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + + junit + junit + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven + test + + + + + + + + weld-embedded + + true + + arquillian + weld-ee-embedded-1.1 + + + + + weld-ee-embedded-1.1 + + + + org.jboss.arquillian.container + arquillian-weld-ee-embedded-1.1 + 1.0.0.CR3 + test + + + org.jboss.weld + weld-core + 1.1.5.Final + test + + + org.slf4j + slf4j-simple + 1.6.4 + test + + + + org.jboss.solder + solder-impl + + + + + + + + + agorava-twitter-cdi + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + true + + ${arquillian} + ${arquillian} + + + + + + surefire-it + integration-test + + test + + + false + true + false + true + + + + + + + diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/Twitter.java b/agorava-twitter-cdi/src/main/java/org/agorava/Twitter.java new file mode 100644 index 0000000..20bdaad --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/Twitter.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +import org.agorava.core.api.ServiceRelated; + +@Qualifier +@ServiceRelated +@Target({ TYPE, METHOD, PARAMETER, FIELD }) +@Retention(RUNTIME) +@Documented +/** + * @author antoine + * + */ +public @interface Twitter { + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/TwitterBaseService.java b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterBaseService.java new file mode 100644 index 0000000..4db5b73 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterBaseService.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava; + +import java.lang.annotation.Annotation; + +import org.agorava.core.api.oauth.OAuthService; +import org.agorava.core.cdi.AbstractSocialNetworkService; + +/** + * A specialization of {@link OAuthService} to add TwitterRelated specific methods + * + * @author Antoine Sabot-Durand + */ + +public abstract class TwitterBaseService extends AbstractSocialNetworkService { + + static final String API_ROOT = "https://api.twitter.com/1/"; + + @Override + public Annotation getQualifier() { + return TwitterLiteral.INSTANCE; + } + + @Override + public String getApiRootUrl() { + return API_ROOT; + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/TwitterLiteral.java b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterLiteral.java new file mode 100644 index 0000000..23ca3b5 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava; + +import javax.enterprise.util.AnnotationLiteral; + +/** + * @author antoine + * + */ +public class TwitterLiteral extends AnnotationLiteral implements Twitter { + + private static final long serialVersionUID = 5431958087840055287L; + public static Twitter INSTANCE = new TwitterLiteral(); +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/TwitterServicesHub.java b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterServicesHub.java new file mode 100644 index 0000000..7ff54cd --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/TwitterServicesHub.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava; + +import java.lang.annotation.Annotation; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; + +import org.agorava.core.api.event.OAuthComplete; +import org.agorava.core.api.event.SocialEvent.Status; +import org.agorava.core.cdi.AbstractSocialNetworkServicesHub; +import org.agorava.twitter.impl.TwitterUserServiceImpl; +import org.jboss.solder.logging.Logger; + +/** + * @author Antoine Sabot-Durand + * + */ + +public class TwitterServicesHub extends AbstractSocialNetworkServicesHub { + + @Inject + Logger log; + + @Inject + Instance services; + + @Override + public Annotation getQualifier() { + return TwitterLiteral.INSTANCE; + } + + public void initMyProfile(@Observes @Twitter OAuthComplete oauthComplete) { + log.debug("**** Initializing Twitter profile ****"); + if (oauthComplete.getStatus() == Status.SUCCESS) + oauthComplete.getEventData().setUserProfile(services.select(TwitterUserServiceImpl.class).get().getUserProfile()); + + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/cdi/TwitterTimelineServiceDecorator.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/cdi/TwitterTimelineServiceDecorator.java new file mode 100644 index 0000000..43cae9e --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/cdi/TwitterTimelineServiceDecorator.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.cdi; + +import javax.decorator.Decorator; +import javax.decorator.Delegate; +import javax.enterprise.event.Event; +import javax.enterprise.inject.Any; +import javax.inject.Inject; + +import org.agorava.Twitter; +import org.agorava.core.api.event.SocialEvent.Status; +import org.agorava.core.api.event.StatusUpdated; +import org.agorava.twitter.TwitterTimelineService; +import org.agorava.twitter.model.Tweet; + +@Decorator +/** + * + * @author Antoine Sabot-Durand + * + */ +public abstract class TwitterTimelineServiceDecorator implements TwitterTimelineService { + + /** + * + */ + @Inject + @Delegate + @Any + private TwitterTimelineService delegate; + + @Inject + @Twitter + private Event statusUpdateEventProducer; + + @Override + public Tweet updateStatus(String status) { + Tweet res = delegate.updateStatus(status); + statusUpdateEventProducer.fire(new StatusUpdated(Status.SUCCESS, status, res)); + return res; + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/CursoredLongList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/CursoredLongList.java new file mode 100644 index 0000000..968beb9 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/CursoredLongList.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import java.util.List; + +import org.agorava.twitter.model.CursoredList; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonIgnoreType; +import org.codehaus.jackson.annotate.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonIgnoreType +public class CursoredLongList { + + private final CursoredList list; + + @JsonCreator + public CursoredLongList(@JsonProperty("ids") List collection, @JsonProperty("previous_cursor") long previousCursor, + @JsonProperty("next_cursor") long nextCursor) { + list = new CursoredList(collection, previousCursor, nextCursor); + } + + @JsonIgnore + public CursoredList getList() { + return list; + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterBlockServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterBlockServiceImpl.java new file mode 100644 index 0000000..5982243 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterBlockServiceImpl.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import static com.google.common.collect.Maps.newHashMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.agorava.TwitterBaseService; +import org.agorava.core.cdi.utils.URLUtils; +import org.agorava.twitter.TwitterBlockService; +import org.agorava.twitter.impl.TwitterUserServiceImpl.TwitterProfileList; +import org.agorava.twitter.model.TwitterProfile; + +/** + * @author Antoine Sabot-Durand + * @author Craig Walls + * + */ +public class TwitterBlockServiceImpl extends TwitterBaseService implements TwitterBlockService { + + @SuppressWarnings("serial") + private static class LongList extends ArrayList { + } + + @Override + public TwitterProfile block(long userId) { + Map request = newHashMap(); + request.put("user_id", String.valueOf(userId)); + return getService().postForObject(buildUri("blocks/create.json"), request, TwitterProfile.class); + } + + @Override + public TwitterProfile block(String screenName) { + Map request = newHashMap(); + request.put("screen_name", screenName); + return getService().postForObject(buildUri("blocks/create.json"), request, TwitterProfile.class); + } + + @Override + public TwitterProfile unblock(long userId) { + Map request = newHashMap(); + request.put("user_id", String.valueOf(userId)); + return getService().postForObject(buildUri("blocks/destroy.json"), request, TwitterProfile.class); + } + + @Override + public TwitterProfile unblock(String screenName) { + Map request = newHashMap(); + request.put("screen_name", screenName); + return getService().postForObject(buildUri("blocks/destroy.json"), request, TwitterProfile.class); + } + + @Override + public List getBlockedUsers() { + return getBlockedUsers(1, 20); + } + + @Override + public List getBlockedUsers(int page, int pageSize) { + Map parameters = URLUtils.buildPagingParametersWithPerPage(page, pageSize, 0, 0); + return getService().getForObject(buildUri("blocks/blocking.json", parameters), TwitterProfileList.class); + } + + @Override + public List getBlockedUserIds() { + return getService().getForObject(buildUri("blocks/blocking/ids.json"), LongList.class); + } + + @Override + public boolean isBlocking(long userId) { + return isBlocking(buildUri("blocks/exists.json", "user_id", String.valueOf(userId))); + } + + @Override + public boolean isBlocking(String screenName) { + return isBlocking(buildUri("blocks/exists.json", "screen_name", screenName)); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterDirectMessageServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterDirectMessageServiceImpl.java new file mode 100644 index 0000000..50f5e47 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterDirectMessageServiceImpl.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import static com.google.common.collect.Maps.newHashMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.agorava.TwitterBaseService; +import org.agorava.core.cdi.utils.URLUtils; +import org.agorava.twitter.TwitterDirectMessageService; +import org.agorava.twitter.model.DirectMessage; + +/** + * @author Antoine Sabot-Durand + * + */ +public class TwitterDirectMessageServiceImpl extends TwitterBaseService implements TwitterDirectMessageService { + + @SuppressWarnings("serial") + class DirectMessageList extends ArrayList { + } + + @Override + public List getDirectMessagesReceived() { + return getDirectMessagesReceived(1, 20, 0, 0); + } + + @Override + public List getDirectMessagesReceived(int page, int pageSize) { + return getDirectMessagesReceived(page, pageSize, 0, 0); + } + + @Override + public List getDirectMessagesReceived(int page, int pageSize, long sinceId, long maxId) { + + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("direct_messages.json", parameters), DirectMessageList.class); + } + + @Override + public List getDirectMessagesSent() { + return getDirectMessagesSent(1, 20, 0, 0); + } + + @Override + public List getDirectMessagesSent(int page, int pageSize) { + return getDirectMessagesSent(page, pageSize, 0, 0); + } + + @Override + public List getDirectMessagesSent(int page, int pageSize, long sinceId, long maxId) { + + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("direct_messages/sent.json", parameters), DirectMessageList.class); + } + + @Override + public DirectMessage getDirectMessage(long id) { + + return getService().getForObject(buildUri("direct_messages/show/" + id + ".json"), DirectMessage.class); + } + + @Override + public DirectMessage sendDirectMessage(String toScreenName, String text) { + + Map data = newHashMap(); + data.put("screen_name", String.valueOf(toScreenName)); + data.put("text", text); + return getService().postForObject(buildUri("direct_messages/new.json"), data, DirectMessage.class); + } + + @Override + public DirectMessage sendDirectMessage(long toUserId, String text) { + + Map data = newHashMap(); + data.put("user_id", String.valueOf(toUserId)); + data.put("text", text); + return getService().postForObject(buildUri("direct_messages/new.json"), data, DirectMessage.class); + } + + @Override + public void deleteDirectMessage(long messageId) { + + getService().delete(buildUri("direct_messages/destroy/" + messageId + ".json")); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterFriendServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterFriendServiceImpl.java new file mode 100644 index 0000000..84a6ce1 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterFriendServiceImpl.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import static com.google.common.collect.Maps.newHashMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.agorava.TwitterBaseService; +import org.agorava.core.cdi.utils.URLUtils; +import org.agorava.twitter.impl.TwitterUserServiceImpl.TwitterProfileList; +import org.agorava.twitter.model.CursoredList; +import org.agorava.twitter.model.TwitterProfile; + +/** + * @author Antoine Sabot-Durand + * @author Craig Walls + * + */ +public class TwitterFriendServiceImpl extends TwitterBaseService implements org.agorava.twitter.TwitterFriendService { + + @Override + public CursoredList getFriends() { + return getFriendsInCursor(-1); + } + + @Override + public CursoredList getFriendsInCursor(long cursor) { + CursoredList friendIds = getFriendIdsInCursor(cursor); + return getCursoredProfileList(friendIds, friendIds.getPreviousCursor(), friendIds.getNextCursor()); + } + + @Override + public CursoredList getFriends(long userId) { + return getFriendsInCursor(userId, -1); + } + + @Override + public CursoredList getFriendsInCursor(long userId, long cursor) { + CursoredList friendIds = getFriendIdsInCursor(userId, cursor); + return getCursoredProfileList(friendIds, friendIds.getPreviousCursor(), friendIds.getNextCursor()); + } + + @Override + public CursoredList getFriends(String screenName) { + return getFriendsInCursor(screenName, -1); + } + + @Override + public CursoredList getFriendsInCursor(String screenName, long cursor) { + CursoredList friendIds = getFriendIdsInCursor(screenName, cursor); + return getCursoredProfileList(friendIds, friendIds.getPreviousCursor(), friendIds.getNextCursor()); + } + + @Override + public CursoredList getFriendIds() { + return getFriendIdsInCursor(-1); + } + + @Override + public CursoredList getFriendIdsInCursor(long cursor) { + + return getService() + .getForObject(buildUri("friends/ids.json", "cursor", String.valueOf(cursor)), CursoredLongList.class).getList(); + } + + @Override + public CursoredList getFriendIds(long userId) { + return getFriendIdsInCursor(userId, -1); + } + + @Override + public CursoredList getFriendIdsInCursor(long userId, long cursor) { + Map parameters = newHashMap(); + parameters.put("cursor", String.valueOf(cursor)); + parameters.put("user_id", String.valueOf(userId)); + return getService().getForObject(buildUri("friends/ids.json", parameters), CursoredLongList.class).getList(); + } + + @Override + public CursoredList getFriendIds(String screenName) { + return getFriendIdsInCursor(screenName, -1); + } + + @Override + public CursoredList getFriendIdsInCursor(String screenName, long cursor) { + Map parameters = newHashMap(); + parameters.put("cursor", String.valueOf(cursor)); + parameters.put("screen_name", screenName); + return getService().getForObject(buildUri("friends/ids.json", parameters), CursoredLongList.class).getList(); + } + + @Override + public CursoredList getFollowers() { + return getFollowersInCursor(-1); + } + + @Override + public CursoredList getFollowersInCursor(long cursor) { + CursoredList followerIds = getFollowerIdsInCursor(cursor); + return getCursoredProfileList(followerIds, followerIds.getPreviousCursor(), followerIds.getNextCursor()); + } + + @Override + public CursoredList getFollowers(long userId) { + return getFollowersInCursor(userId, -1); + } + + @Override + public CursoredList getFollowersInCursor(long userId, long cursor) { + CursoredList followerIds = getFollowerIdsInCursor(userId, cursor); + return getCursoredProfileList(followerIds, followerIds.getPreviousCursor(), followerIds.getNextCursor()); + } + + @Override + public CursoredList getFollowers(String screenName) { + return getFollowersInCursor(screenName, -1); + } + + @Override + public CursoredList getFollowersInCursor(String screenName, long cursor) { + CursoredList followerIds = getFollowerIdsInCursor(screenName, cursor); + return getCursoredProfileList(followerIds, followerIds.getPreviousCursor(), followerIds.getNextCursor()); + } + + @Override + public CursoredList getFollowerIds() { + return getFollowerIdsInCursor(-1); + } + + @Override + public CursoredList getFollowerIdsInCursor(long cursor) { + + return getService().getForObject(buildUri("followers/ids.json", "cursor", String.valueOf(cursor)), + CursoredLongList.class).getList(); + } + + @Override + public CursoredList getFollowerIds(long userId) { + return getFollowerIdsInCursor(userId, -1); + } + + @Override + public CursoredList getFollowerIdsInCursor(long userId, long cursor) { + Map parameters = newHashMap(); + parameters.put("cursor", String.valueOf(cursor)); + parameters.put("user_id", String.valueOf(userId)); + return getService().getForObject(buildUri("followers/ids.json", parameters), CursoredLongList.class).getList(); + } + + @Override + public CursoredList getFollowerIds(String screenName) { + return getFollowerIdsInCursor(screenName, -1); + } + + @Override + public CursoredList getFollowerIdsInCursor(String screenName, long cursor) { + Map parameters = newHashMap(); + parameters.put("cursor", String.valueOf(cursor)); + parameters.put("screen_name", screenName); + return getService().getForObject(buildUri("followers/ids.json", parameters), CursoredLongList.class).getList(); + } + + @Override + public String follow(long userId) { + + return (String) getService().postForObject(buildUri("friendships/create.json", "user_id", String.valueOf(userId)), + EMPTY_DATA, Map.class).get("screen_name"); + } + + @Override + public String follow(String screenName) { + + return (String) getService().postForObject(buildUri("friendships/create.json", "screen_name", screenName), EMPTY_DATA, + Map.class).get("screen_name"); + } + + @Override + public String unfollow(long userId) { + + return (String) getService().postForObject(buildUri("friendships/destroy.json", "user_id", String.valueOf(userId)), + EMPTY_DATA, Map.class).get("screen_name"); + } + + @Override + public String unfollow(String screenName) { + + return (String) getService().postForObject(buildUri("friendships/destroy.json", "screen_name", screenName), EMPTY_DATA, + Map.class).get("screen_name"); + } + + @Override + public TwitterProfile enableNotifications(long userId) { + + return getService().postForObject(buildUri("notifications/follow.json", "user_id", String.valueOf(userId)), EMPTY_DATA, + TwitterProfile.class); + } + + @Override + public TwitterProfile enableNotifications(String screenName) { + + return getService().postForObject(buildUri("notifications/follow.json", "screen_name", screenName), EMPTY_DATA, + TwitterProfile.class); + } + + @Override + public TwitterProfile disableNotifications(long userId) { + + return getService().postForObject(buildUri("notifications/leave.json", "user_id", String.valueOf(userId)), EMPTY_DATA, + TwitterProfile.class); + } + + @Override + public TwitterProfile disableNotifications(String screenName) { + + return getService().postForObject(buildUri("notifications/leave.json", "screen_name", screenName), EMPTY_DATA, + TwitterProfile.class); + } + + // doesn't require authentication + @Override + public boolean friendshipExists(String userA, String userB) { + Map params = newHashMap(); + return getService().getForObject(buildUri("friendships/exists.json", params), boolean.class); + } + + @Override + public CursoredList getIncomingFriendships() { + return getIncomingFriendships(-1); + } + + @Override + public CursoredList getIncomingFriendships(long cursor) { + + return getService().getForObject(buildUri("friendships/incoming.json", "cursor", String.valueOf(cursor)), + CursoredLongList.class).getList(); + } + + @Override + public CursoredList getOutgoingFriendships() { + return getOutgoingFriendships(-1); + } + + @Override + public CursoredList getOutgoingFriendships(long cursor) { + + return getService().getForObject(buildUri("friendships/outgoing.json", "cursor", String.valueOf(cursor)), + CursoredLongList.class).getList(); + } + + private CursoredList getCursoredProfileList(List userIds, long previousCursor, long nextCursor) { + // TODO: Would be good to figure out how to retrieve profiles in a tighter-than-cursor granularity. + List> chunks = chunkList(userIds, 100); + CursoredList users = new CursoredList(userIds.size(), previousCursor, nextCursor); + for (List userIdChunk : chunks) { + String joinedIds = URLUtils.commaJoiner.join(userIdChunk); + users.addAll(getService().getForObject(buildUri("users/lookup.json", "user_id", joinedIds), + TwitterProfileList.class)); + } + return users; + } + + private List> chunkList(List list, int chunkSize) { + List> chunkedList = new ArrayList>(); + int start = 0; + while (start < list.size()) { + int end = Math.min(chunkSize + start, list.size()); + chunkedList.add(list.subList(start, end)); + start = end; + } + return chunkedList; + } + + private static final Map EMPTY_DATA = newHashMap(); + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterGeoServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterGeoServiceImpl.java new file mode 100644 index 0000000..e1edca0 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterGeoServiceImpl.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import static com.google.common.collect.Maps.newHashMap; + +import java.util.List; +import java.util.Map; + +import org.agorava.TwitterBaseService; +import org.agorava.twitter.TwitterGeoService; +import org.agorava.twitter.jackson.PlacesList; +import org.agorava.twitter.model.Place; +import org.agorava.twitter.model.PlacePrototype; +import org.agorava.twitter.model.PlaceType; +import org.agorava.twitter.model.SimilarPlaces; +import org.agorava.twitter.model.SimilarPlacesResponse; + +/** + * @author Antoine Sabot-Durand + * @author Craig Walls + * + */ +public class TwitterGeoServiceImpl extends TwitterBaseService implements TwitterGeoService { + + @Override + public Place getPlace(String placeId) { + return getService().getForObject(buildUri("geo/id/" + placeId + ".json"), Place.class); + } + + @Override + public List reverseGeoCode(double latitude, double longitude) { + return reverseGeoCode(latitude, longitude, null, null); + } + + @Override + public List reverseGeoCode(double latitude, double longitude, PlaceType granularity, String accuracy) { + Map parameters = buildGeoParameters(latitude, longitude, granularity, accuracy, null); + return getService().getForObject(buildUri("geo/reverse_geocode.json", parameters), PlacesList.class).getList(); + } + + @Override + public List search(double latitude, double longitude) { + return search(latitude, longitude, null, null, null); + } + + @Override + public List search(double latitude, double longitude, PlaceType granularity, String accuracy, String query) { + Map parameters = buildGeoParameters(latitude, longitude, granularity, accuracy, query); + return getService().getForObject(buildUri("geo/search.json", parameters), PlacesList.class).getList(); + } + + @Override + public SimilarPlaces findSimilarPlaces(double latitude, double longitude, String name) { + return findSimilarPlaces(latitude, longitude, name, null, null); + } + + @Override + public SimilarPlaces findSimilarPlaces(double latitude, double longitude, String name, String streetAddress, + String containedWithin) { + Map parameters = buildPlaceParameters(latitude, longitude, name, streetAddress, containedWithin); + SimilarPlacesResponse response = getService().getForObject(buildUri("geo/similar_places.json", parameters), + SimilarPlacesResponse.class); + PlacePrototype placePrototype = new PlacePrototype(response.getToken(), latitude, longitude, name, streetAddress, + containedWithin); + + return new SimilarPlaces(response.getPlaces(), placePrototype); + } + + @Override + public Place createPlace(PlacePrototype placePrototype) { + Map request = buildPlaceParameters(placePrototype.getLatitude(), placePrototype.getLongitude(), + placePrototype.getName(), placePrototype.getStreetAddress(), placePrototype.getContainedWithin()); + request.put("token", placePrototype.getCreateToken()); + return getService().postForObject("https://api.twitter.com/1/geo/place.json", request, Place.class); + } + + // private helpers + + private Map buildGeoParameters(double latitude, double longitude, PlaceType granularity, String accuracy, + String query) { + Map parameters = newHashMap(); + parameters.put("lat", String.valueOf(latitude)); + parameters.put("long", String.valueOf(longitude)); + if (granularity != null) { + parameters.put("granularity", granularity.equals(PlaceType.POINT_OF_INTEREST) ? "poi" : granularity.toString() + .toLowerCase()); + } + if (accuracy != null) { + parameters.put("accuracy", accuracy); + } + if (query != null) { + parameters.put("query", query); + } + return parameters; + } + + private Map buildPlaceParameters(double latitude, double longitude, String name, String streetAddress, + String containedWithin) { + Map parameters = newHashMap(); + parameters.put("lat", String.valueOf(latitude)); + parameters.put("long", String.valueOf(longitude)); + parameters.put("name", name); + if (streetAddress != null) { + parameters.put("attribute:street_address", streetAddress); + } + if (containedWithin != null) { + parameters.put("contained_within", containedWithin); + } + return parameters; + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterTimelineServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterTimelineServiceImpl.java new file mode 100644 index 0000000..dcdfce2 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterTimelineServiceImpl.java @@ -0,0 +1,365 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import static com.google.common.collect.Maps.newHashMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Named; + +import org.agorava.TwitterBaseService; +import org.agorava.core.cdi.utils.URLUtils; +import org.agorava.twitter.TwitterTimelineService; +import org.agorava.twitter.impl.TwitterUserServiceImpl.TwitterProfileList; +import org.agorava.twitter.model.StatusDetails; +import org.agorava.twitter.model.Tweet; +import org.agorava.twitter.model.TwitterProfile; + +/** + * @author Antoine Sabot-Durand + * @author Craig Walls + * + */ +@Named +public class TwitterTimelineServiceImpl extends TwitterBaseService implements TwitterTimelineService { + + private static final String USER_TIMELINE_URL = "statuses/user_timeline.json"; + private static final String HOME_TIMELINE_URL = "statuses/home_timeline.json"; + private static final String PUBLIC_TIMELINE_URL = "statuses/public_timeline.json"; + + @Override + public List getPublicTimeline() { + return getService().getForObject(buildUri(PUBLIC_TIMELINE_URL), TweetList.class); + } + + @Override + public List getHomeTimeline() { + return getHomeTimeline(1, 20, 0, 0); + } + + @Override + public List getHomeTimeline(int page, int pageSize) { + return getHomeTimeline(page, pageSize, 0, 0); + } + + @Override + public List getHomeTimeline(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri(HOME_TIMELINE_URL, parameters), TweetList.class); + } + + @Override + public List getUserTimeline() { + return getUserTimeline(1, 20, 0, 0); + } + + @Override + public List getUserTimeline(int page, int pageSize) { + return getUserTimeline(page, pageSize, 0, 0); + } + + @Override + public List getUserTimeline(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri(USER_TIMELINE_URL, parameters), TweetList.class); + } + + @Override + public List getUserTimeline(String screenName) { + return getUserTimeline(screenName, 1, 20, 0, 0); + } + + @Override + public List getUserTimeline(String screenName, int page, int pageSize) { + return getUserTimeline(screenName, page, pageSize, 0, 0); + } + + @Override + public List getUserTimeline(String screenName, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("screen_name", screenName); + return getService().getForObject(buildUri(USER_TIMELINE_URL, parameters), TweetList.class); + } + + @Override + public List getUserTimeline(long userId) { + return getUserTimeline(userId, 1, 20, 0, 0); + } + + @Override + public List getUserTimeline(long userId, int page, int pageSize) { + return getUserTimeline(userId, page, pageSize, 0, 0); + } + + @Override + public List getUserTimeline(long userId, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("user_id", String.valueOf(userId)); + return getService().getForObject(buildUri(USER_TIMELINE_URL, parameters), TweetList.class); + } + + @Override + public List getMentions() { + return getMentions(1, 20, 0, 0); + } + + @Override + public List getMentions(int page, int pageSize) { + return getMentions(page, pageSize, 0, 0); + } + + @Override + public List getMentions(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("statuses/mentions.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedByMe() { + return getRetweetedByMe(1, 20, 0, 0); + } + + @Override + public List getRetweetedByMe(int page, int pageSize) { + return getRetweetedByMe(page, pageSize, 0, 0); + } + + @Override + public List getRetweetedByMe(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("statuses/retweeted_by_me.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedByUser(long userId) { + return getRetweetedByUser(userId, 1, 20, 0, 0); + } + + @Override + public List getRetweetedByUser(long userId, int page, int pageSize) { + return getRetweetedByUser(userId, page, pageSize, 0, 0); + } + + @Override + public List getRetweetedByUser(long userId, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("user_id", String.valueOf(userId)); + return getService().getForObject(buildUri("statuses/retweeted_by_user.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedByUser(String screenName) { + return getRetweetedByUser(screenName, 1, 20, 0, 0); + } + + @Override + public List getRetweetedByUser(String screenName, int page, int pageSize) { + return getRetweetedByUser(screenName, page, pageSize, 0, 0); + } + + @Override + public List getRetweetedByUser(String screenName, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("screen_name", screenName); + return getService().getForObject(buildUri("statuses/retweeted_by_user.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedToMe() { + return getRetweetedToMe(1, 20, 0, 0); + } + + @Override + public List getRetweetedToMe(int page, int pageSize) { + return getRetweetedToMe(page, pageSize, 0, 0); + } + + @Override + public List getRetweetedToMe(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("statuses/retweeted_to_me.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedToUser(long userId) { + return getRetweetedToUser(userId, 1, 20, 0, 0); + } + + @Override + public List getRetweetedToUser(long userId, int page, int pageSize) { + return getRetweetedToUser(userId, page, pageSize, 0, 0); + } + + @Override + public List getRetweetedToUser(long userId, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("user_id", String.valueOf(userId)); + return getService().getForObject(buildUri("statuses/retweeted_to_user.json", parameters), TweetList.class); + } + + @Override + public List getRetweetedToUser(String screenName) { + return getRetweetedToUser(screenName, 1, 20, 0, 0); + } + + @Override + public List getRetweetedToUser(String screenName, int page, int pageSize) { + return getRetweetedToUser(screenName, page, pageSize, 0, 0); + } + + @Override + public List getRetweetedToUser(String screenName, int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + parameters.put("screen_name", screenName); + return getService().getForObject(buildUri("statuses/retweeted_to_user.json", parameters), TweetList.class); + } + + @Override + public List getRetweetsOfMe() { + return getRetweetsOfMe(1, 20, 0, 0); + } + + @Override + public List getRetweetsOfMe(int page, int pageSize) { + return getRetweetsOfMe(page, pageSize, 0, 0); + } + + @Override + public List getRetweetsOfMe(int page, int pageSize, long sinceId, long maxId) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, sinceId, maxId); + return getService().getForObject(buildUri("statuses/retweets_of_me.json", parameters), TweetList.class); + } + + @Override + public Tweet getStatus(long tweetId) { + return getService().getForObject(buildUri("statuses/show/" + tweetId + ".json"), Tweet.class); + } + + @Override + public Tweet updateStatus(String message) { + return updateStatus(message, new StatusDetails()); + } + + // public Tweet updateStatus(String message, Resource media) { + // return updateStatus(message, media, new StatusDetails()); + // } + + public Tweet updateStatus(String message, StatusDetails details) { + Map tweetParams = newHashMap(); + tweetParams.put("status", message); + tweetParams.putAll(details.toParameterMap()); + return getService().postForObject(buildUri("statuses/update.json"), tweetParams, Tweet.class); + } + + // public Tweet updateStatus(String message, Resource media, StatusDetails details) { + // + // Multimap tweetParams = LinkedHashMultimap.create(); + // tweetParams.add("status", message); + // tweetParams.add("media", media); + // tweetParams.putAll(details.toParameterMap()); + // return restTemplate.getService().postForObject("https://upload.twitter.com/1/statuses/update_with_media.json", + // tweetParams, + // Tweet.class); + // } + + @Override + public void deleteStatus(long tweetId) { + getService().delete(buildUri("statuses/destroy/" + tweetId + ".json")); + } + + @Override + public void retweet(long tweetId) { + Map data = newHashMap(); + getService().postForObject(buildUri("statuses/retweet/" + tweetId + ".json"), data, String.class); + } + + @Override + public List getRetweets(long tweetId) { + return getRetweets(tweetId, 100); + } + + @Override + public List getRetweets(long tweetId, int count) { + Map parameters = newHashMap(); + parameters.put("count", String.valueOf(count)); + return getService().getForObject(buildUri("statuses/retweets/" + tweetId + ".json", parameters), TweetList.class); + } + + @Override + public List getRetweetedBy(long tweetId) { + return getRetweetedBy(tweetId, 1, 100); + } + + @Override + public List getRetweetedBy(long tweetId, int page, int pageSize) { + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, 0, 0); + return getService().getForObject(buildUri("statuses/" + tweetId + "/retweeted_by.json", parameters), + TwitterProfileList.class); + } + + @Override + public List getRetweetedByIds(long tweetId) { + return getRetweetedByIds(tweetId, 1, 100); + } + + @Override + public List getRetweetedByIds(long tweetId, int page, int pageSize) { + // requires authentication, even though getRetweetedBy() does not. + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, 0, 0); + return getService() + .getForObject(buildUri("statuses/" + tweetId + "/retweeted_by/ids.json", parameters), LongList.class); + } + + @Override + public List getFavorites() { + return getFavorites(1, 20); + } + + @Override + public List getFavorites(int page, int pageSize) { + // Note: The documentation for favorites.json doesn't list the count parameter, but it works + // anyway. + Map parameters = URLUtils.buildPagingParametersWithCount(page, pageSize, 0, 0); + return getService().getForObject(buildUri("favorites.json", parameters), TweetList.class); + } + + @Override + public void addToFavorites(long tweetId) { + Map data = newHashMap(); + getService().postForObject(buildUri("favorites/create/" + tweetId + ".json"), data, String.class); + } + + @Override + public void removeFromFavorites(long tweetId) { + Map data = newHashMap(); + getService().postForObject(buildUri("favorites/destroy/" + tweetId + ".json"), data, String.class); + } + + @SuppressWarnings("serial") + private static class LongList extends ArrayList { + } + + @SuppressWarnings("serial") + private static class TweetList extends ArrayList { + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterUserServiceImpl.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterUserServiceImpl.java new file mode 100644 index 0000000..6b1fc29 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/impl/TwitterUserServiceImpl.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.agorava.TwitterBaseService; +import org.agorava.core.cdi.utils.URLUtils; +import org.agorava.twitter.TwitterUserService; +import org.agorava.twitter.model.ImageSize; +import org.agorava.twitter.model.RateLimitStatus; +import org.agorava.twitter.model.SuggestionCategory; +import org.agorava.twitter.model.TwitterProfile; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * @author Antoine Sabot-Durand + * + */ +public class TwitterUserServiceImpl extends TwitterBaseService implements TwitterUserService { + + /** + * Typed list of TwitterProfile. This helps Jackson know which type to deserialize list contents into. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ + @SuppressWarnings("serial") + static class TwitterProfileList extends ArrayList { + } + + @SuppressWarnings("serial") + static class SuggestionCategoryList extends ArrayList { + } + + @JsonIgnoreProperties(ignoreUnknown = true) + static class TwitterProfileUsersList { + + private final List list; + + @JsonCreator + public TwitterProfileUsersList(@JsonProperty("users") List list) { + this.list = list; + } + + public List getList() { + return list; + } + } + + static final String VERIFY_CREDENTIALS_URL = "account/verify_credentials.json"; + + static final String GET_USER_PROFILE_URL = "users/show.json"; + static final String SEARCH_USER_URL = "users/search.json"; + static final String SUGGESTION_CATEGORIES = "users/suggestions.json"; + static final String LOOKUP = "users/lookup.json"; + static final String RATE_LIMIT_STATUS = "account/rate_limit_status.json"; + + @Override + public String getProfileId() { + return getSession().getUserProfile().getId(); + } + + @Override + public String getScreenName() { + return getSession().getUserProfile().getFullName(); + } + + @Override + public TwitterProfile getUserProfile(String screenName) { + return getService().getForObject(buildUri(GET_USER_PROFILE_URL, "screen_name", screenName), TwitterProfile.class); + } + + @Override + public TwitterProfile getUserProfile(long userId) { + return getService().getForObject(buildUri(GET_USER_PROFILE_URL, "user_id", String.valueOf(userId)), + TwitterProfile.class); + } + + @Override + public byte[] getUserProfileImage(String screenName) { + return getUserProfileImage(screenName, ImageSize.NORMAL); + } + + @Override + public byte[] getUserProfileImage(String screenName, ImageSize size) { + throw new UnsupportedOperationException("Not supported yet"); + } + + @Override + public List getUsers(String... userIds) { + String joinedIds = URLUtils.commaJoiner.join(userIds); + return getService().getForObject(buildUri(LOOKUP, "user_id", joinedIds), TwitterProfileList.class); + } + + @Override + public List getUsersByName(String... screenNames) { + String joinedScreenNames = URLUtils.commaJoiner.join(screenNames); + return getService().getForObject(buildUri(LOOKUP, "screen_name", joinedScreenNames), TwitterProfileList.class); + } + + @Override + public List searchForUsers(String query) { + return searchForUsers(query, 1, 20); + } + + @Override + public List searchForUsers(String query, int page, int pageSize) { + Map parameters = URLUtils.buildPagingParametersWithPerPage(page, pageSize, 0, 0); + parameters.put("q", query); + return getService().getForObject(buildUri(SEARCH_USER_URL, parameters), TwitterProfileList.class); + } + + @Override + public List getSuggestionCategories() { + return getService().getForObject(buildUri(SUGGESTION_CATEGORIES), SuggestionCategoryList.class); + } + + @Override + public List getSuggestions(String slug) { + return getService().getForObject(buildUri("users/suggestions/" + slug + ".json"), TwitterProfileUsersList.class) + .getList(); + } + + @Override + public RateLimitStatus getRateLimitStatus() { + return getService().getForObject(buildUri(RATE_LIMIT_STATUS), RateLimitStatus.class); + } + + @Override + public TwitterProfile getUserProfile() { + return getService().getForObject(buildUri(VERIFY_CREDENTIALS_URL), TwitterProfile.class); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/AbstractTrendsList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/AbstractTrendsList.java new file mode 100644 index 0000000..c275b13 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/AbstractTrendsList.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.text.DateFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.agorava.twitter.model.Trend; +import org.agorava.twitter.model.Trends; + + +/** + * Abstract model class representing a list of trends. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +class AbstractTrendsList { + private final List list; + + public AbstractTrendsList(Map> trends, DateFormat dateFormat) { + list = new ArrayList(trends.size()); + for (Iterator>> trendsIt = trends.entrySet().iterator(); trendsIt.hasNext();) { + Entry> entry = trendsIt.next(); + + list.add(new Trends(toDate(entry.getKey(), dateFormat), entry.getValue())); + } + Collections.sort(list, new Comparator() { + public int compare(Trends t1, Trends t2) { + return t1.getTime().getTime() > t2.getTime().getTime() ? -1 : 1; + } + }); + } + + public List getList() { + return list; + } + + protected Date toDate(String dateString, DateFormat dateFormat) { + if (dateString == null) { + return null; + } + + try { + return dateFormat.parse(dateString); + } catch (ParseException e) { + return null; + } + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DailyTrendsList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DailyTrendsList.java new file mode 100644 index 0000000..892ab37 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DailyTrendsList.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Map; + +import org.agorava.twitter.model.Trend; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Holder of a list of daily trends. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class DailyTrendsList extends AbstractTrendsList { + + @JsonCreator + public DailyTrendsList(@JsonProperty("trends") Map> trends) { + super(trends, new SimpleDateFormat("yyyy-MM-dd HH:mm")); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DirectMessageMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DirectMessageMixin.java new file mode 100644 index 0000000..9c9c7bd --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/DirectMessageMixin.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.Date; + +import org.agorava.twitter.model.TwitterProfile; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to DirectMessage. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +abstract class DirectMessageMixin { + @JsonCreator + DirectMessageMixin(@JsonProperty("id") long id, @JsonProperty("text") String text, + @JsonProperty("sender") TwitterProfile sender, @JsonProperty("recipient") TwitterProfile receipient, + @JsonProperty("created_at") @JsonDeserialize(using = TimelineDateDeserializer.class) Date createdAt) { + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsDeserializer.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsDeserializer.java new file mode 100644 index 0000000..cbb5efd --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsDeserializer.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.agorava.twitter.model.Trend; +import org.agorava.twitter.model.Trends; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +/** + * Deserializer to read local trends data into a LocalTrendsHolder object. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +class LocalTrendsDeserializer extends JsonDeserializer { + + @Override + public LocalTrendsHolder deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, + JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Iterator dayIt = tree.iterator(); + if (dayIt.hasNext()) { + JsonNode day = dayIt.next(); + Date createdAt = toDate(day.get("created_at").asText()); + JsonNode trendNodes = day.get("trends"); + List trends = new ArrayList(); + for (Iterator trendsIt = trendNodes.iterator(); trendsIt.hasNext();) { + JsonNode trendNode = trendsIt.next(); + trends.add(new Trend(trendNode.get("name").asText(), trendNode.get("query").getTextValue())); + } + jp.skipChildren(); + return new LocalTrendsHolder(new Trends(createdAt, trends)); + } + + throw ctxt.mappingException(LocalTrendsHolder.class); + } + + private static final String LOCAL_TREND_DATE_FORMAT = "yyyy-mm-dd'T'HH:mm:ss'Z'"; + + private static Date toDate(String dateString) { + try { + return new SimpleDateFormat(LOCAL_TREND_DATE_FORMAT).parse(dateString); + } catch (ParseException e) { + return null; + } + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsHolder.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsHolder.java new file mode 100644 index 0000000..99f1619 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/LocalTrendsHolder.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.agorava.twitter.model.Trends; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Holds a Trends object deserialized from Twitter's local trends JSON structure. Provides a convenient place to hang the @JsonDeserialize + * annotation. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonDeserialize(using = LocalTrendsDeserializer.class) +class LocalTrendsHolder { + + private final Trends trends; + + public LocalTrendsHolder(Trends trends) { + this.trends = trends; + } + + public Trends getTrends() { + return trends; + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceMixin.java new file mode 100644 index 0000000..f980e15 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceMixin.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; + +import org.agorava.twitter.model.PlaceType; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +@JsonIgnoreProperties(ignoreUnknown = true) +class PlaceMixin { + + @JsonCreator + public PlaceMixin(@JsonProperty("id") String id, @JsonProperty("name") String name, + @JsonProperty("full_name") String fullName, + @JsonProperty("attributes") @JsonDeserialize(using = StreetAddressDeserializer.class) String streetAddress, + @JsonProperty("country") String country, @JsonProperty("country_code") String countryCode, + @JsonProperty("place_type") @JsonDeserialize(using = PlaceTypeDeserializer.class) PlaceType placeType) { + } + + private static class StreetAddressDeserializer extends JsonDeserializer { + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + return tree.has("street_address") ? tree.get("street_address").asText() : null; + } + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceTypeDeserializer.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceTypeDeserializer.java new file mode 100644 index 0000000..c4affac --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlaceTypeDeserializer.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; + +import org.agorava.twitter.model.PlaceType; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +class PlaceTypeDeserializer extends JsonDeserializer { + + @Override + public PlaceType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + String placeTypeText = jp.getText().toUpperCase(); + if (placeTypeText.equals("POI")) { + return PlaceType.POINT_OF_INTEREST; + } + return PlaceType.valueOf(jp.getText().toUpperCase()); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlacesList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlacesList.java new file mode 100644 index 0000000..3b2443f --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/PlacesList.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; +import java.util.List; + +import org.agorava.twitter.model.Place; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.type.TypeReference; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PlacesList { + + private final List list; + + @JsonCreator + public PlacesList(@JsonProperty("result") @JsonDeserialize(using = PlacesDeserializer.class) List list) { + this.list = list; + } + + public List getList() { + return list; + } + + private static class PlacesDeserializer extends JsonDeserializer> { + @SuppressWarnings("unchecked") + @Override + public List deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setDeserializationConfig(ctxt.getConfig()); + jp.setCodec(mapper); + + JsonNode dataNode = jp.readValueAsTree().get("places"); + return (List) mapper.readValue(dataNode, new TypeReference>() { + }); + } + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/RateLimitStatusMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/RateLimitStatusMixin.java new file mode 100644 index 0000000..b7f8f88 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/RateLimitStatusMixin.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Mixin class for adding Jackson annotations to RateLimitStatus. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class RateLimitStatusMixin { + + @JsonCreator + RateLimitStatusMixin(@JsonProperty("hourly_limit") int hourlyLimit, @JsonProperty("remaining_hits") int remainingHits, + @JsonProperty("reset_time_in_seconds") long resetTimeInSeconds) { + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SavedSearchMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SavedSearchMixin.java new file mode 100644 index 0000000..a82747d --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SavedSearchMixin.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.Date; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to SavedSearch. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +abstract class SavedSearchMixin { + @JsonCreator + SavedSearchMixin(@JsonProperty("id") long id, @JsonProperty("name") String name, @JsonProperty("query") String query, + @JsonProperty("position") int position, + @JsonProperty("created_at") @JsonDeserialize(using = TimelineDateDeserializer.class) Date createdAt) { + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SearchResultsMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SearchResultsMixin.java new file mode 100644 index 0000000..19c8b71 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SearchResultsMixin.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.List; + +import org.agorava.twitter.model.Tweet; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Mixin class for adding Jackson annotations to SearchResults. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class SearchResultsMixin { + + @JsonCreator + SearchResultsMixin(@JsonProperty("results") List tweets, @JsonProperty("max_id") long maxId, + @JsonProperty("since_id") long sinceId) { + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesDeserializer.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesDeserializer.java new file mode 100644 index 0000000..4de5b0e --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesDeserializer.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; +import java.util.List; + +import org.agorava.twitter.model.Place; +import org.agorava.twitter.model.SimilarPlacesResponse; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; + +class SimilarPlacesDeserializer extends JsonDeserializer { + @Override + public SimilarPlacesResponse deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, + JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setDeserializationConfig(ctxt.getConfig()); + jp.setCodec(mapper); + + JsonNode tree = jp.readValueAsTree(); + JsonNode resultNode = tree.get("result"); + String token = resultNode.get("token").getTextValue(); + JsonNode placesNode = resultNode.get("places"); + @SuppressWarnings("unchecked") + List places = (List) mapper.readValue(placesNode, new TypeReference>() { + }); + return new SimilarPlacesResponse(places, token); + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesMixin.java new file mode 100644 index 0000000..4d24467 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SimilarPlacesMixin.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonDeserialize(using = SimilarPlacesDeserializer.class) +class SimilarPlacesMixin { + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SuggestionCategoryMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SuggestionCategoryMixin.java new file mode 100644 index 0000000..d67240c --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/SuggestionCategoryMixin.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Mixin class for adding Jackson annotations to SuggestionCategory. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +abstract class SuggestionCategoryMixin { + @JsonCreator + SuggestionCategoryMixin(@JsonProperty("name") String name, @JsonProperty("slug") String slug, @JsonProperty("size") int size) { + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TimelineDateDeserializer.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TimelineDateDeserializer.java new file mode 100644 index 0000000..b2ba329 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TimelineDateDeserializer.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +/** + * Deserializer to read date values from Twitter timeline entries. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +class TimelineDateDeserializer extends JsonDeserializer { + + @Override + public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + try { + return new SimpleDateFormat(TIMELINE_DATE_FORMAT, Locale.ENGLISH).parse(jp.getText()); + } catch (ParseException e) { + return null; + } + } + + private static final String TIMELINE_DATE_FORMAT = "EEE MMM dd HH:mm:ss ZZZZZ yyyy"; + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendMixin.java new file mode 100644 index 0000000..6913c62 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendMixin.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Mixin class for adding Jackson annotations to Trend. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +abstract class TrendMixin { + + @JsonCreator + TrendMixin(@JsonProperty("name") String name, @JsonProperty("query") String query) { + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendsMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendsMixin.java new file mode 100644 index 0000000..d1471d3 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TrendsMixin.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.Date; +import java.util.List; + +import org.agorava.twitter.model.Trend; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to Trends. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +abstract class TrendsMixin { + @JsonCreator + TrendsMixin(@JsonProperty("created_at") @JsonDeserialize(using = TimelineDateDeserializer.class) Date time, + @JsonProperty("trends") List trends) { + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetDeserializer.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetDeserializer.java new file mode 100644 index 0000000..602a559 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetDeserializer.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.agorava.twitter.model.Tweet; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; + +/** + * Custom Jackson deserializer for tweets. Tweets can't be simply mapped like other Twitter model objects because the JSON + * structure varies between the search API and the timeline API. This deserializer determine which structure is in play and + * creates a tweet from it. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +class TweetDeserializer extends JsonDeserializer { + + @Override + public Tweet deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + long id = tree.get("id").asLong(); + String text = tree.get("text").asText(); + JsonNode fromUserNode = tree.get("user"); + String fromScreenName = null; + long fromId = 0; + String fromImageUrl = null; + String dateFormat = TIMELINE_DATE_FORMAT; + if (fromUserNode != null) { + fromScreenName = fromUserNode.get("screen_name").asText(); + fromId = fromUserNode.get("id").asLong(); + fromImageUrl = fromUserNode.get("profile_image_url").asText(); + } else { + fromScreenName = tree.get("from_user").asText(); + fromId = tree.get("from_user_id").asLong(); + fromImageUrl = tree.get("profile_image_url").asText(); + dateFormat = SEARCH_DATE_FORMAT; + } + Date createdAt = toDate(tree.get("created_at").asText(), new SimpleDateFormat(dateFormat, Locale.ENGLISH)); + String source = tree.get("source").asText(); + JsonNode toUserIdNode = tree.get("in_reply_to_user_id"); + Long toUserId = toUserIdNode != null ? toUserIdNode.getLongValue() : null; + JsonNode languageCodeNode = tree.get("iso_language_code"); + String languageCode = languageCodeNode != null ? languageCodeNode.asText() : null; + Tweet tweet = new Tweet(id, text, createdAt, fromScreenName, fromImageUrl, toUserId, fromId, languageCode, source); + JsonNode inReplyToStatusIdNode = tree.get("in_reply_to_status_id"); + Long inReplyToStatusId = inReplyToStatusIdNode != null && !inReplyToStatusIdNode.isNull() ? inReplyToStatusIdNode + .getLongValue() : null; + tweet.setInReplyToStatusId(inReplyToStatusId); + JsonNode retweetCountNode = tree.get("retweet_count"); + Integer retweetCount = retweetCountNode != null && !retweetCountNode.isNull() ? retweetCountNode.getIntValue() : null; + tweet.setRetweetCount(retweetCount); + JsonNode favoritedNode = tree.get("favorited"); + boolean favorited = favoritedNode != null && !favoritedNode.isNull() ? favoritedNode.getBooleanValue() : false; + tweet.setFavorited(favorited); + jp.skipChildren(); + return tweet; + } + + private Date toDate(String dateString, DateFormat dateFormat) { + if (dateString == null) { + return null; + } + + try { + return dateFormat.parse(dateString); + } catch (ParseException e) { + return null; + } + } + + private static final String TIMELINE_DATE_FORMAT = "EEE MMM dd HH:mm:ss ZZZZZ yyyy"; + + private static final String SEARCH_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetMixin.java new file mode 100644 index 0000000..e32e556 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TweetMixin.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to Tweet. Relies on TweetDeserializer to do actual deserialization, as Tweet JSON + * structures differ slightly between timeline lists and search results. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonDeserialize(using = TweetDeserializer.class) +interface TweetMixin { +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterModule.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterModule.java new file mode 100644 index 0000000..2ba349c --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterModule.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import org.agorava.Twitter; +import org.agorava.twitter.model.DirectMessage; +import org.agorava.twitter.model.Place; +import org.agorava.twitter.model.RateLimitStatus; +import org.agorava.twitter.model.SavedSearch; +import org.agorava.twitter.model.SearchResults; +import org.agorava.twitter.model.SimilarPlacesResponse; +import org.agorava.twitter.model.SuggestionCategory; +import org.agorava.twitter.model.Trend; +import org.agorava.twitter.model.Trends; +import org.agorava.twitter.model.Tweet; +import org.agorava.twitter.model.TwitterProfile; +import org.agorava.twitter.model.UserList; +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.module.SimpleModule; + +/** + * Jackson module for registering mixin annotations against Twitter model classes. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ + +@Twitter +class TwitterModule extends SimpleModule { + public TwitterModule() { + super("TwitterModule", new Version(1, 0, 0, null)); + } + + @Override + public void setupModule(SetupContext context) { + context.setMixInAnnotations(TwitterProfile.class, TwitterProfileMixin.class); + context.setMixInAnnotations(SavedSearch.class, SavedSearchMixin.class); + context.setMixInAnnotations(Trend.class, TrendMixin.class); + context.setMixInAnnotations(Trends.class, TrendsMixin.class); + context.setMixInAnnotations(SuggestionCategory.class, SuggestionCategoryMixin.class); + context.setMixInAnnotations(DirectMessage.class, DirectMessageMixin.class); + context.setMixInAnnotations(UserList.class, UserListMixin.class); + context.setMixInAnnotations(Tweet.class, TweetMixin.class); + context.setMixInAnnotations(SearchResults.class, SearchResultsMixin.class); + context.setMixInAnnotations(Place.class, PlaceMixin.class); + context.setMixInAnnotations(SimilarPlacesResponse.class, SimilarPlacesMixin.class); + context.setMixInAnnotations(RateLimitStatus.class, RateLimitStatusMixin.class); + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileMixin.java new file mode 100644 index 0000000..56086b8 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileMixin.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.Date; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to TwitterProfile. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@SuppressWarnings("unused") +abstract class TwitterProfileMixin { + @JsonCreator + TwitterProfileMixin(@JsonProperty("id") String id, @JsonProperty("screen_name") String screenName, + @JsonProperty("name") String name, @JsonProperty("url") String url, + @JsonProperty("profile_image_url") String profileImageUrl, @JsonProperty("description") String description, + @JsonProperty("location") String location, + @JsonProperty("created_at") @JsonDeserialize(using = TimelineDateDeserializer.class) Date createdDate) { + } + + @JsonProperty("notifications") + private boolean notificationsEnabled; + + @JsonProperty("lang") + private String language; + + @JsonProperty("statuses_count") + private int statusesCount; + + @JsonProperty("listed_count") + private int listedCount; + + @JsonProperty("friends_count") + private int friendsCount; + + @JsonProperty("followers_count") + private int followersCount; + + @JsonProperty("favourites_count") + private int favoritesCount; + + @JsonProperty("following") + private boolean following; + + @JsonProperty("follow_request_sent") + private boolean followRequestSent; + + @JsonProperty("protected") + private boolean isProtected; + + @JsonProperty("verified") + private boolean verified; + + @JsonProperty("geo_enabled") + private boolean geoEnabled; + + @JsonProperty("contributors_enabled") + private boolean contributorsEnabled; + + @JsonProperty("is_translator") + private boolean translator; + + @JsonProperty("time_zone") + private String timeZone; + + @JsonProperty("utc_offset") + private int utcOffset; + + @JsonProperty("profile_use_background_image") + private boolean useBackgroundImage; + + @JsonProperty("profile_sidebar_border_color") + private String sidebarBorderColor; + + @JsonProperty("profile_sidebar_fill_color") + private String sidebarFillColor; + + @JsonProperty("profile_background_color") + private String backgroundColor; + + @JsonProperty("profile_background_image_url") + private String backgroundImageUrl; + + @JsonProperty("profile_background_tile") + private boolean backgroundImageTiled; + + @JsonProperty("profile_text_color") + private String textColor; + + @JsonProperty("profile_link_color") + private String linkColor; + + @JsonProperty("show_all_inline_media") + private boolean showAllInlineMedia; +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileUsersList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileUsersList.java new file mode 100644 index 0000000..a04d527 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/TwitterProfileUsersList.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.List; + +import org.agorava.twitter.model.TwitterProfile; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Holder for list of TwitterProfile objects pulled from a JSON object's "users" property. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class TwitterProfileUsersList { + + private final List list; + + @JsonCreator + public TwitterProfileUsersList(@JsonProperty("users") List list) { + this.list = list; + } + + public List getList() { + return list; + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListList.java new file mode 100644 index 0000000..41ea3f5 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListList.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.util.List; + +import org.agorava.twitter.model.CursoredList; +import org.agorava.twitter.model.UserList; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Holder for list of UserList, pulled from JSON object's "lists" property. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class UserListList { + private final CursoredList list; + + @JsonCreator + public UserListList(@JsonProperty("lists") List list, @JsonProperty("previous_cursor") long previousCursor, + @JsonProperty("next_cursor") long nextCursor) { + this.list = new CursoredList(list, previousCursor, nextCursor); + } + + @JsonIgnore + public CursoredList getList() { + return list; + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListMixin.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListMixin.java new file mode 100644 index 0000000..6437071 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/UserListMixin.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Mixin class for adding Jackson annotations to UserList. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +abstract class UserListMixin { + + @JsonCreator + UserListMixin(@JsonProperty("id") long id, @JsonProperty("name") String name, @JsonProperty("full_name") String fullName, + @JsonProperty("uri") String uriPath, @JsonProperty("description") String description, + @JsonProperty("slug") String slug, + @JsonProperty("mode") @JsonDeserialize(using = ModeDeserializer.class) boolean isPublic, + @JsonProperty("following") boolean isFollowing, @JsonProperty("member_count") int memberCount, + @JsonProperty("subscriber_count") int subscriberCount) { + } + + private static class ModeDeserializer extends JsonDeserializer { + @Override + public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + return jp.getText().equals("public"); + } + } +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/WeeklyTrendsList.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/WeeklyTrendsList.java new file mode 100644 index 0000000..da0c272 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/WeeklyTrendsList.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Map; + +import org.agorava.twitter.model.Trend; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Holder of a list of weekly trends. + * + * @author Craig Walls + * @author Antoine Sabot-Durand + */ +@JsonIgnoreProperties(ignoreUnknown = true) +class WeeklyTrendsList extends AbstractTrendsList { + + @JsonCreator + public WeeklyTrendsList(@JsonProperty("trends") Map> trends) { + super(trends, new SimpleDateFormat("yyyy-MM-dd")); + } + +} diff --git a/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/package-info.java b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/package-info.java new file mode 100644 index 0000000..7b3bea9 --- /dev/null +++ b/agorava-twitter-cdi/src/main/java/org/agorava/twitter/jackson/package-info.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.jackson; + diff --git a/agorava-twitter-cdi/src/main/resources/META-INF/beans.xml b/agorava-twitter-cdi/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..4f5440d --- /dev/null +++ b/agorava-twitter-cdi/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + + org.agorava.twitter.cdi.TwitterTimelineServiceDecorator + + + diff --git a/agorava-twitter-cdi/src/main/resources/org/jboss/seam/social/Twitter.properties b/agorava-twitter-cdi/src/main/resources/org/jboss/seam/social/Twitter.properties new file mode 100644 index 0000000..56e5a98 --- /dev/null +++ b/agorava-twitter-cdi/src/main/resources/org/jboss/seam/social/Twitter.properties @@ -0,0 +1,16 @@ +#------------------------------------------------------------------------------- +# Copyright 2012 Agorava +# +# 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. +#------------------------------------------------------------------------------- +service.name=Twitter diff --git a/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterServiceProducer.java b/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterServiceProducer.java new file mode 100644 index 0000000..0be351c --- /dev/null +++ b/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterServiceProducer.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.cdi.test; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +import org.agorava.Twitter; +import org.agorava.TwitterServicesHub; +import org.agorava.core.api.SocialNetworkServicesHub; +import org.agorava.core.cdi.oauth.OAuthApplication; + +/** + * @author antoine + * + */ +public class TwitterServiceProducer { + + @Twitter + @ApplicationScoped + @OAuthApplication(apiKey = "FQzlQC49UhvbMZoxUIvHTQ", apiSecret = "VQ5CZHG4qUoAkUUmckPn4iN4yyjBKcORTW0wnok4r1k") + @Produces + public SocialNetworkServicesHub OAuthSettinsProducer(TwitterServicesHub service) { + return service; + } + +} diff --git a/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterTest.java b/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterTest.java new file mode 100644 index 0000000..ce8b57e --- /dev/null +++ b/agorava-twitter-cdi/src/test/java/org/agorava/twitter/cdi/test/TwitterTest.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright 2012 Agorava + * + * 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 org.agorava.twitter.cdi.test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Date; +import java.util.List; + +import javax.inject.Inject; + +import org.agorava.Twitter; +import org.agorava.core.api.SocialNetworkServicesHub; +import org.agorava.core.api.oauth.OAuthToken; +import org.agorava.core.cdi.scribe.OAuthTokenScribe; +import org.agorava.twitter.TwitterTimelineService; +import org.agorava.twitter.TwitterUserService; +import org.agorava.twitter.model.SuggestionCategory; +import org.agorava.twitter.model.Tweet; +import org.agorava.twitter.model.TwitterProfile; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.GenericArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.importer.ZipImporter; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.DependencyResolvers; +import org.jboss.shrinkwrap.resolver.api.maven.MavenDependencyResolver; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +public class TwitterTest { + + @Inject + @Twitter + SocialNetworkServicesHub serviceHub; + + @Inject + TwitterTimelineService tl; + + @Inject + TwitterUserService userService; + + @Deployment + public static Archive createTestArchive() throws FileNotFoundException { + + WebArchive ret = ShrinkWrap + .create(WebArchive.class, "test.war") + .addAsLibraries( + ShrinkWrap.create(ZipImporter.class, "agorava-twitter-api.jar") + .importFrom(new File("../agorava-twitter-api/target/agorava-twitter-api.jar")) + .as(JavaArchive.class)).addPackages(true, "org.agorava") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml").addClass(TwitterServiceProducer.class); + System.out.println(System.getProperty("arquillian")); + if (("weld-ee-embedded-1.1".equals(System.getProperty("arquillian")) || System.getProperty("arquillian") == null)) { + // Don't embed dependencies that are already in the CL in the embedded container from surefire + ret.addAsLibraries(DependencyResolvers.use(MavenDependencyResolver.class).loadMetadataFromPom("pom.xml") + .artifact("org.jboss.solder:solder-impl").resolveAs(GenericArchive.class)); + } else { + ret.addAsLibraries(DependencyResolvers.use(MavenDependencyResolver.class).loadMetadataFromPom("pom.xml") + .artifact("org.jboss.solder:solder-impl").artifact("org.scribe:scribe") + .artifact("org.apache.commons:commons-lang3").artifact("org.codehaus.jackson:jackson-mapper-asl") + .artifact("com.google.guava:guava").resolveAsFiles()); + } + return ret; + } + + @Before + public void init() { + OAuthToken token = new OAuthTokenScribe("334872715-u75bjYqWyQSYjFMnKeTDZUn8i0QAExjUQ4ENZXH3", + "08QG7HVqDjkr1oH1YfBRWmd0n8EG73CuzJgTjFI0sk"); + serviceHub.getSession().setAccessToken(token); + serviceHub.getService().initAccessToken(); + } + + @Test + public void authorizationUrlTest() { + Assert.assertTrue(serviceHub.getService().getAuthorizationUrl().startsWith("http")); + } + + @Test + public void sendATweet() { + Tweet tweet = tl.updateStatus("Tweet sent from JUnit at " + new Date().toString()); + Assert.assertFalse(tweet.getId() == 0); + + } + + @Test + public void searchUser() { + List res = userService.searchForUsers("antoine"); + Assert.assertFalse(res.isEmpty()); + + } + + @Test + public void SuggestionCaegoriesNotEmpty() { + List res = userService.getSuggestionCategories(); + Assert.assertFalse(res.isEmpty()); + + } +} diff --git a/agorava-twitter-cdi/src/test/resources/META-INF/beans.xml b/agorava-twitter-cdi/src/test/resources/META-INF/beans.xml new file mode 100644 index 0000000..7159cb3 --- /dev/null +++ b/agorava-twitter-cdi/src/test/resources/META-INF/beans.xml @@ -0,0 +1,19 @@ + + + + diff --git a/agorava-twitter-cdi/src/test/resources/arquillian.xml b/agorava-twitter-cdi/src/test/resources/arquillian.xml new file mode 100644 index 0000000..c9cb026 --- /dev/null +++ b/agorava-twitter-cdi/src/test/resources/arquillian.xml @@ -0,0 +1,42 @@ + + + + + + + target/arquillian + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a6dbef0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,59 @@ + + + + + + agorava-parent + org.agorava + 1.0.0-SNAPSHOT + + + 4.0.0 + org.agorava + agorava-twitter-parent + pom + + + agorava-twitter-api + agorava-twitter-cdi + + + + + + + + org.agorava + agorava-twitter-api + ${project.version} + + + org.agorava + agorava-twitter-cdi + ${project.version} + + + org.agorava + agorava-parent + 1.0.0-SNAPSHOT + pom + import + + + +