Vincent Massol wrote:
> Hi Sergiu,
> 
> On Mar 15, 2008, at 8:11 AM, Sergiu Dumitriu wrote:
> 
>> Hi,
>>
>> How do you feel about the next usage scenarios for the observation
>> component?
>>
>>
>> A. Simple observing of changes
> 
> [snip]
> 
>> B. Simple observing of actions
> 
> [snip]
> 
>> C. Precondition/Postcondition enforcing
>> The previous two use cases allow a simple ping that something has
>> already happened. (Actually, the listeners can also change the passed
>> document, as the actual object is sent.) But I'd like to be able to
>> write a listener that can say "this is not allowed, please stop this
>> action", or "these changes are not OK, don't save this document".  
>> So, a
>> precondition can be that "/save/" cannot be performed between 6PM and
>> 7AM, which would be a needed feature in some companies, or that "/ 
>> view/"
>> cannot be performed on the "SectionA" space from the IP addresses like
>> 192.168.2.*, which belongs to the SectionB users (these are action
>> events). And a postcondition can be that the XWiki.XWikiPreferences  
>> can
>> only be updated by changing XWikiGlobalRights objects, other types of
>> changes can only be performed by a superadmin only, or that adding  
>> some
>> content that looks like spam is not allowed (these are document  
>> events).
>>
>> So, on top of the previous use cases, I'd like to add a "phase" to the
>> events, which indicates if the event is sent before or after the  
>> change
>> (or we can just add new events), and a new type of exception thrown by
>> the listeners, which is not ignored. Right now, if a listener throws  
>> an
>> exception, it is ignored. This exception, when received by the code  
>> that
>> sends the notification, should stop the normal processing and display
>> "action not allowed" + ex.getMessage to the user.
> 
> My first reaction is that I'm not really fan of this approach. The way  
> I had planned to implement this in the V2.0 architecture is by either:
> 
> 1) replacing existing component with a different implementation. This  
> is when the current behavior need to be modified/replaced by another  
> one.
> 2) depending on the component, introduce new component. For example  
> the Action Manager in the new action component allows defining new  
> Actions that can be inserted before or after existing actions (or even  
> replace existing actions but that's 1)).
> 
> To summarize, I would agree with your idea except that with components  
> there's another way of doing it and I don't think we should have too  
> many ways. If you think about how you'd implement your idea you'll end  
> up creating a state machine component to which actions are hooked to.  
> This is what the Action Manager component is meant to do, although for  
> the moment I have resisted introducing a FSM since I wanted to see the  
> exact need first and with 1) and 2) I thought we could already do  
> quite a lot (not sure what we cannot do to be honest).

This allows introducing/changing ONE new functionality, by completely 
replacing a whole component, but it isn't flexible enough IMHO. Using 
events also allows:
- chaining several completely different "behaviors"
- writing one listener for all the actions, instead of replacing several 
Actions just to introduce a check
- defining a behavior as a Groovy script placed inside a document, so 
adding a new -- let's say -- security feature will not require writing a 
component, packaged as a jar, but just installing a wiki application, 
controllable from the wiki, like the IRC bot.

I don't see a need for a FSM, as the place where these events should be 
sent are already clear, and the old notification already sends pre- and 
post-notifications, just that all the errors are ignored.

>> D. Rendering hooks
>> While working on the SkinExtensions and trying to write a better #toc
>> macro, I was faced with the problem that there's no way a plugin can
>> change the rendered content at the end. Yes, it can alter it line by
>> line, and in theory there is an endRenderingHook sent with the  
>> content,
>> but that is actually buggy, as an empty string is sent instead of the
>> content, and the result is discarded. Still, even if fixed, this is  
>> sent
>> only for *rendered* content, not *parsed* content. My initial idea was
>> to change the PluginInterface by adding two new methods that will be
>> called before and after the content was generated, but that is a bad
>> idea, since the PluginInterface is already too big and has too many
>> types of methods. And since the new rendering component is not yet
>> available, I thought that we can also use events for this.
>>
>> So, instead of writing new methods in the PluginInterface, we can add
>> other type of events, which gets sent in the parsing/rendering  
>> process.
>> That way, we don't need to have a plugin that implements all these
>> methods, and adding a new feature will require just sending a new type
>> of event, instead of changing an interface (which is dangerous).
>>
>> The source would be an object holding the string, which can be  
>> modified
>> by the listeners. Other information could be the content document, if
>> there is one, the rendering/parsing context, anything else?
> 
> Again my first reaction is that I'm no fan... :) The reason is that I  
> have this implemented in the new rendering component.
> First any piece of code can get the parsed content of a text having  
> any kind of syntax (Element Blocks or DOM). Second, it's possible to  
> write any Macro that will manipulate this DOM and make any  
> modification to it. This is how the Toc Macro is going to be rewritten  
> actually.
> 
> However you're right in that right now all I have planned for are  
> Macros and these are triggered by the macro syntax in the text to  
> parse/rendering. So it's a good idea to add a small FSM in the  
> rendering component since we already need an order in the macro  
> execution but also to add the ability to register macros to be  
> executed regardless of whether they appear in the parsed text or not.

At first I thought that the new rendering part would be enough, but then 
I realized that in order for some code to be executed, it must exist in 
the source, as a macro or something.

Then I thought that we can make several tree walkers that are executed, 
instead of one that transforms the tree into XHTML, or PDF, or RSS, or a 
different wiki markup, or whatever, but I'm not sure this is a good 
idea, either.

I don't like the events approach for this (especially the fact that the 
event is used for passing data around), but for the moment it seemed a 
simpler approach while waiting for the rendering engine.

>> E. Other generic events
>> Like FlushCacheEvent, StartupEvent, ShutdownEvent, VirtualInitEvent,
>> VirtualShutdownEvent (sent when a wiki is deleted by the
>> WikiManagerEvent), Application[Added/Enabled/Disabled/Removed]Event
>> (sent by the ApplicationManager), Space[Added/Removed]Event (sent by  
>> the
>> SpaceManagerPlugin), etc.
> 
> +1 to those.
> 
> Thanks
> -Vincent
> 
> _______________________________________________
> devs mailing list
> [email protected]
> http://lists.xwiki.org/mailman/listinfo/devs
> 


-- 
Sergiu Dumitriu
http://purl.org/net/sergiu/
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs

Reply via email to