/// <summary>
        /// Tests the item for membership in all child groups and adds it if appropriate.
        /// </summary>
        /// <returns>True if the item was added to at least one child group.</returns>
        protected virtual bool AddItemToChildren(T item)
        {
            if (!_specification.Test(item).Success)
            {
                return(false);
            }

            bool addedToChild = false;

            foreach (FilteredGroup <T> childGroup in _childGroups)
            {
                if (childGroup.AddItem(item))
                {
                    addedToChild = true;
                }
            }

            if (!addedToChild)
            {
                FilteredGroup <T> newGroup = CreateNewGroup(item);
                if (newGroup != null)
                {
                    ChildGroups.Add(newGroup);
                    addedToChild = AddItemToChild(item, newGroup);
                    Platform.CheckTrue(addedToChild, "Item should be guaranteed to have been inserted.");
                }
            }

            return(addedToChild);
        }
        private void OnChildGroupEmpty(FilteredGroup <T> childGroup)
        {
            bool remove;

            OnChildGroupEmpty(childGroup, out remove);
            if (remove)
            {
                ChildGroups.Remove(childGroup);
            }
        }
        /// <summary>
        /// Tests the item for membership in <paramref name="child"/> and adds it if appropriate.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <param name="child">The child group.</param>
        /// <returns>True if the item was added, otherwise false.</returns>
        protected virtual bool AddItemToChild(T item, FilteredGroup <T> child)
        {
            Platform.CheckTrue(ChildGroups.Contains(child), "Group is not a child of this group.");

            if (!_specification.Test(item).Success)
            {
                return(false);
            }

            return(child.AddItem(item));
        }
 /// <summary>
 /// Called when a child group becomes empty.
 /// </summary>
 /// <param name="childGroup">The child group that has just become empty.</param>
 /// <param name="remove">Out parameter indicates whether or not the child group should be removed.  By default,
 /// this value depends on whether there is an <see cref="IFilteredGroupFactory{T}"/> in this node that is capable
 /// of automatically recreating an appropriate child group; if there is such a factory, then the value is true,
 /// otherwise it is false.</param>
 protected virtual void OnChildGroupEmpty(FilteredGroup <T> childGroup, out bool remove)
 {
     //TODO (CR May09): make it so if there is a factory, you can't add your own groups.
     //NOTE: in the interest of time, deferring actually doing this since it involves no API changes.
     remove = _childGroupFactory != null;
 }