/* Copyright (c) Cloud Software Group, Inc. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; namespace XenAdmin.Controls { partial class VirtualTreeNode { [DebuggerDisplay("{Tag}")] public class PersistenceInfo : IEquatable { public ReadOnlyCollection Path { get; private set; } public ReadOnlyCollection PathToMaximalSubTree { get; private set; } public VirtualTreeNode Node { get; private set; } public object Tag { get; private set; } public PersistenceInfo(VirtualTreeNode node) { Util.ThrowIfParameterNull(node, "node"); Node = node; Path = new ReadOnlyCollection(GetPath(node)); var maxSubTree = MaximalSubTree(node, node.Tag); PathToMaximalSubTree = new ReadOnlyCollection(maxSubTree == null ? new List() : GetPath(maxSubTree)); Tag = node.Tag; } private static List GetPath(VirtualTreeNode node) { var path = new List(); if (node.Tag != null && node.Parent != null) path.Add(node.Tag); path.AddRange(new List(node.Ancestors).FindAll(o => o.Parent != null).ConvertAll(n => n.Tag).FindAll(o => o != null)); path.Reverse(); return path; } /// /// Find the maximal sub-tree under which the object appears only once /// /// /// /// private VirtualTreeNode MaximalSubTree(VirtualTreeNode me, Object o) { if (me.Parent == null) return me; foreach (VirtualTreeNode sibling in me.Parent.Nodes) { if (sibling == me) continue; if (ObjectExistsUnder(o, sibling)) return me; } return MaximalSubTree(me.Parent, o); } private bool ObjectExistsUnder(Object o, VirtualTreeNode parent) { foreach (VirtualTreeNode child in parent.Nodes) { if (child.Tag == o) return true; if (ObjectExistsUnder(o, child)) return true; } return false; } public override bool Equals(object obj) { return Equals(obj as PersistenceInfo); } public override int GetHashCode() { if (Tag == null) { return string.Empty.GetHashCode(); } return Tag.GetHashCode(); } #region IEquatable Members public bool Equals(PersistenceInfo other) { if (other != null) { if (Tag == null && other.Tag == null) { return true; } else if (Tag != null && other.Tag != null && Tag.Equals(other.Tag)) { return true; } } return false; } #endregion } } }