예제 #1
0
        protected override INotifyValue <bool> CreateTracker(SynchronizationComputation <TLeft, TRight> computation)
        {
            var tracker = Guard.Observe(computation.Input);

            tracker.Successors.SetDummy();
            return(tracker);
        }
예제 #2
0
        public IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
        {
            switch (context.ChangePropagation)
            {
            case ChangePropagationMode.None:
                return(null);

            case ChangePropagationMode.OneWay:
                if (direction != SynchronizationDirection.LeftToRight && direction != SynchronizationDirection.LeftToRightForced && direction != SynchronizationDirection.LeftWins)
                {
                    return(null);
                }
                break;

            case ChangePropagationMode.TwoWay:
                break;

            default:
                throw new InvalidOperationException("The change propagation mode is invalid.");
            }

            var instantiationMonitor = Predicate.Observe(computation.Input);
            var monitor = new Monitor(instantiationMonitor, computation);

            monitor.StartMonitoring();
            return(monitor);
        }
        private void HandleStaticRTLDependency(SynchronizationComputation <TRight, TLeft> syncComputation)
        {
            var input = rightGetter(syncComputation.Input);

            CallRTLTransformationForInput(syncComputation, syncComputation.SynchronizationContext.Direction,
                                          input, leftGetter(syncComputation.Opposite.Input), leftSetter, rightSetter);
        }
        private IDisposable CreateLeftToRightSynchronization(bool allowRightToLeft, SynchronizationComputation <TLeft, TRight> syncComputation)
        {
            IDisposable dependency = null;

            switch (syncComputation.SynchronizationContext.ChangePropagation)
            {
            case ChangePropagationMode.None:
                HandleStaticLTRDependency(syncComputation);
                break;

            case ChangePropagationMode.OneWay:
                dependency = HandleOneWayLTRSynchronization(syncComputation);
                break;

            case ChangePropagationMode.TwoWay:
                if (allowRightToLeft)
                {
                    dependency = HandleTwoWayLTRSynchronization(syncComputation);
                }
                else
                {
                    dependency = HandleOneWayLTRSynchronization(syncComputation);
                }
                break;

            default:
                break;
            }
            if (dependency != null)
            {
                syncComputation.Dependencies.Add(dependency);
            }

            return(dependency);
        }
            public OneWayLTRSynchronization(INotifyValue <TDepLeft> left, SynchronizationComputation <TLeft, TRight> computation, SynchronizationSingleDependency <TLeft, TRight, TDepLeft, TDepRight> parent)
            {
                Left        = left;
                Parent      = parent;
                Computation = computation;

                Left.ValueChanged += Left_ValueChanged;
            }
            public OneWayRTLDependency(INotifyValue <TDepRight> right, SynchronizationComputation <TRight, TLeft> computation, SynchronizationSingleDependency <TLeft, TRight, TDepLeft, TDepRight> parent)
            {
                Right       = right;
                Parent      = parent;
                Computation = computation;

                Right.ValueChanged += Left_ValueChanged;
            }
            public TwoWaySynchronization(INotifyReversableValue <TDepLeft> left, INotifyReversableValue <TDepRight> right, SynchronizationComputation <TLeft, TRight> computation, SynchronizationSingleDependency <TLeft, TRight, TDepLeft, TDepRight> parent)
            {
                Left        = left;
                Right       = right;
                Parent      = parent;
                Computation = computation;

                Left.ValueChanged  += Left_ValueChanged;
                Right.ValueChanged += Right_ValueChanged;
            }
        private IDisposable HandleTwoWayRTLSynchronization(SynchronizationComputation <TRight, TLeft> syncComputation)
        {
            var left  = leftFunc.InvokeReversable(syncComputation.Opposite.Input);
            var right = rightFunc.InvokeReversable(syncComputation.Input);
            Action <TLeft, TDepLeft>   leftSetter  = (l, val) => left.Value = val;
            Action <TRight, TDepRight> rightSetter = (r, val) => right.Value = val;

            CallRTLTransformationForInput(syncComputation, syncComputation.SynchronizationContext.Direction,
                                          right.Value, left.Value, leftSetter, rightSetter);
            return(new TwoWaySynchronization(left, right, syncComputation.Opposite, this));
        }
예제 #9
0
 public virtual IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
 {
     if (direction.IsRightToLeft())
     {
         return(Perform(computation.Opposite.Input, computation.Input, context));
     }
     else
     {
         return(null);
     }
 }
예제 #10
0
 public IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
 {
     if (Action != null)
     {
         return(Action(computation.Input, computation.Opposite.Input, direction, context));
     }
     else
     {
         return(null);
     }
 }
 private void Match(SynchronizationComputation <TLeft, TRight> baseCorrespondence, TDepLeft leftValue, TDepRight rightValue)
 {
     if (leftValue == null && rightValue == null)
     {
         return;
     }
     if ((leftValue != null && rightValue == null) ||
         (rightValue != null && leftValue == null) ||
         !childRule.ShouldCorrespond(leftValue, rightValue, baseCorrespondence.SynchronizationContext))
     {
         baseCorrespondence.SynchronizationContext.Inconsistencies.Add(new ReferenceInconsistency <TLeft, TRight, TDepLeft, TDepRight>(this, baseCorrespondence, leftValue, rightValue));
     }
 }
예제 #12
0
        internal void Synchronize(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
        {
            var dependencies = computation.Dependencies;

            foreach (var job in SynchronizationJobs.Where(j => !j.IsEarly))
            {
                var dependency = job.Perform(computation, direction, context);
                if (dependency != null)
                {
                    dependencies.Add(dependency);
                }
            }
        }
예제 #13
0
        internal void InitializeOutput(SynchronizationComputation <TLeft, TRight> computation)
        {
            var context      = computation.SynchronizationContext;
            var dependencies = computation.Dependencies;

            foreach (var job in SynchronizationJobs.Where(j => j.IsEarly))
            {
                var dependency = job.Perform(computation, context.Direction, context);
                if (dependency != null)
                {
                    dependencies.Add(dependency);
                }
            }
        }
예제 #14
0
            public Dependency(ISynchronizationJob <TLeft, TRight> inner, SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, INotifyValue <bool> tracker)
            {
                Inner       = inner;
                Computation = computation;
                Direction   = direction;
                Tracker     = tracker;

                if (tracker.Value)
                {
                    Current = Inner.Perform(Computation, Direction, Computation.SynchronizationContext);
                }

                Tracker.ValueChanged += Tracker_ValueChanged;
            }
        internal void CallRTLTransformationForInput(SynchronizationComputation <TRight, TLeft> syncComputation, SynchronizationDirection direction, TDepRight input, TDepLeft context, Action <TLeft, TDepLeft> leftSetter, Action <TRight, TDepRight> rightSetter)
        {
            if (direction == SynchronizationDirection.CheckOnly)
            {
                // two-way change propagation is handled through dependency
                if (syncComputation.SynchronizationContext.ChangePropagation == ChangePropagationMode.None)
                {
                    Match(syncComputation.Opposite, leftGetter(syncComputation.Opposite.Input), input);
                }
                return;
            }
            var left = syncComputation.Opposite.Input;

            if (input != null)
            {
                if (leftSetter == null)
                {
                    return;
                }
                var comp = syncComputation.TransformationContext.CallTransformation(childRule.RightToLeft, new object[] { input }, new object[] { context });
                if (comp == null)
                {
                    return;
                }
                if (!comp.IsDelayed)
                {
                    leftSetter(left, comp.Output as TDepLeft);
                }
                else
                {
                    comp.OutputInitialized += (o, e) => leftSetter(left, comp.Output as TDepLeft);
                };
            }
            else
            {
                if (direction == SynchronizationDirection.RightWins)
                {
                    CallLTRTransformationForInput(syncComputation.Opposite, SynchronizationDirection.RightWins, context, input, leftSetter, rightSetter);
                }
                else if (direction == SynchronizationDirection.RightToLeftForced)
                {
                    if (leftSetter == null)
                    {
                        return;
                    }
                    leftSetter(left, null);
                }
            }
        }
        private IDisposable HandleTwoWayRTLSynchronization(SynchronizationComputation <TRight, TLeft> syncComputation)
        {
            var left = leftFunc.InvokeReversable(syncComputation.Opposite.Input);

            left.Successors.SetDummy();
            var right = rightFunc.InvokeReversable(syncComputation.Input);

            right.Successors.SetDummy();
            Action <TLeft, TDepLeft>   leftSetter  = (l, val) => left.Value = val;
            Action <TRight, TDepRight> rightSetter = (r, val) => right.Value = val;

            CallRTLTransformationForInput(syncComputation, syncComputation.SynchronizationContext.Direction,
                                          right.Value, left.Value, leftSetter, rightSetter);
            return(new IncrementalReferenceConsistencyCheck <TLeft, TRight, TDepLeft, TDepRight>(left, right, syncComputation.Opposite, this));
        }
        public GuardedSynchronization(SynchronizationComputation <TLeft, TRight> computation, Func <SynchronizationComputation <TLeft, TRight>, IDisposable> func, INotifyValue <bool> guard)
        {
            Computation = computation;
            Func        = func;
            Guard       = guard;

            if (guard.Value)
            {
                Current = func(computation);
                if (Current != null)
                {
                    Computation.Dependencies.Add(Current);
                }
            }

            Guard.ValueChanged += Guard_ValueChanged;
        }
예제 #18
0
 protected virtual IDisposable SynchronizeRTLCollections(SynchronizationComputation <TRight, TLeft> computation, ICollection <TDepLeft> lefts, ICollection <TDepRight> rights, ISynchronizationContext context, bool ignoreCandidates)
 {
     if (lefts != null)
     {
         if (lefts.IsReadOnly)
         {
             throw new InvalidOperationException("Collection is read-only!");
         }
         IEnumerable <TDepLeft> leftsSaved = lefts;
         if (rights == null || context.Direction == SynchronizationDirection.RightToLeftForced)
         {
             leftsSaved = lefts.ToArray();
             lefts.Clear();
         }
         var         doubles     = new HashSet <TDepLeft>();
         IEnumerable leftContext = ignoreCandidates ? null : lefts;
         foreach (var item in rights)
         {
             var comp = context.CallTransformation(childRule.RightToLeft, new object[] { item }, leftContext) as SynchronizationComputation <TDepRight, TDepLeft>;
             comp.DoWhenOutputIsAvailable((inp, outp) =>
             {
                 if (!lefts.Contains(outp))
                 {
                     lefts.Add(outp);
                 }
                 else
                 {
                     doubles.Add(outp);
                 }
             });
         }
         if (context.Direction == SynchronizationDirection.RightWins)
         {
             foreach (var item in leftsSaved.Except(doubles))
             {
                 AddCorrespondingToRights(rights, context, item);
             }
         }
         return(RegisterRightChangePropagationHooks(lefts, rights, context));
     }
     else
     {
         throw new NotSupportedException("Target collection must not be null!");
     }
 }
        private IDisposable HandleOneWayRTLSynchronization(SynchronizationComputation <TRight, TLeft> syncComputation)
        {
            var input = rightFunc.Observe(syncComputation.Input);
            Action <TRight, TDepRight> rightSetter = (right, val) =>
            {
                var reversable = input as INotifyReversableValue <TDepRight>;
                if (reversable != null && reversable.IsReversable)
                {
                    reversable.Value = val;
                }
                else
                {
                    throw new InvalidOperationException(string.Format("The expression {0} cannot be written to as it is not reversable.", input));
                }
            };

            CallRTLTransformationForInput(syncComputation, syncComputation.SynchronizationContext.Direction,
                                          input.Value, leftGetter(syncComputation.Opposite.Input), leftSetter, rightSetter);
            return(new OneWayRTLDependency(input, syncComputation, this));
        }
예제 #20
0
        public IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
        {
            var left  = computation.Input;
            var right = computation.Opposite.Input;

            switch (context.ChangePropagation)
            {
            case NMF.Transformations.ChangePropagationMode.None:
                PerformNoChangePropagation(left, right, direction);
                return(null);

            case NMF.Transformations.ChangePropagationMode.OneWay:
                return(PerformOneWay(left, right, context));

            case NMF.Transformations.ChangePropagationMode.TwoWay:
                return(PerformTwoWay(left, right, context));

            default:
                throw new InvalidOperationException();
            }
        }
        private void CallRTLTransformationForInput(SynchronizationComputation <TRight, TLeft> syncComputation, SynchronizationDirection direction, TDepRight input, TDepLeft context, Action <TLeft, TDepLeft> leftSetter, Action <TRight, TDepRight> rightSetter)
        {
            var left = syncComputation.Opposite.Input;

            if (input != null)
            {
                if (leftSetter == null)
                {
                    return;
                }
                var comp = syncComputation.TransformationContext.CallTransformation(childRule.RightToLeft, new object[] { input }, new object[] { context });
                if (comp == null)
                {
                    return;
                }
                if (!comp.IsDelayed)
                {
                    leftSetter(left, comp.Output as TDepLeft);
                }
                else
                {
                    comp.OutputInitialized += (o, e) => leftSetter(left, comp.Output as TDepLeft);
                };
            }
            else
            {
                if (direction == SynchronizationDirection.RightWins)
                {
                    CallLTRTransformationForInput(syncComputation.Opposite, SynchronizationDirection.RightWins, context, input, leftSetter, rightSetter);
                }
                else if (direction == SynchronizationDirection.RightToLeftForced)
                {
                    if (leftSetter == null)
                    {
                        return;
                    }
                    leftSetter(left, null);
                }
            }
        }
예제 #22
0
 protected abstract INotifyValue <bool> CreateTracker(SynchronizationComputation <TLeft, TRight> computation);
예제 #23
0
 public IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context)
 {
     return(new Dependency(Inner, computation, direction, CreateTracker(computation)));
 }
예제 #24
0
 protected override INotifyValue <bool> CreateTracker(SynchronizationComputation <TLeft, TRight> computation)
 {
     return(Guard.Observe(computation.Input));
 }
 private SynchronizationComputation(TransformationRuleBase <TIn, TOut> rule, SynchronizationComputation <TOut, TIn> opposite)
     : base(rule, opposite.Context)
 {
     Opposite = opposite;
 }
 public SynchronizationComputation(TransformationRuleBase <TIn, TOut> rule, TransformationRuleBase <TOut, TIn> reverseRule, IComputationContext context, TIn input)
     : base(rule, context)
 {
     Opposite = new OppositeComputation(this, reverseRule);
     Input    = input;
 }
 public OppositeComputation(SynchronizationComputation <TIn, TOut> opposite, TransformationRuleBase <TOut, TIn> rule)
     : base(rule, opposite)
 {
 }
 private IDisposable CreateRightToLeftOnlySynchronization(SynchronizationComputation <TRight, TLeft> syncComputation)
 {
     return(CreateRightToLeftSynchronization(false, syncComputation));
 }
예제 #29
0
 public Monitor(INotifyValue <bool> instantiationMonitor, SynchronizationComputation <TLeft, TRight> computation)
 {
     InstantiationMonitor = instantiationMonitor;
     Computation          = computation;
 }
 private IDisposable CreateLeftToRightSynchronization(SynchronizationComputation <TLeft, TRight> syncComputation)
 {
     return(CreateLeftToRightSynchronization(true, syncComputation));
 }