/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 freemarker.ext.jython;
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.
PyLong;
import org.python.core.
PyNone;
import org.python.core.
PyObject;
import org.python.core.
PySequence;
import org.python.core.
PyStringMap;
import freemarker.ext.beans.
BeansWrapper;
import freemarker.ext.beans.
DateModel;
import freemarker.ext.util.
ModelCache;
import freemarker.template.
TemplateModel;
class
JythonModelCache extends
ModelCache {
private final
JythonWrapper wrapper;
JythonModelCache(
JythonWrapper wrapper) {
this.
wrapper =
wrapper;
}
@
Override
protected boolean
isCacheable(
Object object) {
return true;
}
@
Override
protected
TemplateModel create(
Object obj) {
boolean
asHash = false;
boolean
asSequence = false;
JythonVersionAdapter versionAdapter =
JythonVersionAdapterHolder.
INSTANCE;
if (
versionAdapter.
isPyInstance(
obj)) {
Object jobj =
versionAdapter.
pyInstanceToJava(
obj);
// 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
JythonHashModel.
FACTORY.
create(
obj,
wrapper);
}
if (
asSequence ||
obj instanceof
PySequence) {
return
JythonSequenceModel.
FACTORY.
create(
obj,
wrapper);
}
if (
obj instanceof
PyInteger ||
obj instanceof
PyLong ||
obj instanceof
PyFloat) {
return
JythonNumberModel.
FACTORY.
create(
obj,
wrapper);
}
if (
obj instanceof
PyNone) {
return null;
}
return
JythonModel.
FACTORY.
create(
obj,
wrapper);
}
}