// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using AWS.Deploy.Common.Extensions; using AWS.Deploy.Common.Recipes; namespace AWS.Deploy.Common { public class Recommendation : IUserInputOption { /// /// Returns the full path to the project file /// public string ProjectPath => ProjectDefinition.ProjectPath; public ProjectDefinition ProjectDefinition { get; } public RecipeDefinition Recipe { get; } public int ComputedPriority { get; } public string Name => Recipe.Name; public bool IsExistingCloudApplication { get; set; } public string Description => Recipe.Description; public string ShortDescription => Recipe.ShortDescription; public DeploymentBundle DeploymentBundle { get; } public readonly Dictionary ReplacementTokens = new(); public Recommendation(RecipeDefinition recipe, ProjectDefinition projectDefinition, int computedPriority, Dictionary additionalReplacements) { additionalReplacements ??= new Dictionary(); Recipe = recipe; ComputedPriority = computedPriority; ProjectDefinition = projectDefinition; DeploymentBundle = new DeploymentBundle(); CollectRecommendationReplacementTokens(GetConfigurableOptionSettingItems().ToList()); foreach (var replacement in additionalReplacements) { ReplacementTokens[replacement.Key] = replacement.Value; } } public List GetConfigurableOptionSettingCategories() { var categories = Recipe.Categories; // If any top level settings has a category of General make sure the General category is added to the list. if(!categories.Any(x => string.Equals(x.Id, Category.General.Id)) && Recipe.OptionSettings.Any(x => string.IsNullOrEmpty(x.Category) || string.Equals(x.Category, Category.General.Id))) { categories.Insert(0, Category.General); } // Add the build settings category if it is not already in the list of categories. if(!categories.Any(x => string.Equals(x.Id, Category.DeploymentBundle.Id))) { categories.Add(Category.DeploymentBundle); } return categories; } public IEnumerable GetConfigurableOptionSettingItems() { // For any top level settings that don't have a category assigned to them assign the General category. foreach(var setting in Recipe.OptionSettings) { if(string.IsNullOrEmpty(setting.Category)) { setting.Category = Category.General.Id; } } return Recipe.OptionSettings; } private void CollectRecommendationReplacementTokens(List optionSettings) { foreach (var optionSetting in optionSettings) { string defaultValue = optionSetting.DefaultValue?.ToString() ?? ""; Regex regex = new Regex(@"^.*\{[\w\d]+\}.*$"); Match match = regex.Match(defaultValue); if (match.Success) { var replacement = defaultValue.Substring(defaultValue.IndexOf("{"), defaultValue.IndexOf("}") + 1); ReplacementTokens[replacement] = ""; } if (optionSetting.ChildOptionSettings.Any()) CollectRecommendationReplacementTokens(optionSetting.ChildOptionSettings); } } public void AddReplacementToken(string key, object value) { ReplacementTokens[key] = value; } /// /// Helper to get the project's directory /// /// Full name of directory containing this recommendation's project file public string GetProjectDirectory() { var projectDirectory = new FileInfo(ProjectPath).Directory?.FullName; if (string.IsNullOrEmpty(projectDirectory)) throw new InvalidProjectPathException(DeployToolErrorCode.ProjectPathNotFound, "The project path provided is invalid."); return projectDirectory; } } }