Beispiel #1
0
        public void Should_add_new_workflow_with_default_states()
        {
            var id = Guid.NewGuid();

            var workflows_1 = workflows_0.Add(id, "1");

            Assert.Equal(workflows_1[id].Steps.Keys, new[] { Status.Archived, Status.Draft, Status.Published });
        }
Beispiel #2
0
        private void LoadWorkflow(string path)
        {
            var workflow = LoadWorkflowFromFile(path);

            if (workflow != null)
            {
                Workflows.Add(workflow);
                ScheduleWorkflow(workflow);
                _onCreatedRetries = 0;
            }
            else
            {
                if (_onCreatedRetries < MaxRetries)
                {
                    _onCreatedRetries++;
                    Logger.InfoFormat("Trying to load the workflow {0} again.", path);
                    Thread.Sleep(500);
                    LoadWorkflow(path);
                }
                else
                {
                    Logger.ErrorFormat("An error occured while loading the workflow {0}.", path);
                    _onCreatedRetries = 0;
                }
            }
        }
Beispiel #3
0
        private void LoadWorkflowOnChanged(string path)
        {
            var workflow = LoadWorkflowFromFile(path);

            if (workflow != null)
            {
                var duplicateId = Workflows.SingleOrDefault(wf => wf.Id == workflow.Id);
                if (duplicateId != null)
                {
                    Logger.ErrorFormat(
                        "An error occured while loading the workflow : {0}. The workflow Id {1} is already assigned in {2}",
                        path, workflow.Id, duplicateId.WorkflowFilePath);
                }
                else
                {
                    Workflows.Add(workflow);
                    ScheduleWorkflow(workflow);
                }
            }
            else
            {
                Logger.InfoFormat("Trying to load the workflow {0} again.", path);
                Thread.Sleep(500);
                LoadWorkflowOnChanged(path);
            }
        }
Beispiel #4
0
        public async Task <IWorkflow> AddDefaultWorkflow()
        {
            var w = await Workflow.Create(this, "New Workflow");

            Workflows.Add(w);
            return(w);
        }
        ///--------------------------------------------------------------------------------
        /// <summary>This method updates the view model data and sends update command back
        /// to the solution builder.</summary>
        ///--------------------------------------------------------------------------------
        protected override void OnUpdate()
        {
            // send update for any updated children
            foreach (WorkflowViewModel item in Workflows)
            {
                if (item.IsEdited == true)
                {
                    item.Update();
                }
            }
            // send update for any new children
            foreach (WorkflowViewModel item in ItemsToAdd.OfType <WorkflowViewModel>())
            {
                item.Update();
                Workflows.Add(item);
            }
            ItemsToAdd.Clear();

            // send delete for any deleted children
            foreach (WorkflowViewModel item in ItemsToDelete.OfType <WorkflowViewModel>())
            {
                item.Delete();
                Workflows.Remove(item);
            }
            ItemsToDelete.Clear();

            // reset modified for children
            foreach (WorkflowViewModel item in Workflows)
            {
                item.ResetModified(false);
            }
        }
        private void AddWorkflow()
        {
            var model = new Workflow().Default();
            var vm    = new WorkflowViewModel(model);

            Workflows.Add(vm);
        }
Beispiel #7
0
        private void LoadWorkflows()
        {
            var workflows = Database.GetWorkflows();

            foreach (var workflow in workflows)
            {
                var wf = LoadWorkflowFromDatabase(workflow);
                Workflows.Add(wf);
            }
        }
Beispiel #8
0
        public override void NonUIThreadInitialize()
        {
            base.NonUIThreadInitialize();

            foreach (WorkflowTemplate w in ((StudyType)Item).Workflows.Where(x => x.Deleted == false))
            {
                DataStoreItemViewModel wvm = new DataStoreItemViewModel(w);
                Workflows.Add((WorkflowTemplateViewModel)wvm);
            }
        }
Beispiel #9
0
 private void LoadWorkflows()
 {
     foreach (string file in Directory.GetFiles(WorkflowsFolder))
     {
         var workflow = LoadWorkflowFromFile(file);
         if (workflow != null)
         {
             Workflows.Add(workflow);
         }
     }
 }
Beispiel #10
0
        private void LoadWorkflows()
        {
            //foreach (string file in Directory.GetFiles(@"C:\Wexflow\Workflows\prod"))
            //{
            //    Database.InsertWorkflow(new Db.Workflow { Xml = File.ReadAllText(file) });
            //}

            var workflows = Database.GetWorkflows();

            foreach (var workflow in workflows)
            {
                var wf = LoadWorkflowFromDatabase(workflow);
                Workflows.Add(wf);
            }
        }
Beispiel #11
0
        private void LoadWorkflow(string path)
        {
            var workflow = LoadWorkflowFromFile(path);

            if (workflow != null)
            {
                Workflows.Add(workflow);
                ScheduleWorkflow(workflow);
            }
            else
            {
                Logger.InfoFormat("Trying to load the workflow {0} again.", path);
                Thread.Sleep(500);
                LoadWorkflow(path);
            }
        }
Beispiel #12
0
        private void ReadProjectWorkflows(string directory)
        {
            var dirInfo = new DirectoryInfo(directory);
            var files   = dirInfo.GetFiles("*.xaml", SearchOption.AllDirectories);

            foreach (var file in files)
            {
                string fullName = file.FullName;
                var    wf       = new Workflow(this, fullName);
                Workflows.Add(PathHelper.MakeRelativePath(fullName, Folder).ToLower(), wf);

                if (MainFile.Equals(fullName, StringComparison.InvariantCultureIgnoreCase))
                {
                    InitialWorkflow = wf;
                }
            }
        }
        public LoggingSettings(XElement xml, string webserverUri)
            : base(xml, webserverUri)
        {
            IsInitializing = true;

            var postWorkflow = xml.Element("PostWorkflow");

            bool boolValue;
            int  intValue;

            IsLoggingEnabled    = bool.TryParse(xml.AttributeSafe("IsLoggingEnabled"), out boolValue) && boolValue;
            IsVersionLogged     = bool.TryParse(xml.AttributeSafe("IsVersionLogged"), out boolValue) && boolValue;
            IsTypeLogged        = bool.TryParse(xml.AttributeSafe("IsTypeLogged"), out boolValue) && boolValue;
            IsDurationLogged    = bool.TryParse(xml.AttributeSafe("IsDurationLogged"), out boolValue) && boolValue;
            IsDataAndTimeLogged = bool.TryParse(xml.AttributeSafe("IsDataAndTimeLogged"), out boolValue) && boolValue;
            IsInputLogged       = bool.TryParse(xml.AttributeSafe("IsInputLogged"), out boolValue) && boolValue;
            IsOutputLogged      = bool.TryParse(xml.AttributeSafe("IsOutputLogged"), out boolValue) && boolValue;
            NestedLevelCount    = Int32.TryParse(xml.AttributeSafe("NestedLevelCount"), out intValue) ? intValue : 0;
            LogAll           = bool.TryParse(xml.AttributeSafe("LogAll"), out boolValue) && boolValue;
            LogFileDirectory = xml.AttributeSafe("LogFileDirectory");
            ServiceInput     = xml.AttributeSafe("ServiceInput");

            var workflows = xml.Element("Workflows");

            if (workflows != null)
            {
                foreach (var workflow in workflows.Elements())
                {
                    Workflows.Add(new WorkflowDescriptor(workflow));
                }
            }

            if (postWorkflow != null)
            {
                PostWorkflow = new WorkflowDescriptor(xml.Element("PostWorkflow"));
            }

            RunPostWorkflow = PostWorkflow != null;

            IsInitializing = false;
        }
Beispiel #14
0
        /// <summary>
        /// Loads a workflow from an providen filepath
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool LoadWorkflow(string path)
        {
            string configPath = path + "\\config.json";

            if (File.Exists(configPath))
            {
                try
                {
                    dynamic  item     = JsonConvert.DeserializeObject(File.ReadAllText(configPath));
                    Workflow workflow = new Workflow(item, path);
                    Application.Current.Dispatcher.Invoke(() => Workflows.Add(workflow));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to load Workflow. Invalid config.js format!");
                    return(false);
                }
                return(true);
            }
            return(false);
        }
Beispiel #15
0
        private void LoadFilesFromDisk(string folder)
        {
            if (string.IsNullOrEmpty(folder))
            {
                folder = Path;
            }
            var Files = System.IO.Directory.EnumerateFiles(folder, "*.*", System.IO.SearchOption.AllDirectories).OrderBy((x) => x).ToArray();

            foreach (string file in Files)
            {
                if (System.IO.Path.GetExtension(file).ToLower() == ".xaml")
                {
                    Workflows.Add(Workflow.FromFile(this, file));
                }
                else if (System.IO.Path.GetExtension(file).ToLower() == ".json")
                {
                    var      json = System.IO.File.ReadAllText(file);
                    Detector _d   = JsonConvert.DeserializeObject <Detector>(json);
                    if (!string.IsNullOrEmpty(_d._id))
                    {
                        var exists = RobotInstance.instance.Detectors.FindById(_d._id);
                        if (exists != null)
                        {
                            _d._id = null;
                        }
                        else
                        {
                            _d.isLocalOnly = true;
                        }
                    }
                    if (string.IsNullOrEmpty(_d._id))
                    {
                        _d._id = Guid.NewGuid().ToString();
                    }
                    _d.isDirty = true;
                    _d.Start(true);
                    Detectors.Add(_d);
                }
            }
        }
 ///--------------------------------------------------------------------------------
 /// <summary>This method applies workflow updates.</summary>
 ///--------------------------------------------------------------------------------
 public void ProcessEditWorkflowPerformed(WorkflowEventArgs data)
 {
     try
     {
         bool isItemMatch = false;
         if (data != null && data.Workflow != null)
         {
             foreach (WorkflowViewModel item in Workflows)
             {
                 if (item.Workflow.WorkflowID == data.Workflow.WorkflowID)
                 {
                     isItemMatch = true;
                     item.Workflow.TransformDataFromObject(data.Workflow, null, false);
                     item.OnUpdated(item, null);
                     item.ShowInTreeView();
                     break;
                 }
             }
             if (isItemMatch == false)
             {
                 // add new Workflow
                 data.Workflow.Solution = Solution;
                 WorkflowViewModel newItem = new WorkflowViewModel(data.Workflow, Solution);
                 newItem.Updated += new EventHandler(Children_Updated);
                 Workflows.Add(newItem);
                 Solution.WorkflowList.Add(newItem.Workflow);
                 Items.Add(newItem);
                 OnUpdated(this, null);
                 newItem.ShowInTreeView();
             }
         }
     }
     catch (Exception ex)
     {
         ShowIssue(ex.Message + ex.StackTrace);
     }
 }
Beispiel #17
0
        public Guid CreateWorkflow(string workflowId, string entityId)
        {
            if (WorkflowConfigurations.Any(x => x.Key == workflowId))
            {
                var workflowConfiguration = WorkflowConfigurations.First(x => x.Key == workflowId).Value;

                var workflow = new Workflow
                               (
                    workflowConfiguration,
                    EngineConfiguration.EntityConfigurations.Where(x => x.Key == entityId)
                    .SelectMany(x => x.Value)
                    .Where(x => workflowConfiguration.Steps.Select(a => a.Key).Contains(x.Step))
                               );

                Workflows.Add(workflow.Identifier, workflow);


                return(workflow.Identifier);
            }
            else
            {
                throw new Exception($"Workflow {workflowId} Not Found");
            }
        }
Beispiel #18
0
        private void LoadWorkflows()
        {
            foreach (string file in Directory.GetFiles(WorkflowsFolder))
            {
                var workflow = LoadWorkflowFromFile(file);
                if (workflow != null)
                {
                    Workflows.Add(workflow);
                }
            }

            var watcher = new FileSystemWatcher(WorkflowsFolder, "*.xml")
            {
                EnableRaisingEvents   = true,
                IncludeSubdirectories = false
            };

            watcher.Created += (_, args) =>
            {
                try
                {
                    Logger.Info("FileSystemWatcher.OnCreated");
                    watcher.EnableRaisingEvents = false;

                    LoadWorkflow(args.FullPath);
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;
                }
            };

            watcher.Deleted += (_, args) =>
            {
                try
                {
                    watcher.EnableRaisingEvents = false;

                    Logger.Info("FileSystemWatcher.OnDeleted");

                    var removedWorkflow = Workflows.SingleOrDefault(wf => wf.WorkflowFilePath == args.FullPath);
                    if (removedWorkflow != null)
                    {
                        Logger.InfoFormat("Workflow {0} is stopped and removed because its definition file {1} was deleted.",
                                          removedWorkflow.Name, removedWorkflow.WorkflowFilePath);
                        removedWorkflow.Stop();

                        StopCronJobs(removedWorkflow.Id);
                        Workflows.Remove(removedWorkflow);
                    }
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;
                }
            };

            watcher.Changed += (_, args) =>
            {
                try
                {
                    watcher.EnableRaisingEvents = false;

                    try
                    {
                        Logger.Info("FileSystemWatcher.OnChanged");

                        if (Workflows != null)
                        {
                            var changedWorkflow = Workflows.SingleOrDefault(wf => wf.WorkflowFilePath == args.FullPath);

                            if (changedWorkflow != null)
                            {
                                // the existing file might have caused an error during loading, so there may be no corresponding
                                // workflow to the changed file
                                changedWorkflow.Stop();

                                StopCronJobs(changedWorkflow.Id);
                                Workflows.Remove(changedWorkflow);
                                Logger.InfoFormat("A change in the definition file {0} of workflow {1} has been detected. The workflow will be reloaded.", changedWorkflow.WorkflowFilePath, changedWorkflow.Name);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Error("Error during workflow reload", e);
                    }

                    LoadWorkflowOnChanged(args.FullPath);
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;
                }
            };
        }
Beispiel #19
0
        /// <summary>
        /// Saves a workflow in the database.
        /// </summary>
        /// <param name="xml">XML of the workflow.</param>
        /// <param name="userId">User id.</param>
        /// <param name="userProfile">User profile.</param>
        /// <param name="schedule">Indicates whether to schedule the workflow or not.</param>
        /// <returns>Workflow db id.</returns>
        public string SaveWorkflow(string userId, UserProfile userProfile, string xml, bool schedule)
        {
            try
            {
                using (var xmlReader = XmlReader.Create(new StringReader(xml)))
                {
                    XmlNamespaceManager xmlNamespaceManager = null;
                    var xmlNameTable = xmlReader.NameTable;
                    if (xmlNameTable != null)
                    {
                        xmlNamespaceManager = new XmlNamespaceManager(xmlNameTable);
                        xmlNamespaceManager.AddNamespace("wf", "urn:wexflow-schema");
                    }

                    var xdoc     = XDocument.Parse(xml);
                    var id       = int.Parse(xdoc.XPathSelectElement("/wf:Workflow", xmlNamespaceManager).Attribute("id").Value);
                    var workflow = Workflows.FirstOrDefault(w => w.Id == id);

                    if (workflow == null) // insert
                    {
                        // check the workflow before to save it
                        try
                        {
                            new Workflow(
                                this
                                , 1
                                , new Dictionary <Guid, Workflow>()
                                , "-1"
                                , xml
                                , TempFolder
                                , WorkflowsTempFolder
                                , TasksFolder
                                , ApprovalFolder
                                , XsdPath
                                , Database
                                , GlobalVariables
                                );
                        }
                        catch (Exception e)
                        {
                            Logger.ErrorFormat("An error occured while saving the workflow {0}:", e, xml);
                            return("-1");
                        }
                        string dbId = Database.InsertWorkflow(new Db.Workflow {
                            Xml = xml
                        });

                        if (userProfile == UserProfile.Administrator)
                        {
                            InsertUserWorkflowRelation(userId, dbId);
                        }

                        var wfFromDb    = Database.GetWorkflow(dbId);
                        var newWorkflow = LoadWorkflowFromDatabase(wfFromDb);

                        Logger.InfoFormat("New workflow {0} has been created. The workflow will be loaded.", newWorkflow.Name);
                        Workflows.Add(newWorkflow);
                        if (schedule)
                        {
                            ScheduleWorkflow(newWorkflow);
                        }
                        return(dbId);
                    }
                    else // update
                    {
                        // check the workflow before to save it
                        try
                        {
                            new Workflow(
                                this
                                , 1
                                , new Dictionary <Guid, Workflow>()
                                , "-1"
                                , xml
                                , TempFolder
                                , WorkflowsTempFolder
                                , TasksFolder
                                , ApprovalFolder
                                , XsdPath
                                , Database
                                , GlobalVariables
                                );
                        }
                        catch (Exception e)
                        {
                            Logger.ErrorFormat("An error occured while saving the workflow {0}:", e, xml);
                            return("-1");
                        }

                        var workflowFromDb = Database.GetWorkflow(workflow.DbId);
                        workflowFromDb.Xml = xml;
                        Database.UpdateWorkflow(workflow.DbId, workflowFromDb);

                        var changedWorkflow = Workflows.SingleOrDefault(wf => wf.DbId == workflowFromDb.GetDbId());

                        if (changedWorkflow != null)
                        {
                            changedWorkflow.Stop();

                            StopCronJobs(changedWorkflow.Id);
                            Workflows.Remove(changedWorkflow);
                            Logger.InfoFormat("A change in the workflow {0} has been detected. The workflow will be reloaded.", changedWorkflow.Name);

                            var updatedWorkflow = LoadWorkflowFromDatabase(workflowFromDb);
                            Workflows.Add(updatedWorkflow);
                            if (schedule)
                            {
                                ScheduleWorkflow(updatedWorkflow);
                            }
                            return(changedWorkflow.DbId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("Error while saving a workflow: {0}", e.Message);
            }

            return("-1");
        }
Beispiel #20
0
        void LoadWorkflows()
        {
            foreach (string file in Directory.GetFiles(WorkflowsFolder))
            {
                var workflow = LoadWorkflowFromFile(file);
                if (workflow != null)
                {
                    Workflows.Add(workflow);
                }
            }

            var watcher = new FileSystemWatcher(WorkflowsFolder, "*.xml")
            {
                EnableRaisingEvents   = true,
                IncludeSubdirectories = false
            };

            watcher.Created += (_, args) =>
            {
                var workflow = LoadWorkflowFromFile(args.FullPath);
                if (workflow != null)
                {
                    Workflows.Add(workflow);
                    ScheduleWorkflow(workflow);
                }
            };

            watcher.Deleted += (_, args) =>
            {
                var removedWorkflow = Workflows.SingleOrDefault(wf => wf.WorkflowFilePath == args.FullPath);
                if (removedWorkflow != null)
                {
                    Logger.InfoFormat("Workflow {0} is stopped and removed because its definition file {1} was deleted.",
                                      removedWorkflow.Name, removedWorkflow.WorkflowFilePath);
                    removedWorkflow.Stop();

                    StopCronJobs(removedWorkflow.Id);
                    Workflows.Remove(removedWorkflow);
                }
            };

            watcher.Changed += (_, args) =>
            {
                try
                {
                    if (Workflows != null)
                    {
                        var changedWorkflow = Workflows.SingleOrDefault(wf => wf.WorkflowFilePath == args.FullPath);

                        if (changedWorkflow != null)
                        {
                            // the existing file might have caused an error during loading, so there may be no corresponding
                            // workflow to the changed file
                            changedWorkflow.Stop();

                            StopCronJobs(changedWorkflow.Id);
                            Workflows.Remove(changedWorkflow);
                            Logger.InfoFormat("A change in the definition file {0} of workflow {1} has been detected. The workflow will be reloaded.", changedWorkflow.WorkflowFilePath, changedWorkflow.Name);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error("Error during workflow reload", e);
                }

                var reloaded = LoadWorkflowFromFile(args.FullPath);
                if (reloaded != null)
                {
                    var duplicateId = Workflows.SingleOrDefault(wf => wf.Id == reloaded.Id);
                    if (duplicateId != null)
                    {
                        Logger.ErrorFormat(
                            "An error occured while loading the workflow : {0}. The workflow Id {1} is already assgined in {2}",
                            args.FullPath, reloaded.Id, duplicateId.WorkflowFilePath);
                    }
                    else
                    {
                        Workflows.Add(reloaded);
                        ScheduleWorkflow(reloaded);
                    }
                }
            };
        }
Beispiel #21
0
        public void ApplyEvent(IEvent @event)
        {
            switch (@event)
            {
            case AppCreated e:
            {
                Roles = Roles.CreateDefaults(e.Name);

                SimpleMapper.Map(e, this);

                break;
            }

            case AppUpdated e:
            {
                SimpleMapper.Map(e, this);

                break;
            }

            case AppImageUploaded e:
            {
                Image = e.Image;

                break;
            }

            case AppImageRemoved _:
            {
                Image = null;

                break;
            }

            case AppPlanChanged e:
            {
                Plan = AppPlan.Build(e.Actor, e.PlanId);

                break;
            }

            case AppPlanReset _:
            {
                Plan = null;

                break;
            }

            case AppContributorAssigned e:
            {
                Contributors = Contributors.Assign(e.ContributorId, e.Role);

                break;
            }

            case AppContributorRemoved e:
            {
                Contributors = Contributors.Remove(e.ContributorId);

                break;
            }

            case AppClientAttached e:
            {
                Clients = Clients.Add(e.Id, e.Secret);

                break;
            }

            case AppClientUpdated e:
            {
                Clients = Clients.Update(e.Id, e.Role);

                break;
            }

            case AppClientRenamed e:
            {
                Clients = Clients.Rename(e.Id, e.Name);

                break;
            }

            case AppClientRevoked e:
            {
                Clients = Clients.Revoke(e.Id);

                break;
            }

            case AppWorkflowAdded e:
            {
                Workflows = Workflows.Add(e.WorkflowId, e.Name);

                break;
            }

            case AppWorkflowUpdated e:
            {
                Workflows = Workflows.Update(e.WorkflowId, e.Workflow);

                break;
            }

            case AppWorkflowDeleted e:
            {
                Workflows = Workflows.Remove(e.WorkflowId);

                break;
            }

            case AppPatternAdded e:
            {
                Patterns = Patterns.Add(e.PatternId, e.Name, e.Pattern, e.Message);

                break;
            }

            case AppPatternDeleted e:
            {
                Patterns = Patterns.Remove(e.PatternId);

                break;
            }

            case AppPatternUpdated e:
            {
                Patterns = Patterns.Update(e.PatternId, e.Name, e.Pattern, e.Message);

                break;
            }

            case AppRoleAdded e:
            {
                Roles = Roles.Add(e.Name);

                break;
            }

            case AppRoleDeleted e:
            {
                Roles = Roles.Remove(e.Name);

                break;
            }

            case AppRoleUpdated e:
            {
                Roles = Roles.Update(e.Name, e.Permissions.Prefix(Name));

                break;
            }

            case AppLanguageAdded e:
            {
                LanguagesConfig = LanguagesConfig.Set(e.Language);

                break;
            }

            case AppLanguageRemoved e:
            {
                LanguagesConfig = LanguagesConfig.Remove(e.Language);

                break;
            }

            case AppLanguageUpdated e:
            {
                LanguagesConfig = LanguagesConfig.Set(e.Language, e.IsOptional, e.Fallback);

                if (e.IsMaster)
                {
                    LanguagesConfig = LanguagesConfig.MakeMaster(e.Language);
                }

                break;
            }

            case AppArchived _:
            {
                Plan = null;

                IsArchived = true;

                break;
            }
            }
        }
Beispiel #22
0
 protected void On(AppWorkflowAdded @event)
 {
     Workflows = Workflows.Add(@event.WorkflowId, @event.Name);
 }
Beispiel #23
0
        /// <summary>
        /// Saves a workflow in the database.
        /// </summary>
        /// <param name="xml">XML of the workflow.</param>
        /// <returns>Workflow db id.</returns>
        public int SaveWorkflow(string xml)
        {
            try
            {
                using (var xmlReader = XmlReader.Create(new StringReader(xml)))
                {
                    XmlNamespaceManager xmlNamespaceManager = null;
                    var xmlNameTable = xmlReader.NameTable;
                    if (xmlNameTable != null)
                    {
                        xmlNamespaceManager = new XmlNamespaceManager(xmlNameTable);
                        xmlNamespaceManager.AddNamespace("wf", "urn:wexflow-schema");
                    }

                    var xdoc     = XDocument.Parse(xml);
                    var id       = int.Parse(xdoc.XPathSelectElement("/wf:Workflow", xmlNamespaceManager).Attribute("id").Value);
                    var workflow = Workflows.FirstOrDefault(w => w.Id == id);

                    if (workflow == null) // insert
                    {
                        int dbId = Database.InsertWorkflow(new Db.Workflow {
                            Xml = xml
                        });
                        var wfFromDb    = Database.GetWorkflow(dbId);
                        var newWorkflow = LoadWorkflowFromDatabase(wfFromDb);

                        Logger.InfoFormat("New workflow {0} has been created. The workflow will be loaded.", newWorkflow.Name);
                        Workflows.Add(newWorkflow);
                        ScheduleWorkflow(newWorkflow);
                        return(dbId);
                    }
                    else // update
                    {
                        var workflowFromDb = Database.GetWorkflow(workflow.DbId);
                        workflowFromDb.Xml = xml;
                        Database.UpdateWorkflow(workflowFromDb);

                        var changedWorkflow = Workflows.SingleOrDefault(wf => wf.DbId == workflowFromDb.Id);

                        if (changedWorkflow != null)
                        {
                            changedWorkflow.Stop();

                            StopCronJobs(changedWorkflow.Id);
                            Workflows.Remove(changedWorkflow);
                            Logger.InfoFormat("A change in the workflow {0} has been detected. The workflow will be reloaded.", changedWorkflow.Name);

                            var updatedWorkflow = LoadWorkflowFromDatabase(workflowFromDb);
                            Workflows.Add(updatedWorkflow);
                            ScheduleWorkflow(updatedWorkflow);

                            return(changedWorkflow.DbId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("Error while saving a workflow: {0}", e.Message);
            }

            return(-1);
        }