/** Copyright 2012 Fahad Al-Khameesi, Madeleine Appert, Niklas Logren, Arild Matsson and Jonathan Orr�. This file is part of Bibbla. Bibbla is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bibbla is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bibbla. If not, see <http://www.gnu.org/licenses/>. **/ package dat255.grupp06.bibbla.backend.tasks; import java.util.ArrayList; import java.util.List; import org.jsoup.Connection.Method; import org.jsoup.Connection.Response; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import dat255.grupp06.bibbla.backend.Backend; import dat255.grupp06.bibbla.model.Book; import dat255.grupp06.bibbla.utils.Error; import dat255.grupp06.bibbla.utils.Message; public class SearchJob extends Job { private String searchPhrase = null; private Message message = new Message(); private int pageNumber; /** * Creates a new SearchJob, which returns the first page of the search results. * @param s - The string to search for. */ public SearchJob(String s){ this(s, 0); } /** * Creates a new SearchJob, which returns the specified page of search results. * @param s - The string to search for. * @param pageNumber - which page to fetch. 0=page1, 1=page1, 2=page2 ... */ public SearchJob(String s, int pageNumber){ searchPhrase = s; message = new Message(); this.pageNumber = pageNumber; } /** * Starts the searching procedure. * @returns a Message, which has a List<Book> as its object if successful. */ public Message run(){ try { System.out.print("\n****** SearchJob\n"); System.out.print("* step 1: fetch search results... "); Response response = connectAndRetry(); System.out.print("* step 2: parse search results... "); parseSearchResults(response); System.out.print("succeeded! *\n*"); System.out.print("****** SearchJob done \n"); } catch (Exception e) { message.error = (message.error!=null) ? message.error : Error.SEARCH_FAILED; System.out.print("failed: "+e.getMessage()+" *** \n"); } return message; } /** * Fetches and saves the HTML of the search results. * * @throws Exception if HTTP connection fails. */ protected Response connect() throws Exception { String url; // Fetch first page? if (pageNumber == 0) { url = "http://www.gotlib.goteborg.se/search*swe/X?searchtype=X&searcharg="+searchPhrase+"&searchscope=6&SUBMIT=S%C3%B6k"; } // Fetch any other page. else { url = "http://www.gotlib.goteborg.se/search~S6*swe?/X"+searchPhrase+"&searchscope=6&SORT=D/X"+searchPhrase+"&searchscope=6&SORT=D&SUBKEY="+searchPhrase+"/"+(((pageNumber-1)*50)+ 1)+"%2C1000000%2C1000000%2CB/browse"; } // Send HTTP request. Response r = Jsoup.connect(url) .method(Method.GET) .timeout(Backend.CONNECTION_TIMEOUT) .execute(); return r; } /** * Parses the HTML fetched by fetchSearchResults(). * * @throws Exception if parsing fails. */ private void parseSearchResults(Response response) throws Exception { List<Book> results = new ArrayList<Book>(); // Prepare HTML for parsing. Document html = response.parse(); // Each result lies in its own table - loop through them all. Elements tables = html.select("table.breifCitTable"); for(Element e : tables) { Book book = new Book(); book.setName(e.select("a").get(1).text()); book.setAuthor(e.select("strong").first().text()); book.setType(e.select("td.sokresultat").get(4).getElementsByTag("img").first().attr("alt")); book.setUrl(e.select("a").get(1).attr("abs:href")); book.setReserveUrl(e.select("div.reserverapadding").select("a").attr("abs:href")); book.setAvailable(availableParse(e.select("td.sokresultat").select("em").text())); results.add(book); } message.obj = results; } /** * Parse the first word of string as int. * @param A string whose first word possibly is a number. * @return An int which defaults to 0 if parse fails. */ private int availableParse(String text) { try { return Integer.parseInt(text.split(" ")[0]); } catch (NumberFormatException exc) { return 0; } } }