FixAntenna/AdminTool/Builder/CommandBuilder.cs (124 lines of code) (raw):
// Copyright (c) 2021 EPAM Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Epam.FixAntenna.AdminTool.Commands;
namespace Epam.FixAntenna.AdminTool.Builder
{
/// <summary>
/// Provides ability to build the command instance.
/// </summary>
internal class CommandBuilder
{
private static readonly CommandBuilder Instance = new CommandBuilder();
protected internal readonly Dictionary<MapKey, Type> ClassCommandCash = new Dictionary<MapKey, Type>();
private CommandBuilder()
{
}
public static CommandBuilder GetInstance()
{
return Instance;
}
/// <summary>
/// Creates the command instance.
/// </summary>
/// <param name="commandName"> the command name </param>
/// <param name="externalPackage"> the package where command situated
/// </param>
public virtual Command BuildCommand(string commandName, string externalPackage)
{
var commandClass = FindCommandClass(commandName, externalPackage);
try
{
return (Command) Activator.CreateInstance(commandClass);
}
catch (TypeLoadException e)
{
throw new AdminToolException(e);
}
catch (TargetInvocationException e)
{
throw new AdminToolException(e);
}
}
/// <summary>
/// Finds the command in command cash, if command does not exist
/// find in externalPackage.
/// </summary>
/// <param name="name"> the command name </param>
/// <param name="externalPackage"> the package were command exist
/// </param>
/// <returns> Class </returns>
private Type FindCommandClass(string name, string externalPackage)
{
Type commandClass = null;
if (!string.IsNullOrWhiteSpace(externalPackage))
{
var mapKey = new MapKey(commandName: name, packageName: externalPackage);
if (!ClassCommandCash.TryGetValue(mapKey, out commandClass))
{
commandClass = GetCommandClass(externalPackage, name);
}
if (commandClass == null)
{
throw new ArgumentException();
}
ClassCommandCash[mapKey] = commandClass;
}
// no class in cash
if (commandClass == null)
{
// try get from default package
var mapKey = new MapKey(commandName: name, packageName: AdminConstants.DefaultCommandPackage);
if (!ClassCommandCash.TryGetValue(mapKey, out commandClass))
{
commandClass = GetCommandClass(AdminConstants.DefaultCommandPackage, name);
if (commandClass == null)
{
throw new ArgumentException();
}
ClassCommandCash[mapKey] = commandClass;
}
}
return commandClass;
}
/// <summary>
/// Returns class by short name.
/// </summary>
/// <param name="nameOfPackage"> the name of package. </param>
/// <param name="className"> the short name of class. </param>
/// <returns> Instance of Class or null if class with input shortname not found.. </returns>
public static Type GetCommandClass(string nameOfPackage, string className)
{
// nameOfPackage consist of namespace and assembly name: 'namespace,assembly'
try
{
var parts = nameOfPackage.Split(',');
var typeName = parts.Length > 1
? $"{parts[0]}.{className},{parts[1]}"
: $"{parts[0]}.{className}";
return Type.GetType(typeName);
}
catch (IOException e)
{
throw new AdminToolException(e);
}
catch (TypeLoadException e)
{
throw new AdminToolException(e);
}
}
/// <summary>
/// Map key bean
/// </summary>
protected internal class MapKey
{
internal string PackageName { get; }
internal string CommandName { get; }
public MapKey(string commandName, string packageName)
{
CommandName = commandName;
PackageName = packageName;
}
public override bool Equals(object o)
{
if (this == o)
{
return true;
}
if (o == null || GetType() != o.GetType())
{
return false;
}
var mapKey = (MapKey) o;
if (!CommandName?.Equals(mapKey.CommandName, StringComparison.OrdinalIgnoreCase) ?? mapKey.CommandName != null)
{
return false;
}
if (!PackageName?.Equals(mapKey.PackageName, StringComparison.OrdinalIgnoreCase) ?? mapKey.PackageName != null)
{
return false;
}
return true;
}
public override int GetHashCode()
{
var result = PackageName != null ? PackageName.GetHashCode() : 0;
result = 31 * result + (CommandName != null ? CommandName.GetHashCode() : 0);
return result;
}
}
}
}