« November 2009
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     
       
Today
XML

Blog::Navigation

GetJava Download Button
Get the Source
Personal Blog

Blog::Referers

Today's Page Hits: 1144

Powered by Roller Weblogger.
« Half empty or half... | Main | Retrieving .class... »
20070324 Saturday March 24, 2007

Script Beans - part 2

This is continuation of my earlier post on script beans. On rethinking, I've made few (minor) changes to ScriptObject and Callable. The changes are:



ScriptObject

import javax.script.ScriptException;

/**
 * Any Java object supporting this interface can be
 * accessed from scripts with "simpler" access pattern.
 * For example, a script engine may support natural
 * property/field access syntax for the properties exposed
 * via this interface. We use this interface so that we
 * can dynamically add/delete/modify fields exposed to
 * scripts. Also, script engines may expose this interface for
 * it's own objects.
 */
public interface ScriptObject {
  // special value to denote no-result -- so that
  // null could be used as proper result value
  public static final Object UNDEFINED = new Object();
  // empty object array
  public static final Object[] EMPTY_ARRAY = new Object[0];

  /*
   * Returns all property names supported by this object.
   * Property "name" is either a String or an Integer".
   */
  public Object[] getIds();

  /**
   * Get the value of the named property.
   */
  public Object get(String name);

  /**
   * Get the value of the "indexed" property. 
   * Returns UNDEFINED if the property does not exist.
   */
  public Object get(int index);

  /**
   * Set the value of the named property. Returns
   * whether the put was successful or not.
   */
  public boolean put(String name, Object value);

  /**
   * Set the value of the indexed property. Returns
   * whether the put was successful or not.
   */
  public boolean put(int index, Object value);

  /**
   * Returns whether the named property exists or not.
   */
  public boolean has(String name);

  /**
   * Returns whether the indexed property exists or not.
   */
  public boolean has(int index);

  /**
   * Deletes the named property. Returns true on success.
   */
  public boolean delete(String name);

  /**
   * Deletes the indexed property. Returns true on success.
   */
  public boolean delete(int index);

  /**
   * Call the named method on this script object.
   */
  public Object invoke(String name, Object... arguments)
      throws NoSuchMethodException, ScriptException;
}



Callable.java

import javax.script.ScriptException;

/**
 * This interface is used to represent "function/method" valued
 * properties in ScriptObjects.
 */
public interface Callable {
  /**
   * Call the underlying function passing the given
   * arguments and return the result.
   */
  public Object call(Object... args) throws ScriptException;
}



AbstractScriptObject.java

import javax.script.ScriptException;

/**
 * Simple dummy implementation of ScriptObject.
 */
public abstract class AbstractScriptObject 
  implements ScriptObject {

  public Object[] getIds() {
    return EMPTY_ARRAY;
  }    

  public Object get(String name) {
    return UNDEFINED;
  }

  public Object get(int index) {
    return UNDEFINED;
  }

  public boolean put(String name, Object value) {
    return false;
  }

  public boolean put(int index, Object value) {
    return false;
  }

  public boolean has(String name) {
    return false;
  }

  public boolean has(int index) {
    return false;
  }

  public boolean delete(String name) {
    return false;
  }

  public boolean delete(int index) {
    return false;
  }

  public Object invoke(String name, Object... arguments) 
    throws NoSuchMethodException, ScriptException {
    Object value =  get(name);
    if (value instanceof Callable) {
      return ((Callable)value).call(arguments);
    } else {
      throw new NoSuchMethodException(name);
    }
  }
}



( Mar 24 2007, 02:12:41 PM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

Comments:

The invoke(...) method can be helpful for interface usability reasons, but I don't see why a MethodMissing kind of feature could not be implemented by having a Callable subclass following the Special Case pattern.

Excellent blog, BTW. I specially liked the Scala summary posts, I'm hoping that they will help to make the language more popular.

Posted by Rafael Ferreira on March 25, 2007 at 02:36 AM IST #

Hi Rafael Ferreira: Yes, I agree that Callable could take care of that case as well. But, as you said, invoke() is easier to work with. And explicit Callable helps in creating and storing "method references" for future call from event handlers/listeners and so on. And thanks for your good words on my blog.

Posted by A. Sundararajan on March 25, 2007 at 12:52 PM IST #

You asked "Also, beanutils API seems to concentrate only on "properties" only. There is nothing mentioned about "methods". (Did I miss anything in BeanUtils API that deals methods?)" There is a simple reason, not all methods are part of the bean. There are getters, setters and maybe listener infrastructure, but that's it. Not all methods do fit here.. especially no overloaded methods. Now for your ScriptObject... this is thought to be used from a script, yes? As for groovy, to support this as it is thought, we need a wrapper around your ScriptObject... which is kind of funny.. because if you have a POJO that you want to use with the ScriptObject, then the language needs to wrap that ScriptObject with a wrapper and so you get access the way you wanted to have this... only, in Groovy, we could have used the POJO directly. Of course you would not get method missing then...

Posted by Jochen "blackdrag" Theodorou on March 26, 2007 at 05:00 PM IST #

Post a Comment:

Comments are closed for this entry.
Copyright (C) 2005, A. Sundararajan's Weblog