protected override INotifyValue <bool> CreateTracker(SynchronizationComputation <TLeft, TRight> computation) { var tracker = Guard.Observe(computation.Input); tracker.Successors.SetDummy(); return(tracker); }
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)); }
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); } }
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)); } }
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); } } }
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); } } }
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; }
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)); }
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); } } }
protected abstract INotifyValue <bool> CreateTracker(SynchronizationComputation <TLeft, TRight> computation);
public IDisposable Perform(SynchronizationComputation <TLeft, TRight> computation, SynchronizationDirection direction, ISynchronizationContext context) { return(new Dependency(Inner, computation, direction, CreateTracker(computation))); }
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)); }
public Monitor(INotifyValue <bool> instantiationMonitor, SynchronizationComputation <TLeft, TRight> computation) { InstantiationMonitor = instantiationMonitor; Computation = computation; }
private IDisposable CreateLeftToRightSynchronization(SynchronizationComputation <TLeft, TRight> syncComputation) { return(CreateLeftToRightSynchronization(true, syncComputation)); }