001: package freemarker.ext.rhino;
002:
003: import org.mozilla.javascript.EvaluatorException;
004: import org.mozilla.javascript.Function;
005: import org.mozilla.javascript.NativeJavaObject;
006: import org.mozilla.javascript.Scriptable;
007: import org.mozilla.javascript.ScriptableObject;
008:
009: import freemarker.ext.beans.BeansWrapper;
010: import freemarker.ext.util.ModelFactory;
011: import freemarker.template.AdapterTemplateModel;
012: import freemarker.template.ObjectWrapper;
013: import freemarker.template.TemplateCollectionModel;
014: import freemarker.template.TemplateHashModelEx;
015: import freemarker.template.TemplateModel;
016: import freemarker.template.TemplateModelException;
017: import freemarker.template.TemplateSequenceModel;
018:
019: /**
020: * <p><font color="red">Experimental: no backward compatibility guarantees</font>;
021: * any feedback is highly welcome!</p>
022: *
023: * @author Attila Szegedi
024: * @version $Id: RhinoScriptableModel.java,v 1.4 2005/06/22 10:52:52 ddekany Exp $
025: */
026: public class RhinoScriptableModel implements TemplateHashModelEx,
027: TemplateSequenceModel, AdapterTemplateModel {
028: static final ModelFactory FACTORY = new ModelFactory() {
029: public TemplateModel create(Object object, ObjectWrapper wrapper) {
030: return new RhinoScriptableModel((Scriptable) object,
031: (BeansWrapper) wrapper);
032: }
033: };
034:
035: private final Scriptable scriptable;
036: private final BeansWrapper wrapper;
037:
038: public RhinoScriptableModel(Scriptable scriptable,
039: BeansWrapper wrapper) {
040: this .scriptable = scriptable;
041: this .wrapper = wrapper;
042: }
043:
044: public TemplateModel get(String key) throws TemplateModelException {
045: Object retval = ScriptableObject.getProperty(scriptable, key);
046: if (retval instanceof Function) {
047: return new RhinoFunctionModel((Function) retval,
048: scriptable, wrapper);
049: } else {
050: return wrapper.wrap(retval);
051: }
052: }
053:
054: public TemplateModel get(int index) throws TemplateModelException {
055: Object retval = ScriptableObject.getProperty(scriptable, index);
056: if (retval instanceof Function) {
057: return new RhinoFunctionModel((Function) retval,
058: scriptable, wrapper);
059: } else {
060: return wrapper.wrap(retval);
061: }
062: }
063:
064: public boolean isEmpty() {
065: return scriptable.getIds().length == 0;
066: }
067:
068: public TemplateCollectionModel keys() throws TemplateModelException {
069: return (TemplateCollectionModel) wrapper.wrap(scriptable
070: .getIds());
071: }
072:
073: public int size() {
074: return scriptable.getIds().length;
075: }
076:
077: public TemplateCollectionModel values()
078: throws TemplateModelException {
079: Object[] ids = scriptable.getIds();
080: Object[] values = new Object[ids.length];
081: for (int i = 0; i < values.length; i++) {
082: Object id = ids[i];
083: if (id instanceof Number) {
084: values[i] = ScriptableObject.getProperty(scriptable,
085: ((Number) id).intValue());
086: } else {
087: values[i] = ScriptableObject.getProperty(scriptable,
088: String.valueOf(id));
089: }
090: }
091: return (TemplateCollectionModel) wrapper.wrap(values);
092: }
093:
094: Scriptable getScriptable() {
095: return scriptable;
096: }
097:
098: BeansWrapper getWrapper() {
099: return wrapper;
100: }
101:
102: public Object getAdaptedObject(Class hint) {
103: try {
104: return NativeJavaObject.coerceType(hint, scriptable);
105: } catch (EvaluatorException e) {
106: return NativeJavaObject
107: .coerceType(Object.class, scriptable);
108: }
109: }
110: }
|