internal static Process Convert(ProcessDocument processDocument)
        {
            return(new Process
            {
                processId = processDocument.Id,

                processStageId = processDocument.ProcessStage,
                createdOn = processDocument.CreatedOn,

                resourceId = processDocument.Resource,
                resourceType = Type.GetType(processDocument.ResourceType),

                resources = processDocument.GetResources(),

                confirmedWhen = processDocument.ConfirmedWhen,
                confirmedBy = processDocument.ConfirmedBy,
                previousStep = processDocument.PreviousStep,
            });
        }
        internal static Task <TResult> CreateAsync <TResult>(Guid processId,
                                                             Guid processStageId,
                                                             Guid actorId, Guid resourceId, Type resourceType, DateTime createdOn,
                                                             Process.ProcessStageResource[] resources,
                                                             Guid?previousStepId, DateTime?confirmedWhen, Guid?confirmedBy,
                                                             Guid [] lookupActorIds,
                                                             Func <TResult> onSuccess,
                                                             Func <TResult> onAlreadyExists)
        {
            return(AzureStorageRepository.Connection(
                       azureStorageRepository =>
            {
                var rollback = new RollbackAsync <TResult>();

                var resourceTypeString = resourceType.AssemblyQualifiedName;
                var processDocument = new ProcessDocument()
                {
                    ProcessStage = processStageId,

                    Resource = resourceId,
                    ResourceType = resourceTypeString,
                    CreatedOn = createdOn,
                    Owner = actorId,

                    ConfirmedBy = confirmedBy,
                    PreviousStep = previousStepId,
                    ConfirmedWhen = confirmedWhen,
                };
                processDocument.SetResources(resources);
                rollback.AddTaskCreate(processId, processDocument,
                                       onAlreadyExists, azureStorageRepository);

                foreach (var lookupActorId in lookupActorIds.Distinct())
                {
                    rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepActorLookupDocument>(lookupActorId, resourceTypeString,
                                                                                                       (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                                                                                                       actorDoc => actorDoc.RemoveLookupDocumentId(processId),
                                                                                                       azureStorageRepository);
                }

                rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepResourceLookupDocument>(resourceId, resourceTypeString,
                                                                                                      (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                                                                                                      actorDoc => actorDoc.RemoveLookupDocumentId(processId),
                                                                                                      azureStorageRepository);

                bool[] updates = resources
                                 .Select(
                    resource =>
                {
                    if (!resource.resourceId.HasValue)
                    {
                        return true;
                    }
                    rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepResourceKeyLookupDocument>(
                        resource.resourceId.Value, resource.type.AssemblyQualifiedName,
                        (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                        lookupDoc => lookupDoc.RemoveLookupDocumentId(processId),
                        azureStorageRepository);
                    return true;
                })
                                 .ToArray();

                return rollback.ExecuteAsync(onSuccess);
            }));
        }