SwingのJTableでActiveObjectsのエンティティ編集をするための予習

SwingのJTableを使ってActiveObjectsのエンティティを表示・編集できるようにしようと思っています。
JTableはStringなどいくつかのデータ型をデフォルトで編集できるようになっています。しかし、デフォルトですべてのデータ型が編集可能ではないと思います。デフォルトで編集できないデータ型を編集するためには独自の編集クラスを用意する必要があります。
そこで、JTableがデフォルトでどのようなデータ型を編集できるのかを調べてみました。

調べるデータ型

今回は、ActiveObjectsのエンティティの編集が目的なので、AcitveObjectsが取り扱うデータ型のみが対象です。
以前にd:id:nattou_curry_2:20081118:1227017604で書いた「DatabaseTypeとJavaの型の対応表」を基にすると、以下のデータ型が調査対象になりそうです。

  • Boolean
  • java.util.Calendar
  • Character
  • java.util.Date
  • Double
  • Enum
  • Float
  • Integer
  • Long
  • Object
  • RawEntity(※除外)
  • Short
  • String
  • java.net.URI
  • java.net.URL

このうちRawEntityはActiveObjects特有のインタフェースで、JTableによるデフォルトの編集は意味がないため今回の対象からは除外します。残りの14種類のデータ型を調査対象とします。

検証用のテーブルモデル

JTable上に1行14列のデータを用意します。各列が14種類の調査対象データ型のデータを持つようにテーブルモデルを作成します。行は一行だけで十分です。
以下が、実際に作成したテーブルモデルです。最も重要な箇所は、getColumnClass()メソッドです。このメソッドで各列に対応するデータ型(Class型インスタンス)を返しています。

import java.util.*;
import java.net.*;
import javax.swing.table.*;

public class AOTypeTableModel extends AbstractTableModel {
	
	/**
	 * 行の数を取得する。
	 */
	@Override
	public int getRowCount() {
		return 1;
	}

	/**
	 * 列の数を取得する。
	 */
	@Override
	public int getColumnCount() {
		return 14;
	}

	/**
	 * 指定したセルが編集可能であることを確認する。
	 */
	@Override
	public boolean isCellEditable(int row, int col) {
		return true;
	}

	/**
	 * 指定した列の名前を取得する。
	 */
	@Override
	public String getColumnName(int col) {
		switch ( col ) {
			case 0:
				return "Boolean";
			case 1:
				return "Calendar";
			case 2:			
				return "Character";
			case 3:
				return "Date";
			case 4:
				return "Double";
			case 5:
				return "Enum";
			case 6:
				return "Float";
			case 7:
				return "Integer";
			case 8:
				return "Long";
			case 9:
				return "Object";
			case 10:
				return "Short";
			case 11:
				return "String";
			case 12:
				return "URI";
			case 13:
				return "URL";
		}
		return "";
	}

	/**
	 * 指定した列の型を取得する。
	 */
	@Override
	public Class getColumnClass(int c) {
		switch ( c ) {
		case 0:
			return Boolean.class;
		case 1:
			return Calendar.class;
		case 2:			
			return Character.class;
		case 3:
			return Date.class;
		case 4:
			return Double.class;
		case 5:
			return Enum.class;
		case 6:
			return Float.class;
		case 7:
			return Integer.class;
		case 8:
			return Long.class;
		case 9:
			return Object.class;
		case 10:
			return Short.class;
		case 11:
			return String.class;
		case 12:
			return URI.class;
		case 13:
			return URL.class;
		}
		return null;
	}
	
	/**
	 * 指定したセルの値を取得する。
	 */
	@Override
	public Object getValueAt(int row, int column) {
		switch ( column ) {
		case 0:
			return Boolean.TRUE;
		case 1:
			return new GregorianCalendar();
		case 2:			
			return new Character( 'A' );
		case 3:
			return new Date();
		case 4:
			return new Double( 1.323313244322 );
		case 5:
			return Thread.State.NEW;
		case 6:
			return new Float( 1.323332 );
		case 7:
			return new Integer( 20 );
		case 8:
			return new Long( 320432432432L );
		case 9:
			return new Object();
		case 10:
			return new Short( (short) 3 );
		case 11:
			return "aaaa";
		case 12:
			try {
				return new URI( "http://java.sun.com/j2se/1.3/" );
			} catch ( URISyntaxException e ) {
				throw new RuntimeException( e );
			}
		case 13:
			try {
				return new URL( "http://java.sun.com/index.html" );
			} catch ( MalformedURLException e ) {
				throw new RuntimeException( e );
			}
		}
		return null;
	}
}

検証用プログラムを動かす

上記のテーブルモデル使用するテーブルを持つプログラムを作成しました。以下のような画面になります。

各列が今回対象のデータ型のデータを表示しているのがわかります。テーブルの各列のデータをダブルクリックすることで編集できればその列のデータ型は「編集可能」、編集できなければ「編集不能」と判断します。

結果

以下のような結果になりました。

デフォルトで編集可能なデータ型
  • java.util.Date
  • Double
  • Float
  • Integer
  • Long
  • Object
  • Short
  • String
  • java.net.URI
  • java.net.URL
デフォルトで編集不能なデータ型
  • Boolean
  • java.util.Calendar
  • Character
  • Enum

結果について補足

  • java.util.Date型は編集できるけれど、少し挙動がおかしいです。というのも、「2008/12/20」と表示されているjava.util.Date型のセルをダブルクリックすると、編集状態になるとともに「Sat Dec 20 14:39:13 JST 2008」という表示に変わりました。しかし、そのまま編集結果を確定すると入力エラーとなるのです。しかし、「2008/12/21」と編集しなおすと問題なく編集確定できました。
  • Object型はtoString()の結果を文字列として編集しているだけのように見えます。ほとんど意味がないですね。
  • Boolean型が編集できないことに違和感を覚えました。チェックボックス表示で明らかに編集できそうだからです。なにか、考慮漏れがあるのでしょうか・・・?
  • java.util.Calendar型はそもそもきちんと表示できてないです。

まとめ

ActiveObjectsのエンティティをJTableで編集可能にするには以下のデータ型の編集について注意が必要そうです。

データ型 理由
Object デフォルトの編集が意味なし
java.util.Date デフォルトの編集の挙動が不審
Boolean デフォルト編集不可
java.util.Calendar デフォルト編集不可
Character デフォルト編集不可
Enum デフォルト編集不可
RawEntity そもそもどう扱うか考慮が必要

以上でした。