Unofficial
"CLDC 1.1
+ MIDP 2.0"
API Reference.
(日本語版)

パッケージ javax.microedition.rms

Mobile Information Devie Profile は、永続的にデータを格納し、それをその後検索するためのメカニズムを MIDlet に提供します。

参照先:
          説明

インタフェースの概要
RecordComparator このインタフェースは、どれがそれらに一致するか、それらの相対的なソートの序列位置を確かめるために2つのレコードを(実装が定義した方法にて)比較するコンパレータを定義します。
RecordEnumeration レコード・ストアの中のレコードを双方向に移動可能な RecordEnumeration を定義するインタフェースです。
RecordFilter そのレコードが、アプリケーションが定義した判定基準にマッチしているか否かをチェックするフィルタを定義するインタフェースです。
RecordListener レコード・ストアにレコードが追加/変更/削除された際のイベントを受け取るリスナーを定義するインタフェースです。
 

クラスの概要
RecordStore レコード・ストアを表すクラスです。
 

例外の概要
InvalidRecordIDException レコード ID が無効なため、オペレーションを完了することができなかった場合に throw される例外です。
RecordStoreException レコード・ストアの操作において一般的な例外が発生したことを示す例外クラスです。
RecordStoreFullException システム・ストレージ(システムの記憶装置)が足りないため、レコード・ストアに対する操作を完了することができなかったことを示す例外クラスです。
RecordStoreNotFoundException 対象となるレコード・ストアを見つけることができなかったため、操作を完了できなかったことを示す例外クラスです。
RecordStoreNotOpenException クローズされたレコード・ストアに対して操作を行おうとしたことを示す例外クラスです。
 

パッケージ javax.microedition.rms の説明

Mobile Information Devie Profile は、永続的にデータを格納し、それをその後検索するためのメカニズムを MIDlet に提供します。 この永続的な記録メカニズムはシンプルなレコード志向のデータベースに倣って設計されており、レコード管理システムと呼びます。

永続的なストレージ

MIDlet がデータを持続して保存し、後でそれを検索できるメカニズムを MIDP は提供します。 レコード管理システム(RMS)と呼ばれる、この永続的なストレージ・メカニズムは、簡単なレコード指向のデータベースに倣います。

レコード・ストア

レコード・ストアは MIDlet の複数回の呼び出し(実行)にまたがって永続的に残るレコードのコレクションから成ります。 プラットフォームは、リブート、バッテリーの交換などを含むプラットフォームの正常な使用の範囲において、MIDlet のレコード・ストアを完全に維持するように最大限の努力をします。

レコード・ストアは MIDlet に露出しない、プラットフォームに依存する場所に作成されます。 レコード・ストアのための名前空間は MIDlet スイートの粒度で制御されます。 MIDlet スイート中の MIDlet は、異なる名前を提供し、それらがそれぞれである限り(固有である限り)、複数のレコード・ストアを作成できます。 また、プラットフォームから MIDlet スイートを削除するとき、MIDlet に関連している全てのレコード・ストアも削除されなければなりません。 MIDlet スイート中の MIDlet は、直接お互いのレコード・ストアにアクセスできます。 MIDP 2.0 の新しい API はレコード・ストアを作成する MIDlet が、そのような許可を与えることを明確に選択するのであれば、レコード・ストアの共有を可能にします。

共有は別の MIDlet スイートにおいてレコード・ストアを命名する能力を通して2つの MIDlet スイートの認証に関する利用規則(アクセシビリティ規則)を定義することで行います。

レコード・ストアは MIDlet スイートのユニークな名前にレコード・ストアの名前を加えた唯一の名前を使用します。 MIDlet スイートはアプリケーション・ディスクリプタの MIDlet-VendorMIDlet-Name 属性によって特定します。

共有すべきレコード・ストアが作成されるとき、アクセス制御を定義します。 レコード・ストアが開かれるとき、アクセス制御が実施されます。 アクセス・モードは、全ての他の MIDlet スイートによる使用あるいは共有を可能にします。

レコード・ストア名は、大文字と小文字とを区別する最大 32 個の Unicode 文字の任意の組み合わせから成ります。 レコード・ストア名は該当する MIDlet スイートの範囲内でユニークでなければなりません。 換言すれば、MIDlet スイート中の MIDlet は同じ名前で1つ以上のレコード・ストアを作成することは出来ません。 しかしながら、MIDlet スイートの1つの MIDlet は、別の MIDlet スイートの MIDlet として同じ名前のレコード・ストアを持つことができます。 このような場合、レコード・ストアはそれぞれ異なり、別々です。

この API はロッキング操作を全く提供しません。 レコード・ストアの実装は、全ての独自のレコード・ストアの操作が不可分(atomic)で、同期(synchronous)しており、連続的であり(serialized =受付順に処理することを意味する)、多重アクセスが発生しないことを保証します。 しかしながら、MIDlet がレコード・ストアにアクセスするために複数のスレッドを用いるなら、このアクセスを調整するのは MIDlet の責任であり、これを行わなかった場合、予期せぬ結果を生じるかもしれません。 例えば、MIDlet の2つのスレッドが同時に同じ記録を元に RecordStore.setRecord() を呼び出すと、レコード・ストアはこれらの呼び出しを連続的に処理します。そして、その結果データベースに不正は全く発生しません。 しかしながら、書き込みの1つが次に、もう片方によって上書きされるでしょう。これは MIDlet の中で問題を発生させるかもしれません。 同様に、プラットフォームがレコード・ストアの透過的な同期を実行する場合、プラットフォームの責任において MIDlet と同期化エンジンとの間のレコード・ストアに対する排他的なアクセスを実施しなければなりません。

このレコード・ストアは System.currentTimeMillis() メソッドによって返される日時情報を表す long 型の値を使用します。レコード・ストアは前回内容が修正された時刻を記録するためにこの値を使用します。 また、レコード・ストアはバージョンを保持しています。バージョンはレコード・ストアの内容を変更する操作のたびにインクリメントされる整数です。 これらは、同期エンジンで使用する際にも役立ちます。

レコード

レコードは byte 配列です。 開発者は、配列の中および byte 配列から異なるデータ・タイプのパックおよびアンパックするために ByteArrayInputStream および ByteArrayOutputStream と同様に DataInputStream および DataOutputStream を使用できます。

レコードは特定のレコード・ストアの中において、それらの recordId によって唯一特定されます。その recordId は整数値です。 この recordId は記録の主キー(プライマリー・キー)として使用します。 レコード・ストアの作成済みの先頭レコードは 1 と等しい recordId を持ちます。そして、それぞれその後の recordId はシンプルに1ずつインクリメントします。 例えば、2つのレコードがレコード・ストアに追加されて、1番目が 'n'recordId を持つとすると、次は (n + 1)recordId となります。 MIDlet は、RecordEnumeration クラス(さかき注:実際はインタフェースです)を使用することで、他のインデックス・リストを作成できます。

例:

これは、ゲームにおいてハイスコアを格納し、検索するためにレコード管理システムを使用する例です。 この例では、ハイスコアを別々のレコードに蓄積し、RecordEnumeration を使用してソートを行います。


import javax.microedition.rms.*;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;

/**
 * ゲームのスコアを蓄積し表示するクラスです。
 */
public class RMSGameScores
    implements RecordFilter, RecordComparator
{
    /*
     * ゲームのスコアを蓄積するために使用するレコード・ストアです。
     */
    private RecordStore recordStore = null;

    /*
     * プレイヤーの名前でフィルタリングする際に使用します。
     */
    public static String playerNameFilter = null;

    /*
     * RecordFilter インタフェースの一部です。
     */
    public boolean matches(byte[] candidate)
        throws IllegalArgumentException
    {
        // もしフィルターが設定されていなければ一致する項目はありません。
        if (this.playerNameFilter == null) {
            return false;
        }

        ByteArrayInputStream bais = new ByteArrayInputStream(candidate);
        DataInputStream inputStream = new DataInputStream(bais);
        String name = null;
        
        try {
            int score = inputStream.readInt();
            name = inputStream.readUTF();
        }
        catch (EOFException eofe) {
            System.out.println(eofe);
            eofe.printStackTrace();
        }
        catch (IOException eofe) {
            System.out.println(eofe);
            eofe.printStackTrace();
        }
        return (this.playerNameFilter.equals(name));
    }

    /*
     * RecordComparator インタフェースの一部です。
     */
    public int compare(byte[] rec1, byte[] rec2)
    {
        // レコードからスコアを取り出すための DataInputStream を構築します。
        ByteArrayInputStream bais1 = new ByteArrayInputStream(rec1);
        DataInputStream inputStream1 = new DataInputStream(bais1);
        ByteArrayInputStream bais2 = new ByteArrayInputStream(rec2);
        DataInputStream inputStream2 = new DataInputStream(bais2);
        int score1 = 0;
        int score2 = 0;
        try {
            // スコアを取り出します。
            score1 = inputStream1.readInt();
            score2 = inputStream2.readInt();
        }
        catch (EOFException eofe) {
            System.out.println(eofe);
            eofe.printStackTrace();
        }
        catch (IOException eofe) {
            System.out.println(eofe);
            eofe.printStackTrace();
        }

        // スコアをソートします。
        if (score1 < score2) {
            return RecordComparator.PRECEDES;
        }
        else if (score1 > score2) {
            return RecordComparator.FOLLOWS;
        }
        else {
            return RecordComparator.EQUIVALENT;
        }
    }

    /**
     * コンストラクタは必要に応じてレコード・ストアを作成あるいはオープンします。
     */
    public RMSGameScores()
    {
        //
        // 新しいレコード・ストアをこの例のために作成します。
        //
        try {
            recordStore = RecordStore.openRecordStore("scores", true);
        }
        catch (RecordStoreException rse) {
            System.out.println(rse);
            rse.printStackTrace();
        }
    }

    /**
     * 新しいレコード・ストアをストレージに追加します。
     *
     * @param score 保存するスコア。
     * @param playerName このスコアを出したプレイヤーの名前。
     */
    public void addScore(int score, String playerName)
    {
        //
        // 各スコアはスコア、プレイヤーの名前の順番に個別のレコードに格納します。
        //
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream outputStream = new DataOutputStream(baos);
        try {
            // スコアを byte 配列にして格納します。
            outputStream.writeInt(score);
            // 次にプレイヤーの名前を格納します。
            outputStream.writeUTF(playerName);
        }
        catch (IOException ioe) {
            System.out.println(ioe);
            ioe.printStackTrace();
        }

        // byte 配列を取り出します。
        byte[] b = baos.toByteArray();
        // これをレコード・ストアに追加します。
        try {
            recordStore.addRecord(b, 0, b.length);
        }
        catch (RecordStoreException rse) {
            System.out.println(rse);
            rse.printStackTrace();
        }
    }

    /**
     * printScores メソッドのためのヘルパーメソッドです。
     */
    private void printScoresHelper(RecordEnumeration re)
    {
        try {
            while(re.hasNextElement()) {
                int id = re.nextRecordIndex();
                ByteArrayInputStream bais = new ByteArrayInputStream(recordStore.getRecord(id));
                DataInputStream inputStream = new DataInputStream(bais);
                try {
                    int score = inputStream.readInt();
                    String playerName = inputStream.readUTF();
                    System.out.println(playerName + " = " + score);
                }
                catch (EOFException eofe) {
                    System.out.println(eofe);
                    eofe.printStackTrace();
                }
            }
        }
        catch (RecordStoreException rse) {
            System.out.println(rse);
            rse.printStackTrace();
        }
        catch (IOException ioe) {
            System.out.println(ioe);
            ioe.printStackTrace();
        }
    }

    /**
     * このメソッドはゲームのスコアをスコア順にソートして全て表示します。
     */
    public void printScores()
    {
        try {
            // ゲームのスコアを実装したコンパレータを使用してソートを行い、
            // レコードを列挙します。
            RecordEnumeration re = recordStore.enumerateRecords(null, this, 
                                                                true);
            printScoresHelper(re);
        }
        catch (RecordStoreException rse) {
            System.out.println(rse);
            rse.printStackTrace();
        }
    }

    /**
     * 指定されたプレイヤーの名前のゲームのスコアをソートして全て表示します。
     */
    public void printScores(String playerName)
    {
        try {
            // ゲームのスコアを実装したコンパレータおよびフィルターを使用してソートを行い、
            // レコードを列挙します。
            RecordEnumeration re = recordStore.enumerateRecords(this, this, 
                                                                true);
            printScoresHelper(re);
        }
        catch (RecordStoreException rse) {
            System.out.println(rse);
            rse.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        RMSGameScores rmsgs = new RMSGameScores();
        rmsgs.addScore(100, "Alice");
        rmsgs.addScore(120, "Bill");
        rmsgs.addScore(80, "Candice");
        rmsgs.addScore(40, "Dean");
        rmsgs.addScore(200, "Ethel");
        rmsgs.addScore(110, "Farnsworth");
        rmsgs.addScore(220, "Farnsworth");
        System.out.println("All scores");
        rmsgs.printScores();
        System.out.println("Farnsworth's scores");
        RMSGameScores.playerNameFilter = "Farnsworth";
        rmsgs.printScores("Farnsworth");
    }
}
導入されたバージョン:
MIDP 1.0


Unofficial
"CLDC 1.1
+ MIDP 2.0"
API Reference.
(日本語版)

公式仕様書原文の著作権表記等(※):

Mobile Information Device Profile Specification ("Specification")
Version: 2.0
Status: FCS
Release: November 5, 2002

Copyright 2002 Sun Microsystems, Inc. and Motorola, Inc.
All rights reserved.
※ただしこの API リファレンスは英語仕様を一語一句正確に翻訳したものではなく、一度私が英語の仕様原文を読んだ上で元の意味と構造をなるべく保つように書き起こしたものです。このため一部は完全に異なる説明となっています。また CLDC 1.1 部分は同仕様の範囲外であるため、まったく参考とはしていません。

※仕様書のライセンス上、問題は無いと考えておりますが、万が一問題があるとお考えの関係者の方がいらっしゃいましたらメールにて連絡をいただけると幸いに存じます(第一言語に日本語、第二言語に英語を希望しますが、返信は基本的に日本語で行います)。

この API リファレンスは仕様書の日本語版という位置づけでは作成していませんし、仕様書ほど厳格でもありません。MUST、SHOULD、MAY などの仕様の条件を強調する文を維持していません(反映すらしていない個所もあります)。仮想マシンおよび MIDP の実装のために使用することは避けてください。そのような用途には必ず公式仕様書原文そのものを用いるべきです。
この API リファレンスに記載されている内容は"さかきけい"が Sun Microsystems, Inc や Motorola, Inc、Java Community Process が公開している各種公式資料を元に、独自に調査・編集したものであり、Sun Microsystems, Inc や Motorola, Inc、Java Community Process 等とは一切関係ありません。したがってこの API リファレンスに関する問い合わせを関係各社等に対して行うことを固く禁じます。
また、記載された内容には既知か否かに関らず誤りが含まれる可能性があり、一切保証はありません。本 API リファレンスを使用した結果、不利益が生じたとしても"さかきけい"は一切の責任を負いません。
許可無く公開/非公開および Internet/Intranet/LAN を問わず他サイトに転載すること、複写および複製すること、ローカル・ファイル等に保存することを禁じます。


Copyright© 2001-2002,2005-2009,2011 by KEI SAKAKI.
ALL RIGHTS RESERVED.
無断転載を禁じます。

Unofficial "CLDC 1.0 + MIDP 1.0" API Reference はこちらです。