// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/fields/FormInput.java
// public interface FormInput<T> {
// 
//     void setOnInputChangedListener(OnInputChangedListener listener);
// 
//     void setError(ValidationError error);
// 
//     Class<T> getType();
//     T getValue();
//     void setValue(T value);
// 
//     ValidationError getError();
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/FieldNotFoundException.java
// public class FieldNotFoundException extends Exception {
// 
//     private final String fieldName;
// 
//     FieldNotFoundException(String fieldName){
//         this.fieldName = fieldName;
//     }
// 
//     public String getFieldName() {
//         return fieldName;
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/IntrospectedObject.java
// public interface IntrospectedObject<T>{
// 
//     T getObject();
//     void assignValue(String property, Object value);
//     void setTarget(T object);
//     FormInput getInputFrom(Field field);
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/IntrospectionTools.java
// public interface IntrospectionTools {
//     <T> IntrospectedObject<T> build(Class<T> clazz, InputBundle fields) throws NonBuildableException, FieldNotFoundException;
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/NonBuildableException.java
// public class NonBuildableException extends Exception {
// 
//     private final Class clazz;
// 
//     public NonBuildableException(Class clazz){
//         this.clazz = clazz;
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/listeners/OnValidTypedFormListener.java
// public interface OnValidTypedFormListener<T> {
// 
//     void onFormValid(TypedForm<T> form, T object);
//     void onFormInvalid(TypedForm<T> form);
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/InputBundle.java
// public class InputBundle {
// 
//     Map<String,FormInput> fieldMap = new HashMap<>();
// 
//     public void put(String propertyName, FormInput formInput) {
//         fieldMap.put(propertyName, formInput);
//     }
// 
//     public Set<String> getPropertiesNames() {
//         return fieldMap.keySet();
//     }
// 
//     public FormInput getInputNamed(String key) {
//         return fieldMap.get(key);
//     }
// 
//     public List<FormInput> getFields() {
//         return new ArrayList<FormInput>(fieldMap.values());
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/TypedFormValidator.java
// public interface TypedFormValidator<T> {
// 
//     ValidationResult validate(IntrospectedObject<T> object, ValidationResult result);
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/validator/ValidationResult.java
// public interface ValidationResult {
// 
//     List<ValidationError> getErrors();
//     void appendError(ValidationError error);
//     boolean isValid();
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/validator/ValidationResultImpl.java
// public class ValidationResultImpl implements ValidationResult {
//     final List<ValidationError> errors = new ArrayList<>();
// 
//     @Override
//     public List<ValidationError> getErrors() {
//         return errors;
//     }
// 
//     @Override
//     public void appendError(ValidationError error) {
//         errors.add(error);
//     }
// 
//     @Override
//     public boolean isValid() {
//         return errors.isEmpty();
//     }
// }


import com.greengrowapps.ggaforms.fields.FormInput;
import com.greengrowapps.ggaforms.introspection.FieldNotFoundException;
import com.greengrowapps.ggaforms.introspection.IntrospectedObject;
import com.greengrowapps.ggaforms.introspection.IntrospectionTools;
import com.greengrowapps.ggaforms.introspection.NonBuildableException;
import com.greengrowapps.ggaforms.listeners.OnValidTypedFormListener;
import com.greengrowapps.ggaforms.validation.InputBundle;
import com.greengrowapps.ggaforms.validation.TypedFormValidator;
import com.greengrowapps.ggaforms.validation.validator.ValidationResult;
import com.greengrowapps.ggaforms.validation.validator.ValidationResultImpl;
import java.security.InvalidParameterException;
import java.util.HashSet;
import java.util.Set;
package com.greengrowapps.ggaforms;




public class TypedFormImpl<T> extends SimpleFormImpl implements TypedForm<T> {

    private final IntrospectedObject<T> introspectedObject;
    private final Set<TypedFormValidator> validators = new HashSet<>();
    private OnValidTypedFormListener<T> listener;

    protected TypedFormImpl(InputBundle fields, Class<T> clazz, IntrospectionTools tools){
        super(fields);
        try {
            introspectedObject = tools.build(clazz,fields);
        } catch (NonBuildableException e) {
            throw new InvalidParameterException("Typed form need to use a class with an empty constructor");
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/fields/FormInput.java
// public interface FormInput<T> {
// 
//     void setOnInputChangedListener(OnInputChangedListener listener);
// 
//     void setError(ValidationError error);
// 
//     Class<T> getType();
//     T getValue();
//     void setValue(T value);
// 
//     ValidationError getError();
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/FieldNotFoundException.java
// public class FieldNotFoundException extends Exception {
// 
//     private final String fieldName;
// 
//     FieldNotFoundException(String fieldName){
//         this.fieldName = fieldName;
//     }
// 
//     public String getFieldName() {
//         return fieldName;
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/IntrospectedObject.java
// public interface IntrospectedObject<T>{
// 
//     T getObject();
//     void assignValue(String property, Object value);
//     void setTarget(T object);
//     FormInput getInputFrom(Field field);
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/IntrospectionTools.java
// public interface IntrospectionTools {
//     <T> IntrospectedObject<T> build(Class<T> clazz, InputBundle fields) throws NonBuildableException, FieldNotFoundException;
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/introspection/NonBuildableException.java
// public class NonBuildableException extends Exception {
// 
//     private final Class clazz;
// 
//     public NonBuildableException(Class clazz){
//         this.clazz = clazz;
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/listeners/OnValidTypedFormListener.java
// public interface OnValidTypedFormListener<T> {
// 
//     void onFormValid(TypedForm<T> form, T object);
//     void onFormInvalid(TypedForm<T> form);
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/InputBundle.java
// public class InputBundle {
// 
//     Map<String,FormInput> fieldMap = new HashMap<>();
// 
//     public void put(String propertyName, FormInput formInput) {
//         fieldMap.put(propertyName, formInput);
//     }
// 
//     public Set<String> getPropertiesNames() {
//         return fieldMap.keySet();
//     }
// 
//     public FormInput getInputNamed(String key) {
//         return fieldMap.get(key);
//     }
// 
//     public List<FormInput> getFields() {
//         return new ArrayList<FormInput>(fieldMap.values());
//     }
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/TypedFormValidator.java
// public interface TypedFormValidator<T> {
// 
//     ValidationResult validate(IntrospectedObject<T> object, ValidationResult result);
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/validator/ValidationResult.java
// public interface ValidationResult {
// 
//     List<ValidationError> getErrors();
//     void appendError(ValidationError error);
//     boolean isValid();
// 
// }
// 
// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/validation/validator/ValidationResultImpl.java
// public class ValidationResultImpl implements ValidationResult {
//     final List<ValidationError> errors = new ArrayList<>();
// 
//     @Override
//     public List<ValidationError> getErrors() {
//         return errors;
//     }
// 
//     @Override
//     public void appendError(ValidationError error) {
//         errors.add(error);
//     }
// 
//     @Override
//     public boolean isValid() {
//         return errors.isEmpty();
//     }
// }


// Path: GGAForms/ggaforms/src/main/java/com/greengrowapps/ggaforms/TypedFormImpl.java
import com.greengrowapps.ggaforms.fields.FormInput;
import com.greengrowapps.ggaforms.introspection.FieldNotFoundException;
import com.greengrowapps.ggaforms.introspection.IntrospectedObject;
import com.greengrowapps.ggaforms.introspection.IntrospectionTools;
import com.greengrowapps.ggaforms.introspection.NonBuildableException;
import com.greengrowapps.ggaforms.listeners.OnValidTypedFormListener;
import com.greengrowapps.ggaforms.validation.InputBundle;
import com.greengrowapps.ggaforms.validation.TypedFormValidator;
import com.greengrowapps.ggaforms.validation.validator.ValidationResult;
import com.greengrowapps.ggaforms.validation.validator.ValidationResultImpl;
import java.security.InvalidParameterException;
import java.util.HashSet;
import java.util.Set;

package com.greengrowapps.ggaforms;




public class TypedFormImpl<T> extends SimpleFormImpl implements TypedForm<T> {

    private final IntrospectedObject<T> introspectedObject;
    private final Set<TypedFormValidator> validators = new HashSet<>();
    private OnValidTypedFormListener<T> listener;

    protected TypedFormImpl(InputBundle fields, Class<T> clazz, IntrospectionTools tools){
        super(fields);
        try {
            introspectedObject = tools.build(clazz,fields);
        } catch (NonBuildableException e) {
            throw new InvalidParameterException("Typed form need to use a class with an empty constructor");
        } catch (FieldNotFoundException e) {