import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
+import java.util.Set;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
private final HashSet<Object> noChildrenAllowed = new HashSet<Object>();
/**
- * Mapping from Item ID to parent Item.
+ * Mapping from Item ID to parent Item ID.
*/
private final HashMap<Object, Object> parent = new HashMap<Object, Object>();
+ /**
+ * Mapping from Item ID to parent Item ID for items included in the filtered
+ * container.
+ */
+ private HashMap<Object, Object> filteredParent = null;
+
/**
* Mapping from Item ID to a list of child IDs.
*/
*/
private LinkedList<Object> filteredRoots = null;
+ /**
+ * Determines how filtering of the container is done.
+ */
+ private boolean includeParentsWhenFiltering = true;
+
/*
* Can the specified Item have any children? Don't add a JavaDoc comment
* here, we use the default documentation from implemented interface.
* interface.
*/
public Object getParent(Object itemId) {
+ if (filteredParent != null) {
+ return filteredParent.get(itemId);
+ }
return parent.get(itemId);
}
* interface.
*/
public boolean isRoot(Object itemId) {
- if (filteredRoots != null && !filteredRoots.contains(itemId)) {
- return false;
- }
-
- if (parent.containsKey(itemId)) {
- return false;
+ // If the container is filtered the itemId must be among filteredRoots
+ // to be a root.
+ if (filteredRoots != null) {
+ if (!filteredRoots.contains(itemId)) {
+ return false;
+ }
+ } else {
+ // Container is not filtered
+ if (parent.containsKey(itemId)) {
+ return false;
+ }
}
return containsId(itemId);
// Making root?
if (newParentId == null) {
// The itemId should become a root so we need to
- // - Remove it from the old parent's children list (also filtered
- // list)
+ // - Remove it from the old parent's children list
// - Add it as a root
// - Remove it from the item -> parent list (parent is null for
// roots)
children.remove(itemId);
}
- if (filteredChildren != null) {
- LinkedList<Object> f = filteredChildren.get(itemId);
- if (f != null) {
- f.remove(itemId);
- if (f.isEmpty()) {
- filteredChildren.remove(f);
- }
- }
- }
}
// Add to be a root
roots.add(itemId);
- if (filteredRoots != null) {
- if (passesFilters(itemId)) {
- filteredRoots.add(itemId);
- }
- }
// Updates parent
parent.remove(itemId);
+ if (hasFilters()) {
+ // Refilter the container if setParent is called when filters
+ // are applied. Changing parent can change what is included in
+ // the filtered version (if includeParentsWhenFiltering==true).
+ doFilterContainer(hasFilters());
+ }
+
fireContentsChange(-1);
return true;
}
pcl.add(itemId);
- // Add children list for filtered case also
- if (filteredChildren != null) {
- LinkedList<Object> f = filteredChildren.get(newParentId);
- if (f == null) {
- // Create an empty list for holding children if one were not
- // previously created
- f = new LinkedList<Object>();
- filteredChildren.put(newParentId, f);
- }
- }
-
// Removes from old parent or root
if (oldParentId == null) {
roots.remove(itemId);
children.remove(oldParentId);
}
}
- if (filteredChildren != null) {
- LinkedList<Object> f = filteredChildren.get(oldParentId);
- if (f != null) {
- f.remove(itemId);
- if (f.isEmpty()) {
- filteredChildren.remove(oldParentId);
- }
- }
- }
+ }
+
+ if (hasFilters()) {
+ // Refilter the container if setParent is called when filters
+ // are applied. Changing parent can change what is included in
+ // the filtered version (if includeParentsWhenFiltering==true).
+ doFilterContainer(hasFilters());
}
fireContentsChange(-1);
return true;
}
+ private boolean hasFilters() {
+ return (filteredRoots != null);
+ }
+
/**
* TODO javadoc
*
}
}
+ /**
+ * Used to control how filtering works. @see
+ * {@link #setIncludeParentsWhenFiltering(boolean)} for more information.
+ *
+ * @return true if all parents for items that match the filter are included
+ * when filtering, false if only the matching items are included
+ */
+ public boolean isIncludeParentsWhenFiltering() {
+ return includeParentsWhenFiltering;
+ }
+
+ /**
+ * Controls how the filtering of the container works. Set this to true to
+ * make filtering include parents for all matched items in addition to the
+ * items themselves. Setting this to false causes the filtering to only
+ * include the matching items and make items with excluded parents into root
+ * items.
+ *
+ * @param includeParentsWhenFiltering
+ * true to include all parents for items that match the filter,
+ * false to only include the matching items
+ */
+ public void setIncludeParentsWhenFiltering(
+ boolean includeParentsWhenFiltering) {
+ this.includeParentsWhenFiltering = includeParentsWhenFiltering;
+ }
+
/*
* Overridden to provide filtering for root & children items.
*
* @see com.vaadin.data.util.IndexedContainer#updateContainerFiltering()
*/
@Override
- protected void updateContainerFiltering() {
- super.updateContainerFiltering();
+ protected boolean doFilterContainer(boolean hasFilters) {
+ if (!hasFilters) {
+ // All filters removed
+ filteredRoots = null;
+ filteredChildren = null;
+ return super.doFilterContainer(hasFilters);
+ }
+
+ // Reset data structures
filteredRoots = new LinkedList<Object>();
filteredChildren = new HashMap<Object, LinkedList<Object>>();
+ filteredParent = new HashMap<Object, Object>();
+
+ if (includeParentsWhenFiltering) {
+ // Filter so that parents for items that match the filter are also
+ // included
+ HashSet<Object> includedItems = new HashSet<Object>();
+ for (Object rootId : roots) {
+ if (filterIncludingParents(rootId, includedItems)) {
+ filteredRoots.add(rootId);
+ addFilteredChildrenRecursively(rootId, includedItems);
+ }
+ }
+ // includedItemIds now contains all the item ids that should be
+ // included. Filter IndexedContainer based on this
+ filterOverride = includedItems;
+ super.doFilterContainer(hasFilters);
+ filterOverride = null;
+
+ return true;
+ } else {
+ // Filter by including all items that pass the filter and make items
+ // with no parent new root items
+
+ // Filter IndexedContainer first so getItemIds return the items that
+ // match
+ super.doFilterContainer(hasFilters);
+
+ LinkedHashSet<Object> filteredItemIds = new LinkedHashSet<Object>(
+ getItemIds());
- // Filter root item ids
- for (Object rootId : roots) {
- if (passesFilters(rootId)) {
- filteredRoots.add(rootId);
+ for (Object itemId : filteredItemIds) {
+ Object itemParent = parent.get(itemId);
+ if (itemParent == null || !filteredItemIds.contains(itemParent)) {
+ // Parent is not included or this was a root, in both cases
+ // this should be a filtered root
+ filteredRoots.add(itemId);
+ } else {
+ // Parent is included. Add this to the children list (create
+ // it first if necessary)
+ addFilteredChild(itemParent, itemId);
+ }
}
+
+ return true;
}
+ }
- // Filter children
- for (Object parent : children.keySet()) {
- if (passesFilters(parent)) {
- LinkedList<Object> filtered = new LinkedList<Object>();
- filteredChildren.put(parent, filtered);
- for (Object child : children.get(parent)) {
- if (passesFilters(child)) {
- filtered.add(child);
- }
- }
+ /**
+ * Adds the given childItemId as a filteredChildren for the parentItemId and
+ * sets it filteredParent.
+ *
+ * @param parentItemId
+ * @param childItemId
+ */
+ private void addFilteredChild(Object parentItemId, Object childItemId) {
+ LinkedList<Object> parentToChildrenList = filteredChildren
+ .get(parentItemId);
+ if (parentToChildrenList == null) {
+ parentToChildrenList = new LinkedList<Object>();
+ filteredChildren.put(parentItemId, parentToChildrenList);
+ }
+ filteredParent.put(childItemId, parentItemId);
+ parentToChildrenList.add(childItemId);
+
+ }
+
+ /**
+ * Recursively adds all items in the includedItems list to the
+ * filteredChildren map in the same order as they are in the children map.
+ * Starts from parentItemId and recurses down as long as child items that
+ * should be included are found.
+ *
+ * @param parentItemId
+ * The item id to start recurse from. Not added to a
+ * filteredChildren list
+ * @param includedItems
+ * Set containing the item ids for the items that should be
+ * included in the filteredChildren map
+ */
+ private void addFilteredChildrenRecursively(Object parentItemId,
+ HashSet<Object> includedItems) {
+ LinkedList<Object> childList = children.get(parentItemId);
+ if (childList == null) {
+ return;
+ }
+
+ for (Object childItemId : childList) {
+ if (includedItems.contains(childItemId)) {
+ addFilteredChild(parentItemId, childItemId);
+ addFilteredChildrenRecursively(childItemId, includedItems);
}
}
+ }
+ /**
+ * Scans the itemId and all its children for which items should be included
+ * when filtering. All items which passes the filters are included.
+ * Additionally all items that have a child node that should be included are
+ * also themselves included.
+ *
+ * @param itemId
+ * @param includedItems
+ * @return true if the itemId should be included in the filtered container.
+ */
+ private boolean filterIncludingParents(Object itemId,
+ HashSet<Object> includedItems) {
+ boolean toBeIncluded = passesFilters(itemId);
+
+ LinkedList<Object> childList = children.get(itemId);
+ if (childList != null) {
+ for (Object childItemId : children.get(itemId)) {
+ toBeIncluded |= filterIncludingParents(childItemId,
+ includedItems);
+ }
+ }
+
+ if (toBeIncluded) {
+ includedItems.add(itemId);
+ }
+ return toBeIncluded;
}
+ private Set<Object> filterOverride = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.data.util.IndexedContainer#passesFilters(java.lang.Object)
+ */
+ @Override
+ protected boolean passesFilters(Object itemId) {
+ if (filterOverride != null) {
+ return filterOverride.contains(itemId);
+ } else {
+ return super.passesFilters(itemId);
+ }
+ }
}
private ArrayList<Object> itemIds = new ArrayList<Object>();
/** List of item ids that passes the filtering */
- private LinkedHashSet filteredItemIds = null;
+ private LinkedHashSet<Object> filteredItemIds = null;
/**
* Linked list of ordered Property IDs.
// this optimization is why some code is duplicated with
// addItemAtInternalIndex()
- final Item item = new IndexedContainerItem(itemId);
if (filteredItemIds != null) {
- if (passesFilters(item)) {
+ if (passesFilters(itemId)) {
filteredItemIds.add(itemId);
}
}
// Sends the event
fireContentsChange(itemIds.size() - 1);
- return item;
+ return new IndexedContainerItem(itemId);
}
/**
}
}
- protected void updateContainerFiltering() {
+ /**
+ * Called when the filters have changed or when another event that effects
+ * filtering has taken place. Updates internal data structures and fires an
+ * item set change if necessary.
+ */
+ private void updateContainerFiltering() {
// Clearing filters?
- if (filters == null || filters.isEmpty()) {
+ boolean hasFilters = (filters != null && !filters.isEmpty());
+
+ if (doFilterContainer(hasFilters)) {
+ fireContentsChange(-1);
+ }
+ }
+
+ /**
+ * Filters the data in the container and updates internal data structures.
+ * This method should reset any internal data structures and then repopulate
+ * them so {@link #getItemIds()} and other methods only return the filtered
+ * items.
+ *
+ * @param hasFilters
+ * true if filters has been set for the container, false
+ * otherwise
+ * @return true if the item set has changed as a result of the filtering
+ */
+ protected boolean doFilterContainer(boolean hasFilters) {
+ if (!hasFilters) {
filteredItemIds = null;
if (filters != null) {
filters = null;
- fireContentsChange(-1);
+ return true;
}
- return;
- }
+ return false;
+ }
// Reset filtered list
if (filteredItemIds == null) {
filteredItemIds = new LinkedHashSet();
}
}
- fireContentsChange(-1);
- }
+ return true;
- protected final boolean passesFilters(Object itemId) {
- return passesFilters(new IndexedContainerItem(itemId));
}
- private boolean passesFilters(Item item) {
+ /**
+ * Checks if the given itemId passes the filters set for the container. The
+ * caller should make sure the itemId exists in the container. For
+ * non-existing itemIds the behavior is undefined.
+ *
+ * @param itemId
+ * An itemId that exists in the container.
+ * @return true if the itemId passes all filters or no filters are set,
+ * false otherwise.
+ */
+ protected boolean passesFilters(Object itemId) {
+ IndexedContainerItem item = new IndexedContainerItem(itemId);
if (filters == null) {
return true;
}
package com.vaadin.tests.components.tree;\r
\r
import com.vaadin.data.Item;\r
+import com.vaadin.data.Property.ValueChangeEvent;\r
+import com.vaadin.data.Property.ValueChangeListener;\r
import com.vaadin.data.util.HierarchicalContainer;\r
import com.vaadin.tests.components.TestBase;\r
import com.vaadin.ui.Button;\r
+import com.vaadin.ui.CheckBox;\r
import com.vaadin.ui.Tree;\r
import com.vaadin.ui.Button.ClickEvent;\r
import com.vaadin.ui.Button.ClickListener;\r
ccTree.expandItem(o);\r
}\r
\r
+ final CheckBox filterType = new CheckBox(\r
+ "Include parent when filtering", true);\r
+ filterType.addListener(new ValueChangeListener() {\r
+\r
+ public void valueChange(ValueChangeEvent event) {\r
+ cont.setIncludeParentsWhenFiltering(((CheckBox) event\r
+ .getProperty()).booleanValue());\r
+ }\r
+ });\r
+ addComponent(filterType);\r
+\r
final Button b = new Button("Add filter 'foo'", new ClickListener() {\r
public void buttonClick(final ClickEvent event) {\r
cont.addContainerFilter("caption", "foo", true, false);\r
});\r
\r
addComponent(num);\r
- final Button r = new Button("Remove filter", new ClickListener() {\r
+ final Button num2 = new Button("Add filter '0-'", new ClickListener() {\r
+ public void buttonClick(final ClickEvent event) {\r
+ cont.addContainerFilter("caption", "0-", true, false);\r
+\r
+ }\r
+ });\r
+\r
+ addComponent(num2);\r
+ final Button num3 = new Button("Add filter 'Number 4'",\r
+ new ClickListener() {\r
+ public void buttonClick(final ClickEvent event) {\r
+ cont.addContainerFilter("caption", "Number 4", true,\r
+ false);\r
+\r
+ }\r
+ });\r
+\r
+ addComponent(num3);\r
+ final Button p1 = new Button("Set Number 3 parent to Number 0",\r
+ new ClickListener() {\r
+ public void buttonClick(final ClickEvent event) {\r
+ cont.setParent(3, 0);\r
+\r
+ }\r
+ });\r
+ addComponent(p1);\r
+ final Button r = new Button("Remove filters", new ClickListener() {\r
public void buttonClick(final ClickEvent event) {\r
cont.removeAllContainerFilters();\r
\r
* down to all available nodes.\r
* @param expectedRootSize\r
* Expected number of root items\r
+ * @param rootsHaveChildren\r
+ * true if all roots have children, false otherwise (skips some\r
+ * asserts)\r
*/\r
- private void validateHierarchicalContainer(Hierarchical container,\r
+ protected void validateHierarchicalContainer(Hierarchical container,\r
Object expectedFirstItemId, Object expectedLastItemId,\r
- Object itemIdInSet, Object itemIdNotInSet,\r
- boolean rootsHaveChildren, int expectedSize,\r
- int expectedTraversalSize, int expectedRootSize) {\r
+ Object itemIdInSet, Object itemIdNotInSet, int expectedSize,\r
+ int expectedRootSize, boolean rootsHaveChildren) {\r
\r
validateContainer(container, expectedFirstItemId, expectedLastItemId,\r
itemIdInSet, itemIdNotInSet, expectedSize);\r
// all roots must be roots\r
assertTrue(container.isRoot(rootId));\r
\r
- // all roots have children allowed in this case\r
- assertTrue(container.areChildrenAllowed(rootId));\r
-\r
- // all roots have children in this case\r
if (rootsHaveChildren) {\r
+ // all roots have children allowed in this case\r
+ assertTrue(container.areChildrenAllowed(rootId));\r
+\r
+ // all roots have children in this case\r
Collection<?> children = container.getChildren(rootId);\r
assertNotNull(rootId + " should have children", children);\r
assertTrue(rootId + " should have children",\r
(children.size() > 0));\r
-\r
// getParent\r
for (Object childId : children) {\r
assertEquals(container.getParent(childId), rootId);\r
}\r
- } else {\r
\r
}\r
}\r
// removeItem of unknown items should return false\r
assertFalse(container.removeItem(itemIdNotInSet));\r
\r
- assertEquals(expectedTraversalSize, countNodes(container));\r
+ assertEquals(expectedSize, countNodes(container));\r
\r
validateHierarchy(container);\r
}\r
int expectedSize = sampleData.length + packages;\r
validateHierarchicalContainer(container, "com",\r
"com.vaadin.util.SerializerHelper",\r
- "com.vaadin.terminal.ApplicationResource", "blah", true,\r
- expectedSize, expectedSize, 1);\r
+ "com.vaadin.terminal.ApplicationResource", "blah",\r
+ expectedSize, 1, true);\r
\r
}\r
\r
int expectedSize = sampleData.length + packages;\r
validateHierarchicalContainer(container, "com",\r
"com.vaadin.util.SerializerHelper",\r
- "com.vaadin.terminal.ApplicationResource", "blah", true,\r
- expectedSize, expectedSize, 1);\r
+ "com.vaadin.terminal.ApplicationResource", "blah",\r
+ expectedSize, 1, true);\r
\r
sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME },\r
new boolean[] { true });\r
validateHierarchicalContainer(container,\r
"com.vaadin.terminal.gwt.server.ApplicationPortlet2",\r
"com.vaadin.data.util.ObjectProperty",\r
- "com.vaadin.terminal.ApplicationResource", "blah", true,\r
- expectedSize, expectedSize, 1);\r
-\r
- }\r
-\r
- protected void testHierarchicalFiltering(Container.Hierarchical container) {\r
- Container.Filterable filterable = (Container.Filterable) container;\r
-\r
- initializeContainer(container);\r
-\r
- // Filter by "contains ab"\r
- filterable.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false);\r
-\r
- // 20 items should remain in the container but the root should be\r
- // filtered\r
- int expectedSize = 20;\r
- int expectedTraversalSize = 0;\r
- int expectedRoots = 0;\r
-\r
- validateHierarchicalContainer(container,\r
- "com.vaadin.data.BufferedValidatable",\r
- "com.vaadin.ui.TabSheet",\r
- "com.vaadin.terminal.gwt.client.Focusable", "blah", true,\r
- expectedSize, expectedTraversalSize, expectedRoots);\r
-\r
- // filter out every second item except hierarchy items\r
- filterable.removeAllContainerFilters();\r
- filterable.addContainerFilter(ID_NUMBER, "1", false, false);\r
-\r
- int packages = 21;\r
- int other = sampleData.length / 2;\r
-\r
- expectedSize = packages + other;\r
- expectedRoots = 1;\r
- expectedTraversalSize = expectedSize;\r
-\r
- validateHierarchicalContainer(container, "com", "com.vaadin.util",\r
- "com.vaadin.data.util.IndexedContainer", "blah", true,\r
- expectedSize, expectedTraversalSize, expectedRoots);\r
-\r
- // Additionally remove all without 'm' in the simple name. Hierarchy is\r
- // now one root only.\r
- filterable.addContainerFilter(SIMPLE_NAME, "m", false, false);\r
-\r
- expectedSize = 27;\r
- expectedRoots = 1;\r
- expectedTraversalSize = 1;\r
-\r
- validateHierarchicalContainer(container, "com",\r
- "com.vaadin.ui.UriFragmentUtility",\r
- "com.vaadin.terminal.gwt.client.ui.TreeImages", "blah", false,\r
- expectedSize, expectedTraversalSize, expectedRoots);\r
+ "com.vaadin.terminal.ApplicationResource", "blah",\r
+ expectedSize, 1, true);\r
\r
}\r
\r
testContainerFiltering(new HierarchicalContainer());\r
}\r
\r
- public void testHierarchicalFiltering() {\r
- testHierarchicalFiltering(new HierarchicalContainer());\r
- }\r
-\r
public void testSorting() {\r
testContainerSorting(new HierarchicalContainer());\r
}\r
testContainerSortingAndFiltering(new HierarchicalContainer());\r
}\r
\r
- // public void testHierarchicalSortingAndFiltering() {\r
- // testHierarchicalSortingAndFiltering(new HierarchicalContainer());\r
- // }\r
+ public void testHierarchicalFilteringWithParents() {\r
+ HierarchicalContainer container = new HierarchicalContainer();\r
+ initializeContainer(container);\r
+ container.setIncludeParentsWhenFiltering(true);\r
+\r
+ // Filter by "contains ab"\r
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false);\r
+\r
+ // 20 items match the filters and the have 8 parents that should also be\r
+ // included\r
+ // only one root "com" should exist\r
+ // filtered\r
+ int expectedSize = 29;\r
+ int expectedRoots = 1;\r
+\r
+ validateHierarchicalContainer(container, "com",\r
+ "com.vaadin.ui.TabSheet",\r
+ "com.vaadin.terminal.gwt.client.Focusable", "blah",\r
+ expectedSize, expectedRoots, true);\r
+\r
+ // only include .gwt.client classes\r
+ container.removeAllContainerFilters();\r
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.",\r
+ false, false);\r
+\r
+ int packages = 6;\r
+ int classes = 112;\r
+\r
+ expectedSize = packages + classes;\r
+ expectedRoots = 1;\r
+\r
+ validateHierarchicalContainer(container, "com",\r
+ "com.vaadin.terminal.gwt.client.WidgetSet",\r
+ "com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical",\r
+ "blah", expectedSize, expectedRoots, true);\r
+\r
+ // Additionally remove all without 'm' in the simple name.\r
+ container.addContainerFilter(SIMPLE_NAME, "m", false, false);\r
+\r
+ expectedSize = 7 + 18;\r
+ expectedRoots = 1;\r
+\r
+ validateHierarchicalContainer(\r
+ container,\r
+ "com",\r
+ "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility",\r
+ "com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer",\r
+ "blah", expectedSize, expectedRoots, true);\r
+\r
+ }\r
\r
+ public void testHierarchicalFilteringWithoutParents() {\r
+ HierarchicalContainer container = new HierarchicalContainer();\r
+\r
+ initializeContainer(container);\r
+ container.setIncludeParentsWhenFiltering(false);\r
+\r
+ // Filter by "contains ab"\r
+ container.addContainerFilter(SIMPLE_NAME, "ab", false, false);\r
+\r
+ // 20 items match the filter.\r
+ // com.vaadin.data.BufferedValidatable\r
+ // com.vaadin.data.Validatable\r
+ // com.vaadin.terminal.gwt.client.Focusable\r
+ // com.vaadin.terminal.gwt.client.Paintable\r
+ // com.vaadin.terminal.gwt.client.ui.Table\r
+ // com.vaadin.terminal.gwt.client.ui.VLabel\r
+ // com.vaadin.terminal.gwt.client.ui.VScrollTable\r
+ // com.vaadin.terminal.gwt.client.ui.VTablePaging\r
+ // com.vaadin.terminal.gwt.client.ui.VTabsheet\r
+ // com.vaadin.terminal.gwt.client.ui.VTabsheetBase\r
+ // com.vaadin.terminal.gwt.client.ui.VTabsheetPanel\r
+ // com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent\r
+ // com.vaadin.terminal.Paintable\r
+ // com.vaadin.terminal.Scrollable\r
+ // com.vaadin.terminal.Sizeable\r
+ // com.vaadin.terminal.VariableOwner\r
+ // com.vaadin.ui.Label\r
+ // com.vaadin.ui.Table\r
+ // com.vaadin.ui.TableFieldFactory\r
+ // com.vaadin.ui.TabSheet\r
+ // all become roots.\r
+ int expectedSize = 20;\r
+ int expectedRoots = 20;\r
+\r
+ validateHierarchicalContainer(container,\r
+ "com.vaadin.data.BufferedValidatable",\r
+ "com.vaadin.ui.TabSheet",\r
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetBase", "blah",\r
+ expectedSize, expectedRoots, false);\r
+\r
+ // only include .gwt.client classes\r
+ container.removeAllContainerFilters();\r
+ container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.",\r
+ false, false);\r
+\r
+ int packages = 3;\r
+ int classes = 110;\r
+\r
+ expectedSize = packages + classes;\r
+ expectedRoots = 35 + 1; // com.vaadin.terminal.gwt.client.ui +\r
+ // com.vaadin.terminal.gwt.client.*\r
+\r
+ // Sorting is case insensitive\r
+ validateHierarchicalContainer(container,\r
+ "com.vaadin.terminal.gwt.client.ApplicationConfiguration",\r
+ "com.vaadin.terminal.gwt.client.WidgetSet",\r
+ "com.vaadin.terminal.gwt.client.ui.VOptionGroup", "blah",\r
+ expectedSize, expectedRoots, false);\r
+\r
+ // Additionally remove all without 'P' in the simple name.\r
+ container.addContainerFilter(SIMPLE_NAME, "P", false, false);\r
+\r
+ expectedSize = 13;\r
+ expectedRoots = expectedSize;\r
+\r
+ validateHierarchicalContainer(container,\r
+ "com.vaadin.terminal.gwt.client.Paintable",\r
+ "com.vaadin.terminal.gwt.client.ui.VTabsheetPanel",\r
+ "com.vaadin.terminal.gwt.client.ui.VPopupCalendar", "blah",\r
+ expectedSize, expectedRoots, false);\r
+\r
+ }\r
}\r