Example #1
0
        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);
 }
Example #3
0
        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;
    }