package de.invesdwin.util.lang;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.nustaq.serialization.FSTConfiguration;
import de.invesdwin.norva.apt.staticfacade.StaticFacadeDefinition;
import de.invesdwin.norva.beanpath.BeanPathObjects;
import de.invesdwin.norva.beanpath.IDeepCloneProvider;
import de.invesdwin.util.lang.internal.AObjectsStaticFacade;
@Immutable
@StaticFacadeDefinition(name = "de.invesdwin.util.lang.internal.AObjectsStaticFacade", targets = {
BeanPathObjects.class })
public final class Objects extends AObjectsStaticFacade {
public static final FSTConfiguration SERIALIZATION_CONFIG = FSTConfiguration.getDefaultConfiguration();
public static final Set<String> REFLECTION_EXCLUDED_FIELDS = new HashSet<String>();
static {
//datanucleus enhancer fix
REFLECTION_EXCLUDED_FIELDS.add("jdoDetachedState");
REFLECTION_EXCLUDED_FIELDS.add("class");
//use FST in BeanPathObjects as deepClone fallback instead of java serialization
BeanPathObjects.setDeepCloneProvider(new IDeepCloneProvider() {
@Override
public <T> T deepClone(final T obj) {
return Objects.deepClone(obj);
}
});
}
private Objects() {}
public static <T> T defaultIfNull(final T object, final T defaultValue) {
return org.apache.commons.lang3.ObjectUtils.defaultIfNull(object, defaultValue);
}
@SafeVarargs
public static <T> T firstNonNull(final T... values) {
return org.apache.commons.lang3.ObjectUtils.firstNonNull(values);
}
public static boolean equals(@Nullable final Object a, @Nullable final Object b) {
return com.google.common.base.Objects.equal(a, b);
}
/**
* Same as equals, just that an empty collection is equal to null.
*/
public static boolean equalsProperty(final Object oldValue, final Object newValue) {
if (!equals(oldValue, newValue)) {
Iterable<?> iterable = null;
Object other = null;
if (oldValue instanceof Iterable) {
iterable = (Iterable<?>) oldValue;
other = newValue;
} else if (newValue instanceof Iterable) {
iterable = (Iterable<?>) newValue;
other = oldValue;
}
if (iterable == null) {
return false;
} else {
return !iterable.iterator().hasNext() && other == null;
}
} else {
return true;
}
}
public static int hashCode(final Object object) {
return java.util.Objects.hashCode(object);
}
public static int hashCode(final Object o1, final Object o2) {
// final int prime = 31;
// int result = super.hashCode();
// result = prime * result + ((first == null) ? 0 : first.hashCode());
// result = prime * result + ((second == null) ? 0 : second.hashCode());
// return result;
final int prime = 31;
int result = 1;
result = prime * result + hashCode(o1);
result = prime * result + hashCode(o2);
return result;
}
public static int hashCode(final Object o1, final Object o2, final Object o3) {
final int prime = 31;
int result = 1;
result = prime * result + hashCode(o1);
result = prime * result + hashCode(o2);
result = prime * result + hashCode(o3);
return result;
}
public static int hashCode(final Object o1, final Object o2, final Object o3, final Object o4) {
final int prime = 31;
int result = 1;
result = prime * result + hashCode(o1);
result = prime * result + hashCode(o2);
result = prime * result + hashCode(o3);
result = prime * result + hashCode(o4);
return result;
}
public static int hashCode(final Object o1, final Object o2, final Object o3, final Object o4, final Object o5) {
final int prime = 31;
int result = 1;
result = prime * result + hashCode(o1);
result = prime * result + hashCode(o2);
result = prime * result + hashCode(o3);
result = prime * result + hashCode(o4);
result = prime * result + hashCode(o5);
return result;
}
public static int hashCode(final Object o1, final Object o2, final Object o3, final Object o4, final Object o5,
final Object o6) {
final int prime = 31;
int result = 1;
result = prime * result + hashCode(o1);
result = prime * result + hashCode(o2);
result = prime * result + hashCode(o3);
result = prime * result + hashCode(o4);
result = prime * result + hashCode(o5);
result = prime * result + hashCode(o6);
return result;
}
public static int hashCode(@Nullable final Object... objects) {
return com.google.common.base.Objects.hashCode(objects);
}
@SuppressWarnings({ "unchecked", "null" })
public static <T> T deepClone(final T obj) {
if (obj == null) {
return (T) null;
}
final byte[] serialized = serialize((Serializable) obj);
return (T) deserialize(serialized);
}
@SuppressWarnings("unchecked")
public static <T> T deserialize(final byte[] objectData) {
return (T) SERIALIZATION_CONFIG.asObject(objectData);
}
public static <T> T deserialize(final InputStream in) {
//FST is unreliable regarding input streams
try {
return deserialize(IOUtils.toByteArray(in));
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
public static byte[] serialize(final Serializable obj) {
return SERIALIZATION_CONFIG.asByteArray(obj);
}
public static String toString(final Object obj) {
return Strings.asStringReflective(obj);
}
public static String toStringMultiline(final Object obj) {
return Strings.asStringReflectiveMultiline(obj);
}
public static String toStringIdentity(final Object obj) {
return Strings.asStringIdentity(obj);
}
public static ToStringHelper toStringHelper(final Object obj) {
return new ToStringHelper(obj, false);
}
public static ToStringHelper toStringHelperMultiline(final Object obj) {
return new ToStringHelper(obj, true);
}
public static int reflectionHashCode(final Object obj) {
return hashCode(obj.getClass(), HashCodeBuilder.reflectionHashCode(obj, REFLECTION_EXCLUDED_FIELDS));
}
public static boolean reflectionEquals(final Object thisObj, final Object obj) {
return EqualsBuilder.reflectionEquals(thisObj, obj, REFLECTION_EXCLUDED_FIELDS);
}
public static int reflectionCompareTo(final Object thisObj, final Object obj) {
return CompareToBuilder.reflectionCompare(thisObj, obj, REFLECTION_EXCLUDED_FIELDS);
}
}