Today, I started my journey into the world of Java 7. Quite late I know, but as they better late than never. So I now have a build of Java 7 SDK on my desktop, and spent some time fiddling with the new features in. One of the most striking features of Java 7, specially after working in ActionScript 3, is the ability to switch on strings.

ActionScript developers would know the value and power of this small feature, as it gets rid of those ugly multiple if-else if-else if-else blocks. One way to fool around was to use Enums but that to me seemed overkill specifically if the input data was coming from a file, database or human interface.

Thus, what looked like in the Java world till Java 6
public void someMethod(String command) {
    if("dir".equals(command)) {
        // list the files in folder
    } else if("cls".equals(command)) {
        // clear the screen
    } else if("rename".equals(command)) {
        // rename the given file
    } else if("delete".equals(command)) {
        // delete the given file
    } else if("ver".equals(command)) {
        // display OS version
    } else {
        throw new IllegalArgumentException("Command not found.");
    }
}

has now been reduced to something like,
public void someMethod(String command) {
    switch(command) {
        case "dir":
            // list file in folder
            break;

        case "cls":
            // clear the screen
            break;

        case "rename":
            // rename the given file
            break;

        case "delete":
            // delete the given file
            break;

        case "ver":
            // display OS version
            break;

        default:
            throw new IllegalArgumentException("Command not found.");
    }
}

Foshizle, it is not a super-developer-feature that may make you say a WOW, but it surely would make some pieces of code readable, and easily debug-able.

Happy Coding!

written by Sandeep Gupta

Wednesday, June 29, 2011 at 9:33 PM

Problem:
There are two astronomically huge numbers that need to be added. The numbers are stored digit per digit as nodes of a linked list.

Solution:
This is a classic linked-list problem, and often comes up as the favorite interview question in C/C++. I have had the same experience in my recent past both as an interviewee and as an interviewer. Anyways, over to the solution.

Consider that our data is stored in a simple linked list structure such as,
public class Node {

    public int digit;

    public Node nextNode = null;

}

The biggest hurdle in solving the problem is that the linked list can be traversed from one end, in our case the left end of the number (as a String) whereas the addition has to happen from the right-end of the number. To solve the same the easiest solution would be to reverse the linked lists. This way once you have the result, just reverse it back. Reversing should be easy as,

private static Node reverse(Node sum) {
  Node current = null;
  do {
   Node newNode = new Node(sum.digit);
   newNode.nextNode = current;
   current = newNode;
   sum = sum.nextNode;
  } while(sum != null);
  
  return current;
 }

Throwing in a convenience method to convert a string into the number as a linked list,

public static Node createNumber(String string) {
  char[] array = string.toCharArray();
  Node parentNode = new Node(array[0] - '0');
  Node node = parentNode;
  
  for(int i = 1; i < array.length; i++) {
   Node temp = new Node(array[i] - '0');
   node.nextNode = temp;
   node = temp;
  }
  
  return parentNode;
 }
and to display the number as a String,
public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append(this.digit);
  Node nextNode = this.nextNode;
  while(nextNode != null) {
   builder.append(nextNode.digit);
   nextNode = nextNode.nextNode;
  }
  
  return builder.toString();
 }

The code piece would look something like,
/**
 * Copyright (C) 2011, Sandeep Gupta
 * http://www.sangupta.com
 * 
 * The file is licensed under the 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.
 * 
 */

/**
* Simple solution to add astronomically huge numbers.
* 
* @author sangupta
* @since 27 Jun 2011
*/
public class Node {

 private int digit;
 
 private Node nextNode = null;
 
 public Node(int digit) {
  this.digit = digit;
 }
 
 public static void main(String[] args) {
  Node num1 = Node.createNumber("12345");
  Node num2 = Node.createNumber("55");
  Node sum = Node.sum(num1, num2);
  System.out.println("Sum: " + sum);
 }
 
 public static Node sum(Node num1, Node num2) {
  Node n1 = reverse(num1);
  Node n2 = reverse(num2);
  
  int carry = 0;
  Node sum = sum(n1, n2, carry);
  
  sum = reverse(sum);
  
  return sum;
 }

 private static Node sum(Node num1, Node num2, int carry) {
  Node result;
  if(num1 == null && num2 == null) {
   if(carry == 0) {
    result = null;
   } else {
    result = new Node(carry);
   }
  } else if(num1 != null && num2 != null) {
   int temp = num1.digit + num2.digit + carry;
   int digit = temp % 10;
   carry = temp / 10;
   
   result = new Node(digit);
   result.nextNode = sum(num1.nextNode, num2.nextNode, carry);
  } else if(num1 != null) {
   int temp = num1.digit + carry;
   int digit = num1.digit % 10;
   carry = temp / 10;
   
   result = new Node(digit);
   result.nextNode = sum(num1.nextNode, null, carry);
  } else {
   // only num2 is not null here
   int temp = num2.digit + carry;
   int digit = num2.digit % 10;
   carry = temp / 10;
   
   result = new Node(digit);
   result.nextNode = sum(null, num2.nextNode, carry);
  }
  
  return result;
 }
 
}

Hope this helps.

written by Sandeep Gupta

Tuesday, June 28, 2011 at 8:00 AM

Problem:
Consider a list of lottery tickets where the only information available is the ticket number, and the contact/verification details of the purchaser. The tickets are sold as per 4 regions, East/West/North/South, and have the same as the first letter of the ticket number. Given that one has to traverse through all ticket numbers only once, design a lottery system to pick a winner.

Solution:
We are given that the list of all tickets has to be traversed and only once. Thus, our lottery winner cannot be based on a random selection amongst the list. Because, first we won't be traversing through the entire list and second that a person buying 1000 tickets will have a better chance at winning.

Given the constraint, we need to iterate over all tickets. Let's assume there are 100 tickets and we have iterated over 10 tickets by now. We need a winner amongst these 10 tickets, assuming these were the only ones. As we read 11th ticket, we need to choose a winner amongst the winner of 10 tickets, and the 11th ticket. This way we can define an approach where with every ticket processing we keep choosing between the current winner (till the last ticket) and the ticket being processed.

Thus, the solution can be coded as under,
/**
 * Copyright (C) 2011, Sandeep Gupta
 * http://www.sangupta.com
 * 
 * The file is licensed under the 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.
 * 
 */

/**
* A simple solution to the lottery problem.
* 
* @author sangupta
* @since 27 Jun 2011
*/
public class Lottery {
 
 public static void main(String[] args) {
  List tickets = new ArrayList();
  tickets.add(new Ticket("E123", "A"));
  tickets.add(new Ticket("E345", "B"));
  tickets.add(new Ticket("N672", "C"));
  tickets.add(new Ticket("S642", "D"));
  tickets.add(new Ticket("W945", "E"));
  
  Ticket winner = selectWinner(tickets);
  System.out.println("Winner: " + winner.contactDetails);
 }
 
 /**
  * The method selects a winner amongst the given lottery tickets.
  * 
  * @param tickets
  * @return
  */
 public static Ticket selectWinner(List tickets) {
  // Usual checks
  if(tickets == null || tickets.size() == 0) {
   System.out.println("No ticket sold, thus no winner.");
   return null;
  }
  
  if(tickets.size() == 1) {
   System.out.println("Only one ticket sold, the winner is the same.");
   return tickets.get(0);
  }
  
  // iterate over all ticket
  Ticket currentWinner = tickets.get(0);
  long currentWinnerHash = ticketToHash(currentWinner);
  for(int index = 1; index < tickets.size(); index++) {
   Ticket candidate = tickets.get(index);
   
   long hash =  ticketToHash(candidate);
   double random;
   do {
    random = Math.random();
   } while(random == 0.5);
   
   if((random < 0.5) && (hash < currentWinnerHash)) {
    currentWinner = candidate;
   } else if(hash > currentWinnerHash) {
    currentWinner = candidate;
   }
   
   if(currentWinner == candidate) {
    currentWinnerHash = hash;
   }
  }
  
  return currentWinner;
 }
 
 /**
  * Store ticket details.
  */
 public static class Ticket {
  
  String ticketNumber;
  
  String contactDetails;
  
  public Ticket(String number, String details) {
   this.ticketNumber = number;
   this.contactDetails = details;
  }
  
 }

}

Consider a buyer who buys 1000 tickets. As he will buy from the same region, all his tickets will land up in the same region code. Thus, we need to randomize the region within the ticket as well and this can be done inside our ticketToHash method, as under,

  /**
  * Convert the ticket number to a long hash value
  * 
  * @param currentWinner
  * @return
  */
 private static long ticketToHash(Ticket currentWinner) {
  String number = currentWinner.ticketNumber;

  // replace the region of the ticket with a digit first
  int digit = (int) (Math.random() * 10);
  number = String.valueOf(digit) + number.substring(1);
  
  // randomize all digits
  number = shuffle(number.toCharArray());
  
  // return the hash of the number
  Long num = Long.parseLong(number);
  long randomHash = (long) ((double)num.hashCode() * new Random().nextInt(1000000));
  return randomHash;
 }

Another randomization way is to randomize the obtained digits itself. This will make sure that large ticket numbers do not necessarily produce a larger hash.

  /**
  * Shuffle for array length * 5 times, picking any two positions and swapping them
  * 
  * @param charArray
  * @return
  */
 private static String shuffle(char[] charArray) {
  if(charArray.length == 1) {
   return charArray.toString();
  }

  Random random = new Random(new Random().nextLong());
  int length = charArray.length;
  int limit = length * 5;
  for(int i = 0; i < limit; i++) {
   int position1 = random.nextInt(length);
   int position2;
   do {
    position2 = random.nextInt(length);
   } while(position1 == position2);
   
   // swap these two positions
   char temp = charArray[position1];
   charArray[position1] = charArray[position2];
   charArray[position2] = temp;
  }
  
  return String.valueOf(charArray);
 }
The above solution holds good for all conditions as mentioned in the problem statement. Improvement Areas: The part where the ticket number is converted to hash, and the hash compared to other hashes can be modified to make sure that a very high value of hash does not keeps intact as the current winner. The part may again be randomized for the same.

Hope this helps.

written by Sandeep Gupta

Monday, June 27, 2011 at 3:33 PM

They say necessity is the mother of all invention. That's right! As per my previous post ISBN Book Renaming, I had coded a small command line tool that helps in renaming books as per their ISBN number. As my father lay hands on the tools, and started using it, he found it useful but also complained that it lagged features, and yes, was buggy in a way ;)

So here is an update on the command line tool, with the following new features and a couple of small bug fixes:
  • Adds support to retain the ISBN number as the prefix or the suffix when renaming the book.
  • Fixes bugs when there are child folders in the folder supplied
  • Some housekeeping issues

Details on using the tool and where to grab the latest download are available here. You can download a copy of this version of the tool from my Google Code repository.

The source code for the tool is as under,

/**
 * Copyright (C) 2011, Sandeep Gupta
 * http://www.sangupta.com
 * 
 * The file is licensed under the 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.sangupta.isbntools;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Command line tool to rename the files in a folder picking the filename to be
 * the ISBN number and hitting the webservice at http://isbndb.com for getting
 * the filename.
 * 
 * All folders and any file ending in extension ZIP are skipped.
 * 
 * Update 24 Jun 2011: Updated to include options for renaming files per different schemes 
 * and a few small bug fixes. 
 * 
 * @author sangupta
 * @since 18 Jun 2011
 * @version 1.1
 */
public class ISBNBookRenamer {

 /**
  * The API key for the site http://isbndb.com where we get the book names
  * from the ISBN code
  */
 private static final String ISBNDB_API_KEY = "";

 /**
  * The API end point that will be hit
  */
 private static final String API_URL = "http://isbndb.com/api/books.xml?access_key=" + ISBNDB_API_KEY + "&index1=isbn&value1=";

 private static int renamingOption = 0;

 /**
  * The main entry point.
  * 
  * @param args
  */
 public static void main(String[] args) {
  // check for proper usage
  if (args.length < 1) {
   usage();
   return;
  }

  if (args.length == 2) {
   renamingOption = args[1].charAt(0) - 48;
   if (renamingOption != 1 && renamingOption != 2) {
    System.out.println("Wrong arguments provided, check usage... exiting!\n");
    usage();
    return;
   }
  }

  // perform sanity checks

  String folderPath = args[0];
  File folder = new File(folderPath);

  if (!folder.exists()) {
   System.out
     .println("The folder path you specified does not exists.");
   return;
  }

  if (!folder.isDirectory()) {
   System.out.println("The path you specified is not a folder.");
   return;
  }

  // get a list of all files
  File[] files = folder.listFiles();
  if (files == null || files.length == 0) {
   System.out.println("No file in folder to work upon.");
   return;
  }

  for (File localFile : files) {
   if (localFile.isFile()) {
    renameBook(localFile);
   }
  }

  System.out.println("\nDone!\n");
 }

 /**
  * Displays the usage information on the tool.
  */
 private static void usage() {
  System.out.println("Usage: ");
  System.out.println("       $ java -jar ISBNBookRenamer <folder> [renamingOption]");
  System.out.println("              folder: the folder where all books are stored");
  System.out.println("              renamingOption: an optional integral parameter tht specifies on how to rename the file");
  System.out.println("                  <not specified/default> : isbn.pdf will be renamed as filename.pdf");
  System.out.println("                  1 : isbn.pdf will be renamed as filename_isbn.pdf");
  System.out.println("                  2 : isbn.pdf will be renamed as isbn_filename.pdf");
 }

 /**
  * Processes the given file and renames the file as per ISBN bookname if
  * possible.
  * 
  * @param localFile
  */
 private static void renameBook(File localFile) {
  String fileName = localFile.getName();
  String parentFolder = localFile.getParent();

  // strip off name and extension
  String name = null, extension = null;
  int extensionIndex = fileName.lastIndexOf('.');
  if (extensionIndex != -1) {
   name = fileName.substring(0, extensionIndex);
   extension = fileName.substring(extensionIndex + 1);
   if (!extension.equalsIgnoreCase("pdf")) {
    System.out.println("Filename " + fileName + "extension is not PDF... skipping!");
    return;
   }
  }

  if (name != null && name.length() != 10) {
   System.out.println("Filename " + fileName + " is not 10 characters long... skipping!");
   return;
  }

  // now fetch the ISBN name for the book
  String bookName = getISBNBookName(name);
  if (bookName == null) {
   System.out.println("Unable to fetch book name for file: " + fileName + "... skipping!");
   return;
  }

  // rename the book
  bookName = sanitizeBookName(bookName);

  String newFileName = "";
  switch (renamingOption) {
  case 1:
   newFileName = bookName + '_' + name + '.' + extension;
   break;
  case 2:
   newFileName = name + '_' + bookName + '.' + extension;
   break;
  default:
   newFileName = bookName + '.' + extension;
  }

  File newFile = new File(parentFolder + File.separatorChar + newFileName);

  System.out.println("Renaming " + fileName + " to " + newFileName);

  boolean success = localFile.renameTo(newFile);

  if (!success) {
   System.out.println("Failed renaming " + fileName + " to "
     + newFileName);
   return;
  }

 }

 /**
  * Sanitize the bookname and remove characters that cannot be a part of the
  * filename
  * 
  * @param bookName
  * @return
  */
 public static String sanitizeBookName(String bookName) {
  bookName = bookName.replace(':', '_');
  bookName = remove(bookName, 'รข');
  bookName = remove(bookName, ',');
  bookName = remove(bookName, '˘');
  bookName = remove(bookName, '„');
  return bookName;
 }

 public static String remove(String str, char remove) {
  if (isEmpty(str) || str.indexOf(remove) == -1) {
   return str;
  }
  char[] chars = str.toCharArray();
  int pos = 0;
  for (int i = 0; i < chars.length; i++) {
   if (chars[i] != remove) {
    chars[pos++] = chars[i];
   }
  }
  return new String(chars, 0, pos);
 }

 private static boolean isEmpty(String str) {
  if (str == null || str.length() == 0) {
   return true;
  }

  return false;
 }

 /**
  * Given the ISBN number, return the bookname as possible.
  * 
  * @param name
  * @return
  */
 private static String getISBNBookName(String name) {
  String urlToHit = API_URL + name;

  // hit the webservice
  HttpURLConnection conn = null;
  InputStream in = null;
  BufferedReader rd = null;
  try {
   conn = (HttpURLConnection) (new URL(urlToHit)).openConnection();
   conn.setRequestMethod("GET");

   int responseCode = conn.getResponseCode();
   if (responseCode != HttpURLConnection.HTTP_OK) {
    in = conn.getErrorStream();
    rd = new BufferedReader(new InputStreamReader(in));
    String tempLine = rd.readLine();
    StringBuilder response = new StringBuilder();
    while (tempLine != null) {
     response.append(tempLine).append("\n");
     tempLine = rd.readLine();
    }

    System.out.println("Unable to get book name for " + name + " with error: " + response.toString());
   } else {
    in = conn.getInputStream();
    rd = new BufferedReader(new InputStreamReader(in));
    String tempLine = rd.readLine();
    StringBuilder response = new StringBuilder();
    while (tempLine != null) {
     response.append(tempLine).append("\n");
     tempLine = rd.readLine();
    }

    String xml = response.toString();
    System.out.println("XML response returned is: " + xml);

    int titleIndexStart = xml.indexOf("<Title>");
    if (titleIndexStart == -1) {
     System.out.println("Unable to get book title via XML response: " + xml);
     return null;
    }

    int titleIndexEnd = xml.indexOf("</Title>", titleIndexStart);
    String bookName = xml.substring(titleIndexStart + 7, titleIndexEnd);
    return bookName;
   }
  } catch (MalformedURLException e) {
   System.out.println("Unable to get book name for book " + name);
   e.printStackTrace();
  } catch (IOException e) {
   System.out.println("Unable to get book name for book " + name);
   e.printStackTrace();
  } finally {
   if (conn != null) {
    conn.disconnect();
   }

   if (rd != null) {
    try {
     rd.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }

   if (in != null) {
    try {
     in.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }

  return null;
 }

}

Hope this helps.

written by Sandeep Gupta

Friday, June 24, 2011 at 2:21 PM

Being a lazy Saturday morning, on breakfast table my father told me that how he was spending his time. He downloaded some books from the internet where in the file was named using the ISBN number of the book, say as, 1590595262.pdf for the The Robosapien Companion, and that he was spending time renaming these books by searching Google and giving the file a proper name. I felt bad that me being a developer, still my dad was wasting time on something futile.

Hence, I loaded my Eclipse and sat to write a small command line tool that can do the same. Given a folder the tool will pick up all the files in the folder (except ZIP files), find files that may be ISBN named, and once found, will try and hit the free webservice at ISBNDB to retrieve the book name. If retrieval succeeds, the file will be renamed as per the book name, else skipped.

The tool can be downloaded from my Google Code repository. Using the tool is plain and simple,
$ java -jar ISBNBookRenamer-1.0-b2.jar <folder>
where folder is the folder that consists of files named as <ISBN number>.*. Note that any file ending in .ZIP will be skipped.

The source code for the tool is as under,

/**
 * Copyright (C) 2011, Sandeep Gupta
 * http://www.sangupta.com
 * 
 * The file is licensed under the 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.sangupta.isbntools;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Command line tool to rename the files in a folder picking the filename to be
 * the ISBN number and hitting the webservice at http://isbndb.com for getting 
 * the filename.
 * 
 * All files ending in extension ZIP are skipped.
 * 
 * @author sangupta
 * @since 18 Jun 2011
 */
public class ISBNBookRenamer {
        
        /**
         * The API key for the site http://isbndb.com where we get the book names from the ISBN code
         */
        private static final String ISBNDB_API_KEY = "";
        
        /**
         * The API end point that will be hit
         */
        private static final String API_URL = "http://isbndb.com/api/books.xml?access_key=" + ISBNDB_API_KEY + "&index1=isbn&value1=";

        /**
         * The main entry point.
         * 
         * @param args
         */
        public static void main(String[] args) {
                // check for proper usage
                if(args.length != 1) {
                        System.out.println("Usage: ");
                        System.out.println("       $ java -jar ISBNBookRenamer <folder>");
                        System.out.println("              folder: the folder where all books are stored");
                        return;
                }

                // perform sanity checks
                String folderPath = args[0];
                File folder = new File(folderPath);
                
                if(!folder.exists()) {
                        System.out.println("The folder path you specified does not exists.");
                        return;
                }
                
                if(!folder.isDirectory()) {
                        System.out.println("The path you specified is not a folder.");
                        return;
                }
                
                // get a list of all files
                File[] files = folder.listFiles();
                if(files == null || files.length == 0) {
                        System.out.println("No file in folder to work upon.");
                        return;
                }
                
                for(File localFile : files) {
                        renameBook(localFile);
                }
                
                System.out.println("Done renaming books.");
        }

        /**
         * Processes the given file and renames the file as per ISBN bookname
         * if possible.
         * 
         * @param localFile
         */
        private static void renameBook(File localFile) {
                String fileName = localFile.getName();
                String parentFolder = localFile.getParent();
                
                // strip off name and extension
                String name = null, extension = null;
                int extensionIndex = fileName.lastIndexOf('.');
                if(extensionIndex != -1) {
                        name = fileName.substring(0, extensionIndex);
                        extension = fileName.substring(extensionIndex + 1);
                        if(extension.equalsIgnoreCase("zip")) {
                                System.out.println("Filename " + fileName + "extension is ZIP... skipping!");
                                return;
                        }
                }
                
                if(name.length() != 10) {
                        System.out.println("Filename " + fileName + "is longer than 10 characters... skipping!");
                        return;
                }
                
                // now fetch the ISBN name for the book
                String bookName = getISBNBookName(name);
                if(bookName == null) {
                        System.out.println("Unable to fetch book name for file: " + fileName + "... skipping!");
                        return;
                }
                
                // rename the book
                bookName = sanitizeBookName(bookName);
                
                String newFileName = bookName + '.' + extension;
                File newFile = new File(parentFolder + File.separatorChar + newFileName);
                System.out.println("Renaming " + fileName + " to " + newFileName);
                boolean success = localFile.renameTo(newFile);
                if(!success) {
                        System.out.println("Failed renaming " + fileName + " to " + newFileName);
                        return;
                }
        }

        /**
         * Sanitize the bookname and remove characters that cannot be a part of the filename
         * 
         * @param bookName
         * @return
         */
        private static String sanitizeBookName(String bookName) {
                bookName = bookName.replace(':', '_');
                return bookName;
        }

        /**
         * Given the ISBN number, return the bookname as possible.
         * 
         * @param name
         * @return
         */
        private static String getISBNBookName(String name) {
                String urlToHit = API_URL + name;
                
                // hit the webservice
                HttpURLConnection conn = null;
                InputStream in = null;
            BufferedReader rd = null;
                try {
                        conn = (HttpURLConnection) (new URL(urlToHit)).openConnection();
                        conn.setRequestMethod("GET");
        
                        int responseCode = conn.getResponseCode();
                        if (responseCode != HttpURLConnection.HTTP_OK) {
                                in = conn.getErrorStream();
                                rd = new BufferedReader(new InputStreamReader(in));
                            String tempLine = rd.readLine();
                            StringBuilder response = new StringBuilder();
                                while (tempLine != null) {
                                        response.append(tempLine).append("\n");
                                        tempLine = rd.readLine();
                                }
                                
                                System.out.println("Unable to get book name for " + name + " with error: " + response.toString());
                        } else {
                                in = conn.getInputStream();
                                rd = new BufferedReader(new InputStreamReader(in));
                            String tempLine = rd.readLine();
                            StringBuilder response = new StringBuilder();
                                while (tempLine != null) {
                                        response.append(tempLine).append("\n");
                                        tempLine = rd.readLine();
                                }
                                
                                String xml = response.toString();
                                System.out.println("XML response returned is: " + xml);
                                
                                int titleIndexStart = xml.indexOf("<Title>");
                                if(titleIndexStart == -1) {
                                        System.out.println("Unable to get book title via XML response: " + xml);
                                        return null;
                                }
                                
                                int titleIndexEnd = xml.indexOf("</Title>", titleIndexStart);
                                String bookName = xml.substring(titleIndexStart + 7, titleIndexEnd);
                                return bookName;
                        }
                } catch (MalformedURLException e) {
                        System.out.println("Unable to get book name for book " + name);
                        e.printStackTrace();
                } catch (IOException e) {
                        System.out.println("Unable to get book name for book " + name);
                        e.printStackTrace();
                } finally {
                        if(conn != null) {
                                conn.disconnect();
                        }

                        if(rd != null) {
                                try {
                                        rd.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                        
                        if(in != null) {
                                try {
                                        in.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                }
                
                return null;
        }

}

Hope this helps.

written by Sandeep Gupta

Saturday, June 18, 2011 at 8:56 PM