/**
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.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 dat255.grupp06.bibbla.model.Book;
import dat255.grupp06.bibbla.model.Credentials;
import dat255.grupp06.bibbla.utils.Error;
import dat255.grupp06.bibbla.utils.Message;
import dat255.grupp06.bibbla.utils.Session;
/**
* Reserves a book at the supplied library.
*
* @author Niklas Logren
*/
public class ReserveJob extends AuthorizedJob {
static final String KEY_LIBCODE = "locx00";
static final String KEY_YEAR = "needby_Year", VAL_YEAR = "Year";
static final String KEY_MONTH = "needby_Month", VAL_MONTH = "Month";
static final String KEY_DAY = "needby_Day", VAL_DAY = "Day";
private Book book;
private Session session;
private String libraryCode;
private Map<String, String> postData;
/**
* Creates a new ReserveJob which will try to reserve a book at the given library.
*
* @param book - The book to reserve. Needs reserveUrl set.
* @param libraryCode - The code of the library to send the book to. See library-codes.txt.
* @param session - The session the book should be reserved using. User account is specified here.
*/
public ReserveJob(Book book, String libraryCode, Credentials credentials,
Session session) {
super(credentials, session);
this.book = book;
this.libraryCode = libraryCode;
this.session = session;
}
/**
* Performs the reservation.
*
* @returns a Message.
* If reservation was successful, error==null and obj is a string
* detailing which library the book will be sent to.
* If reservation failed, obj will be a string containing the error message.
*/
public Message run() {
login();
// Prepare field for paramless connect()
postData = createPostData(libraryCode);
// Attempt reservation
Response reserveResponse = null;
try {
reserveResponse = connectAndRetry();
} catch (Exception e) {
Message errorMessage = new Message();
errorMessage.error = Error.RESERVE_FAILED;
return errorMessage;
}
// Parse html from response
Document html;
try {
html = reserveResponse.parse();
} catch (IOException e) {
Message errorMessage = new Message();
errorMessage.error = Error.RESERVE_FAILED;
return errorMessage;
}
// Identify
String library;
try {
library = identifyReceivingLibrary(html);
} catch (JobFailedException e) {
Message errorMessage = new Message();
errorMessage.error = Error.RESERVE_FAILED;
return errorMessage;
}
// Prepare a result message
Message successMessage = new Message();
successMessage.obj = library;
return successMessage;
}
/**
* Creates a map of post data to send with the reservation request.
* @param libraryCode code identifying a library
* @return a map modelled by { "locx00" = <var>libraryCode</var>;
* "needby_Year" = "Year"; "needby_Month" = "Month"; "needby_Day" = "Day" }
*/
static Map<String, String> createPostData(final String libraryCode) {
Map<String,String> postData = new HashMap<String,String>() {
private static final long serialVersionUID = 5883265540089660691L;
{
put(KEY_LIBCODE, libraryCode);
put(KEY_YEAR, VAL_YEAR);
put(KEY_MONTH, VAL_MONTH);
put(KEY_DAY, VAL_DAY);
}
};
return postData;
}
@Override
/**
* POSTs the reservation, and saves the response.
* @throws IOException if connection failed.
*/
protected final Response connect() throws IOException {
// Send request and return response.
Response httpResponse = Jsoup.connect(book.getReserveUrl())
.method(Method.POST)
.cookies(session.getCookies())
.data(postData)
.execute();
return httpResponse;
}
/**
* Find the name of the library where the book will arrive.
* @param html produced from the reservation connection
* @return the name of a library
* @throws JobFailedException if the element of the library name could not
* be found. Assume the reservation failed.
*/
static String identifyReceivingLibrary(Document html)
throws JobFailedException {
Element div = html.getElementById("singlecolumn");
try {
return div.getElementsByTag("b").first().text();
} catch (NullPointerException e) {
throw new JobFailedException(e);
}
}
}