of 10
8/20/2019 SMI Filtering and Searching Records in RMS Draft
1/23
Filtering
and
Searching
Records
in
RMS.
Version
0.4,
Draft
INFO
8/20/2019 SMI Filtering and Searching Records in RMS Draft
2/23
Filtering and Searching in RMS
2
COPYRIGHT
Samsung Electronics Co. Ltd.
This material is copyrighted by Samsung Electronics. Any unauthorized reproductions,
use or disclosure of this material, or any part thereof, is strictly prohibited and is a
violation under the Copyright Law. Samsung Electronics reserves the right to make
changes in specifications at any time and without notice. The information furnished by
Samsung Electronics in this material is believed to be accurate and reliable, but is not
warranted true in all cases.
Trademarks and Service Marks
The Samsung Logo is the trademark of Samsung Electronics. Java is the trademark of
Sun Microsystems.
All other company and product names may be trademarks of the respective companieswith which they are associated.
8/20/2019 SMI Filtering and Searching Records in RMS Draft
3/23
Filtering and Searching in RMS
3
About This Document
The Java ME Record Management System (RMS) provides a mechanism through which
MIDlets can insert records, read records, search for particular records and sort records
stored by the RMS. Earlier Java ME Record Management System document explains
about RMS and its basic operation. This document explains about advanced RMS
operations like traversing (filtering), searching and sorting records in RMS.
Scope
This document is intended for MIDP developers wishing to develop mobile applications
using Record Management System (RMS). It assumes good knowledge of java
programming language. This document focuses on RMS and therefore explaining the
Java technology is out of the scope in this documentation.
To know more about Java ME basics and Java programming language, refer to the
Knowledge Base under Samsung Mobile Innovator (SMI).
http://innovator.samsungmobile.com/platform.main.do?platformId=3
http://innovator.samsungmobile.com/cms/cnts/knowledge.detail.view.do?platformId=3&cntsId=6320http://innovator.samsungmobile.com/platform.main.do?platformId=3http://innovator.samsungmobile.com/platform.main.do?platformId=3http://innovator.samsungmobile.com/platform.main.do?platformId=3http://innovator.samsungmobile.com/cms/cnts/knowledge.detail.view.do?platformId=3&cntsId=6320
8/20/2019 SMI Filtering and Searching Records in RMS Draft
4/23
Filtering and Searching in RMS
4
Table of Contents
Introduction .......................................................................................................... 5
Traversing a Record ............................................................................................. 5
Enumerating Records ........................................................................................... 6
Traversing in an Enumeration .............................................................................. 8
1. Moving Forward. ............................................................................................ 8
2. Moving Backward........................................................................................... 9
Filtering a Record ............................................................................................... 10
Sorting a Record ................................................................................................. 10
Sample Example................................................................................................. 12
Class: RMSMIDlet............................................................................................ 12
Class: RMSForm............................................................................................... 13
Class: RMSFilter............................................................................................... 22
Class: RMSComparator .................................................................................... 23
8/20/2019 SMI Filtering and Searching Records in RMS Draft
5/23
Filtering and Searching in RMS
5
Introduction
In the first released RMS document, we have learned what RMS is all about and its basic
operations. We learned how to open, create, and delete RecordStore. We also learned
about adding, retrieving and deleting Records to and from RecordStore. Apart from these
basic operations there are situations where you want to navigate through the records,
sort out records, and filter records to get the wanted data. We will learn on how these
operations can be achieved.
Traversing a Record
Whenever a Record is added in the RecordStore, RMS returns an index. This index is an
integer positive value starting from 1 and it keeps on growing whenever a new Record is
added in RecordStore.
Similarly whenever we delete a Record from a RecordStore, we cannot use the deleted
record index again. Using the same index again for adding or modifying would result in
an InvalidRecordIDException.
So how to do we traverse Records in RecordStore, since accessing deleted index would
throw InvalidRecordIDException
There are two ways for traversing through the Records.
1. Loop through the records skipping invalid index. Here you need to use try catch
statement for catching InvalidRecordIDException as shown in the below code
snippet. This looping is time consuming if the Records are huge.
8/20/2019 SMI Filtering and Searching Records in RMS Draft
6/23
Filtering and Searching in RMS
6
...
try {
RecordStore rs = RecordStore.openRecordStore("RecordName", true);
for( int i = 1; i < rs.getNumRecords(); i++ ) {
try {
byte[] data = rs.getRecord( i );
... // process the data
} catch( InvalidRecordIDException e ){
// just ignore and move to the next record
}
} catch( RecordStoreException e ){
// a more general error that should be handled somehow
}
}
...
2. Another way to traverse through the Records is through the use of Enumeration.
Enumerating Records
RMS provides an enumerateRecords method in RecordStore class for traversing through
the Records. enumerateRecords method returns an enumeration of valid records (valid
indexes) for traversing using RecordEnumeration interface.
So instead of looping through the records and skipping invalid records, we can tell RMS
to give an enumeration of valid records.
public RecordEnumeration enumerateRecords(RecordFilter filter,
RecordComparator comparator,
boolean keepUpdated)
throws RecordStoreNotOpenException
8/20/2019 SMI Filtering and Searching Records in RMS Draft
7/23
Filtering and Searching in RMS
7
You can traverse the records either way either ways i.e. forward or backward. You can
always get an updated enumeration of Records (track changes to the records as they
occur).
RecordEnumeration takes three parameters for returning the enumeration.
The First parameter is RecordFilter which can be used to determine what subset of the
RecordStore Records will be used. We will learn in detail about RecordFilter later.
Second parameter is RecordComparator which can be used to determine the order in
which the records are returned. We will learn in detail about RecordComparator later.
Third parameter is boolean value which when:
true: the enumerator will keep its enumeration current with any changes in the records
of the record store. Tracking changes requires extra overhead. So use it with caution as
there are possible performance consequences.
false: the enumeration will not be kept current and may return recordIds for records
that have been deleted or miss records that are added later.
...
RecordStore rs = RecordStore.openRecordStore("RecordName", true);
RecordEnumeration enum = rs.enumerateRecords( null, null, false );
... // use the enumeration here
enum.destroy(); // always clean it up!
Since RecordEnumeration can keep track of the latest changes in RecordStore, it may
use system resources, so it always better to call destroy() after your work is done.
destroy() frees internal resources used by RecordEnumeration.
8/20/2019 SMI Filtering and Searching Records in RMS Draft
8/23
Filtering and Searching in RMS
8
Traversing in an Enumeration
As already mentioned you can traverse the records either ways i.e. forward or backward.
1. Moving Forward.
RecordEnumeration interface has three methods for moving forward while traversing
through the Records.
hasNextElement() - Returns true if more elements exist in the next direction.
nextRecordId() - Returns the recordId of the next record in this enumeration. After
calling this method, the enumeration is advanced to the next available record.
nextRecord() - Returns a copy of the next record in this enumeration. Any changes
made to this array will NOT be reflected in the record store. After calling this
method, the enumeration is advanced to the next available record.
...
RecordStore rs = RecordStore.openRecordStore("RecordName", true);
RecordEnumeration enum = rs.enumerateRecords( null, null, false );
try {
while( enum.hasNextElement() ){
int id = enum.nextRecordId();
byte[] data = rs.getRecord( id );
OR
byte[] data = enum.nextRecord();
... // do something here
}} catch( RecordStoreException e ){
// handle the error here
}
...
8/20/2019 SMI Filtering and Searching Records in RMS Draft
9/23
Filtering and Searching in RMS
9
2. Moving Backward.
RecordEnumeration interface has three methods for moving backward while
traversing through the Records.
hasPreviousElement() - Returns true if more elements exist in the previous
direction.
previousRecordId() - Returns the recordId of the previous record in this
enumeration. After calling this method, the enumeration is advanced to the previous
available record.
previousRecord () - Returns a copy of the previous record in this enumeration. Any
changes made to this array will NOT be reflected in the record store. After calling this
method, the enumeration is advanced to the previous available record.
...
RecordStore rs = RecordStore.openRecordStore("RecordName", true);
RecordEnumeration enum = rs.enumerateRecords( null, null, false );
try {
while( enum. hasPreviousElement () ){
int id = enum. previousRecordId ();
byte[] data = rs.getRecord( id );
OR
byte[] data = enum. previousRecord ();
... // do something here
}
} catch( RecordStoreException e ){
// handle the error here
}
...
8/20/2019 SMI Filtering and Searching Records in RMS Draft
10/23
Filtering and Searching in RMS
10
Filtering a Record
If you are interested in only a subset of the record, then you need to use RecordFilter
interface. With this you can skip unwanted records by applying a filter (RecordFilter
object).
RecordFilter has a matches(byte[] candidate) method that filters out the data and
decides whether a record is to be included in the enumeration or not. matches(byte[]
candidate) takes byte array data of the other record for matching. This interface is
used in the RecordStore for searching or sub setting records.
public class MyFilter implements RecordFilter {
public boolean matches( byte[] recordData ){... // matching code here
}
}
RecordStore enumerateRecords() method takes RecordFilter has the first parameter.
...
enum = rs.enumerateRecords( new MyFilter(), null, false );
...
Sorting a Record
RecordStore enumerateRecords() method returns enumeration of records in unordered
manner. So to get the records in a predictable order, we need to use the
RecordComparator interface.
RecordComparator has compare(byte[] rec1, byte[] rec2) methods that compares
two records to see if they match or what their relative sort order is. The return value
indicates the ordering of the two records. The return value can be one of the following:
EQUIVALENT: means that in terms of search or sort order, the two records are the
same.
8/20/2019 SMI Filtering and Searching Records in RMS Draft
11/23
Filtering and Searching in RMS
11
FOLLOWS: means that the left (first parameter) record follows the right (second
parameter) record in terms of search or sort order.
PRECEDES: means that the left (first parameter) record precedes the right (secondparameter) record in terms of search or sort order.
If you are interested in only a subset of the record, then you need to use RecordFilter
interface. With this you can skip unwanted records by applying a filter (RecordFilter
object).
public class MyComparator implements RecordComparator {
public int compare( byte[] r1, byte[] r2 ){
int salary1 = getSalary( r1 );
int salary2 = getSalary( r2 );
if( salary1 < salary2 ){
return PRECEDES;
} else if( salary1 == salary2 ){
return EQUIVALENT;
} else {
return FOLLOWS;
}
}
private int getSalary( byte[] data ){
... // code to get salary info
}
}
RecordStore enumerateRecords() method takes RecordComparator has the secondparameter.
...
enum = rs.enumerateRecords( null, new MyComparator(), false );
...
8/20/2019 SMI Filtering and Searching Records in RMS Draft
12/23
Filtering and Searching in RMS
12
Sample Example
The example below demonstrates RecordFilter, RecordComparator interface usage.
Class: RMSMIDlet
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.*;
public class RMSMIDlet extends MIDlet {
private RMSForm rmsForm;
public Display display;
public void startApp() {
display = Display.getDisplay(this);
rmsForm = new RMSForm(this);
display.setCurrent(rmsForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
}
8/20/2019 SMI Filtering and Searching Records in RMS Draft
13/23
Filtering and Searching in RMS
13
Class: RMSForm
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.rms.RecordStoreNotOpenException;
public class RMSForm extends Form implements CommandListener{
private Command addRecordCommand = new Command("Add Record",
Command.ITEM, 1);
private Command findRecordCommand = new Command("Filter Record",
Command.ITEM, 1);
private Command sortRecordCommand = new Command("Sort Record",
Command.ITEM, 1);
private Command selectCommand = new Command("Select", Command.OK, 1);
private Command backCommand = new Command("Back", Command.BACK, 2);
8/20/2019 SMI Filtering and Searching Records in RMS Draft
14/23
Filtering and Searching in RMS
14
private Command exitCommand = new Command("Exit", Command.EXIT, 1);
private RMSMIDlet midlet;
private RecordStore recordStore;
private TextField studentNameTextField;
private ChoiceGroup studentDepartmentChoiceGroup, sortOrderChoiceGroup;
private final String department[] = {"Science", "Arts", "Commerce"};
public static final String sortOrder[] = {"Ascending", "Descending"};
private final String recordStoreName = "rmsexample";
private boolean isFilterScreen;
public RMSForm(RMSMIDlet midlet)
{
super("Traversing, Sorting, Searching");
this.midlet = midlet;
studentNameTextField = new TextField("Enter Student Name", null, 1024,
TextField.ANY);
studentDepartmentChoiceGroup = new ChoiceGroup("Select Department",
Choice.EXCLUSIVE, department, null);
sortOrderChoiceGroup = new ChoiceGroup("Select Order", Choice.EXCLUSIVE,
sortOrder, null);
setCommandListener(this);
showRecordScreen();
}
private void openRecordStore()
{
try {
recordStore = RecordStore.openRecordStore(recordStoreName, true);
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
8/20/2019 SMI Filtering and Searching Records in RMS Draft
15/23
Filtering and Searching in RMS
15
}
private void closeRecordStore()
{
try {
recordStore.closeRecordStore();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
private void removeAllCommands()
{
removeCommand(exitCommand);
removeCommand(addRecordCommand);
removeCommand(findRecordCommand);
removeCommand(sortRecordCommand);
removeCommand(backCommand);
removeCommand(selectCommand);
}
private void showRecordScreen()
{
deleteAll();
removeAllCommands();
studentNameTextField.setString(null);
addCommand(exitCommand);
addCommand(addRecordCommand);
addCommand(findRecordCommand);
addCommand(sortRecordCommand);
setTitle("Add Record");
append(studentNameTextField);
append(studentDepartmentChoiceGroup);
setCommandListener(this);
}
8/20/2019 SMI Filtering and Searching Records in RMS Draft
16/23
Filtering and Searching in RMS
16
private void showSortRecordScreen()
{
deleteAll();
removeAllCommands();
setTitle("Select Sort Order");
append(sortOrderChoiceGroup);
addCommand(backCommand);
addCommand(selectCommand);
setCommandListener(this);
isFilterScreen = false;
}
private void showFilterRecordScreen()
{
deleteAll();
removeAllCommands();
setTitle("Select Filter");
append(studentDepartmentChoiceGroup);
addCommand(backCommand);
addCommand(selectCommand);
setCommandListener(this);
isFilterScreen = true;
}
private void doRecordFilter(String filterString)
{
try {
openRecordStore();
if(recordStore.getNumRecords()>0)
{
RMSFilter filter = new RMSFilter(filterString);
RecordEnumeration recEnum = recordStore.enumerateRecords(filter,
null, true);
if( recEnum.numRecords()>0 )
{
deleteAll();
8/20/2019 SMI Filtering and Searching Records in RMS Draft
17/23
Filtering and Searching in RMS
17
removeAllCommands();
while(recEnum.hasNextElement())
{
try {
byte[] filterRecordData = recEnum.nextRecord();
ByteArrayInputStream bis = new
ByteArrayInputStream(filterRecordData);
DataInputStream dis = new DataInputStream(bis);
String studentName = dis.readUTF();
readUTF();String studentDept = dis.
StringItem stringItem = new StringItem("Student Information",
"\nName: "+studentName+"\nDepartment: "+studentDept+"\n");
append(stringItem);
} catch (IOException ex) {
ex.printStackTrace();
} catch (InvalidRecordIDException ex) {
ex.printStackTrace();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
addCommand(backCommand);
setCommandListener(this);
}else
{
Alert alert = new Alert("Error");
alert.setString("No Record Exists.\nPlease select another filter");
alert.setTimeout(Alert.FOREVER);
midlet.display.setCurrent(alert);
}
}
else
{
Alert alert = new Alert("Error");
8/20/2019 SMI Filtering and Searching Records in RMS Draft
18/23
Filtering and Searching in RMS
18
alert.setString("No Record Exists.\nPlease Add record");
alert.setTimeout(Alert.FOREVER);
midlet.display.setCurrent(alert);
}
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
}
}
private void doRecordSorting(String sortingString)
{
try {
openRecordStore();
if(recordStore.getNumRecords()>0)
{
RMSComparator comparator = new RMSComparator(sortingString);
RecordEnumeration recEnum = recordStore.enumerateRecords(null,
comparator, true);
if( recEnum.numRecords()>0 )
{
deleteAll();
removeAllCommands();
while(recEnum.hasNextElement())
{
try {
byte[] filterRecordData = recEnum.nextRecord();
ByteArrayInputStream bis = new
ByteArrayInputStream(filterRecordData);
DataInputStream dis = new DataInputStream(bis);
String studentName = dis.readUTF();
String studentDept = di ();s.readUTF
StringItem stringItem = new StringItem("Student Information",
"\nName: "+studentName+"\nDepartment: "+studentDept+"\n");
append(stringItem);
} catch (IOException ex) {
ex.printStackTrace();
8/20/2019 SMI Filtering and Searching Records in RMS Draft
19/23
Filtering and Searching in RMS
19
} catch (InvalidRecordIDException ex) {
ex.printStackTrace();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
addCommand(backCommand);
setCommandListener(this);
}else
{
Alert alert = new Alert("Error");
alert.setString("No Record Exists.\nPlease select another filter");
alert.setTimeout(Alert.FOREVER);
midlet.display.setCurrent(alert);
}
}else
{
Alert alert = new Alert("Error");
alert.setString("No Record Exists.\nPlease Add record");
alert.setTimeout(Alert.FOREVER);
midlet.display.setCurrent(alert);
}
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
}
}
private void addRecord(String data, int studentDeptIndex)
{
try {
openRecordStore();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeUTF(data);
8/20/2019 SMI Filtering and Searching Records in RMS Draft
20/23
Filtering and Searching in RMS
20
dos.writeUTF(department[studentDeptIndex]);
byte[] recordData = baos.toByteArray();
int addedIndex =recordStore.addRecord(recordData, 0, recordData.length);
dos.close();
baos.close();
closeRecordStore();
} catch (IOException ex) {
ex.printStackTrace();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
public void commandAction(Command c, Displayable d) {
if(c == exitCommand)
midlet.destroyApp(true);
else
if(c == addRecordCommand)
{
String data = studentNameTextField.getString();
int choiceIndex = studentDepartmentChoiceGroup.getSelectedIndex();
if(data == null || data.length()
8/20/2019 SMI Filtering and Searching Records in RMS Draft
21/23
Filtering and Searching in RMS
21
{ showFilterRecordScreen(); }
else
if(c == sortRecordCommand)
{ showSortRecordScreen(); }
else
if(c == selectCommand)
{
if(isFilterScreen)
{
int filterIndex = studentDepartmentChoiceGroup.getSelectedIndex();
doRecordFilter(department[filterIndex]);
}else
{
int sortIndex = sortOrderChoiceGroup.getSelectedIndex();
doRecordSorting(sortOrder[sortIndex]);
}
}else
if(c == backCommand)
{
System.out.println("backCommand isFilterScreen "+isFilterScreen);
showRecordScreen();
}
}
}
Class: RMSFilter
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import javax.microedition.rms.RecordFilter;
public class RMSFilter implements RecordFilter{
8/20/2019 SMI Filtering and Searching Records in RMS Draft
22/23
Filtering and Searching in RMS
22
private String filterString;
public RMSFilter(String filterString)
{ this.filterString = filterString; }
public boolean matches(byte[] candidate) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(candidate);
DataInputStream dis = new DataInputStream(bis);
String studentName = dis.readUTF();
String studentDept = dis.readUTF();
if (filterString.equals(studentDept)) {
return true;
}
return false;
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
}
lass: RMSComparatorC
import javax.microedition.rms.RecordComparator;
public class RMSComparator implements RecordComparator{
private String sortingOrder;
public RMSComparator(String sortingOrder)
{ this.sortingOrder = sortingOrder; }
8/20/2019 SMI Filtering and Searching Records in RMS Draft
23/23
Filtering and Searching in RMS
public int compare(byte[] rec1, byte[] rec2) {
String str1 = new String(rec1);
String str2 = new String(rec2);
int result = str1.compareTo(str2);
if (result == 0){
return RecordComparator.EQUIVALENT;
} else if (result < 0){
if(sortingOrder.equals("Ascending"))
return RecordComparator.FOLLOWS;
else
return RecordComparator.PRECEDES;
} else {
if(sortingOrder.equals("Ascending"))
return RecordComparator.PRECEDES;
else
return RecordComparator.FOLLOWS;
}
}
}