Oct. 15, 2009, 3:48 p.m.
posted by barateon
Manipulating Record Stores and RecordsRecord stores have two basic types of operations: those that deal with manipulating the record store as a whole and those that deal with manipulating the records within the record store. A summary of different record store and record manipulation operations is provided in the following sections. 14.2.1 Manipulating a Record StoreThe programmer accesses record stores by name. These names are case-sensitive and may contain between 1 and 32 Unicode characters. The name space for record stores is a flat, non-hierarchical space.[1]
Within a MIDlet suite, record store names are unique. In other words, MIDlets within a MIDlet suite are not allowed to create more than one record store with the same name. On the other hand, no such restriction applies to different MIDlet suites: a MIDlet within one MIDlet suite is allowed to have a record store with the same name as a MIDlet in another MIDlet suite. In that case, the record stores are distinct and separate. A MIDlet can obtain a list of all the record stores owned by the containing MIDlet suite by calling the class static method listRecordStores of class RecordStore. In order to access a record store, the record store must be opened first. A MIDlet can open one of its record stores with the method openRecordStore that takes two parameters: a String containing the name of the record store, and a boolean indicating whether the record store should be created if it does not exist yet. The method openRecordStore returns an object of type RecordStore, which provides access to the following methods that return information about the associated record store:
The two final operations on a record store are closing and deleting it. A record store is closed by invoking the method closeRecordStore. Note that a record store is not closed until all outstanding opens have been matched with a corresponding close operation. In other words, as long as there are open references to a record store, it will not be closed. When a record store is finally closed, all record listeners are removed (see Section 14.2.5, "Filtering, Comparing, Listening, and Enumerating Records"), and any attempts to perform any operations on the record store object cause a RecordStoreNotOpenException to be thrown. A record store is deleted by passing its name as a String to the static method deleteRecordStore of class RecordStore. A record store must be closed before it can be deleted. 2 Shared Record Stores
To create a shared record store, the MIDlet calls the openRecordStore method, which takes four parameters:
Sharing is accomplished through the ability to name a record store created by another MIDlet suite. That is, record stores are identified using the unique name of the MIDlet suite plus the name of the record store. MIDlet suites are identified by the MIDlet-Vendor and MIDlet-Name attributes from the manifest and/or application descriptor (see Section 19.1.3, "MIDlet Attributes"). To open a shared record store from another MIDlet suite, the MIDlet calls the openRecordStore method that takes three String parameters: the name of the record store, and the vendor name and MIDlet suite name of the MIDlet suite that created the shared record store. As described in Section 19.3.2, "MIDlet Suite Removal," when a MIDlet suite is deleted all of its record stores are also removed. This includes any shared record stores that it owns. 14.2.3 Manipulating Records in a Record StoreWithin a record store, individual records can be added, retrieved, modified, and deleted. The most common methods for manipulating records are summarized below:
14.2.4 Converting Record Data to and from Byte ArraysBefore data can be saved into a record store, it must be converted into an array of bytes. Using CLDC classes such as DataInputStream, DataOutputStream, ByteArrayInputStream, or ByteArrayOutputStream, developers can pack and unpack different data types into and out of byte arrays. As an example, consider a game MIDlet that needs to record scores and names of players. The code fragment below illustrates how such a record (byte array) might be created: ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(baos); // Add the score (an int) then the name of the player (a UTF) // to the DataOutputStream. outputStream.writeInt(score); outputStream.writeUTF(name); // Now, extract the byte array (record) byte[] theRecord = baos.toByteArray(); Once the record has been created, it can be inserted into a record store using the addRecord operation introduced in Section 14.2.3, "Manipulating Records in a Record Store." 14.2.5 Filtering, Comparing, Listening, and Enumerating RecordsThe records of a record store may be processed in various ways. To provide programmer-defined ways to filter, search, and sort a record store, RMS provides the four Java interfaces discussed below. The RecordFilter interfaceThe RecordFilter interface allows the programmer to define filters for searching records. This interface requires the programmer to supply a method called matches that accepts one record as a parameter. This method returns a boolean indicating whether or not the given record matches the user-defined search criteria. For instance, consider the following example in which a record store contains different types of records, with the type being indicated by the first byte. In this example, Integer records are indicated by the first byte being 'I'. The following filter returns true if the candidate record is an Integer record:
public class IntegerFilter implements RecordFilter {
public boolean matches(byte[] candidate)
throws IllegalArgumentException {
return candidate[0] == 'I';
}
}
The RecordComparator interfaceThe RecordComparator interface allows the programmer to define comparison operations for records. This interface defines the method compare that takes two records as parameters. This method returns one of the following class-static values from the RecordComparator class:
To carry forth the previous example, let's assume that the Integer records discussed above have the format of a record type indicator (in this case: 'I') followed by a four-byte Integer. Furthermore, let's assume that we want to sort the records in ascending order according to value of the four-byte Integer field. A record comparator to accomplish this could be written as follows (with error checking omitted):
class IntegerCompare implements RecordComparator {
public int compare(byte[] b1, byte[] b2) {
DataInputStream is1 = new DataInputStream(
new ByteArrayInputStream(b1));
DataInputStream is2 = new DataInputStream(
new ByteArrayInputStream(b2));
/**
* Skip record type (1 byte), then read ints
*/
is1.skip(1);
is2.skip(1);
int i1 = is1.readInt();
int i2 = is2.readInt();
if (i1 > i2) return RecordComparator.FOLLOWS;
if (i1 < i2) return RecordComparator.PRECEDES;
return RecordComparator.EQUIVALENT;
}
}
The RecordListener interfaceIn order to monitor the addition and modifications of records to a record store, RMS provides the RecordListener interface. This interface defines three methods that a class must implement. Each method takes two parameters: a RecordStore and a recordID:
The following code fragment shows a simple record listener that prints out a line indicating what type of operation is being done to a record store:
/**
* Add the listener to the record store
*/
recordStore.addRecordListener((RecordListener) new myListener());
...
public class myListener implements RecordListener {
final private static int ADDED = 1;
final private static int CHANGED = 2;
final private static int DELETED = 3;
private void handleCall(int type, RecordStore rs, int rid) {
System.out.print("Record store " + rs.getName() +
" and record id " + rid +
" was ");
switch (type) {
case myListener.ADDED:
System.out.println("added");
break;
case myListener.CHANGED:
System.out.println("changed");
break;
case myListener.DELETED:
System.out.println("deleted");
break;
}
}
public void recordAdded(RecordStore rs, int rid) {
handleCall(myListener.ADDED, rs, rid);
}
public void recordChanged(RecordStore rs, int rid) {
handleCall(myListener.CHANGED, rs, rid);
}
public void recordDeleted(RecordStore rs, int rid) {
handleCall(myListener.DELETED, rs, rid);
}
}
The RecordEnumerator interfaceThe final interface provided by RMS is the RecordEnumeration interface. A class implementing this interface provides a mechanism to enumerate over all the records in the record store. Although a developer can implement this interface, the most common usage of record enumeration is simply using the enumerateRecords provided by the RecordStore class. The enumerateRecords method returns an instance of a class that implements the RecordEnumeration interface. It takes three parameters: a RecordComparator, a RecordFilter, and a boolean that indicates that the returned enumerator should register itself as a listener in order to keep it updated with ongoing activity on the record store. The most efficient way to get each record in a record store is to supply neither a RecordComparator nor a RecordFilter:
simpleRE = recordStore.enumerateRecords(null, null, false);
while (re.hasNextElement()) {
byte b[] = re.nextRecord();
...
}
This example would return, in an undefined order, every record in the record store while ignoring changes made to the record store by other MIDlets or threads. A more complex example is enumerating through a subset of records in the record store and sorting them in a user-defined manner. Using our previous examples of the RecordComparator and the RecordFilter, we can construct a record enumerator that only returns the records containing Integer numbers in numerically ascending order with the following code fragment:
IntegerFilter iFilt = new IntegerFilter();
IntCompare iCompare = new IntegerCompare();
intRE = recordStore.enumerateRecords((RecordFilter)iFilt,
(RecordComparator)iCompare,
false);
while (IntRE.hasNextElement()) {
byte b[] = re.nextRecord();
...
}
Suppose that our record store had two types of records: Integer and String, with the String records starting with an 'S' and the Integer records beginning with an 'I'. If our record store contained the following records: Record 1: 'I', 100 Record 2: 'S', "Joy" Record 3: 'I', 50 Record 4: 'S', "Zachary" Record 5: 'S', "Abby" Record 6: 'I', 25 then the enumeration returned by intRE would be Record 6, Record 3, then Record 1. |
- Comment