ДанныеXDTOИзДанныхИБ (БСП)

Автор: 1С
ОбщийМодуль.ОбменДаннымиXDTOСервер
БСП

Данные xdto из данных. Выполняет преобразование данных информационной базы в структуру с данными в соответствии с правилами.

// Выполняет преобразование данных информационной базы в структуру с данными в соответствии с правилами.
//
// Параметры:
//  КомпонентыОбмена    - Структура - содержит все правила и параметры обмена.
//  Источник            - ЛюбаяСсылка - Ссылка на выгружаемый объект информационной базы.
//  ПравилоКонвертации  - СтрокаТаблицыЗначений - Строка таблицы правил конвертации объектов, 
//                        в соответствии с которой выполняется преобразование.
//  СтекВыгрузки        - массив - ссылки на выгружаемые объекты с учетом вложенности.
//
// Возвращаемое значение:
//  Структура - результат преобразования.
//
Функция ДанныеXDTOИзДанныхИБ(КомпонентыОбмена, Источник, Знач ПравилоКонвертации, СтекВыгрузки = Неопределено) Экспорт
	
	Приемник = Новый Структура;
	
	Если СтекВыгрузки = Неопределено Тогда
		СтекВыгрузки = Новый Массив;
	КонецЕсли;
	
	Если ПравилоКонвертации.ЭтоСсылочныйТип Тогда
		
		ПозицияВСтеке = СтекВыгрузки.Найти(Источник.Ссылка);
		
		// Проверяем, выгружался ли объект по ссылке, чтобы не допустить зацикливания.
		Если ПозицияВСтеке <> Неопределено Тогда
			
			Если ПозицияВСтеке > 0 Тогда
				Возврат Неопределено;
			ИначеЕсли СтекВыгрузки.Количество() > 1 Тогда
				// Необходимо искать перебором.
				ПерваяИтерация = Истина;
				Для Каждого ЭлементСтека Из СтекВыгрузки Цикл
					Если ПерваяИтерация Тогда
						ПерваяИтерация = Ложь;
						Продолжить;
					КонецЕсли;
					Если ЭлементСтека = Источник.Ссылка Тогда
						Возврат Неопределено;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
		
		СтекВыгрузки.Добавить(Источник.Ссылка);
		
		Если Не ОбщегоНазначения.СсылкаСуществует(Источник.Ссылка) Тогда
			Возврат Неопределено;
		КонецЕсли;
		
	Иначе
		СтекВыгрузки.Добавить(Источник);
	КонецЕсли;
	
	Если ПравилоКонвертации.ЭтоКонстанта Тогда
		
		Если ПравилоКонвертации.ТипXDTO.Свойства.Количество() = 1 Тогда
			
			Приемник.Вставить(ПравилоКонвертации.ТипXDTO.Свойства[0].Имя, Источник.Значение);
			
		Иначе
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Ошибка XML-схемы. Для приемника должно быть задано одно свойство.
				|Тип источника: %1
				|Тип приемника: %2'"),
				Строка(ТипЗнч(Источник)),
				ПравилоКонвертации.ТипXDTO);
		КонецЕсли;
		
	Иначе
		
		// Выполнение ПКС, 1-й этап
		Для Каждого ПКС Из ПравилоКонвертации.Свойства Цикл
			
			Если ПравилоКонвертации.ОбъектДанных <> Неопределено
				И ПКС.СвойствоКонфигурации = ""
				И ПКС.ИспользуетсяАлгоритмКонвертации Тогда
				Продолжить;
			КонецЕсли;
			
			Если СтекВыгрузки.Количество() > 1 И Не ПКС.ОбработкаКлючевогоСвойства Тогда
				Продолжить;
			КонецЕсли;
			
			ВыгрузитьСвойство(
				КомпонентыОбмена,
				Источник,
				Приемник,
				ПКС,
				СтекВыгрузки,
				1);
		КонецЦикла;
		
		// Выполнение ПКС для ТЧ (прямая конвертация).
		Если СтекВыгрузки.Количество() = 1 Тогда
			Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
				Если НЕ (ЗначениеЗаполнено(ТЧИСвойства.ТЧКонфигурации) И ЗначениеЗаполнено(ТЧИСвойства.ТЧФормата)) Тогда
					Продолжить;
				КонецЕсли;
				// ТЧ пустая.
				Если Источник[ТЧИСвойства.ТЧКонфигурации].Количество() = 0 Тогда
					Продолжить;
				КонецЕсли;
				НоваяТЧПриемника = СоздатьТЧПриемникаПоПКС(ТЧИСвойства.Свойства);
				Для Каждого СтрокаТЧКонфигурации Из Источник[ТЧИСвойства.ТЧКонфигурации] Цикл
					СтрокаТЧПриемник = НоваяТЧПриемника.Добавить();
					Для Каждого ПКС Из ТЧИСвойства.Свойства Цикл
						Если ПКС.ИспользуетсяАлгоритмКонвертации Тогда
							Продолжить;
						КонецЕсли;
						ВыгрузитьСвойство(
							КомпонентыОбмена,
							СтрокаТЧКонфигурации,
							СтрокаТЧПриемник,
							ПКС,
							СтекВыгрузки,
							1);
					КонецЦикла;
				КонецЦикла;
				Приемник.Вставить(ТЧИСвойства.ТЧФормата, НоваяТЧПриемника);
			КонецЦикла;
		КонецЕсли;
		
		// {Обработчик: ПриОтправкеДанных} Начало
		Если ПравилоКонвертации.ЕстьОбработчикПриОтправкеДанных Тогда
			
			Если Не Приемник.Свойство("КлючевыеСвойства") Тогда
				Приемник.Вставить("КлючевыеСвойства", Новый Структура);
			КонецЕсли;
			
			ПриОтправкеДанных(Источник, Приемник, ПравилоКонвертации.ПриОтправкеДанных, КомпонентыОбмена, СтекВыгрузки);
			
			Если Приемник = Неопределено Тогда
				Возврат Неопределено;
			КонецЕсли;
			
			Если СтекВыгрузки.Количество() > 1 Тогда
				Для Каждого КлючевоеСвойство Из Приемник.КлючевыеСвойства Цикл
					Приемник.Вставить(КлючевоеСвойство.Ключ, КлючевоеСвойство.Значение);
				КонецЦикла;
				Приемник.Удалить("КлючевыеСвойства");
			КонецЕсли;
			
			// Выполнение ПКС, 2-й этап
			Для Каждого ПКС Из ПравилоКонвертации.Свойства Цикл
				Если ПКС.СвойствоФормата = "" 
					Или (СтекВыгрузки.Количество() > 1 И Не ПКС.ОбработкаКлючевогоСвойства) Тогда
					Продолжить;
				КонецЕсли;
				
				// Выполняем конвертацию, если в свойство помещена инструкция.
				ЗначениеСвойства = Неопределено;
				Если СтекВыгрузки.Количество() = 1 И ПКС.ОбработкаКлючевогоСвойства Тогда
					Приемник.КлючевыеСвойства.Свойство(ПКС.СвойствоФормата, ЗначениеСвойства);
				Иначе
					СвойствоФормата_Имя = СокрЛП(ПКС.СвойствоФормата);
					ВложенныеСвойства = СтрРазделить(СвойствоФормата_Имя,".",Ложь);
					// Указано полное имя свойства, входящего в группу общих свойств.
					Если ВложенныеСвойства.Количество() > 1 Тогда
						ПолучитьЗначениеВложенныхСвойств(Приемник, ВложенныеСвойства, ЗначениеСвойства);
					Иначе
						Приемник.Свойство(СвойствоФормата_Имя, ЗначениеСвойства);
					КонецЕсли;
				КонецЕсли;
				Если ЗначениеСвойства = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если ПКС.ИспользуетсяАлгоритмКонвертации Тогда
					
					Если ТипЗнч(ЗначениеСвойства) = Тип("Структура")
						И ЗначениеСвойства.Свойство("Значение")
						И ЗначениеСвойства.Свойство("ИмяПКО")
						Или ПКС.ПравилоКонвертацииСвойства <> ""
						И ТипЗнч(ЗначениеСвойства) <> Тип("Структура") Тогда
						
						ВыгрузитьСвойство(
							КомпонентыОбмена,
							Источник,
							Приемник,
							ПКС,
							СтекВыгрузки,
							2);
							
					КонецЕсли;
						
				КонецЕсли;
			КонецЦикла;
			
			// Выполнение ПКС для ТЧ
			Если СтекВыгрузки.Количество() = 1 Тогда
				
				// Формируем структуру новых табличных частей по ПКС.
				СвойстваТЧПриемника = Новый Структура;
				Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
					
					ИмяТЧПриемника = ТЧИСвойства.ТЧФормата;
					
					Если ПустаяСтрока(ИмяТЧПриемника) Тогда
						Продолжить;
					КонецЕсли;
					
					Если Не СвойстваТЧПриемника.Свойство(ИмяТЧПриемника) Тогда
						ТаблицаПКС = Новый ТаблицаЗначений;
						ТаблицаПКС.Колонки.Добавить("СвойствоФормата", Новый ОписаниеТипов("Строка"));
						
						СвойстваТЧПриемника.Вставить(ИмяТЧПриемника, ТаблицаПКС);
					КонецЕсли;
					
					Для Каждого ПКС Из ТЧИСвойства.Свойства Цикл
						СтрокаСвойство = СвойстваТЧПриемника[ИмяТЧПриемника].Добавить();
						СтрокаСвойство.СвойствоФормата = ПКС.СвойствоФормата;
					КонецЦикла;
					
				КонецЦикла;
				
				Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
					
					Если Не ТЧИСвойства.ИспользуетсяАлгоритмКонвертации Тогда
						Продолжить;
					КонецЕсли;
					
					ПКСДляТЧ = ТЧИСвойства.Свойства;
					ИмяТЧПриемника = ТЧИСвойства.ТЧФормата;
					
					ТЧПриемника = Неопределено;
					Если Не ЗначениеЗаполнено(ИмяТЧПриемника)
						Или Не Приемник.Свойство(ИмяТЧПриемника, ТЧПриемника) Тогда
						Продолжить;
					КонецЕсли;
					
					// Создаем новую ТЗ, в которой нет ограничений типа для колонок.
					НоваяТЧПриемника = СоздатьТЧПриемникаПоПКС(СвойстваТЧПриемника[ИмяТЧПриемника]);
					
					// Убираем лишние колонки, которые могли добавить в приемнике.
					УдаляемыеКолонки = Новый Массив;
					Для Каждого Колонка Из ТЧПриемника.Колонки Цикл
						Если НоваяТЧПриемника.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
							УдаляемыеКолонки.Добавить(Колонка);
						КонецЕсли;
					КонецЦикла;
					Для Каждого Колонка Из УдаляемыеКолонки Цикл
						ТЧПриемника.Колонки.Удалить(Колонка);
					КонецЦикла;
					
					// Копируем данные в новую таблицу приемника.
					Для Каждого СтрокаТЧПриемника Из ТЧПриемника Цикл
						СтрокаНовойТЧПриемника = НоваяТЧПриемника.Добавить();
						ЗаполнитьЗначенияСвойств(СтрокаНовойТЧПриемника, СтрокаТЧПриемника);
					КонецЦикла;
					Приемник[ИмяТЧПриемника] = НоваяТЧПриемника;
					
					Для Каждого Строка Из НоваяТЧПриемника Цикл
						
						Для Каждого ПКС Из ПКСДляТЧ Цикл
							
							Если НЕ ПКС.ИспользуетсяАлгоритмКонвертации Тогда
								Продолжить;
							КонецЕсли;
							
							ВыгрузитьСвойство(
								КомпонентыОбмена,
								Источник,
								Строка,
								ПКС,
								СтекВыгрузки,
								2);
								
						КонецЦикла;
						
					КонецЦикла;
					
				КонецЦикла;
				
			КонецЕсли;
			
		КонецЕсли;
		// {Обработчик: ПриОтправкеДанных} Окончание
		
		Если СтекВыгрузки.Количество() > 1 Тогда
			Приемник.Вставить("ТипСоставногоСвойства", ПравилоКонвертации.ТипКлючевыхСвойствОбъектаXDTO);
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Приемник;
	
КонецФункции

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

Рекомендации

Похожие публикации

Данные (БСП)

ПриВыгрузкеДанных (БСП)

ПриЗагрузкеДанных (БСП)

ЕстьДанныеДляОбработки (БСП)

РазмерДанных (БСП)

Синтакс-помощник БСП