-RhinoのCollection対応方法
まったくMaya固有の内容ではないので、明日つかえるトリビアかな。。。まずはWrapFactoryのオーバーライド。型をみてラッパーを選択するだけの内容です。
public class MayaWrapFactory extends WrapFactory { public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType) { if(javaObject instanceof Map) { return new NativeJavaMap(scope, (Map)javaObject); } return super.wrapAsJavaObject(cx, scope, javaObject, staticType); } }
そして、Mapをラップするオブジェクト。
public class NativeJavaMap extends NativeJavaObject {
private static final long serialVersionUID = -3987211835989098780L;
private Map _map;
public NativeJavaMap(Scriptable scope, Map map) {
super(scope, map, Map.class);
if(map == null) {
throw new IllegalArgumentException();
}
_map = map;
}
public boolean has(String name, Scriptable start) {
if(_map.containsKey(name)) {
return true;
}
return super.has(name, start);
}
public Object get(String name, Scriptable start) {
if(_map.containsKey(name)) {
return _map.get(name);
}
return super.get(name, start);
}
public void put(String name, Scriptable start, Object value) {
_map.put(name, value);
}
public Object getIds() {
Set set = new HashSet(_map.keySet());
Object ids = super.getIds();
for(int i = 0; i < ids.length; i++) {
Object name = ids[i];
if(set.contains(name) == false) {
continue;
}
set.add(name);
}
return set.toArray(new Object[set.size()]);
}
public String getClassName() {
return "javaMap";
}
}
以下は、テストコード。
public class NativeJavaMapTest extends TestCase { public void testGet() { Context cx = Context.enter(); cx.setWrapFactory(new MayaWrapFactory()); Scriptable scope = cx.initStandardObjects(); Map map = new HashMap(); Object obj = Context.javaToJS(map, scope); ScriptableObject.putProperty(scope, "map", obj); map.put("testKey", "testValue"); Object obj = _cx.evaluateString(scope, "map.testKey", null, 0, null); String s = (String)JavaAdapter.convertResult(obj, String.class); assertEquals("testValue", s); Context.exit(); } }