//	+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++
//	|                                Класс перехвата событий                                    |
//	+                                       ShmalevoZ                                           +
//	|                                        2007-12                                            |
//	+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++

//---------------------------------------------------------------------------------------------
// Вызывает зарегистрированных делегатов с отбором по возвращаемым делегатами событиям и
// если событие возникло из какого либо определенного контекста, то с фильтром по типам контекстов
// Если обработчик события делегата возвращает 1, то вызывается оригинальное событие,
// иначе оригинальное событие не вызывается

//---------------------------------------------------------------------------------------------
// Собственные атрибуты
Перем гТаблицаСсылок;		// ссылки на делегатовв
Перем гТаблицаОписаний;		// описания делегатов
Перем гЛог;					// ссылка на лог
Перем гСервисКонтекста;		// Общие.Сервис.Контекст
Перем гИндексы;				// индексированные таблицы для быстрого поиска
Перем гСобытие;				// абстрактное событие


//******************************************************************************
// НормализоватьКонтекст(СсылаКонтекст)
//
// Параметры: 
//  СсылаКонтекст
//
// Возвращаемое значение:
//  Неопределенный
//
// Описание:
//  Возвращает ссылка на переданный контекст
//
Функция НормализоватьКонтекст(СсылаКонтекст)
	
	Возврат СсылаКонтекст;
	
КонецФункции // НормализоватьКонтекст()


//******************************************************************************
// _this()
//
// Параметры: 
//  СсылкаКонтекст			- контекст
//
// Возвращаемое значение:
//  ГрупповойКонтекст		- ссылка на контекст
//
// Описание:
//  Возвращает ссылку на контекст
//
Функция _this()
	
	Возврат НормализоватьКонтекст(Контекст);
	
КонецФункции // _this()


//******************************************************************************
// Присвоить(Чему, Что)
//
// Параметры: 
//  Чему, Что
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция Присвоить(Чему, Что)
	
	Чему	= Что;
	
	Возврат "";
КонецФункции // Присвоить()


//******************************************************************************
// ПолучитьСсылкуНаТаблицуОбъектов()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьСсылкуНаТаблицуОбъектов()
	
	Возврат гТаблицаСсылок;
	
КонецФункции // ПолучитьСсылкуНаТаблицуОбъектов()


//******************************************************************************
// ПолучитьСсылкуНаТаблицуОписаний()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьСсылкуНаТаблицуОписаний()
	
	Возврат гТаблицаОписаний;

КонецФункции // ПолучитьСсылкуНаТаблицуОписаний()


//******************************************************************************
// ПолучитьUID()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьUID()
	
	//---------------------------------------------------------------------------------------------
	// Создалим внутренний идентификатор для объекта, назначим его объекту,
	//	имеем в виду, что UID в нашем случае не может начинаться с цифры,
	//	т.к. он будет выступать в качестве идентификатора колонки таблицы зачений
	СистемныеИдентификаторы		= СоздатьОбъект("GUID");
	Результат					= "1";
	СтрокаИсключаемыхСимволов	= "0123456789";
	Пока Найти(СтрокаИсключаемыхСимволов, Лев(Результат, 1)) <> 0 Цикл
		СистемныеИдентификаторы.Новый();
		Результат	= СистемныеИдентификаторы.ВСтроку();
	КонецЦикла;
	Результат	= СтрЗаменить(Результат, "-", "");
	
	Возврат Результат;
КонецФункции // ПолучитьUID()


//******************************************************************************
// СтрокаВСписок(РазбираемаяСтрока)
//
// Параметры: 
//  РазбираемаяСтрока
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция СтрокаВСписок(РазбираемаяСтрока, Разделитель, УдалятьРазделитель = 1) Экспорт
	
	Результат			= СоздатьОбъект("СписокЗначений");
	ВремСтр				= РазбираемаяСтрока;
	
	Позиция				= Найти(ВремСтр, Разделитель);
	ДлинаРазделителя	= СтрДлина(Разделитель);
	
	Пока Позиция <> 0 Цикл
		Удалить		= ?(УдалятьРазделитель = 1, -1*ДлинаРазделителя, ДлинаРазделителя-1);
		Добавить	= СокрЛП(Лев(ВремСтр, Позиция+Удалить));
		Если ПустаяСтрока(Добавить) = 0 Тогда
			Результат.ДобавитьЗначение(Лев(ВремСтр, Позиция+Удалить));
		КонецЕсли;
		ВремСтр 	= СокрЛП(Прав(ВремСтр, СтрДлина(ВремСтр)-Позиция-ДлинаРазделителя+1));
		Позиция		= Найти(ВремСтр, Разделитель);
	КонецЦикла;
	
	Если СтрДлина(ВремСтр) <> 0 Тогда
	    Результат.ДобавитьЗначение(ВремСтр);
	КонецЕсли;
	
	Возврат Результат;
КонецФункции // СтрокаВСписок()


//******************************************************************************
// ПолучитьТекстСсылкиНаДелегата(НомерДелегата)
//
// Параметры: 
//  НомерДелегата			- номер зарегестрированного делегата
//
// Возвращаемое значение:
//  Строка					- текст ссылки на делегата
//
// Описание:
//  Возвращает текст ссылки на статический объект делегата событий
//
Функция ПолучитьТекстСсылкиНаДелегата(НомерДелегата) Экспорт
	
	Результат	= _this().ПолучитьТекстСсылки() + ".ПолучитьСсылкуНаДелегата(" + НомерДелегата + ")";
	
	Возврат Результат;
КонецФункции // ПолучитьТекстСсылкиНаДелегата()


//******************************************************************************
// ПолучитьТаблицуДелегатовСобытия(Событие, ПроверятьТипКонтекста, СсылкаКонтекст)
//
// Параметры: 
//  Событие					- идентификатор события
//  ПроверятьТипКонтекста	- необходимость фильтровать по типу контекста
//  СсылкаКонтекст			- контекст события
//
// Возвращаемое значение:
//  ТаблицаЗначений
//
// Описание:
//  Возвращает таблицу делегатов события
//
Функция ПолучитьТаблицуДелегатовСобытия(Событие, ПроверятьТипКонтекста, СсылкаКонтекст)
	
	Индекс			= НРег(Событие);
	ТипКонтекста	= "";
	Если ПроверятьТипКонтекста = 1 Тогда
		ТипКонтекста	= гСервисКонтекста.ПолныйТипКонтекста(СсылкаКонтекст);
		Индекс			= Индекс + ":" + НРег(ТипКонтекста);
	КонецЕсли;
	
	Если гИндексы.НайтиСтроку("ИндексСобытиеКонтекст", Индекс, 0, 1) <> 0 Тогда
		Возврат гИндексы.ТаблицаДелегатов;
	КонецЕсли;
	
	//---------------------------------------------------------------------------------------------
	// Проверим делегатов на обработку события
	Результат			= СоздатьОбъект("ТаблицаЗначений");
	Результат.НоваяКолонка("Идентификатор");
	Результат.НоваяКолонка("Приоритет");
	Результат.НоваяКолонка("Номер");
	// по большей части для отладки
	Результат.НоваяКолонка("Представление");
	
	Искомое			= "," + НРег(Событие) + ",";
	ТаблицаОписаний	= ПолучитьСсылкуНаТаблицуОписаний();
	ТаблицаОписаний.ВыбратьСтроки();
	Пока ТаблицаОписаний.ПолучитьСтроку() = 1 Цикл
		
		ДелегатОбрабатываетСобытие	= 1;
		
		Если Найти(ТаблицаОписаний.События, Искомое) = 0 Тогда
			ДелегатОбрабатываетСобытие	= 0;
		КонецЕсли;
		Если (ПроверятьТипКонтекста = 1) и (ДелегатОбрабатываетСобытие = 1) Тогда
			Если ПустаяСтрока(ТаблицаОписаний.ТипыКонтекстов) = 1 Тогда
				ДелегатОбрабатываетСобытие	= 0;
			Иначе
				
				СписокТиповКонтекстов		= СтрокаВСписок(ТаблицаОписаний.ТипыКонтекстов, ",", 1);
				КоличествоТипов				= СписокТиповКонтекстов.РазмерСписка();
				ДелегатОбрабатываетСобытие	= 0;
				Для НомерТипа = 1 По КоличествоТипов Цикл
					ТребуемыйТипКонтекста		= СписокТиповКонтекстов.ПолучитьЗначение(НомерТипа);
					ДелегатОбрабатываетСобытие	= Макс(ДелегатОбрабатываетСобытие, гСервисКонтекста.КонтекстПринадлежитТипу(СсылкаКонтекст, ТребуемыйТипКонтекста));
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
		
		Если ДелегатОбрабатываетСобытие = 0 Тогда
			Продолжить;
		КонецЕсли;
		
		Результат.НоваяСтрока();
		Результат.Приоритет		= ТаблицаОписаний.Приоритет;
		Результат.Номер			= ТаблицаОписаний.НомерСтроки;
		Результат.Идентификатор	= ТаблицаОписаний.UID;
		Результат.Представление	= ТаблицаОписаний.Информация.Идентификатор;
		
	КонецЦикла;
	
	Результат.Сортировать("Приоритет+");
	
	гИндексы.НоваяСтрока();
	гИндексы.Событие			= НРег(Событие);
	гИндексы.СобытиеКонтекст	= Индекс;
	гИндексы.ТаблицаДелегатов	= Результат;
	
	Возврат Результат;
КонецФункции // ПолучитьТаблицуДелегатовСобытия()


//******************************************************************************
// ВызватьДелегатовПоСобытию(Событие, СписокПараметров, ПроверятьТипКонтекста = 0, СсылкаКонтекст = "")
//
// Параметры: 
//  Событие						: строка, идентификатор события
//  СписокПараметров			: данные события
//  ПроверятьТипКонтекста		: флаг проверки типа контекста
//  СсылкаКонтекс				: ссылка на вызывающий контекст
//
// Возвращаемое значение:
//  Флаг стандартной обработки события
//
// Описание:
//  Вызывает делегатов по входящему событию с возможным фильтром по типу контекста, учитывая приоритет вызова
//
Функция ВызватьДелегатовПоСобытию(Событие, СписокПараметров, ПроверятьТипКонтекста = 0, СсылкаКонтекст = "")
	
	ИскомоеСобытие	= СокрЛП(Событие);
	
	Результат			= 1;
	ТаблицаДелегатов	= ПолучитьТаблицуДелегатовСобытия(ИскомоеСобытие, ПроверятьТипКонтекста, СсылкаКонтекст);
	ТаблицаДелегатов.ВыбратьСтроки();
	Пока ТаблицаДелегатов.ПолучитьСтроку() = 1 Цикл
		ТекстСсылкиНаДелегата	= ПолучитьТекстСсылкиНаДелегата(ТаблицаДелегатов.Номер);
		Результат				= Мин(Результат, ПолучитьСсылкуНаТаблицуОбъектов().ПолучитьЗначение(1, ТаблицаДелегатов.Идентификатор).ОбработатьСобытие(Событие, СписокПараметров, ТекстСсылкиНаДелегата));
		// Если вернулся статус 0, то прерываем вызовы
		Если Результат = 0 Тогда
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
КонецФункции // ВызватьДелегатовПоСобытию()


//	+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++
//	|                                                                                           |
//	+                            Обработка состава делегатов                                    +
//	|                                                                                           |
//	+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++---+++

//******************************************************************************
// ЗарегистрироватьДелегата(Делегат, ТаблицаПараметров)
//
// Параметры: 
//  Делегат		: объект, которому будет делегироваться обработка событий
//
// Возвращаемое значение:
//  UID, зарезервированный для делегата
//
// Описание:
//  Добавляет данные о делегате в глобальные таблицы переменной глДанныеМенеджераПерехватаСобытий
//
Функция ЗарегистрироватьДелегата(Делегат)
	
	//---------------------------------------------------------------------------------------------
	// Заранее создадим таблицу информации о делегате
	ТаблицаИнформации	= СоздатьОбъект("ТаблицаЗначений");
	ТаблицаИнформации.НоваяКолонка("UID");				// присвоенный при регистрации делегата UID
	ТаблицаИнформации.НоваяКолонка("Идентификатор");	// идентификатор класса
	ТаблицаИнформации.НоваяКолонка("События");			// события, на какие подписан делегат
	ТаблицаИнформации.НоваяКолонка("ТипыКонтекстов");	// типы обрабатываемых делегатом контекстов
	ТаблицаИнформации.НоваяКолонка("Приоритет");		// приоритет вызова делегата
	ТаблицаИнформации.НоваяСтрока();
	
	//---------------------------------------------------------------------------------------------
	// Получим обрабатываемые события
	СобытияДелегата		= Делегат.ПолучитьИдентификаторыСобытий();
	ТаблицаИнформации.События	= СобытияДелегата;
	// и очистим их от мусора
	СобытияДелегата		= СтрЗаменить(СобытияДелегата, " ", "");
	СобытияДелегата		= СтрЗаменить(СобытияДелегата, СимволТабуляции, "");
	СобытияДелегата		= СтрЗаменить(СобытияДелегата, ";", ",");
	// Если событий нет, то и регистрировать делегата не надо
	Если ПустаяСтрока(СобытияДелегата) = 1 Тогда
		Возврат "";
	КонецЕсли;
	СобытияДелегата		= НРег("," + СобытияДелегата + ",");
	//---------------------------------------------------------------------------------------------
	// Также поступим с типами обрабатываемых контекстов
	ТипыКонтекстов		= Делегат.ПолучитьИдентификаторыКонтекстов();
	ТаблицаИнформации.ТипыКонтекстов	= ТипыКонтекстов;
	ТипыКонтекстов		= СтрЗаменить(ТипыКонтекстов, " ", "");
	ТипыКонтекстов		= СтрЗаменить(ТипыКонтекстов, СимволТабуляции, "");
	ТипыКонтекстов		= СтрЗаменить(ТипыКонтекстов, ";", ",");
	ТипыКонтекстов		= "," + ТипыКонтекстов + ",";
	
	UID			= ПолучитьUID();
	
	ТипДелегата						= ТипЗначенияСтр(Делегат);
	Индекс							= НРег(ТипДелегата);
	ТаблицаИнформации.UID			= UID;
	ТаблицаИнформации.Идентификатор	= ТипДелегата;
	ТаблицаИнформации.Приоритет		= Делегат.ПолучитьПриоритет();
	
	ПолучитьСсылкуНаТаблицуОбъектов().НоваяКолонка(UID);
	ПолучитьСсылкуНаТаблицуОбъектов().УстановитьЗначение(1, UID, Делегат);
	
	ПолучитьСсылкуНаТаблицуОписаний().НоваяСтрока();
	ПолучитьСсылкуНаТаблицуОписаний().UID				= UID;
	ПолучитьСсылкуНаТаблицуОписаний().События			= СобытияДелегата;
	ПолучитьСсылкуНаТаблицуОписаний().ТипыКонтекстов	= ТипыКонтекстов;
	ПолучитьСсылкуНаТаблицуОписаний().Информация		= ТаблицаИнформации;
	ПолучитьСсылкуНаТаблицуОписаний().Приоритет			= ТаблицаИнформации.Приоритет;
	ПолучитьСсылкуНаТаблицуОписаний().Индекс			= Индекс;
	
	//---------------------------------------------------------------------------------------------
	// Запишем в журнал информацию о ходе загрузки
	Текст	= "Добавлен делегат обработки события(й)";
	Текст	= Текст + РазделительСтрок + ТаблицаИнформации.Идентификатор;
	Текст	= Текст + РазделительСтрок + ТаблицаИнформации.События;
	гЛог.Добавить(Текст, _this());
	
КонецФункции // ЗарегистрироватьДелегата()


//******************************************************************************
// ПолучитьПараметрыДелегатаПоУмолчанию(Идентификатор)
//
// Параметры: 
//  Идентификатор			- идентификатор (тип) класса-делегата событий
//
// Возвращаемое значение:
//  ТаблицаЗначений			- параметры делегата
//
// Описание:
//  Возвращает параметры делегата из общих настроек
//
Функция ПолучитьПараметрыДелегатаПоУмолчанию(Идентификатор)
	
	Результат	= СоздатьОбъект("ТаблицаЗначений");
	Результат.НоваяКолонка("Идентификатор");
	Результат.НоваяКолонка("Значение");
	
	Параметры	= СоздатьОбъект("Общие.Параметры");
	Параметры.ИспользоватьСекцию(Идентификатор);
	СписокАтрибутов	= Параметры.ПолучитьСписокАтрибутов();
	Количество		= СписокАтрибутов.РазмерСписка();
	Для Номер = 1 По Количество Цикл
		Результат.НоваяСтрока();
		Результат.Идентификатор	= СписокАтрибутов.ПолучитьЗначение(Номер);
		Результат.Значение		= Параметры.Получить(Результат.Идентификатор);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции // ПолучитьПараметрыДелегатаПоУмолчанию()


//******************************************************************************
// ОповеститьОбИзмененииСоставаДелегатов()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура ОповеститьОбИзмененииСоставаДелегатов()
	
	гСобытие.Опубликовать("ПриИзмененииСоставаДелегатов");
	
КонецПроцедуры // ОповеститьОбИзмененииСоставаДелегатов()


//******************************************************************************
// ДобавитьДелегата(Делегат, ВходящаяТаблицаПараметров = "")
//
// Параметры: 
//  Делегат						: ссылка или идентификатор класса
//  ВходящаяТаблицаПараметров	: таблица параметров регистрации
//
// Возвращаемое значение:
//  UID, назначеный классу в случае успешной регистрации
//
// Описание:
//  Пытается добавить делегата событий
//
Функция ДобавитьДелегата(Делегат, ВходящаяТаблицаПараметров = "") Экспорт
	
	//---------------------------------------------------------------------------------------------
	// Во-первых создадим объект класса и проверим, можно ли ему делегировать события. 
	// Делегат должен поддерживать интерфейс, описанный в Общие.Событие.Делегат
	// Делегат должен принимать входящие параметры загрузки вида
	// Идентификатор | Значение
	Объект				= ?(ТипЗначенияСтр(Делегат) = "Строка", СоздатьОбъект(Делегат), Делегат);
	ТаблицаПараметров	= ?(ТипЗначенияСтр(ВходящаяТаблицаПараметров) = "ТаблицаЗначений", ВходящаяТаблицаПараметров, ПолучитьПараметрыДелегатаПоУмолчанию(ТипЗначенияСтр(Делегат)));
	//---------------------------------------------------------------------------------------------
	// Выведем статус-строку, чтобы пользователь знал, что машина не висит, а думает
	Представление		= Объект.Представление();
	Состояние(Представление);
	Если Объект.НеобходимаРегистрация() = 0 Тогда
		Возврат "";
	КонецЕсли;
	
	UID	= ЗарегистрироватьДелегата(Объект);
	
	гИндексы.УдалитьСтроки();
	
	ОповеститьОбИзмененииСоставаДелегатов();
	
	Возврат UID;
КонецФункции // ДобавитьДелегата()


//******************************************************************************
// УдалитьДелегата(Идентификатор)
//
// Параметры: 
//  Идентификатор			- удаляемый делегат
//
// Возвращаемое значение:
//  Число
//
// Описание:
//  Удаляет делегата. Возвращает успех выполнения
//
Функция УдалитьДелегата(Идентификатор) Экспорт
	
	НомерСтроки	= 0;
	Результат	= ПолучитьСсылкуНаТаблицуОписаний().НайтиЗначение(Идентификатор, НомерСтроки, "UID");
	
	Если Результат = 1 Тогда
		
		Если ПолучитьСсылкуНаТаблицуОбъектов().ПолучитьЗначение(1, Идентификатор).Системный() = 1 Тогда
			Результат	= 0;
		Иначе
			ПолучитьСсылкуНаТаблицуОписаний().УдалитьСтроку(НомерСтроки);
			ПолучитьСсылкуНаТаблицуОбъектов().УстановитьЗначение(1, Идентификатор, 0); // прямо обнулим ссылку
			ПолучитьСсылкуНаТаблицуОбъектов().УдалитьКолонку(Идентификатор);
		КонецЕсли;
	КонецЕсли;
	
	гИндексы.УдалитьСтроки();
	
	ОповеститьОбИзмененииСоставаДелегатов();
	
	Возврат Результат;
КонецФункции // УдалитьДелегата()


//******************************************************************************
// УдалитьВсехДелегатов()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура УдалитьВсехДелегатов()
	
	ТаблицаОписаний	= ПолучитьСсылкуНаТаблицуОписаний();
	Пока ТаблицаОписаний.КоличествоСтрок() > 0 Цикл
		УдалитьДелегата(ТаблицаОписаний.ПолучитьЗначение(1, "UID"));
	КонецЦикла;
	
КонецПроцедуры // УдалитьВсехДелегатов()


//******************************************************************************
// КоличествоДелегатов()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция КоличествоДелегатов() Экспорт
	
	Результат	= ПолучитьСсылкуНаТаблицуОписаний().КоличествоСтрок();
	
	Возврат Результат;
КонецФункции // КоличествоДелегатов()


//******************************************************************************
// ПолучитьUIDДелегата()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьUIDДелегата(НомерДелегата) Экспорт
	
	Результат	= ПолучитьСсылкуНаТаблицуОписаний().ПолучитьЗначение(НомерДелегата, "UID");
	
	Возврат Результат;
КонецФункции // ПолучитьUIDДелегата()


//******************************************************************************
// ПолучитьСсылкуНаДелегата(НомерДелегата)
//
// Параметры: 
//  НомерДелегата
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьСсылкуНаДелегата(НомерДелегата) Экспорт
	
	Идентификатор	= ПолучитьСсылкуНаТаблицуОписаний().ПолучитьЗначение(НомерДелегата, "UID");
	
	Возврат ПолучитьСсылкуНаТаблицуОбъектов().ПолучитьЗначение(1, Идентификатор);
КонецФункции // ПолучитьСсылкуНаДелегата()


//******************************************************************************
// ПолучитьИнформациюОДелегате(НомерДелегата)
//
// Параметры: 
//  НомерДелегата
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьИнформациюОДелегате(НомерДелегата) Экспорт
	
	Возврат ПолучитьСсылкуНаТаблицуОписаний().ПолучитьЗначение(НомерДелегата, "Информация");

КонецФункции // ПолучитьИнформациюОДелегате()


//******************************************************************************
// НайтиДелегата(Идентфиикатор)
//
// Параметры: 
//  Идентфиикатор			- искомый тип класса - делегата событий
//
// Возвращаемое значение:
//  Число					- номер, присвоенный делегату, 0 если не найден
//
// Описание:
//  Ищет зарегистрированного делегата заданного типа
//
Функция НайтиДелегата(Идентификатор) Экспорт
	
	Искомое		= НРег(Идентификатор);
	Результат	= 0;
	ПолучитьСсылкуНаТаблицуОписаний().НайтиЗначение(Искомое, Результат, "Индекс");
	
	Возврат Результат;
КонецФункции // НайтиДелегата()


//******************************************************************************
// ПолучитьДелегата()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ПолучитьДелегата(НомерДелегата) Экспорт
	
	Идентификатор	= ПолучитьСсылкуНаТаблицуОписаний().ПолучитьЗначение(НомерДелегата, "UID");
	
	Возврат ПолучитьСсылкуНаТаблицуОбъектов().ПолучитьЗначение(1, Идентификатор);
КонецФункции // ПолучитьДелегата()


//******************************************************************************
// Зарегистрирован(Идентификатор)
//
// Параметры: 
//  Идентификатор
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция Зарегистрирован(Идентификатор) Экспорт
	
	Результат	= Мин(1, НайтиДелегата(Идентификатор));
	
	Возврат Результат;
КонецФункции // Зарегистрирован()


//******************************************************************************
// ЗагрузитьНастройкиПоУмолчанию()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура ЗагрузитьНастройкиПоУмолчанию() Экспорт
	
	УдалитьВсехДелегатов();
	
	Информатор			= СоздатьОбъект("MetaInfoClasses");
	СписокКлассов		= Информатор.ПолучитьВсеИменаКлассов();
	КоличествоКлассов	= СписокКлассов.РазмерСписка();
	Искомое				= "Общие.Событие.Делегат";
	Для НомерКласса = 1 По КоличествоКлассов Цикл
		Идентификатор	= СписокКлассов.ПолучитьЗначение(НомерКласса);
		Если Информатор.ЯвляетсяОбъектом(Идентификатор, Искомое) = 1 Тогда
			ДобавитьДелегата(Идентификатор);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры // ЗагрузитьНастройкиПоУмолчанию()


//******************************************************************************
// ЕстьДелегатыСобытия(Событие, СсылкаКонтекст = "")
//
// Параметры: 
//  Событие					- событие
//  СсылкаКонтекст = ""		- контекст события
//
// Возвращаемое значение:
//  Число
//
// Описание:
//  Возвращает признак наличия делегатов события
//
Функция ЕстьДелегатыСобытия(Событие, СсылкаКонтекст = "") Экспорт
	
	ТаблицаДелегатов	= "";
	Если ТипЗначения(СсылкаКонтекст) = 100 Тогда
		ТаблицаДелегатов	= ПолучитьТаблицуДелегатовСобытия(Событие, 1, СсылкаКонтекст);
	Иначе
		ТаблицаДелегатов	= ПолучитьТаблицуДелегатовСобытия(Событие, 0, "");
	КонецЕсли;
	
	Результат	= Мин(1, ТаблицаДелегатов.КоличествоСтрок());
	
	Возврат Результат;
КонецФункции // ЕстьДелегатыСобытия()


//******************************************************************************
// Конструктор()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура Конструктор()
	
	//---------------------------------------------------------------------------------------------
	// Чтобы не создавать объекты сервиса контекста каждый раз, создадим его сразу
	гСервисКонтекста	= СоздатьОбъект("Общие.Сервис.Контекст");
	гСобытие			= СоздатьОбъект("Общие.Событие");
	
	//---------------------------------------------------------------------------------------------
	// Создадим собственные структуры
	гТаблицаСсылок		= СоздатьОбъект("ТаблицаЗначений");
	гТаблицаСсылок.НоваяСтрока();
	гТаблицаОписаний	= СоздатьОбъект("ТаблицаЗначений");
	гТаблицаОписаний.НоваяКолонка("Идентификатор");
	гТаблицаОписаний.НоваяКолонка("UID");
	гТаблицаОписаний.НоваяКолонка("Информация");
	гТаблицаОписаний.НоваяКолонка("События");
	гТаблицаОписаний.НоваяКолонка("ТипыКонтекстов");
	гТаблицаОписаний.НоваяКолонка("Приоритет");
	гТаблицаОписаний.НоваяКолонка("Индекс");
	
	//---------------------------------------------------------------------------------------------
	// Логирование
	Регистратор	= СоздатьОбъект("Общие.Статик.Регистратор");
	гЛог		= Регистратор.Получить("Общие.Статик.Объект.Лог");
	
	//---------------------------------------------------------------------------------------------
	// Индексы для быстрого поиска
	гИндексы	= СоздатьОбъект("ИндексированнаяТаблица");
	гИндексы.НоваяКолонка("Событие");
	гИндексы.НоваяКолонка("Контекст");
	гИндексы.НоваяКолонка("СобытиеКонтекст");
	гИндексы.НоваяКолонка("ТаблицаДелегатов");
	гИндексы.ДобавитьИндекс("ИндексСобытиеКонтекст", "СобытиеКонтекст");
	
	ЗагрузитьНастройкиПоУмолчанию();
	
КонецПроцедуры // Конструктор()


//******************************************************************************
// Деструктор()
//
// Параметры: 
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура Деструктор()
	
	УдалитьВсехДелегатов();
	
КонецПроцедуры // Деструктор()


//******************************************************************************
// ОпубликоватьСобытие(Событие, Параметры, СсылкаКонтекст = "")
//
// Параметры: 
//  Событие, Параметры, СсылкаКонтекст = ""
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Функция ОпубликоватьСобытие(Событие, Параметры, СсылкаКонтекст = "") Экспорт
	
	Если ТипЗначенияСтр(СсылкаКонтекст) = "ГрупповойКонтекст" Тогда
		Результат	= ВызватьДелегатовПоСобытию(Событие, Параметры, 1, СсылкаКонтекст);
	Иначе
		Результат	= ВызватьДелегатовПоСобытию(Событие, Параметры, 0, "");
	КонецЕсли;
	
	Возврат Результат;
КонецФункции // ОпубликоватьСобытие()

