using System.Collections.Generic; using PlasticGui.Gluon.WorkspaceWindow.Views.IncomingChanges; namespace Unity.PlasticSCM.Editor.Views.IncomingChanges.Gluon { internal class UnityIncomingChangesTree { internal static UnityIncomingChangesTree BuildIncomingChangeCategories( IncomingChangesTree tree) { return new UnityIncomingChangesTree(tree); } UnityIncomingChangesTree(IncomingChangesTree tree) { mInnerTree = tree; mMetaCache.Build(mInnerTree.GetNodes()); } internal List GetNodes() { return mInnerTree.GetNodes(); } internal bool HasMeta(IncomingChangeInfo changeInfo) { return mMetaCache.ContainsMeta(changeInfo); } internal IncomingChangeInfo GetMetaChange(IncomingChangeInfo change) { return mMetaCache.GetExistingMeta(change); } internal void FillWithMeta(List changes) { changes.AddRange( mMetaCache.GetExistingMeta(changes)); } internal void Sort(string key, bool isAscending) { mInnerTree.Sort(key, isAscending); } MetaCache mMetaCache = new MetaCache(); IncomingChangesTree mInnerTree; class MetaCache { internal bool ContainsMeta(IncomingChangeInfo changeInfo) { string key = BuildKey.ForMetaChange(changeInfo); return mCache.ContainsKey(key); } internal IncomingChangeInfo GetExistingMeta(IncomingChangeInfo change) { IncomingChangeInfo result; if (!mCache.TryGetValue(BuildKey.ForMetaChange(change), out result)) return null; return result; } internal List GetExistingMeta( List changes) { List result = new List(); foreach (IncomingChangeInfo change in changes) { string key = BuildKey.ForMetaChange(change); IncomingChangeInfo metaChange; if (!mCache.TryGetValue(key, out metaChange)) continue; result.Add(metaChange); } return result; } internal void Build(List incomingChangesCategories) { mCache.Clear(); foreach (IncomingChangeCategory category in incomingChangesCategories) { ExtractMetaToCache(category, mCache); } } static void ExtractMetaToCache( IncomingChangeCategory category, Dictionary cache) { List changes = category.GetChanges(); HashSet indexedKeys = BuildIndexedKeys( changes); for (int i = changes.Count - 1; i >= 0; i--) { IncomingChangeInfo currentChange = changes[i]; string path = currentChange.GetPath(); if (!MetaPath.IsMetaPath(path)) continue; string realPath = MetaPath.GetPathFromMetaPath(path); if (!indexedKeys.Contains(BuildKey.BuildCacheKey( currentChange.CategoryType, realPath))) continue; // found foo.c and foo.c.meta - move .meta to cache cache.Add(BuildKey.ForChange(currentChange), currentChange); changes.RemoveAt(i); } } static HashSet BuildIndexedKeys( List changes) { HashSet result = new HashSet(); foreach (IncomingChangeInfo change in changes) { if (MetaPath.IsMetaPath(change.GetPath())) continue; result.Add(BuildKey.ForChange(change)); } return result; } Dictionary mCache = new Dictionary(); static class BuildKey { internal static string ForChange( IncomingChangeInfo change) { return BuildCacheKey( change.CategoryType, change.GetPath()); } internal static string ForMetaChange( IncomingChangeInfo change) { return BuildCacheKey( change.CategoryType, MetaPath.GetMetaPath(change.GetPath())); } internal static string BuildCacheKey( IncomingChangeCategory.Type type, string path) { return string.Concat(type, ":", path); } } } } }