I also wanted to add a ObservationManager.getListener(String  
listenerName) API.

-Vincent

On May 29, 2009, at 12:13 PM, Vincent Massol wrote:

>
> On May 29, 2009, at 12:02 PM, Marius Dumitru Florea wrote:
>
>> Hi Vincent,
>>
>> Vincent Massol wrote:
>>> Here's my latest proposal:
>>>
>>> /**
>>> * Components wanting to receive Observation {...@link Event events}
>>> must implement this interface.
>>> *
>>> * @version $Id: EventListener.java 10164 2008-06-09 12:44:53Z
>>> sdumitriu $
>>> */
>>> public interface EventListener
>>> {
>>>    /**
>>>     * @return the listener's name. It's a free form text identifying
>>> this listener instance in a unique manner.
>>>     *         This name is used for some operations in {...@link
>>> ObservationManager}.
>>>     */
>>>    String getName();
>>>
>>>    /**
>>>     * @return the list of events this listener is configured to
>>> receive. This listener will be automatically
>>>     *         registered with this list of events against the {...@link
>>> ObservationManager}. For each matching event
>>>     *         the {...@link #onEvent(Event, Object, Object)} method
>>> will be called.
>>>     */
>>>    List<Event> getEvents();
>>>
>>>    /**
>>>     * The {...@link org.xwiki.observation.ObservationManager} calls
>>> this methods when an event matches the events for
>>>     * which this listener is registered (see {...@link #getEvents()}.
>>>     *
>>>     * @param event the event triggered. Can be used to differentiate
>>> different events if your Object supports several
>>>     *            events for example.
>>>     * @param source the event source i.e. the object for which the
>>> event was triggered. For example this would be the
>>>     *            document Object if the event is a document update
>>> event.
>>>     * @param data some additional and optional data passed that can
>>> be acted on.
>>>     */
>>>    void onEvent(Event event, Object source, Object data);
>>> }
>>>
>>> And:
>>>
>>> /**
>>> * The main orchestrator for event notification. To receive events
>>> create a component implementing the
>>> * {...@link EventListener} interface. Your component will be
>>> automatically registered when this Observation
>>> * Manager component is loaded. To send events to all registered
>>> listeners, call one of the
>>> * {...@link #notify} methods.
>>> *
>>> * @version $Id: ObservationManager.java 20537 2009-05-26 20:41:25Z
>>> vmassol $
>>> */
>>> @ComponentRole
>>> public interface ObservationManager
>>> {
>>>    /**
>>>     * Manually add a listener. Components implementing the {...@link
>>> EventListener} interfaces are only loaded
>>>     * when the Observation Manager component is created. Thus if you
>>> need to add a new listener while the
>>>     * system is running you'll need to call this method.
>>>     *
>>>     * @param event the event to register the listener against; acts
>>> as a template that filters out only specific events
>>>     *            the listener is interested in
>>>     * @param eventListener the listener to register
>>>     */
>>>    void addListener(EventListener eventListener);
>>>
>>>    /**
>>>     * Remove a listener from the list of registered listeners. The
>>> removed listener will no longer receive events.
>>>     *
>>>     * @param listenerName the name of the listener to remove (must
>>> match {...@link EventListener#getName()}
>>>     */
>>>    void removeListener(String listenerName);
>>>
>>>    /**
>>>     * Adds an Event to an already registered listener.
>>>     *
>>>     * @param listenerName the name of the listener to which the
>>> event must be added
>>>     *        (must match {...@link EventListener#getName()}
>>>     * @param event the event to add to the matching listener
>>>     */
>>>    void addEvent(String listenerName, Event event);
>>>
>>>    /**
>>>     * Removes an Event to an already registered listener.
>>>     *
>>>     * @param listenerName the name of the listener to which the
>>> event must be removed
>>>     *        (must match {...@link EventListener#getName()}
>>>     * @param event the event to remove to the matching listener
>>>     */
>>>    void removeEvent(String listenerName, Event event);
>>>
>>>    /**
>>>     * Remove a listener from a specific event.
>>>     *
>>>     * @param event the event to remove the listener from.
>>>     * @param eventListener the listener to remove.
>>>     */
>>>    void removeListener(Event event, EventListener eventListener);
>>
>> I don't understand why sometimes you use the name of the listener (a
>> String) to identify it and some times a reference (EventListener).  
>> Why
>> does the ObservationManager need a listener name? I'm asking  
>> because in
>> the event systems I know (like the DOM event system) there's no  
>> need for
>> such a name.
>
> The instance is used to register it and the name is used to modify  
> an existing instance since it would be cumbersome for the calling  
> code to have to retrieve an instance just to add an Event to it.
>
> Note that this is more complex than it looks and it also prevents  
> having cyclic dependencies between Listener components and main  
> components (like MacroManager and MacroManagerListener for ex) since  
> the listener will need to call the  main component when an event  
> happens and thus if the main component need to add an Event it would  
> need to get a listener instance.
>
> -Vincent
>
>>>    /**
>>>     * Call the registered listeners matching the passed Event.
>>>     * The definition of <em>source</em> and <em>data</em> is purely
>>> up to the communicating classes.
>>>     *
>>>     * @param event the event to pass to the registered listeners
>>>     * @param source the source of the event (or <code>null</code>)
>>>     * @param data the additional data related to the event (or
>>> <code>null</code>)
>>>     */
>>>    void notify(Event event, Object source, Object data);
>>>
>>>    /**
>>>     * Convenience front-end where the additional data parameter is
>>> <code>null</code>.
>>>     *
>>>     * @param event the event to pass to the registered listeners
>>>     * @param source the source of the event (or <code>null</code>)
>>>     * @see #notify(org.xwiki.observation.event.Event, Object,  
>>> Object)
>>>     */
>>>    void notify(Event event, Object source);
>>> }
>>>
>>> This allows adding events after the listener is registered thus
>>> allowing Sergiu's use case in the Localization module.
>>>
>>> WDYT?
>>>
>>> Thanks
>>> -Vincent
>>>
>>> On May 28, 2009, at 1:59 PM, Sergiu Dumitriu wrote:
>>>
>>>> Sergiu Dumitriu wrote:
>>>>> Vincent Massol wrote:
>>>>>> Hi,
>>>>>>
>>>>>> There's a pb with the current implementation:
>>>>>> When we get the Observation manager implementation and list the
>>>>>> registered listeners we only get the components that have been
>>>>>> initialized *before* we get the Observation manager component.
>>>>>> Thus if
>>>>>> we want to be sure all listeners will receive events we need to
>>>>>> ensure  they're loaded first. This is hard to do.
>>>>>>
>>>>>> I'm proposing instead to modify the observation module:
>>>>>>
>>>>>> * Modify EventListener to be a @ComponentRole
>>>>> +1
>>>>>
>>>>>> * Add List<Event> EventListener.getEvents() (the events that the
>>>>>> listener handles)
>>>>> Hm, I'm not sure about this. A document watcher will dynamically
>>>>> add and
>>>>> remove events to the list of monitored resources. We could have  
>>>>> this
>>>>> method to be called for the initial registration, as otherwise  
>>>>> it's
>>>>> hard
>>>>> to do the initialization.
>>>>>
>>>>> +0
>>>> Also, this requires that the ComponentManager is Initializable,
>>>> otherwise it won't actually register anything.
>>>>
>>>>>> * Inject List<EventListener> in DefaultObservationManager. Thus  
>>>>>> when
>>>>>> the Observation Manager is looked up, all listener components are
>>>>>> created and injected.
>>>>> +1
>>>>>
>>>>>> * Keep add/removeListener in ObservationManager so that listeners
>>>>>> can
>>>>>> be manually added/removed (for ex if a new listener component is
>>>>>> added  dynamically in the system) but with following signatures:
>>>>>> - addListener(EventListener);
>>>>>> - removeListener(EventListener);
>>>>> -1. See above, a component with a dynamic list of events will  
>>>>> need to
>>>>> register/unregister just one in a long list. So we do need the
>>>>> existing
>>>>> signatures. Maybe add these signatures, but also keep the existing
>>>>> ones.

_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs

Reply via email to