From f561cd09acb0b13682b95a41935a65a489830f50 Mon Sep 17 00:00:00 2001 From: Michael Rybakin Date: Fri, 22 Sep 2023 15:47:32 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9A=20#1332:=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=84=D1=83=D0=BD?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D0=B9=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B?= =?UTF-8?q?=20=D1=81=20XML,=20=D1=81=20=D1=82=D0=B5=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Xml/XmlGlobalFunctions.cs | 99 ++++++++++++-- tests/global-funcs.os | 125 ++++++++++++++++++ 2 files changed, 216 insertions(+), 8 deletions(-) diff --git a/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs b/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs index 5345c40d6..65d2ad8fc 100644 --- a/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs +++ b/src/OneScript.StandardLibrary/Xml/XmlGlobalFunctions.cs @@ -6,11 +6,13 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Xml; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.StandardLibrary.Binary; +using OneScript.StandardLibrary.TypeDescriptions; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; @@ -21,10 +23,30 @@ namespace OneScript.StandardLibrary.Xml [GlobalContext(Category="Функции работы с XML")] public class XmlGlobalFunctions : GlobalContextBase { + private static readonly Dictionary _allowedEnums = new Dictionary + {{typeof(ClrEnumValueWrapper),typeof(AllowedSignEnum)}, + {typeof(ClrEnumValueWrapper),typeof(AllowedLengthEnum)}, + {typeof(ClrEnumValueWrapper),typeof(DateFractionsEnum)} + }; + + /// + /// Получает XML представление значения для помещения в текст элемента или значение атрибута XML. + /// + /// + /// Значение. Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные, + /// Неопределено, Null, а также значения перечислений ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты + /// + /// + /// Строковое представление значения. Для двоичных данных - строка в формате Вase64. + /// При недопустимом типе значения выбрасывается исключение + /// + /// [ContextMethod("XMLСтрока", "XMLString")] public string XMLString(IValue value) { - if (value.SystemType == BasicTypes.Undefined) + if (value.SystemType == BasicTypes.String) + return value.AsString(); + else if (value.SystemType == BasicTypes.Undefined || value.SystemType == BasicTypes.Null) return ""; else if(value.SystemType == BasicTypes.Boolean) return XmlConvert.ToString(value.AsBoolean()); @@ -34,23 +56,47 @@ public string XMLString(IValue value) return XmlConvert.ToString(value.AsNumber()); else { - if(value.GetRawValue() is BinaryDataContext bdc) + var rawValue = value.GetRawValue(); + if(rawValue is BinaryDataContext bdc) { return Convert.ToBase64String(bdc.Buffer, Base64FormattingOptions.InsertLineBreaks); } - else + if(rawValue is GuidWrapper guid) + { + return guid.AsString(); + } + else if (_allowedEnums.ContainsKey(rawValue.GetType())) { - return value.GetRawValue().AsString(); + return rawValue.AsString(); } } + + throw RuntimeException.InvalidArgumentValue(); } + /// + /// Выполняет преобразование из строки, полученной из текста элемента или значения атрибута XML, + /// в значение в соответствии с указанным типом. Действие, обратное действию метода XMLСтрока + /// + /// + /// Тип, значение которого надо получить при преобразовании из строкового представления XML. + /// Допустимые типы: Булево, Число, Строка, Дата, УникальныйИдентификатор, ДвоичныеДанные, + /// Неопределено, Null, перечисления ДопустимыйЗнак, ДопустимаяДлина, ЧастиДаты + /// + /// + /// Строка, содержащая строковое представление значения соответствующего типа + /// + /// + /// Значение заданного типа. + /// При недопустимом типе или неправильном строковом представлении выбрасывается исключение + /// + /// [ContextMethod("XMLЗначение", "XMLValue")] public IValue XMLValue(IValue givenType, string presentation) { if (givenType.GetRawValue().SystemType != BasicTypes.Type) { - throw new ArgumentException(nameof(givenType)); + throw RuntimeException.InvalidNthArgumentType(1); } var dataType = givenType.GetRawValue() as BslTypeValue; @@ -74,19 +120,56 @@ public IValue XMLValue(IValue givenType, string presentation) { return ValueFactory.Create(presentation); } - else if (typeValue.Equals(BasicTypes.Undefined) && presentation == "") + else if (typeValue.Equals(BasicTypes.Undefined)) + { + if (presentation.Trim() == "") + return ValueFactory.Create(); + else + { + throw RuntimeException.InvalidNthArgumentValue(2); + } + return ValueFactory.Create(); + } + else if (typeValue.Equals(BasicTypes.Null)) { + if (presentation.Trim() == "") + return ValueFactory.CreateNullValue(); + else + { + throw RuntimeException.InvalidNthArgumentValue(2); + } return ValueFactory.Create(); } + else if (typeValue.ImplementingClass == typeof(GuidWrapper)) + { + try + { + return new GuidWrapper(presentation); + } + catch + { + throw RuntimeException.InvalidNthArgumentValue(2); + } + } else if (typeValue.ImplementingClass == typeof(BinaryDataContext)) { byte[] bytes = Convert.FromBase64String(presentation); return new BinaryDataContext(bytes); } - else + else if (_allowedEnums.TryGetValue(typeValue.ImplementingClass, out var enumType)) { - throw RuntimeException.InvalidArgumentValue(); + try + { + var enumerationContext = GlobalsHelper.GetEnum(enumType); + return enumerationContext[presentation]; + } + catch (RuntimeException) + { + throw RuntimeException.InvalidNthArgumentValue(2); + } } + + throw RuntimeException.InvalidNthArgumentType(1); } diff --git a/tests/global-funcs.os b/tests/global-funcs.os index 9bce86e3c..50d9d4d37 100644 --- a/tests/global-funcs.os +++ b/tests/global-funcs.os @@ -43,6 +43,15 @@ ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаДвоичныеДанные"); ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаСтрокаИзПеременной"); ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеДвоичныеДанные"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаNULL"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаGUID"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаПеречисления"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеNULL"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеGUID"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеПеречисления"); + ВсеТесты.Добавить("ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЗаписьВBase64"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтениеИзBase64"); @@ -374,6 +383,122 @@ КонецПроцедуры +Процедура ТестДолжен_Проверить_XMLСтрокаNULL() Экспорт + + юТест.ПроверитьРавенство("", XMLСтрока(NULL)); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеNULL() Экспорт + + Тип = Тип("NULL"); + + Значение = XMLЗначение(Тип, " "); + юТест.ПроверитьТип(Значение, Тип); + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип, "NULL"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении NULL в XMLЗначение"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаGUID() Экспорт + + Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e"; + GUID = Новый УникальныйИдентификатор(Строка); + юТест.ПроверитьРавенство(Строка, XMLСтрока(GUID)); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеGUID() Экспорт + + Тип = Тип("УникальныйИдентификатор"); + Строка = "ae1d6d78-c3d5-4ef0-b096-2fb4f8e4717e"; + + Значение = XMLЗначение(Тип, Строка); + юТест.ПроверитьТип(Значение, Тип); + юТест.ПроверитьРавенство(Строка(Значение), Строка); + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип, "-a-e1d6d78c3d54ef0b0962fb4f8e4717e"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом представлении GUID в XMLЗначение"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаПеречисления() Экспорт + + Перечисление = ДопустимыйЗнак.Неотрицательный; + юТест.ПроверитьРавенство("Неотрицательный", XMLСтрока(Перечисление)); // нужно "Nonnegative" + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеПеречисления() Экспорт + Тип = Тип("ДопустимаяДлина"); + Значение = XMLЗначение(Тип, "Fixed"); + + юТест.ПроверитьТип(Значение, Тип); + юТест.ПроверитьРавенство(Значение, ДопустимаяДлина.Фиксированная); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLСтрокаНедопустимыеТипы() Экспорт + + Массив = Новый Массив(1); + БылоИсключение = Ложь; + Попытка + Стр = XMLСтрока(Массив); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока"); + + Перечисление = НаправлениеСортировки.Возр; + БылоИсключение = Ложь; + Попытка + Стр = XMLСтрока(Перечисление); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом перечислении в XMLСтрока"); + +КонецПроцедуры + +Процедура ТестДолжен_Проверить_XMLЗначениеНедопустимыеТипы() Экспорт + + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип("НаправлениеСортировки"), "Возр"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом типе в XMLСтрока"); + + Перечисление = НаправлениеСортировки.Возр; + БылоИсключение = Ложь; + Попытка + Значение = XMLЗначение(Тип("ДопустимаяДлина"), "Возр"); + Исключение + БылоИсключение = Истина; + КонецПопытки; + + юТест.ПроверитьИстину(БылоИсключение,"Не было исключения при недопустимом значении в XMLСтрока"); + +КонецПроцедуры + + Функция ПрочитатьФайлСкрипта(Знач Файл) Ч = Новый ЧтениеТекста(Файл);