/*******************************************************************************
* 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.events;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.persistence.tools.workbench.utility.AbstractModel;
import org.eclipse.persistence.tools.workbench.utility.ClassTools;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.events.CollectionChangeListener;
import org.eclipse.persistence.tools.workbench.utility.events.ReflectiveChangeListener;
import org.eclipse.persistence.tools.workbench.utility.events.TreeChangeEvent;
import org.eclipse.persistence.tools.workbench.utility.events.TreeChangeListener;
import org.eclipse.persistence.tools.workbench.utility.iterators.CloneIterator;
public class ReflectiveTreeChangeListenerTests extends TestCase {
public static Test suite() {
return new TestSuite(ReflectiveTreeChangeListenerTests.class);
}
public ReflectiveTreeChangeListenerTests(String name) {
super(name);
}
private TreeChangeListener buildZeroArgumentListener(Object target) {
return ReflectiveChangeListener.buildTreeChangeListener(target, "nodeAddedZeroArgument", "nodeRemovedZeroArgument", "treeChangedZeroArgument");
}
private TreeChangeListener buildSingleArgumentListener(Object target) {
return ReflectiveChangeListener.buildTreeChangeListener(target, "nodeAddedSingleArgument", "nodeRemovedSingleArgument", "treeChangedSingleArgument");
}
public void testNodeAddedZeroArgument() {
TestModel testModel = new TestModel("root");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(this.buildZeroArgumentListener(target));
testModel.addNode("root", "child");
assertTrue(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeAddedZeroArgumentNamedTree() {
TestModel testModel = new TestModel("root");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildZeroArgumentListener(target));
testModel.addNode("root", "child");
assertTrue(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeAddedSingleArgument() {
TestModel testModel = new TestModel("root");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(this.buildSingleArgumentListener(target));
testModel.addNode("root", "child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertTrue(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeAddedSingleArgumentNamedTree() {
TestModel testModel = new TestModel("root");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildSingleArgumentListener(target));
testModel.addNode("root", "child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertTrue(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeRemovedZeroArgument() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(this.buildZeroArgumentListener(target));
testModel.removeNode("child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertTrue(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeRemovedZeroArgumentNamedTree() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildZeroArgumentListener(target));
testModel.removeNode("child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertTrue(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeRemovedSingleArgument() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(this.buildSingleArgumentListener(target));
testModel.removeNode("child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertTrue(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testNodeRemovedSingleArgumentNamedTree() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildSingleArgumentListener(target));
testModel.removeNode("child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertTrue(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testTreeChangedZeroArgument() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "another child"});
testModel.addTreeChangeListener(this.buildZeroArgumentListener(target));
testModel.replaceNode("child", "another child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertTrue(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testTreeChangedZeroArgumentNamedTree() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "another child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildZeroArgumentListener(target));
testModel.replaceNode("child", "another child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertTrue(target.treeChangedZeroArgumentFlag);
assertFalse(target.treeChangedSingleArgumentFlag);
}
public void testTreeChangedSingleArgument() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "another child"});
testModel.addTreeChangeListener(this.buildSingleArgumentListener(target));
testModel.replaceNode("child", "another child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertTrue(target.treeChangedSingleArgumentFlag);
}
public void testTreeChangedSingleArgumentNamedTree() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "another child"});
testModel.addTreeChangeListener(TestModel.STRINGS_TREE, this.buildSingleArgumentListener(target));
testModel.replaceNode("child", "another child");
assertFalse(target.nodeAddedZeroArgumentFlag);
assertFalse(target.nodeAddedSingleArgumentFlag);
assertFalse(target.nodeRemovedZeroArgumentFlag);
assertFalse(target.nodeRemovedSingleArgumentFlag);
assertFalse(target.treeChangedZeroArgumentFlag);
assertTrue(target.treeChangedSingleArgumentFlag);
}
public void testBogusDoubleArgument1() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
boolean exCaught = false;
try {
TreeChangeListener listener = ReflectiveChangeListener.buildTreeChangeListener(target, "collectionChangedDoubleArgument");
fail("bogus listener: " + listener);
} catch (RuntimeException ex) {
if (ex.getCause().getClass() == NoSuchMethodException.class) {
exCaught = true;
}
}
assertTrue(exCaught);
}
public void testBogusDoubleArgument2() throws Exception {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
Method method = ClassTools.method(target, "collectionChangedDoubleArgument", new Class[] {TreeChangeEvent.class, Object.class});
boolean exCaught = false;
try {
TreeChangeListener listener = ReflectiveChangeListener.buildTreeChangeListener(target, method);
fail("bogus listener: " + listener);
} catch (RuntimeException ex) {
if (ex.getMessage().equals(method.toString())) {
exCaught = true;
}
}
assertTrue(exCaught);
}
public void testListenerMismatch() {
TestModel testModel = new TestModel("root");
testModel.addNode("root", "child");
Target target = new Target(testModel, TestModel.STRINGS_TREE, new String[]{"root", "child"});
// build a TREE change listener and hack it so we
// can add it as a COLLECTION change listener
Object listener = ReflectiveChangeListener.buildTreeChangeListener(target, "nodeAddedSingleArgument");
testModel.addCollectionChangeListener((CollectionChangeListener) listener);
boolean exCaught = false;
try {
testModel.changeCollection();
fail("listener mismatch: " + listener);
} catch (IllegalArgumentException ex) {
exCaught = true;
}
assertTrue(exCaught);
}
private class TestModel extends AbstractModel {
private final String root;
private Map childrenLists = new HashMap();
private Map parents = new HashMap();
public static final String STRINGS_TREE = "strings";
TestModel(String root) {
super();
if (root == null) {
throw new NullPointerException();
}
this.root = root;
this.childrenLists.put(root, new ArrayList());
this.parents.put(root, null);
}
String getRoot() {
return this.root;
}
private Object[] path(String node) {
Object temp = node;
List reversePath = new ArrayList();
do {
reversePath.add(temp);
temp = this.parents.get(temp);
} while (temp != null);
return CollectionTools.reverse(reversePath).toArray();
}
Iterator strings() {
return new CloneIterator(this.childrenLists.keySet()) {
protected void remove(Object o) {
TestModel.this.removeNode((String) o);
}
};
}
void addNode(String parent, String child) {
if ((parent == null) || (child == null)) {
throw new NullPointerException();
}
Collection children = (Collection) this.childrenLists.get(parent);
if (children == null) {
throw new IllegalStateException("cannot add a child to a non-existent parent");
}
if (this.childrenLists.get(child) != null) {
throw new IllegalStateException("cannot add a child that is already in the tree");
}
children.add(child);
this.childrenLists.put(child, new ArrayList());
this.parents.put(child, parent);
this.fireNodeAdded(STRINGS_TREE, this.path(child));
}
void removeNode(String node) {
if (node == null) {
throw new NullPointerException();
}
Collection children = (Collection) this.childrenLists.get(node);
if (children == null) {
throw new IllegalStateException("node is not in tree");
}
Object[] path = this.path(node);
for (Iterator stream = children.iterator(); stream.hasNext(); ) {
this.removeNode((String) stream.next());
}
this.childrenLists.remove(node);
this.parents.remove(node);
this.fireNodeRemoved(STRINGS_TREE, path);
}
void replaceNode(String oldNode, String newNode) {
if ((oldNode == null) || (newNode == null)) {
throw new NullPointerException();
}
Collection children = (Collection) this.childrenLists.remove(oldNode);
if (children == null) {
throw new IllegalStateException("old node is not in tree");
}
this.childrenLists.put(newNode, children);
for (Iterator stream = children.iterator(); stream.hasNext(); ) {
Object child = stream.next();
this.parents.put(child, newNode);
}
Object parent = this.parents.remove(oldNode);
this.parents.put(newNode, parent);
this.fireTreeStructureChanged(STRINGS_TREE, this.path(newNode));
}
void changeCollection() {
this.fireCollectionChanged("bogus collection");
}
}
private class Target {
TestModel testModel;
String treeName;
String[] path;
boolean nodeAddedZeroArgumentFlag = false;
boolean nodeAddedSingleArgumentFlag = false;
boolean nodeRemovedZeroArgumentFlag = false;
boolean nodeRemovedSingleArgumentFlag = false;
boolean treeChangedZeroArgumentFlag = false;
boolean treeChangedSingleArgumentFlag = false;
Target(TestModel testModel, String treeName, String[] path) {
super();
this.testModel = testModel;
this.treeName = treeName;
this.path = path;
}
void nodeAddedZeroArgument() {
this.nodeAddedZeroArgumentFlag = true;
}
void nodeAddedSingleArgument(TreeChangeEvent e) {
this.nodeAddedSingleArgumentFlag = true;
assertSame(this.testModel, e.getSource());
assertEquals(this.treeName, e.getTreeName());
assertTrue(Arrays.equals(this.path, e.getPath()));
}
void nodeRemovedZeroArgument() {
this.nodeRemovedZeroArgumentFlag = true;
}
void nodeRemovedSingleArgument(TreeChangeEvent e) {
this.nodeRemovedSingleArgumentFlag = true;
assertSame(this.testModel, e.getSource());
assertEquals(this.treeName, e.getTreeName());
assertTrue(Arrays.equals(this.path, e.getPath()));
}
void treeChangedZeroArgument() {
this.treeChangedZeroArgumentFlag = true;
}
void treeChangedSingleArgument(TreeChangeEvent e) {
this.treeChangedSingleArgumentFlag = true;
assertSame(this.testModel, e.getSource());
assertEquals(this.treeName, e.getTreeName());
assertTrue(Arrays.equals(this.path, e.getPath()));
}
void collectionChangedDoubleArgument(TreeChangeEvent e, Object o) {
fail("bogus event: " + e);
}
}
}