/* Copyright (c) 2008 Google Inc. * * 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 sample.books; import com.google.gdata.client.Service; import com.google.gdata.client.books.BooksService; import com.google.gdata.client.books.VolumeQuery; import sample.util.SimpleCommandLineParser; import com.google.gdata.data.Category; import com.google.gdata.data.books.BooksCategory; import com.google.gdata.data.books.VolumeEntry; import com.google.gdata.data.books.VolumeFeed; import com.google.gdata.data.dublincore.Creator; import com.google.gdata.data.dublincore.Title; import com.google.gdata.data.extensions.Rating; import com.google.gdata.util.AuthenticationException; import com.google.gdata.util.ServiceException; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.util.List; /** * Demonstrates Books API operations using the Java client library. */ public class BooksClient { protected BooksClient() {} /** * Input stream for reading user input. */ private static final BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(System.in)); /** * The name of the server hosting the YouTube GDATA feeds. */ public static final String BOOKS_GDATA_SERVER = "http://books.google.com"; /** * The URL of the volumes feed */ public static final String VOLUMES_FEED = BOOKS_GDATA_SERVER + "/books/feeds/volumes"; /** * The URL of the user library feeds */ public static final String USER_LIBRARY_FEED = BOOKS_GDATA_SERVER + "/books/feeds/users/me/collections/library/volumes"; /** * The URL of the user annotation feed */ public static final String USER_ANNOTATION_FEED = BOOKS_GDATA_SERVER + "/books/feeds/users/me/volumes"; /** * Searches the VOLUMES_FEED for search terms and print each resulting * VolumeEntry. * * @param service a BooksService object. * @param authenticated whether the user is authenticated. * @throws ServiceException * If the service is unable to handle the request. * @throws IOException error sending request or reading the feed. */ private static void searchVolumes(BooksService service, boolean authenticated) throws IOException, ServiceException { VolumeQuery query = new VolumeQuery(new URL(VOLUMES_FEED)); // exclude no-preview book (by default, they are included) query.setMinViewability(VolumeQuery.MinViewability.PARTIAL); System.out.println("\nEnter search terms: "); String searchTerms = readLine(); System.out.println(); query.setFullTextQuery(searchTerms); printUnderlined("Running Search for '" + searchTerms + "'"); VolumeFeed volumeFeed = service.query(query, VolumeFeed.class); printVolumeFeed(volumeFeed); if (authenticated) { handleSearchVolumes(service, volumeFeed); } } /** * Handle options after displaying a search feed, specifically reviewing or * adding to the user's library. * * @param service a BooksService object. * @param volumeFeed a volume feed object. * @throws ServiceException * If the service is unable to handle the request. * @throws IOException error sending request or reading the feed. */ private static void handleSearchVolumes(BooksService service, VolumeFeed volumeFeed) throws IOException, ServiceException { while (true) { System.out.println("\nWhat would you like to do?"); System.out.println("\t1) Add a volume to my library"); System.out.println("\t2) Submit a rating for a volume"); System.out.println("\t0) Back to main menu"); System.out.println("\nEnter Number (0-2): "); int choice = readInt(); String volumeId; switch (choice) { case 1: volumeId = readVolumeId(volumeFeed); if (!volumeId.equals("")) { addToLibrary(service, volumeId); } break; case 2: volumeId = readVolumeId(volumeFeed); System.out.println("Please input a rating value (1-5)"); int rating = readInt(); if (rating >= 1 && rating <= 5 && !volumeId.equals("")) { addRating(service, volumeId, rating); } break; case 0: default: return; } } } /** * Prints a String, a newline, and a number of '-' characters equal to the * String's length. * * @param stringToUnderline - the string to print underlined */ private static void printUnderlined(String stringToUnderline) { System.out.println(stringToUnderline); for (int i = 0; i < stringToUnderline.length(); ++i) { System.out.print("-"); } System.out.println("\n"); } /** * Adds a volume to the user's library * * @param service a BooksService object. * @param volumeId The volume id to insert * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void addToLibrary(BooksService service, String volumeId) throws IOException, ServiceException { VolumeEntry newEntry = new VolumeEntry(); newEntry.setId(volumeId); try { service.insert(new URL(USER_LIBRARY_FEED), newEntry); } catch (ServiceException se) { System.out.println("There was an error adding your volume.\n"); return; } System.out.println("Added " + volumeId); } /** * Adds a rating for a volume * * @param service a BooksService object. * @param volumeId The volume id to rate * @param value The rating to insert * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void addRating(BooksService service, String volumeId, int value) throws IOException, ServiceException { VolumeEntry newEntry = new VolumeEntry(); newEntry.setId(volumeId); Rating rating = new Rating(); rating.setMin(1); rating.setMax(5); rating.setValue(value); newEntry.setRating(rating); try { service.insert(new URL(USER_ANNOTATION_FEED), newEntry); } catch (ServiceException se) { System.out.println("There was an error adding your rating.\n"); return; } System.out.println("Added rating for " + volumeId); } /** * Prints a VolumeEntry * * @param entry The VolumeEntry to be printed * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void printVolumeEntry(VolumeEntry entry) throws IOException, ServiceException { System.out.print("Title: "); for (Title t : entry.getTitles()) { System.out.print(t.getValue() + "\t"); } System.out.println(); System.out.print("Author: "); for (Creator c : entry.getCreators()) { System.out.print(c.getValue() + "\t"); } System.out.println(); if (entry.hasRating()) { System.out.println("Rating: " + entry.getRating().getAverage()); } if (entry.hasReview()) { System.out.println("Review: " + entry.getReview().getValue()); } boolean firstLabel = true; if (entry.getCategories().size() > 0) { for (Category c : entry.getCategories()) { if (c.getScheme() == BooksCategory.Scheme.LABELS_SCHEME) { if (firstLabel) { System.out.print("Labels: "); firstLabel = false; } System.out.print(c.getTerm() + "\t"); } } if (!firstLabel) { System.out.println(); } } if (entry.hasViewability()) { System.out.println("Viewability: " + entry.getViewability().getValue()); } System.out.println(); } /** * Show the feed of user annotations. * * @param service A BooksService object. * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void showUserAnnotations(Service service) throws IOException, ServiceException { VolumeFeed volumeFeed = service.getFeed(new URL(USER_ANNOTATION_FEED), VolumeFeed.class); printVolumeFeed(volumeFeed); } /** * Show the feed of user annotations. * * @param service A BooksService object. * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void showUserLibrary(Service service) throws IOException, ServiceException { VolumeFeed volumeFeed = service.getFeed(new URL(USER_LIBRARY_FEED), VolumeFeed.class); printVolumeFeed(volumeFeed); } /** * Reads a line of text from the standard input. * * @throws IOException If unable to read a line from the standard input. * @return A line of text read from the standard input. */ private static String readLine() throws IOException { return bufferedReader.readLine(); } /** * Reads a line of text from the standard input and returns the parsed * integer representation. * * @throws IOException If unable to read a line from the standard input. * @return An integer read from the standard input. */ private static int readInt() throws IOException { String input = readLine(); try { return Integer.parseInt(input); } catch (NumberFormatException nfe) { return 0; } } /** * Solicits the user for the index of a volume in a list * * @param volumeFeed A volume Feed. * @return String containing a volume ID. * @throws IOException If there are problems reading user input. */ private static String readVolumeId(VolumeFeed volumeFeed) throws IOException { System.out.println("Input the index of one of the volumes listed above (1-" + volumeFeed.getEntries().size() + ")"); int input = readInt(); if (input == 0) { return ""; } return volumeFeed.getEntries().get(input - 1).getId(); } /** * Displays a menu of the main activities a user can perform. */ private static void printMenu() { System.out.println("\n"); System.out.println("Choose one of the following demo options:"); System.out.println("\t1) Search for books"); System.out.println("\t2) My list of books (requires authentication)"); System.out.println("\t3) My annotations (requires authentication)"); System.out.println("\t0) Exit"); System.out.println("\nEnter Number (0-3): "); } /** * Shows the usage of how to run the sample from the command-line. */ private static void printUsage() { System.out.println("Usage:\n java BooksClient.jar"); System.out.println("or with authentication:\n java BooksClient.jar " + " --username <user@gmail.com> " + " --password <pass> "); } /** * Print a volume feed of entries as a numbered list * * @param volumeFeed A feed of volumes * @throws IOException Error sending request or reading the feed. * @throws ServiceException If the service is unable to handle the request. */ private static void printVolumeFeed(VolumeFeed volumeFeed) throws IOException, ServiceException { String title = volumeFeed.getTitle().getPlainText(); System.out.println(title); List<VolumeEntry> volumeEntries = volumeFeed.getEntries(); if (volumeEntries.size() == 0) { System.out.println("This feed contains no entries."); return; } System.out.println("Results " + volumeFeed.getStartIndex() + " - " + (volumeFeed.getStartIndex() + volumeEntries.size() - 1) + " of " + volumeFeed.getTotalResults()); System.out.println(); int count = 1; for (VolumeEntry entry : volumeEntries) { System.out.println("(Volume #" + String.valueOf(count) + ")"); printVolumeEntry(entry); count++; } System.out.println(); } /** * BooksClient is a sample command line application that * demonstrates many features of the Books Data API using the Java Client * library. * * This sample demonstrates both search and social activities in the API. * Social activities are only available to authenticated users. * * @param args Used to pass the username and password of a test account. */ public static void main(String[] args) { SimpleCommandLineParser parser = new SimpleCommandLineParser(args); String username = parser.getValue("username", "user", "u"); String password = parser.getValue("password", "pass", "p"); boolean help = parser.containsKey("help", "h"); boolean authenticated = (username != null) && (password != null); if (help) { printUsage(); System.exit(1); } BooksService service = new BooksService("gdataSample-Books-1"); if (authenticated) { try { service.setUserCredentials(username, password); } catch (AuthenticationException e) { System.out.println("Invalid login credentials."); System.exit(1); } } while (true) { try { printMenu(); int choice = readInt(); switch (choice) { case 1: // Search for books searchVolumes(service, authenticated); break; case 2: // View the user's library if (authenticated) { showUserLibrary(service); } else { System.out.println("You need to specify a user account"); printUsage(); } break; case 3: // View the user's annotations if (authenticated) { showUserAnnotations(service); } else { System.out.println("You need to specify a user account"); printUsage(); } break; case 0: default: System.out.println("Bye!"); System.exit(0); } } catch (IOException e) { // Communications error System.err.println( "There was a problem communicating with the service."); e.printStackTrace(); } catch (ServiceException e) { // Server side error System.err.println("The server had a problem handling your request."); e.printStackTrace(); } } } }