/*
* This code is distributed under The GNU Lesser General Public License (LGPLv3)
* Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html
*
* Copyright Denis Pavlov 2009
* Web: http://www.genericdtoassembler.org
* SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/
* SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/
*/
package com.inspiresoftware.lib.dto.geda.assembler.extension.impl;
import com.inspiresoftware.lib.dto.geda.assembler.extension.DataReader;
import com.inspiresoftware.lib.dto.geda.assembler.extension.DataWriter;
import com.inspiresoftware.lib.dto.geda.assembler.extension.MethodSynthesizer;
import com.inspiresoftware.lib.dto.geda.exception.GeDARuntimeException;
import com.inspiresoftware.lib.dto.geda.exception.UnableToCreateInstanceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
/**
* Reflection implementation of method synthesizer. Least efficient implementation,
* yet the most stable one since it does not require auto generation of classes
* during runtime.
*
* @author denispavlov
* @since 1.1.2
*
*/
public class ReflectionMethodSynthesizer extends AbstractMethodSynthesizer
implements MethodSynthesizer {
private static final Logger LOG = LoggerFactory.getLogger(ReflectionMethodSynthesizer.class);
public ReflectionMethodSynthesizer(final ClassLoader classLoader) {
super(classLoader);
}
/** {@inheritDoc} */
@Override
protected String getSynthesizerId() {
return "reflection";
}
/** {@inheritDoc} */
@Override
protected DataReader makeReaderClass(
final ClassLoader loader,
final Method readMethod,
final String readerClassName,
final String sourceClassNameFull,
final String sourceClassGetterMethodName,
final Type sourceClassGetterMethodReturnType,
final MakeContext ctx)
throws UnableToCreateInstanceException, GeDARuntimeException {
final Class< ? > returnType;
if (sourceClassGetterMethodReturnType instanceof Class) {
final Class< ? > rcl = ((Class< ? >) sourceClassGetterMethodReturnType);
if (rcl.isPrimitive()) {
returnType = PRIMITIVE_TO_WRAPPER_CLASS.get(rcl.getCanonicalName());
} else {
returnType = (Class< ? >) sourceClassGetterMethodReturnType;
}
} else if (sourceClassGetterMethodReturnType instanceof ParameterizedType) {
returnType =
(Class< ? >) ((ParameterizedType) sourceClassGetterMethodReturnType).getRawType();
} else if (sourceClassGetterMethodReturnType instanceof TypeVariable) {
returnType = Object.class; // generics
} else {
returnType = Object.class; // default
}
return new DataReader() {
private final Method method = readMethod;
private final Class< ? > type = returnType;
public Class< ? > getReturnType() {
return type;
}
public Object read(final Object source) {
try {
return method.invoke(source);
} catch (Exception exp) {
LOG.error(exp.getMessage(), exp);
}
return null;
}
};
}
/** {@inheritDoc} */
@Override
protected DataWriter makeWriterClass(
final ClassLoader loader,
final Method writeMethod,
final String writerClassName,
final String sourceClassNameFull,
final String sourceClassSetterMethodName,
final Class< ? > sourceClassSetterMethodArgumentClass,
final MakeContext ctx)
throws UnableToCreateInstanceException {
final Class< ? > argType;
if (sourceClassSetterMethodArgumentClass.isPrimitive()) {
argType = PRIMITIVE_TO_WRAPPER_CLASS.get(sourceClassSetterMethodArgumentClass.getCanonicalName());
} else {
argType = sourceClassSetterMethodArgumentClass;
}
return new DataWriter() {
private final Method method = writeMethod;
private final Class< ? > type = argType;
public Class< ? > getParameterType() {
return type;
}
public void write(final Object source, final Object value) {
final Object args = value;
try {
this.method.invoke(source, args);
} catch (Exception exp) {
LOG.error(exp.getMessage(), exp);
}
}
};
}
}