/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package org.jgap.impl; import java.io.*; import java.lang.reflect.*; import org.jgap.util.*; import org.jgap.*; /** * Default clone handler supporting IApplicationData as well as implementations * of Cloneable (for the latter: in case the clone-method is accessible via * reflection). * * @author Klaus Meffert * @since 2.6 */ public class DefaultCloneHandler implements ICloneHandler, ICloneable, Serializable, Comparable { /** String containing the CVS revision. Read out via reflection!*/ private final static String CVS_REVISION = "$Revision: 1.14 $"; /** * Handles all implementations of IApplicationData as well as all of * java.lang.Cloneable (for which the clone-method is accessible via * reflection. This is not the case for package protected classes, e.g.). * * @param a_obj the object to check for (maybe null) * @param a_clazz the class to check for whether it is handled (maybe null) * @return true in case class is clonable via this handler * * @author Klaus Meffert * @since 2.6 */ public boolean isHandlerFor(final Object a_obj, final Class a_clazz) { Class clazz; if (a_clazz == null) { if (a_obj == null) { return false; } clazz = a_obj.getClass(); } else { clazz = a_clazz; } if (IApplicationData.class.isAssignableFrom(clazz)) { return true; } if (ICloneable.class.isAssignableFrom(clazz)) { return true; } if (Cloneable.class.isAssignableFrom(clazz)) { // Ensure access via reflection is possible. // Thank you Java for providing only a marker interface and not // something convenient :-( // ------------------------------------------------------------ boolean result; try { Method m = clazz.getMethod("clone", new Class[] {}); boolean modified = false; if (!m.isAccessible()) { m.setAccessible(true); modified = true; } result = m.isAccessible(); if (modified) { m.setAccessible(false); } } catch (Exception ex) { return false; } return result; } else { return false; } } /** * Performs the clone operation. * * @param a_objToClone the object to clone * @param a_class not considered here * @param a_params not considered here * * @return Object * * @author Klaus Meffert * @since 2.6 */ public Object perform(final Object a_objToClone, final Class a_class, final Object a_params) { Class clazz; if (a_class == null) { if (a_objToClone == null) { return null; } clazz = a_objToClone.getClass(); } else { clazz = a_class; } if (ICloneable.class.isAssignableFrom(clazz)) { try { return ( (ICloneable) a_objToClone).clone(); } catch (CloneException cex) { throw new IllegalStateException(cex); } } if (IApplicationData.class.isAssignableFrom(a_objToClone.getClass())) { try { return ( (IApplicationData) a_objToClone).clone(); } catch (CloneNotSupportedException cex) { throw new IllegalStateException(cex); } } // Support Cloneable interface by looking for clone() method // via introspection. // --------------------------------------------------------- try { Method cloneMethod = a_objToClone.getClass().getMethod( "clone", new Class[] {}); cloneMethod.setAccessible(true); return cloneMethod.invoke(a_objToClone, new Object[] {}); } catch (InvocationTargetException iex) { throw new IllegalStateException(iex.getTargetException()); } catch (Throwable ex) { throw new IllegalStateException(ex); } } /** * @return deep clone of this instance * * @author Klaus Meffert * @since 3.2 */ public Object clone() { return new DefaultCloneHandler(); } /** * @param a_other sic * @return as always * * @author Klaus Meffert * @since 3.2 */ public int compareTo(Object a_other) { if (a_other.getClass().equals(getClass())) { return 0; } else { return getClass().getName().compareTo(a_other.getClass().getName()); } } }