www.amazon.com Book Ranking MIDlet : Networks « J2ME « Java






www.amazon.com Book Ranking MIDlet

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;
      }
    }
  }
}

           
       








Related examples in the same category

1.MIDlet to invoke a CGI script.
2.MIDlet to invoke a CGI script (POST method is used)
3.Https MIDlet
4.Pass a cookie (stored in rms) between the MIDlet and a Java servlet.
5.Use GET or POST to communicate with a Java servlet.
6.Use Java servlets sessions to tally golf scores.
7.Http Test
8.An example MIDlet to invoke a CGI script.An example MIDlet to invoke a CGI script.
9.Timer ServerTimer Server
10.Http ExampleHttp Example
11.Socket connectionSocket connection
12.Http ConnectionHttp Connection
13.Cookie MIDletCookie MIDlet
14.JargoneerJargoneer
15.Post MIDlet
16.Patchy MIDletPatchy MIDlet
17.MIDlet to invoke a CGI script (GET method).MIDlet to invoke a CGI script (GET method).
18.Fetch Page MidletFetch Page Midlet
19.Invoke Servlet Midlet 2
20.Invoke Servlet Midlet 1
21.MIDlet to invoke a CGI script (POST method is used) (2)MIDlet to invoke a CGI script (POST method is used) (2)
22.Demonstrates the functionality of DatagramConnection framework.Demonstrates the functionality of DatagramConnection framework.
23.Sample to demonstrate Http GET and POST from MIDlet
24.Get file from networkGet file from network
25.Midlet Servlet 2Midlet Servlet 2
26.MIDlet to fetch a page using an HttpConnectionMIDlet to fetch a page using an HttpConnection
27.A simple network clientA simple network client
28.Send client request and Get server responseSend client request and Get server response
29.Socket MIDletSocket MIDlet
30.Time Server
31.Http MIDletHttp MIDlet
32.DatagramSenderDatagramSender
33.Datagram Receiver