Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.reactome.util.compare;
import static org.reactome.util.compare.AttributeProcessor.isAttributeContainingInstances;
import static org.reactome.util.general.CollectionUtils.safeList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import org.gk.model.GKInstance;
import org.gk.model.InstanceUtilities;
import org.gk.model.ReactomeJavaConstants;
import org.gk.persistence.MySQLAdaptor;
import org.gk.schema.SchemaAttribute;
import org.reactome.util.compare.AttributeProcessor.AttributeRelationshipType;
/**
* This class can be used to perform comparisons on any two DatabaseObjects across two different databases.
* (It assumes that they have the same DB_ID).
* @author sshorser
* @author jweiser
*/
public class DBObjectComparer
{
private static Map>>>
instanceAttributeToValuesMap = new ConcurrentHashMap<>();
private static final int DEFAULT_MAX_RECURSION_DEPTH = 5;
private static final int DEFAULT_INSTANCES_DIFFERENCES_COUNT = 0;
private static final int DEFAULT_RECURSION_DEPTH = 0;
/**
* Compares two GKInstances.
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
public static int compareInstances(GKInstance instance1, GKInstance instance2, StringBuilder stringBuilder)
{
final boolean checkReferrers = false;
return compareInstances(instance1, instance2, stringBuilder, DEFAULT_MAX_RECURSION_DEPTH, checkReferrers);
}
/**
* Compares two GKInstances.
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @param checkReferrers Should referring instances also be checked? If true, then referring attributes
* will also be checked for differences. They will be followed to the same recursion depth as regular
* attributes. Using this with a high maxRecursionDepth could lead to a very long execution time. Be careful!!
* You might also want to use a custom predicate to filter out attributes that could lead to a cyclical difference
* check.
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
public static int compareInstances(
GKInstance instance1, GKInstance instance2, StringBuilder stringBuilder, boolean checkReferrers
)
{
return compareInstances(instance1, instance2, stringBuilder, DEFAULT_MAX_RECURSION_DEPTH, checkReferrers);
}
/**
* Compares two GKInstances.
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @param maxRecursionDepth The maximum depth of recursion that will be allowed. Normally a depth of 2 or 3 is
* probably sufficient.
* @param checkReferrers Should referring instances also be checked? If true, then referring attributes
* will also be checked for differences. They will be followed to the same recursion depth as regular
* attributes. Using this with a high maxRecursionDepth could lead to a very long execution time. Be careful!!
* You might also want to use a custom predicate to filter out attributes that could lead to a cyclical difference
* check by using one of:
* {@link #compareInstances(GKInstance, GKInstance, StringBuilder, int, Predicate, boolean)}
* {@link #compareInstances(GKInstance, GKInstance, StringBuilder, int, int, int, Predicate, boolean)}
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
public static int compareInstances(
GKInstance instance1, GKInstance instance2, StringBuilder stringBuilder,
int maxRecursionDepth, boolean checkReferrers
)
{
// Given named constant for context in using this value as an argument
final Predicate super SchemaAttribute> customAttributeNameFilter = null;
return compareInstances(
instance1, instance2, stringBuilder, DEFAULT_INSTANCES_DIFFERENCES_COUNT,
DEFAULT_RECURSION_DEPTH, maxRecursionDepth, customAttributeNameFilter, checkReferrers
);
}
/**
* Compares two GKInstances.
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @param maxRecursionDepth The maximum depth of recursion that will be allowed. Normally a depth of 2 or 3 is
* probably sufficient.
* @param customAttributeNameFilter A custom Predicate that will be used to filter attribute names. The default
* predicate looks like this:
Predicate<? super SchemaAttribute> attributeNameFilter = a -> {
return !a.getName().equals("DB_ID")
&& !a.getName().equals("dateTime")
&& !a.getName().equals("modified")
&& !a.getName().equals("created");
};
* @param checkReferrers Should referring instances also be checked? If true, then referring attributes
* will also be checked for differences. They will be followed to the same recursion depth as regular
* attributes. Using this with a high maxRecursionDepth could lead to a very long execution time. Be careful!!
* You might also want to use a custom predicate to filter out attributes that could lead to a cyclical difference
* check. See the customAttributeNameFilter parameter above for the default.
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
public static int compareInstances(
GKInstance instance1, GKInstance instance2, StringBuilder stringBuilder, int maxRecursionDepth,
Predicate super SchemaAttribute> customAttributeNameFilter, boolean checkReferrers
)
{
return compareInstances(
instance1, instance2, stringBuilder, DEFAULT_INSTANCES_DIFFERENCES_COUNT,
DEFAULT_RECURSION_DEPTH, maxRecursionDepth, customAttributeNameFilter, checkReferrers
);
}
/**
* Recursively compares two GKInstances.
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @param diffCount The number of differences so far. Should start at 0.
* @param recursionDepth The depth of the recursion so far. Should start at 0.
* @param customAttributeNameFilter A custom Predicate that will be used to filter attribute names.
* The default predicate looks like this:
Predicate<? super SchemaAttribute> attributeNameFilter = a -> {
return !a.getName().equals("DB_ID")
&& !a.getName().equals("dateTime")
&& !a.getName().equals("modified")
&& !a.getName().equals("created");
};
* @param checkReferrers Should referring instances also be checked? If true, then referring attributes
* will also be checked for differences. They will be followed to the same recursion depth as regular
* attributes. Using this with a high maxRecursionDepth could lead to a very long execution time. Be careful!!
* You might also want to use a custom predicate to filter out attributes that could lead to a cyclical difference
* check. See the customAttributeNameFilter parameter above for the default.
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
private static int compareInstances(
GKInstance instance1, GKInstance instance2, StringBuilder stringBuilder, int diffCount, int recursionDepth,
int maxRecursionDepth, Predicate super SchemaAttribute> customAttributeNameFilter, boolean checkReferrers
)
{
if (instance1 == null || instance2 == null || isInstanceEdit(instance1) || isInstanceEdit(instance2))
{
return diffCount;
}
if (differentInstanceTypes(instance1, instance2))
{
stringBuilder
.append(getIndentString(recursionDepth))
.append(getInstanceTypeMismatchMessage(instance1, instance2));
return 1;
}
int count = compareValuesOfInstancesForAttributes(
AttributeRelationshipType.REGULAR_ATTRIBUTE, instance1, instance2, stringBuilder, diffCount,
recursionDepth, maxRecursionDepth, customAttributeNameFilter, checkReferrers
);
if (checkReferrers) {
count = compareValuesOfInstancesForAttributes(
AttributeRelationshipType.REVERSE_ATTRIBUTE, instance1, instance2, stringBuilder, count,
recursionDepth, maxRecursionDepth, customAttributeNameFilter, checkReferrers
);
}
return count;
}
/**
* Recursively compares two GKInstances.
* @param attributeRelationshipType Relationship between the passed attribute to the passed instances (i.e. a
* 'regular' or referrer attribute)
* @param instance1 The first instance
* @param instance2 The second instance
* @param stringBuilder A StringBuilder that will contain a detailed report of differences
* @param diffCount The number of differences so far. Should start at 0.
* @param recursionDepth The depth of the recursion so far. Should start at 0.
* @param maxRecursionDepth The maximum depth of recursion that will be allowed. Normally a depth of 2 or 3 is
* probably sufficient.
* @param customAttributeNameFilter A custom Predicate that will be used to filter attribute names.
* The default predicate looks like this:
Predicate<? super SchemaAttribute> attributeNameFilter = a -> {
return !a.getName().equals("DB_ID")
&& !a.getName().equals("dateTime")
&& !a.getName().equals("modified")
&& !a.getName().equals("created");
};
* @param checkReferrers Should referring instances also be checked? If true, then referring attributes
* will also be checked for differences. They will be followed to the same recursion depth as regular
* attributes. Using this with a high maxRecursionDepth could lead to a very long execution time. Be careful!!
* You might also want to use a custom predicate to filter out attributes that could lead to a cyclical difference
* check.
* @return The number of differences between the two instances.
* A single-valued attribute that differs will count as 1 diff.
* If the instances have different schema classes, that will count as 1 diff.
* If a multi-valued attribute has a different number of elements between the two instances,
* that will count as 1 diff and the elements will NOT be compared.
*/
private static int compareValuesOfInstancesForAttributes(
AttributeRelationshipType attributeRelationshipType, GKInstance instance1, GKInstance instance2,
StringBuilder stringBuilder, int diffCount, int recursionDepth, int maxRecursionDepth,
Predicate super SchemaAttribute> customAttributeNameFilter, boolean checkReferrers
)
{
List attributes = AttributeProcessor.filterAttributes(
AttributeProcessor.getAttributes(instance1.getSchemClass(), attributeRelationshipType),
customAttributeNameFilter
);
int count = diffCount;
for (SchemaAttribute attribute : attributes)
{
List