/*--------------------------------------------------
* SearchStreams.java
*
* Display a Form and TextField for searching records
* Each record contains multiple Java data types -
* (String, boolean and integer). Use the String
* data for searching
*
* Uses: Enumeration, RecordFilter
*
* Example from the book: Core J2ME Technology
* Copyright John W. Muchow http://www.CoreJ2ME.com
* You may use/modify for any non-commercial purpose
*-------------------------------------------------*/
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
import javax.microedition.lcdui.*;
public class SearchStreams extends MIDlet implements CommandListener
{
private Display display; // Reference to Display object
private Form fmMain; // The main form
private StringItem siMatch; // The matching text, if any
private Command cmFind; // Command to search record store
private Command cmExit; // Command to insert items
private TextField tfFind; // Search text
private RecordStore rs = null; // Record store
static final String REC_STORE = "db_7"; // Name of record store
public SearchStreams()
{
display = Display.getDisplay(this);
// Define textfield, stringItem and commands
tfFind = new TextField("Find", "", 10, TextField.ANY);
siMatch = new StringItem(null, null);
cmExit = new Command("Exit", Command.EXIT, 1);
cmFind = new Command("Find", Command.SCREEN, 2);
// Create the form, add commands
fmMain = new Form("Record Search");
fmMain.addCommand(cmExit);
fmMain.addCommand(cmFind);
// Append textfield and stringItem
fmMain.append(tfFind);
fmMain.append(siMatch);
// Capture events
fmMain.setCommandListener(this);
//--------------------------------
// Open and write to record store
//--------------------------------
openRecStore(); // Create the record store
writeTestData(); // Write a series of records
}
public void destroyApp( boolean unconditional )
{
closeRecStore(); // Close record store
}
public void startApp()
{
display.setCurrent(fmMain);
}
public void pauseApp()
{
}
public void openRecStore()
{
try
{
// The second parameter indicates that the record store
// should be created 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());
}
}
/*--------------------------------------------------
* Create three arrays to write into record store
*-------------------------------------------------*/
public void writeTestData()
{
String[] pets = {"duke - big, goofy golden retriever",
"tiger - we found in a field",
"spike - loves chasing car tires",
"beauregard - barks at everything"};
boolean[] dog = {true, false, true, true};
int[] rank = {3, 0, 1, 2};
writeStream(pets, dog, rank);
}
/*--------------------------------------------------
* Write to record store using streams.
*-------------------------------------------------*/
public void writeStream(String[] sData, boolean[] bData, int[] iData)
{
try
{
// Only add the records once
if (rs.getNumRecords() > 0)
return;
// Write data into an internal byte array
ByteArrayOutputStream strmBytes = new ByteArrayOutputStream();
// Write Java data types into the above byte array
DataOutputStream strmDataType = new DataOutputStream(strmBytes);
byte[] record;
for (int i = 0; i < sData.length; i++)
{
// Write Java data types
strmDataType.writeUTF(sData[i]);
strmDataType.writeBoolean(bData[i]);
strmDataType.writeInt(iData[i]);
// Clear any buffered data
strmDataType.flush();
// Get stream data into byte array and write record
record = strmBytes.toByteArray();
rs.addRecord(record, 0, record.length);
// Toss any data in the internal array so writes
// starts at beginning (of the internal array)
strmBytes.reset();
}
strmBytes.close();
strmDataType.close();
}
catch (Exception e)
{
db(e.toString());
}
}
/*--------------------------------------------------
* Search using enumerator and record filter
*-------------------------------------------------*/
private void searchRecordStore()
{
try
{
// Record store is not empty
if (rs.getNumRecords() > 0)
{
// Setup the search filter with the user requested text
SearchFilter search =
new SearchFilter(tfFind.getString());
RecordEnumeration re =
rs.enumerateRecords(search, null, false);
// A match was found using the filter
if (re.numRecords() > 0)
{
// Read from the specified byte array
ByteArrayInputStream strmBytes =
new ByteArrayInputStream(re.nextRecord());
// Read Java data types from the above byte array
DataInputStream strmDataType =
new DataInputStream(strmBytes);
// Show matching result in stringItem component on form
siMatch.setText(strmDataType.readUTF());
search.searchFilterClose(); // Close record filter
strmBytes.close(); // Close stream
strmDataType.close(); // Close stream
re.destroy(); // Free enumerator
}
}
}
catch (Exception e)
{
db(e.toString());
}
}
public void commandAction(Command c, Displayable s)
{
if (c == cmFind)
{
searchRecordStore();
}
else if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
}
/*--------------------------------------------------
* Simple message to console for debug/errors
* When used with Exceptions we should handle the
* error in a more appropriate manner.
*-------------------------------------------------*/
private void db(String str)
{
System.err.println("Msg: " + str);
}
}
/*--------------------------------------------------
* Search for text within a record
* Each record passed in contains multiple Java data
* types (String, boolean and integer)
*-------------------------------------------------*/
class SearchFilter implements RecordFilter
{
private String searchText = null;
// Read from a specified byte array
private ByteArrayInputStream strmBytes = null;
// Read Java data types from the above byte array
private DataInputStream strmDataType = null;
public SearchFilter(String searchText)
{
// This is the text to search for
this.searchText = searchText.toLowerCase();
}
// Cleanup
public void searchFilterClose()
{
try
{
if (strmBytes != null)
strmBytes.close();
if (strmDataType != null)
strmDataType.close();
}
catch (Exception e)
{}
}
public boolean matches(byte[] candidate)
{
String str = null;
try
{
strmBytes = new ByteArrayInputStream(candidate);
strmDataType = new DataInputStream(strmBytes);
// Although 3 pieces of data were written to
// the record (String, boolean and integer)
// we only need one read because the string to
// search is the first "field" in the record
str = strmDataType.readUTF().toLowerCase();
}
catch (Exception e)
{
return false;
}
// Look for a match
if (str != null && str.indexOf(searchText) != -1)
return true;
else
return false;
}
}
|