using System;
using System.Linq;
using System.Threading.Tasks;
using CTA.WebForms.Services;
using CTA.WebForms.TagCodeBehindHandlers;
using HtmlAgilityPack;
namespace CTA.WebForms.TagConverters
{
///
/// An abstract converter capable of porting view layer tags of a given
/// type to an alternate representation. This includes porting related
/// to code behind references.
///
public abstract class TagConverter
{
private protected TaskManagerService _taskManagerService;
private protected CodeBehindReferenceLinkerService _codeBehindLinkerService;
private protected ViewImportService _viewImportService;
///
/// The name of the tag to apply this converter to.
///
public string TagName { get; set; }
///
/// The type representation of the source tag in code behind
/// files, if such a type exists.
///
public string CodeBehindType { get; set; }
///
/// The name of the type to be used for conversion of code behind
/// references to the source tag. In most cases
/// will be sufficient.
///
public string CodeBehindHandler { get; set; }
///
/// The set of conditions used to decide which template to use on any
/// given source tag.
///
///
/// Used to inject any necessary services and perform other initialization
/// steps required before tag migration.
///
/// The service instance that is used
/// to perform managed calls to other services.
/// The service instance that will
/// be used to convert tag code behind references.
/// The service instance that will be used
/// for adding any view imports needed for the conversion.
public virtual void Initialize(
TaskManagerService taskManagerService,
CodeBehindReferenceLinkerService codeBehindLinkerService,
ViewImportService viewImportService)
{
_taskManagerService = taskManagerService;
_codeBehindLinkerService = codeBehindLinkerService;
_viewImportService = viewImportService;
}
///
/// Retrieves an instance of the specified code behind handler class
/// if one exists.
///
/// The value of the ID attribute for the node which this
/// handler will be used on.
/// An instance of the converter's code behind handler class if
/// one was specified, otherwise null.
/// Throws if code behind handler
/// is specified but class couldn't be found.
public TagCodeBehindHandler GetCodeBehindHandlerInstance(string idValue)
{
if (CodeBehindHandler == null || string.IsNullOrWhiteSpace(idValue))
{
return null;
}
var handlerType = GetCodeBehindHandlerType();
if (handlerType == null)
{
throw new InvalidOperationException($"Code behind handler type {CodeBehindHandler} could not be found");
}
return (TagCodeBehindHandler)Activator.CreateInstance(handlerType, CodeBehindType, idValue);
}
///
/// Retrieves the type of the specified code behind handler class
/// if one exists.
///
/// The code behind handler type if it can be found, null otherwise
private protected Type GetCodeBehindHandlerType()
{
if (CodeBehindHandler == null)
{
return null;
}
var handlerClassName = CodeBehindHandler.Equals("Default", StringComparison.InvariantCultureIgnoreCase)
? nameof(DefaultTagCodeBehindHandler) : CodeBehindHandler;
var webFormsAssembly = AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.StartsWith("CTA.WebForms") && !a.FullName.Contains("Test"))
.FirstOrDefault();
var handlerType = webFormsAssembly?
.GetTypes()
.Where(t => t.Name.Equals(handlerClassName) && !t.IsAbstract && !t.IsInterface)
.FirstOrDefault();
return handlerType;
}
///
/// Replaces the provided with its Blazor equivalent
/// as specified by the given converter.
///
/// The tag to be replaced.
/// The path of the view file being modified.
/// The code behind handler to be used on this node, if one exists.
/// The task id of the view file converter that called this method.
public abstract Task MigrateTagAsync(HtmlNode node, string viewFilePath, TagCodeBehindHandler handler, int taskId);
///
/// Checks whether the properties of this converter form a valid configuration.
///
public abstract void Validate();
}
}