Date: 2005-02-22T13:36:15
Editor: JasonBriggs
Wiki: Jakarta-Velocity Wiki
Page: JythonUberspect
URL: http://wiki.apache.org/jakarta-velocity/JythonUberspect
no comment
New Page:
NOTE: this is a work-in-progress.
{{{
/*
* Copyright 2000-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nz.net.briggs.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.log4j.Logger;
import org.apache.velocity.util.introspection.*;
import org.python.core.*;
/**
* a subclass of UberspectImpl that supports dynamic Jython objects. Methods
and
* attributes can therefore be called on a jython object within a velocity
template
* without requiring additional tools (and without resorting to direct method
calls
* against the jython methods (i.e. no __findattr__ in your template)
* @author <a href="mailto:[EMAIL PROTECTED]">Jason R Briggs</a>
*/
public class JythonUberspect extends UberspectImpl
{
private static final Logger log =
Logger.getLogger(JythonUberspect.class.getName());
/**
* support the standard jython iterators (otherwise pass up to UberspectImpl)
* in a velocity #foreach
*/
public Iterator getIterator(Object obj, Info i) throws Exception
{
if (obj instanceof PyArray)
{
PyArray pa = (PyArray)obj;
return new PyIterator(pa, pa.__len__());
}
else if (obj instanceof PyList)
{
PyList pl = (PyList)obj;
return new PyIterator(pl, pl.__len__());
}
else if (obj instanceof PyTuple)
{
PyTuple pt = (PyTuple)obj;
return new PyIterator(pt, pt.__len__());
}
else if (obj instanceof PyXRange)
{
PyXRange px = (PyXRange)obj;
return new PyIterator(px, px.__len__());
}
else
{
return super.getIterator(obj, i);
}
}
/**
* get the method for a jython object (or pass up)
*/
public VelMethod getMethod(Object obj, String methodName, Object[] args,
Info i) throws Exception
{
if (obj instanceof PyObject)
{
return new PyMethod(methodName);
}
else
{
return super.getMethod(obj, methodName, args, i);
}
}
/**
* get a property from a jython object for data retrieval
*/
public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i)
throws Exception
{
if (obj instanceof PyObject)
{
return new PyGetProperty(identifier);
}
else
{
return super.getPropertyGet(obj, identifier, i);
}
}
/**
* get a property from a jython object for data modification
*/
public VelPropertySet getPropertySet(Object obj, String identifier, Object
arg, Info info) throws Exception
{
if (obj instanceof PyObject)
{
return new PySetProperty(identifier);
}
else
{
return super.getPropertySet(obj, identifier, arg, info);
}
}
}
/**
* a jython velocity method
*/
class PyMethod implements VelMethod
{
private static final Logger log =
Logger.getLogger(JythonUberspect.class.getName());
final PyString methodname;
public PyMethod(String methodname)
{
this.methodname = new PyString(methodname);
}
/**
* returns the jython method name
*/
public String getMethodName()
{
return methodname.toString();
}
/**
* the return type of the invoked method. Just being lazy here and
returning 'Object'
* for everything at the moment
*/
public Class getReturnType()
{
return Object.class;
}
/**
* execute the jython method
*/
public Object invoke(Object o, Object[] params)
{
PyObject po = (PyObject)o;
PyObject rtn = null;
try
{
// find the method attr on the python object
PyObject meth = po.__findattr__(methodname);
if (params == null || params.length < 1)
{
rtn = meth.__call__();
}
else
{
// build a python params array
PyObject[] pparams = new PyObject[params.length];
for (int i = 0; i < pparams.length; i++)
{
if (params[i] instanceof String)
{
pparams[i] = new PyString((String)params[i]);
}
else if (params[i] instanceof PyObject)
{
pparams[i] = (PyObject)params[i];
}
else
{
log.error("unsupported param type : " +
params[i].getClass().getName());
return null;
}
}
rtn = meth.__call__(pparams);
if (rtn instanceof PyNone)
{
rtn = null;
}
}
return rtn;
}
catch (Exception e)
{
log.error(e);
}
return null;
}
/**
* is this method cacheable
*/
public boolean isCacheable()
{
return true;
}
}
/**
* a jython velocity GET property
*/
class PyGetProperty implements VelPropertyGet
{
private static final Logger log =
Logger.getLogger(JythonUberspect.class.getName());
private PyString propname;
public PyGetProperty(String propname)
{
this.propname = new PyString(propname);
}
/**
* the name of the jython property/attribute
*/
public String getMethodName()
{
return propname.toString();
}
/**
* returns the property value
*/
public Object invoke(java.lang.Object o)
{
PyObject po = (PyObject)o;
try
{
Object rtn = po.__findattr__(propname);
if (rtn instanceof PyNone)
{
// handle python None correctly
return null;
}
else
{
return rtn;
}
}
catch (Exception e)
{
log.error(e);
}
return null;
}
/**
* is this property cacheable
*/
public boolean isCacheable()
{
return true;
}
}
/**
* a jython velocity SET property
*/
class PySetProperty implements VelPropertySet
{
private static final Logger log =
Logger.getLogger(JythonUberspect.class.getName());
private PyString propname;
public PySetProperty(String propname)
{
this.propname = new PyString(propname);
}
/**
* the name of the property/attribute
*/
public String getMethodName()
{
return propname.toString();
}
/**
* set the value of a property
*/
public Object invoke(Object o, Object arg)
{
PyObject po = (PyObject)o;
try
{
if (arg instanceof String)
{
po.__setattr__(propname, new PyString((String)arg));
}
else if (arg instanceof PyObject)
{
po.__setattr__(propname, (PyObject)arg);
}
else
{
log.error("unsupported argument type : " +
arg.getClass().getName());
}
}
catch (Exception e)
{
log.error(e);
}
return null;
}
/**
* is this property cacheable
*/
public boolean isCacheable()
{
return true;
}
}
/**
* supporting iterator class for python list/sequence objects
*/
class PyIterator implements Iterator
{
PySequence seq;
int len;
int pos = -1;
public PyIterator(PySequence seq, int len)
{
this.seq = seq;
this.len = len;
}
/**
* do we have more values?
*/
public boolean hasNext()
{
return (pos + 1 < len);
}
/**
* return the next value
*/
public Object next()
{
pos++;
if (pos < len)
{
return seq.__finditem__(pos);
}
else
{
throw new NoSuchElementException();
}
}
/**
* NOT CURRENTLY SUPPORTED
*/
public void remove()
{
throw new UnsupportedOperationException();
}
}
}}}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]