Beispiel #1
0
        public static IChangeSet <TObject, TKey> RefreshFilteredFrom <TObject, TKey>(
            this ChangeAwareCache <TObject, TKey> filtered,
            InternalCache <TObject, TKey> allData,
            Func <TObject, bool> predicate)
        {
            if (allData.Count == 0)
            {
                return(ChangeSet <TObject, TKey> .Empty);
            }

            foreach (var kvp in allData.KeyValues)
            {
                var exisiting = filtered.Lookup(kvp.Key);
                var matches   = predicate(kvp.Value);

                if (matches)
                {
                    if (!exisiting.HasValue)
                    {
                        filtered.Add(kvp.Value, kvp.Key);
                    }
                }
                else
                {
                    if (exisiting.HasValue)
                    {
                        filtered.Remove(kvp.Key);
                    }
                }
            }

            return(filtered.CaptureChanges());
        }
Beispiel #2
0
        public IObservable <IChangeSet <TDestination, TKey> > Run()
        {
            return(Observable.Create <IChangeSet <TDestination, TKey> >(observer =>
            {
                var locker = new object();
                var shared = _source.Synchronize(locker).Publish();

                //capture all items so we can apply a forced transform
                var cache = new InternalCache <TSource, TKey>();
                var cacheLoader = shared.Subscribe(changes => cache.Clone(changes));

                //create change set of items where force refresh is applied
                var refresher = _forceTransform.Synchronize(locker)
                                .Select(selector => CaptureChanges(cache, selector))
                                .Select(changes => new ChangeSet <TSource, TKey>(changes))
                                .NotEmpty();

                var sourceAndRefreshes = shared.Merge(refresher);

                //do raw transform
                var transform = new Transform <TDestination, TSource, TKey>(sourceAndRefreshes, _transformFactory, _exceptionCallback, true).Run();

                return new CompositeDisposable(cacheLoader, transform.SubscribeSafe(observer), shared.Connect());
            }));
        }
Beispiel #3
0
 private static IEnumerable <Change <TSource, TKey> > CaptureChanges(InternalCache <TSource, TKey> cache, Func <TSource, TKey, bool> shouldTransform)
 {
     foreach (var kvp in cache.KeyValues)
     {
         if (shouldTransform(kvp.Value, kvp.Key))
         {
             yield return(new Change <TSource, TKey>(ChangeReason.Refresh, kvp.Key, kvp.Value));
         }
     }
 }
Beispiel #4
0
        private void Update(InternalCache <TObject, TKey> cache, IChangeSet <TObject, TKey> updates)
        {
            IChangeSet <TObject, TKey> notifications;

            lock (_locker)
            {
                //update cache for the individual source
                cache.Clone(updates);

                //update combined
                notifications = UpdateCombined(updates);
            }

            if (notifications.Count != 0)
            {
                _updatedCallback(notifications);
            }
        }
Beispiel #5
0
        private void RegisterForRemoval(IChangeSet <TObject, TKey> changes, InternalCache <TObject, TKey> cache)
        {
            changes.ForEach(change =>
            {
                switch (change.Reason)
                {
                case ChangeReason.Update:
                    // ReSharper disable once InconsistentlySynchronizedField
                    change.Previous.IfHasValue(t => _removeAction(t));
                    break;

                case ChangeReason.Remove:
                    // ReSharper disable once InconsistentlySynchronizedField
                    _removeAction(change.Current);
                    break;
                }
            });
            cache.Clone(changes);
        }
Beispiel #6
0
        public IObservable <IChangeSet <TObject, TKey> > Run()
        {
            return(Observable.Create <IChangeSet <TObject, TKey> >(observer =>
            {
                var allData = new InternalCache <TObject, TKey>();
                var filteredData = new ChangeAwareCache <TObject, TKey>();
                Func <TObject, bool> predicate = t => false;

                var locker = new object();

                var refresher = LatestPredicateObservable()
                                .Synchronize(locker)
                                .Select(p =>
                {
                    //set the local predicate
                    predicate = p;

                    //reapply filter using all data from the cache
                    return filteredData.RefreshFilteredFrom(allData, predicate);
                });

                var dataChanged = _source
                                  .Synchronize(locker)
                                  .Select(changes =>
                {
                    //maintain all data [required to re-apply filter]
                    allData.Clone(changes);

                    //maintain filtered data
                    filteredData.FilterChanges(changes, predicate);

                    //get latest changes
                    return filteredData.CaptureChanges();
                });

                return refresher
                .Merge(dataChanged)
                .NotEmpty()
                .SubscribeSafe(observer);
            }));
        }
Beispiel #7
0
        public IObservable <IQuery <TObject, TKey> > Run()
        {
            if (_itemChangedTrigger == null)
            {
                return(_source
                       .Scan((InternalCache <TObject, TKey>)null, (cache, changes) =>
                {
                    if (cache == null)
                    {
                        cache = new InternalCache <TObject, TKey>(changes.Count);
                    }

                    cache.Clone(changes);
                    return cache;
                }).Select(list => new AnonymousQuery <TObject, TKey>(list)));
            }

            return(_source.Publish(shared =>
            {
                var locker = new object();
                var state = new InternalCache <TObject, TKey>();

                var inlineChange = shared
                                   .MergeMany(_itemChangedTrigger)
                                   .Synchronize(locker)
                                   .Select(_ => new AnonymousQuery <TObject, TKey>(state));

                var sourceChanged = shared
                                    .Synchronize(locker)
                                    .Scan(state, (list, changes) =>
                {
                    list.Clone(changes);
                    return list;
                }).Select(list => new AnonymousQuery <TObject, TKey>(list));

                return sourceChanged.Merge(inlineChange);
            }));
        }
Beispiel #8
0
        public IObservable <IChangeSet <TObject, TKey> > Run()
        {
            return(Observable.Create <IChangeSet <TObject, TKey> >(observer =>
            {
                var locker = new object();
                var cache = new InternalCache <TObject, TKey>();
                var subscriber = _source
                                 .Synchronize(locker)
                                 .Do(changes => RegisterForRemoval(changes, cache), observer.OnError)
                                 .SubscribeSafe(observer);

                return Disposable.Create(() =>
                {
                    subscriber.Dispose();

                    lock (locker)
                    {
                        cache.Items.ForEach(t => _removeAction(t));
                        cache.Clear();
                    }
                });
            }));
        }
Beispiel #9
0
 public GroupCache(TGroupKey key)
 {
     Key   = key;
     Cache = new InternalCache <TObject, TKey>();
 }
Beispiel #10
0
 public AnonymousQuery(InternalCache <TObject, TKey> cache)
 {
     _cache = cache.Clone();
 }