001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2021, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 */
028
029package org.jfree.chart.util;
030
031import java.lang.reflect.InvocationTargetException;
032import java.lang.reflect.Method;
033import java.lang.reflect.Modifier;
034import java.util.Collection;
035import java.util.Iterator;
036
037/**
038 * A collection of useful static utility methods for handling classes and object
039 * instantiation.
040 */
041public final class ObjectUtils {
042
043    /**
044     * Default constructor - private.
045     */
046    private ObjectUtils() {
047    }
048
049    /**
050     * Returns {@code true} if the two objects are equal OR both
051     * {@code null}.
052     *
053     * @param o1 object 1 ({@code null} permitted).
054     * @param o2 object 2 ({@code null} permitted).
055     * 
056     * @return {@code true} or {@code false}.
057     * 
058     * @deprecated Use Objects.equals() from the JDK.
059     */
060    public static boolean equal(Object o1, Object o2) {
061        if (o1 == o2) {
062            return true;
063        }
064        if (o1 != null) {
065            return o1.equals(o2);
066        }
067        else {
068            return false;
069        }
070    }
071
072    /**
073     * Returns a hash code for an object, or zero if the object is
074     * {@code null}.
075     *
076     * @param object the object ({@code null} permitted).
077     * @return The object's hash code (or zero if the object is
078     *         {@code null}).
079     */
080    public static int hashCode(Object object) {
081        int result = 0;
082        if (object != null) {
083            result = object.hashCode();
084        }
085        return result;
086    }
087
088    /**
089     * Returns a clone of the specified object, if it can be cloned, otherwise
090     * throws a CloneNotSupportedException.
091     *
092     * @param object the object to clone ({@code null} not permitted).
093     * @return A clone of the specified object.
094     * @throws CloneNotSupportedException if the object cannot be cloned.
095     */
096    public static Object clone(Object object)
097        throws CloneNotSupportedException {
098        if (object == null) {
099            throw new IllegalArgumentException("Null 'object' argument.");
100        }
101        if (object instanceof PublicCloneable) {
102            PublicCloneable pc = (PublicCloneable) object;
103            return pc.clone();
104        }
105        else {
106            try {
107                Method method = object.getClass().getMethod("clone",
108                        (Class[]) null);
109                if (Modifier.isPublic(method.getModifiers())) {
110                    return method.invoke(object, (Object[]) null);
111                }
112            }
113            catch (NoSuchMethodException e) {
114                throw new CloneNotSupportedException("Object without clone() method is impossible.");
115            }
116            catch (IllegalAccessException e) {
117                throw new CloneNotSupportedException("Object.clone(): unable to call method.");
118            }
119            catch (InvocationTargetException e) {
120                throw new CloneNotSupportedException("Object without clone() method is impossible.");
121            }
122        }
123        throw new CloneNotSupportedException("Failed to clone.");
124    }
125
126    /**
127     * Returns a new collection containing clones of all the items in the
128     * specified collection.
129     *
130     * @param collection the collection ({@code null} not permitted).
131     * @return A new collection containing clones of all the items in the
132     *         specified collection.
133     * @throws CloneNotSupportedException if any of the items in the collection
134     *                                    cannot be cloned.
135     */
136    public static Collection deepClone(Collection collection)
137            throws CloneNotSupportedException {
138
139        if (collection == null) {
140            throw new IllegalArgumentException("Null 'collection' argument.");
141        }
142        // all JDK-Collections are cloneable ...
143        // and if the collection is not clonable, then we should throw
144        // a CloneNotSupportedException anyway ...
145        Collection result = (Collection) ObjectUtils.clone(collection);
146        result.clear();
147        Iterator iterator = collection.iterator();
148        while (iterator.hasNext()) {
149            Object item = iterator.next();
150            if (item != null) {
151                result.add(clone(item));
152            }
153            else {
154                result.add(null);
155            }
156        }
157        return result;
158    }
159
160}