diff --git a/Pf2eDataScrapper/SchemaBuilder/SchemaNode.cs b/Pf2eDataScrapper/SchemaBuilder/SchemaNode.cs
index 6bfc4bc..cffa64b 100644
--- a/Pf2eDataScrapper/SchemaBuilder/SchemaNode.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/SchemaNode.cs
@@ -1,41 +1,76 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
using Pf2eDataScrapper.SchemaBuilder.Types;
namespace Pf2eDataScrapper.SchemaBuilder
{
+ ///
+ /// Элемент схемы данных.
+ ///
internal class SchemaNode
{
+ ///
+ /// Отображаемое имя элемента.
+ ///
public string Name = "";
+ ///
+ /// Путь к элементу.
+ ///
public string Path = "";
+ ///
+ /// Родительский элемент.
+ ///
public SchemaNode? Parent = null;
+ ///
+ /// Указание, является ли элемент корневым.
+ ///
public bool Root = false;
+ ///
+ /// Корневой элемент схемы данных.
+ ///
public SchemaNode RootNode => Root ? this : Parent!.RootNode;
+ ///
+ /// Типы данных, использующиеся в элементе.
+ ///
public List Types = [];
+ ///
+ /// Указание, может ли этот элемент отсутсвовать в структуре данных.
+ ///
public bool IsNullable = false;
+ ///
+ /// Объект для определения типа поля в схеме данных.
+ ///
public TypeResolver Resolver = new();
+ ///
+ /// Количество значений, добавленных в тип.
+ ///
public int Values { get; protected set; } = 0;
+ ///
+ /// Указание, является ли тип элемента простым.
+ ///
public bool IsSimple => Types.Count == 1;
+ ///
+ /// Конструктор корневого элемента.
+ ///
public SchemaNode()
{
this.Root = true;
}
+ ///
+ /// Конструктор элемента схемы данных.
+ ///
+ /// Родительский элемент.
+ /// Имя элемента.
public SchemaNode(SchemaNode parent, string name)
{
this.Parent = parent;
@@ -44,6 +79,10 @@ namespace Pf2eDataScrapper.SchemaBuilder
this.Resolver = parent.Resolver;
}
+ ///
+ /// Добавление нового возможного значения.
+ ///
+ /// Добавляемое значение
public void AddValue(JToken? value)
{
if (value is null || Resolver.TokenType(value) == JTokenType.Null)
@@ -68,6 +107,10 @@ namespace Pf2eDataScrapper.SchemaBuilder
Types.Add(newType);
}
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public string GetTypeName()
{
if (IsSimple)
@@ -75,11 +118,15 @@ namespace Pf2eDataScrapper.SchemaBuilder
return Types[0].GetTypeName();
}
- List typeNames = Types.Select(t => t.GetTypeName()).ToList();
+ var typeNames = Types.Select(t => t.GetTypeName()).ToList();
return string.Join("|", typeNames);
}
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
if (IsSimple)
@@ -97,6 +144,9 @@ namespace Pf2eDataScrapper.SchemaBuilder
return string.Join("\n" + AbstractSchemaType.Tab, result);
}
+ ///
+ /// Подготовка элемента к красивому представлению.
+ ///
public void Beautify()
{
foreach (var type in Types)
diff --git a/Pf2eDataScrapper/SchemaBuilder/TypeResolver.cs b/Pf2eDataScrapper/SchemaBuilder/TypeResolver.cs
index f334db0..d80266b 100644
--- a/Pf2eDataScrapper/SchemaBuilder/TypeResolver.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/TypeResolver.cs
@@ -1,15 +1,19 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
using Pf2eDataScrapper.SchemaBuilder.Types;
namespace Pf2eDataScrapper.SchemaBuilder
{
+ ///
+ /// Класс для определения типа поля в схеме данных.
+ ///
internal class TypeResolver
{
+ ///
+ /// Проверка соответствия пути.
+ ///
+ /// Элемент, путь которого проверяется.
+ /// Проверяемый путь. Допускается использование `*` в местах, где допускается любое значение.
+ /// `true`, если `node.Path` соответсвует указанному в `path` значению.
public bool CheckPath(SchemaNode node, string path)
{
if (!path.Contains("*"))
@@ -27,12 +31,23 @@ namespace Pf2eDataScrapper.SchemaBuilder
return !pathParts.Where((t, i) => t != "*" && t != nodeParts[i]).Any();
}
-
+
+ ///
+ /// Проверка соответствия пути.
+ ///
+ /// Элемент, путь которого проверяется.
+ /// Проверяемые пути. Допускается использование `*` в местах, где допускается любое значение.
+ /// `true`, если `node.Path` соответсвует хотя бы одному указанному в `paths` значению.
public bool CheckPath(SchemaNode node, ICollection paths)
{
return paths.Any(path => CheckPath(node, path));
}
+ ///
+ /// Получение типа значения.
+ ///
+ /// Значение.
+ /// Типа значения.
public JTokenType TokenType(JToken? value)
{
if (value is null || value.Type is JTokenType.Null or JTokenType.Undefined or JTokenType.None)
@@ -43,13 +58,23 @@ namespace Pf2eDataScrapper.SchemaBuilder
return value.Type;
}
+ ///
+ /// Определение типа поля.
+ ///
+ /// Поле схемы данных, для которого создаётся тип.
+ /// Добавляемое значение.
+ /// Новый тип для схемы данных
+ ///
+ /// Возникает, если у `value` значение идентично `null`
+ /// (такие значения должны обрабаотываться в `SchemaNode`).
+ ///
public virtual AbstractSchemaType Resolve(SchemaNode node, JToken? value)
{
var type = TokenType(value);
if (type == JTokenType.Null)
{
- throw new Exception("Value is null, cannot determine type");
+ throw new ArgumentNullException();
}
return type switch
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/AbstractSchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/AbstractSchemaType.cs
index 56669bd..0834703 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/AbstractSchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/AbstractSchemaType.cs
@@ -1,37 +1,56 @@
-using System.ComponentModel.Design.Serialization;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Абстрактный тип представоления данных в схеме.
+ ///
+ /// Элемент, к которому добавляется тип.
internal abstract class AbstractSchemaType(SchemaNode parent)
{
+ ///
+ /// Элемент схемы данных, к которому относится тип.
+ ///
public SchemaNode Parent = parent;
+ ///
+ /// Корневой элемент схемы данных.
+ ///
public SchemaNode Root => Parent.RootNode;
+ ///
+ /// Объект для определения типа поля в схеме данных.
+ ///
public TypeResolver Resolver => Root.Resolver;
///
- /// Check if type is compatible with current type.
+ /// Проверка, что значение совместимо с текущим типом.
///
- /// Value to be checked
- /// True if value is compatible with current type
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public abstract bool IsCompatibleValue(JToken value);
///
- /// Add new possible value.
+ /// Добавление нового значения.
///
- /// New value
+ /// Новое значение.
public abstract void AddValue(JToken value);
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public abstract void Beautify();
///
- /// String representation of type.
+ /// Получение строкового представоения типа элемента.
///
- ///
+ /// Строковое представоение типа элемента
public abstract string GetTypeName();
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
return $"{GetTypeName()} {Parent.Path}";
@@ -39,20 +58,20 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
///
- /// Tabulation characters.
+ /// Отступ для строкового представления.
///
public const string Tab = " ";
///
- /// Limit of elements in list or dictionary to be displayed.
+ /// Предел количество отображаемых элементов.
///
- public const int ElementLimit = 20;
+ public const int ElementLimit = 10;
///
- /// Indent text.
+ /// Увеличение отступа строки.
///
- /// Text to be indented
- /// Indented text
+ /// Изменяемая строка.
+ /// Строка с добавленными отступами.
public static string Indent(string text)
{
return text.Replace("\n", "\n" + Tab);
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/ArraySchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/ArraySchemaType.cs
index 56063b4..896cc30 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/ArraySchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/ArraySchemaType.cs
@@ -1,28 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Transactions;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Тип представоления массива в схеме.
+ ///
+ /// Элемент, к которому добавляется тип.
internal class ArraySchemaType(SchemaNode parent) : AbstractSchemaType(parent)
{
+ ///
+ /// Минимальное количество элементов в массиве.
+ ///
public int MinCount = int.MaxValue;
+ ///
+ /// Максимальное количество элементов в массиве.
+ ///
public int MaxCount = int.MinValue;
+ ///
+ /// Схема элемента массива.
+ ///
protected SchemaNode ElementSchema = new(parent, "[]");
- protected List Values = [];
-
+ ///
+ /// Проверка, что значение совместимо с текущим типом.
+ ///
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public override bool IsCompatibleValue(JToken value)
{
return Resolver.TokenType(value) == JTokenType.Array;
}
+ ///
+ /// Добавление нового значения.
+ ///
+ /// Новое значение.
public override void AddValue(JToken value)
{
if (value.Type != JTokenType.Array)
@@ -41,16 +55,27 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
}
}
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public override void Beautify()
{
-
+ ElementSchema.Beautify();
}
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public override string GetTypeName()
{
return $"array<{ElementSchema.GetTypeName()}>";
}
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
return string.Join("\n" + Tab, [
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/DictionarySchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/DictionarySchemaType.cs
index 9bead9c..4a49d73 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/DictionarySchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/DictionarySchemaType.cs
@@ -1,23 +1,37 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Тип представоления словаря в схеме.
+ ///
+ /// Элемент, к которому добавляется тип.
internal class DictionarySchemaType(SchemaNode parent) : AbstractSchemaType(parent)
{
+ ///
+ /// Схема ключей словаря.
+ ///
public SchemaNode KeyNode = new(parent, "[key]");
+ ///
+ /// Схема значений словаря.
+ ///
public SchemaNode ItemNode = new(parent, "[value]");
+ ///
+ /// Проверка, что значение совместимо с текущим типом.
+ ///
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public override bool IsCompatibleValue(JToken value)
{
return Resolver.TokenType(value) == JTokenType.Object;
}
+ ///
+ /// Добавление нового значения.
+ ///
+ /// Новое значение.
public override void AddValue(JToken value)
{
var obj = (JObject)value;
@@ -29,16 +43,28 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
}
}
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public override void Beautify()
{
-
+ KeyNode.Beautify();
+ ItemNode.Beautify();
}
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public override string GetTypeName()
{
return $"dict<{KeyNode.GetTypeName()}, {ItemNode.GetTypeName()}>";
}
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
return string.Join("\n" + Tab, [
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/IgnoreSchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/IgnoreSchemaType.cs
index 2d2ce19..d5d7605 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/IgnoreSchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/IgnoreSchemaType.cs
@@ -1,24 +1,42 @@
using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Тип, указывающий, что данные игнорируются.
+ ///
+ /// Элемент, к которому добавляется тип.
internal class IgnoreSchemaType(SchemaNode parent) : AbstractSchemaType(parent)
{
+ ///
+ /// Проверка, что значение совместимо с текущим типом.
+ ///
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public override bool IsCompatibleValue(JToken value)
{
return true;
}
+
+ ///
+ /// Добавление нового значения.
+ ///
+ /// Новое значение.
public override void AddValue(JToken value)
{
}
+
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public override void Beautify()
{
}
+
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public override string GetTypeName()
{
return "ignore";
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/ObjectSchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/ObjectSchemaType.cs
index 9a299b5..b5324d2 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/ObjectSchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/ObjectSchemaType.cs
@@ -1,21 +1,32 @@
using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Тип представоления объектов в схеме.
+ ///
+ /// Элемент, к которому добавляется тип.
internal class ObjectSchemaType(SchemaNode parent) : AbstractSchemaType(parent)
{
+ ///
+ /// Элемнты полей объекта.
+ ///
public List Fields = [];
+ ///
+ /// Проверка, что значение совместимо с текущим типом.
+ ///
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public override bool IsCompatibleValue(JToken value)
{
return Resolver.TokenType(value) == JTokenType.Object;
}
+ ///
+ /// Добавление нового значения.
+ ///
+ /// Новое значение.
public override void AddValue(JToken value)
{
var obj = (JObject)value;
@@ -42,6 +53,9 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
}
}
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public override void Beautify()
{
Fields.Sort((a, b) =>
@@ -51,7 +65,7 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
return 1;
}
- return a.Name.CompareTo(b.Name);
+ return string.Compare(a.Name, b.Name, StringComparison.Ordinal);
});
foreach (var field in Fields)
@@ -60,11 +74,19 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
}
}
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public override string GetTypeName()
{
return "object";
}
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
List rows = [base.ToString()];
diff --git a/Pf2eDataScrapper/SchemaBuilder/Types/StaticSchemaType.cs b/Pf2eDataScrapper/SchemaBuilder/Types/StaticSchemaType.cs
index ab3d565..4ad0fe7 100644
--- a/Pf2eDataScrapper/SchemaBuilder/Types/StaticSchemaType.cs
+++ b/Pf2eDataScrapper/SchemaBuilder/Types/StaticSchemaType.cs
@@ -2,17 +2,37 @@
namespace Pf2eDataScrapper.SchemaBuilder.Types
{
+ ///
+ /// Тип представоления простых значений в схеме.
+ ///
+ /// Элемент, к которому добавляется тип.
+ /// Тип значения.
internal class StaticSchemaType(SchemaNode parent, JTokenType type) : AbstractSchemaType(parent)
{
+ ///
+ /// Тип значения.
+ ///
protected JTokenType Type = type;
+ ///
+ /// Набор возможных значений и их количества.
+ ///
protected Dictionary Values = [];
-
+
+ ///
+ /// Проверка, что значение совместимо с текущим типом.
+ ///
+ /// Проверяемое значение.
+ /// `true`, если значение совместимо с текущим типом.
public override bool IsCompatibleValue(JToken value)
{
return value.Type == Type;
}
+ ///
+ /// Добавление нового значения.
+ ///
+ /// Новое значение.
public override void AddValue(JToken value)
{
Values.TryAdd(value, 0);
@@ -20,6 +40,9 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
Values[value]++;
}
+ ///
+ /// Подготовка типа к красивому представлению.
+ ///
public override void Beautify()
{
if (Type == JTokenType.String)
@@ -39,11 +62,19 @@ namespace Pf2eDataScrapper.SchemaBuilder.Types
Values = Values.OrderByDescending(pair => pair.Value).ToDictionary(pair => pair.Key, pair => pair.Value);
}
+ ///
+ /// Получение строкового представоения типа элемента.
+ ///
+ /// Строковое представоение типа элемента
public override string GetTypeName()
{
return Type.ToString().ToLower();
}
+ ///
+ /// Полное строковое представление элемента.
+ ///
+ /// Строковое представление элемента.
public override string ToString()
{
var result = base.ToString();