Working with the RMS - Part II
by John W. Muchow -11/15/2001
Portions of this article are used with permission from the forthcoming book Core J2ME Technology by John W. Muchow, published by Sun Microsystems Press and Prentice Hall. Copyright 2001 Sun Microsystems Inc.
In the first article of this series, we answered several common questions regarding persistent storage (Record Management System) within MIDP:
- Can record stores be shared among MIDlets?
- Can record id's be re-used?
- How do you use the Enumeration class?
We concluded the previous article with a MIDlet that showed how one might use the Enumeration class to move through records in persistent storage. As an extension of that example, this article will address how to use an enumeration to sort and search records within the record store.
Sorting with RecordComparator
RecordEnumeration is a class that allows forward and backward movement through a record store. Moving through the store requires nothing more than a check to see if there is another record available (in either direction), and if so, requesting its data.
RecordStore rs;
...
RecordEnumeration re = rs.enumerateRecords(null, null, false);
while (re.hasNextElement())
{
String str = new String(re.nextRecord());
System.out.println("Record: " + str);
}
RecordComparator is a Java interface. You implement this interface when you would like the enumeration to return records in sorted order. There is only one method in the RecordComparator interface, compare(). This method is called by the enumeration to create the (sorted) result set. Here is a simple class that implements the interface.
public class Comparator implements RecordComparator
{
public int compare(byte[] rec1, byte[] rec2)
{
String str1 = new String(rec1), str2 = new String(rec2);
int result = str1.compareTo(str2);
if (result == 0)
return RecordComparator.EQUIVALENT;
else if (result < 0)
return RecordComparator.PRECEDES;
else
return RecordComparator.FOLLOWS;
}
}
When exiting the compare() method, you must return one of the three pre-defined return values. The following code block shows how you might use the Comparator class with an enumeration.
RecordStore rs;
...
// Create a new comparator for sorting
Comparator comp = new Comparator();
// Reference the comparator when creating the result set
RecordEnumeration re = rs.enumerateRecords(null, comp, false);
// Move through the sorted results
while (re.hasNextElement())
{
String str = new String(re.nextRecord());
...
}
Example: Simple String Sort
The following example uses the Comparator class shown above to sort the contents of a record store. Figure 1 shows the sorted records as returned from the enumeration. Example 1: SimpleSort.java /*--------------------------------------------------
* SimpleSort.java
*
* No GUI interface, all output is to the console
*-------------------------------------------------*/
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
public class SimpleSort extends MIDlet
{
private RecordStore rs = null;
static final String REC_STORE = "db_1";
public SimpleSort()
{
openRecStore(); // Create the record store
// Write a few records
writeRecord("Sand Wedge");
writeRecord("One Wood");
writeRecord("Putter");
writeRecord("Five Iron");
// Read back with enumerator, sorting the results
readRecords();
closeRecStore(); // Close record store
deleteRecStore(); // Remove the record store
}
public void destroyApp( boolean unconditional )
{
}
public void startApp()
{
// There is no user interface, go ahead and shutdown
destroyApp(false);
notifyDestroyed();
}
public void pauseApp()
{
}
public void openRecStore()
{
try
{
// Create record store if it does not exist
rs = RecordStore.openRecordStore(REC_STORE, true );
}
catch (Exception e)
{
db(e.toString());
}
}
public void closeRecStore()
{
try
{
rs.closeRecordStore();
}
catch (Exception e)
{
db(e.toString());
}
}
public void deleteRecStore()
{
if (RecordStore.listRecordStores() != null)
{
try
{
RecordStore.deleteRecordStore(REC_STORE);
}
catch (Exception e)
{
db(e.toString());
}
}
}
public void writeRecord(String str)
{
byte[] rec = str.getBytes();
try
{
rs.addRecord(rec, 0, rec.length);
}
catch (Exception e)
{
db(e.toString());
}
}
public void readRecords()
{
try
{
if (rs.getNumRecords() > 0)
{
Comparator comp = new Comparator();
RecordEnumeration re = rs.enumerateRecords(null, comp, false);
while (re.hasNextElement())
{
String str = new String(re.nextRecord());
System.out.println(str);
System.out.println("------------------------------");
}
}
}
catch (Exception e)
{
db(e.toString());
}
}
/*--------------------------------------------------
* Simple message to console for debug/errors
*-------------------------------------------------*/
private void db(String str)
{
System.err.println("Msg: " + str);
}
}
/*--------------------------------------------------
| Comparator.java
|
| Compares two records to determine sort order
*-------------------------------------------------*/
class Comparator implements RecordComparator
{
public int compare(byte[] rec1, byte[] rec2)
{
String str1 = new String(rec1), str2 = new String(rec2);
int result = str1.compareTo(str2);
if (result == 0)
return RecordComparator.EQUIVALENT;
else if (result < 0)
return RecordComparator.PRECEDES;
else
return RecordComparator.FOLLOWS;
}
}
 Figure 1: Sorted records using an Enumerator with RecordComparator
Searching with RecordFilter
In addition to sorting records, an enumeration can filter (search) records using the RecordFilter interface.
class SearchFilter implements RecordFilter
{
private String searchText = null;
public SearchFilter(String searchText)
{
// This is the text to search for
this.searchText = searchText.toLowerCase();
}
public boolean matches(byte[] candidate)
{
String str = new String(candidate).toLowerCase();
// Look for a match
if (searchText != null && str.indexOf(searchText) != -1)
return true;
else
return false;
}
}
There is one method that must be written when implementing the RecordFilter interface, matches(). For the SearchFilter class shown above, when an instance is created, we save the desired search text in a private variable. This text is then used when the enumeration calls the matches() method, passing in a record from the record store. Here is a small piece of code that shows how you create a reference between the filter and an enumeration.
RecordStore rs;
...
// Create a new search filter
SearchFilter search = new SearchFilter(“search text”);
// Reference the filter when creating the result set
RecordEnumeration re = rs.enumerateRecords(search, null, false);
// If there is at least one record in result set, a match was found
if (re.numRecords() > 0)
// do something here...
|