package org.python.core.adapter; import org.python.core.Py; import org.python.core.PyArray; import org.python.core.PyFloat; import org.python.core.PyInteger; import org.python.core.PyJavaClass; import org.python.core.PyJavaInstance; import org.python.core.PyLong; import org.python.core.PyObject; import org.python.core.PyProxy; import org.python.core.PyString; import org.python.core.PyType; /** * Implements the algorithm originally used in {@link Py#java2py} to adapt objects. * * Pre-class adapters are added to handle instances of PyObject, PyProxy and * null values. Class adapters are added to handle builtin Java classes: String, * Integer, Float, Double, Byte, Long, Short, Character, Class and Boolean. An * adapter is added to the post-class adapters to handle wrapping arrays * properly. Finally, if all of the added adapters can handle an object, it's * wrapped in a PyJavaInstance. * */ public class ClassicPyObjectAdapter extends ExtensiblePyObjectAdapter { public ClassicPyObjectAdapter() { addPreClass(new PyObjectAdapter() { public PyObject adapt(Object o) { return (PyObject) o; } public boolean canAdapt(Object o) { return o instanceof PyObject; } }); addPreClass(new PyObjectAdapter() { public PyObject adapt(Object o) { return ((PyProxy) o)._getPyInstance(); } public boolean canAdapt(Object o) { return o instanceof PyProxy; } }); addPreClass(new PyObjectAdapter() { public boolean canAdapt(Object o) { return o == null; } public PyObject adapt(Object o) { return Py.None; } }); add(new ClassAdapter(String.class) { public PyObject adapt(Object o) { return new PyString((String) o); } }); add(new ClassAdapter(Character.class) { public PyObject adapt(Object o) { return Py.makeCharacter((Character) o); } }); add(new ClassAdapter(Class.class) { public PyObject adapt(Object o) { Class cls = (Class) o; if (PyObject.class.isAssignableFrom(cls)) { return PyType.fromClass(cls); } return PyJavaClass.lookup(cls); } }); add(new NumberToPyFloat(Double.class)); add(new NumberToPyFloat(Float.class)); add(new NumberToPyInteger(Integer.class)); add(new NumberToPyInteger(Byte.class)); add(new NumberToPyInteger(Short.class)); add(new ClassAdapter(Long.class) { public PyObject adapt(Object o) { return new PyLong(((Number) o).longValue()); } }); add(new ClassAdapter(Boolean.class) { public PyObject adapt(Object o) { return ((Boolean) o).booleanValue() ? Py.One : Py.Zero; } }); addPostClass(new PyObjectAdapter() { public PyObject adapt(Object o) { return new PyArray(o.getClass().getComponentType(), o); } public boolean canAdapt(Object o) { return o.getClass().isArray(); } }); } /** * Always returns true as we just return new PyJavaInstance(o) if the * adapters added to the superclass can't handle o. */ public boolean canAdapt(Object o) { return true; } public PyObject adapt(Object o) { PyObject result = super.adapt(o); if (result != null) { return result; } return new PyJavaInstance(o); } private static class NumberToPyInteger extends ClassAdapter { public NumberToPyInteger(Class c) { super(c); } public PyObject adapt(Object o) { return new PyInteger(((Number) o).intValue()); } } private static class NumberToPyFloat extends ClassAdapter { public NumberToPyFloat(Class c) { super(c); } public PyObject adapt(Object o) { return new PyFloat(((Number) o).doubleValue()); } } }