Exemplo n.º 1
0
        private IChangeSet <T> Process(IChangeSet <T> changes)
        {
            //if all removes and not Clear, then more efficient to try clear range
            if (changes.TotalChanges == changes.Removes && changes.All(c => c.Reason != ListChangeReason.Clear) && changes.Removes > 1)
            {
                var removed = changes.Unified().Select(u => u.Current);
                _innerList.RemoveMany(removed);
                return(_innerList.CaptureChanges());
            }

            return(ProcessImpl(changes));
        }
Exemplo n.º 2
0
        private IChangeSet <TDestination> Process(ChangeAwareList <TDestination> transformed, IChangeSet <TSource> source)
        {
            //TODO: This is very inefficient as it flattens range operation
            //need to find a means of re-forming ranges
            var children = source.Unified().SelectMany(change =>
            {
                var many = _manyselector(change.Current);
                return(many.Select(m => new TransformedItem <TDestination>(change.Reason, m)));
            });

            foreach (var child in children)
            {
                switch (child.Reason)
                {
                case ListChangeReason.Add:
                    transformed.Add(child.Current);
                    break;

                case ListChangeReason.Replace:
                    transformed.Remove(child.Previous.Value);
                    transformed.Add(child.Current);
                    break;

                case ListChangeReason.Remove:
                    transformed.Remove(child.Current);
                    break;

                case ListChangeReason.Clear:
                    transformed.Clear();
                    break;
                }
            }
            return(transformed.CaptureChanges());
        }
Exemplo n.º 3
0
        private IChangeSet <TDestination> Process(IChangeSet <TSource> changes)
        {
            Transform(changes);
            var changed = _transformed.CaptureChanges();

            return(changed.Transform(container => container.Destination));
        }
Exemplo n.º 4
0
        private IChangeSet <T> ProcessImpl(ChangeAwareList <T> target, IChangeSet <T> changes)
        {
            foreach (var change in changes)
            {
                switch (change.Reason)
                {
                case ListChangeReason.Add:
                {
                    var current = change.Item.Current;
                    Insert(target, current);
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    var ordered = change.Range.OrderBy(t => t, _comparer).ToList();
                    if (target.Count == 0)
                    {
                        target.AddRange(ordered);
                    }
                    else
                    {
                        ordered.ForEach(item => Insert(target, item));
                    }
                    break;
                }

                case ListChangeReason.Replace:
                {
                    var current = change.Item.Current;
                    //TODO: check whether an item should stay in the same position
                    //i.e. update and move
                    Remove(target, change.Item.Previous.Value);
                    Insert(target, current);
                    break;
                }

                case ListChangeReason.Remove:
                {
                    var current = change.Item.Current;
                    Remove(target, current);
                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    target.RemoveMany(change.Range);
                    break;
                }

                case ListChangeReason.Clear:
                {
                    target.Clear();
                    break;
                }
                }
            }
            return(target.CaptureChanges());
        }
Exemplo n.º 5
0
        private IChangeSet <T> Reset(ChangeAwareList <T> original, ChangeAwareList <T> target)
        {
            var sorted = original.OrderBy(t => t, _comparer).ToList();

            target.Clear();
            target.AddRange(sorted);
            return(target.CaptureChanges());
        }
Exemplo n.º 6
0
        private IChangeSet <T> Page(IChangeSet <T> changeset = null)
        {
            if (changeset != null)
            {
                _all.Clone(changeset);
            }

            var previous = _paged;

            int pages = CalculatePages();
            int page  = _parameters.Page > pages ? pages : _parameters.Page;
            int skip  = _parameters.Size * (page - 1);

            var current = _all.Skip(skip)
                          .Take(_parameters.Size)
                          .ToList();

            var adds    = current.Except(previous);
            var removes = previous.Except(current);

            _paged.RemoveMany(removes);

            adds.ForEach(t =>
            {
                var index = current.IndexOf(t);
                _paged.Insert(index, t);
            });

            var startIndex = skip;

            var moves = changeset.EmptyIfNull()
                        .Where(change => change.Reason == ListChangeReason.Moved &&
                               change.MovedWithinRange(startIndex, startIndex + _parameters.Size));

            foreach (var change in moves)
            {
                //check whether an item has moved within the same page
                var currentIndex  = change.Item.CurrentIndex - startIndex;
                var previousIndex = change.Item.PreviousIndex - startIndex;
                _paged.Move(previousIndex, currentIndex);
            }

            //find replaces [Is this ever the case that it can be reached]
            for (int i = 0; i < current.Count; i++)
            {
                var currentItem  = current[i];
                var previousItem = previous[i];

                if (ReferenceEquals(currentItem, previousItem))
                {
                    continue;
                }

                var index = _paged.IndexOf(currentItem);
                _paged.Move(i, index);
            }
            return(_paged.CaptureChanges());
        }
Exemplo n.º 7
0
 public IObservable <IChangeSet <T> > Run()
 {
     return(_source.Select(changes =>
     {
         _filtered.Filter(changes, _predicate);
         return _filtered.CaptureChanges();
     })
            .NotEmpty());
 }
Exemplo n.º 8
0
        private IChangeSet <T> ChangeComparer(ChangeAwareList <T> target, IComparer <T> comparer)
        {
            _comparer = comparer;
            var sorted = target.OrderBy(t => t, _comparer).ToList();

            target.Clear();
            target.AddRange(sorted);
            return(target.CaptureChanges());
        }
Exemplo n.º 9
0
 public IObservable <IChangeSet <T> > Run()
 {
     return(Observable.Create <IChangeSet <T> >(observer =>
     {
         var filtered = new ChangeAwareList <T>();
         return _source.Select(changes =>
         {
             filtered.Filter(changes, _predicate);
             return filtered.CaptureChanges();
         }).NotEmpty().SubscribeSafe(observer);
     }));
 }
Exemplo n.º 10
0
        private IChangeSet <T> Virtualise(List <T> all, ChangeAwareList <T> virtualised, IChangeSet <T> changeset = null)
        {
            if (changeset != null)
            {
                all.Clone(changeset);
            }

            var previous = virtualised;

            var current = all.Skip(_parameters.StartIndex)
                          .Take(_parameters.Size)
                          .ToList();

            var adds    = current.Except(previous);
            var removes = previous.Except(current);

            virtualised.RemoveMany(removes);

            adds.ForEach(t =>
            {
                var index = current.IndexOf(t);
                virtualised.Insert(index, t);
            });

            var moves = changeset.EmptyIfNull()
                        .Where(change => change.Reason == ListChangeReason.Moved &&
                               change.MovedWithinRange(_parameters.StartIndex, _parameters.StartIndex + _parameters.Size));

            foreach (var change in moves)
            {
                //check whether an item has moved within the same page
                var currentIndex  = change.Item.CurrentIndex - _parameters.StartIndex;
                var previousIndex = change.Item.PreviousIndex - _parameters.StartIndex;
                virtualised.Move(previousIndex, currentIndex);
            }

            //find replaces [Is this ever the case that it can be reached]
            for (var i = 0; i < current.Count; i++)
            {
                var currentItem  = current[i];
                var previousItem = previous[i];

                if (ReferenceEquals(currentItem, previousItem))
                {
                    continue;
                }

                var index = virtualised.IndexOf(currentItem);
                virtualised.Move(i, index);
            }
            return(virtualised.CaptureChanges());
        }
Exemplo n.º 11
0
        public IObservable <IChangeSet <T> > Run()
        {
            return(Observable.Create <IChangeSet <T> >(observer =>
            {
                var allWithMatch = new List <ItemWithMatch>();
                var all = new List <T>();
                var filtered = new ChangeAwareList <T>();
                var locker = new object();

                //requery wehn controller either fires changed or requery event
                var refresher = _predicates.Synchronize(locker)
                                .Select(predicate =>
                {
                    Requery(predicate, allWithMatch, all, filtered);
                    var changed = filtered.CaptureChanges();
                    return changed;
                });

                var shared = _source.Synchronize(locker).Publish();

                //take current filter state of all items
                var updateall = shared.Synchronize(locker)
                                .Transform(t => new ItemWithMatch(t, _predicate(t)))
                                .Subscribe(allWithMatch.Clone);

                //filter result list
                var filter = shared.Synchronize(locker)
                             .Select(changes =>
                {
                    filtered.Filter(changes, _predicate);
                    var changed = filtered.CaptureChanges();
                    return changed;
                });

                var subscriber = refresher.Merge(filter).NotEmpty().SubscribeSafe(observer);

                return new CompositeDisposable(updateall, subscriber, shared.Connect());
            }));
        }
Exemplo n.º 12
0
        public Continuation <IChangeSet <T> > Write(IChangeSet <T> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }
            IChangeSet <T> result;

            lock (_locker)
            {
                try
                {
                    _data.Clone(changes);
                    result = _data.CaptureChanges();
                }
                catch (Exception ex)
                {
                    return(new Continuation <IChangeSet <T> >(ex));
                }
            }
            return(new Continuation <IChangeSet <T> >(result));
        }
Exemplo n.º 13
0
        private IChangeSet <IGroup <TObject, TGroupKey> > Regroup(ChangeAwareList <IGroup <TObject, TGroupKey> > result,
                                                                  IDictionary <TGroupKey, Group <TObject, TGroupKey> > groupCollection,
                                                                  IReadOnlyCollection <ItemWithValue <TObject, TGroupKey> > currentItems)
        {
            //TODO: We need to update ItemWithValue>

            foreach (var itemWithValue in currentItems)
            {
                var currentGroupKey = itemWithValue.Value;
                var newGroupKey     = _groupSelector(itemWithValue.Item);
                if (newGroupKey.Equals(currentGroupKey))
                {
                    continue;
                }


                //remove from the old group
                var currentGroupLookup = GetCache(groupCollection, currentGroupKey);
                var currentGroupCache  = currentGroupLookup.Group;
                currentGroupCache.Edit(innerList => innerList.Remove(itemWithValue.Item));

                if (currentGroupCache.List.Count == 0)
                {
                    groupCollection.Remove(currentGroupKey);
                    result.Remove(currentGroupCache);
                }

                //Mark the old item with the new cache group
                itemWithValue.Value = newGroupKey;

                //add to the new group
                var newGroupLookup = GetCache(groupCollection, newGroupKey);
                var newGroupCache  = newGroupLookup.Group;
                newGroupCache.Edit(innerList => innerList.Add(itemWithValue.Item));

                if (newGroupLookup.WasCreated)
                {
                    result.Add(newGroupCache);
                }
            }

            return(result.CaptureChanges());
        }
Exemplo n.º 14
0
        private IChangeSet <T> Reorder(ChangeAwareList <T> target)
        {
            int index  = -1;
            var sorted = target.OrderBy(t => t, _comparer).ToList();

            foreach (var item in sorted)
            {
                index++;

                var existing = target[index];
                //if item is in the same place,
                if (ReferenceEquals(item, existing))
                {
                    continue;
                }

                //Cannot use binary search as Resort is implicit of a mutable change
                var old = target.IndexOf(item);
                target.Move(old, index);
            }

            return(target.CaptureChanges());
        }
Exemplo n.º 15
0
        private IChangeSet <IGroup <TObject, TGroupKey> > Process(ChangeAwareList <IGroup <TObject, TGroupKey> > result, IDictionary <TGroupKey, Group <TObject, TGroupKey> > groupCollection, IChangeSet <ItemWithValue <TObject, TGroupKey> > changes)
        {
            //TODO.This flattened enumerator is inefficient as range operations are lost.
            //maybe can infer within each grouping whether we can regroup i.e. Another enumerator!!!

            foreach (var grouping in changes.Unified().GroupBy(change => change.Current.Value))
            {
                //lookup group and if created, add to result set
                var currentGroup = grouping.Key;
                var lookup       = GetCache(groupCollection, currentGroup);
                var groupCache   = lookup.Group;

                if (lookup.WasCreated)
                {
                    result.Add(groupCache);
                }

                //start a group edit session, so all changes are batched
                groupCache.Edit(
                    list =>
                {
                    //iterate through the group's items and process
                    foreach (var change in grouping)
                    {
                        switch (change.Reason)
                        {
                        case ListChangeReason.Add:
                            {
                                list.Add(change.Current.Item);
                                break;
                            }

                        case ListChangeReason.Replace:
                            {
                                var previousItem  = change.Previous.Value.Item;
                                var previousGroup = change.Previous.Value.Value;

                                //check whether an item changing has resulted in a different group
                                if (previousGroup.Equals(currentGroup))
                                {
                                    //find and replace
                                    var index   = list.IndexOf(previousItem);
                                    list[index] = change.Current.Item;
                                }
                                else
                                {
                                    //add to new group
                                    list.Add(change.Current.Item);

                                    //remove from old group
                                    groupCollection.Lookup(previousGroup)
                                    .IfHasValue(g =>
                                    {
                                        g.Edit(oldList => oldList.Remove(previousItem));
                                        if (g.List.Count != 0)
                                        {
                                            return;
                                        }
                                        groupCollection.Remove(g.GroupKey);
                                        result.Remove(g);
                                    });
                                }

                                break;
                            }

                        case ListChangeReason.Remove:
                            {
                                list.Remove(change.Current.Item);
                                break;
                            }

                        case ListChangeReason.Clear:
                            {
                                list.Clear();
                                break;
                            }
                        }
                    }
                });

                if (groupCache.List.Count == 0)
                {
                    groupCollection.Remove(groupCache.GroupKey);
                    result.Remove(groupCache);
                }
            }
            return(result.CaptureChanges());
        }
Exemplo n.º 16
0
        private IChangeSet <TValue> Process(IChangeSet <ItemWithValue <T, TValue> > updates)
        {
            Action <TValue> addAction = value => _valueCounters.Lookup(value)
                                        .IfHasValue(count => _valueCounters[value] = count + 1)
                                        .Else(() =>
            {
                _valueCounters[value] = 1;
                _result.Add(value);
            });

            Action <TValue> removeAction = value =>
            {
                var counter = _valueCounters.Lookup(value);
                if (!counter.HasValue)
                {
                    return;
                }

                //decrement counter
                var newCount = counter.Value - 1;
                _valueCounters[value] = newCount;
                if (newCount != 0)
                {
                    return;
                }

                //if there are none, then remove and notify
                _result.Remove(value);
            };

            foreach (var change in updates)
            {
                switch (change.Reason)
                {
                case ListChangeReason.Add:
                {
                    var value = change.Item.Current.Value;
                    addAction(value);
                    break;
                }

                case ListChangeReason.AddRange:
                {
                    change.Range.Select(item => item.Value).ForEach(addAction);
                    break;
                }

                //	case ListChangeReason.Evaluate:
                case ListChangeReason.Replace:
                {
                    var value    = change.Item.Current.Value;
                    var previous = change.Item.Previous.Value.Value;
                    if (value.Equals(previous))
                    {
                        return(_result.CaptureChanges());
                    }

                    removeAction(previous);
                    addAction(value);
                    break;
                }

                case ListChangeReason.Remove:
                {
                    var previous = change.Item.Current.Value;
                    removeAction(previous);
                    break;
                }

                case ListChangeReason.RemoveRange:
                {
                    change.Range.Select(item => item.Value).ForEach(removeAction);
                    break;
                }

                case ListChangeReason.Clear:
                {
                    _result.Clear();
                    _valueCounters.Clear();
                    break;
                }
                }
            }
            return(_result.CaptureChanges());
        }
Exemplo n.º 17
0
 private IChangeSet <TDestination> Process(IChangeSet <TSource> changes)
 {
     _transformed.Transform(changes, _factory);
     return(_transformed.CaptureChanges());
 }