<< GUI design - Contact List, Part 2 | Home | Display - Best Practice (hopefully) >>

Contact sorting - Contact List, Part 3

Simple sorting of data from RecordStore

This is the final part of my little tutorial/coursework re-do, where I will show you how easily can stored contacts be organised.

  1. Designing Address Book - Contact List, Part 1
  2. GUI design - Contact List, Part 2

Some of you may know that RecordStore works on base of LIFO - Last In, First Out approach. For example if record has been added in the order: peter, marta, bruno, mark they will be read out of RecordStore in reversed order as: mark, bruno, marta, peter. To get contacts sorted, there are two options; either try to put contacts in order every time new contact is added or, try to put them in order once they read out from RecordStore, just before they get displayed on screen. The first option is overkill as it is just too much work for application to perform each time new record is stored and pretty much useless (read all records, add new record in correct position and overwrite previous data), so second option is the obvious choice.

Even at this point there are various ways to solve this problem. With observation of Sony Ericsson W910 menu routine, I decided to collect only fraction of the contact details from RecordsStore (only contact name and the first number associated with this contact). Collection of a name and first phone number will be my skeleton for further development.

The bellow code is part of RecordStoreOperations class that does basic reading of stored records.

  1. Open record store
  2. Read records in byte array form
  3. Call fromByteArrayPartial(byte[] data) method to convert byte array to Contact object and return this to caller method
  4. If there are more records repeat the two steps above
  5. Close RecordStore
  6. Return Vector with Contact object to form for display

    /**
     * Method to retrieve all contacts from record store
     *
     * @return list of all contacts stored in vector
     */
    public Vector listContacts() {
        Vector vec = new Vector();
        rsm = new RecordStoreManager();
        RecordStore rs = rsm.openRSM();
        try {
            RecordEnumeration re = rs.enumerateRecords(null, null, false);
            while (re.hasNextElement()) {
                byte[] record = re.nextRecord();
                vec.addElement(fromByteArrayPartial(record));
            }
        }
        catch (RecordStoreException rse) {
            //Need of loggin mechanism, for now only silent stack trace to console
            rse.printStackTrace();
        }
        catch (IOException ioe) {
            //Need of loggin mechanism, for now only system message to console
            System.out.println("Problem with un-packing byte array");
        }
        return vec;
    }

    /**
     * Method will receive byte array of data that have to be stored in Contact object.
     * However as this is only general list the method will only retrieve name and
     * first stored number with it's type.
     *
     * @param data specifies byte array to be process
     * @return initialized Contact object
     * @throws IOException if there is a problem data out stream closing operation
     */
    private Contact fromByteArrayPartial(byte[] data) throws IOException {
        Contact contact = new Contact();
        ByteArrayInputStream bays = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bays);

        contact.setName(dis.readUTF());
        String phoneType = dis.readUTF();
        String phoneNum = dis.readUTF();
        contact.setPhoneNumbers(phoneType, phoneNum);
        dis.close();

        return contact;
    }

Unsorted lis Sorted list example 1 Sorted list example 2
Unsorted list Sorted list ex.1 Sorted list ex.2

From the image above, first on the left - Unsorted list, you can see outcome of the provided code. Besides the fact that listed contacts are not sorted, we have another problem at hand. Me as the user, can be silly as to save two different contacts with same name. This is standard situation, as most of us can distinguish between phone numbers with different country or exchange code (0044, 0208, etc.). There is a need for application to be able to identify record we try to manipulate with minimum amount of additional info. Luckily RecordStore does support the use of record IDs and we can do following.

        rsm = new RecordStoreManager();
        RecordStore rs = rsm.openRSM();
        try {
            RecordEnumeration re = rs.enumerateRecords(null, null, false);

            while (re.hasNextElement()) {
                int i = re.nextRecordId();
                byte[] record = rs.getRecord(i);
                vec.addElement(fromByteArrayPartial(record, i));
            }
        }
You may ask why I'm mixing RecordStore class with RecordEnumeration interface. RecordStore has no safe and simple way to iterate through stored records and RecordEnumeration has no direct way to retrieve records beside using nextRecord() and previousRecord() methods that would require extra iteration operation forward and backward to collect record ID and then retrieve data, because there is no direct way to retrieve record ID and the data at same time. So RecordEnumeration assures that there is still a record to be read and it will get me the record ID. Then the ID is used to get data in byte array form.

As you can see from above images I decided to go little fancy and beside showing first phone number, the application tells the user what type of number it is. I extended fromByteArrayPartial() method to this form.
    private ContactListLabel fromByteArrayPartial(byte[] data, int i) throws IOException {
        ContactListLabel contactListLabel;
        ByteArrayInputStream bays = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bays);

        String name = dis.readUTF();
        String type = dis.readUTF();
        String number = dis.readUTF();
        contactListLabel = new ContactListLabel(i, name, type, number);
        dis.close();
        return contactListLabel;
    }
From the code you can see a new object ContactListLabel has been introduced, that is based on a set of setter and getter methods plus sorting function, which you can see bellow.
    public Vector sortContacts(Vector v) {
	   for(int i = 0; i < v.size() - 1; i++) {
		   ContactListLabel cll = (ContactListLabel)v.elementAt(i);
		   for(int y = i + 1; y < v.size(); y++){
			   ContactListLabel cll2 = (ContactListLabel)v.elementAt(y);
			   if(cll.getNameLabel().toLowerCase().compareTo(cll2.getNameLabel().toLowerCase())> 0){
				   v.setElementAt(cll2,i);
                   ContactListLabel temp = (ContactListLabel)v.elementAt(y);
				   v.setElementAt(cll,y);
                   cll = temp;
			   }
		   }
	   }
	   return v;
	}
Thank you, goes to masijade for helping me to simplify original sorting algorithm of doubled size. Never forget KISS rule (Keep It Simple Stupid).

This concludes my original intention of improving my "fancy" ContactList application as a school assignment. I believe that supplied source code at the end can be good starting point for other functional additions to this application, to make it even more interesting. For myself, I would like to extend contact details option, provide a way to associate image with a contact and maybe see how this application can be done with use of LWUIT (on java.net, Shai's Java & LWUIT Blog or developer.com - Introducing a Lightweight UI Toolkit: Bringing Desktop Development into Java ME).

Download finished source code of Contact List application here.

Categories : Java, Snippets, Tips, JME

Export this post as PDF document  Export this post to PDF document

Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!



Add a comment Send a TrackBack