Add methods for Cloneables to ObjectUtils (LANG-576).
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@908745 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7a304cfc7b
commit
7b6ab58a01
|
@ -17,6 +17,10 @@
|
|||
package org.apache.commons.lang3;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.lang3.exception.CloneFailedException;
|
||||
|
||||
/**
|
||||
* <p>Operations on <code>Object</code>.</p>
|
||||
|
@ -309,6 +313,48 @@ public class ObjectUtils {
|
|||
return c1 != null ? c1 : c2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone an object.
|
||||
*
|
||||
* @param <T> the type of the object
|
||||
* @param o the object to clone
|
||||
* @return the clone if the object implements {@link Cloneable} otherwise <code>null</code>
|
||||
* @throws CloneFailedException if the object is cloneable and the clone operation fails
|
||||
* @since 3.0
|
||||
*/
|
||||
public static <T> T clone(final T o) {
|
||||
if (o instanceof Cloneable) {
|
||||
try {
|
||||
final Method clone = o.getClass().getMethod("clone", (Class[])null);
|
||||
@SuppressWarnings("unchecked")
|
||||
final T result = (T)clone.invoke(o, (Object[])null);
|
||||
return result;
|
||||
} catch (final NoSuchMethodException e) {
|
||||
throw new CloneFailedException("Cloneable type has no clone method", e);
|
||||
} catch (final IllegalAccessException e) {
|
||||
throw new CloneFailedException("Cannot clone Cloneable type", e);
|
||||
} catch (final InvocationTargetException e) {
|
||||
throw new CloneFailedException("Exception cloning Cloneable type", e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone an object if possible.
|
||||
*
|
||||
* @param <T> the type of the object
|
||||
* @param o the object to clone
|
||||
* @return the clone if the object implements {@link Cloneable} otherwise the object itself
|
||||
* @throws CloneFailedException if the object is cloneable and the clone operation fails
|
||||
* @since 3.0
|
||||
*/
|
||||
public static <T> T cloneIfPossible(final T o) {
|
||||
final T clone = clone(o);
|
||||
return clone == null ? o : clone;
|
||||
}
|
||||
|
||||
// Null
|
||||
//-----------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.commons.lang3.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a clone cannot be created. In contrast to
|
||||
* {@link CloneNotSupportedException} this is a {@link RuntimeException}.
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
* @since 3.0
|
||||
*/
|
||||
public class CloneFailedException extends RuntimeException {
|
||||
// ~ Static fields/initializers ---------------------------------------------
|
||||
|
||||
private static final long serialVersionUID = 20091223L;
|
||||
|
||||
// ~ Constructors -----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a CloneFailedException.
|
||||
*
|
||||
* @param message description of the exception
|
||||
* @since upcoming
|
||||
*/
|
||||
public CloneFailedException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a CloneFailedException.
|
||||
*
|
||||
* @param cause cause of the exception
|
||||
* @since upcoming
|
||||
*/
|
||||
public CloneFailedException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a CloneFailedException.
|
||||
*
|
||||
* @param message description of the exception
|
||||
* @param cause cause of the exception
|
||||
* @since upcoming
|
||||
*/
|
||||
public CloneFailedException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -21,6 +21,9 @@ import java.lang.reflect.Modifier;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.exception.CloneFailedException;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
|
@ -212,4 +215,89 @@ public class ObjectUtilsTest extends TestCase {
|
|||
assertNull( ObjectUtils.min((String)null, (String)null) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#clone(Object)} with a cloneable object.
|
||||
*/
|
||||
public void testCloneOfCloneable() {
|
||||
final CloneableString string = new CloneableString("apache");
|
||||
final CloneableString stringClone = ObjectUtils.clone(string);
|
||||
assertEquals("apache", stringClone.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#clone(Object)} with a not cloneable object.
|
||||
*/
|
||||
public void testCloneOfNotCloneable() {
|
||||
final String string = new String("apache");
|
||||
assertNull(ObjectUtils.clone(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#clone(Object)} with an uncloneable object.
|
||||
*/
|
||||
public void testCloneOfUncloneable() {
|
||||
final UncloneableString string = new UncloneableString("apache");
|
||||
try {
|
||||
ObjectUtils.clone(string);
|
||||
fail("Thrown " + CloneFailedException.class.getName() + " expected");
|
||||
} catch (final CloneFailedException e) {
|
||||
assertEquals(NoSuchMethodException.class, e.getCause().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#cloneIfPossible(Object)} with a cloneable object.
|
||||
*/
|
||||
public void testPossibleCloneOfCloneable() {
|
||||
final CloneableString string = new CloneableString("apache");
|
||||
final CloneableString stringClone = ObjectUtils.cloneIfPossible(string);
|
||||
assertEquals("apache", stringClone.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#cloneIfPossible(Object)} with a not cloneable object.
|
||||
*/
|
||||
public void testPossibleCloneOfNotCloneable() {
|
||||
final String string = new String("apache");
|
||||
assertSame(string, ObjectUtils.cloneIfPossible(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ObjectUtils#cloneIfPossible(Object)} with an uncloneable object.
|
||||
*/
|
||||
public void testPossibleCloneOfUncloneable() {
|
||||
final UncloneableString string = new UncloneableString("apache");
|
||||
try {
|
||||
ObjectUtils.cloneIfPossible(string);
|
||||
fail("Thrown " + CloneFailedException.class.getName() + " expected");
|
||||
} catch (final CloneFailedException e) {
|
||||
assertEquals(NoSuchMethodException.class, e.getCause().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String that is cloneable.
|
||||
*/
|
||||
static final class CloneableString extends MutableObject<String> implements Cloneable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
CloneableString(final String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloneableString clone() throws CloneNotSupportedException {
|
||||
return (CloneableString)super.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String that is not cloneable.
|
||||
*/
|
||||
static final class UncloneableString extends MutableObject<String> implements Cloneable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
UncloneableString(final String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue