/// <summary>
        /// Throws an exception if the media object should not be added
        /// as a child.
        /// </summary>
        /// <param name="media"></param>
        /// <returns></returns>
        /// <exception cref="InvalidCastException">
        /// Thrown if the "media" argument is not an <see cref="IDvItem"/> or an <see cref="IDvContainer"/> object.
        /// Also thrown if the underlying referenced item of "media" is not an <see cref="IDvItem"/>.
        /// </exception>
        /// <exception cref="Error_PendingDeleteException">
        /// Thrown if the underlying referenced item of "media" is slated for deletion.
        /// </exception>
        private void ThrowExceptionIfBad(IDvMedia media)
        {
            if (media.IsItem)
            {
                // perform an explicit cast - throws InvalidCastException if error
                IDvItem dvItem = (IDvItem)media;

                if (media.IsReference)
                {
                    IDvItem underlying = dvItem.RefItem as IDvItem;
                    if (underlying == null)
                    {
                        throw new InvalidCastException("Cannot convert media.RefItem to IDvItem");
                    }
                    else if (underlying.IsDeletePending)
                    {
                        throw new Error_PendingDeleteException(underlying);
                    }
                }
            }
            else
            {
                // perform an explicit cast - throws InvalidCastException if error
                IDvContainer dvContainer = (IDvContainer)media;
            }
        }
        /// <summary>
        /// Adds a new child item that points to another item in the content hierarchy.
        ///
        /// <para>
        /// WARNING: This method does not check to see if the referred item is actually
        /// in the content hierarchy because of performance reasons of traversing
        /// up the ancestor's of the referred item. Programmers are warned
        /// to take caution.
        /// </para>
        ///
        /// <para>
        /// The proper way to enforce consistency is to ensure that referred item
        /// and the container share a common ancestor.
        /// </para>
        /// </summary>
        /// <param name="underlyingItem">An item that shares a common ancestor as this container, or is a direct child of this parent.</param>
        /// <returns>A new media item (referring to "underlyingItem") that is a child of this container.</returns>
        public IDvItem AddReference(IDvItem underlyingItem)
        {
            underlyingItem.LockReferenceList();

            IDvItem newItem = underlyingItem.CreateReference();

            this.AddObject(newItem, false);

            underlyingItem.UnlockReferenceList();
            return(newItem);
        }
        /// <summary>
        /// This removes a container or item object from
        /// the child list. It is used by other
        /// RemoveXXX methods defined in this class
        /// and implements the portion that allows
        /// proper media server eventing.
        /// <para>
        /// Method properly tells items to notify all other
        /// items that reference it that it will be deleted.
        /// </para>
        /// <para>
        /// Method properly tells containers to recursively
        /// remove their child objects, so that descendent
        /// reference items are properly removed.
        /// </para>
        /// </summary>
        /// <param name="removeThis"></param>
        public override void RemoveObject(IUPnPMedia removeThis)
        {
            IDvMedia     dv        = removeThis as IDvMedia;
            IDvItem      item      = removeThis as IDvItem;
            IDvContainer container = removeThis as IDvContainer;

            // Before we go about doing any removal operations,
            // we fire the event to indicate this object is
            // about to be removed.
            ArrayList removeThese = new ArrayList(1);

            removeThese.Add(removeThis);
            if (this.OnChildrenToRemove != null)
            {
                this.OnChildrenToRemove(this, removeThese);
            }

            if (item != null)
            {
                // Notify any and all referring items that
                // this object is about to be removed
                // from its parent.
                item.NotifyPendingDelete();
            }
            else if (container != null)
            {
                // Instruct all child containers to
                // remove their own children.
                IList children = container.CompleteList;
                foreach (IDvMedia child in children)
                {
                    container.RemoveObject(child);
                }
            }

            // go ahead and remove this object
            base.RemoveObject(removeThis);

            // Notify that the child has formerly been
            // removed.
            if (this.OnChildrenRemoved != null)
            {
                this.OnChildrenRemoved(this, removeThese);
            }

            this.NotifyRootOfChange();
        }
 /// <summary>
 /// Implements the core logic for removing a single item from this container.
 /// The method will notify all items that refer to the removed item to
 /// remove themselves from their respective parent containers.
 /// Local binaries associated as resources are not deleted.
 /// Control points must call DeleteResource first.
 /// </summary>
 /// <param name="removeThis">the single item to remove</param>
 private void RemoveItem(IDvItem removeThis)
 {
     this.RemoveObject(removeThis);
 }
 /// <summary>
 /// Adds a new item as a child of this container.
 /// </summary>
 /// <param name="addThis"><see cref="IDvItem"/> that should be added.
 /// <see cref="IDvItem"/> instances are often instantiated using the
 /// <see cref="OpenSource.UPnP.AV.CdsMetadata.DvMediaBuilder.CreateItem"/> method,
 /// or the <see cref="IDvItem.CreateReference"/>()
 /// method can be used also.
 /// </param>
 /// <exception cref="Error_PendingDeleteException">
 /// Thrown if the item being added is a reference to another item
 /// that is pending a delete.
 /// </exception>
 private void AddItem(IDvItem addThis)
 {
     this.AddObject(addThis, false);
 }
 /// <summary>
 /// Implements the core logic for removing a single item from this container.
 /// The method will notify all items that refer to the removed item to
 /// remove themselves from their respective parent containers.
 /// Local binaries associated as resources are not deleted.
 /// Control points must call DeleteResource first.
 /// </summary>
 /// <param name="removeThis">the single item to remove</param>
 private void RemoveItem(IDvItem removeThis)
 {
     this.RemoveObject(removeThis);
 }
 /// <summary>
 /// Adds a new item as a child of this container.
 /// </summary>
 /// <param name="addThis"><see cref="IDvItem"/> that should be added.
 /// <see cref="IDvItem"/> instances are often instantiated using the 
 /// <see cref="OpenSource.UPnP.AV.CdsMetadata.DvMediaBuilder.CreateItem"/> method,
 /// or the <see cref="IDvItem.CreateReference"/>()
 /// method can be used also.
 /// </param>
 /// <exception cref="Error_PendingDeleteException">
 /// Thrown if the item being added is a reference to another item
 /// that is pending a delete.
 /// </exception>
 private void AddItem(IDvItem addThis)
 {
     this.AddObject(addThis, false);
 }
        /// <summary>
        /// Adds a new child item that points to another item in the content hierarchy.
        /// 
        /// <para>
        /// WARNING: This method does not check to see if the referred item is actually
        /// in the content hierarchy because of performance reasons of traversing
        /// up the ancestor's of the referred item. Programmers are warned
        /// to take caution.
        /// </para>
        /// 
        /// <para>
        /// The proper way to enforce consistency is to ensure that referred item
        /// and the container share a common ancestor.
        /// </para>
        /// </summary>
        /// <param name="underlyingItem">An item that shares a common ancestor as this container, or is a direct child of this parent.</param>
        /// <returns>A new media item (referring to "underlyingItem") that is a child of this container.</returns>
        public IDvItem AddReference(IDvItem underlyingItem)
        {
            underlyingItem.LockReferenceList();

            IDvItem newItem = underlyingItem.CreateReference();
            this.AddObject(newItem, false);

            underlyingItem.UnlockReferenceList();
            return newItem;
        }