diff --git a/Ginger/Ginger/SolutionWindows/TreeViewItems/SharedActivitiesGroupTreeItem.cs b/Ginger/Ginger/SolutionWindows/TreeViewItems/SharedActivitiesGroupTreeItem.cs index b7bb80d453..6f402ea92d 100644 --- a/Ginger/Ginger/SolutionWindows/TreeViewItems/SharedActivitiesGroupTreeItem.cs +++ b/Ginger/Ginger/SolutionWindows/TreeViewItems/SharedActivitiesGroupTreeItem.cs @@ -128,16 +128,20 @@ private void ExportBPMN(object sender, RoutedEventArgs e) { Reporter.ToStatus(eStatusMsgKey.ExportingToBPMNFile); string xml = CreateBPMNXMLForActivitiesGroup(mActivitiesGroup); - string filePath = SaveBPMNXMLFile($"{mActivitiesGroup.Name}.bpmn", xml); + string filePath = SaveBPMNXMLFile(filename: mActivitiesGroup.Name, xml); string solutionRelativeFilePath = WorkSpace.Instance.SolutionRepository.ConvertFullPathToBeRelative(filePath); Reporter.ToUser(eUserMsgKey.ExportToBPMNSuccessful, solutionRelativeFilePath); } catch (Exception ex) { - if (ex is BPMNExportException) + if (ex is BPMNConversionException) { Reporter.ToUser(eUserMsgKey.GingerEntityToBPMNConversionError, ex.Message); } + else + { + Reporter.ToUser(eUserMsgKey.GingerEntityToBPMNConversionError, "Unexpected Error, check logs for more details."); + } Reporter.ToLog(eLogLevel.ERROR, "Error occurred while exporting BPMN", ex); } finally @@ -149,8 +153,8 @@ private void ExportBPMN(object sender, RoutedEventArgs e) private string CreateBPMNXMLForActivitiesGroup(ActivitiesGroup activitiesGroup) { Reporter.ToLog(eLogLevel.INFO, $"Creating BPMN XML for activities group {activitiesGroup.Name}"); - ActivitiesGroupToBPMNConverter activitiesGroupToBPMNConverter = new(); - Collaboration collaboration = activitiesGroupToBPMNConverter.Convert(activitiesGroup); + ActivitiesGroupToBPMNConverter activitiesGroupToBPMNConverter = new(activitiesGroup); + Collaboration collaboration = activitiesGroupToBPMNConverter.Convert(); BPMNXMLSerializer serializer = new(); string xml = serializer.Serialize(collaboration); return xml; diff --git a/Ginger/GingerCoreNET/BPMN/ActivitiesGroupToBPMNConverter.cs b/Ginger/GingerCoreNET/BPMN/ActivitiesGroupToBPMNConverter.cs index e9050ed41e..aa3aed8081 100644 --- a/Ginger/GingerCoreNET/BPMN/ActivitiesGroupToBPMNConverter.cs +++ b/Ginger/GingerCoreNET/BPMN/ActivitiesGroupToBPMNConverter.cs @@ -37,265 +37,465 @@ namespace Amdocs.Ginger.CoreNET.BPMN /// public sealed class ActivitiesGroupToBPMNConverter { + private readonly ActivitiesGroup _activityGroup; + private readonly ISolutionFacadeForBPMN _solutionFacade; + + public ActivitiesGroupToBPMNConverter(ActivitiesGroup activityGroup) : this(activityGroup, new WorkSpaceToSolutionFacadeAdapter(WorkSpace.Instance)) { } + + /// + /// Create a new . + /// + /// to be converted. + /// A facade to expose solution data. + public ActivitiesGroupToBPMNConverter(ActivitiesGroup activityGroup, ISolutionFacadeForBPMN solutionFacade) + { + ValidateConstructorArgs(activityGroup, solutionFacade); + _activityGroup = activityGroup; + _solutionFacade = solutionFacade; + } + + /// + /// Validate constructor arguments before assigning them to member variables. + /// + /// Constrcutor argument + /// Constructor argument + /// If or is null. + private void ValidateConstructorArgs(ActivitiesGroup activityGroup, ISolutionFacadeForBPMN solutionFacade) + { + if(activityGroup == null) + { + throw new ArgumentNullException(nameof(activityGroup)); + } + if(solutionFacade == null) + { + throw new ArgumentNullException(nameof(solutionFacade)); + } + } + /// /// Convert to a BPMN . /// - /// to convert. /// BPMN . - public Collaboration Convert(ActivitiesGroup activityGroup) + public Collaboration Convert() { - AttachIdentifiersToActivities(activityGroup.ActivitiesIdentifiers); - IEnumerable activitiesInActivityGroup = GetActivitiesFromActivityGroup(activityGroup); - Activity? firstActivity = activitiesInActivityGroup.FirstOrDefault(activity => activity.Active); - if (firstActivity == null) + AttachIdentifiersToActivities(); + + Collaboration collaboration = CreateCollaboration(); + + IEnumerable activities = GetActivities(); + + Activity firstActivity = activities.First(); + IFlowSource previousFlowSource = AddStartEventForActivity(collaboration, firstActivity); + + foreach (Activity activity in activities) { - throw new BPMNExportException($"No {GingerDicser.GetTermResValue(eTermResKey.Activity)} found, make sure all the {GingerDicser.GetTermResValue(eTermResKey.Activity)} are not in-active."); + previousFlowSource = AddTasksForActivity(collaboration, activity, previousFlowSource); } - TargetBase? targetAppForSystemRef; - if (IsWebServicesActivity(firstActivity)) + Activity lastActivity = activities.Last(); + AddEndEventForActivity(collaboration, lastActivity, previousFlowSource); + + return collaboration; + } + + /// + /// Attach ActivityGroup's ActivityIdentifiers to their relevant Activities from SharedRepository + /// + private void AttachIdentifiersToActivities() + { + foreach (ActivityIdentifiers identifier in _activityGroup.ActivitiesIdentifiers) { - Consumer consumer = GetConsumerForActivity(firstActivity); - targetAppForSystemRef = GetTargetAppFromConsumer(consumer); + identifier.IdentifiedActivity = GetActivityFromSharedRepositoryByIdentifier(identifier); + + if (identifier.IdentifiedActivity == null) + { + identifier.ExistInRepository = false; + } } - else + } + + + private Activity? GetActivityFromSharedRepositoryByIdentifier(ActivityIdentifiers activityIdentifier) + { + ObservableList activitiesInRepository = _solutionFacade.GetActivitiesFromSharedRepository(); + + Activity? activityInRepository = activitiesInRepository + .FirstOrDefault(activity => + activity.Guid == activityIdentifier.ActivityGuid && + string.Equals(activity.ActivityName, activityIdentifier.ActivityName)); + + if (activityInRepository == null) + { + activityInRepository = activitiesInRepository + .FirstOrDefault(x => + x.Guid == activityIdentifier.ActivityGuid); + } + + if (activityInRepository == null) { - targetAppForSystemRef = GetTargetAppFromTargetAppName(firstActivity.TargetApplication); + activityInRepository = activitiesInRepository + .FirstOrDefault(x => + string.Equals(x.ActivityName, activityIdentifier.ActivityName)); } - if(targetAppForSystemRef == null) + return activityInRepository; + } + + /// + /// Checks whether the given is of WebServices platform or not. + /// + /// to check the platform of. + /// if the given is of WebServices platform, otherwise. + /// If no is found for the given target application name. + private bool IsWebServicesActivity(Activity activity) + { + IEnumerable applicationPlatforms = _solutionFacade.GetApplicationPlatforms(); + ApplicationPlatform? activityAppPlatform = applicationPlatforms.FirstOrDefault(platform => string.Equals(platform.AppName, activity.TargetApplication)); + if (activityAppPlatform == null) { - throw new BPMNExportException($"No suitable {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} found for Collaboration System Ref."); + throw new BPMNConversionException($"No Application Platform found for {GingerDicser.GetTermResValue(eTermResKey.Activity)} with {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} '{activity.TargetApplication}'."); } - Collaboration collaboration = new(activityGroup.Guid, CollaborationType.SubProcess) + return activityAppPlatform.Platform == ePlatformType.WebServices; + } + + /// + /// Get list of from which are eligible for conversion. + /// + /// List of . + /// If is empty or no is eligible for conversion. + private IEnumerable GetActivities() + { + IEnumerable activities = _activityGroup + .ActivitiesIdentifiers + .Select(identifier => identifier.IdentifiedActivity) + .Where(activity => activity != null && activity.Active); + + if(!activities.Any()) { - Name = activityGroup.Name, - SystemRef = targetAppForSystemRef.Guid.ToString(), - Description = activityGroup.Description - }; + throw new BPMNConversionException($"No eligible {GingerDicser.GetTermResValue(eTermResKey.Activity)} found for creating BPMN."); + } + return activities; + } - IEnumerable targetApps = GetTargetAppsInActivityGroup(activityGroup); + /// + /// Create new BPMN . + /// + /// Newly created BPMN . + private Collaboration CreateCollaboration() + { + IEnumerable participants = CreateParticipants(); + + Participant firstParticipant = participants.First(); - foreach (TargetBase targetApp in targetApps) + Collaboration collaboration = new(_activityGroup.Guid, CollaborationType.SubProcess) + { + Name = _activityGroup.Name, + SystemRef = firstParticipant.Guid, + Description = _activityGroup.Description + }; + + foreach (Participant participant in participants) { - Participant participant = new(targetApp.Guid) - { - Name = targetApp.Name, - SystemRef = targetApp.Guid.ToString() - }; collaboration.AddParticipant(participant); } - IFlowSource previousFlowSource; - - Participant participantForStartEvent; - if(!IsWebServicesActivity(firstActivity)) + return collaboration; + } + + /// + /// Creates list of new for all the involved systems in the . + /// + /// List of newly created . + /// If no is found. + private IEnumerable CreateParticipants() + { + List participants = new(); + IEnumerable activities = GetActivities(); + foreach (Activity activity in activities) { - participantForStartEvent = GetParticipantForTargetAppName(collaboration, firstActivity.TargetApplication); + participants.AddRange(CreateParticipantsForActivity(activity)); } - else + + if(!participants.Any()) { - Consumer firstActivityConsumer = firstActivity.ConsumerApplications[0]; - string targetAppName = GetTargetAppFromConsumer(firstActivityConsumer).Name; - participantForStartEvent = GetParticipantForTargetAppName(collaboration, targetAppName); + throw new BPMNConversionException($"No BPMN Participants (Ginger {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)}) found for creating BPMN"); } - StartEvent startEvent = participantForStartEvent.Process.AddStartEvent(name: string.Empty); - previousFlowSource = startEvent; - foreach (Activity activity in activitiesInActivityGroup) - { - if(!activity.Active) - { - continue; - } + return participants; + } - Participant activityParticipant = GetParticipantForTargetAppName(collaboration, activity.TargetApplication); - if(IsWebServicesActivity(activity)) - { - Consumer consumer = GetConsumerForActivity(activity); - string consumerAppName = GetTargetAppFromConsumer(consumer).Name; - Participant consumerParticipant = GetParticipantForTargetAppName(collaboration, consumerAppName); - Task requestSourceTask = consumerParticipant.Process.AddTask(name: $"{activity.ActivityName}_RequestSource"); - Task requestTargetTask = activityParticipant.Process.AddTask(name: $"{activity.ActivityName}_RequestTarget"); - Task responseSourceTask = activityParticipant.Process.AddTask(name: $"{activity.ActivityName}_ResponseSource"); - Task responseTargetTask = consumerParticipant.Process.AddTask(name: $"{activity.ActivityName}_ResponseTarget"); - Flow.Create(name: string.Empty, previousFlowSource, requestSourceTask); - Flow requestFlow = Flow.Create(name: $"{activity.ActivityName}_IN", requestSourceTask, requestTargetTask); - if(requestFlow is MessageFlow requestMessageFlow) - { - requestMessageFlow.MessageRef = activity.Guid.ToString().Remove(activity.Guid.ToString().Length - 2) + "aa"; - } - Flow.Create(name: string.Empty, requestTargetTask, responseSourceTask); - Flow responseFlow = Flow.Create(name: $"{activity.ActivityName}_OUT", responseSourceTask, responseTargetTask); - if(responseFlow is MessageFlow responseMessageFlow) - { - responseMessageFlow.MessageRef = activity.Guid.ToString().Remove(activity.Guid.ToString().Length - 2) + "bb"; - } - previousFlowSource = responseTargetTask; - } - else + /// + /// Creates list of new for all the involved systems in given . + /// + /// whose involved systems will be used for creating new list. + /// List of new . + private IEnumerable CreateParticipantsForActivity(Activity activity) + { + List participants = new(); + + if (IsWebServicesActivity(activity)) + { + Consumer consumer = GetActivityFirstConsumer(activity); + TargetBase consumerTargetApp = GetTargetApplicationByGuid(consumer.ConsumerGuid); + Participant participantForConsumer = new(consumerTargetApp.Guid) { - UserTask userTask = activityParticipant.Process.AddTask(guid: activity.Guid, name: activity.ActivityName); - userTask.MessageRef = activity.Guid.ToString().Remove(activity.Guid.ToString().Length - 2) + "aa"; - Flow.Create(name: string.Empty, previousFlowSource, userTask); - previousFlowSource = userTask; - } + Name = consumerTargetApp.Name, + SystemRef = consumerTargetApp.Guid.ToString() + }; + participants.Add(participantForConsumer); } - Participant lastTaskParticipant = GetParticipantForProcessId(collaboration, previousFlowSource.ProcessId); - EndEvent endEvent = lastTaskParticipant.Process.AddEndEvent(name: string.Empty, EndEventType.Termination); - Flow.Create(name: string.Empty, previousFlowSource, endEvent); + TargetBase targetApp = GetTargetApplicationByName(activity.TargetApplication); + Participant participantForTargetApp = new(targetApp.Guid) + { + Name = targetApp.Name, + SystemRef = targetApp.Guid.ToString() + }; + participants.Add(participantForTargetApp); - return collaboration; + return participants; } - private void AttachIdentifiersToActivities(IEnumerable activityIdentifiers) + /// + /// Get whose name matches the given . + /// + /// Name of the to search for. + /// with name matching the given . + /// If no is found with name matching the given . + private TargetBase GetTargetApplicationByName(string targetAppName) { - foreach (ActivityIdentifiers identifier in activityIdentifiers) + IEnumerable targetApplications = _solutionFacade.GetTargetApplications(); + TargetBase? targetApp = targetApplications.FirstOrDefault(targetApp => string.Equals(targetApp.Name, targetAppName)); + + if (targetApp == null) { - identifier.IdentifiedActivity = GetActivityFromSharedRepositoryByIdentifier(identifier); - if (identifier.IdentifiedActivity == null) - { - identifier.ExistInRepository = false; - } + throw new BPMNConversionException($"No {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} found with name '{targetAppName}'"); } + + return targetApp; } - private Consumer GetConsumerForActivity(Activity activity) + /// + /// Get whose Guid matches the given . + /// + /// Guid of the to search for. + /// with Guid matching the given . + /// If no is found with Guid matching the given . + private TargetBase GetTargetApplicationByGuid(Guid targetAppGuid) { - Consumer? consumer = activity.ConsumerApplications.FirstOrDefault(); - if (consumer == null) + IEnumerable targetApplications = _solutionFacade.GetTargetApplications(); + TargetBase? targetApp = targetApplications.FirstOrDefault(targetApp => targetApp.Guid == targetAppGuid); + + if (targetApp == null) { - throw new BPMNExportException($"Consumer not defined for {GingerDicser.GetTermResValue(eTermResKey.Activity)} '{activity.ActivityName}'."); + throw new BPMNConversionException($"No {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} found with Guid '{targetAppGuid}'"); } - return consumer; + + return targetApp; } - private IEnumerable GetTargetAppsInActivityGroup(ActivitiesGroup activityGroup) + /// + /// Get the first for the given . + /// + /// to get the Consumer of. + /// First for the given . + /// If no is found for the given . + private Consumer GetActivityFirstConsumer(Activity activity) { - IEnumerable targetAppNames = activityGroup - .ActivitiesIdentifiers - .Where(identifier => identifier.IdentifiedActivity != null) - .Select(identifier => identifier.IdentifiedActivity.TargetApplication) - .Distinct(); - - IEnumerable consumerGuids = activityGroup - .ActivitiesIdentifiers - .Where(identifier => identifier.IdentifiedActivity != null) - .SelectMany(identifier => identifier.IdentifiedActivity.ConsumerApplications) - .Select(consumer => consumer.ConsumerGuid); - - IEnumerable targetApps = WorkSpace.Instance.Solution - .GetSolutionTargetApplications() - .Where(targetApp => targetAppNames.Contains(targetApp.Name.ToString())); - - IEnumerable consumerTargetApps = WorkSpace.Instance.Solution - .GetSolutionTargetApplications() - .Where(targetApp => consumerGuids.Contains(targetApp.Guid)); - - return consumerTargetApps.Concat(targetApps).Distinct(new TargetBaseEqualityComparer()); + Consumer? firstConsumer = activity.ConsumerApplications.FirstOrDefault(); + + if (firstConsumer == null) + { + throw new BPMNConversionException($"No Consumer found for {GingerDicser.GetTermResValue(eTermResKey.Activity)} '{activity.ActivityName}'"); + } + + return firstConsumer; } - private IEnumerable GetActivitiesFromActivityGroup(ActivitiesGroup activityGroup) + /// + /// Get for the first of given . + /// + /// to get the from. + /// to get the from. + /// for the first of given . + private Participant GetConsumerParticipant(Collaboration collaboration, Activity activity) { - return - activityGroup - .ActivitiesIdentifiers - .Where(identifier => identifier.IdentifiedActivity != null) - .Select(identifier => identifier.IdentifiedActivity) - .Where(activity => activity.Active); + Consumer consumer = GetActivityFirstConsumer(activity); + Participant consumerParticipant = GetParticipantByGuid(collaboration, consumer.ConsumerGuid); + return consumerParticipant; } - private Activity? GetActivityFromSharedRepositoryByIdentifier(ActivityIdentifiers activityIdentifier) + /// + /// Get the for the target application of given . + /// + /// to get the from. + /// to get the target application from. + /// for the target application of given . + private Participant GetTargetApplicationParticipant(Collaboration collaboration, Activity activity) { - ObservableList activitiesInRepository = WorkSpace.Instance.SolutionRepository.GetAllRepositoryItems(); - - Activity? activityInRepository = activitiesInRepository - .FirstOrDefault(activity => - string.Equals(activity.ActivityName, activityIdentifier.ActivityName) && - activity.Guid == activityIdentifier.ActivityGuid); + TargetBase targetApp = GetTargetApplicationByName(activity.TargetApplication); + Participant targetAppParticipant = GetParticipantByGuid(collaboration, targetApp.Guid); + return targetAppParticipant; + } - if (activityInRepository == null) + /// + /// Add for the given . + /// + /// to add the to. + /// to create the . + /// Previous flow source to create the link with the new . + /// New which should be used to link with the next entitites. + private IFlowSource AddTasksForActivity(Collaboration collaboration, Activity activity, IFlowSource previousFlowSource) + { + if (IsWebServicesActivity(activity)) { - activityInRepository = activitiesInRepository.FirstOrDefault(x => x.Guid == activityIdentifier.ActivityGuid); + previousFlowSource = AddTasksForWebServicesActivity(collaboration, activity, previousFlowSource); } - - if (activityInRepository == null) + else { - activityInRepository = activitiesInRepository.FirstOrDefault(x => string.Equals(x.ActivityName, activityIdentifier.ActivityName)); + previousFlowSource = AddTasksForUIActivity(collaboration, activity, previousFlowSource); } - return activityInRepository; + return previousFlowSource; } - private TargetBase GetTargetAppFromConsumer(Consumer consumer) + /// + /// Get with Guid matching the given . + /// + /// to get the from. + /// Guid of the to search. + /// with Guid matching the given . + /// If no is found with Guid matching the . + private Participant GetParticipantByGuid(Collaboration collaboration, Guid participantGuid) { - IEnumerable targetApps = WorkSpace.Instance.Solution.GetSolutionTargetApplications(); - TargetBase? consumerTargetApp = targetApps.FirstOrDefault(targetApp => string.Equals(targetApp.Guid, consumer.ConsumerGuid)); - if (consumerTargetApp == null) + Participant? participant = collaboration + .Participants + .FirstOrDefault(participant => string.Equals(participant.Guid, participantGuid.ToString())); + + if (participant == null) { - throw new BPMNExportException($"No {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} found for Consumer with Guid '{consumer.ConsumerGuid}'."); + throw new BPMNConversionException($"No BPMN Participant (Ginger {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} found by Guid '{participantGuid}'"); } - return consumerTargetApp; - } - private TargetBase? GetTargetAppFromTargetAppName(string targetAppName) - { - return WorkSpace.Instance.Solution - .GetSolutionTargetApplications() - .FirstOrDefault(targetApp => string.Equals(targetApp.Name, targetAppName)); + return participant; } - private Participant GetParticipantForTargetAppName(Collaboration collaboration, string targetAppName) + /// + /// Add for the given WebServices . + /// + /// to add the to. + /// to create the for. + /// Previous flow source to create the link with the new . + /// New which should be used to link with the next entitites. + private IFlowSource AddTasksForWebServicesActivity(Collaboration collaboration, Activity activity, IFlowSource previousFlowSource) { - Participant? participant = collaboration.Participants.FirstOrDefault(participant => string.Equals(participant.Name, targetAppName)); - if(participant == null) + Participant consumerParticipant = GetConsumerParticipant(collaboration, activity); + Participant targetAppParticipant = GetTargetApplicationParticipant(collaboration, activity); + + Task requestSourceTask = consumerParticipant.Process.AddTask(name: $"{activity.ActivityName}_RequestSource"); + Task requestTargetTask = targetAppParticipant.Process.AddTask(name: $"{activity.ActivityName}_RequestTarget"); + Task responseSourceTask = targetAppParticipant.Process.AddTask(name: $"{activity.ActivityName}_ResponseSource"); + Task responseTargetTask = consumerParticipant.Process.AddTask(name: $"{activity.ActivityName}_ResponseTarget"); + + Flow.Create(name: string.Empty, previousFlowSource, requestSourceTask); + + Flow requestFlow = Flow.Create(name: $"{activity.ActivityName}_IN", requestSourceTask, requestTargetTask); + + if (requestFlow is MessageFlow requestMessageFlow) { - throw new BPMNExportException($"No BPMN Participant({GingerDicser.GetTermResValue(eTermResKey.TargetApplication)}) found for {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} name '{targetAppName}'."); + string activityGuid = activity.Guid.ToString(); + string messageRef = string.Concat(activityGuid.AsSpan(0, activityGuid.Length - 2), "aa"); + requestMessageFlow.MessageRef = messageRef; } - return participant; - } - private Participant GetParticipantForProcessId(Collaboration collaboration, string processId) - { - Participant? participant = collaboration.Participants.FirstOrDefault(participant => string.Equals(participant.Process.Id, processId)); - if(participant == null) + Flow.Create(name: string.Empty, requestTargetTask, responseSourceTask); + + Flow responseFlow = Flow.Create(name: $"{activity.ActivityName}_OUT", responseSourceTask, responseTargetTask); + + if (responseFlow is MessageFlow responseMessageFlow) { - throw new BPMNExportException($"No BPMN Participant({GingerDicser.GetTermResValue(eTermResKey.TargetApplication)}) found for process id '{processId}'."); + string activityGuid = activity.Guid.ToString(); + string messageRef = string.Concat(activityGuid.AsSpan(0, activityGuid.Length - 2), "bb"); + responseMessageFlow.MessageRef = messageRef; } - return participant; + + return responseTargetTask; } - private bool IsWebServicesActivity(Activity activity) + /// + /// Add for the given UI . + /// + /// to add the to. + /// to create the for. + /// Previous flow source to create the link with the new . + /// New which should be used to link with the next entitites. + private UserTask AddTasksForUIActivity(Collaboration collaboration, Activity activity, IFlowSource previousFlowSource) { - ApplicationPlatform? activityAppPlatform = WorkSpace.Instance.Solution - .ApplicationPlatforms - .FirstOrDefault(platform => string.Equals(platform.AppName, activity.TargetApplication)); - if(activityAppPlatform == null) + Participant participant = GetTargetApplicationParticipant(collaboration, activity); + + UserTask userTask = participant.Process.AddTask(guid: activity.Guid, name: activity.ActivityName); + + Flow.Create(name: string.Empty, previousFlowSource, userTask); + + string activityGuid = activity.Guid.ToString(); + string messageRef = string.Concat(activityGuid.AsSpan(0, activityGuid.Length - 2), "aa"); + userTask.MessageRef = messageRef; + + return userTask; + } + + /// + /// Add for the the given . + /// + /// to add the to. + /// to create the for. + /// Newly added . + private StartEvent AddStartEventForActivity(Collaboration collaboration, Activity activity) + { + Participant participant; + if (IsWebServicesActivity(activity)) + { + Consumer consumer = GetActivityFirstConsumer(activity); + participant = GetParticipantByGuid(collaboration, consumer.ConsumerGuid); + } + else { - throw new BPMNExportException($"No Application Platform found for Activity with {GingerDicser.GetTermResValue(eTermResKey.TargetApplication)} '{activity.TargetApplication}'."); + TargetBase targetApp = GetTargetApplicationByName(activity.TargetApplication); + participant = GetParticipantByGuid(collaboration, targetApp.Guid); } - return activityAppPlatform.Platform == ePlatformType.WebServices; + StartEvent startEvent = participant.Process.AddStartEvent(name: string.Empty); + + return startEvent; } - private class TargetBaseEqualityComparer : IEqualityComparer + /// + /// Add for the the given . + /// + /// to add the to. + /// to create the for. + /// Previous slow source to create the link with the new . + /// Newly added . + private EndEvent AddEndEventForActivity(Collaboration collaboration, Activity activity, IFlowSource previousFlowSource) { - public bool Equals(TargetBase? x, TargetBase? y) + Participant participant; + if(IsWebServicesActivity(activity)) { - return - x == null && y == null || - x != null && y != null && x.Guid == y.Guid; + Consumer consumer = GetActivityFirstConsumer(activity); + participant = GetParticipantByGuid(collaboration, consumer.ConsumerGuid); } - - public int GetHashCode([DisallowNull] TargetBase obj) + else { - HashCode hashCode = new(); - hashCode.Add(obj.Guid); - return hashCode.ToHashCode(); + TargetBase targetApp = GetTargetApplicationByName(activity.TargetApplication); + participant = GetParticipantByGuid(collaboration, targetApp.Guid); } + + EndEvent endEvent = participant.Process.AddEndEvent(name: string.Empty); + Flow.Create(name: string.Empty, previousFlowSource, endEvent); + + return endEvent; } } } \ No newline at end of file diff --git a/Ginger/GingerCoreNET/BPMN/BPMNExportException.cs b/Ginger/GingerCoreNET/BPMN/BPMNConversionException.cs similarity index 56% rename from Ginger/GingerCoreNET/BPMN/BPMNExportException.cs rename to Ginger/GingerCoreNET/BPMN/BPMNConversionException.cs index 0c23d2e572..4b4cdffb0a 100644 --- a/Ginger/GingerCoreNET/BPMN/BPMNExportException.cs +++ b/Ginger/GingerCoreNET/BPMN/BPMNConversionException.cs @@ -6,8 +6,8 @@ namespace Amdocs.Ginger.CoreNET.BPMN { - public sealed class BPMNExportException : Exception + public sealed class BPMNConversionException : Exception { - public BPMNExportException(string message) : base(message) { } + public BPMNConversionException(string message) : base(message) { } } } diff --git a/Ginger/GingerCoreNET/BPMN/Collaboration.cs b/Ginger/GingerCoreNET/BPMN/Collaboration.cs index 4354552e75..40bfd25297 100644 --- a/Ginger/GingerCoreNET/BPMN/Collaboration.cs +++ b/Ginger/GingerCoreNET/BPMN/Collaboration.cs @@ -55,7 +55,11 @@ public Collaboration(string guid, CollaborationType collaborationType) public void AddParticipant(Participant participant) { - _participants.Add(participant); + bool isUnique = _participants.All(p => !string.Equals(p.Guid, participant.Guid)); + if (isUnique) + { + _participants.Add(participant); + } } public IEnumerable GetMessageFlows() diff --git a/Ginger/GingerCoreNET/BPMN/IFlowSource.cs b/Ginger/GingerCoreNET/BPMN/IFlowSource.cs index 5dd21181f9..d61014cda3 100644 --- a/Ginger/GingerCoreNET/BPMN/IFlowSource.cs +++ b/Ginger/GingerCoreNET/BPMN/IFlowSource.cs @@ -20,7 +20,7 @@ limitations under the License. namespace Amdocs.Ginger.CoreNET.BPMN { - public interface IFlowSource : IProcessEntitiy + public interface IFlowSource : IProcessEntity { public FlowCollection OutgoingFlows { get; } } diff --git a/Ginger/GingerCoreNET/BPMN/IFlowTarget.cs b/Ginger/GingerCoreNET/BPMN/IFlowTarget.cs index d8be4ef29e..ae27dad8b5 100644 --- a/Ginger/GingerCoreNET/BPMN/IFlowTarget.cs +++ b/Ginger/GingerCoreNET/BPMN/IFlowTarget.cs @@ -20,7 +20,7 @@ limitations under the License. namespace Amdocs.Ginger.CoreNET.BPMN { - public interface IFlowTarget : IProcessEntitiy + public interface IFlowTarget : IProcessEntity { public FlowCollection IncomingFlows { get; } } diff --git a/Ginger/GingerCoreNET/BPMN/IProcessEntitiy.cs b/Ginger/GingerCoreNET/BPMN/IProcessEntity.cs similarity index 95% rename from Ginger/GingerCoreNET/BPMN/IProcessEntitiy.cs rename to Ginger/GingerCoreNET/BPMN/IProcessEntity.cs index ac2aa963a8..4ace011b48 100644 --- a/Ginger/GingerCoreNET/BPMN/IProcessEntitiy.cs +++ b/Ginger/GingerCoreNET/BPMN/IProcessEntity.cs @@ -20,7 +20,7 @@ limitations under the License. namespace Amdocs.Ginger.CoreNET.BPMN { - public interface IProcessEntitiy + public interface IProcessEntity { public string Id { get; } public string ProcessId { get; } diff --git a/Ginger/GingerCoreNET/BPMN/ISolutionFacadeForBPMN.cs b/Ginger/GingerCoreNET/BPMN/ISolutionFacadeForBPMN.cs new file mode 100644 index 0000000000..42925f4d2c --- /dev/null +++ b/Ginger/GingerCoreNET/BPMN/ISolutionFacadeForBPMN.cs @@ -0,0 +1,36 @@ +using Amdocs.Ginger.Common; +using Amdocs.Ginger.Common.Repository; +using GingerCore; +using GingerCoreNET.SolutionRepositoryLib.RepositoryObjectsLib.PlatformsLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Amdocs.Ginger.CoreNET.BPMN +{ + /// + /// A facade to expose solution data for BPMN related operations. + /// + public interface ISolutionFacadeForBPMN + { + /// + /// Get all from SharedRepository. + /// + /// + public ObservableList GetActivitiesFromSharedRepository(); + + /// + /// Get all from SharedRepository. + /// + /// + public ObservableList GetApplicationPlatforms(); + + /// + /// Get all from SharedRepository. + /// + /// + public ObservableList GetTargetApplications(); + } +} diff --git a/Ginger/GingerCoreNET/BPMN/WorkSpaceToSolutionFacadeAdapter.cs b/Ginger/GingerCoreNET/BPMN/WorkSpaceToSolutionFacadeAdapter.cs new file mode 100644 index 0000000000..c1c10efd8e --- /dev/null +++ b/Ginger/GingerCoreNET/BPMN/WorkSpaceToSolutionFacadeAdapter.cs @@ -0,0 +1,38 @@ +using amdocs.ginger.GingerCoreNET; +using Amdocs.Ginger.Common; +using Amdocs.Ginger.Common.Repository; +using GingerCore; +using GingerCoreNET.SolutionRepositoryLib.RepositoryObjectsLib.PlatformsLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Amdocs.Ginger.CoreNET.BPMN +{ + public sealed class WorkSpaceToSolutionFacadeAdapter : ISolutionFacadeForBPMN + { + private readonly WorkSpace _workspace; + + public WorkSpaceToSolutionFacadeAdapter(WorkSpace workspace) + { + _workspace = workspace; + } + + public ObservableList GetActivitiesFromSharedRepository() + { + return _workspace.SolutionRepository.GetAllRepositoryItems(); + } + + public ObservableList GetApplicationPlatforms() + { + return _workspace.Solution.ApplicationPlatforms; + } + + public ObservableList GetTargetApplications() + { + return _workspace.Solution.GetSolutionTargetApplications(); + } + } +} diff --git a/Ginger/GingerCoreNETUnitTest/BPMN/ActivitiesGroupToBPMNTests.cs b/Ginger/GingerCoreNETUnitTest/BPMN/ActivitiesGroupToBPMNTests.cs new file mode 100644 index 0000000000..0650dee5d9 --- /dev/null +++ b/Ginger/GingerCoreNETUnitTest/BPMN/ActivitiesGroupToBPMNTests.cs @@ -0,0 +1,233 @@ +using amdocs.ginger.GingerCoreNET; +using Amdocs.Ginger.Common; +using Amdocs.Ginger.Common.Repository; +using Amdocs.Ginger.CoreNET.BPMN; +using Amdocs.Ginger.Repository; +using Applitools.Utils; +using DocumentFormat.OpenXml.Wordprocessing; +using GingerCore; +using GingerCore.Activities; +using GingerCore.Platforms; +using GingerCoreNET.SolutionRepositoryLib.RepositoryObjectsLib.PlatformsLib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GingerCoreNETUnitTest.BPMN +{ + [TestClass] + public sealed class ActivitiesGroupToBPMNTests + { + [TestMethod] + public void Convert_NullActivityGroup_ThrowsArgumentNullException() + { + ActivitiesGroup activityGroup = null; + ISolutionFacadeForBPMN solutionFacade = new Mock().Object; + + Assert.ThrowsException(() => new ActivitiesGroupToBPMNConverter(activityGroup, solutionFacade)); + } + + [TestMethod] + public void Convert_EmptyActivitesGroup_ThrowsBPMNConversionException() + { + ActivitiesGroup activityGroup = new(); + Mock solutionFacadeMock = new(); + solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList()); + ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Assert.ThrowsException(() => converter.Convert()); + } + + [TestMethod] + public void Convert_AllInactiveActivities_ThrowsBPMNConversionException() + { + Activity inactiveActivity = new() + { + ActivityName = "Inactive Activity", + Active = false + }; + ActivitiesGroup activityGroup = new(); + activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers() + { + IdentifiedActivity = inactiveActivity + }); + Mock solutionFacadeMock = new(); + solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList() { inactiveActivity }); + ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Assert.ThrowsException(() => converter.Convert()); + } + + [TestMethod] + public void Convert_AllNonIdentifiedActivities_ThrowsBPMNConversionException() + { + ActivitiesGroup activityGroup = new(); + activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers() + { + IdentifiedActivity = null + }); + Mock solutionFacadeMock = new(); + solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList()); + ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Assert.ThrowsException(() => converter.Convert()); + } + + [TestMethod] + public void Convert_ActivityGroupWithInActiveActivities_InactiveActivitiesAreIgnored() + { + CreateActivityGroupWithActiveAndInactiveActivities(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade); + Activity inactiveActivity = activityGroup.ActivitiesIdentifiers.First(iden => !iden.IdentifiedActivity.Active).IdentifiedActivity; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Collaboration collaboration = converter.Convert(); + + Assert.IsTrue(collaboration.Participants.Any(), $"{nameof(Collaboration)} has no {nameof(Participant)}"); + Process firstParticipantProcess = collaboration.Participants.ElementAt(0).Process; + Assert.IsTrue(firstParticipantProcess.Tasks.Any(), $"First {nameof(Participant)} {nameof(Process)} is has no {nameof(Amdocs.Ginger.CoreNET.BPMN.Task)}"); + Assert.IsFalse(firstParticipantProcess.Tasks.Any(task => string.Equals(task.Guid, inactiveActivity.Guid.ToString())), $"InActive {nameof(Activity)} is not ignored"); + } + + [TestMethod] + public void Convert_ActivityGroupWithInActiveActivities_OnlyActiveActivitiesAreConverted() + { + CreateActivityGroupWithActiveAndInactiveActivities(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade); + Activity activeActivity = activityGroup.ActivitiesIdentifiers.First(iden => iden.IdentifiedActivity.Active).IdentifiedActivity; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Collaboration collaboration = converter.Convert(); + + Assert.IsTrue(collaboration.Participants.Any(), $"{nameof(Collaboration)} has no {nameof(Participant)}"); + Process firstParticipantProcess = collaboration.Participants.ElementAt(0).Process; + Assert.IsTrue(firstParticipantProcess.Tasks.Any(), $"First {nameof(Participant)} {nameof(Process)} is has no {nameof(Amdocs.Ginger.CoreNET.BPMN.Task)}"); + Assert.IsTrue(firstParticipantProcess.Tasks.Any(task => string.Equals(task.Guid, activeActivity.Guid.ToString())), $"Active {nameof(Activity)} is not converted"); + } + + private void CreateActivityGroupWithActiveAndInactiveActivities(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade) + { + ObservableList applicationPlatforms = new() + { + new ApplicationPlatform() + { + AppName = "MyWebApp", + Platform = ePlatformType.Web + }, + new ApplicationPlatform() + { + AppName = "MyWebServicesApp", + Platform = ePlatformType.WebServices + } + }; + activityGroup = new(); + Activity activeActivity = new() + { + ActivityName = "Active Activity", + TargetApplication = applicationPlatforms[0].AppName, + Active = true + }; + activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers() { IdentifiedActivity = activeActivity }); + Activity inactiveActivity = new() + { + ActivityName = "Inactive Activitiy", + TargetApplication = applicationPlatforms[1].AppName, + Active = false + }; + activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers() { IdentifiedActivity = inactiveActivity }); + Mock solutionFacadeMock = new(); + solutionFacadeMock.Setup(sf => sf.GetApplicationPlatforms()).Returns(applicationPlatforms); + solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList() { activeActivity, inactiveActivity }); + solutionFacadeMock.Setup(sf => sf.GetTargetApplications()).Returns(new ObservableList() + { + new TargetApplication() { Guid = applicationPlatforms[0].Guid, AppName = applicationPlatforms[0].AppName }, + new TargetApplication() { Guid = applicationPlatforms[1].Guid, AppName = applicationPlatforms[1].AppName } + }); + solutionFacade = solutionFacadeMock.Object; + + } + + [TestMethod] + public void Convert_ActivityWithOnlyOneWebServicesActivity_HasTargetApplicationParticipant() + { + CreateActivityGroupWithOnlyOneWebServicesActivity(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade); + TargetBase targetApp = solutionFacade.GetTargetApplications().First(ta => string.Equals(ta.Name, activityGroup.ActivitiesIdentifiers[0].IdentifiedActivity.TargetApplication)); + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Collaboration collaboration = converter.Convert(); + + Assert.IsTrue(collaboration.Participants.Any(participant => string.Equals(participant.Guid, targetApp.Guid.ToString())), $"{nameof(Participant)} for {nameof(Activity)}'s {nameof(TargetApplication)} not found"); + } + + [TestMethod] + public void Convert_ActivityWithOnlyOneWebServicesActivity_HasConsumerParticipant() + { + CreateActivityGroupWithOnlyOneWebServicesActivity(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade); + Consumer consumer = activityGroup.ActivitiesIdentifiers[0].IdentifiedActivity.ConsumerApplications[0]; + ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade); + + Collaboration collaboration = converter.Convert(); + + Assert.IsTrue(collaboration.Participants.Any(participant => string.Equals(participant.Guid, consumer.ConsumerGuid.ToString())), $"{nameof(Participant)} for {nameof(Activity)}'s {nameof(Consumer)} not found"); + } + + private void CreateActivityGroupWithOnlyOneWebServicesActivity(out ActivitiesGroup activityGroup, out ISolutionFacadeForBPMN solutionFacade) + { + Mock solutionFacadeMock = new(); + ObservableList applicationPlatforms = new() + { + new ApplicationPlatform() + { + AppName = "MyWebApp", + Platform = ePlatformType.Web + }, + new ApplicationPlatform() + { + AppName = "MyWebServices", + Platform = ePlatformType.WebServices + } + }; + ObservableList targetApplications = new() + { + new TargetApplication() + { + Guid = applicationPlatforms[0].Guid, + AppName = applicationPlatforms[0].AppName + }, + new TargetApplication() + { + Guid = applicationPlatforms[1].Guid, + AppName = applicationPlatforms[1].AppName + } + }; + activityGroup = new(); + Activity restActivity = new() + { + ActivityName = "REST Activity", + TargetApplication = targetApplications[1].Name, + Active = true, + ConsumerApplications = new ObservableList() + { + new Consumer() + { + ConsumerGuid = targetApplications[0].Guid + } + } + }; + activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers() + { + IdentifiedActivity = restActivity + }); + solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList() { restActivity }); + solutionFacadeMock.Setup(sf => sf.GetApplicationPlatforms()).Returns(applicationPlatforms); + solutionFacadeMock.Setup(sf => sf.GetTargetApplications()).Returns(targetApplications); + solutionFacade = solutionFacadeMock.Object; + + } + } +} diff --git a/Ginger/GingerCoreNETUnitTest/GingerCoreNETUnitTest.csproj b/Ginger/GingerCoreNETUnitTest/GingerCoreNETUnitTest.csproj index 2742d21073..2ccd84a939 100644 --- a/Ginger/GingerCoreNETUnitTest/GingerCoreNETUnitTest.csproj +++ b/Ginger/GingerCoreNETUnitTest/GingerCoreNETUnitTest.csproj @@ -90,6 +90,7 @@ +