/** * Copyright 2009 Google Inc. * * 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 org.waveprotocol.wave.model.util; import junit.framework.TestCase; import org.waveprotocol.wave.model.document.ReadableDocument; import org.waveprotocol.wave.model.document.raw.impl.Element; import org.waveprotocol.wave.model.document.raw.impl.Node; import org.waveprotocol.wave.model.document.raw.impl.Text; import org.waveprotocol.wave.model.document.util.DocProviders; import org.waveprotocol.wave.model.document.util.FilteredView; /** * Test cases for FilteredView behaviour * * TODO(danilatos): Define some behaviour for calling non-visibility methods on * invisible nodes (such as, throw exception, or return null), and implement and * write unit tests for it. * * @author danilatos@google.com (Daniel Danilatos) */ public class FilteredViewTest extends TestCase { /** * Simplistic filtering view * * Elements with "s" as the tag name are shallow skipped, with "d" are deep * skipped. */ private class BasicFilteringView extends FilteredView<Node, Element, Text> { public BasicFilteringView(ReadableDocument<Node, Element, Text> innerView) { super(innerView); } @Override protected FilteredView.Skip getSkipLevel(Node node) { // Check if it's in the document, for validity Node find = node; while (find != getDocumentElement()) { if (find == null) { return Skip.INVALID; } find = find.getParentElement(); } Element e = asElement(node); if (e == null) { return Skip.NONE; } else if (e.getTagName().equals("s")) { return Skip.SHALLOW; } else if (e.getTagName().equals("d")) { return Skip.DEEP; } else { return Skip.NONE; } } protected Node getNode(int ... xmlPoint) { Node current = getDocumentElement(); for (int i = 0; i < xmlPoint.length; i++) { current = current.getFirstChild(); for (int remaining = xmlPoint[i]; remaining > 0; remaining--) { current = current.getNextSibling(); } } return current; } } public void testUnfilteredTraversalStillWorks() { BasicFilteringView doc = parse("hi<a/>there"); assertSame(doc.getNode(1), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(1), doc.getPreviousSibling(doc.getNode(2))); assertSame(null, doc.getPreviousSibling(doc.getNode(0))); assertSame(null, doc.getNextSibling(doc.getNode(2))); assertSame(null, doc.getFirstChild(doc.getNode(1))); assertSame(null, doc.getLastChild(doc.getNode(1))); assertSame(doc.getDocumentElement(), doc.getParentElement(doc.getNode(1))); assertSame(doc.getNode(0), doc.getFirstChild(doc.getDocumentElement())); assertSame(doc.getNode(2), doc.getLastChild(doc.getDocumentElement())); } public void testSubtreeSkippedForDeepNodes() { BasicFilteringView doc = parse("hi<d>xyz</d>there"); assertSame(doc.getNode(2), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(0), doc.getPreviousSibling(doc.getNode(2))); doc = parse("<d>xyz</d>hi there<d>abc</d>"); assertSame(null, doc.getNextSibling(doc.getNode(1))); assertSame(null, doc.getPreviousSibling(doc.getNode(1))); assertSame(doc.getNode(1), doc.getFirstChild(doc.getDocumentElement())); assertSame(doc.getNode(1), doc.getLastChild(doc.getDocumentElement())); } public void testSubtreeRepeatedlySkippedForDeepNodes() { BasicFilteringView doc = parse("hi<d>abc</d><d>xyz</d>there"); assertSame(doc.getNode(3), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(0), doc.getPreviousSibling(doc.getNode(3))); doc = parse("<d>zyx</d><d>xyz</d>hi there<d>abc</d><d>def</d>"); assertSame(null, doc.getNextSibling(doc.getNode(2))); assertSame(null, doc.getPreviousSibling(doc.getNode(2))); assertSame(doc.getNode(2), doc.getFirstChild(doc.getDocumentElement())); assertSame(doc.getNode(2), doc.getLastChild(doc.getDocumentElement())); } public void testElementSkippedForShallowNodes() { BasicFilteringView doc = parse("hi<s/>there"); assertSame(doc.getNode(2), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(0), doc.getPreviousSibling(doc.getNode(2))); doc = parse("hi<s>xyz</s>there"); assertSame(doc.getNode(1, 0), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(1, 0), doc.getPreviousSibling(doc.getNode(2))); assertSame(doc.getDocumentElement(), doc.getParentElement(doc.getNode(1, 0))); doc = parse("<s>xyz</s>hi there<s>abc</s>"); assertSame(doc.getNode(2, 0), doc.getNextSibling(doc.getNode(1))); assertSame(doc.getNode(0, 0), doc.getPreviousSibling(doc.getNode(1))); assertSame(doc.getNode(0, 0), doc.getFirstChild(doc.getDocumentElement())); assertSame(doc.getNode(2, 0), doc.getLastChild(doc.getDocumentElement())); } public void testElementRepeatedlySkippedForShallowNodes() { BasicFilteringView doc = parse("hi<s><s>xyz</s><s>zyx</s></s>there"); assertSame(doc.getNode(1, 0, 0), doc.getNextSibling(doc.getNode(0))); assertSame(doc.getNode(1, 1, 0), doc.getPreviousSibling(doc.getNode(2))); assertSame(doc.getDocumentElement(), doc.getParentElement(doc.getNode(1, 0, 0))); doc = parse("<s><s>xyz</s><s>zyx</s></s>hi there<s><s>abc</s><s>cba</s></s>"); assertSame(doc.getNode(2, 0, 0), doc.getNextSibling(doc.getNode(1))); assertSame(doc.getNode(0, 1, 0), doc.getPreviousSibling(doc.getNode(1))); assertSame(doc.getNode(0, 0, 0), doc.getFirstChild(doc.getDocumentElement())); assertSame(doc.getNode(2, 1, 0), doc.getLastChild(doc.getDocumentElement())); } public void testVisibilityMethodsAlwaysReturnGivenNodeIfVisible() { BasicFilteringView doc = parse("hi<a>th</a>ere"); assertSame(doc.getNode(1), doc.getVisibleNode(doc.getNode(1))); assertSame(doc.getNode(1), doc.getVisibleNodeNext(doc.getNode(1))); assertSame(doc.getNode(1), doc.getVisibleNodePrevious(doc.getNode(1))); assertSame(doc.getNode(1), doc.getVisibleNodeFirst(doc.getNode(1))); assertSame(doc.getNode(1), doc.getVisibleNodeLast(doc.getNode(1))); } public void testVisibilityMethodsAreDepthFirstAndExitVisibleContainers() { BasicFilteringView doc = parse("hi<s><s>xyz</s><s>zyx</s></s>there<s/>"); assertSame(doc.getNode(1, 0, 0), doc.getVisibleNodeFirst(doc.getNode(1))); assertSame(doc.getNode(2), doc.getVisibleNodeNext(doc.getNode(1))); assertSame(doc.getNode(1, 0, 0), doc.getVisibleNodeFirst(doc.getNode(1, 0))); assertSame(doc.getNode(1, 1, 0), doc.getVisibleNodeNext(doc.getNode(1, 0))); assertSame(doc.getNode(1, 1, 0), doc.getVisibleNodeLast(doc.getNode(1, 1))); assertSame(doc.getNode(1, 0, 0), doc.getVisibleNodePrevious(doc.getNode(1, 1))); assertSame(doc.getDocumentElement(), doc.getVisibleNode(doc.getNode(1, 0))); doc = parse("hi<d><d/>abc</d><d>xyz</d>there"); assertSame(doc.getNode(3), doc.getVisibleNodeNext(doc.getNode(1))); assertSame(doc.getNode(0), doc.getVisibleNodePrevious(doc.getNode(2))); assertSame(doc.getDocumentElement(), doc.getVisibleNode(doc.getNode(1, 0))); doc = parse("hi<s><d/><d/></s>there"); assertSame(doc.getNode(2), doc.getVisibleNodeFirst(doc.getNode(1, 0))); assertSame(doc.getNode(2), doc.getVisibleNodeNext(doc.getNode(1, 0))); assertSame(doc.getNode(0), doc.getVisibleNodeLast(doc.getNode(1, 1))); assertSame(doc.getNode(0), doc.getVisibleNodePrevious(doc.getNode(1, 1))); } public void testVisibilityMethodsReturnNullForNullInput() { BasicFilteringView doc = parse(""); assertSame(null, doc.getVisibleNodeFirst(null)); assertSame(null, doc.getVisibleNodeNext(null)); assertSame(null, doc.getVisibleNodePrevious(null)); assertSame(null, doc.getVisibleNodePrevious(null)); assertSame(null, doc.getVisibleNode(null)); } public void testNullReturnedForInvalidNodes() { BasicFilteringView doc = parse(""); Node invalidNode = parse("<x>a<y>b</y>c</x>").getNode(0); assertSame(null, doc.getFirstChild(invalidNode)); assertSame(null, doc.getLastChild(invalidNode)); assertSame(null, doc.getNextSibling(invalidNode)); assertSame(null, doc.getPreviousSibling(invalidNode)); assertSame(null, doc.getParentElement(invalidNode)); } protected BasicFilteringView parse(String xml) { return new BasicFilteringView(DocProviders.POJO.parse(xml)); } }