/*
* Copyright 2003-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.smodel;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.util.Condition;
import org.jetbrains.mps.util.DescendantsTreeIterator;
import org.jetbrains.mps.util.TreeFilterIterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* @author Artem Tikhomirov
*/
public class TreeIteratorTest {
private SNode start, child1, child2, child3, leafD, leafE, lastNode, topNode;
@Before
public void setUp() {
start = newNode("A");
start.addChild("role", child1 = newNode("B"));
start.addChild("role", child2 = newNode("F"));
start.addChild("role", child3 = newNode("I"));
//
child1.addChild("role", newNode("C"));
child1.addChild("role", leafD = newNode("D"));
child1.addChild("role", leafE = newNode("E"));
//
child2.addChild("role", newNode("G"));
child2.addChild("role", newNode("H"));
//
child3.addChild("role", lastNode = newNode("J"));
//
topNode = newNode("X");
topNode.addChild("role", start);
topNode.addChild("role", newNode("Y"));
//
}
@Test
public void testDescendantsTreeIterator() {
ArrayList<SNode> all = new ArrayList<SNode>();
for (DescendantsTreeIterator it = new DescendantsTreeIterator(start); it.hasNext(); ) {
SNode n = it.next();
all.add(n);
}
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"), names(all));
// skip non-leaf element
List<SNode> withoutNode2 = iterateTree(start, child2);
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "I", "J"), names(withoutNode2));
// skip leaf element without a sibling
List<SNode> withoutLeafE = iterateTree(start, leafE);
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "F", "G", "H", "I", "J"), names(withoutLeafE));
// skip leaf element with a sibling
List<SNode> withoutLeafD = iterateTree(start, leafD);
Assert.assertEquals(Arrays.asList("A", "B", "C", "E", "F", "G", "H", "I", "J"), names(withoutLeafD));
// skip very last iteration element
List<SNode> withoutLastNode = iterateTree(start, lastNode);
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I"), names(withoutLastNode));
//
ArrayList<SNode> singleElement = new ArrayList<SNode>();
for (DescendantsTreeIterator it = new DescendantsTreeIterator(newNode("W")); it.hasNext(); ) {
SNode n = it.next();
singleElement.add(n);
}
Assert.assertEquals(Arrays.asList("W"), names(singleElement));
//
Assert.assertTrue(iterateTree(start, start).isEmpty());
final SNode root = newNode("W");
List<SNode> dropRoot = iterateTree(root, root);
Assert.assertTrue(dropRoot.isEmpty());
}
private static List<SNode> iterateTree(SNode start, SNode skipNode) {
ArrayList<SNode> rv = new ArrayList<SNode>();
for (DescendantsTreeIterator it = new DescendantsTreeIterator(start); it.hasNext(); ) {
SNode n = it.next();
if (n == skipNode) {
it.skipChildren();
continue;
}
rv.add(n);
}
return rv;
}
@Test
public void testTreeFilterIterator() {
// except node2
ArrayList<SNode> aaa = new ArrayList<SNode>();
for (Iterator<SNode> it = new TreeFilterIterator<SNode>(new DescendantsTreeIterator(start), new NodeFilter(child2)); it.hasNext(); ) {
aaa.add(it.next());
}
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "I", "J"), names(aaa));
// except node3 (last non-leaf)
aaa = new ArrayList<SNode>();
for (Iterator<SNode> it = new TreeFilterIterator<SNode>(new DescendantsTreeIterator(start), new NodeFilter(child3)); it.hasNext(); ) {
aaa.add(it.next());
}
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H"), names(aaa));
// except start node itself
aaa = new ArrayList<SNode>();
for (Iterator<SNode> it = new TreeFilterIterator<SNode>(new DescendantsTreeIterator(start), new NodeFilter(start)); it.hasNext(); ) {
aaa.add(it.next());
}
Assert.assertTrue(aaa.isEmpty());
// except last node (last leaf and the last one of complete iteration)
aaa = new ArrayList<SNode>();
for (Iterator<SNode> it = new TreeFilterIterator<SNode>(new DescendantsTreeIterator(start), new NodeFilter(lastNode)); it.hasNext(); ) {
aaa.add(it.next());
}
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I"), names(aaa));
// except node which is not from the sub-tree
aaa = new ArrayList<SNode>();
for (Iterator<SNode> it = new TreeFilterIterator<SNode>(new DescendantsTreeIterator(start), new NodeFilter(topNode)); it.hasNext(); ) {
aaa.add(it.next());
}
Assert.assertEquals(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"), names(aaa));
}
private static List<String> names(Collection<SNode> nodes) {
ArrayList<String> rv = new ArrayList<String>(nodes.size());
for (SNode n : nodes) {
rv.add(n.getProperty(SNodeUtil.property_INamedConcept_name));
}
return rv;
}
private static SNode newNode(String name) {
jetbrains.mps.smodel.SNode node = new jetbrains.mps.smodel.SNode(MetaAdapterFactory.getConcept(0, 0, 0, "Mock"));
node.setProperty(SNodeUtil.property_INamedConcept_name, name);
// SNode.toString doesn't like SNode when there's no complete MPS - can't get node's concept. Alias helps to make it feel better.
node.setProperty(SNodeUtil.property_BaseConcept_alias, name);
return node;
}
private static class NodeFilter implements Condition<SNode> {
private final SNode myFilteredNode;
public NodeFilter(SNode node) {
myFilteredNode = node;
}
@Override
public boolean met(SNode object) {
return object == myFilteredNode;
}
}
}