public IEnumerable <ItemMatch <T1, T2> > Append <T1, T2, TId>(ISynchSourcesConfig <T1, T2, TId> sourceConfig, IEnumerable <ItemMatch <T1, T2> > inlet) where TId : IEquatable <TId> { var batchCompleteItems = inlet.CompleteSingleItems(sourceConfig, TargetType.T1); return(batchCompleteItems); }
public IndividualItemMatcher([NotNull] ISynchSourcesConfig <T1, T2, TId> channelConfig, TargetType appendType) { _appendType = appendType; if (channelConfig == null) { throw new ArgumentNullException(nameof(channelConfig)); } ChannelConfig = channelConfig; }
public ItemMatchPipelinePlumber( ISynchSourcesConfig <T1, T2, TId> sourceConfig, IList <ISynchronizationResolver <ItemMatch <T1, T2> > > synchronizationResolvers, Func <IEnumerable <T1>, IEnumerable <T2>, IEnumerable <ItemMatch <T1, T2> > > preprocessor) { _preprocessor = preprocessor; _resolutionStep = new ChangeResolutionStep <ItemMatch <T1, T2>, ISynchSourcesConfig <T1, T2, TId> >(synchronizationResolvers, sourceConfig); _dispatchStep = new ChangeDispatchingStep <ItemMatch <T1, T2> >(); }
public ItemMatcher([NotNull] ISynchSourcesConfig <T1, T2, TId> sourceConfig) : this(sourceConfig.Type1EndpointConfiguration.TypeConfig, sourceConfig.Type2EndpointConfiguration.TypeConfig) { SourceConfig = sourceConfig; if (sourceConfig == null) { throw new ArgumentNullException(nameof(sourceConfig)); } }
public static IEnumerable <ItemMatch <T1, T2> > CompleteSingleItems <T1, T2, TId>( this IEnumerable <ItemMatch <T1, T2> > original, ISynchSourcesConfig <T1, T2, TId> channelConfig, TargetType appendType) where TId : IEquatable <TId> { var singleItemMatcher = new SingleItemCompletionMatcher <T1, T2, TId>(channelConfig, appendType); var completeSingleItems = original.Select(match => singleItemMatcher.Complete(match)).ToList(); return(completeSingleItems); }
public SingleItemCompletionMatcher( [NotNull] ISynchSourcesConfig <T1, T2, TId> channelConfiguration, TargetType completionSourceType) { if (channelConfiguration == null) { throw new ArgumentNullException(nameof(channelConfiguration)); } _channelConfiguration = channelConfiguration; _completionSourceType = completionSourceType; }
public virtual IPlumber <T1, T2, TId> Create <T1, T2, TId>(ISynchSourcesConfig <T1, T2, TId> source, IRuleContainer <TId> rules) where TId : IEquatable <TId> { var preprocessor = CreatePreprocessor(source, rules); var synchronizationResolvers = rules.GetTypedResolvers(source).ToList(); var plumber = new ItemMatchPipelinePlumber <T1, T2, TId>(source, synchronizationResolvers, preprocessor); if (Appender != null) { plumber.Appender = Appender; } return(plumber); }
GetTypedResolvers <T1, T2>(ISynchSourcesConfig <T1, T2, TId> sourcesConfig) /* where T1 : TBase1 * where T2 : TBase2*/ { foreach (Type rule in _rules) { var closedGenericTypeDef = rule; if (rule.GenericTypeArguments.Length > 0) { var genericTypeDef = rule.GetGenericTypeDefinition(); closedGenericTypeDef = genericTypeDef.MakeGenericType(typeof(T1), typeof(T2), typeof(TId)); } var ruleInstance = Activator.CreateInstance(closedGenericTypeDef) as SynchronizationRule <T1, T2, TId>; if (ruleInstance != null) { yield return(ruleInstance.ResolverInstance(sourcesConfig)); } } }
public OneWayPullChannel( [NotNull] ISynchSourcesConfig <T1, T2, TId> channelConfig, [NotNull] IPlumber <T1, T2, TId> plumber, [NotNull] Func <Task <IEnumerable <T1> > > t1DataSource, [NotNull] Func <Task <IEnumerable <T2> > > t2DataSource) { if (plumber == null) { throw new ArgumentNullException(nameof(plumber)); } if (t1DataSource == null) { throw new ArgumentNullException(nameof(t1DataSource)); } if (t2DataSource == null) { throw new ArgumentNullException(nameof(t2DataSource)); } ChannelConfig = channelConfig; Plumber = plumber; _t1DataSource = t1DataSource; _t2DataSource = t2DataSource; }
public static IEnumerable <ItemMatch <T1, T2> > BatchCompleteItems <T1, T2, TId>( this IEnumerable <ItemMatch <T1, T2> > original, ISynchSourcesConfig <T1, T2, TId> channelConfig, TargetType appendType) where TId : IEquatable <TId> { List <ItemMatch <T1, T2> > appendableMatches = new List <ItemMatch <T1, T2> >(); foreach (var itemMatch in original) { if (itemMatch.IsComplete) { yield return(itemMatch); } else { if (appendType == TargetType.T1 && (itemMatch.HasT1() || channelConfig.Type2EndpointConfiguration.IsNew(itemMatch.Result2))) { yield return(itemMatch); } else if (appendType == TargetType.T2 && (itemMatch.HasT2() || channelConfig.Type1EndpointConfiguration.IsNew(itemMatch.Result1))) { yield return(itemMatch); } else { appendableMatches.Add(itemMatch); } } } if (appendableMatches.Count > 0) { // The logic to match two lists already exists, we can simply reuse it! var matcher = new ItemMatcher <T1, T2, TId, ItemMatch <T1, T2> >(channelConfig); IEnumerable <T1> append1 = null; IEnumerable <T2> append2 = null; if (appendType == TargetType.T1) { var batchIds = appendableMatches.Select( match => channelConfig.Type2EndpointConfiguration.TypeConfig.IdExtractor(match.Result2)) .ToArray(); append1 = channelConfig.Type1EndpointConfiguration.Endpoint.Read(batchIds); append2 = appendableMatches.Select(match => match.Result2); } if (appendType == TargetType.T2) { var batchIds = appendableMatches.Select( match => channelConfig.Type1EndpointConfiguration.TypeConfig.IdExtractor(match.Result1)) .ToArray(); append1 = appendableMatches.Select(match => match.Result1); append2 = channelConfig.Type2EndpointConfiguration.Endpoint.Read(batchIds); } if (append1 == null || append2 == null) { throw new Exception("Having two empty lists is can not be matched! Something went wrong."); } foreach (var newMatch in matcher.Match(append1, append2)) { yield return(newMatch); } } }
// Could also put this in another factory method. protected virtual Func <IEnumerable <T1>, IEnumerable <T2>, IEnumerable <ItemMatch <T1, T2> > > CreatePreprocessor <T1, T2, TId>(ISynchSourcesConfig <T1, T2, TId> source, IRuleContainer <TId> rules) where TId : IEquatable <TId> { var matcher = new ItemMatcher <T1, T2, TId, ItemMatch <T1, T2> >(source); Func <IEnumerable <T1>, IEnumerable <T2>, IEnumerable <ItemMatch <T1, T2> > > preprocessor = matcher.Match; return(preprocessor); }
public abstract SynchronizationResult Then(ItemMatch <TBase1, TBase2> item, ISynchSourcesConfig <TBase1, TBase2, TId> cfg);
public abstract bool When(ItemMatch <TBase1, TBase2> item, ISynchSourcesConfig <TBase1, TBase2, TId> cfg);
public SynchronizationResolver <ItemMatch <TBase1, TBase2>, ISynchSourcesConfig <TBase1, TBase2, TId> > ResolverInstance(ISynchSourcesConfig <TBase1, TBase2, TId> cfg) { // Create instance of self with derived types. // Then again, passing the methods as a resolver will still result in calls on the same instance, which we might not want in the future. var derivedInstance = Activator.CreateInstance(GetType()); var castedInstance = (SynchronizationRule <TBase1, TBase2, TId>)derivedInstance; return(new SynchronizationResolver <ItemMatch <TBase1, TBase2>, ISynchSourcesConfig <TBase1, TBase2, TId> >(cfg, castedInstance.When, castedInstance.Then, Name)); }
private IEnumerable <ItemMatch <T1, T2> > CreateInlet(IEnumerable <T1> source1, IEnumerable <T2> source2, ISynchSourcesConfig <T1, T2, TId> sourcesConfig) { IEnumerable <ItemMatch <T1, T2> > inlet; try { inlet = _preprocessor(source1, source2); } catch (Exception ex) { throw new SynchronizationException($"Provided items preprocessor failed with message: \"{ex.Message}\"", ex); } return(inlet); }
public SynchPipeline CreatePipeline(IEnumerable <T1> source1, IEnumerable <T2> source2, ISynchSourcesConfig <T1, T2, TId> sourcesConfig) { IEnumerable <ItemMatch <T1, T2> > pipeline = CreateInlet(source1, source2, sourcesConfig); if (Appender != null) { pipeline = Appender.Append(sourcesConfig, pipeline); } pipeline = _synchItemListeners.Aggregate(pipeline, (current, listener) => current.Select(item => { listener(item); return(item); })); // This is an odd construct where the pipeline has to be constructed because it needs a counter in the do. var synchPipeline = new SynchPipeline(); var endPipeline = pipeline .Do(_ => synchPipeline.ItemsProcessed++) .ResolveChange(_resolutionStep) .Where(action => action.Applicant != null) // Filter out NullSynchActions, which don't have an applicant instance, why not put it in the step itself? .DispatchChange(_dispatchStep); synchPipeline.Pipeline = endPipeline; return(synchPipeline); }