|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.TemplateFiltering;
using Microsoft.TemplateEngine.Abstractions.TemplatePackage;
using Microsoft.TemplateEngine.Cli.Commands;
using Microsoft.TemplateEngine.Cli.TemplateResolution;
using Microsoft.TemplateSearch.Common;
namespace Microsoft.TemplateEngine.Cli.TemplateSearch
{
internal class CliSearchFiltersFactory
{
private IReadOnlyDictionary<string, string?> _existingTemplatePackageFilterData;
internal CliSearchFiltersFactory(IReadOnlyList<IManagedTemplatePackage> installedPackages)
{
Dictionary<string, string?> filterData = new();
foreach (IManagedTemplatePackage descriptor in installedPackages)
{
filterData[descriptor.Identifier] = descriptor.Version;
}
_existingTemplatePackageFilterData = filterData;
}
private static Func<TemplateSearchData, bool> IsNotHiddenBySearchFile =>
(templateSearchData) =>
{
if (templateSearchData.AdditionalData.TryGetValue(CliHostSearchCacheData.DataName, out object? hostDataRaw)
&& hostDataRaw is HostSpecificTemplateData hostData)
{
return !hostData.IsHidden;
}
return true;
};
private Func<TemplatePackageSearchData, bool> AlreadyInstalledFilter =>
(templatePackageSearchData) =>
{
if (!_existingTemplatePackageFilterData!.TryGetValue(templatePackageSearchData.Name, out string? existingPackVersion))
{
// no existing install of this pack - don't filter it
return true;
}
return existingPackVersion != templatePackageSearchData.Version;
};
internal static Func<TemplatePackageSearchData, IReadOnlyList<ITemplateInfo>> GetMatchingTemplatesFilter(SearchCommandArgs commandArgs)
{
return (templatePackageSearchData) =>
{
InMemoryHostSpecificDataLoader hostDataLoader = new(templatePackageSearchData);
IEnumerable<TemplateSearchData> templates = templatePackageSearchData.Templates.Where(template => IsNotHiddenBySearchFile(template));
IEnumerable<TemplateGroup> templateGroups = TemplateGroup.FromTemplateList(CliTemplateInfo.FromTemplateInfo(templates, hostDataLoader));
IEnumerable<Func<TemplateGroup, MatchInfo?>> groupFilters = new[]
{
CliFilters.NameTemplateGroupFilter(commandArgs.SearchNameCriteria)
};
IEnumerable<Func<ITemplateInfo, MatchInfo?>> templateFilters =
commandArgs.AppliedFilters
.OfType<TemplateFilterOptionDefinition>()
.Select(filter => filter.TemplateMatchFilter(commandArgs.GetFilterValue(filter)));
IEnumerable<TemplateGroupMatchInfo> matchInformation =
templateGroups.Select(
group =>
TemplateGroupMatchInfo.ApplyFilters(
group,
groupFilters,
templateFilters,
//TODO: implement it for template options matching, for now the filter just returns empty collection.
CliFilters.EmptyTemplateParameterFilter()));
return matchInformation
.Where(group => group.IsGroupAndTemplateInfoAndParametersMatch)
.SelectMany(group => group.TemplatesWithMatchingParameters)
.ToList();
};
}
internal Func<TemplatePackageSearchData, bool> GetPackFilter(SearchCommandArgs commandArgs)
{
return templatePackageSearchData =>
{
return AlreadyInstalledFilter(templatePackageSearchData)
&& commandArgs.AppliedFilters
.OfType<PackageFilterOptionDefinition>()
.All(filter => filter.PackageMatchFilter(commandArgs.GetFilterValue(filter))(templatePackageSearchData));
};
}
private class InMemoryHostSpecificDataLoader : IHostSpecificDataLoader
{
private IReadOnlyDictionary<string, HostSpecificTemplateData> _hostSpecificData;
internal InMemoryHostSpecificDataLoader(TemplatePackageSearchData templatePackageSearchData)
{
Dictionary<string, HostSpecificTemplateData> hostSpecificData = new();
foreach (var templateData in templatePackageSearchData.Templates)
{
if (templateData.AdditionalData.TryGetValue(CliHostSearchCacheData.DataName, out object? hostDataRaw)
&& hostDataRaw is HostSpecificTemplateData hostData)
{
hostSpecificData[((ITemplateInfo)templateData).Identity] = hostData;
}
}
_hostSpecificData = hostSpecificData;
}
public HostSpecificTemplateData ReadHostSpecificTemplateData(ITemplateInfo templateInfo)
{
if (_hostSpecificData.TryGetValue(templateInfo.Identity, out HostSpecificTemplateData? data))
{
return data;
}
return HostSpecificTemplateData.Default;
}
}
}
}
|