/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* 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.asper.sources.net.sf.cglib.reflect.FastMethod;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.event.EventBeanManufactureException;
import com.espertech.esper.event.EventBeanManufacturer;
import com.espertech.esper.event.WriteablePropertyDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Factory for event beans created and populate anew from a set of values.
*/
public class EventBeanManufacturerBean implements EventBeanManufacturer
{
private static Log log = LogFactory.getLog(EventBeanManufacturerBean.class);
private final BeanInstantiator beanInstantiator;
private final BeanEventType beanEventType;
private final EventAdapterService service;
private final FastMethod[] writeMethodsFastClass;
private final Method[] writeMethodsReflection;
private final boolean hasPrimitiveTypes;
private final boolean[] primitiveType;
/**
* Ctor.
* @param beanEventType target type
* @param service factory for events
* @param properties written properties
* @param engineImportService for resolving write methods
* @throws EventBeanManufactureException if the write method lookup fail
*/
public EventBeanManufacturerBean(BeanEventType beanEventType,
EventAdapterService service,
WriteablePropertyDescriptor[] properties,
EngineImportService engineImportService
)
throws EventBeanManufactureException
{
this.beanEventType = beanEventType;
this.service = service;
beanInstantiator = BeanInstantiatorFactory.makeInstantiator(beanEventType, engineImportService);
writeMethodsReflection = new Method[properties.length];
if (beanEventType.getFastClass() != null) {
writeMethodsFastClass = new FastMethod[properties.length];
}
else {
writeMethodsFastClass = null;
}
boolean primitiveTypeCheck = false;
primitiveType = new boolean[properties.length];
for (int i = 0; i < properties.length; i++)
{
writeMethodsReflection[i] = properties[i].getWriteMethod();
if (beanEventType.getFastClass() != null) {
writeMethodsFastClass[i] = beanEventType.getFastClass().getMethod(properties[i].getWriteMethod());
}
primitiveType[i] = properties[i].getType().isPrimitive();
primitiveTypeCheck |= primitiveType[i];
}
hasPrimitiveTypes = primitiveTypeCheck;
}
public EventBean make(Object[] propertyValues)
{
Object outObject = makeUnderlying(propertyValues);
return service.adapterForTypedBean(outObject, beanEventType);
}
public Object makeUnderlying(Object[] propertyValues)
{
Object outObject = beanInstantiator.instantiate();
if (writeMethodsFastClass != null) {
if (!hasPrimitiveTypes) {
Object[] parameters = new Object[1];
for (int i = 0; i < writeMethodsFastClass.length; i++)
{
parameters[0] = propertyValues[i];
try
{
writeMethodsFastClass[i].invoke(outObject, parameters);
}
catch (InvocationTargetException e)
{
handle(e, writeMethodsFastClass[i].getName());
}
}
}
else
{
Object[] parameters = new Object[1];
for (int i = 0; i < writeMethodsFastClass.length; i++)
{
if (primitiveType[i]) {
if (propertyValues[i] == null) {
continue;
}
}
parameters[0] = propertyValues[i];
try
{
writeMethodsFastClass[i].invoke(outObject, parameters);
}
catch (InvocationTargetException e)
{
handle(e, writeMethodsFastClass[i].getName());
}
}
}
}
else {
if (!hasPrimitiveTypes) {
Object[] parameters = new Object[1];
for (int i = 0; i < writeMethodsReflection.length; i++)
{
parameters[0] = propertyValues[i];
try
{
writeMethodsReflection[i].invoke(outObject, parameters);
}
catch (InvocationTargetException e)
{
String message = "Unexpected exception encountered invoking setter-method '" + writeMethodsReflection[i] + "' on class '" +
beanEventType.getUnderlyingType().getName() + "' : " + e.getTargetException().getMessage();
log.error(message, e);
}
catch (IllegalAccessException e)
{
handle(e, writeMethodsReflection[i].getName());
}
}
}
else
{
Object[] parameters = new Object[1];
for (int i = 0; i < writeMethodsReflection.length; i++)
{
if (primitiveType[i]) {
if (propertyValues[i] == null) {
continue;
}
}
parameters[0] = propertyValues[i];
try
{
writeMethodsReflection[i].invoke(outObject, parameters);
}
catch (InvocationTargetException e)
{
handle(e, writeMethodsReflection[i].getName());
}
catch (IllegalAccessException e)
{
handle(e, writeMethodsReflection[i].getName());
}
}
}
}
return outObject;
}
private void handle(InvocationTargetException ex, String methodName) {
String message = "Unexpected exception encountered invoking setter-method '" + methodName + "' on class '" +
beanEventType.getUnderlyingType().getName() + "' : " + ex.getTargetException().getMessage();
log.error(message, ex);
}
private void handle(IllegalAccessException ex, String methodName) {
String message = "Unexpected exception encountered invoking setter-method '" + methodName + "' on class '" +
beanEventType.getUnderlyingType().getName() + "' : " + ex.getMessage();
log.error(message, ex);
}
}