private VersionAction[] ApplyVersionActionStep(IEnumerable <ItemVersion> versions, VersionAction action) { var versionActions = new List <VersionAction>(); foreach (var versioner in Versioners) { if (!action.Version.ContainsKey(versioner.VersionKey)) { continue; } // get all versions which only differ in the version key of this versioner from the version we are operating on var match = new ItemVersion(action.Version.ToDictionary(v => v.Key, v => v.Key == versioner.VersionKey ? null : v.Value)); var inSpace = versions.Where(v => v.ContainedBy(match)).Select(v => v[versioner.VersionKey]).ToArray(); var keyActions = versioner.ApplyVersionAction(inSpace, new VersionKeyAction { Op = action.Op, Value = action.Version[versioner.VersionKey] }); // promote keyActions to actions, add to versionActions var actions = keyActions.Select(ka => new VersionAction(action.Version, versioner.VersionKey, ka)); versionActions.AddRange(actions); } versionActions = versionActions.Distinct().OrderBy(va => va.ToString()).ToList(); if (versionActions.Any(va => va.Op == DataOp.Delete && versionActions.Any(va2 => va2.Op == DataOp.Create && va2.Version == va.Version))) { throw new Exception("Cannot perform version operation as it requires both adding and deleting a version"); } return(versionActions.ToArray()); }
public VersionAction[] ApplyVersionAction(IEnumerable <ItemVersion> versions, VersionAction action, int depth = 0) { if (depth > 15) { throw new Exception("ApplyVersionAction expansion too deep"); } var result = ApplyVersionActionStep(versions, action); if (result.ToString() == action.ToString()) { return(result); } return(result.SelectMany(va => ApplyVersionAction(versions, va, depth + 1)).ToArray()); }