/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util.visitor;
import java.lang.reflect.InvocationTargetException;
import com.servoy.j2db.query.IQueryElement;
import com.servoy.j2db.util.Immutable;
/**
* Visitor class to for performing a deep clone that maintains tree structure.
*
* @see IVisitable
* @author rgansevles
*
*/
public class DeepCloneVisitor implements IVisitor
{
public static IVisitor createDeepCloneVisitor()
{
return new VisitOnceDelegateVisitor(new DeepCloneVisitor());
}
private DeepCloneVisitor()
{
}
public Object visit(Object o)
{
if (o == null || o instanceof Immutable)
{
// do not need to make a copy
return new IVisitor.VistorResult(o, false);
}
try
{
if (o instanceof IQueryElement)
{
return ((IQueryElement)o).shallowClone();
}
// don't know why we can't use the reflection method below for object arrays, it throws NoSuchMethodException
if (o instanceof Object[])
{
return ((Object[])o).clone();
}
if (o instanceof byte[])
{
return ((byte[])o).clone();
}
if (o instanceof int[])
{
return ((int[])o).clone();
}
if (o instanceof short[])
{
return ((short[])o).clone();
}
if (o instanceof long[])
{
return ((long[])o).clone();
}
if (o instanceof float[])
{
return ((float[])o).clone();
}
if (o instanceof double[])
{
return ((double[])o).clone();
}
if (o instanceof char[])
{
return ((char[])o).clone();
}
if (o instanceof boolean[])
{
return ((boolean[])o).clone();
}
// something else than the known stuff, is there a clone method?
if (o instanceof Cloneable)
{
try
{
// assume clone() is a shallow clone like it is for ArrayList, HashMap, Object[] etc.
return o.getClass().getMethod("clone", (Class[])null).invoke(o, (Object[])null); //$NON-NLS-1$
}
catch (NoSuchMethodException e)
{
// Cloneable but no clone method???
throw new RuntimeException("Cannot clone Cloneable class " + o.getClass()); //$NON-NLS-1$
}
catch (Exception e)
{
if (e instanceof InvocationTargetException && ((InvocationTargetException)e).getTargetException() instanceof CloneNotSupportedException)
{
throw (CloneNotSupportedException)((InvocationTargetException)e).getTargetException();
}
throw new CloneNotSupportedException(o.getClass().getName());
}
}
// cannot clone, assume immutable primitives like Integer, String
return o;
}
catch (CloneNotSupportedException e)
{
throw new RuntimeException("Clone not supported in class " + o.getClass(), e); //$NON-NLS-1$
}
}
}