// Path: src/main/java/org/spearal/SpearalContext.java
// public interface SpearalContext {
// 
// 	void configure(Configurable configurable);
// 	void configure(Configurable configurable, boolean append);
// 	
// 	Securizer getSecurizer();
// 	
// 	String alias(Class<?> cls);
// 	String unalias(String aliasedClassName);
// 	
// 	Class<?> loadClass(String classNames, Type target)
// 		throws SecurityException;
// 	Object newInstance(Class<?> cls);
// 	
// 	Property[] getProperties(Class<?> cls);
// 	
// 	Object instantiate(Type type, Object param)
// 		throws InstantiationException, IllegalAccessException;
// 	Object instantiate(Property property, Object param)
// 		throws InstantiationException, IllegalAccessException;
// 	Object instantiatePartial(Class<?> cls, Property[] partialProperties)
// 		throws InstantiationException, IllegalAccessException;
// 	
// 	Coder getCoder(Class<?> valueClass);
// 	
// 	String[] getUnfilterableProperties(Class<?> valueClass);
// 	
// 	Object convert(Object value, Type targetType);
// 	
// 	Property createProperty(String name, Field field, Method getter, Method setter);
// 	
// 	FilteredBeanDescriptor createDescriptor(SpearalPropertyFilter filter, Object value);
// }
// 
// Path: src/main/java/org/spearal/configuration/PartialObjectFactory.java
// public interface PartialObjectProxy {
// 
// 	boolean $hasUndefinedProperties();
// 	boolean $isDefined(String propertyName);
// 	boolean $undefine(String propertyName);
// 	Property[] $getDefinedProperties();
// }
// 
// Path: src/main/java/org/spearal/configuration/PartialObjectFactory.java
// public static class UndefinedPropertyException extends RuntimeException {
// 
// 	private static final long serialVersionUID = 1L;
// 
// 	public UndefinedPropertyException(String propertyName) {
// 		super("Property '" + propertyName + "' is undefined");
// 	}
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyFactory.java
// public interface Property {
// 		
// 	String getName();
// 	Class<?> getType();
// 	Type getGenericType();
// 		
// 	boolean hasField();
// 	Field getField();
// 	boolean hasGetter();
// 	Method getGetter();
// 	boolean hasSetter();
// 	Method getSetter();
// 		
// 	Class<?> getDeclaringClass();
// 		
// 	Object init(ExtendedSpearalDecoder decoder, Object holder)
// 		throws InstantiationException, IllegalAccessException, InvocationTargetException;
// 		
// 	Object get(Object holder)
// 		throws IllegalAccessException, InvocationTargetException;
// 		
// 	void set(Object holder, Object value)
// 		throws IllegalAccessException, InvocationTargetException;
// 		
// 	boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
// 	<A extends Annotation> A getAnnotation(Class<A> annotationClass);
// 		
// 	boolean isReadOnly();
// 		
// 	public void write(ExtendedSpearalEncoder encoder, Object holder)
// 		throws IOException, IllegalAccessException, InvocationTargetException;
// 			
// 	public void read(ExtendedSpearalDecoder decoder, Object holder, int parameterizedType)
// 		throws IOException, InstantiationException, IllegalAccessException, InvocationTargetException;
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyInstantiatorProvider.java
// public interface PropertyInstantiatorProvider extends Repeatable {
// 
// 	public interface PropertyInstantiator {
// 		
// 		Object instantiate(SpearalContext context, Property property, Object param);
// 	}
// 	
// 	PropertyInstantiator getInstantiator(Property property);
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyInstantiatorProvider.java
// public interface PropertyInstantiator {
// 		
// 	Object instantiate(SpearalContext context, Property property, Object param);
// }
// 
// Path: src/main/java/org/spearal/configuration/TypeInstantiatorProvider.java
// public interface TypeInstantiatorProvider extends Repeatable {
// 
// 	public interface TypeInstantiator {
// 		
// 		Object instantiate(SpearalContext context, Type type, Object param);
// 	}
// 	
// 	TypeInstantiator getInstantiator(Type type);
// }
// 
// Path: src/main/java/org/spearal/configuration/TypeInstantiatorProvider.java
// public interface TypeInstantiator {
// 		
// 	Object instantiate(SpearalContext context, Type type, Object param);
// }


import org.spearal.configuration.PropertyInstantiatorProvider.PropertyInstantiator;
import org.spearal.configuration.TypeInstantiatorProvider;
import org.spearal.configuration.TypeInstantiatorProvider.TypeInstantiator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.spearal.SpearalContext;
import org.spearal.configuration.PartialObjectFactory.PartialObjectProxy;
import org.spearal.configuration.PartialObjectFactory.UndefinedPropertyException;
import org.spearal.configuration.PropertyFactory.Property;
import org.spearal.configuration.PropertyInstantiatorProvider;
		private final Property[] properties;
		private Map<String, Property> definedProperties = new HashMap<String, Property>();
		
		public PropertiesInvocationHandler(SpearalContext context, Property[] properties) {
			this(context, properties, null);
		}
		
		public PropertiesInvocationHandler(SpearalContext context, Property[] properties, Property[] definedProperties) {
			this.context = context;
			this.methods = new HashMap<Method, String>();
			this.values = new HashMap<String, Object>();
			this.properties = properties;
			
			for (Property property : properties) {
				methods.put(property.getGetter(), property.getName());
				if (property.getSetter() != null)
					methods.put(property.getSetter(), property.getName());
			}
			if (definedProperties != null) {
				for (Property property : definedProperties) {
					this.definedProperties.put(property.getName(), property);
					this.values.put(property.getName(), null);
				}
			}
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			
// Path: src/main/java/org/spearal/SpearalContext.java
// public interface SpearalContext {
// 
// 	void configure(Configurable configurable);
// 	void configure(Configurable configurable, boolean append);
// 	
// 	Securizer getSecurizer();
// 	
// 	String alias(Class<?> cls);
// 	String unalias(String aliasedClassName);
// 	
// 	Class<?> loadClass(String classNames, Type target)
// 		throws SecurityException;
// 	Object newInstance(Class<?> cls);
// 	
// 	Property[] getProperties(Class<?> cls);
// 	
// 	Object instantiate(Type type, Object param)
// 		throws InstantiationException, IllegalAccessException;
// 	Object instantiate(Property property, Object param)
// 		throws InstantiationException, IllegalAccessException;
// 	Object instantiatePartial(Class<?> cls, Property[] partialProperties)
// 		throws InstantiationException, IllegalAccessException;
// 	
// 	Coder getCoder(Class<?> valueClass);
// 	
// 	String[] getUnfilterableProperties(Class<?> valueClass);
// 	
// 	Object convert(Object value, Type targetType);
// 	
// 	Property createProperty(String name, Field field, Method getter, Method setter);
// 	
// 	FilteredBeanDescriptor createDescriptor(SpearalPropertyFilter filter, Object value);
// }
// 
// Path: src/main/java/org/spearal/configuration/PartialObjectFactory.java
// public interface PartialObjectProxy {
// 
// 	boolean $hasUndefinedProperties();
// 	boolean $isDefined(String propertyName);
// 	boolean $undefine(String propertyName);
// 	Property[] $getDefinedProperties();
// }
// 
// Path: src/main/java/org/spearal/configuration/PartialObjectFactory.java
// public static class UndefinedPropertyException extends RuntimeException {
// 
// 	private static final long serialVersionUID = 1L;
// 
// 	public UndefinedPropertyException(String propertyName) {
// 		super("Property '" + propertyName + "' is undefined");
// 	}
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyFactory.java
// public interface Property {
// 		
// 	String getName();
// 	Class<?> getType();
// 	Type getGenericType();
// 		
// 	boolean hasField();
// 	Field getField();
// 	boolean hasGetter();
// 	Method getGetter();
// 	boolean hasSetter();
// 	Method getSetter();
// 		
// 	Class<?> getDeclaringClass();
// 		
// 	Object init(ExtendedSpearalDecoder decoder, Object holder)
// 		throws InstantiationException, IllegalAccessException, InvocationTargetException;
// 		
// 	Object get(Object holder)
// 		throws IllegalAccessException, InvocationTargetException;
// 		
// 	void set(Object holder, Object value)
// 		throws IllegalAccessException, InvocationTargetException;
// 		
// 	boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
// 	<A extends Annotation> A getAnnotation(Class<A> annotationClass);
// 		
// 	boolean isReadOnly();
// 		
// 	public void write(ExtendedSpearalEncoder encoder, Object holder)
// 		throws IOException, IllegalAccessException, InvocationTargetException;
// 			
// 	public void read(ExtendedSpearalDecoder decoder, Object holder, int parameterizedType)
// 		throws IOException, InstantiationException, IllegalAccessException, InvocationTargetException;
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyInstantiatorProvider.java
// public interface PropertyInstantiatorProvider extends Repeatable {
// 
// 	public interface PropertyInstantiator {
// 		
// 		Object instantiate(SpearalContext context, Property property, Object param);
// 	}
// 	
// 	PropertyInstantiator getInstantiator(Property property);
// }
// 
// Path: src/main/java/org/spearal/configuration/PropertyInstantiatorProvider.java
// public interface PropertyInstantiator {
// 		
// 	Object instantiate(SpearalContext context, Property property, Object param);
// }
// 
// Path: src/main/java/org/spearal/configuration/TypeInstantiatorProvider.java
// public interface TypeInstantiatorProvider extends Repeatable {
// 
// 	public interface TypeInstantiator {
// 		
// 		Object instantiate(SpearalContext context, Type type, Object param);
// 	}
// 	
// 	TypeInstantiator getInstantiator(Type type);
// }
// 
// Path: src/main/java/org/spearal/configuration/TypeInstantiatorProvider.java
// public interface TypeInstantiator {
// 		
// 	Object instantiate(SpearalContext context, Type type, Object param);
// }


// Path: src/main/java/org/spearal/impl/instantiator/ProxyInstantiator.java
import org.spearal.configuration.PropertyInstantiatorProvider.PropertyInstantiator;
import org.spearal.configuration.TypeInstantiatorProvider;
import org.spearal.configuration.TypeInstantiatorProvider.TypeInstantiator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.spearal.SpearalContext;
import org.spearal.configuration.PartialObjectFactory.PartialObjectProxy;
import org.spearal.configuration.PartialObjectFactory.UndefinedPropertyException;
import org.spearal.configuration.PropertyFactory.Property;
import org.spearal.configuration.PropertyInstantiatorProvider;

		private final Property[] properties;
		private Map<String, Property> definedProperties = new HashMap<String, Property>();
		
		public PropertiesInvocationHandler(SpearalContext context, Property[] properties) {
			this(context, properties, null);
		}
		
		public PropertiesInvocationHandler(SpearalContext context, Property[] properties, Property[] definedProperties) {
			this.context = context;
			this.methods = new HashMap<Method, String>();
			this.values = new HashMap<String, Object>();
			this.properties = properties;
			
			for (Property property : properties) {
				methods.put(property.getGetter(), property.getName());
				if (property.getSetter() != null)
					methods.put(property.getSetter(), property.getName());
			}
			if (definedProperties != null) {
				for (Property property : definedProperties) {
					this.definedProperties.put(property.getName(), property);
					this.values.put(property.getName(), null);
				}
			}
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			
			if (method.getDeclaringClass() == PartialObjectProxy.class) {