/// <summary>
        /// Attempts to create an instance of <see cref="IDataFlowPipelineEngine"/> described by the blueprint <paramref name="pipeline"/>.  Components are then checked if they
        /// support <see cref="ICheckable"/> using the <paramref name="checkNotifier"/> to record the results.
        /// </summary>
        /// <param name="pipeline">The blueprint to attempt to generate</param>
        /// <param name="checkNotifier">The event notifier to record how it went</param>
        /// <param name="initizationObjects">The objects available for fulfilling IPipelineRequirements</param>
        public void Check(IPipeline pipeline, ICheckNotifier checkNotifier, object[] initizationObjects)
        {
            //Try to construct the pipeline into an in memory Engine based on the in Catalogue blueprint (Pipeline)
            IDataFlowPipelineEngine dataFlowPipelineEngine = null;

            try
            {
                dataFlowPipelineEngine = Create(pipeline, new FromCheckNotifierToDataLoadEventListener(checkNotifier));
                checkNotifier.OnCheckPerformed(new CheckEventArgs("Pipeline successfully constructed in memory", CheckResult.Success));
            }
            catch (Exception exception)
            {
                checkNotifier.OnCheckPerformed(
                    new CheckEventArgs("Failed to construct pipeline, see Exception for details", CheckResult.Fail,
                                       exception));
            }

            if (initizationObjects == null)
            {
                checkNotifier.OnCheckPerformed(new CheckEventArgs("initizationObjects parameter has not been set (this is a programmer error most likely ask your developer to fix it - this parameter should be empty not null)",
                                                                  CheckResult.Fail));
                return;
            }

            //Initialize each component with the initialization objects so that they can check themselves (note that this should be preview data, hopefully the components don't run off and start nuking stuff just because they got their GO objects)
            if (dataFlowPipelineEngine != null)
            {
                try
                {
                    dataFlowPipelineEngine.Initialize(initizationObjects);
                    checkNotifier.OnCheckPerformed(
                        new CheckEventArgs(
                            "Pipeline sucesfully initialized with " +
                            initizationObjects.Length + " initialization objects",
                            CheckResult.Success));
                }
                catch (Exception exception)
                {
                    checkNotifier.OnCheckPerformed(
                        new CheckEventArgs(
                            "Pipeline initialization failed, there were " + initizationObjects.Length +
                            " objects for use in initialization (" +
                            string.Join(",", initizationObjects.Select(o => o.ToString())) + ")", CheckResult.Fail,
                            exception));
                }

                checkNotifier.OnCheckPerformed(new CheckEventArgs("About to check engine/components", CheckResult.Success));
                dataFlowPipelineEngine.Check(checkNotifier);
            }
        }
        public void Check(ICheckNotifier notifier)
        {
            try
            {
                if (_cacheProgress.Pipeline_ID == null)
                {
                    throw new Exception("CacheProgress " + _cacheProgress.ID + " doesn't have a caching pipeline!");
                }

                IPipeline pipeline = null;
                try
                {
                    pipeline = _cacheProgress.Pipeline;
                }
                catch (Exception e)
                {
                    notifier.OnCheckPerformed(new CheckEventArgs("Error when trying to load Pipeline ID = " + _cacheProgress.Pipeline_ID.Value, CheckResult.Fail, e));
                }

                if (pipeline == null)
                {
                    notifier.OnCheckPerformed(new CheckEventArgs("Could not run Pipeline checks due to previous errors", CheckResult.Fail));
                }
                else
                {
                    var checker = new PipelineChecker(pipeline);
                    checker.Check(notifier);
                }

                if (_cacheProgress.CacheFillProgress == null && _cacheProgress.LoadProgress.OriginDate == null)
                {
                    //if we don't know what dates to request
                    notifier.OnCheckPerformed(
                        new CheckEventArgs(
                            "Both the CacheFillProgress and the LoadProgress.OriginDate are null, this means we don't know where the cache has filled up to and we don't know when the dataset is supposed to start.  This means it is impossible to know what dates to fetch",
                            CheckResult.Fail));
                }

                if (_cacheProgress.PermissionWindow_ID != null && !_cacheProgress.PermissionWindow.WithinPermissionWindow(DateTime.UtcNow))
                {
                    notifier.OnCheckPerformed(new CheckEventArgs(
                                                  "Current time is " + DateTime.UtcNow +
                                                  " which is not a permitted time according to the configured PermissionWindow " + _cacheProgress.PermissionWindow.Description +
                                                  " of the CacheProgress " + _cacheProgress,
                                                  CheckResult.Warning));
                }

                var shortfall = _cacheProgress.GetShortfall();

                if (shortfall <= TimeSpan.Zero)
                {
                    if (_cacheProgress.CacheLagPeriod == null)
                    {
                        notifier.OnCheckPerformed(
                            new CheckEventArgs(
                                "CacheProgress reports that it has loaded up till " + _cacheProgress.CacheFillProgress +
                                " which is in the future.  So we don't need to load this cache.", CheckResult.Warning));
                    }
                    else
                    {
                        notifier.OnCheckPerformed(
                            new CheckEventArgs(
                                "CacheProgress reports that it has loaded up till " + _cacheProgress.CacheFillProgress +
                                " but there is a lag period of " + _cacheProgress.CacheLagPeriod +
                                " which means we are not due to load any cached data yet.", CheckResult.Warning));
                    }
                }

                var factory = new CachingPipelineUseCase(_cacheProgress);
                IDataFlowPipelineEngine engine = null;
                try
                {
                    engine = factory.GetEngine(new FromCheckNotifierToDataLoadEventListener(notifier));
                }
                catch (Exception e)
                {
                    notifier.OnCheckPerformed(new CheckEventArgs("Could not create IDataFlowPipelineEngine", CheckResult.Fail, e));
                }

                if (engine != null)
                {
                    engine.Check(notifier);
                }
            }
            catch (Exception e)
            {
                notifier.OnCheckPerformed(
                    new CheckEventArgs(
                        "Entire checking process for cache progress " + _cacheProgress +
                        " crashed, see Exception for details", CheckResult.Fail, e));
            }
        }