/// <summary>
        /// Cancel the process
        /// </summary>
        /// <param name="processRuntimeId"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public override bool Cancel(Guid processRuntimeId, string reason)
        {
            var filter = Builders <MongoProcessRuntimePersistence> .Filter.Eq(r => r.Id, processRuntimeId);

            var updater = Builders <MongoProcessRuntimePersistence> .Update
                          .Set(p => p.Status, (int)ProcessStateEnum.Cancelled)
                          .Set(p => p.NextStepId, string.Empty)
                          .Set(p => p.SuspendedStepId, string.Empty)
                          .CurrentDate(p => p.LastUpdated);

            MongoProcessRuntimePersistence item = _collection.FindOneAndUpdate(filter, updater);

            return(item != null);
        }
        /// <summary>
        /// Un-freeze the runtime process
        /// </summary>
        /// <param name="processRuntimeId"></param>
        /// <param name="runtime"></param>
        /// <param name="nextStep"></param>
        /// <param name="collection"></param>
        /// <returns></returns>
        public override bool TryUnfreeze(Guid processRuntimeId, out IProcessRuntime runtime, out StepRuntime nextStep,
                                         out IPropertySetCollection collection)
        {
            runtime    = null;
            nextStep   = null;
            collection = null;
            var filter = Builders <MongoProcessRuntimePersistence> .Filter.Eq(r => r.Id, processRuntimeId);

            MongoProcessRuntimePersistence rtp = _collection.Find(filter).SingleOrDefault();

            if (rtp == null)
            {
                return(false);
            }
            var defFilter = Builders <ProcessDefinitionPersistence> .Filter.And(
                Builders <ProcessDefinitionPersistence> .Filter.Eq(r => r.FlowId, rtp.DefinitionFlowId),
                Builders <ProcessDefinitionPersistence> .Filter.Eq(r => r.Md5, rtp.DefinitionMd5)
                );

            ProcessDefinition    definition;
            ProcessDefStatusEnum status;

            AccountData[] accounts;
            if (!_processDefinitionService.TryFind(defFilter, out definition, out status, out accounts))
            {
                return(false);
            }
            collection = rtp.PropertyCollection.Deserialize();
            if (!string.IsNullOrEmpty(rtp.NextStepId))
            {
                StepDefinition   stepDef = definition.Steps.SingleOrDefault(s => s.StepId == rtp.NextStepId);
                StepDefinitionId sid     = new StepDefinitionId(stepDef.Id, stepDef.StepId);
                LinkDefinition[] links   = definition.Links.Where(l => l.Source == sid).ToArray();
                nextStep = new StepRuntime(stepDef, links.Select(l => new LinkRuntime(l)).ToArray());
            }
            runtime = Create(rtp.Id, definition, rtp.SuspendedStepId, (ProcessStateEnum)rtp.Status);
            return(true);
        }
        /// <summary>
        /// Create persistent element
        /// </summary>
        /// <param name="runtime"></param>
        /// <param name="collection"></param>
        /// <param name="errors"></param>
        /// <param name="processDefinitionDigest"></param>
        /// <param name="nextStepId"></param>
        /// <returns></returns>
        private MongoProcessRuntimePersistence CreateMongoProcessRuntimePersistence(
            IProcessRuntime runtime,
            IPropertySetCollection collection,
            string nextStepId,
            List <string> errors,
            ProcessDefinitionDigest processDefinitionDigest)
        {
            var persistedCollection            = CreatePersistentPropertyCollection(runtime, collection);
            MongoProcessRuntimePersistence rtp = new MongoProcessRuntimePersistence
            {
                Id = runtime.Id,
                SuspendedStepId    = runtime.LastExecutedStep?.StepId,
                Status             = (int)runtime.State,
                LastUpdated        = DateTime.UtcNow,
                PropertyCollection = persistedCollection,
                DefinitionFlowId   = processDefinitionDigest.FlowId,
                DefinitionMd5      = processDefinitionDigest.Md5,
                NextStepId         = null,
                Errors             = errors
            };

            return(rtp);
        }
        /// <summary>
        /// Retrieve Process Runtime summary
        /// </summary>
        /// <param name="processRuntimeId"></param>
        /// <param name="summary"></param>
        /// <returns></returns>
        public override bool TryGetProcessSummary(Guid processRuntimeId, out ProcessRuntimeSummary summary)
        {
            summary = null;
            var filter = Builders <MongoProcessRuntimePersistence> .Filter.Eq(r => r.Id, processRuntimeId);

            MongoProcessRuntimePersistence rtp = _collection.Find(filter).SingleOrDefault();

            if (rtp == null)
            {
                return(false);
            }
            summary = new ProcessRuntimeSummary
            {
                Id     = processRuntimeId,
                Errors = rtp.Errors == null?new string[] {}:rtp.Errors.ToArray(),
                    Status            = (ProcessStateEnum)rtp.Status,
                    LastUpdated       = rtp.LastUpdated,
                    NextStepId        = rtp.NextStepId,
                    SuspendedInStep   = rtp.SuspendedStepId,
                    FlowDefinitionId  = rtp.DefinitionFlowId,
                    FlowDefinitionMd5 = rtp.DefinitionMd5
            };
            return(true);
        }