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 }