Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional IBDO parameter diff options. #609

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 69 additions & 3 deletions src/main/java/emissary/core/DiffCheckConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package emissary.core;

import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;

Expand All @@ -12,13 +13,13 @@ public class DiffCheckConfiguration {
* Possible configuration options
*/
public enum DiffCheckOptions {
DATA, TIMESTAMP, INTERNAL_ID, TRANSFORM_HISTORY
DATA, TIMESTAMP, INTERNAL_ID, TRANSFORM_HISTORY, KEY_VALUE_PARAMETER_DIFF, DETAILED_PARAMETER_DIFF
}

/**
* Stateful field of 'enabled' options
*/
private final EnumSet<DiffCheckOptions> enabled;
private final Set<DiffCheckOptions> enabled;

/**
* Start building a new configuration
Expand Down Expand Up @@ -74,6 +75,24 @@ public boolean checkTransformHistory() {
return enabled.contains(DiffCheckOptions.TRANSFORM_HISTORY);
}

/**
* Check if parameter diff should produce detailed output
*
* @return if performing a detailed parameter diff
*/
public boolean performDetailedParameterDiff() {
return enabled.contains(DiffCheckOptions.DETAILED_PARAMETER_DIFF);
}

/**
* Check if parameter diff should produce non-matching key/value output
*
* @return if performing a key/value parameter diff
*/
public boolean performKeyValueParameterDiff() {
return enabled.contains(DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF);
}

/**
jdcove2 marked this conversation as resolved.
Show resolved Hide resolved
* Accessor for enabled options
*
Expand All @@ -89,7 +108,7 @@ public Set<DiffCheckOptions> getEnabled() {
* @param enabled set of pre-configured options
*/
private DiffCheckConfiguration(final EnumSet<DiffCheckOptions> enabled) {
this.enabled = enabled;
this.enabled = Collections.unmodifiableSet(enabled);
}

/**
Expand Down Expand Up @@ -120,6 +139,11 @@ public DiffCheckConfiguration build() {
public DiffCheckConfiguration explicit(final DiffCheckOptions... options) {
reset();
building.addAll(Arrays.asList(options));

if (building.contains(DiffCheckOptions.DETAILED_PARAMETER_DIFF) && building.contains(DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF)) {
throw new IllegalArgumentException("Cannot contain DETAILED_PARAMETER_DIFF and KEY_VALUE_PARAMETER_DIFF!");
}

return build();
}

Expand Down Expand Up @@ -219,5 +243,47 @@ public DiffCheckBuilder disableTransformHistory() {
building.remove(DiffCheckOptions.TRANSFORM_HISTORY);
return this;
}

/**
* Enable transform history for diff checking
*
* @return the builder
*/
public DiffCheckBuilder enableKeyValueParameterDiff() {
building.add(DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF);
building.remove(DiffCheckOptions.DETAILED_PARAMETER_DIFF);
return this;
}

/**
* Disable transform history for diff checking
*
* @return the builder
*/
public DiffCheckBuilder disableKeyValueParameterDiff() {
building.remove(DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF);
return this;
}

/**
* Enable transform history for diff checking
*
* @return the builder
*/
public DiffCheckBuilder enableDetailedParameterDiff() {
building.add(DiffCheckOptions.DETAILED_PARAMETER_DIFF);
building.remove(DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF);
return this;
}

/**
* Disable transform history for diff checking
*
* @return the builder
*/
public DiffCheckBuilder disableDetailedParameterDiff() {
building.remove(DiffCheckOptions.DETAILED_PARAMETER_DIFF);
return this;
}
}
}
72 changes: 69 additions & 3 deletions src/main/java/emissary/core/IBaseDataObjectDiffHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class IBaseDataObjectDiffHelper {

Expand Down Expand Up @@ -58,8 +63,15 @@ public static void diff(final IBaseDataObject ibdo1, final IBaseDataObject ibdo2
}

diff(ibdo1.getFontEncoding(), ibdo2.getFontEncoding(), "fontEncoding", differences);
// TreeMap automatically sorts parameters by key
diff(convertMap(ibdo1.getParameters()), convertMap(ibdo2.getParameters()), "parameters", differences);

if (options.performDetailedParameterDiff()) {
diff(convertMap(ibdo1.getParameters()), convertMap(ibdo2.getParameters()), "parameters", differences);
} else if (options.performKeyValueParameterDiff()) {
keyValueMapDiff(convertMap(ibdo1.getParameters()), convertMap(ibdo2.getParameters()), "parameters", differences);
} else {
minimalMapDiff(convertMap(ibdo1.getParameters()), convertMap(ibdo2.getParameters()), "parameters", differences);
}

diff(ibdo1.getNumChildren(), ibdo2.getNumChildren(), "numChildren", differences);
diff(ibdo1.getNumSiblings(), ibdo2.getNumSiblings(), "numSiblings", differences);
diff(ibdo1.getBirthOrder(), ibdo2.getBirthOrder(), "birthOrder", differences);
Expand Down Expand Up @@ -211,7 +223,7 @@ public static void diff(final boolean boolean1, final boolean boolean2, final St
* @param map1 the first map to compare.
* @param map2 the second map to compare.
* @param identifier an identifier to describe the context of this map comparison.
* @param differences the string list differences are to be added to.
* @param differences the string list of differences to be added to.
*/
public static void diff(final Map<String, byte[]> map1, final Map<String, byte[]> map2, final String identifier,
final List<String> differences) {
Expand All @@ -226,6 +238,60 @@ public static void diff(final Map<String, byte[]> map1, final Map<String, byte[]
}
}

/**
* This method compares two maps and adds only the key/value pairs that differ to the provided string list.
*
* @param parameter1 the first map to compare.
* @param parameter2 the second map to compare.
* @param identifier an identifier to describe the context of this map comparison.
* @param differences the string list of differences to be added to.
*/
public static void keyValueMapDiff(final Map<String, Collection<String>> parameter1, final Map<String, Collection<String>> parameter2,
jdcove2 marked this conversation as resolved.
Show resolved Hide resolved
final String identifier, final List<String> differences) {
final Set<Entry<String, Collection<String>>> p1Entries = new HashSet<>(parameter1.entrySet());
final Set<Entry<String, Collection<String>>> p2Entries = new HashSet<>(parameter2.entrySet());
final Map<String, Collection<String>> p1 = new HashMap<>(parameter1);
final Map<String, Collection<String>> p2 = new HashMap<>(parameter2);

for (Entry<String, Collection<String>> p1Entry : p1Entries) {
if (p2Entries.contains(p1Entry)) {
p1.remove(p1Entry.getKey());
p2.remove(p1Entry.getKey());
}
}

if (!p1.isEmpty() || !p2.isEmpty()) {
differences.add(String.format("%s%s: %s : %s", identifier, ARE_NOT_EQUAL + "-Differing Keys/Values", p1, p2));
}
}

/**
* This method compares two maps and adds only the keys that differ to the provided string list.
*
* @param parameter1 the first map to compare.
* @param parameter2 the second map to compare.
* @param identifier an identifier to describe the context of this map comparison.
* @param differences the string list of differences to be added to.
*/
public static void minimalMapDiff(final Map<String, Collection<String>> parameter1, final Map<String, Collection<String>> parameter2,
final String identifier, final List<String> differences) {
final Set<Entry<String, Collection<String>>> p1Entries = new HashSet<>(parameter1.entrySet());
final Set<Entry<String, Collection<String>>> p2Entries = new HashSet<>(parameter2.entrySet());
final Set<String> p1Keys = new TreeSet<>(parameter1.keySet());
final Set<String> p2Keys = new TreeSet<>(parameter2.keySet());

for (Entry<String, Collection<String>> p1Entry : p1Entries) {
if (p2Entries.contains(p1Entry)) {
p1Keys.remove(p1Entry.getKey());
p2Keys.remove(p1Entry.getKey());
}
}

if (!p1Keys.isEmpty() || !p2Keys.isEmpty()) {
differences.add(String.format("%s%s: %s : %s", identifier, ARE_NOT_EQUAL + "-Differing Keys", p1Keys, p2Keys));
}
}

/**
* This method converts the IBDO parameter map of Object values to a map of String values for better comparison.
*
Expand Down
134 changes: 134 additions & 0 deletions src/test/java/emissary/core/DiffCheckConfigurationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package emissary.core;

import emissary.core.DiffCheckConfiguration.DiffCheckBuilder;
import emissary.core.DiffCheckConfiguration.DiffCheckOptions;
import emissary.test.core.junit5.UnitTest;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

class DiffCheckConfigurationTest extends UnitTest {
@Test
void testNonParameter() {
final DiffCheckBuilder diffCheckBuilder = DiffCheckConfiguration.configure();
final DiffCheckConfiguration emptyConfiguration = diffCheckBuilder.build();

assertEquals(0, emptyConfiguration.getEnabled().size(), "Configuration should be empty!");

diffCheckBuilder.enableData();
diffCheckBuilder.enableInternalId();
diffCheckBuilder.enableTimestamp();
diffCheckBuilder.enableTransformHistory();

final DiffCheckConfiguration nonParameterConfiguration = diffCheckBuilder.build();

assertTrue(nonParameterConfiguration.checkData());
assertTrue(nonParameterConfiguration.checkInternalId());
assertTrue(nonParameterConfiguration.checkTimestamp());
assertTrue(nonParameterConfiguration.checkTransformHistory());
assertFalse(nonParameterConfiguration.performDetailedParameterDiff());
assertFalse(nonParameterConfiguration.performKeyValueParameterDiff());

diffCheckBuilder.disableData();
diffCheckBuilder.disableInternalId();
diffCheckBuilder.disableTimestamp();
diffCheckBuilder.disableTransformHistory();

assertEquals(0, diffCheckBuilder.build().getEnabled().size(), "Configuration should be empty!");
}

@Test
void testKeyValueDetailed() {
final DiffCheckBuilder diffCheckBuilder = DiffCheckConfiguration.configure();

diffCheckBuilder.enableDetailedParameterDiff();

final DiffCheckConfiguration detailedParameterConfiguration = diffCheckBuilder.build();

assertTrue(detailedParameterConfiguration.performDetailedParameterDiff());
assertFalse(detailedParameterConfiguration.performKeyValueParameterDiff());

diffCheckBuilder.enableKeyValueParameterDiff();

final DiffCheckConfiguration keyValueParameterConfiguration = diffCheckBuilder.build();

assertFalse(keyValueParameterConfiguration.performDetailedParameterDiff());
assertTrue(keyValueParameterConfiguration.performKeyValueParameterDiff());

diffCheckBuilder.disableKeyValueParameterDiff();

assertEquals(0, diffCheckBuilder.build().getEnabled().size(), "Configuration should be empty!");

diffCheckBuilder.enableKeyValueParameterDiff();

final DiffCheckConfiguration KeyValueParameterConfiguration2 = diffCheckBuilder.build();

assertFalse(KeyValueParameterConfiguration2.performDetailedParameterDiff());
assertTrue(KeyValueParameterConfiguration2.performKeyValueParameterDiff());

diffCheckBuilder.enableDetailedParameterDiff();

final DiffCheckConfiguration detailedParameterConfiguration2 = diffCheckBuilder.build();

assertTrue(detailedParameterConfiguration2.performDetailedParameterDiff());
assertFalse(detailedParameterConfiguration2.performKeyValueParameterDiff());

diffCheckBuilder.disableDetailedParameterDiff();

assertEquals(0, diffCheckBuilder.build().getEnabled().size(), "Configuration should be empty!");
}

@Test
void checkReset() {
final DiffCheckBuilder diffCheckBuilder = DiffCheckConfiguration.configure();

diffCheckBuilder.enableData();
diffCheckBuilder.enableInternalId();
diffCheckBuilder.enableTimestamp();
diffCheckBuilder.enableTransformHistory();
diffCheckBuilder.enableDetailedParameterDiff();
diffCheckBuilder.reset();

assertEquals(0, diffCheckBuilder.build().getEnabled().size(), "Configuration should be empty!");
}

@Test
void checkExplicit() {
final DiffCheckBuilder diffCheckBuilder = DiffCheckConfiguration.configure();
final DiffCheckConfiguration explicitDetailedConfiguration = diffCheckBuilder.explicit(
DiffCheckOptions.DATA,
DiffCheckOptions.DETAILED_PARAMETER_DIFF,
DiffCheckOptions.INTERNAL_ID,
DiffCheckOptions.TIMESTAMP,
DiffCheckOptions.TRANSFORM_HISTORY);

assertTrue(explicitDetailedConfiguration.checkData());
assertTrue(explicitDetailedConfiguration.checkInternalId());
assertTrue(explicitDetailedConfiguration.checkTimestamp());
assertTrue(explicitDetailedConfiguration.checkTransformHistory());
assertTrue(explicitDetailedConfiguration.performDetailedParameterDiff());
assertFalse(explicitDetailedConfiguration.performKeyValueParameterDiff());

final DiffCheckConfiguration explicitKeyValueConfiguration = diffCheckBuilder.explicit(
DiffCheckOptions.DATA,
DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF,
DiffCheckOptions.INTERNAL_ID,
DiffCheckOptions.TIMESTAMP,
DiffCheckOptions.TRANSFORM_HISTORY);

assertTrue(explicitKeyValueConfiguration.checkData());
assertTrue(explicitKeyValueConfiguration.checkInternalId());
assertTrue(explicitKeyValueConfiguration.checkTimestamp());
assertTrue(explicitKeyValueConfiguration.checkTransformHistory());
assertFalse(explicitKeyValueConfiguration.performDetailedParameterDiff());
assertTrue(explicitKeyValueConfiguration.performKeyValueParameterDiff());

assertThrows(IllegalArgumentException.class, () -> diffCheckBuilder.explicit(
DiffCheckOptions.DETAILED_PARAMETER_DIFF,
DiffCheckOptions.KEY_VALUE_PARAMETER_DIFF));
}
}
Loading