// Path: core/src/main/java/net/sf/beanlib/PropertyInfo.java
// public class PropertyInfo {
// 
//     private final String propertyName;
// 
//     private final Object fromBean;
// 
//     private final Object toBean;
// 
//     public PropertyInfo(String propertyName, Object fromBean, Object toBean) {
//         this.propertyName = propertyName;
//         this.fromBean = fromBean;
//         this.toBean = toBean;
//     }
// 
//     /** Returns the property name. */
//     public String getPropertyName() {
//         return propertyName;
//     }
// 
//     /** Returns the Java Bean from which the property is read. */
//     public Object getFromBean() {
//         return fromBean;
//     }
// 
//     /** Returns the Java Bean to which the property is to be written. */
//     public Object getToBean() {
//         return toBean;
//     }
// 
//     @Override
//     public String toString() {
//         return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
//     }
// }


import net.sf.beanlib.PropertyInfo;
/*
 * Copyright 2007 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.beanlib.spi;


/**
 * Custom Bean Transformer SPI.
 * <p>
 * Used to provide custom transformation that takes precedence over the default transformation.
 * <h2>Quick Start</h2> For example, by default when BeanReplicator is replicating the content of a JavaBean, it would
 * try to instantiate the target class via the no-arg constructor. If the no-arg constructor is not defined (such as in
 * the Point class below), it would cause a NoSuchMethodException to be thrown:
 *
 * <pre>
 * <blockquote>public class Point {
 *     private final int x, y;
 *
 *     // missing no-arg constructor
 *     public Point(int x, int y) {
 *         this.x = x;
 *         this.y = y;
 *     }
 *     public int getX() { return x; }
 *     public int getY() { return y; }
 * }
 *
 * public class Bean {
 *     private Point point;
 *     public Point getPoint() { return point; }
 *     public void setPoint(Point point) { this.point = point; }
 * }
 *
 * ...
 * // Initialize a bean
 * Bean from = new Bean();
 * from.setPoint(new Point(1,2));
 *
 * // Tries to replicate the bean using the default implementation
 * BeanReplicator replicator = new BeanReplicator();
 * // Will cause NoSuchMethodException, as Point does not have a no-arg constructor
 * Bean to = replicator.replicateBean(from);
 * </blockquote>
 * </pre>
 *
 * One way to get around this problem is to define a custom transformer and the respective factory:
 *
 * <pre>
 * <blockquote>public class MyBeanTransformer implements CustomBeanTransformerSpi {
 *     public  boolean isTransformable(Object from, Class toClass, PropertyInfo propertyInfo) {
 *         return toClass == Point.class;
 *     }
 *
 *     public <T> T transform(Object in, Class<T> toClass, PropertyInfo propertyInfo) {
 *         Point from = (Point)in;
 *         // Note the framework takes care of the issue of object identity,
 *         // so we don't need to here.
 *         return (T)new Point(from.getX(), from.getY());
 *     }
 * }
 *
 * public class MyBeanTransformerFactory implements CustomBeanTransformerSpi.Factory {
 *     public CustomBeanTransformerSpi newCustomBeanTransformer(BeanTransformerSpi beanTransformer) {
 *         return new MyBeanTransformer();
 *     }
 * }
 *
 * ...
 * // Initialize a bean
 * Bean from = new Bean();
 * from.setPoint(new Point(1,2));
 *
 * // Partially overrides the default transformer behavior
 * BeanTransformerSpi transformer = new BeanTransformer(new MyBeanTransformerFactory());
 * BeanReplicator replicator = new BeanReplicator(transformer);
 *
 * // Replicates the bean
 * Bean to = replicator.replicateBean(from); // now works!
 * </blockquote>
 * </pre>
 *
 * <h2>Customizing HibernateBeanReplicator</h2> Customizing the behavior of HibernateBeanReplicator is basically
 * identical to that of BeanReplicator as decribed above. For example, assuming the same MyBeanTransformerFactory
 * defined above is used,
 *
 * <pre>
 * <blockquote>// Partially overrides the default Hibernate bean transformer's behavior
 * HibernateBeanReplicator replicator = new Hibernate3BeanReplicator();
 * replicator.initCustomTransformerFactory(new MyBeanTransformerFactory());
 * replicator.copy(...);
 * </blockquote>
 * </pre>
 *
 * @see BeanTransformerSpi
 * @author Joe D. Velopar
 */
public interface CustomBeanTransformerSpi extends Transformable {

    /**
     * Custom Bean Transformer Factory SPI.
     *
     * @author Joe D. Velopar
     */
    public static interface Factory {

        /**
         * Returns a custom transformer.
         *
         * @param contextBeanTransformer the context bean transformer currently used to provide the default
         *            transformation behavior.
         */
        CustomBeanTransformerSpi newCustomBeanTransformer(BeanTransformerSpi contextBeanTransformer);
    }

    /**
     * Returns true if the given object is to be transformed by this transformer; false otherwise.
     *
     * @param from source object
     * @param propertyInfo If null, it means the in object is a root level object. Otherwise, propertyInfo contains
     *            information about the input object as a java bean property value to be transformed.
     * @param toClass target class
     */
// Path: core/src/main/java/net/sf/beanlib/PropertyInfo.java
// public class PropertyInfo {
// 
//     private final String propertyName;
// 
//     private final Object fromBean;
// 
//     private final Object toBean;
// 
//     public PropertyInfo(String propertyName, Object fromBean, Object toBean) {
//         this.propertyName = propertyName;
//         this.fromBean = fromBean;
//         this.toBean = toBean;
//     }
// 
//     /** Returns the property name. */
//     public String getPropertyName() {
//         return propertyName;
//     }
// 
//     /** Returns the Java Bean from which the property is read. */
//     public Object getFromBean() {
//         return fromBean;
//     }
// 
//     /** Returns the Java Bean to which the property is to be written. */
//     public Object getToBean() {
//         return toBean;
//     }
// 
//     @Override
//     public String toString() {
//         return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
//     }
// }


// Path: core/src/main/java/net/sf/beanlib/spi/CustomBeanTransformerSpi.java
import net.sf.beanlib.PropertyInfo;

/*
 * Copyright 2007 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.beanlib.spi;


/**
 * Custom Bean Transformer SPI.
 * <p>
 * Used to provide custom transformation that takes precedence over the default transformation.
 * <h2>Quick Start</h2> For example, by default when BeanReplicator is replicating the content of a JavaBean, it would
 * try to instantiate the target class via the no-arg constructor. If the no-arg constructor is not defined (such as in
 * the Point class below), it would cause a NoSuchMethodException to be thrown:
 *
 * <pre>
 * <blockquote>public class Point {
 *     private final int x, y;
 *
 *     // missing no-arg constructor
 *     public Point(int x, int y) {
 *         this.x = x;
 *         this.y = y;
 *     }
 *     public int getX() { return x; }
 *     public int getY() { return y; }
 * }
 *
 * public class Bean {
 *     private Point point;
 *     public Point getPoint() { return point; }
 *     public void setPoint(Point point) { this.point = point; }
 * }
 *
 * ...
 * // Initialize a bean
 * Bean from = new Bean();
 * from.setPoint(new Point(1,2));
 *
 * // Tries to replicate the bean using the default implementation
 * BeanReplicator replicator = new BeanReplicator();
 * // Will cause NoSuchMethodException, as Point does not have a no-arg constructor
 * Bean to = replicator.replicateBean(from);
 * </blockquote>
 * </pre>
 *
 * One way to get around this problem is to define a custom transformer and the respective factory:
 *
 * <pre>
 * <blockquote>public class MyBeanTransformer implements CustomBeanTransformerSpi {
 *     public  boolean isTransformable(Object from, Class toClass, PropertyInfo propertyInfo) {
 *         return toClass == Point.class;
 *     }
 *
 *     public <T> T transform(Object in, Class<T> toClass, PropertyInfo propertyInfo) {
 *         Point from = (Point)in;
 *         // Note the framework takes care of the issue of object identity,
 *         // so we don't need to here.
 *         return (T)new Point(from.getX(), from.getY());
 *     }
 * }
 *
 * public class MyBeanTransformerFactory implements CustomBeanTransformerSpi.Factory {
 *     public CustomBeanTransformerSpi newCustomBeanTransformer(BeanTransformerSpi beanTransformer) {
 *         return new MyBeanTransformer();
 *     }
 * }
 *
 * ...
 * // Initialize a bean
 * Bean from = new Bean();
 * from.setPoint(new Point(1,2));
 *
 * // Partially overrides the default transformer behavior
 * BeanTransformerSpi transformer = new BeanTransformer(new MyBeanTransformerFactory());
 * BeanReplicator replicator = new BeanReplicator(transformer);
 *
 * // Replicates the bean
 * Bean to = replicator.replicateBean(from); // now works!
 * </blockquote>
 * </pre>
 *
 * <h2>Customizing HibernateBeanReplicator</h2> Customizing the behavior of HibernateBeanReplicator is basically
 * identical to that of BeanReplicator as decribed above. For example, assuming the same MyBeanTransformerFactory
 * defined above is used,
 *
 * <pre>
 * <blockquote>// Partially overrides the default Hibernate bean transformer's behavior
 * HibernateBeanReplicator replicator = new Hibernate3BeanReplicator();
 * replicator.initCustomTransformerFactory(new MyBeanTransformerFactory());
 * replicator.copy(...);
 * </blockquote>
 * </pre>
 *
 * @see BeanTransformerSpi
 * @author Joe D. Velopar
 */
public interface CustomBeanTransformerSpi extends Transformable {

    /**
     * Custom Bean Transformer Factory SPI.
     *
     * @author Joe D. Velopar
     */
    public static interface Factory {

        /**
         * Returns a custom transformer.
         *
         * @param contextBeanTransformer the context bean transformer currently used to provide the default
         *            transformation behavior.
         */
        CustomBeanTransformerSpi newCustomBeanTransformer(BeanTransformerSpi contextBeanTransformer);
    }

    /**
     * Returns true if the given object is to be transformed by this transformer; false otherwise.
     *
     * @param from source object
     * @param propertyInfo If null, it means the in object is a root level object. Otherwise, propertyInfo contains
     *            information about the input object as a java bean property value to be transformed.
     * @param toClass target class
     */
    boolean isTransformable(Object from, Class<?> toClass, PropertyInfo propertyInfo);