Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActivityGroup to BPMN Refactoring + UnitTests #3327

Merged
merged 9 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down
546 changes: 373 additions & 173 deletions Ginger/GingerCoreNET/BPMN/ActivitiesGroupToBPMNConverter.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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) { }
}
}
6 changes: 5 additions & 1 deletion Ginger/GingerCoreNET/BPMN/Collaboration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<MessageFlow> GetMessageFlows()
Expand Down
2 changes: 1 addition & 1 deletion Ginger/GingerCoreNET/BPMN/IFlowSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
Expand Down
2 changes: 1 addition & 1 deletion Ginger/GingerCoreNET/BPMN/IFlowTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
36 changes: 36 additions & 0 deletions Ginger/GingerCoreNET/BPMN/ISolutionFacadeForBPMN.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// A facade to expose solution data for BPMN related operations.
/// </summary>
public interface ISolutionFacadeForBPMN
{
/// <summary>
/// Get all <see cref="Activity"/> from SharedRepository.
/// </summary>
/// <returns></returns>
public ObservableList<Activity> GetActivitiesFromSharedRepository();

/// <summary>
/// Get all <see cref="ApplicationPlatform"/> from SharedRepository.
/// </summary>
/// <returns></returns>
public ObservableList<ApplicationPlatform> GetApplicationPlatforms();

/// <summary>
/// Get all <see cref="TargetBase"/> from SharedRepository.
/// </summary>
/// <returns></returns>
public ObservableList<TargetBase> GetTargetApplications();
}
}
38 changes: 38 additions & 0 deletions Ginger/GingerCoreNET/BPMN/WorkSpaceToSolutionFacadeAdapter.cs
Original file line number Diff line number Diff line change
@@ -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<Activity> GetActivitiesFromSharedRepository()
{
return _workspace.SolutionRepository.GetAllRepositoryItems<Activity>();
}

public ObservableList<ApplicationPlatform> GetApplicationPlatforms()
{
return _workspace.Solution.ApplicationPlatforms;
}

public ObservableList<TargetBase> GetTargetApplications()
{
return _workspace.Solution.GetSolutionTargetApplications();
}
}
}
233 changes: 233 additions & 0 deletions Ginger/GingerCoreNETUnitTest/BPMN/ActivitiesGroupToBPMNTests.cs
Original file line number Diff line number Diff line change
@@ -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<ISolutionFacadeForBPMN>().Object;

Assert.ThrowsException<ArgumentNullException>(() => new ActivitiesGroupToBPMNConverter(activityGroup, solutionFacade));
}

[TestMethod]
public void Convert_EmptyActivitesGroup_ThrowsBPMNConversionException()
{
ActivitiesGroup activityGroup = new();
Mock<ISolutionFacadeForBPMN> solutionFacadeMock = new();
solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList<Activity>());
ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object;
ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade);

Assert.ThrowsException<BPMNConversionException>(() => 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<ISolutionFacadeForBPMN> solutionFacadeMock = new();
solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList<Activity>() { inactiveActivity });
ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object;
ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade);

Assert.ThrowsException<BPMNConversionException>(() => converter.Convert());
}

[TestMethod]
public void Convert_AllNonIdentifiedActivities_ThrowsBPMNConversionException()
{
ActivitiesGroup activityGroup = new();
activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers()
{
IdentifiedActivity = null
});
Mock<ISolutionFacadeForBPMN> solutionFacadeMock = new();
solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList<Activity>());
ISolutionFacadeForBPMN solutionFacade = solutionFacadeMock.Object;
ActivitiesGroupToBPMNConverter converter = new(activityGroup, solutionFacade);

Assert.ThrowsException<BPMNConversionException>(() => 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<ApplicationPlatform> 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<ISolutionFacadeForBPMN> solutionFacadeMock = new();
solutionFacadeMock.Setup(sf => sf.GetApplicationPlatforms()).Returns(applicationPlatforms);
solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList<Activity>() { activeActivity, inactiveActivity });
solutionFacadeMock.Setup(sf => sf.GetTargetApplications()).Returns(new ObservableList<TargetBase>()
{
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<ISolutionFacadeForBPMN> solutionFacadeMock = new();
ObservableList<ApplicationPlatform> applicationPlatforms = new()
{
new ApplicationPlatform()
{
AppName = "MyWebApp",
Platform = ePlatformType.Web
},
new ApplicationPlatform()
{
AppName = "MyWebServices",
Platform = ePlatformType.WebServices
}
};
ObservableList<TargetBase> 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<Consumer>()
{
new Consumer()
{
ConsumerGuid = targetApplications[0].Guid
}
}
};
activityGroup.ActivitiesIdentifiers.Add(new ActivityIdentifiers()
{
IdentifiedActivity = restActivity
});
solutionFacadeMock.Setup(sf => sf.GetActivitiesFromSharedRepository()).Returns(new ObservableList<Activity>() { restActivity });
solutionFacadeMock.Setup(sf => sf.GetApplicationPlatforms()).Returns(applicationPlatforms);
solutionFacadeMock.Setup(sf => sf.GetTargetApplications()).Returns(targetApplications);
solutionFacade = solutionFacadeMock.Object;

}
}
}
Loading
Loading