package eu.stratosphere.util.reflect; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import eu.stratosphere.util.FilteringIterable; import eu.stratosphere.util.Predicate; public class DynamicClass<DeclaringClass> { private DynamicConstructor<DeclaringClass> constructor; private final Map<String, DynamicInvokable<?, ?, ?>> methods = new HashMap<String, DynamicInvokable<?, ?, ?>>(); private final Class<DeclaringClass> declaringClass; private final Map<String, Field> fields = new HashMap<String, Field>(); private Map<String, DynamicProperty<?>> properties; private int stateMask; private final static int PROPERTY_INIT = 0x1; public DynamicClass(final Class<DeclaringClass> declaringClass) { this.declaringClass = declaringClass; } public synchronized DynamicConstructor<DeclaringClass> getConstructor() { if (this.constructor == null) this.constructor = DynamicConstructor.valueOf(this.declaringClass); return this.constructor; } private synchronized Field getField(final String name) { Field field = this.fields.get(name); if (field == null) try { this.fields.put(name, field = this.declaringClass.getField(name)); } catch (final Exception e) { throw new RuntimeException(e); } return field; } public Object getFieldValue(final DeclaringClass instance, final String name) { try { return this.getField(name).get(instance); } catch (final Exception e) { throw new RuntimeException(e); } } public synchronized DynamicInvokable<?, ?, ?> getMethod(final String name) { DynamicInvokable<?, ?, ?> method = this.methods.get(name); if (method == null) this.methods.put(name, method = DynamicMethod.valueOf(this.declaringClass, name)); return method; } public Object getStaticFieldValue(final String name) { try { return this.getField(name).get(null); } catch (final Exception e) { throw new RuntimeException(e); } } public Object invoke(final DeclaringClass instance, final String name, final Object... params) { return this.getMethod(name).invoke(instance, params); } public Object invokeStatic(final String name, final Object... params) { return this.getMethod(name).invoke(null, params); } public boolean isInstantiable() { return this.getConstructor().isInvokableFor(); } public DynamicInstance<DeclaringClass> newDynamicInstance(final Object... params) { return new DynamicInstance<DeclaringClass>(this, params); } public DeclaringClass newInstance(final Object... params) { return this.getConstructor().invoke(params); } public void setFieldValue(final DeclaringClass instance, final String name, final Object value) { try { this.getField(name).set(instance, value); } catch (final Exception e) { throw new RuntimeException(e); } } public void setStaticFieldValue(final String name, final Object value) { try { this.getField(name).set(null, value); } catch (final Exception e) { throw new RuntimeException(e); } } @SuppressWarnings({ "unchecked", "rawtypes" }) public <BaseType> Iterable<DynamicProperty<BaseType>> getProperties(final Class<BaseType> baseType) { return new FilteringIterable(this.getProperties(), new Predicate<DynamicProperty>() { @Override public boolean isTrue(final DynamicProperty property) { return baseType.isAssignableFrom(property.getType()); } }); } public boolean needsInit(final int stateBit) { return (this.stateMask & stateBit) == 0; } public void setState(final int stateBit) { this.stateMask |= stateBit; } public Iterable<DynamicProperty<?>> getProperties() { if (this.needsInit(PROPERTY_INIT)) this.initProperties(); return this.properties.values(); } @SuppressWarnings("rawtypes") private void initProperties() { try { this.properties = new HashMap<String, DynamicProperty<?>>(); for (final PropertyDescriptor property : Introspector.getBeanInfo(this.declaringClass) .getPropertyDescriptors()) if (property.getPropertyType() != null) this.properties.put(property.getName(), new BeanProperty(property)); this.setState(PROPERTY_INIT); } catch (final IntrospectionException e) { throw new RuntimeException(e); } } }