/*
* GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Contact info: xamjadmin@users.sourceforge.net
*/
package org.cobra_grendel.js;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.mozilla.javascript.Function;
public class JavaClassWrapper implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1L;
private final Map functions = new HashMap();
private PropertyInfo integerIndexer;
private final Class javaClass;
private PropertyInfo nameIndexer;
private final Map properties = new HashMap();
public JavaClassWrapper(final Class class1)
{
super();
javaClass = class1;
scanMethods();
}
private void ensurePropertyKnown(final String methodName, final Method method)
{
String capPropertyName;
String propertyName;
boolean getter = false;
if (methodName.startsWith("get"))
{
capPropertyName = methodName.substring(3);
propertyName = uncapitalize(capPropertyName);
getter = true;
}
else if (methodName.startsWith("set"))
{
capPropertyName = methodName.substring(3);
propertyName = uncapitalize(capPropertyName);
}
else if (methodName.startsWith("is"))
{
capPropertyName = methodName.substring(2);
propertyName = uncapitalize(capPropertyName);
getter = true;
}
else
{
throw new IllegalArgumentException("methodName=" + methodName);
}
PropertyInfo pinfo = (PropertyInfo) properties.get(propertyName);
if (pinfo == null)
{
Class pt = getter ? method.getReturnType() : method.getParameterTypes()[0];
pinfo = new PropertyInfo(propertyName, pt);
properties.put(propertyName, pinfo);
}
if (getter)
{
pinfo.setGetter(method);
}
else
{
pinfo.setSetter(method);
}
}
public String getClassName()
{
String className = javaClass.getName();
int lastDotIdx = className.lastIndexOf('.');
return lastDotIdx == -1 ? className : className.substring(lastDotIdx + 1);
}
public Function getFunction(final String name)
{
return (Function) functions.get(name);
}
public PropertyInfo getIntegerIndexer()
{
return integerIndexer;
}
public PropertyInfo getNameIndexer()
{
return nameIndexer;
}
public PropertyInfo getProperty(final String name)
{
return (PropertyInfo) properties.get(name);
}
private boolean isIntegerIndexer(final String name, final Method method)
{
return "item".equals(name) && method.getParameterTypes().length == 1 || "setItem".equals(name) && method.getParameterTypes().length == 2;
}
private boolean isNameIndexer(final String name, final Method method)
{
return "namedItem".equals(name) && method.getParameterTypes().length == 1 || "setNamedItem".equals(name) && method.getParameterTypes().length == 2;
}
private boolean isPropertyMethod(final String name, final Method method)
{
if (name.startsWith("get") || name.startsWith("is"))
{
return method.getParameterTypes().length == 0;
}
else if (name.startsWith("set"))
{
return method.getParameterTypes().length == 1;
}
else
{
return false;
}
}
public Object newInstance() throws InstantiationException, IllegalAccessException
{
return javaClass.newInstance();
}
private void scanMethods()
{
Method[] methods = javaClass.getMethods();
int len = methods.length;
for (int i = 0; i < len; i++)
{
Method method = methods[i];
String name = method.getName();
if (isPropertyMethod(name, method))
{
ensurePropertyKnown(name, method);
}
if (isNameIndexer(name, method))
{
updateNameIndexer(name, method);
}
else if (isIntegerIndexer(name, method))
{
updateIntegerIndexer(name, method);
}
else
{
JavaFunctionObject f = (JavaFunctionObject) functions.get(name);
if (f == null)
{
f = new JavaFunctionObject(name);
functions.put(name, f);
}
f.addMethod(method);
}
}
}
@Override
public String toString()
{
return javaClass.getName();
}
private String uncapitalize(final String text)
{
try
{
return Character.toLowerCase(text.charAt(0)) + text.substring(1);
}
catch (IndexOutOfBoundsException iob)
{
return text;
}
}
private void updateIntegerIndexer(final String methodName, final Method method)
{
boolean getter = true;
if (methodName.startsWith("set"))
{
getter = false;
}
PropertyInfo indexer = integerIndexer;
if (indexer == null)
{
Class pt = getter ? method.getReturnType() : method.getParameterTypes()[1];
indexer = new PropertyInfo("$item", pt);
integerIndexer = indexer;
}
if (getter)
{
indexer.setGetter(method);
}
else
{
indexer.setSetter(method);
}
}
private void updateNameIndexer(final String methodName, final Method method)
{
boolean getter = true;
if (methodName.startsWith("set"))
{
getter = false;
}
PropertyInfo indexer = nameIndexer;
if (indexer == null)
{
indexer = new PropertyInfo("$item", Object.class);
nameIndexer = indexer;
}
if (getter)
{
indexer.setGetter(method);
}
else
{
indexer.setSetter(method);
}
}
}