public IEnumerable <InstallItem> SortByDependencies(IEnumerable <InstallItem> items, IArasMetadataProvider metadata, int maxLoops = 10) { int loops = 0; var state = CycleState.ResolvedCycle; var results = items ?? Enumerable.Empty <InstallItem>(); var analyzer = new DependencyAnalyzer(metadata); while (loops < maxLoops && state == CycleState.ResolvedCycle) { if (loops > 0) { analyzer.Reset(); } foreach (var newInstallItem in items) { analyzer.AddReferenceAndDependencies(newInstallItem); } analyzer.FinishAdding(); results = GetDependencyList(analyzer, items, out state).ToList(); loops++; } results = results .Where(i => !IsDelete(i)) .Concat(results .Where(IsDelete) .OrderByDescending(DefaultInstallOrder) ).ToArray(); return(results); }
/// <summary> /// Construct a new <see cref="ExportProcessor"/> from a connection to Aras /// </summary> /// <param name="conn"></param> public ExportProcessor(IAsyncConnection conn) { _conn = conn; _metadata = ArasMetadataProvider.Cached(conn); _metadata.Reset(); _dependAnalyzer = new DependencyAnalyzer(_metadata); }
internal IEnumerable <InstallItem> GetDependencyList(DependencyAnalyzer dependAnalyzer , IEnumerable <InstallItem> values, out CycleState cycleState) { cycleState = CycleState.NoCycle; var lookup = (from i in values group i by i.Reference into refGroup select refGroup) .ToDictionary(i => i.Key, i => (IEnumerable <InstallItem>)i); IEnumerable <ItemReference> sorted = null; IList <ItemReference> cycle = new List <ItemReference>() { null }; List <XmlNode> refs; // Bias the install order initially to try and help the dependency sort properly handle anything // where explicit dependencies don't exist. Then, perform the dependency sort. var initialSort = lookup.Keys .OrderBy(DefaultInstallOrder) .ThenBy(i => i.Type.ToLowerInvariant()) .ThenBy(i => i.Unique) .ToList(); sorted = initialSort.DependencySort <ItemReference>(d => { IEnumerable <InstallItem> res = null; if (lookup.TryGetValue(d, out res)) { return(res.SelectMany(r => { var ii = r as InstallItem; if (ii == null) { return Enumerable.Empty <ItemReference>(); } return dependAnalyzer.GetDependencies(ii.Reference); })); } return(Enumerable.Empty <ItemReference>()); }, ref cycle, false); // Attempt to remove cycles by identifying a Relationships tag in one of the cycles // and moving the Relationships to the top level if (cycle.Count > 0 && (cycle[0] != null || cycle.Count > 1)) { cycleState = CycleState.UnresolvedCycle; for (int i = (cycle[0] == null ? 2 : 1); i < cycle.Count; i++) { refs = dependAnalyzer.GetReferences(cycle[i - 1], cycle[i]).ToList(); if (refs.Count == 1) { var relTag = refs[0].Parents().FirstOrDefault(e => e.LocalName == "Relationships"); if (relTag != null) { var parentTag = refs[0].Parents().Last(e => e.LocalName == "Item").Parent(); foreach (var child in relTag.Elements().ToList()) { child.Detach(); parentTag.AppendChild(child); var sourceId = (XmlElement)child.AppendChild(child.OwnerDocument.CreateElement("source_id")); sourceId.SetAttribute("type", relTag.Parent().Attribute("type")); sourceId.SetAttribute("keyed_name", relTag.Parent().Attribute("_keyed_name")); sourceId.InnerText = relTag.Parent().Attribute("id"); } relTag.Detach(); cycleState = CycleState.ResolvedCycle; //return Enumerable.Empty<InstallItem>(); } } } } var result = new List <InstallItem>(); IEnumerable <InstallItem> items = null; foreach (var sort in sorted) { if (lookup.TryGetValue(sort, out items)) { foreach (var item in items) { result.Add(item); } } else { result.Add(InstallItem.FromDependency(sort)); } } return(result); }
public static IEnumerable<InstallItem> SortByDependencies(IEnumerable<InstallItem> items, IAsyncConnection conn) { int loops = 0; var state = CycleState.ResolvedCycle; var results = items; var metadata = ArasMetadataProvider.Cached(conn); metadata.Wait(); var analyzer = new DependencyAnalyzer(metadata); while (loops < 10 && state == CycleState.ResolvedCycle) { foreach (var newInstallItem in items) { analyzer.GatherDependencies(newInstallItem.Script, newInstallItem.Reference, newInstallItem.CoreDependencies); } analyzer.CleanDependencies(); results = GetDependencyList(analyzer, items, out state).ToList(); loops++; } return results; }
private static IEnumerable<InstallItem> GetDependencyList(DependencyAnalyzer dependAnalyzer , IEnumerable<InstallItem> values, out CycleState cycleState) { cycleState = CycleState.NoCycle; var lookup = (from i in values group i by i.Reference into refGroup select refGroup) .ToDictionary(i => i.Key, i => (IEnumerable<InstallItem>)i); IEnumerable<ItemReference> sorted = null; IList<ItemReference> cycle = new List<ItemReference>() { null }; List<XmlNode> refs; sorted = lookup.Keys.DependencySort<ItemReference>(d => { IEnumerable<InstallItem> res = null; if (lookup.TryGetValue(d, out res)) return res.SelectMany(r => { var ii = r as InstallItem; if (ii == null) return Enumerable.Empty<ItemReference>(); return dependAnalyzer.GetDependencies(ii.Reference); }); return Enumerable.Empty<ItemReference>(); }, ref cycle, false); // Attempt to remove cycles by identifying a Relationships tag in one of the cycles // and moving the Relationships to the top level if (cycle.Count > 0 && (cycle[0] != null || cycle.Count > 1)) { cycleState = CycleState.UnresolvedCycle; for (int i = (cycle[0] == null ? 2 : 1); i < cycle.Count; i++) { refs = dependAnalyzer.GetReferences(cycle[i - 1], cycle[i]).ToList(); if (refs.Count == 1) { var relTag = refs[0].Parents().FirstOrDefault(e => e.LocalName == "Relationships"); if (relTag != null) { var parentTag = refs[0].Parents().Last(e => e.LocalName == "Item").Parent(); foreach (var child in relTag.Elements().ToList()) { child.Detatch(); parentTag.AppendChild(child); var sourceId = (XmlElement)child.AppendChild(child.OwnerDocument.CreateElement("source_id")); sourceId.SetAttribute("type", relTag.Parent().Attribute("type")); sourceId.SetAttribute("keyed_name", relTag.Parent().Attribute("_keyed_name")); sourceId.InnerText = relTag.Parent().Attribute("id"); } relTag.Detatch(); cycleState = CycleState.ResolvedCycle; return Enumerable.Empty<InstallItem>(); } } } } var result = new List<InstallItem>(); IEnumerable<InstallItem> items = null; foreach (var sort in sorted) { if (lookup.TryGetValue(sort, out items)) { foreach (var item in items) result.Add(item); } else { result.Add(InstallItem.FromDependency(sort)); } } return result; }