IntentArchitect / Support

A repository dedicated to handling issues and support queries
3 stars 0 forks source link

Identifying other modules #15

Closed leonAtRain closed 1 year ago

leonAtRain commented 1 year ago

Ask a question

We've got our own implementation of the Mapstruct as a module that is customized for our scenario. I've implemented a gRpc module which also requires a specific map to be added to the Mapstruct interface. My question is - while generating the mapper template, is it possible to know if the gRPC module is active in the specific application that I can make the necessary changes - if the module is not there, it would just skip that step.

dandrejvv commented 1 year ago

Hi @leonAtRain. To answer your question, there are a few ways you can go about achieving that.

It is best practice to rather check for the existence of a Template Instance that gets installed by your gRpc module than it is to check directly whether the gRpc module is installed. This is to cater for scenarios where you may perform refactoring later and to decouple your modules by not referencing them directly. You can do this check inside your Template or Software Factory Extension that needs to detect whether gRpc is installed.

If you are in the context of a Template, you can use the TryGetTemplate method which will perform a search and return a template instance based on a Template Id or Role name. The Template Id / Role name can target the Template that is present inside your gRpc module and if the method returns an instance, then you know the module is present and you can do certain logic then.

If the code in question lies inside a Software Factory Extension, you can leverage the IApplication object to make use of the FindTemplateIntance method which works similar to the TryGetTemplate method.

Otherwise if your module does not have a template but you wish to check that it is installed, the IApplication (for Software Factory Extensions) and ExecutionContext (for Templates) also has a InstalledModules property that holds a list of all the Modules (their Module Ids) that's installed. You can perform a .Any(x => x.ModuleId == "MyModuleId") check on them to see if your module is present.

I hope that those options will help you.

leonAtRain commented 1 year ago

I Thought I got it , but I'm doing something wrong: ITemplate templat; if (TryGetTemplate("Rain.Module.Grpc.ServiceImpl", out templat)) { members.Add(string.Join(Environment.NewLine, CreateToDtoGrpcMethod())); }

my SF is showing me this nice message:

System.Exception: Error occurred in Template: RainModelMapping.DtoEntityMapper [[DTO: AccountBalanceDto - ec54faf1-c687-45cb-b738-92ed915654a0]] ---> System.Exception: More than one instance of template Rain.Module.Grpc.ServiceImpl was found. Rain.Module.Grpc.ServiceImpl [[Service: BillFormatService - 02866016-2942-4bf5-8782-e2ca9801278a]], Rain.Module.Grpc.ServiceImpl [[Service: BillingAccountService - bc0a690f-0563-487b-9f0f-76a5c6168bfa]], Rain.Module.Grpc.ServiceImpl [[Service: BillingCycleSpecificationService - e53a99dc-75d0-41bc-b522-ff6eb399cf0d]], Rain.Module.Grpc.ServiceImpl [[Service: FinancialAccountService - 663fb459-1ea5-43d1-81fc-7d4ae974a72c]], Rain.Module.Grpc.ServiceImpl [[Service: PartyAccountService - 55802915-de8f-4bdf-93ca-124f63a796bf]], Rain.Module.Grpc.ServiceImpl [[Service: SettlementAccountService - 44965307-06a5-433b-9fc7-d8eb12d560e3]] at Intent.SoftwareFactory.Engine.Runtime.ApplicationManager.FindTemplateInstance(String templateIdOrRole, Func2 predicate) in D:\AzureDevOpsAgents\IntentProprietaryRepository\_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\Engine\Runtime\ApplicationManager.cs:line 505 at Intent.Modules.Common.SoftwareFactoryExecutionContextExtensions.FindTemplateInstance[TTemplate](ISoftwareFactoryExecutionContext executionContext, String templateId) in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Engine/SoftwareFactoryExecutionContextExtensions.cs:line 66 at Intent.Modules.Common.Templates.IntentTemplateBase.<>c__DisplayClass82_01.b0() in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Templates/IntentTemplateBase.cs:line 1232 at Intent.Modules.Common.Templates.IntentTemplateBase.GetTemplate[TTemplate](Func1 getTemplate, Func1 getDependencyDescriptionForException, TemplateDiscoveryOptions options) in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Templates/IntentTemplateBase.cs:line 1166 at Intent.Modules.Common.Templates.IntentTemplateBase.GetTemplate[TTemplate](String templateId, TemplateDiscoveryOptions options) in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Templates/IntentTemplateBase.cs:line 1231 at Intent.Modules.Common.Templates.IntentTemplateBase.TryGetTemplate[TTemplate](String templateId, TTemplate& template) in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Templates/IntentTemplateBase.cs:line 1243 at RainModelMapping.Templates.DtoEntityMapper.DtoEntityMapperTemplate.GetMembers() in C:\Users\LeonNortjie\source\repos\Rain.IntentModules\RainModelMapping\Templates\DtoEntityMapper\DtoEntityMapperTemplate.cs:line 76 at RainModelMapping.Templates.DtoEntityMapper.DtoEntityMapperTemplate.TransformText() in C:\Users\LeonNortjie\source\repos\Rain.IntentModules\RainModelMapping\Templates\DtoEntityMapper\DtoEntityMapperTemplate.cs:line 43 at Intent.Modules.Common.Templates.IntentTemplateBase.RunTemplate() in /home/vsts/work/1/s/Modules/Intent.Modules.Common/Templates/IntentTemplateBase.cs:line 189 at Intent.Modules.Common.Java.Templates.JavaTemplateBase1.GetTemplateFile() in /home/vsts/work/1/s/Modules/Intent.Modules.Common.Java/Templates/JavaTemplateBase.cs:line 169 at Intent.Modules.Common.Java.Templates.JavaTemplateBase1.RunTemplate() in /home/vsts/work/1/s/Modules/Intent.Modules.Common.Java/Templates/JavaTemplateBase.cs:line 215 at Intent.SoftwareFactory.Templates.TemplateOutput.GenerateOutput() in D:\AzureDevOpsAgents\IntentProprietaryRepository_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\Templates\Outputs\TemplateOutput.cs:line 31 --- End of inner exception stack trace --- at Intent.SoftwareFactory.Templates.TemplateOutput.GenerateOutput() in D:\AzureDevOpsAgents\IntentProprietaryRepository_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\Templates\Outputs\TemplateOutput.cs:line 35 at Intent.SoftwareFactory.Engine.OutputFile..ctor(IOutputTarget project, ITemplateOutput templateOutput, IFileLog existingFileInfo, ISoftwareFactoryEventDispatcher eventDispatcher) in D:\AzureDevOpsAgents\IntentProprietaryRepository_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\Engine\Output\OutputFile.cs:line 30 at Intent.SoftwareFactory.ProcessOrchestration.<>cDisplayClass18_2.b__1() in D:\AzureDevOpsAgents\IntentProprietaryRepository_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\ProcessOrchestration.cs:line 385 at Intent.SoftwareFactory.TaskTracker.StartSubTask(String name, Action action, Nullable`1 subTaskCount) in D:\AzureDevOpsAgents\IntentProprietaryRepository_work\1\s\Intent.IntentArchitect\IntentArchitect.SoftwareFactory\Intent.SoftwareFactory\ProcessOrchestration.cs:line 468

leonAtRain commented 1 year ago

I've found something that works -

        if (ExecutionContext.GetApplicationTemplates().Any(t => t.Id.Equals("Rain.Module.Grpc.ServiceImpl")))
        {
            members.Add(string.Join(Environment.NewLine, CreateToDtoGrpcMethod()));
        }

Would this still qualify as Best practice?

dandrejvv commented 1 year ago

Hi @leonAtRain. The error you are experiencing has to do with the fact that there is more than one template instance that was found so the TryGetTemplate method will not suffice in that case since it assumes there will be only a single Template Instance to be returned however, there is an overload where you can pass in a specific model to find a specific Template Instance if you have it available.

Assuming you don't have the model at hand, you can do the following:

var serviceTemplates = this.ExecutionContext.FindTemplateInstances<IClassProvider>(TemplateDependency.OnTemplate("Rain.Module.Grpc.ServiceImpl"));
if (serviceTemplates.Any())
{
     members.Add(string.Join(Environment.NewLine, CreateToDtoGrpcMethod()));
}

I hope this will clear up your concern. However, I do think it is worth mentioning that in the case where you would like to add code based on the existence of another Module, you may want to look at the Java File Builder Pattern. I am happy to take you through it if you are keen.

JonathanLydall commented 1 year ago

Hi @leonAtRain, we're closing this ticket, but let us know if there is anything unclear here.