package com.rcpcompany.uibindings.model.utils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.EqualityHelper;
/**
* Various utility methods.
*
* @author Tonny Madsen, The RCP Company
*/
public class BasicUtils {
/**
* Variant of {@link EqualityHelper} that ignores containing references...
*/
@SuppressWarnings("serial")
private static class MyEqualityHelper extends EqualityHelper {
@Override
public boolean equals(EObject a, EObject b) {
final boolean res = super.equals(a, b);
// if (a != null && b != null) {
// LogUtils.debug(this, "" + ClassUtils.getLastClassName(a) + "@" +
// System.identityHashCode(a) + " <> "
// + ClassUtils.getLastClassName(b) + "@" + System.identityHashCode(b) + " ==== " +
// res);
// }
return res;
}
@Override
protected boolean haveEqualReference(EObject eObject1, EObject eObject2, EReference reference) {
if (reference.isContainer()) return true;
return super.haveEqualReference(eObject1, eObject2, reference);
}
}
public static final Comparator<Object> OBJECT_COMPARATOR = new Comparator<Object>() {
@Override
public int compare(Object sf1, Object sf2) {
return System.identityHashCode(sf1) - System.identityHashCode(sf2);
}
};
/**
* Version of {@link Collections#sort(List, Comparator)} that can be used with {@link EList}
* with the unique property.
*
* @param list the list to be sorted.
* @param c the comparator to determine the order of the list. A <tt>null</tt> value indicates
* that the elements' <i>natural ordering</i> should be used.
* @throws ClassCastException if the list contains elements that are not <i>mutually
* comparable</i> using the specified comparator.
* @throws UnsupportedOperationException if the specified list's list-iterator does not support
* the <tt>set</tt> operation.
* @see Comparator
*/
public static <T> void sort(EList<T> list, Comparator<? super T> c) {
ECollections.sort(list, c);
}
/**
* Returns whether the two objects are equal or both <code>null</code>.
* <p>
* See Objects of Guava
*
* @param a object a
* @param b object b
* @return true if a and b are equal or both are <code>null</code>
*/
public static boolean equals(Object a, Object b) {
if (a == b) return true;
if (a == null) return false;
return a.equals(b);
}
/**
* Returns whether the two objects are deeply equal or both <code>null</code>.
* <p>
* Note that two arrays of the same length, base type and with equals elements are considered
* equal.
* <p>
* Also two collections of the same size and with equal elements are also considered equal.
* <p>
* And two {@link EObject} are compared using {@link EcoreUtil#equals(EObject, EObject)}.
*
* @param a object a
* @param b object b
* @return true if a and b are equal or both are <code>null</code>
*/
public static boolean deepEquals(Object a, Object b) {
if (a == b) return true;
if (a == null) return false;
if (a.getClass().isArray() && b.getClass().isArray()) {
if (a.getClass() != b.getClass()) return false;
if (a instanceof Object[] && b instanceof Object[])
return Arrays.deepEquals((Object[]) a, (Object[]) b);
else if (a instanceof byte[] && b instanceof byte[])
return Arrays.equals((byte[]) a, (byte[]) b);
else if (a instanceof short[] && b instanceof short[])
return Arrays.equals((short[]) a, (short[]) b);
else if (a instanceof int[] && b instanceof int[])
return Arrays.equals((int[]) a, (int[]) b);
else if (a instanceof long[] && b instanceof long[])
return Arrays.equals((long[]) a, (long[]) b);
else if (a instanceof char[] && b instanceof char[])
return Arrays.equals((char[]) a, (char[]) b);
else if (a instanceof float[] && b instanceof float[])
return Arrays.equals((float[]) a, (float[]) b);
else if (a instanceof double[] && b instanceof double[])
return Arrays.equals((double[]) a, (double[]) b);
else if (a instanceof boolean[] && b instanceof boolean[])
return Arrays.equals((boolean[]) a, (boolean[]) b);
else
return false;
}
if (a instanceof Collection && b instanceof Collection) {
final Collection<?> aData = (Collection<?>) a;
final Collection<?> bData = (Collection<?>) b;
if (aData.size() != bData.size()) return false;
final Iterator<?> aIterator = aData.iterator();
final Iterator<?> bIterator = bData.iterator();
while (aIterator.hasNext()) {
if (!deepEquals(aIterator.next(), bIterator.next())) return false;
}
return true;
}
if (a instanceof EObject && b instanceof EObject) {
final EqualityHelper equalityHelper = new MyEqualityHelper();
return equalityHelper.equals(((EObject) a), ((EObject) b));
}
return a.equals(b);
}
/**
* Returns whether the two EObjects are equal or both <code>null</code>.
* <p>
* This version uses the equality concept from EMF with object keys. I.e. if <code>key</code> is
* non-<code>null</code>, it also tests if the key attribute of the objects are
* {@link #equals(Object, Object)}. So two objects are "equal" if just the keys are equal.
*
* @param a object a
* @param b object b
* @param key key attribute in objects
* @return true if a and b are equal or both are <code>null</code>
*/
public static boolean equals(EObject a, EObject b, EAttribute key) {
if (a == b) return true;
if (key != null && a != null && b != null) return equals(a.eGet(key), b.eGet(key));
return deepEquals(a, b);
}
/**
* Returns whether the two {@link Diagnostic} objects are equal or both <code>null</code>.
*
* @param a {@link Diagnostic} object a
* @param b {@link Diagnostic} object b
* @return true if a and b represent the same {@link Diagnostic} or both are <code>null</code>
*/
public static boolean equals(Diagnostic a, Diagnostic b) {
if (a == b) return true;
if (a == null) return false;
if (a.getSeverity() != b.getSeverity()) return false;
if (!equals(a.getSource(), b.getSource())) return false;
if (a.getCode() != b.getCode()) return false;
if (!equals(a.getMessage(), b.getMessage())) return false;
if (!equals(a.getException(), b.getException())) return false;
if (!deepEquals(a.getChildren(), b.getChildren())) return false;
if (!deepEquals(a.getData(), b.getData())) return false;
return true;
}
}