Hashtable Interface to MIDP RecordStore
来源:互联网 发布:高中知识软件下载 编辑:程序博客网 时间:2024/06/03 13:09
The javax.microedition.rms package provides the Record Management System (RMS) implementation. It is a kind of DBMS, but its API doesnot resemble JDBC or any of other J2SE APIs. The primary concept of RMS is the RecordStore. The RecordStore element is the Record, and Record's essence is a byte array.
I have created a special adaptor to the RMS. It doesnot cover all the RMS capabilities but allows us to use RMS as a backend for a Map-like object structure. There is no java.util.Map interface in MIDP, so our "RecordMap" adapter uses java.util.Hashtable as a pattern. Even more, it extends java.util.Hashtable. It is a pure interface inheritance, all the methods are overridden in our RecordMap.
Our RecordMap is configurable in that it can be parameterized with different implementations of our own EntryMapper interface to provide the concrete functionality of the data mapping between Hashtable key-value pairs and RecordStore byte arrays.
package j2mefancier;
public interface EntryMapper {
byte[] bytes(Object key, Object value);
Object key(byte[] bytes);
Object value(byte[] bytes);
}
Then, here is a couple of small utility classes used by our RecordMap:
package j2mefancier;
import java.util.*;
import javax.microedition.rms.*;
public class EnumAdapter implements Enumeration {
private RecordEnumeration re;
private EntryMapper mapper;
private boolean isKey;
public EnumAdapter(RecordStore rs, EntryMapper mapper, boolean isKey) throws RecordStoreException {
this.re = rs.enumerateRecords(null, null, false);
this.mapper = mapper;
this.isKey = isKey;
}
public boolean hasMoreElements() {
return re.hasNextElement();
}
public Object nextElement() {
try {
byte[] bytes = re.nextRecord();
return isKey ? mapper.key(bytes) : mapper.value(bytes);
} catch (RecordStoreException e) {
return null;
}
}
}
package j2mefancier;
import javax.microedition.rms.*;
public class Filter implements RecordFilter {
private Object obj;
private EntryMapper mapper;
private boolean isKey;
public Filter(Object obj, EntryMapper mapper, boolean isKey) {
if (obj == null) throw new NullPointerException();
this.obj = obj;
this.mapper = mapper;
this.isKey = isKey;
}
public boolean matches(byte[] candidate) {
return obj.equals(isKey ? mapper.key(candidate) : mapper.value(candidate));
}
}
Now, look at the implementation of the EntryMapper interface I use for own purposes. Note that it allows only String keys and values, so the best use case of this implementation is for RMS backend of Properties-like data. Again, there is no java.util.Properties in MIDP, otherwise I'd prefer to use Properties API instead of Hashtable one. Other use cases require more intelligent entry mappers.
package j2mefancier;
import java.io.*;
public class EntryMapperImpl implements EntryMapper {
public byte[] bytes(Object key, Object value) {
if (! (key instanceof String) || ! (value instanceof String))
throw new IllegalArgumentException();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeUTF(key.toString());
dos.writeUTF(value.toString());
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
return baos.toByteArray();
}
public Object key(byte[] bytes) {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
try {
return dis.readUTF();
} catch (IOException e) {
return null;
}
}
public Object value(byte[] bytes) {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
try {
dis.readUTF();
return dis.readUTF();
} catch (IOException e) {
return null;
}
}
}
And here is the heart of the thing: the RecordMap class. I don't insist on its implementation optimality etc., the main purpose is to demonstrate the idea. Probably you can develop more efficient implementations for some use cases and also add more clever exception handling. The usual Hashtable toString() functionality is omitted to keep the code more compact.
package j2mefancier;
import java.util.*;
import javax.microedition.rms.*;
public class RecordMap extends Hashtable {
private RecordStore rs;
private EntryMapper mapper;
public RecordMap(RecordStore rs, EntryMapper mapper) {
this.rs = rs;
this.mapper = mapper;
}
public void clear() {
try {
RecordEnumeration re = rs.enumerateRecords(null, null, false);
while (re.hasNextElement()) rs.deleteRecord(re.nextRecordId());
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public boolean contains(Object value) {
try {
RecordEnumeration re = rs.enumerateRecords(new Filter(value, mapper, false), null, false);
return re.hasNextElement();
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public boolean containsKey(Object key) {
return get(key) != null;
}
public Enumeration elements() {
try {
return new EnumAdapter(rs, mapper, false);
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public Object get(Object key) {
try {
RecordEnumeration re = rs.enumerateRecords(new Filter(key, mapper, true), null, false);
if (re.hasNextElement()) return mapper.value(re.nextRecord());
return null;
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public boolean isEmpty() {
return size() == 0;
}
public Enumeration keys() {
try {
return new EnumAdapter(rs, mapper, true);
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public Object put(Object key, Object value) {
if (value == null) throw new NullPointerException();
try {
Object old = remove(key);
byte[] bytes = mapper.bytes(key, value);
rs.addRecord(bytes, 0, bytes.length);
return old;
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public Object remove(Object key) {
try {
RecordEnumeration re = rs.enumerateRecords(new Filter(key, mapper, true), null, false);
if (re.hasNextElement()) {
Object old = mapper.value(re.nextRecord());
rs.deleteRecord(re.previousRecordId());
return old;
}
return null;
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public int size() {
try {
return rs.getNumRecords();
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
public String toString() {
try {
return "RecordMap-" + rs.getName();
} catch (RecordStoreException e) {
throw wrapped(e);
}
}
private RuntimeException wrapped(RecordStoreException e) {
return new RuntimeException(e.getMessage());
}
}
- Hashtable Interface to MIDP RecordStore
- MIDP
- powershell Hashtable to arraylist
- Introduction to C# interface
- DataTemplate Binding to Interface
- interface to load data
- How to use Interface
- nec616 RecordStore 注意事项
- RecordStore中索引探讨
- RecordStore实现访问计数器
- javax.microedition.rms.RecordStore
- Introduction to Message Passing Interface
- Matlab Interface to Generic Dlls
- Databinding to user Interface controls
- How to: Implement Interface Events
- WSDL to Component Interface Faults
- How to use Comparable Interface
- Use interface references to Collections
- VTK的简介和安装(Linux)
- 刚刚激活,使用一下。
- Windows程序内部运行原理 - 孙鑫 - VC++6.0 - Code by SunXin/Remark by HackerJLY
- VTK:读入DICOM,体绘制
- 嵌入式系统发展史上的里程碑
- Hashtable Interface to MIDP RecordStore
- 学习 Linux LVM,第 1 部分
- 防止U盘中毒的简便方法
- 50种强大的CSS技术||struts+spring+hibernate的web应用示例
- 一个数的三次方尾数是888,有什么规律吗?
- mysql笔记
- Java 语法介绍(一):Java语言的基本组成
- 三五个人十来条枪 如何走出软件作坊成为开发正规军 (转贴)
- 修改fish的命令提示符(附:超好用的SHELL——FISH)