/// <summary>
        /// Creates a data trigger view model.
        /// </summary>
        /// <param name="trigger">The trigger.</param>
        /// <param name="parentViewModel">The parent view model.</param>
        /// <returns>The <see cref="IDataTriggerViewModel" />.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// trigger
        /// or
        /// parentViewModel
        /// </exception>
        /// <exception cref="System.NotSupportedException"></exception>
        /// <exception cref="ArgumentNullException">The <paramref name="trigger" /> parameter is null.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="parentViewModel" /> parameter is null.</exception>
        /// <exception cref="NotSupportedException">The trigger type is not supported.</exception>
        public IDataTriggerViewModel CreateViewModel(ProcessDataTriggerEdit trigger, IProcessDataTriggersViewModel parentViewModel)
        {
            if (trigger == null)
                throw new ArgumentNullException("trigger");

            if (parentViewModel == null)
                throw new ArgumentNullException("parentViewModel");

            switch (trigger.TriggerType)
            {
                case DataTriggerTypes.Process:
                    {
                        var viewModel = ProcessTriggerViewModelFactory.CreateExport().Value;
                        viewModel.Initialize(trigger, parentViewModel);

                        return viewModel;
                    }

                case DataTriggerTypes.StoredProcedure:
                    {
                        var viewModel = StoredProcedureTriggerViewModelFactory.CreateExport().Value;
                        viewModel.Initialize(trigger, parentViewModel);

                        return viewModel;
                    }

                default:
                    throw new NotSupportedException(string.Format("Trigger type \"{0}\" is not supported.", trigger.TriggerType));
            }
        }
        /// <summary>
        /// Creates a data trigger type selector view model.
        /// </summary>
        /// <param name="trigger">The trigger.</param>
        /// <param name="parentViewModel">The parent view model.</param>
        /// <returns>The <see cref="IDataTriggerTypeSelectorViewModel" />.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// trigger
        /// or
        /// parentViewModel
        /// </exception>
        /// <exception cref="ArgumentNullException">The <paramref name="trigger" /> parameter is null.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="parentViewModel" /> parameter is null.</exception>
        public IDataTriggerTypeSelectorViewModel CreateViewModel(ProcessDataTriggerEdit trigger, IProcessDataTriggersViewModel parentViewModel)
        {
            if (trigger == null)
                throw new ArgumentNullException("trigger");

            if (parentViewModel == null)
                throw new ArgumentNullException("parentViewModel");

            var viewModel = DataTriggerTypeSelectorFactory.CreateExport().Value;
            viewModel.Initialize(trigger, parentViewModel);

            return viewModel;
        }
        /// <summary>
        /// Opens the data trigger field mapping designer window.
        /// </summary>
        /// <param name="parentWindow">The parent window.</param>
        /// <param name="sourceProcess">The process.</param>
        /// <param name="trigger">The trigger.</param>
        /// <param name="saveAction">The save action.</param>
        /// <param name="cancelAction">The cancel action.</param>
        /// <param name="removeAction">The remove action.</param>
        public async void EditExpression(
            ITopLevelWindow parentWindow,
            IProcessEdit sourceProcess,
            ProcessDataTriggerEdit trigger,
            Action saveAction,
            Action cancelAction,
            Action removeAction)
        {
            SaveAction = saveAction;
            CancelAction = cancelAction;
            RemoveAction = removeAction;

            KeyFieldsEnabled = false;
            ProcessEdit = sourceProcess;

            ExpressionDesigner.LoadFromExpressionObjects(new List<IExpressionObjectBase>());

            if (string.IsNullOrEmpty(trigger.ProcessToModifySystemName))
            {
                PopupFactory.NotifyFailure("Process to modify not found. Please select a process and try again.");
                CancelCommand.Execute(null);
                return;
            }

            ProcessInfo destinationProcess;
            try
            {
                WindowManager.Value.ShowStatus(new Status { IsBusy = true });
                try
                {
                    destinationProcess = await ProcessInfo.GetProcessAsync(trigger.ProcessToModifySystemName);
                }
                finally
                {
                    WindowManager.Value.ShowStatus(new Status());
                }
            }
            catch (Exception ex)
            {
                PopupFactory.NotifyFailure(ex);
                CancelCommand.Execute(null);
                return;
            }

            LoadExpressionItems(sourceProcess, destinationProcess, trigger);

            _itemHashes = ExpressionDesigner.Diagram.Items.Select(x => x.GetHashCode()).ToList();
            WindowManager.Value.ShowChildWindow(parentWindow, this);
        }
 private static void Static(WeakEventListener<StoredProcedureDataTriggerViewModel, ProcessDataTriggerEdit, PropertyChangedEventArgs> listener, ProcessDataTriggerEdit source)
 {
     source.PropertyChanged -= listener.OnEvent;
 }
        /// <summary>
        /// Creates the property changed listener.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns>The weak event listener.</returns>
        private WeakEventListener<StoredProcedureDataTriggerViewModel, ProcessDataTriggerEdit, PropertyChangedEventArgs> CreatePropertyChangedListener(ProcessDataTriggerEdit model)
        {
            var listener = new WeakEventListener<StoredProcedureDataTriggerViewModel, ProcessDataTriggerEdit, PropertyChangedEventArgs>(this, model);
            model.PropertyChanged += listener.OnEvent;
            listener.OnEventAction = OnModelPropertyChanged;
            listener.OnDetachAction = Static;

            return listener;
        }
        /// <summary>
        /// Initializes the view model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="parentViewModel">The parent view model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="model" /> parameter is null.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="parentViewModel" /> parameter is null.</exception>
        public void Initialize(ProcessDataTriggerEdit model, IProcessDataTriggersViewModel parentViewModel)
        {
            if (model == null)
                throw new ArgumentNullException("model");

            if (parentViewModel == null)
                throw new ArgumentNullException("parentViewModel");

            ParentViewModel = parentViewModel;
            Model = model;
            RuntimeDatabaseProcedures = ParentViewModel.UnitOfWork != null ? ParentViewModel.UnitOfWork.RuntimeDatabaseProcedures : null;
        }
        /// <summary>
        /// Loads the expression items.
        /// </summary>
        /// <param name="sourceProcess">The source process.</param>
        /// <param name="destinationProcess">The destination process.</param>
        /// <param name="trigger">The trigger.</param>
        private async void LoadExpressionItems(
            IProcessEdit sourceProcess,
            ProcessInfo destinationProcess,
            ProcessDataTriggerEdit trigger)
        {
            WindowManager.Value.ShowStatus(new Status { IsBusy = true });

            var expressions = new List<IExpressionObjectBase>();
            var newExpressions = new List<IExpressionObjectBase>();

            var syncContext = new NotifyClientAction(
                () =>
                    {
                        ExpressionDesigner.LoadFromExpressionObjects(expressions);
                        IsSaveable = IsTestable();
                        WindowManager.Value.ShowStatus(new Status());
                    });

            syncContext.OperationStarted();

            newExpressions.Add(
                CreateSourceItem(
                    sourceProcess,
                    DataTriggerMappingExpressionNames.SourceItem,
                    string.Format("{0} (source)", sourceProcess.Name),
                    SourceItemObjectName));

            if (trigger.ModificationType != DataTriggerModificationType.Self)
                newExpressions.Add(
                    CreateSourceItem(
                        destinationProcess,
                        DataTriggerMappingExpressionNames.SourceToModifyItem,
                        string.Format("{0} (old)", destinationProcess.Name),
                        ModifiedItemObjectName));

            newExpressions.Add(CreateUserInfoSourceItem(DataTriggerMappingExpressionNames.UserInfo));

            try
            {
                var systemParameters = await CreateSystemParametersItemAsync(DataTriggerMappingExpressionNames.SystemParameters);
                if (systemParameters != null)
                {
                    newExpressions.Add(systemParameters);
                }
            }
            catch (DataPortalException)
            {
            }

            newExpressions.Add(CreateDestinationItem(destinationProcess, DataTriggerMappingExpressionNames.DestinationItem, destinationProcess.Name));

            UpdatePositions(newExpressions);

            if (!string.IsNullOrWhiteSpace(trigger.ModificationMapping))
            {
                try
                {
                    var expressionsContainer = Serializer.Deserialize(trigger.ModificationMapping);
                    expressions.AddRange(expressionsContainer.Expressions);
                }
                catch
                {
                    // Do nothing, new expressions will be used.
                }
            }

            UpdateStateList(sourceProcess);

            UpdateStoredExpressions(expressions, newExpressions, syncContext);
            syncContext.OperationCompleted();
        }
        /// <summary>
        /// Opens the data trigger field mapping designer window.
        /// </summary>
        /// <param name="parentWindow">The parent window.</param>
        /// <param name="process">The process.</param>
        /// <param name="trigger">The trigger.</param>
        /// <param name="fieldMapping">The field mapping.</param>
        /// <param name="saveAction">The save action.</param>
        /// <param name="cancelAction">The cancel action.</param>
        /// <param name="removeAction">The remove action.</param>
        public void EditExpression(
            ITopLevelWindow parentWindow,
            IProcessEdit process,
            ProcessDataTriggerEdit trigger,
            DataTriggerFieldMappingEdit fieldMapping,
            Action saveAction,
            Action cancelAction,
            Action removeAction)
        {
            SaveAction = saveAction;
            CancelAction = cancelAction;
            RemoveAction = removeAction;

            ProcessEdit = process;
            KeyFieldsEnabled = fieldMapping.ModificationType != DataTriggerModificationType.Link
                               && fieldMapping.ModificationType != DataTriggerModificationType.Unlink;

            ExpressionDesigner.LoadFromExpressionObjects(new List<IExpressionObjectBase>());

            var criteria = new DataTriggerListFieldsMappingCriteria
                               {
                                   ModifiedProcessSystemName = trigger.ProcessToModifySystemName,
                                   DestinationFieldSystemName = fieldMapping.DestinationFieldSystemName
                               };

            var processFields = process.GetAllFields().ToArray();

            if (fieldMapping.ModificationType == DataTriggerModificationType.Link || fieldMapping.ModificationType == DataTriggerModificationType.Unlink)
            {
                if (string.IsNullOrEmpty(fieldMapping.SourceDataProcessName))
                {
                    PopupFactory.NotifyFailure("Source field is invalid. Please select a valid source field and try again.");
                    CancelCommand.Execute(null);
                    return;
                }

                criteria.SourceDataProcessName = fieldMapping.SourceDataProcessName;
            }
            else
            {
                foreach (var dataSource in fieldMapping.DataSources)
                {
                    var sourceField = processFields.FirstOrDefault(f => f.SystemName == dataSource.SourceFieldSystemName);

                    if (sourceField == null)
                    {
                        PopupFactory.NotifyFailure("Source field not found. Please select a valid source field and try again.");
                        CancelCommand.Execute(null);
                        return;
                    }

                    var requiredStep = (CrossRefRequiredStepEdit)sourceField.StepList.FirstOrDefault(s => s is CrossRefRequiredStepEdit);

                    if (requiredStep == null || !requiredStep.CrossRefProcessId.HasValue)
                    {
                        PopupFactory.NotifyFailure("Source field is invalid. Please select a valid source field and try again.");
                        CancelCommand.Execute(null);
                        return;
                    }

                    criteria.DataSourcesCriteria.Add(
                        new DataTriggerFieldMappingDataSourceCriteria
                        {
                            SourceName = dataSource.Name,
                            PublishedProcessId = requiredStep.CrossRefProcessId.Value,
                            SourceFieldName = sourceField.Name,
                            PropertyPath = dataSource.GetPropertyPath()
                        });
                }
            }

            WindowManager.Value.ShowStatus(new Status { IsBusy = true });

            DataTriggerMappingDataRetriever.GetDataTriggerMappingDataRetriever(
                criteria,
                result =>
                    {
                        WindowManager.Value.ShowStatus(new Status());
                        if (result.Error != null)
                        {
                            PopupFactory.NotifyFailure(result.Error);
                            CancelCommand.Execute(null);
                            return;
                        }

                        LoadExpressionItems(
                            process,
                            result.Object.DataSources,
                            result.Object.SourceDataProcess,
                            result.Object.DestinationListField,
                            result.Object.DestinationProcess,
                            fieldMapping);

                        _itemHashes = ExpressionDesigner.Diagram.Items.Select(x => x.GetHashCode()).ToList();

                        WindowManager.Value.ShowChildWindow(parentWindow, this);
                    });
        }
        /// <summary>
        /// Initializes the current <see cref="ProcessDataTriggerViewModel"/>.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="parent">The parent view model.</param>
        public void Initialize(ProcessDataTriggerEdit model, IProcessDataTriggersViewModel parent)
        {
            if (model == null)
                throw new ArgumentNullException("model");

            if (parent == null)
                throw new ArgumentNullException("parent");

            ParentViewModel = parent;
            Model = model;
            _processList = parent.PublishedProcesses.Where(CanIncludeInProcessToModifyList).ToList();
            _processToModify = _processList.FirstOrDefault(p => p.SystemName == Model.ProcessToModifySystemName);

            if (_processToModify == null)
            {
                Model.ProcessToModifySystemName = null;
            }
        }
        /// <summary>
        /// Initializes the view model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="parentViewModel">The parent view model.</param>
        /// <exception cref="System.ArgumentNullException">
        /// model
        /// or
        /// parentViewModel
        /// </exception>
        /// <exception cref="ArgumentNullException">The <paramref name="model" /> parameter is null.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="parentViewModel" /> parameter is null.</exception>
        public void Initialize(ProcessDataTriggerEdit model, IProcessDataTriggersViewModel parentViewModel)
        {
            if (model == null)
                throw new ArgumentNullException("model");

            if (parentViewModel == null)
                throw new ArgumentNullException("parentViewModel");

            ParentViewModel = parentViewModel;
            Model = model;

            _triggerType = Model.TriggerType;
            RaisePropertyChanged(() => TriggerType);
            TriggerViewModel = TriggerViewModelFactory.CreateViewModel(Model, ParentViewModel);
        }