Java tutorial
/* * Copyright (c) 2012 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 com.google.api.services.samples.youtube.cmdline.data; import com.google.api.client.googleapis.json.GoogleJsonResponseException; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.services.samples.youtube.cmdline.Auth; import com.google.api.services.youtube.YouTube; import com.google.api.services.youtube.model.ResourceId; import com.google.api.services.youtube.model.SearchListResponse; import com.google.api.services.youtube.model.SearchResult; import com.google.api.services.youtube.model.Thumbnail; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ArrayNode; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This application demonstrates a semantic YouTube search that prompts the * user to enter a search term and select a topic related to that term. The * class calls the Freebase API to get a topic ID, then passes that id along * with another user query term to the YouTube APIs. The result is a list of * videos based on a semantic search. * * @author Jeremy Walker */ public class Topics { /** * Define a global variable that identifies the name of a file that * contains the developer's API key. */ private static final String PROPERTIES_FILENAME = "youtube.properties"; /** * Define a global variable that specifies the maximum number of videos * that an API response can contain. */ private static final long NUMBER_OF_VIDEOS_RETURNED = 5; /** * Define a global variable that specifies the maximum number of topics * that an API response can contain. */ private static final long NUMBER_OF_TOPICS_RETURNED = 5; /** * Define a global instance of a Youtube object, which will be used * to make YouTube Data API requests. */ private static YouTube youtube; /** * Execute a search request that starts by calling the Freebase API to * retrieve a topic ID matching a user-provided term. Then initialize a * YouTube object to search for YouTube videos and call the YouTube Data * API's youtube.search.list method to retrieve a list of videos associated * with the selected Freebase topic and with another search query term, * which the user also enters. Finally, display the titles, video IDs, and * thumbnail images for the first five videos in the YouTube Data API * response. * * @param args This application does not use command line arguments. */ public static void main(String[] args) { // Read the developer key from the properties file. Properties properties = new Properties(); try { InputStream in = Topics.class.getResourceAsStream("/" + PROPERTIES_FILENAME); properties.load(in); } catch (IOException e) { System.err.println("There was an error reading " + PROPERTIES_FILENAME + ": " + e.getCause() + " : " + e.getMessage()); System.exit(1); } try { // Retrieve a Freebase topic ID based on a user-entered query term. String topicsId = getTopicId(); if (topicsId.length() < 1) { System.out.println("No topic id will be applied to your search."); } // Prompt the user to enter a search query term. This term will be // used to retrieve YouTube search results related to the topic // selected above. String queryTerm = getInputQuery("search"); // This object is used to make YouTube Data API requests. The last // argument is required, but since we don't need anything // initialized when the HttpRequest is initialized, we override // the interface and provide a no-op function. youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() { public void initialize(HttpRequest request) throws IOException { } }).setApplicationName("youtube-cmdline-search-sample").build(); YouTube.Search.List search = youtube.search().list("id,snippet"); // Set your developer key from the {{ Google Cloud Console }} for // non-authenticated requests. See: // {{ https://cloud.google.com/console }} String apiKey = properties.getProperty("youtube.apikey"); search.setKey(apiKey); search.setQ(queryTerm); if (topicsId.length() > 0) { search.setTopicId(topicsId); } // Restrict the search results to only include videos. See: // https://developers.google.com/youtube/v3/docs/search/list#type search.setType("video"); // To increase efficiency, only retrieve the fields that the // application uses. search.setFields("items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)"); search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED); SearchListResponse searchResponse = search.execute(); List<SearchResult> searchResultList = searchResponse.getItems(); if (searchResultList != null) { prettyPrint(searchResultList.iterator(), queryTerm, topicsId); } else { System.out.println("There were no results for your query."); } } catch (GoogleJsonResponseException e) { System.err.println( "There was a service error: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage()); e.printStackTrace(); } catch (IOException e) { System.err.println("There was an IO error: " + e.getCause() + " : " + e.getMessage()); e.printStackTrace(); } } /* * Prompt the user to enter a search term and return the user's input. * * @param searchCategory This value is displayed to the user to clarify the information that the application is requesting. */ private static String getInputQuery(String searchCategory) throws IOException { String inputQuery = ""; BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in)); do { System.out.print("Please enter a " + searchCategory + " term: "); inputQuery = bReader.readLine(); } while (inputQuery.length() < 1); return inputQuery; } /** * Retrieve Freebase topics that match a user-provided query term. Then * prompt the user to select a topic and return its topic ID. */ private static String getTopicId() throws IOException { // The application will return an empty string if no matching topic ID // is found or no results are available. String topicsId = ""; // Prompt the user to enter a query term for finding Freebase topics. String topicQuery = getInputQuery("topics"); // The Freebase Java library does not provide search functionality, so // the application needs to call directly against the URL. This code // constructs the proper URL, then uses jackson classes to convert the // JSON response into a Java object. You can learn more about the // Freebase search calls at: http://wiki.freebase.com/wiki/ApiSearch. HttpClient httpclient = new DefaultHttpClient(); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("query", topicQuery)); params.add(new BasicNameValuePair("limit", Long.toString(NUMBER_OF_TOPICS_RETURNED))); String serviceURL = "https://www.googleapis.com/freebase/v1/search"; String url = serviceURL + "?" + URLEncodedUtils.format(params, "UTF-8"); HttpResponse httpResponse = httpclient.execute(new HttpGet(url)); HttpEntity entity = httpResponse.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); try { // Convert the JSON to an object. This code does not do an // exact map from JSON to POJO (Plain Old Java object), but // you could create additional classes and use them with the // mapper.readValue() function to get that exact mapping. ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readValue(instream, JsonNode.class); // Confirm that the HTTP request was handled successfully by // checking the API response's HTTP response code. if (rootNode.get("status").asText().equals("200 OK")) { // In the API response, the "result" field contains the // list of needed results. ArrayNode arrayNodeResults = (ArrayNode) rootNode.get("result"); // Prompt the user to select a topic from the list of API // results. topicsId = getUserChoice(arrayNodeResults); } } finally { instream.close(); } } return topicsId; } /** * Output results from the Freebase topic search to the user, prompt the * user to select a topic, and return the appropriate topic ID. * * @param freebaseResults ArrayNode This object contains the search results. */ private static String getUserChoice(ArrayNode freebaseResults) throws IOException { String freebaseId = ""; if (freebaseResults.size() < 1) { return freebaseId; } // Print a list of topics retrieved from Freebase. for (int i = 0; i < freebaseResults.size(); i++) { JsonNode node = freebaseResults.get(i); System.out.print(" " + i + " = " + node.get("name").asText()); if (node.get("notable") != null) { System.out.print(" (" + node.get("notable").get("name").asText() + ")"); } System.out.println(""); } BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in)); String inputChoice; // Prompt the user to select a topic. do { System.out.print("Choose the number of the Freebase Node: "); inputChoice = bReader.readLine(); } while (!isValidIntegerSelection(inputChoice, freebaseResults.size())); // Return the topic ID needed for the API request that retrieves // YouTube search results. JsonNode node = freebaseResults.get(Integer.parseInt(inputChoice)); freebaseId = node.get("mid").asText(); return freebaseId; } /** * Confirm that the string represents a valid, positive integer, that is * less than or equal to 999,999,999. (Since the API will not return a * billion results for a query, any integer that the user enters will need * to be less than that to be valid, anyway.) * * @param input The string to test. * @param max The integer must be less then this maximum number. */ public static boolean isValidIntegerSelection(String input, int max) { if (input.length() > 9) return false; boolean validNumber = false; // Only accept positive numbers with a maximum of nine digits. Pattern intsOnly = Pattern.compile("^\\d{1,9}$"); Matcher makeMatch = intsOnly.matcher(input); if (makeMatch.find()) { int number = Integer.parseInt(makeMatch.group()); if ((number >= 0) && (number < max)) { validNumber = true; } } return validNumber; } /* * Prints out all results in the Iterator. For each result, print the * title, video ID, and thumbnail. * * @param iteratorSearchResults Iterator of SearchResults to print * @param query Search query (String) */ private static void prettyPrint(Iterator<SearchResult> iteratorSearchResults, String query, String topicsId) { System.out.println("\n============================================================="); System.out.println(" First " + NUMBER_OF_VIDEOS_RETURNED + " videos for search on \"" + query + "\" with Topics id: " + topicsId + "."); System.out.println("=============================================================\n"); if (!iteratorSearchResults.hasNext()) { System.out.println(" There aren't any results for your query."); } while (iteratorSearchResults.hasNext()) { SearchResult singleVideo = iteratorSearchResults.next(); ResourceId rId = singleVideo.getId(); // Confirm that the result represents a video. Otherwise, the // item will not contain a video ID. if (rId.getKind().equals("youtube#video")) { Thumbnail thumbnail = singleVideo.getSnippet().getThumbnails().getDefault(); System.out.println(" Video Id" + rId.getVideoId()); System.out.println(" Title: " + singleVideo.getSnippet().getTitle()); System.out.println(" Thumbnail: " + thumbnail.getUrl()); System.out.println("\n-------------------------------------------------------------\n"); } } } }