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]

Reply via email to