📄 jythonwrapper.java
字号:
/*
* Copyright (c) 2003 The Visigoth Software Society. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Visigoth Software Society (http://www.visigoths.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
* project contributors may be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact visigoths@visigoths.org.
*
* 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
* nor may "FreeMarker" or "Visigoth" appear in their names
* without prior written permission of the Visigoth Software Society.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Visigoth Software Society. For more
* information on the Visigoth Software Society, please see
* http://www.visigoths.org/
*/
package freemarker.ext.jython;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.python.core.Py;
import org.python.core.PyDictionary;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyJavaInstance;
import org.python.core.PyLong;
import org.python.core.PyNone;
import org.python.core.PyObject;
import org.python.core.PySequence;
import org.python.core.PyString;
import org.python.core.PyStringMap;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.DateModel;
import freemarker.ext.util.ModelCache;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelAdapter;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.utility.OptimizerUtil;
/**
* An object wrapper that wraps Jython objects into FreeMarker template models
* and vice versa.
* @version $Id: JythonWrapper.java,v 1.23.2.1 2005/10/04 16:18:08 revusky Exp $
* @author Attila Szegedi
*/
public class JythonWrapper implements ObjectWrapper
{
private static final Class PYOBJECT_CLASS = PyObject.class;
public static final JythonWrapper INSTANCE = new JythonWrapper();
private final ModelCache modelCache = new ModelCache(this);
private boolean attributesShadowItems = true;
public JythonWrapper()
{
}
/**
* Sets whether this wrapper caches model instances. Default is false.
* When set to true, calling {@link #wrap(Object)} multiple times for
* the same object will return the same model.
*/
public void setUseCache(boolean useCache)
{
modelCache.setUseCache(useCache);
}
/**
* Sets whether attributes shadow items in wrapped objects. When true
* (this is the default value), <code>${object.name}</code> will first
* try to locate a python attribute with the specified name on the object
* using {@link PyObject#__findattr__(java.lang.String)}, and only if it
* doesn't find the attribute will it call
* {@link PyObject#__getitem__(org.python.core.PyObject)}.
* When set to false, the lookup order is reversed and items
* are looked up before attributes.
*/
public synchronized void setAttributesShadowItems(boolean attributesShadowItems)
{
this.attributesShadowItems = attributesShadowItems;
}
boolean isAttributesShadowItems()
{
return attributesShadowItems;
}
/**
* Wraps the passed Jython object into a FreeMarker template model. If
* the object is not a Jython object, it is first coerced into one using
* {@link Py#java2py(java.lang.Object)}. {@link PyDictionary} and {@link
* PyStringMap} are wrapped into a hash model, {@link PySequence}
* descendants are wrapped into a sequence model, {@link PyInteger}, {@link
* PyLong}, and {@link PyFloat} are wrapped into a number model. All objects
* are wrapped into a scalar model (using {@link Object#toString()} and a
* boolean model (using {@link PyObject#__nonzero__()}. For internal
* general-purpose {@link PyObject}s returned from a call to {@link
* #unwrap(TemplateModel)}, the template model that was passed to
* <code>unwrap</code> is returned.
*/
public TemplateModel wrap(Object obj)
{
if(obj == null) {
return null;
}
if (obj instanceof TemplateModel) {
return (TemplateModel)obj;
}
if(obj instanceof TemplateModelAdapter) {
return ((TemplateModelAdapter)obj).getTemplateModel();
}
boolean asHash = false;
boolean asSequence = false;
if(obj instanceof PyJavaInstance) {
Object jobj = ((PyJavaInstance)obj).__tojava__(java.lang.Object.class);
// FreeMarker-aware, Jython-wrapped Java objects are left intact
if(jobj instanceof TemplateModel) {
return (TemplateModel)jobj;
}
if(jobj instanceof Map) {
asHash = true;
}
if (jobj instanceof Date) {
return new DateModel((Date) jobj, BeansWrapper.getDefaultInstance());
}
else if(jobj instanceof Collection) {
asSequence = true;
// FIXME: This is an ugly hack, but AFAIK, there's no better
// solution if we want to have Sets and other non-List
// collections managed by this layer, as Jython quite clearly
// doesn't support sets.
if(!(jobj instanceof List)) {
obj = new ArrayList((Collection)jobj);
}
}
}
// If it's not a PyObject, first make a PyObject out of it.
if(!(obj instanceof PyObject))
{
obj = Py.java2py(obj);
}
if(asHash || obj instanceof PyDictionary || obj instanceof PyStringMap)
{
return modelCache.getInstance(obj, JythonHashModel.FACTORY);
}
if(asSequence || obj instanceof PySequence)
{
return modelCache.getInstance(obj, JythonSequenceModel.FACTORY);
}
if(obj instanceof PyInteger || obj instanceof PyLong || obj instanceof PyFloat)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -