// Path: src/main/java/org/azeckoski/reflectutils/ClassFields.java
// public static enum FieldsFilter {
//     /**
//      * all complete (read and write) fields,
//      * getters and setters included
//      */
//     COMPLETE, 
//     /**
//      * (default)
//      * all readable fields (may not be writeable),
//      * includes transient and virtual (getter only) fields
//      */
//     READABLE, 
//     /**
//      * all writeable fields (may not be readable),
//      * public and setters
//      */
//     WRITEABLE, 
//     /**
//      * all accessible serializable fields or getters (skips transients)
//      */
//     SERIALIZABLE,
//     /**
//      * all accessible serializable fields (skips transient fields),
//      * no virtual fields (getters only)
//      */
//     SERIALIZABLE_FIELDS,
//     /**
//      * all fields including ones that are virtual (read or write only)
//      */
//     ALL
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldGetValueException.java
// public class FieldGetValueException extends RuntimeException {
// 
//    /**
//     * the field name we were trying to get the value from 
//     */
//    public String fieldName;
//    /**
//     * the object with the field we were trying to get a value from
//     */
//    public Object object;
// 
//    public FieldGetValueException(String fieldName, Object object, Throwable cause) {
//       super("Failed to get field ("+fieldName+") value from object ("+object+"), cause=" + cause, cause);
//       this.fieldName = fieldName;
//       this.object = object;
//    }
//    public FieldGetValueException(String message, String fieldName, Object object, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//       this.object = object;
//    }
//    
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldSetValueException.java
// public class FieldSetValueException extends RuntimeException {
// 
//    /**
//     * the field name we were trying to set 
//     */
//    public String fieldName;
//    /**
//     * the value we were trying to set on the field
//     */
//    public Object fieldvalue;
//    /**
//     * the object with the field we were trying to set
//     */
//    public Object object;
// 
//    public FieldSetValueException(String fieldName, Object fieldvalue, Object object, Throwable cause) {
//       super("Failed to set field ("+fieldName+") to value ("+fieldvalue+"), cause=" + cause, cause);
//       this.fieldName = fieldName;
//       this.fieldvalue = fieldvalue;
//       this.object = object;
//    }
//    public FieldSetValueException(String message, String fieldName,
//          Object fieldvalue, Object object, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//       this.fieldvalue = fieldvalue;
//       this.object = object;
//    }
//    
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldnameNotFoundException.java
// public class FieldnameNotFoundException extends RuntimeException {
// 
//    public String fieldName;
// 
//    public FieldnameNotFoundException(String fieldName) {
//       this(fieldName, null);
//    }
// 
//    public FieldnameNotFoundException(String fieldName, Throwable cause) {
//       this("Could not find fieldName ("+fieldName+") on object", fieldName, cause);
//    }
// 
//    public FieldnameNotFoundException(String message, String fieldName, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//    }
// 
// }


import java.util.List;
import java.util.Map;
import org.azeckoski.reflectutils.ClassFields.FieldsFilter;
import org.azeckoski.reflectutils.exceptions.FieldGetValueException;
import org.azeckoski.reflectutils.exceptions.FieldSetValueException;
import org.azeckoski.reflectutils.exceptions.FieldnameNotFoundException;
/**
 * $Id: FieldAdapter.java 2 2008-10-01 10:04:26Z azeckoski $
 * $URL: http://reflectutils.googlecode.com/svn/trunk/src/main/java/org/azeckoski/reflectutils/beanutils/FieldAdapter.java $
 * FieldAdapter.java - genericdao - Sep 20, 2008 8:15:36 AM - azeckoski
 **************************************************************************
 * Copyright (c) 2008 Aaron Zeckoski
 * Licensed under the Apache License, Version 2.0
 * 
 * A copy of the Apache License has been included in this 
 * distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 * Aaron Zeckoski (azeckoski @ gmail.com) (aaronz @ vt.edu) (aaron @ caret.cam.ac.uk)
 */

package org.azeckoski.reflectutils.beanutils;




/**
 * Interface that allows us to adapt to special class types like the apache dynabeans without
 * requiring them to be a dependency unless they happen to be in the ClassLoader
 * 
 * @author Aaron Zeckoski (azeckoski @ gmail.com)
 */
public interface FieldAdapter {

    /**
     * @param obj any object
     * @return true if this object is part of the set this adapter is made to handle, false otherwise
     */
    public boolean isAdaptableObject(Object obj);

    /**
     * @param beanClass any class
     * @return true if this class is adaptable, false otherwise
     */
    public boolean isAdaptableClass(Class<?> beanClass);

    /**
     * @return a new instance of the adapted class type based on a sample
     */
    public Object newInstance(Object bean);

    /**
     * @param bean any bean of the adaptable class type
     * @return the list of property names for that bean
     */
    public List<String> getPropertyNames(Object bean);

    /**
     * Finds the type for a field based on the containing object and the field name
     * @param obj any object
     * @param name the name of a field in this object (can be nested, indexed, mapped, etc.)
     * @return the type of the field (will be {@link Object} if the type is indeterminate)
     * @throws FieldnameNotFoundException if the name is invalid for this obj
     * @throws IllegalArgumentException if the params are null
     */
    public Class<?> getFieldType(Object obj, String name);

    /**
     * Get the values of all fields on an object but optionally filter the fields used
     * @param obj any object
     * @param filter (optional) indicates the fields to return the values for, can be null for defaults <br/>
     * WARNING: getting the field values from settable only fields works as expected (i.e. you will an empty map)
     * @return a map of field name -> value
     * @throws IllegalArgumentException if the obj is null
     */
// Path: src/main/java/org/azeckoski/reflectutils/ClassFields.java
// public static enum FieldsFilter {
//     /**
//      * all complete (read and write) fields,
//      * getters and setters included
//      */
//     COMPLETE, 
//     /**
//      * (default)
//      * all readable fields (may not be writeable),
//      * includes transient and virtual (getter only) fields
//      */
//     READABLE, 
//     /**
//      * all writeable fields (may not be readable),
//      * public and setters
//      */
//     WRITEABLE, 
//     /**
//      * all accessible serializable fields or getters (skips transients)
//      */
//     SERIALIZABLE,
//     /**
//      * all accessible serializable fields (skips transient fields),
//      * no virtual fields (getters only)
//      */
//     SERIALIZABLE_FIELDS,
//     /**
//      * all fields including ones that are virtual (read or write only)
//      */
//     ALL
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldGetValueException.java
// public class FieldGetValueException extends RuntimeException {
// 
//    /**
//     * the field name we were trying to get the value from 
//     */
//    public String fieldName;
//    /**
//     * the object with the field we were trying to get a value from
//     */
//    public Object object;
// 
//    public FieldGetValueException(String fieldName, Object object, Throwable cause) {
//       super("Failed to get field ("+fieldName+") value from object ("+object+"), cause=" + cause, cause);
//       this.fieldName = fieldName;
//       this.object = object;
//    }
//    public FieldGetValueException(String message, String fieldName, Object object, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//       this.object = object;
//    }
//    
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldSetValueException.java
// public class FieldSetValueException extends RuntimeException {
// 
//    /**
//     * the field name we were trying to set 
//     */
//    public String fieldName;
//    /**
//     * the value we were trying to set on the field
//     */
//    public Object fieldvalue;
//    /**
//     * the object with the field we were trying to set
//     */
//    public Object object;
// 
//    public FieldSetValueException(String fieldName, Object fieldvalue, Object object, Throwable cause) {
//       super("Failed to set field ("+fieldName+") to value ("+fieldvalue+"), cause=" + cause, cause);
//       this.fieldName = fieldName;
//       this.fieldvalue = fieldvalue;
//       this.object = object;
//    }
//    public FieldSetValueException(String message, String fieldName,
//          Object fieldvalue, Object object, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//       this.fieldvalue = fieldvalue;
//       this.object = object;
//    }
//    
// }
// 
// Path: src/main/java/org/azeckoski/reflectutils/exceptions/FieldnameNotFoundException.java
// public class FieldnameNotFoundException extends RuntimeException {
// 
//    public String fieldName;
// 
//    public FieldnameNotFoundException(String fieldName) {
//       this(fieldName, null);
//    }
// 
//    public FieldnameNotFoundException(String fieldName, Throwable cause) {
//       this("Could not find fieldName ("+fieldName+") on object", fieldName, cause);
//    }
// 
//    public FieldnameNotFoundException(String message, String fieldName, Throwable cause) {
//       super(message, cause);
//       this.fieldName = fieldName;
//    }
// 
// }


// Path: src/main/java/org/azeckoski/reflectutils/beanutils/FieldAdapter.java
import java.util.List;
import java.util.Map;
import org.azeckoski.reflectutils.ClassFields.FieldsFilter;
import org.azeckoski.reflectutils.exceptions.FieldGetValueException;
import org.azeckoski.reflectutils.exceptions.FieldSetValueException;
import org.azeckoski.reflectutils.exceptions.FieldnameNotFoundException;

/**
 * $Id: FieldAdapter.java 2 2008-10-01 10:04:26Z azeckoski $
 * $URL: http://reflectutils.googlecode.com/svn/trunk/src/main/java/org/azeckoski/reflectutils/beanutils/FieldAdapter.java $
 * FieldAdapter.java - genericdao - Sep 20, 2008 8:15:36 AM - azeckoski
 **************************************************************************
 * Copyright (c) 2008 Aaron Zeckoski
 * Licensed under the Apache License, Version 2.0
 * 
 * A copy of the Apache License has been included in this 
 * distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 * Aaron Zeckoski (azeckoski @ gmail.com) (aaronz @ vt.edu) (aaron @ caret.cam.ac.uk)
 */

package org.azeckoski.reflectutils.beanutils;




/**
 * Interface that allows us to adapt to special class types like the apache dynabeans without
 * requiring them to be a dependency unless they happen to be in the ClassLoader
 * 
 * @author Aaron Zeckoski (azeckoski @ gmail.com)
 */
public interface FieldAdapter {

    /**
     * @param obj any object
     * @return true if this object is part of the set this adapter is made to handle, false otherwise
     */
    public boolean isAdaptableObject(Object obj);

    /**
     * @param beanClass any class
     * @return true if this class is adaptable, false otherwise
     */
    public boolean isAdaptableClass(Class<?> beanClass);

    /**
     * @return a new instance of the adapted class type based on a sample
     */
    public Object newInstance(Object bean);

    /**
     * @param bean any bean of the adaptable class type
     * @return the list of property names for that bean
     */
    public List<String> getPropertyNames(Object bean);

    /**
     * Finds the type for a field based on the containing object and the field name
     * @param obj any object
     * @param name the name of a field in this object (can be nested, indexed, mapped, etc.)
     * @return the type of the field (will be {@link Object} if the type is indeterminate)
     * @throws FieldnameNotFoundException if the name is invalid for this obj
     * @throws IllegalArgumentException if the params are null
     */
    public Class<?> getFieldType(Object obj, String name);

    /**
     * Get the values of all fields on an object but optionally filter the fields used
     * @param obj any object
     * @param filter (optional) indicates the fields to return the values for, can be null for defaults <br/>
     * WARNING: getting the field values from settable only fields works as expected (i.e. you will an empty map)
     * @return a map of field name -> value
     * @throws IllegalArgumentException if the obj is null
     */
    public Map<String, Object> getFieldValues(Object obj, FieldsFilter filter);