Mega Code Archive

 
Categories / Java / J2ME
 

Www amazon com Book Ranking MIDlet

/*  * J2ME in a Nutshell By Kim Topley ISBN: 0-596-00253-X  *    */ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.StringItem; import javax.microedition.lcdui.TextField; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class RankingMIDlet extends MIDlet implements CommandListener, Runnable {   private Command exitCommand;   private Command okCommand;   private Command cancelCommand;   private Command newCommand;   private Display display;   private TextField isbnField;   private StringItem isbnDisplay;   private StringItem titleDisplay;   private StringItem rankingDisplay;   private StringItem reviewDisplay;   private Form isbnForm;   private Form searchForm;   private Form resultForm;   private BookInfo searchBookInfo;   private Thread searchThread;   protected void startApp() throws MIDletStateChangeException {     if (display == null) {       initialize();       display.setCurrent(isbnForm);     }   }   protected void pauseApp() {   }   protected void destroyApp(boolean unconditional)       throws MIDletStateChangeException {   }   public void commandAction(Command cmd, Displayable d) {     if (cmd == exitCommand) {       try {         destroyApp(true);       } catch (MIDletStateChangeException ex) {       }       notifyDestroyed();     } else if (cmd == okCommand) {       String isbn = isbnField.getString().trim();       if (!isbn.equals("")) {         searchForBook(new BookInfo(isbn));       }     } else if (cmd == cancelCommand) {       searchThread = null;       isbnField.setString(null);       display.setCurrent(isbnForm);     } else if (cmd == newCommand) {       isbnField.setString(null);       display.setCurrent(isbnForm);     }   }   public void searchForBook(BookInfo info) {     searchBookInfo = info;     isbnDisplay.setText(info.getIsbn().trim());     display.setCurrent(searchForm);     searchThread = new Thread(this);     searchThread.start();   }   public void run() {     try {       boolean found = Fetcher.fetch(searchBookInfo);       if (searchThread == Thread.currentThread()) {         if (found && searchBookInfo.getTitle() != null) {           titleDisplay.setText(searchBookInfo.getTitle());           rankingDisplay               .setText(searchBookInfo.getRanking() == 0 ? ""                   : String.valueOf(searchBookInfo                       .getRanking()));           reviewDisplay.setText(searchBookInfo.getReviews() == 0 ? ""               : String.valueOf(searchBookInfo.getReviews()));           display.setCurrent(resultForm);         } else {           Alert alert = new Alert("Book not found", null, null,               AlertType.ERROR);           alert.setTimeout(Alert.FOREVER);           alert.setString("No book with ISBN "               + searchBookInfo.getIsbn() + " was found.");           isbnField.setString(null);           display.setCurrent(alert, isbnForm);         }       }     } catch (Throwable ex) {       if (searchThread == Thread.currentThread()) {         Alert alert = new Alert("Search Failed", null, null,             AlertType.ERROR);         alert.setTimeout(Alert.FOREVER);         alert.setString("Search failed:\n" + ex.getMessage());         isbnField.setString(null);         display.setCurrent(alert, isbnForm);       }     }   }   private void initialize() {     display = Display.getDisplay(this);     exitCommand = new Command("Exit", Command.EXIT, 0);     okCommand = new Command("OK", Command.OK, 0);     cancelCommand = new Command("Cancel", Command.CANCEL, 0);     newCommand = new Command("New", Command.SCREEN, 1);     isbnForm = new Form("Book Query");     isbnForm.append("Enter an ISBN and press OK:");     isbnField = new TextField("", null, 10, TextField.ANY);     isbnForm.append(isbnField);     isbnForm.addCommand(okCommand);     isbnForm.addCommand(exitCommand);     searchForm = new Form("Book Search");     searchForm.append("Searching for ISBN\n");     isbnDisplay = new StringItem(null, null);     searchForm.append(isbnDisplay);     searchForm.append("\nPlease wait....");     searchForm.addCommand(cancelCommand);     resultForm = new Form("Search Results");     titleDisplay = new StringItem("Book title: ", null);     rankingDisplay = new StringItem("Ranking:    ", null);     reviewDisplay = new StringItem("Reviews:    ", null);     resultForm.append(titleDisplay);     resultForm.append(rankingDisplay);     resultForm.append(reviewDisplay);     resultForm.addCommand(newCommand);     resultForm.addCommand(exitCommand);     // Register for events from all of the forms     isbnForm.setCommandListener(this);     searchForm.setCommandListener(this);     resultForm.setCommandListener(this);   } } class Fetcher {   private static final String BASE_URL = "http://www.amazon.com";   private static final String QUERY_URL = BASE_URL       + "/exec/obidos/search-handle-form/0";   private static final int MAX_REDIRECTS = 5;   // Fetches the title, ranking and review count   // for a book with a given ISBN.   public static boolean fetch(BookInfo info) throws IOException {     InputStream is = null;     OutputStream os = null;     HttpConnection conn = null;     int redirects = 0;     try {       String isbn = info.getIsbn();       String query = "index=books&field-keywords=" + isbn + "\r\n";       String requestMethod = HttpConnection.POST;       String name = QUERY_URL;       while (redirects < MAX_REDIRECTS) {         conn = (HttpConnection) Connector.open(name,             Connector.READ_WRITE);         // Send the ISBN number to perform the query         conn.setRequestMethod(requestMethod);         conn.setRequestProperty("Connection", "Close");         if (requestMethod.equals(HttpConnection.POST)) {           conn.setRequestProperty("Content-Type",               "application/x-www-form-urlencoded");           os = conn.openOutputStream();           os.write(query.getBytes());           os.close();           os = null;         }         // Read the response from the server         is = conn.openInputStream();         int code = conn.getResponseCode();         // If we get a redirect, try again at the new location         if ((code >= HttpConnection.HTTP_MOVED_PERM && code <= HttpConnection.HTTP_SEE_OTHER)             || code == HttpConnection.HTTP_TEMP_REDIRECT) {           // Get the URL of the new location (always absolute)           name = conn.getHeaderField("Location");           is.close();           conn.close();           is = null;           conn = null;           if (++redirects > MAX_REDIRECTS) {             // Too many redirects - give up.             break;           }           // Choose the appropriate request method           requestMethod = HttpConnection.POST;           if (code == HttpConnection.HTTP_MOVED_TEMP               || code == HttpConnection.HTTP_SEE_OTHER) {             requestMethod = HttpConnection.GET;           }           continue;         }         String type = conn.getType();         if (code == HttpConnection.HTTP_OK && type.equals("text/html")) {           info.setFromInputStream(is);           return true;         }       }     } catch (Throwable t) {       System.out.println(t);     } finally {       if (is != null) {         try {           is.close();         } catch (IOException ex) {         }       }       if (os != null) {         try {           os.close();         } catch (IOException ex) {         }       }       if (conn != null) {         try {           conn.close();         } catch (IOException ex) {         }       }     }     return false;   } } /**  * A class that represents a book listing at an online book set, including the  * number of reviews for the book and its sales ranking.  */ class BookInfo {   int id; // Used when persisting   String isbn; // The book ISBN   String title; // The book title   int reviews; // Number of reviews   int ranking; // Current ranking   int lastReviews; // Last review count   int lastRanking; // Last ranking   public BookInfo(String isbn) {     this.isbn = isbn;   }   public String getIsbn() {     return isbn;   }   public String getTitle() {     return title;   }   public int getReviews() {     return reviews;   }   public int getRanking() {     return ranking;   }   public int getLastReviews() {     return lastReviews;   }   public int getLastRanking() {     return lastRanking;   }   // Installs details parsed from an input stream   public void setFromInputStream(InputStream is) {     // Use an InputHelper to search the input     InputHelper helper = new InputHelper(is);     try {       // Default new values to current values       int newRanking = this.ranking;       int newReviews = this.reviews;       boolean found = helper.moveAfterString("buying info: ");       if (!found) {         return;       }       // Gather the title from the rest of this line       StringBuffer titleBuffer = helper.getRestOfLine();       // Look for the number of reviews       found = helper.moveAfterString("Based on ");       if (!found) {         return;       }       // Gather the number of reviews from the current location       String reviewString = helper.gatherNumber();       // Look for the sales rank       found = helper.moveAfterString("Sales Rank: ");       if (!found) {         return;       }       // Gather the number from the current location       String rankingString = helper.gatherNumber();       // Having safely found everything, set the new title       title = titleBuffer.toString().trim();       // Now convert the reviews and ranking to integers.       // If they fail to convert, just leave the existing       // values.       try {         newRanking = Integer.parseInt(rankingString);       } catch (NumberFormatException ex) {       }       if (newRanking != ranking) {         lastRanking = ranking;         ranking = newRanking;         if (lastRanking == 0) {           // First time, set last and current           // to the same value           lastRanking = ranking;         }       }       try {         newReviews = Integer.parseInt(reviewString);       } catch (NumberFormatException ex){       }       if (newReviews != reviews) {         lastReviews = reviews;         reviews = newReviews;         if (lastReviews == 0) {           // First time, set last and current           // to the same value           lastReviews = reviews;         }       }     } catch (IOException ex) {     } finally {       // Allow garbage collection       helper.dispose();       helper = null;     }   } } //A class that scans through an input //stream for strins without reading the //entire stream into a large string. class InputHelper {   // Size of the input buffer   private static final int BUFFER_SIZE = 1024;   // The input buffer   private final char[] buffer = new char[BUFFER_SIZE];   // Number of characters left in the buffer   private int charsLeft;   // Index of the next character in the buffer   private int nextChar;   // InputStreamReader used to map to Unicode   private InputStreamReader reader;   // Constructs a helper to read a given stream   public InputHelper(InputStream is) {     reader = new InputStreamReader(is);   }   // Cleans up when no longer needed   public void dispose() {     if (reader != null) {       try {         reader.close();       } catch (IOException ex) {       }       reader = null;     }   }   // Looks for a given string in the input   // stream and positions the stream so that the   // next character read is one beyond the string.   // Returns true if the string was found, false if   // not (and the stream will have been completely read).   public boolean moveAfterString(String str) throws IOException {     char[] chars = str.toCharArray();     int count = chars.length;     char firstChar = chars[0];     char c = (char) 0;     for (;;) {       if (c != firstChar && !findNext(firstChar)) {         // Reached the end of the input stream         return false;       }       boolean mismatch = false;       for (int i = 1; i < count; i++) {         c = getNext();         if (c != chars[i]) {           mismatch = true;           break;         }       }       if (!mismatch) {         return true;       }       // Mismatch. 'c' has the first mismatched       // character - start the loop again with       // that character. This is necessary because we       // could have found "wweb" while looking for "web"     }   }   // Gets the characters for a number, ignoring   // the grouping separator. The number starts at the   // current input position, but any leading non-numerics   // are skipped.   public String gatherNumber() throws IOException {     StringBuffer sb = new StringBuffer();     boolean gotNumeric = false;     for (;;) {       char c = getNext();       // Skip until we find a digit.       boolean isDigit = Character.isDigit(c);       if (!gotNumeric && !isDigit) {         continue;       }       gotNumeric = true;       if (!isDigit) {         if (c == '.' || c == ',') {           continue;         }         break;       }       sb.append(c);     }     return sb.toString();   }   // Gets the balance of the current line   // and returns it as a StringBuffer   public StringBuffer getRestOfLine() throws IOException {     StringBuffer sb = new StringBuffer();     char c;     for (;;) {       c = getNext();       if (c == '\n' || c == (char) 0) {         break;       }       sb.append(c);     }     return sb;   }   // Gets the next character from the stream,   // returning (char)0 when all input has been read.   private char getNext() throws IOException {     if (charsLeft == 0) {       charsLeft = reader.read(buffer, 0, BUFFER_SIZE);       if (charsLeft < 0) {         return (char) 0;       }       nextChar = 0;     }     charsLeft--;     return buffer[nextChar++];   }   // Finds the next instance of a given character in the   // input stream. The input stream is positioned after   // the located character. If EOF is reached without   // finding the character, false is returned.   private boolean findNext(char c) throws IOException {     for (;;) {       if (charsLeft == 0) {         charsLeft = reader.read(buffer, 0, BUFFER_SIZE);         if (charsLeft < 0) {           return false;         }         nextChar = 0;       }       charsLeft--;       if (c == buffer[nextChar++]) {         return true;       }     }   } }