001/** 002 * 003 * Copyright 2019-2020 Florian Schmaus. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.util; 018 019public final class EqualsUtil { 020 021 private EqualsUtil() { 022 } 023 024 public static <T> boolean equals(T thisObject, Object other, EqualsComperator<T> equalsComperator) { 025 if (other == null) { 026 return false; 027 } 028 if (thisObject == other) { 029 return true; 030 } 031 @SuppressWarnings("unchecked") 032 Class<T> thisObjectClass = (Class<T>) thisObject.getClass(); 033 if (thisObjectClass != other.getClass()) { 034 return false; 035 } 036 037 int thisHashCode = thisObject.hashCode(); 038 int otherHashCode = other.hashCode(); 039 if (thisHashCode != otherHashCode) { 040 return false; 041 } 042 043 EqualsUtil.Builder equalsBuilder = new EqualsUtil.Builder(); 044 045 equalsComperator.compare(equalsBuilder, thisObjectClass.cast(other)); 046 047 return equalsBuilder.isEquals; 048 } 049 050 @FunctionalInterface 051 public interface EqualsComperator<T> { 052 void compare(EqualsUtil.Builder equalsBuilder, T other); 053 } 054 055 public static final class Builder { 056 private boolean isEquals = true; 057 058 private Builder() { 059 } 060 061 private void nullSafeCompare(Object left, Object right, Runnable runnable) { 062 if (!isEquals) { 063 return; 064 } 065 066 if (left == right) { 067 return; 068 } 069 070 if (left == null || right == null) { 071 isEquals = false; 072 return; 073 } 074 075 runnable.run(); 076 } 077 078 public <O> Builder append(O left, O right) { 079 if (!isEquals) { 080 return this; 081 } 082 083 if (left == right) { 084 return this; 085 } 086 087 if (left == null || right == null) { 088 isEquals = false; 089 return this; 090 } 091 092 isEquals = left.equals(right); 093 return this; 094 } 095 096 public Builder append(boolean left, boolean right) { 097 if (!isEquals) { 098 return this; 099 } 100 101 isEquals = left == right; 102 return this; 103 } 104 105 public Builder append(boolean[] left, boolean[] right) { 106 nullSafeCompare(left, right, () -> { 107 if (left.length != right.length) { 108 isEquals = false; 109 return; 110 } 111 for (int i = 0; i < left.length && isEquals; i++) { 112 append(left[i], right[i]); 113 } 114 }); 115 return this; 116 } 117 118 public Builder append(byte left, byte right) { 119 if (!isEquals) { 120 return this; 121 } 122 123 isEquals = left == right; 124 return this; 125 } 126 127 public Builder append(byte[] left, byte[] right) { 128 nullSafeCompare(left, right, () -> { 129 if (left.length != right.length) { 130 isEquals = false; 131 return; 132 } 133 for (int i = 0; i < left.length && isEquals; i++) { 134 append(left[i], right[i]); 135 } 136 }); 137 return this; 138 } 139 140 public Builder append(char left, char right) { 141 if (!isEquals) { 142 return this; 143 } 144 145 isEquals = left == right; 146 return this; 147 } 148 149 public Builder append(char[] left, char[] right) { 150 nullSafeCompare(left, right, () -> { 151 if (left.length != right.length) { 152 isEquals = false; 153 return; 154 } 155 for (int i = 0; i < left.length && isEquals; i++) { 156 append(left[i], right[i]); 157 } 158 }); 159 return this; 160 } 161 162 public Builder append(double left, double right) { 163 if (!isEquals) { 164 return this; 165 } 166 167 return append(Double.doubleToLongBits(left), Double.doubleToLongBits(right)); 168 } 169 170 public Builder append(double[] left, double[] right) { 171 nullSafeCompare(left, right, () -> { 172 if (left.length != right.length) { 173 isEquals = false; 174 return; 175 } 176 for (int i = 0; i < left.length && isEquals; i++) { 177 append(left[i], right[i]); 178 } 179 }); 180 return this; 181 } 182 183 public Builder append(float left, float right) { 184 if (!isEquals) { 185 return this; 186 } 187 188 return append(Float.floatToIntBits(left), Float.floatToIntBits(right)); 189 } 190 191 public Builder append(float[] left, float[] right) { 192 nullSafeCompare(left, right, () -> { 193 if (left.length != right.length) { 194 isEquals = false; 195 return; 196 } 197 for (int i = 0; i < left.length && isEquals; i++) { 198 append(left[i], right[i]); 199 } 200 }); 201 return this; 202 } 203 204 public Builder append(int left, int right) { 205 if (!isEquals) { 206 return this; 207 } 208 209 isEquals = left == right; 210 return this; 211 } 212 213 public Builder append(int[] left, int[] right) { 214 nullSafeCompare(left, right, () -> { 215 if (left.length != right.length) { 216 isEquals = false; 217 return; 218 } 219 for (int i = 0; i < left.length && isEquals; i++) { 220 append(left[i], right[i]); 221 } 222 }); 223 return this; 224 } 225 226 public Builder append(long left, long right) { 227 if (!isEquals) { 228 return this; 229 } 230 231 isEquals = left == right; 232 return this; 233 } 234 235 public Builder append(long[] left, long[] right) { 236 nullSafeCompare(left, right, () -> { 237 if (left.length != right.length) { 238 isEquals = false; 239 return; 240 } 241 for (int i = 0; i < left.length && isEquals; i++) { 242 append(left[i], right[i]); 243 } 244 }); 245 return this; 246 } 247 } 248 249}