blob: 22ffb5982503ddfd92be2aecba301d7276b718c3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2009 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.common.utility.tests.internal.model.value;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.HashBag;
import org.eclipse.jpt.common.utility.internal.iterators.ChainIterator;
import org.eclipse.jpt.common.utility.internal.iterators.ReadOnlyIterator;
import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
import org.eclipse.jpt.common.utility.internal.iterators.TreeIterator;
import org.eclipse.jpt.common.utility.internal.model.AbstractModel;
import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.TreeAspectAdapter;
import org.eclipse.jpt.common.utility.model.event.TreeAddEvent;
import org.eclipse.jpt.common.utility.model.event.TreeChangeEvent;
import org.eclipse.jpt.common.utility.model.event.TreeClearEvent;
import org.eclipse.jpt.common.utility.model.event.TreeEvent;
import org.eclipse.jpt.common.utility.model.event.TreeRemoveEvent;
import org.eclipse.jpt.common.utility.model.listener.ChangeAdapter;
import org.eclipse.jpt.common.utility.model.listener.ChangeListener;
import org.eclipse.jpt.common.utility.model.listener.TreeChangeListener;
import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.common.utility.model.value.TreeValueModel;
import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
import org.eclipse.jpt.common.utility.tests.internal.TestTools;
@SuppressWarnings("nls")
public class TreeAspectAdapterTests extends TestCase {
private TestSubject subject1;
private WritablePropertyValueModel<TestSubject> subjectHolder1;
private TreeAspectAdapter<TestSubject, List<TestNode>> aa1;
private TreeEvent event1;
private TreeChangeListener listener1;
private TestSubject subject2;
public TreeAspectAdapterTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
this.subject1 = new TestSubject();
TestNode root, node;
root = this.subject1.getRootNameNode();
node = this.subject1.addName(root, "name 1.1");
this.subject1.addName(node, "name 1.1.1");
this.subject1.addName(node, "name 1.1.2");
node = this.subject1.addName(root, "name 1.2");
this.subject1.addName(node, "name 1.2.1");
node = this.subject1.addName(root, "name 1.3");
root = this.subject1.getRootDescriptionNode();
node = this.subject1.addDescription(root, "description 1.1");
this.subject1.addDescription(node, "description 1.1.1");
this.subject1.addDescription(node, "description 1.1.2");
node = this.subject1.addDescription(root, "description 1.2");
this.subject1.addDescription(node, "description 1.2.1");
node = this.subject1.addDescription(root, "description 1.3");
this.subjectHolder1 = new SimplePropertyValueModel<TestSubject>(this.subject1);
this.aa1 = this.buildAspectAdapter(this.subjectHolder1);
this.listener1 = this.buildValueChangeListener1();
this.aa1.addTreeChangeListener(TreeValueModel.NODES, this.listener1);
this.event1 = null;
this.subject2 = new TestSubject();
root = this.subject2.getRootNameNode();
node = this.subject2.addName(root, "name 2.1");
this.subject2.addName(node, "name 2.1.1");
this.subject2.addName(node, "name 2.1.2");
node = this.subject2.addName(root, "name 2.2");
this.subject2.addName(node, "name 2.2.1");
node = this.subject2.addName(root, "name 2.3");
root = this.subject2.getRootDescriptionNode();
node = this.subject2.addDescription(root, "description 2.1");
this.subject2.addDescription(node, "description 2.1.1");
this.subject2.addDescription(node, "description 2.1.2");
node = this.subject2.addDescription(root, "description 2.2");
this.subject2.addDescription(node, "description 2.2.1");
node = this.subject2.addDescription(root, "description 2.3");
}
private TreeAspectAdapter<TestSubject, List<TestNode>> buildAspectAdapter(PropertyValueModel<TestSubject> subjectHolder) {
return new TreeAspectAdapter<TestSubject, List<TestNode>>(subjectHolder, TestSubject.NAMES_TREE) {
// this is not a typical aspect adapter - the value is determined by the aspect name
@Override
protected Iterator<List<TestNode>> nodes_() {
if (this.treeNames[0] == TestSubject.NAMES_TREE) {
return this.subject.namePaths();
}
if (this.treeNames[0] == TestSubject.DESCRIPTIONS_TREE) {
return this.subject.descriptionPaths();
}
throw new IllegalStateException("invalid aspect name: " + this.treeNames[0]);
}
};
}
private ChangeListener buildValueChangeListener1() {
return new ChangeAdapter() {
@Override
public void nodeAdded(TreeAddEvent e) {
TreeAspectAdapterTests.this.value1Changed(e);
}
@Override
public void nodeRemoved(TreeRemoveEvent e) {
TreeAspectAdapterTests.this.value1Changed(e);
}
@Override
public void treeCleared(TreeClearEvent e) {
TreeAspectAdapterTests.this.value1Changed(e);
}
@Override
public void treeChanged(TreeChangeEvent e) {
TreeAspectAdapterTests.this.value1Changed(e);
}
};
}
void value1Changed(TreeEvent e) {
this.event1 = e;
}
@Override
protected void tearDown() throws Exception {
TestTools.clear(this);
super.tearDown();
}
public void testSubjectHolder() {
assertNull(this.event1);
this.subjectHolder1.setValue(this.subject2);
assertNotNull(this.event1);
assertEquals(this.aa1, this.event1.getSource());
assertEquals(TreeValueModel.NODES, this.event1.getTreeName());
this.event1 = null;
this.subjectHolder1.setValue(null);
assertNotNull(this.event1);
assertEquals(this.aa1, this.event1.getSource());
assertEquals(TreeValueModel.NODES, this.event1.getTreeName());
this.event1 = null;
this.subjectHolder1.setValue(this.subject1);
assertNotNull(this.event1);
assertEquals(this.aa1, this.event1.getSource());
assertEquals(TreeValueModel.NODES, this.event1.getTreeName());
}
public void testTreeStructureChange() {
assertNull(this.event1);
this.subject1.addTwoNames(this.subject1.getRootNameNode(), "jam", "jaz");
assertNotNull(this.event1);
assertEquals(this.aa1, this.event1.getSource());
assertEquals(TreeValueModel.NODES, this.event1.getTreeName());
assertTrue(this.subject1.containsNameNode("jam"));
assertTrue(this.subject1.containsNameNode("jaz"));
}
public void testNodes() {
assertEquals(this.convertToNames(this.subject1.namePaths()), this.convertToNames(this.aa1.nodes()));
}
private Collection<String> convertToNames(Iterator<List<TestNode>> namePaths) {
Collection<String> result = new HashBag<String>();
while (namePaths.hasNext()) {
List<TestNode> path = namePaths.next();
StringBuffer sb = new StringBuffer();
sb.append('[');
for (int i = 0; i < path.size(); i++) {
sb.append(path.get(i).getText());
if (i < path.size() - 1) {
sb.append(':');
}
}
sb.append(']');
result.add(sb.toString());
}
return result;
}
public void testHasListeners() {
assertTrue(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES));
assertTrue(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE));
this.aa1.removeTreeChangeListener(TreeValueModel.NODES, this.listener1);
assertFalse(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE));
assertFalse(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES));
ChangeListener listener2 = this.buildValueChangeListener1();
this.aa1.addChangeListener(listener2);
assertTrue(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES));
assertTrue(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE));
this.aa1.removeChangeListener(listener2);
assertFalse(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE));
assertFalse(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES));
}
// ********** inner classes **********
class TestSubject extends AbstractModel {
private TestNode rootNameNode;
public static final String NAMES_TREE = "names";
private TestNode rootDescriptionNode;
public static final String DESCRIPTIONS_TREE = "descriptions";
public TestSubject() {
this.rootNameNode = new TestNode("root name");
this.rootDescriptionNode = new TestNode("root description");
}
public TestNode getRootNameNode() {
return this.rootNameNode;
}
public Iterator<TestNode> nameNodes() {
return new TreeIterator<TestNode>(this.rootNameNode) {
@Override
public Iterator<TestNode> children(TestNode next) {
return next.children();
}
};
}
public Iterator<List<TestNode>> namePaths() {
return new TransformationIterator<TestNode, List<TestNode>>(this.nameNodes()) {
@Override
protected List<TestNode> transform(TestNode next) {
return next.getPath();
}
};
}
public TestNode addName(TestNode parent, String name) {
TestNode child = new TestNode(name);
parent.addChild(child);
this.fireNodeAdded(NAMES_TREE, child.getPath());
return child;
}
public void addTwoNames(TestNode parent, String name1, String name2) {
parent.addChild(new TestNode(name1));
parent.addChild(new TestNode(name2));
this.fireTreeChanged(NAMES_TREE, parent.getPath());
}
public void removeNameNode(TestNode nameNode) {
nameNode.getParent().removeChild(nameNode);
this.fireNodeRemoved(NAMES_TREE, nameNode.getPath());
}
public boolean containsNameNode(String name) {
return this.nameNode(name) != null;
}
public TestNode nameNode(String name) {
for (Iterator<TestNode> stream = this.nameNodes(); stream.hasNext(); ) {
TestNode node = stream.next();
if (node.getText().equals(name)) {
return node;
}
}
return null;
}
public TestNode getRootDescriptionNode() {
return this.rootDescriptionNode;
}
public Iterator<TestNode> descriptionNodes() {
return new TreeIterator<TestNode>(this.rootDescriptionNode) {
@Override
public Iterator<TestNode> children(TestNode next) {
return next.children();
}
};
}
public Iterator<List<TestNode>> descriptionPaths() {
return new TransformationIterator<TestNode, List<TestNode>>(this.descriptionNodes()) {
@Override
protected List<TestNode> transform(TestNode next) {
return next.getPath();
}
};
}
public TestNode addDescription(TestNode parent, String description) {
TestNode child = new TestNode(description);
parent.addChild(child);
this.fireNodeAdded(DESCRIPTIONS_TREE, child.getPath());
return child;
}
public void removeDescriptionNode(TestNode descriptionNode) {
descriptionNode.getParent().removeChild(descriptionNode);
this.fireNodeRemoved(DESCRIPTIONS_TREE, descriptionNode.getPath());
}
public boolean containsDescriptionNode(String name) {
for (Iterator<TestNode> stream = this.descriptionNodes(); stream.hasNext(); ) {
TestNode node = stream.next();
if (node.getText().equals(name)) {
return true;
}
}
return false;
}
}
class TestNode {
private final String text;
private TestNode parent;
private final Collection<TestNode> children;
public TestNode(String text) {
this.text = text;
this.children = new HashBag<TestNode>();
}
public String getText() {
return this.text;
}
public TestNode getParent() {
return this.parent;
}
private void setParent(TestNode parent) {
this.parent = parent;
}
public Iterator<TestNode> children() {
return new ReadOnlyIterator<TestNode>(this.children);
}
public void addChild(TestNode child) {
this.children.add(child);
child.setParent(this);
}
public void removeChild(TestNode child) {
this.children.remove(child);
}
public List<TestNode> getPath() {
return CollectionTools.reverseList(this.buildAntiPath());
}
private Iterator<TestNode> buildAntiPath() {
return new ChainIterator<TestNode>(this) {
@Override
protected TestNode nextLink(TestNode currentLink) {
return currentLink.getParent();
}
};
}
@Override
public String toString() {
return "TestNode(" + this.text + ")";
}
}
}