blob: 42875e6adbdf85e726e2103e5074871d2cf34c80 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera2.common.templates;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.abdera2.common.templates.CachingContext;
import org.apache.abdera2.common.templates.ObjectContext;
import org.apache.abdera2.common.anno.Name;
@SuppressWarnings("unchecked")
public final class ObjectContext extends CachingContext {
private static final long serialVersionUID = -1387599933658718221L;
private final Object target;
private final Map<String, AccessibleObject> accessors = new HashMap<String, AccessibleObject>();
public ObjectContext(Object object) {
this(object, false);
}
public ObjectContext(Object object, boolean isiri) {
if (object == null)
throw new IllegalArgumentException();
this.target = object;
setIri(isiri);
initMethods();
}
private void initMethods() {
Class<?> _class = target.getClass();
if (_class.isAnnotation() || _class.isArray() || _class.isEnum() || _class.isPrimitive())
throw new IllegalArgumentException();
if (!_class.isInterface()) {
Field[] fields = _class.getFields();
for (Field field : fields) {
if (!Modifier.isPrivate(field.getModifiers())) {
accessors.put(getName(field), field);
}
}
}
Method[] methods = _class.getMethods();
for (Method method : methods) {
String name = method.getName();
if (!Modifier.isPrivate(method.getModifiers()) && method.getParameterTypes().length == 0
&& !method.getReturnType().equals(Void.class)
&& !isReserved(name)) {
accessors.put(getName(method), method);
}
}
}
private String getName(AccessibleObject object) {
String name = null;
Name varName = object.getAnnotation(Name.class);
if (varName != null)
return varName.value();
if (object instanceof Field) {
name = ((Field)object).getName().toLowerCase();
} else if (object instanceof Method) {
name = ((Method)object).getName().toLowerCase();
if (name.startsWith("get"))
name = name.substring(3);
else if (name.startsWith("is"))
name = name.substring(2);
}
return name;
}
private boolean isReserved(String name) {
return (name.equals("toString") || name.equals("hashCode")
|| name.equals("notify")
|| name.equals("notifyAll")
|| name.equals("getClass") || name.equals("wait"));
}
@Override
protected <T> T resolveActual(String var) {
try {
var = var.toLowerCase();
AccessibleObject accessor = accessors.get(var);
if (accessor == null)
return null;
if (accessor instanceof Method) {
Method method = (Method)accessor;
return (T)method.invoke(target);
} else if (accessor instanceof Field) {
Field field = (Field)accessor;
return (T)field.get(target);
} else
return null;
} catch (InvocationTargetException e) {
throw new IllegalArgumentException("Accessor: " + var, e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Accessor: " + var, e);
}
}
public Iterator<String> iterator() {
return accessors.keySet().iterator();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((target == null) ? 0 : target.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final ObjectContext other = (ObjectContext)obj;
if (target == null) {
if (other.target != null)
return false;
} else if (!target.equals(other.target))
return false;
return true;
}
public boolean contains(String var) {
return accessors.containsKey(var);
}
}