title: How do I propagate updates to all items within a Colectica DDI item graph?
body: <p>I recently needed to update over a hundred Concept items using a script utilizing <a href="http://colectica.com" rel="nofollow">Colectica</a> SDK for <a href="http://www.ddialliance.org" rel="nofollow">DDI</a>, and I need to propagate those updates throughout all locations within a set with a known root Project item. This means that each item referencing an older version of a Concept will need to be updated to reference the new version. This will create a new version of the refrencing item which will need its updates propagated within the set similarly.</p>
  
  <p>My best attempted solution uses an implementation of <code>IVersionableVisitor</code> to update out-of-date references, marking items dirty as needed. At this point, a <code>DirtyItemGatherer</code> visitor can be used to collect and publish items. This would not work in a single pass, but the hope was that it could be run until no more items needed to be updated.</p>
  
  <pre><code>internal class ReferencedVersionUpdaterVisitor : IVersionableVisitor
  {
      public ReferencedVersionUpdaterVisitor(WcfRepositoryClient repositoryClient)
      {
          this.RepositoryClient = repositoryClient;
          this.VisitedLog = new Dictionary&lt;Tuple&lt;Guid, string&gt;,bool&gt;();
          this.Context = new List&lt;IVersionable&gt;();
      }
  
      private WcfRepositoryClient RepositoryClient { get; set; }
  
      private Dictionary&lt;Tuple&lt;Guid, string&gt;, bool&gt; VisitedLog { get; set; }
  
      public bool HaveVisited(IdentifierTriple id)
      {
          var logId = Tuple.Create(id.Identifier, id.AgencyId);
          return this.VisitedLog.ContainsKey(logId) &amp;&amp; this.VisitedLog[logId];
      }
  
      public void RegisterVisit(IdentifierTriple id)
      {
          this.VisitedLog[Tuple.Create(id.Identifier, id.AgencyId)] = true;
      }
  
      private List&lt;IVersionable&gt; Context { get; set; }
  
      public void BeginVisitItem(IVersionable item)
      {
          if (!this.HaveVisited(item.CompositeId) &amp;&amp;
              !this.Context.Any(contextItem =&gt; contextItem.CompositeId.Identifier.Equals(item.CompositeId.Identifier) &amp;&amp; contextItem.CompositeId.AgencyId.Equals(item.CompositeId.AgencyId)))
          {
              if (!item.IsPopulated)
              {
                  var previousVersion = item.Version;
                  this.RepositoryClient.PopulateItem(item, true, ChildReferenceProcessing.Instantiate);
                  if (previousVersion != item.Version)
                  {
                      item.IsDirty = true;
                  }
              }
              this.Context.Add(item);
          }
      }
  
      public void EndVisitItem(IVersionable item)
      {
          if (!this.HaveVisited(item.CompositeId))
          {
              this.Context.Remove(item);
              this.RegisterVisit(item.CompositeId);
          }
      }
  }
  </code></pre>
  
  <p>Unfortunately it does not work; every pass finds the same items because the set still contains parent items referencing the old versions of the children. I've put thought and effort into ideas for tuning this approach, such as modifying items in <code>EndVisitItem()</code> to modify on the way up, but it doesn't address the real issue.</p>
  
  <p>I think that the base issue is that the visitor needs to modify parent items as it walks the set. Since this is a graph, there is not really a parent so much as a referencing item that I happened to use to get to the current node. I attempted to record this using the <code>Context</code> property, but its contents don't seem to always match my expectation that the last item in the context list is the "parent" referencing item.</p>
  
  <p>In Colectica Designer, this problem is solved by internal use of the Navigator structure, which I unfortunately do not see available in the Colectica SDK. Also, while Colectica Designer's Navigator-based solution performs very well, the performance of this visitor is quite poor because of the multiple round-trips to the Colectica Repository from <code>BeginVisitItem()</code>. This makes me feel as though I might be going about this all wrong. <strong>Is there a better way to approach this using the tools available through Colectica SDK?</strong></p>
  
  <p>I should also note that I am aware of the ability to populate latest on all child items, but from there, the problem of locating all dirty items, bumping their versions, saving them, and propagating the updates seems to turn into the same problem that I'm already trying to solve.</p>
  
  <p>I would also like to add that a side-effect of updating everything within the rooted set to the latest versions, not just those Concepts and related items, would be perfectly fine, and, in fact, may be preferred.</p>