/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.test.utility.diff;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.diff.CompositeDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.ContainerDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.Diff;
import org.eclipse.persistence.tools.workbench.utility.diff.DiffWrapper;
import org.eclipse.persistence.tools.workbench.utility.diff.MapEntryDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.NullDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.OrderedContainerDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.OrderedContainerElementDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.ReflectiveDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.ReflectiveFieldDiff;
import org.eclipse.persistence.tools.workbench.utility.diff.SimpleDiff;
import org.eclipse.persistence.tools.workbench.utility.iterators.FilteringIterator;
/**
* lots of hacking here to pull out the various leaf diffs;
* might be able to delegate to the diffs themselves, but
* we would probably need another interface (e.g. TestDiff)
* and it would still be a bit hacky
*/
final class DiffTestTools {
/**
* return all the "leaf" diffs contained by the specified diff
* (i.e. all the diffs that do not contain other diffs)
*/
static Iterator leafDiffs(Diff diff) {
Collection leafDiffs = new ArrayList();
addLeafDiffsTo(diff, leafDiffs);
return leafDiffs.iterator();
}
private static void addLeafDiffsTo(Diff diff, Collection leafDiffs) {
if (diff instanceof CompositeDiff) {
addChildrenTo((CompositeDiff) diff, leafDiffs);
} else if (diff instanceof DiffWrapper) {
addChildTo((DiffWrapper) diff, leafDiffs);
} else if (diff instanceof MapEntryDiff) {
addChildTo((MapEntryDiff) diff, leafDiffs);
} else if (diff instanceof SimpleDiff) {
leafDiffs.add(diff);
} else if (diff instanceof NullDiff) {
leafDiffs.add(diff);
} else {
throw new IllegalArgumentException("this method needs to be updated to handle new Diff implementations");
}
}
private static void addChildrenTo(CompositeDiff diff, Collection leafDiffs) {
Diff[] children = diff.getDiffs();
for (int i = 0; i < children.length; i++) {
addLeafDiffsTo(children[i], leafDiffs);
}
if (diff instanceof ContainerDiff) {
ContainerDiff containerDiff = (ContainerDiff) diff;
if ((containerDiff.getAddedElements().length != 0) || (containerDiff.getRemovedElements().length != 0)) {
// if we have any adds or removes, we treat this field as a leaf AND a branch
leafDiffs.add(containerDiff);
}
}
}
private static void addChildTo(DiffWrapper diff, Collection leafDiffs) {
addLeafDiffsTo(diff.getDiff(), leafDiffs);
}
private static void addChildTo(MapEntryDiff diff, Collection leafDiffs) {
addLeafDiffsTo(diff.getKeyDiff(), leafDiffs);
addLeafDiffsTo(diff.getValueDiff(), leafDiffs);
}
static Iterator differentLeafDiffs(Diff diff) {
return new FilteringIterator(leafDiffs(diff)) {
protected boolean accept(Object next) {
return ((Diff) next).different();
}
};
}
static List differentLeafDiffList(Diff diff) {
return CollectionTools.list(differentLeafDiffs(diff));
}
/**
* return all the "leaf" reflective field diffs contained by the specified diff
* (i.e. all the reflective field diffs that do not contain other reflective
* field diffs)
*/
static Iterator leafReflectiveFieldDiffs(Diff diff) {
Collection leafDiffs = new ArrayList();
addLeafReflectiveFieldDiffsTo(diff, leafDiffs);
return leafDiffs.iterator();
}
private static void addLeafReflectiveFieldDiffsTo(Diff diff, Collection leafDiffs) {
if (diff instanceof CompositeDiff) {
addReflectiveFieldChildrenTo((CompositeDiff) diff, leafDiffs);
} else if (diff instanceof ReflectiveFieldDiff) {
addReflectiveFieldChildTo((ReflectiveFieldDiff) diff, leafDiffs);
} else if (diff instanceof OrderedContainerElementDiff) {
// this should probably only contain ReflectiveDiffs...
addLeafReflectiveFieldDiffsTo(((OrderedContainerElementDiff) diff).getDiff(), leafDiffs);
} else if (diff instanceof MapEntryDiff) {
addLeafReflectiveFieldDiffsTo(((MapEntryDiff) diff).getKeyDiff(), leafDiffs);
addLeafReflectiveFieldDiffsTo(((MapEntryDiff) diff).getValueDiff(), leafDiffs);
} else if (diff instanceof NullDiff) {
// occurs when comparing containers of "primitives"
} else {
throw new IllegalArgumentException("hmmm - something's wrong...");
}
}
private static void addReflectiveFieldChildrenTo(CompositeDiff diff, Collection leafDiffs) {
Diff[] children = diff.getDiffs();
for (int i = 0; i < children.length; i++) {
addLeafReflectiveFieldDiffsTo(children[i], leafDiffs);
}
}
private static void addReflectiveFieldChildTo(ReflectiveFieldDiff diff, Collection leafDiffs) {
Diff childDiff = diff.getDiff();
if (childDiff instanceof ContainerDiff) {
ContainerDiff containerChildDiff = (ContainerDiff) childDiff;
if ((containerChildDiff.getAddedElements().length != 0) || (containerChildDiff.getRemovedElements().length != 0)) {
// if we have any adds or removes, we treat this field as a leaf AND a branch
leafDiffs.add(diff);
}
addReflectiveFieldChildrenTo((CompositeDiff) childDiff, leafDiffs);
} else if (childDiff instanceof OrderedContainerDiff) {
OrderedContainerDiff orderedContainerChildDiff = (OrderedContainerDiff) childDiff;
if (containsAnyAddedOrRemovedChildren(orderedContainerChildDiff)) {
// if we have any adds or removes, we treat this field as a leaf AND a branch
leafDiffs.add(diff);
}
if (containsAnyModifiedChildren(orderedContainerChildDiff)) {
addReflectiveFieldChildrenTo((CompositeDiff) childDiff, leafDiffs);
}
} else if (childDiff instanceof ReflectiveDiff) {
addReflectiveFieldChildrenTo((CompositeDiff) childDiff, leafDiffs);
} else if (childDiff instanceof CompositeDiff) {
addReflectiveFieldChildrenTo((CompositeDiff) childDiff, leafDiffs);
} else if (childDiff instanceof SimpleDiff) {
leafDiffs.add(diff);
} else if (childDiff instanceof NullDiff) {
leafDiffs.add(diff);
} else {
throw new IllegalArgumentException("hmmm - something's wrong...");
}
}
private static boolean containsAnyAddedOrRemovedChildren(OrderedContainerDiff orderedContainerChildDiff) {
Diff[] children = orderedContainerChildDiff.getDiffs();
for (int i = 0; i < children.length; i++) {
OrderedContainerElementDiff child = (OrderedContainerElementDiff) children[i];
if (child.elementWasAdded() || child.elementWasRemoved()) {
return true;
}
}
return false;
}
private static boolean containsAnyModifiedChildren(OrderedContainerDiff orderedContainerChildDiff) {
Diff[] children = orderedContainerChildDiff.getDiffs();
for (int i = 0; i < children.length; i++) {
OrderedContainerElementDiff child = (OrderedContainerElementDiff) children[i];
if (child.elementWasModified()) {
return true;
}
}
return false;
}
static Iterator differentLeafReflectiveFieldDiffs(Diff diff) {
return new FilteringIterator(leafReflectiveFieldDiffs(diff)) {
protected boolean accept(Object next) {
return ((Diff) next).different();
}
};
}
static List differentLeafReflectiveFieldDiffList(Diff diff) {
return CollectionTools.list(differentLeafReflectiveFieldDiffs(diff));
}
}