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

