Skip to content

Commit

Permalink
Introduce EqualsUtil and HashCode.(Builder|Cache)
Browse files Browse the repository at this point in the history
  • Loading branch information
Flowdalic committed Jun 12, 2019
1 parent 92b02af commit fa0c16d
Show file tree
Hide file tree
Showing 8 changed files with 551 additions and 167 deletions.
59 changes: 21 additions & 38 deletions smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.util.Locale;
import java.util.Set;

import org.jivesoftware.smack.util.EqualsUtil;
import org.jivesoftware.smack.util.HashCode;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.TypedCloneable;
import org.jivesoftware.smack.util.XmlStringBuilder;
Expand Down Expand Up @@ -561,32 +563,22 @@ public String getSubject() {
return subject;
}

private final HashCode.Cache hashCodeCache = new HashCode.Cache();

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
if (language != null) {
result = prime * result + this.language.hashCode();
}
result = prime * result + this.subject.hashCode();
return result;
return hashCodeCache.getHashCode(c ->
c.append(language)
.append(subject)
);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Subject other = (Subject) obj;
// simplified comparison because language and subject are always set
return this.language.equals(other.language) && this.subject.equals(other.subject);
return EqualsUtil.equals(this, obj, (e, o) ->
e.append(language, o.language)
.append(subject, o.subject)
);
}

@Override
Expand Down Expand Up @@ -670,31 +662,22 @@ public String getMessage() {
return message;
}

private final HashCode.Cache hashCodeCache = new HashCode.Cache();

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
if (language != null) {
result = prime * result + this.language.hashCode();
}
result = prime * result + this.message.hashCode();
return result;
return hashCodeCache.getHashCode(c ->
c.append(language)
.append(message)
);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Body other = (Body) obj;
// simplified comparison because language and message are always set
return Objects.equals(this.language, other.language) && this.message.equals(other.message);
return EqualsUtil.equals(this, obj, (e, o) ->
e.append(language, o.language)
.append(message, o.message)
);
}

@Override
Expand Down
243 changes: 243 additions & 0 deletions smack-core/src/main/java/org/jivesoftware/smack/util/EqualsUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
/**
*
* Copyright 2019 Florian Schmaus.
*
* Licensed 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.jivesoftware.smack.util;

public final class EqualsUtil {

private EqualsUtil() {
}

public static <T> boolean equals(T thisObject, Object other, EqualsComperator<T> equalsComperator) {
if (other == null) {
return false;
}
if (thisObject == other) {
return true;
}
@SuppressWarnings("unchecked")
Class<T> thisObjectClass = (Class<T>) thisObject.getClass();
if (thisObjectClass != other.getClass()) {
return false;
}

EqualsUtil.Builder equalsBuilder = new EqualsUtil.Builder();

equalsComperator.compare(equalsBuilder, thisObjectClass.cast(other));

return equalsBuilder.isEquals;
}

@FunctionalInterface
public interface EqualsComperator<T> {
void compare(EqualsUtil.Builder equalsBuilder, T other);
}

public static final class Builder {
private boolean isEquals = true;

private Builder() {
}

private void nullSafeCompare(Object left, Object right, Runnable runnable) {
if (!isEquals) {
return;
}

if (left == right) {
return;
}

if (left == null || right == null) {
isEquals = false;
return;
}

runnable.run();
}

public <O> Builder append(O left, O right) {
if (!isEquals) {
return this;
}

if (left == right) {
return this;
}

if (left == null || right == null) {
isEquals = false;
return this;
}

isEquals = left.equals(right);
return this;
}

public Builder append(boolean left, boolean right) {
if (!isEquals) {
return this;
}

isEquals = left == right;
return this;
}

public Builder append(boolean[] left, boolean[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(byte left, byte right) {
if (!isEquals) {
return this;
}

isEquals = left == right;
return this;
}

public Builder append(byte[] left, byte[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(char left, char right) {
if (!isEquals) {
return this;
}

isEquals = left == right;
return this;
}

public Builder append(char[] left, char[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(double left, double right) {
if (!isEquals) {
return this;
}

return append(Double.doubleToLongBits(left), Double.doubleToLongBits(right));
}

public Builder append(double[] left, double[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(float left, float right) {
if (!isEquals) {
return this;
}

return append(Float.floatToIntBits(left), Float.floatToIntBits(right));
}

public Builder append(float[] left, float[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(int left, int right) {
if (!isEquals) {
return this;
}

isEquals = left == right;
return this;
}

public Builder append(int[] left, int[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}

public Builder append(long left, long right) {
if (!isEquals) {
return this;
}

isEquals = left == right;
return this;
}

public Builder append(long[] left, long[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
}

}
Loading

0 comments on commit fa0c16d

Please sign in to comment.