View Javadoc
1   /**
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3    *
4    * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
5    * Portions Copyright 2013-2015 Philip Helger
6    *
7    * The contents of this file are subject to the terms of either the GNU
8    * General Public License Version 2 only ("GPL") or the Common Development
9    * and Distribution License("CDDL") (collectively, the "License").  You
10   * may not use this file except in compliance with the License.  You can
11   * obtain a copy of the License at
12   * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
13   * or packager/legal/LICENSE.txt.  See the License for the specific
14   * language governing permissions and limitations under the License.
15   *
16   * When distributing the software, include this License Header Notice in each
17   * file and include the License file at packager/legal/LICENSE.txt.
18   *
19   * GPL Classpath Exception:
20   * Oracle designates this particular file as subject to the "Classpath"
21   * exception as provided by Oracle in the GPL Version 2 section of the License
22   * file that accompanied this code.
23   *
24   * Modifications:
25   * If applicable, add the following below the License Header, with the fields
26   * enclosed by brackets [] replaced by your own identifying information:
27   * "Portions Copyright [year] [name of copyright owner]"
28   *
29   * Contributor(s):
30   * If you wish your version of this file to be governed by only the CDDL or
31   * only the GPL Version 2, indicate your decision by adding "[Contributor]
32   * elects to include this software in this distribution under the [CDDL or GPL
33   * Version 2] license."  If you don't indicate a single choice of license, a
34   * recipient has the option to distribute your version of this file under
35   * either the CDDL, the GPL Version 2 or to extend the choice of license to
36   * its licensees as provided above.  However, if you add GPL Version 2 code
37   * and therefore, elected the GPL Version 2 license, then the option applies
38   * only if the new code is made subject to such option by the copyright
39   * holder.
40   */
41  package com.helger.jcodemodel.util;
42  
43  import java.util.Arrays;
44  
45  import javax.annotation.Nullable;
46  import javax.annotation.concurrent.Immutable;
47  
48  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
49  
50  /**
51   * A small helper class that provides helper methods for easy
52   * <code>equals</code> method generation
53   *
54   * @author Philip Helger
55   */
56  @Immutable
57  public final class JCEqualsHelper
58  {
59    private JCEqualsHelper ()
60    {}
61  
62    public static boolean isEqual (final boolean aObj1, final boolean aObj2)
63    {
64      return aObj1 == aObj2;
65    }
66  
67    public static boolean isEqual (final byte aObj1, final byte aObj2)
68    {
69      return aObj1 == aObj2;
70    }
71  
72    public static boolean isEqual (final char aObj1, final char aObj2)
73    {
74      return aObj1 == aObj2;
75    }
76  
77    /**
78     * Check if two double values are equal. This is necessary, because in some
79     * cases, the "==" operator returns wrong results.
80     *
81     * @param aObj1
82     *        First double
83     * @param aObj2
84     *        Second double
85     * @return <code>true</code> if they are equal.
86     */
87    public static boolean isEqual (final double aObj1, final double aObj2)
88    {
89      // ESCA-JAVA0078:
90      // Special overload for "double" required!
91      return (aObj1 == aObj2) || (Double.doubleToLongBits (aObj1) == Double.doubleToLongBits (aObj2));
92    }
93  
94    /**
95     * Check if two float values are equal. This is necessary, because in some
96     * cases, the "==" operator returns wrong results.
97     *
98     * @param aObj1
99     *        First float
100    * @param aObj2
101    *        Second float
102    * @return <code>true</code> if they are equal.
103    */
104   public static boolean isEqual (final float aObj1, final float aObj2)
105   {
106     // ESCA-JAVA0078:
107     // Special overload for "float" required!
108     return (aObj1 == aObj2) || (Float.floatToIntBits (aObj1) == Float.floatToIntBits (aObj2));
109   }
110 
111   public static boolean isEqual (final int aObj1, final int aObj2)
112   {
113     return aObj1 == aObj2;
114   }
115 
116   public static boolean isEqual (final long aObj1, final long aObj2)
117   {
118     return aObj1 == aObj2;
119   }
120 
121   public static boolean isEqual (final short aObj1, final short aObj2)
122   {
123     return aObj1 == aObj2;
124   }
125 
126   public static boolean isEqual (@Nullable final Object aObj1, @Nullable final Object aObj2)
127   {
128     // Same object - check first
129     if (aObj1 == aObj2)
130       return true;
131 
132     // Is only one value null?
133     if (aObj1 == null || aObj2 == null)
134       return false;
135 
136     // Check whether the implementation classes are identical
137     final Class <?> aClass1 = aObj1.getClass ();
138     final Class <?> aClass2 = aObj2.getClass ();
139     if (!aClass1.equals (aClass2))
140     {
141       // Not the same class -> not equal!
142       return false;
143     }
144 
145     if (aClass1.isArray ())
146     {
147       // Special handling for arrays
148       final Object [] aArray1 = (Object []) aObj1;
149       final Object [] aArray2 = (Object []) aObj2;
150       // Size check
151       final int nLength = aArray1.length;
152       if (nLength != aArray2.length)
153         return false;
154       // Content check
155       for (int i = 0; i < nLength; i++)
156         if (!isEqual (aArray1[i], aArray2[i]))
157           return false;
158       return true;
159     }
160 
161     // Primitive arrays
162     if (aClass1.equals (boolean [].class))
163       return Arrays.equals ((boolean []) aObj1, (boolean []) aObj2);
164     if (aClass1.equals (byte [].class))
165       return Arrays.equals ((byte []) aObj1, (byte []) aObj2);
166     if (aClass1.equals (char [].class))
167       return Arrays.equals ((char []) aObj1, (char []) aObj2);
168     if (aClass1.equals (double [].class))
169       return Arrays.equals ((double []) aObj1, (double []) aObj2);
170     if (aClass1.equals (float [].class))
171       return Arrays.equals ((float []) aObj1, (float []) aObj2);
172     if (aClass1.equals (int [].class))
173       return Arrays.equals ((int []) aObj1, (int []) aObj2);
174     if (aClass1.equals (long [].class))
175       return Arrays.equals ((long []) aObj1, (long []) aObj2);
176     if (aClass1.equals (short [].class))
177       return Arrays.equals ((short []) aObj1, (short []) aObj2);
178 
179     // Non-array
180     return aObj1.equals (aObj2);
181   }
182 
183   @SuppressFBWarnings ({ "ES_COMPARING_PARAMETER_STRING_WITH_EQ" })
184   public static boolean nullSafeEqualsIgnoreCase (@Nullable final String sObj1, @Nullable final String sObj2)
185   {
186     return sObj1 == null ? sObj2 == null : sObj1.equalsIgnoreCase (sObj2);
187   }
188 }