112 lines
4.9 KiB
C#
112 lines
4.9 KiB
C#
using Newtonsoft.Json.Linq;
|
|
using Pf2eDataScrapper.SchemaBuilder.Types;
|
|
|
|
namespace Pf2eDataScrapper.SchemaBuilder;
|
|
|
|
/// <summary>
|
|
/// Класс для определения типа поля в схеме данных.
|
|
/// </summary>
|
|
internal class TypeResolver
|
|
{
|
|
/// <summary>
|
|
/// Проверка соответствия пути.
|
|
/// </summary>
|
|
/// <param name="node">Элемент, путь которого проверяется.</param>
|
|
/// <param name="path">Проверяемый путь. Допускается использование `*` в местах, где допускается любое значение.</param>
|
|
/// <returns>`true`, если `node.Path` соответсвует указанному в `path` значению.</returns>
|
|
public bool CheckPath(SchemaNode node, string path)
|
|
{
|
|
if (!path.Contains("*"))
|
|
{
|
|
return path == node.Path;
|
|
}
|
|
|
|
string[] pathParts = path.Split('.');
|
|
string[] nodeParts = node.Path.Split('.');
|
|
|
|
return pathParts.Length > nodeParts.Length ? false : !pathParts.Where((t, i) => t != "*" && t != nodeParts[i]).Any();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Проверка соответствия пути.
|
|
/// </summary>
|
|
/// <param name="node">Элемент, путь которого проверяется.</param>
|
|
/// <param name="paths">Проверяемые пути. Допускается использование `*` в местах, где допускается любое значение.</param>
|
|
/// <returns>`true`, если `node.Path` соответсвует хотя бы одному указанному в `paths` значению.</returns>
|
|
public bool CheckPath(SchemaNode node, ICollection<string> paths)
|
|
{
|
|
return paths.Any(path => CheckPath(node, path));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Получение типа значения.
|
|
/// </summary>
|
|
/// <param name="value">Значение.</param>
|
|
/// <returns>Типа значения.</returns>
|
|
public JTokenType TokenType(JToken? value)
|
|
{
|
|
return value is null || value.Type is JTokenType.Null or JTokenType.Undefined or JTokenType.None ? JTokenType.Null : value.Type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Частное определение типа поля.
|
|
/// </summary>
|
|
/// <param name="node">Поле схемы данных, для которого создаётся тип.</param>
|
|
/// <param name="value">Добавляемое значение.</param>
|
|
/// <returns>Новый тип для схемы данных. `null`, что бы использовать значение по умолчанию</returns>
|
|
protected virtual AbstractSchemaType? CustomResolve(SchemaNode node, JToken? value)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Определение типа поля.
|
|
/// </summary>
|
|
/// <param name="node">Поле схемы данных, для которого создаётся тип.</param>
|
|
/// <param name="value">Добавляемое значение.</param>
|
|
/// <param name="disableResolve">Добавляемое значение.</param>
|
|
/// <returns>Новый тип для схемы данных</returns>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// Возникает, если у `value` значение идентично `null`
|
|
/// (такие значения должны обрабаотываться в `SchemaNode`).
|
|
/// </exception>
|
|
public AbstractSchemaType Resolve(SchemaNode node, JToken? value, bool disableResolve)
|
|
{
|
|
if (!disableResolve)
|
|
{
|
|
AbstractSchemaType? customType = this.CustomResolve(node, value);
|
|
|
|
if (customType is not null)
|
|
{
|
|
return customType;
|
|
}
|
|
}
|
|
|
|
JTokenType type = TokenType(value);
|
|
|
|
return type == JTokenType.Null
|
|
? throw new ArgumentNullException(nameof(value))
|
|
: type switch
|
|
{
|
|
JTokenType.Array => new ArraySchemaType(node),
|
|
JTokenType.Object => new ObjectSchemaType(node),
|
|
_ => new StaticSchemaType(node, type)
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Определение типа поля.
|
|
/// </summary>
|
|
/// <param name="node">Поле схемы данных, для которого создаётся тип.</param>
|
|
/// <param name="value">Добавляемое значение.</param>
|
|
/// <returns>Новый тип для схемы данных</returns>
|
|
/// <exception cref="ArgumentNullException">
|
|
/// Возникает, если у `value` значение идентично `null`
|
|
/// (такие значения должны обрабаотываться в `SchemaNode`).
|
|
/// </exception>
|
|
public AbstractSchemaType Resolve(SchemaNode node, JToken? value)
|
|
{
|
|
return this.Resolve(node, value, false);
|
|
}
|
|
}
|