| /******************************************************************************* |
| * Copyright (c) 2007, 2008 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.utility.tests.internal.model.value; |
| |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.HashBag; |
| import org.eclipse.jpt.utility.internal.iterators.ChainIterator; |
| import org.eclipse.jpt.utility.internal.iterators.ReadOnlyIterator; |
| import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; |
| import org.eclipse.jpt.utility.internal.iterators.TreeIterator; |
| import org.eclipse.jpt.utility.internal.model.AbstractModel; |
| import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel; |
| import org.eclipse.jpt.utility.internal.model.value.TreeAspectAdapter; |
| import org.eclipse.jpt.utility.model.event.TreeChangeEvent; |
| import org.eclipse.jpt.utility.model.listener.TreeChangeListener; |
| import org.eclipse.jpt.utility.model.value.PropertyValueModel; |
| import org.eclipse.jpt.utility.model.value.TreeValueModel; |
| import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel; |
| import org.eclipse.jpt.utility.tests.internal.TestTools; |
| |
| import junit.framework.TestCase; |
| |
| public class TreeAspectAdapterTests extends TestCase { |
| private TestSubject subject1; |
| private WritablePropertyValueModel<TestSubject> subjectHolder1; |
| private TreeAspectAdapter<TestSubject, TestNode[]> aa1; |
| private TreeChangeEvent 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, TestNode[]> buildAspectAdapter(PropertyValueModel<TestSubject> subjectHolder) { |
| return new TreeAspectAdapter<TestSubject, TestNode[]>(subjectHolder, TestSubject.NAMES_TREE) { |
| // this is not a typical aspect adapter - the value is determined by the aspect name |
| @Override |
| protected Iterator<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 TreeChangeListener buildValueChangeListener1() { |
| return new TreeChangeListener() { |
| public void nodeAdded(TreeChangeEvent e) { |
| TreeAspectAdapterTests.this.value1Changed(e); |
| } |
| public void nodeRemoved(TreeChangeEvent e) { |
| TreeAspectAdapterTests.this.value1Changed(e); |
| } |
| public void treeCleared(TreeChangeEvent e) { |
| TreeAspectAdapterTests.this.value1Changed(e); |
| } |
| public void treeChanged(TreeChangeEvent e) { |
| TreeAspectAdapterTests.this.value1Changed(e); |
| } |
| }; |
| } |
| |
| void value1Changed(TreeChangeEvent 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()); |
| assertEquals(0, this.event1.getPath().length); |
| |
| this.event1 = null; |
| this.subjectHolder1.setValue(null); |
| assertNotNull(this.event1); |
| assertEquals(this.aa1, this.event1.getSource()); |
| assertEquals(TreeValueModel.NODES, this.event1.getTreeName()); |
| assertEquals(0, this.event1.getPath().length); |
| |
| this.event1 = null; |
| this.subjectHolder1.setValue(this.subject1); |
| assertNotNull(this.event1); |
| assertEquals(this.aa1, this.event1.getSource()); |
| assertEquals(TreeValueModel.NODES, this.event1.getTreeName()); |
| assertEquals(0, this.event1.getPath().length); |
| } |
| |
| 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()); |
| Object[] path = this.event1.getPath(); |
| assertEquals(this.subject1.getRootNameNode(), path[path.length - 1]); |
| 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<TestNode[]> namePaths) { |
| Collection<String> result = new HashBag<String>(); |
| while (namePaths.hasNext()) { |
| Object[] path = namePaths.next(); |
| StringBuffer sb = new StringBuffer(); |
| sb.append('['); |
| for (int i = 0; i < path.length; i++) { |
| sb.append(((TestNode) path[i]).getText()); |
| if (i < path.length - 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)); |
| |
| TreeChangeListener listener2 = this.buildValueChangeListener1(); |
| this.aa1.addTreeChangeListener(listener2); |
| assertTrue(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES)); |
| assertTrue(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE)); |
| this.aa1.removeTreeChangeListener(listener2); |
| assertFalse(this.subject1.hasAnyTreeChangeListeners(TestSubject.NAMES_TREE)); |
| assertFalse(this.aa1.hasAnyTreeChangeListeners(TreeValueModel.NODES)); |
| } |
| |
| // ********** inner classes ********** |
| |
| private 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<TestNode[]> namePaths() { |
| return new TransformationIterator<TestNode, TestNode[]>(this.nameNodes()) { |
| @Override |
| protected TestNode[] transform(TestNode next) { |
| return next.path(); |
| } |
| }; |
| } |
| public TestNode addName(TestNode parent, String name) { |
| TestNode child = new TestNode(name); |
| parent.addChild(child); |
| this.fireNodeAdded(NAMES_TREE, child.path()); |
| 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.path()); |
| } |
| public void removeNameNode(TestNode nameNode) { |
| nameNode.getParent().removeChild(nameNode); |
| this.fireNodeRemoved(NAMES_TREE, nameNode.path()); |
| } |
| 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<TestNode[]> descriptionPaths() { |
| return new TransformationIterator<TestNode, TestNode[]>(this.descriptionNodes()) { |
| @Override |
| protected TestNode[] transform(TestNode next) { |
| return next.path(); |
| } |
| }; |
| } |
| public TestNode addDescription(TestNode parent, String description) { |
| TestNode child = new TestNode(description); |
| parent.addChild(child); |
| this.fireNodeAdded(DESCRIPTIONS_TREE, child.path()); |
| return child; |
| } |
| public void removeDescriptionNode(TestNode descriptionNode) { |
| descriptionNode.getParent().removeChild(descriptionNode); |
| this.fireNodeRemoved(DESCRIPTIONS_TREE, descriptionNode.path()); |
| } |
| 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; |
| } |
| } |
| |
| private 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 TestNode[] path() { |
| return CollectionTools.reverseList(this.buildAntiPath()).toArray(new TestNode[0]); |
| } |
| 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 + ")"; |
| } |
| } |
| |
| } |