📄 recordenumerationimpl.java
字号:
/*
* Created on 2004-12-24 by Tianlei
* version 1.0.0.3
* since MIDP1.0
*
* ��ȫ����2.0�����Դ��,����ע�Ͳμ�Դ��
*/
package a.a.a.midp.rms;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordFilter;
import javax.microedition.rms.RecordListener;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreNotOpenException;
/**
* @author Tianlei
* @version 1.0.0.3
* @since MIDP1.0
*
* ��ȫ����2.0�����Դ��,����ע�Ͳμ�Դ��
*/
public class RecordEnumerationImpl implements RecordEnumeration, RecordListener {
/** The associated record store for this enumeration */
private RecordStore recordStore;
/** The record filter this enumeration should use, or null if none */
private RecordFilter filter;
/** The record comparator this enumeration should use, or null if none */
private RecordComparator comparator;
/** True if this should listen to <code>recordStore</code> for changes */
private boolean beObserver; // false by default
/** Current pos within the enumeration */
private int index; // 0 by default
/** Array of recordId's of records included in the enumeration */
private int[] records;
private static final int NO_SUCH_RECORD = -1;
private RecordEnumerationImpl() {
}
public RecordEnumerationImpl(RecordStore recordStore, RecordFilter filter,
RecordComparator comparator, boolean keepUpdated) {
this.recordStore = recordStore;
this.filter = filter;
this.comparator = comparator;
records = new int[0];
keepUpdated(keepUpdated);
if (!keepUpdated) {
rebuild();
}
}
public synchronized int numRecords() {
checkDestroyed();
return records.length;
}
public synchronized byte[] nextRecord() throws InvalidRecordIDException,
RecordStoreNotOpenException, RecordStoreException {
checkDestroyed();
return recordStore.getRecord(nextRecordId());
}
public synchronized int nextRecordId() throws InvalidRecordIDException {
checkDestroyed();
if (index == records.length - 1) {
throw new InvalidRecordIDException();
}
if (index == NO_SUCH_RECORD) {
index = 0;
} else {
index++;
}
return records[index];
}
public synchronized byte[] previousRecord()
throws InvalidRecordIDException, RecordStoreNotOpenException,
RecordStoreException {
checkDestroyed();
return recordStore.getRecord(previousRecordId());
}
public synchronized int previousRecordId() throws InvalidRecordIDException {
checkDestroyed();
if (index == 0 || records.length == 0) {
throw new InvalidRecordIDException();
}
if (index == NO_SUCH_RECORD) {
index = records.length - 1;
} else {
index--;
}
return records[index];
}
public boolean hasNextElement() {
checkDestroyed();
if (recordStore.isOpen() == false) {
return false;
}
return (index != records.length - 1);
}
public boolean hasPreviousElement() {
checkDestroyed();
if (records.length == 0 || recordStore.isOpen() == false) {
return false; // no records in the enumeration
}
return (index != 0);
}
public void reset() {
checkDestroyed();
index = NO_SUCH_RECORD;
}
public void rebuild() {
checkDestroyed();
synchronized (recordStore.rsLock) { // don't want rs to change here
int[] tmp = recordStore.getRecordIDs();
reFilterSort(tmp);
}
}
public void keepUpdated(boolean keepUpdated) {
checkDestroyed();
if (keepUpdated != beObserver) {
beObserver = keepUpdated;
if (keepUpdated) {
recordStore.addRecordListener(this);
rebuild();
} else {
recordStore.removeRecordListener(this);
}
}
}
public boolean isKeptUpdated() {
checkDestroyed();
return beObserver;
}
public synchronized void recordAdded(RecordStore recordStore, int recordId) {
checkDestroyed();
synchronized (recordStore.rsLock) {
filterAdd(recordId);
}
}
public synchronized void recordChanged(RecordStore recordStore, int recordId) {
checkDestroyed();
int recIndex = findIndexOfRecord(recordId);
if (recIndex < 0) {
return; // not in the enumeration
}
removeRecordAtIndex(recIndex);
synchronized (recordStore.rsLock) {
filterAdd(recordId);
}
}
public synchronized void recordDeleted(RecordStore recordStore, int recordId) {
checkDestroyed();
/*
* Remove the deleted element from the records array. No resorting is
* required.
*/
int recIndex = findIndexOfRecord(recordId);
if (recIndex < 0) {
return; // not in the enumeration
}
// remove this record from the enumeration
removeRecordAtIndex(recIndex);
}
public synchronized void destroy() {
checkDestroyed();
if (beObserver == true) {
recordStore.removeRecordListener(this);
}
filter = null;
comparator = null;
records = null;
recordStore = null; // a signal that this is destroyed!
}
private void checkDestroyed() {
if (recordStore == null) {
throw new IllegalStateException();
}
}
private void filterAdd(int recordId) {
int insertPoint = -1;
if (filter != null) {
try {
if (!filter.matches(recordStore.getRecord(recordId))) {
return; // recordId filtered out
}
} catch (RecordStoreException rse) {
return; // recordId does not exist
}
}
// the new record has been accepted by the filter
int[] newrecs = new int[records.length + 1];
newrecs[0] = recordId; // insert new record at front of list
System.arraycopy(records, 0, newrecs, 1, records.length);
records = newrecs;
if (comparator != null) { // move the new record into place
try {
insertPoint = sortInsert();
} catch (RecordStoreException rse) {
// NOTE: - should never be here
// throw a RSE? destroy record enumeration?
System.out.println("Unexpected exception in filterAdd");
}
}
// keep index up to date as well
if (index != NO_SUCH_RECORD && insertPoint != -1 && insertPoint < index) {
index++;
}
}
private int sortInsert() throws RecordStoreException {
// bubble sort the first record in records into place
int tmp;
int i;
int j;
for (i = 0, j = 1; i < records.length - 1; i++, j++) {
if (comparator.compare(recordStore.getRecord(records[i]),
recordStore.getRecord(records[j])) == RecordComparator.FOLLOWS) {
// if i follows j swap them in records
tmp = records[i];
records[i] = records[j];
records[j] = tmp;
} else {
break; // done sorting if compare returns EQUALS or PRECEDES
}
}
return i; // final index of new record in records
}
private int findIndexOfRecord(int recordId) {
int idx;
int recIndex = -1;
for (idx = records.length - 1; idx >= 0; idx--) {
if (records[idx] == recordId) {
recIndex = idx;
break;
}
}
return recIndex;
}
private void removeRecordAtIndex(int recIndex) {
int[] tmp = new int[records.length - 1];
if (recIndex < records.length) {
System.arraycopy(records, 0, tmp, 0, recIndex);
System.arraycopy(records, recIndex + 1, tmp, recIndex,
(records.length - recIndex) - 1);
} else {
System.arraycopy(records, 0, tmp, 0, records.length - 1);
}
records = tmp;
/*
* If a record prior to current index was deleted update index so
* nothing is skipped
*/
if (index != NO_SUCH_RECORD && recIndex < index) {
index--;
} else if (index == records.length) {
// last element in records removed
index--;
}
}
private void reFilterSort(int[] filtered) {
int filteredIndex = 0;
if (filter == null) {
/*
* If this enumeration doesn't have any filters, the recordId's
* returned by getRecordIDs should be used as they are.
*/
records = filtered;
} else {
/*
* If a filter has been specified, filter the recordStore records to
* determine the subset to be used for this enumeration.
*/
for (int i = 0; i < filtered.length; i++) {
// if this record matches the filter keep it
try {
if (filter.matches(recordStore.getRecord(filtered[i]))) {
// not sure if element overlap is allowed
if (filteredIndex != i) {
filtered[filteredIndex++] = filtered[i];
} else {
filteredIndex++;
}
}
} catch (RecordStoreException rse) {
// if a record can't be found it doesn't match
}
}
records = new int[filteredIndex];
System.arraycopy(filtered, 0, records, 0, filteredIndex);
}
/*
* If a comparator has been specified, sort the remaining records by
* comparing records against each other using the comparator the
* application provides.
*/
if (comparator != null) {
try {
QuickSort(records, 0, records.length - 1, comparator);
} catch (RecordStoreException de) {
// NOTE: - should never be here
// throw a RSE? destroy record enumeration?
System.out.println("Unexpected exception in " + "reFilterSort");
}
}
reset(); // reset the current index of this enumeration
}
private void QuickSort(int a[], int lowIndex, int highIndex,
RecordComparator comparator) throws RecordStoreException {
/*
* A different sorting algorithm may be preferred, because a large
* recursive quicksort can consume lots of stack. Quicksort is very fast
* for most random sequences however...
*/
int left = lowIndex; // the "left" index
int right = highIndex; // the "right" index
/*
* First partition the data into two regions, where every element on the
* left side of the partition is less than every element on the right
* side of the element.
*/
if (highIndex > lowIndex) {
/*
* Arbitrarily choose the initial pivot point to be the middle of
* the array.
*/
int ind = (lowIndex + highIndex) / 2;
int pivotIndex = a[ind];
byte[] pivotData = recordStore.getRecord(pivotIndex);
// loop through the array until the indices cross
while (left <= right) {
/*
* Starting on the left, scan right until the first element
* greater than or equal to the pivot element is found.
*/
while ((left < highIndex)
&& (comparator.compare(recordStore.getRecord(a[left]),
pivotData) == RecordComparator.PRECEDES)) {
left++;
}
/*
* Starting on the right, scan left until the first element that
* is less than or equal to the pivot element is found.
*/
while ((right > lowIndex)
&& (comparator.compare(recordStore.getRecord(a[right]),
pivotData) == RecordComparator.FOLLOWS)) {
right--;
}
// if the indexes haven't crossed, swap the elements
if (left <= right) {
int tmp = a[left];
a[left] = a[right];
a[right] = tmp;
left++;
right--;
}
}
// Sort the left side of the partition
if (lowIndex < right) {
QuickSort(a, lowIndex, right, comparator);
}
// Sort the right side of the partition
if (left < highIndex) {
QuickSort(a, left, highIndex, comparator);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -