com.espertech.esper.event.bean.PropertyHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esper Show documentation
Show all versions of esper Show documentation
Complex event processing and event series analysis component
/**************************************************************************************
* Copyright (C) 2006-2015 EsperTech Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.event.bean;
import com.espertech.esper.client.EventPropertyGetter;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.event.EventPropertyType;
import com.espertech.esper.event.WriteablePropertyDescriptor;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.beans.*;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.*;
/**
* This class offers utililty methods around introspection and CGLIB interaction.
*/
public class PropertyHelper
{
/**
* Return getter for the given method and CGLIB FastClass.
* @param method to return getter for
* @param fastClass is the CGLIB fast classs to make FastMethod for
* @param eventAdapterService factory for event beans and event types
* @return property getter
*/
public static EventPropertyGetter getGetter(Method method, FastClass fastClass, EventAdapterService eventAdapterService)
{
// Get CGLib fast method handle
FastMethod fastMethod = null;
try
{
if (fastClass != null)
{
fastMethod = fastClass.getMethod(method);
}
}
catch (Throwable ex)
{
log.warn(".getAccessors Unable to obtain CGLib fast method implementation, msg=" + ex.getMessage());
}
// Construct the appropriate property getter CGLib or reflect
EventPropertyGetter getter;
if (fastMethod != null)
{
getter = new CGLibPropertyGetter(method, fastMethod, eventAdapterService);
}
else
{
getter = new ReflectionPropMethodGetter(method, eventAdapterService);
}
return getter;
}
/**
* Introspects the given class and returns event property descriptors for each property found
* in the class itself, it's superclasses and all interfaces this class and the superclasses implements.
* @param clazz is the Class to introspect
* @return list of properties
*/
public static List getProperties(Class clazz)
{
// Determine all interfaces implemented and the interface's parent interfaces if any
Set propertyOrigClasses = new HashSet();
getImplementedInterfaceParents(clazz, propertyOrigClasses);
// Add class itself
propertyOrigClasses.add(clazz);
// Get the set of property names for all classes
return getPropertiesForClasses(propertyOrigClasses);
}
/**
* Introspects the given class and returns event property descriptors for each writable property found
* in the class itself, it's superclasses and all interfaces this class and the superclasses implements.
* @param clazz is the Class to introspect
* @return list of properties
*/
public static Set getWritableProperties(Class clazz)
{
// Determine all interfaces implemented and the interface's parent interfaces if any
Set propertyOrigClasses = new HashSet();
getImplementedInterfaceParents(clazz, propertyOrigClasses);
// Add class itself
propertyOrigClasses.add(clazz);
// Get the set of property names for all classes
return getWritablePropertiesForClasses(propertyOrigClasses);
}
private static void getImplementedInterfaceParents(Class clazz, Set classesResult)
{
Class[] interfaces = clazz.getInterfaces();
if (interfaces == null)
{
return;
}
for (int i = 0; i < interfaces.length; i++)
{
classesResult.add(interfaces[i]);
getImplementedInterfaceParents(interfaces[i], classesResult);
}
}
private static Set getWritablePropertiesForClasses(Set propertyClasses)
{
Set result = new HashSet();
for (Class clazz : propertyClasses)
{
addIntrospectPropertiesWritable(clazz, result);
}
return result;
}
private static List getPropertiesForClasses(Set propertyClasses)
{
List result = new LinkedList();
for (Class clazz : propertyClasses)
{
addIntrospectProperties(clazz, result);
addMappedProperties(clazz, result);
}
removeDuplicateProperties(result);
removeJavaProperties(result);
return result;
}
/**
* Remove Java language specific properties from the given list of property descriptors.
* @param properties is the list of property descriptors
*/
protected static void removeJavaProperties(List properties)
{
List toRemove = new LinkedList();
// add removed entries to separate list
for (InternalEventPropDescriptor desc : properties)
{
if ((desc.getPropertyName().equals("class")) ||
(desc.getPropertyName().equals("getClass")) ||
(desc.getPropertyName().equals("toString")) ||
(desc.getPropertyName().equals("hashCode")))
{
toRemove.add(desc);
}
}
// remove
for (InternalEventPropDescriptor desc : toRemove)
{
properties.remove(desc);
}
}
/**
* Removed duplicate properties using the property name to find unique properties.
* @param properties is a list of property descriptors
*/
protected static void removeDuplicateProperties(List properties)
{
LinkedHashMap set = new LinkedHashMap();
List toRemove = new LinkedList();
// add duplicates to separate list
for (InternalEventPropDescriptor desc : properties)
{
if (set.containsKey(desc.getPropertyName()))
{
toRemove.add(desc);
continue;
}
set.put(desc.getPropertyName(), desc);
}
// remove duplicates
for (InternalEventPropDescriptor desc : toRemove)
{
properties.remove(desc);
}
}
/**
* Adds to the given list of property descriptors the properties of the given class
* using the Introspector to introspect properties. This also finds array and indexed properties.
* @param clazz to introspect
* @param result is the list to add to
*/
protected static void addIntrospectProperties(Class clazz, List result)
{
PropertyDescriptor properties[] = introspect(clazz);
for (int i = 0; i < properties.length; i++)
{
PropertyDescriptor property = properties[i];
String propertyName = property.getName();
Method readMethod = property.getReadMethod();
EventPropertyType type = EventPropertyType.SIMPLE;
if (property instanceof IndexedPropertyDescriptor)
{
readMethod = ((IndexedPropertyDescriptor) property).getIndexedReadMethod();
type = EventPropertyType.INDEXED;
}
if (readMethod == null)
{
continue;
}
result.add(new InternalEventPropDescriptor(propertyName, readMethod, type));
}
}
private static void addIntrospectPropertiesWritable(Class clazz, Set result)
{
PropertyDescriptor properties[] = introspect(clazz);
for (int i = 0; i < properties.length; i++)
{
PropertyDescriptor property = properties[i];
String propertyName = property.getName();
Method writeMethod = property.getWriteMethod();
if (writeMethod == null)
{
continue;
}
result.add(new WriteablePropertyDescriptor(propertyName, writeMethod.getParameterTypes()[0], writeMethod));
}
}
/**
* Adds to the given list of property descriptors the mapped properties, ie.
* properties that have a getter method taking a single String value as a parameter.
* @param clazz to introspect
* @param result is the list to add to
*/
protected static void addMappedProperties(Class clazz, List result)
{
Set uniquePropertyNames = new HashSet();
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++)
{
String methodName = methods[i].getName();
if (!methodName.startsWith("get"))
{
continue;
}
String inferredName = methodName.substring(3, methodName.length());
if (inferredName.length() == 0)
{
continue;
}
Class> parameterTypes[] = methods[i].getParameterTypes();
if (parameterTypes.length != 1)
{
continue;
}
if (parameterTypes[0] != String.class)
{
continue;
}
String newInferredName = null;
// Leave uppercase inferred names such as URL
if (inferredName.length() >= 2)
{
if ((Character.isUpperCase(inferredName.charAt(0))) &&
(Character.isUpperCase(inferredName.charAt(1))))
{
newInferredName = inferredName;
}
}
// camelCase the inferred name
if (newInferredName == null)
{
newInferredName = Character.toString(Character.toLowerCase(inferredName.charAt(0)));
if (inferredName.length() > 1)
{
newInferredName += inferredName.substring(1, inferredName.length());
}
}
inferredName = newInferredName;
// if the property inferred name already exists, don't supply it
if (uniquePropertyNames.contains(inferredName))
{
continue;
}
result.add(new InternalEventPropDescriptor(inferredName, methods[i], EventPropertyType.MAPPED));
uniquePropertyNames.add(inferredName);
}
}
/**
* Using the Java Introspector class the method returns the property descriptors obtained through introspection.
* @param clazz to introspect
* @return array of property descriptors
*/
protected static PropertyDescriptor[] introspect(Class clazz)
{
BeanInfo beanInfo;
try
{
beanInfo = Introspector.getBeanInfo(clazz);
}
catch (IntrospectionException e)
{
return (new PropertyDescriptor[0]);
}
return beanInfo.getPropertyDescriptors();
}
public static String getGetterMethodName(String propertyName)
{
return getGetterSetterMethodName(propertyName, "get");
}
public static String getSetterMethodName(String propertyName)
{
return getGetterSetterMethodName(propertyName, "set");
}
public static String getIsMethodName(String propertyName)
{
return getGetterSetterMethodName(propertyName, "is");
}
private static String getGetterSetterMethodName(String propertyName, String operation)
{
StringWriter writer = new StringWriter();
writer.write(operation);
writer.write(Character.toUpperCase(propertyName.charAt(0)));
writer.write(propertyName.substring(1));
return writer.toString();
}
private static final Log log = LogFactory.getLog(PropertyHelper.class);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy