Краткое описание утилиты ng.app.objectqueue
===========================================

Утилита разработана для поддержки списка объектов, содержащихся внутри
контейнера (и всех вложенных в него контейнеров). Объект размещается в
начале списка при создании или модификации и постепенно перемещается по
нему в соответствии с выбранной дисциплиной (очередь или стек). Кроме
дисциплины можно настроить порядок (прямой или обратный), а также
максимальную длину списка. Объект удаляется из списка если он достигает его
конца (в рамках принятой дисциплины) или если стирается из контейнера.

Такой подход позволяет перераспределить ресурсы при построении сервисов
сайта, связанных с отображением различных "лент": новостных, свежих
поступлений, изменений сайта или даже RSS-лент (см. продукт
[name:ng.app.rss])

Принцип действия
----------------

Компонент **ng.app.objectqueue** ассоциируется с любым объектом как
[keyword:аннотация] или регистрируется как утилита в сайт-менеджере (в
последнем случае ее действие распространяется на весь сайт). Специальный
диспетчер перехватывает события, связанные с созданием, удалением или
модификацией объектов и диспетчеризует их для всех компонентов
**ng.app.objectqueue**, которые должны его учесть. Порядок обхода
диспетчером очередей имеет большое значение, так как для любой очереди можно
установить флаг *islast* и прервать таким образом процедуру обхода. Первыми
обходятся очереди в контейнерах, от вложенных к облегающим, затем - утилиты
в сайтменеджерах, также, от вложенных к облегающим.

Каждый компонент **ng.app.objectqueue** ведет небольшой перечень вложенных
объектов, основанный на утилите **IIntIds**, что позволяет сэкономить ресурс
обслуживания очередей.

Требования к установке и настройке
----------------------------------

Обратите внимание, для полноценной работы ng.app.objectqueue, необходима
установка продукта [name:ng.utility], компонент которого,
ng.utility.objecteventchanel, преобразует события (добавления, удаления и
др) в понятный хендлерам ng.app.objectqueue. Использование
[name:ng.utility:ng.utility.objecteventchannel] намного более эффективно,
чем явная проверка в хендлере на наличие интерфейса.

Возможны два варианта установки: установка для сайта и установка для
отдельного контейнера (компонента). В любом случае, до начала работ с
**ng.app.objectqueue**, в сайт-менеджере должна быть зарегистрирована
утилита **IIntIds**, кроме того, компонент **ng.app.objectqueue** ведет
очередь только тех компонентов, которые предоставляют интерфейс::

    ng.app.objectqueue.interfaces.IObjectQueueAble
    
поэтому нужно установить этот интерфейс для всех компонентов, обслуживаемых
очередью. Статическая установка проводится указанием следующей директивы
[keyword:ZCML]::

  <class class="zope.app.file.file.File">
    <implements interface="ng.app.objectqueue.interfaces.IObjectQueueAble" />
  </class>

Для динамической установки можно использовать продукт
[name:ng.schema:ng.schema.interfaceswitcher].

Установка для сайта
~~~~~~~~~~~~~~~~~~~

Как только утилита **IIntIds** зарегистрирована, можно создать и
зарегистрировать утилиту **IObjectQueue** (*Add ObjectQueue* и последующая
регистрация с пустым именем под интерфейсом
**ng.app.objectqueue.interfaces.IObjectQueue**). На вкладке *Queue*
созданной утилиты есть несколько полей, соответствующих интерфейсу
**IObjectQueueData**:

    maxlen : Int
        Максимальная длина очереди;
        
    style : Choice of TextLine
        Дисциплина очереди (fifo/lifo);
        
    order : Choice of TextLine
        Порядок вставки объекта в очередь (straight/reverse);
        
    use  : Bool
        Очередь обслуживает события;
        
    usemodify : Bool
        Очередь обслуживает событие модификации объекта;
        
    length : int
        Текущая длина списка.
        
    islast : Bool
        На этой очереди диспетчеризация события по остальным очередям
        прекращается;
        
    length : Int, только для чтения
        Текущая длина очереди;

        
Установка для отдельного контейнера
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Принцип установки **ng.app.objectqueue** для отдельного контейнера
достаточно обычен: нужно назначить компоненту-контейнеру интерфейс::

    ng.app.objectqueue.objectqueueannotation.interfaces.IObjectQueueAnnotable
    
после чего с каждым экземпляром этого компонента окажется ассоциирована
аннотация с интерфейсом **IObjectQueue**, и в менеджерском интерфейсе
компонента появится вкладка *Queue*, такая же как и в случае утилиты.
Существуют разные способы назначить интерфейс как динамически (см. например
[name:ng.schema:ng.schema.interfaceswitcher]), так и статически. Для
простоты опишем только статический способ: в конфигурацию экземпляра
[keyword:zope3], в данном примере папки, нужно добавить директиву [keyword:ZCML]::

  <class class="zope.app.folder.folder.Folder">
    <implements 
        interface="ng.app.objectqueue.objectqueueannotation.interfaces.IObjectQueueAnnotable"
        />
  </class>


При установке компонента для каждого контейнера (как в примере выше) следует
обратить внимание на настройки *use* и *islast*, первая настройка позволяет не
использовать очередь данного контейнера, а вторая настройка позволяет
исключить из формирования очередей верхнего уровня все содержимое данного
контейнера и вложенных в него контейнеров.
        
Использование **ng.app.objectqueue**
------------------------------------                        

Самый простой способ использования **ng.app.objectqueue** - это
воспользоваться готовым продуктом, таким как [name:ng.app.rss] - компонентом
публикации [keyword:Atom]-фидов. Возможен и непосредственный вызов, например,
в темплейте::

    <tal:block 
        repeat="item context/++nsinterface++ng.app.objectqueue.interfaces.IObjectQueue.values()">
        <a tal:content="item/title" tal:attributes="href item/@@absolute_url"/>
    </tal:block>

В этом случае будет выведен список ссылок на новые поступления в текущем
контейнере и (зависит от настроек) вложенных в него контейнеров, что, как
нетрудно заметить, намного быстрее просмотра всего содержимого контейнера.

Заключение
----------

Использование **ng.app.objectqueue** предполагает некоторое разумное
соглашение между экономией на скорости просмотра вложенных контейнеров при
частом обращении и экономии на скорости внесения и удаления новых объектов
при редактировании. Необходимо отметить, что хотя результат просмотра
вложенных контейнеров также может быть запомнен и сохранен, все-таки
использование **ng.app.objectqueue** обладает тем неоспоримым преимуществом,
что происходит активация существенно меньшего количества объектов (в
условиях реальных сайтов - одного-четырех), что значительно менее
ресурсоемко по сравнению с просмотром.

Другое возможное решение - использование специальных индексов поискового
каталога - отличается меньшей устойчивостью к конфликтам, хотя и дает
большую гибкость.
