[Zope3-dev] should the view lookup machinery call getAdapter?

Steve Alexander steve@cat-box.net
Sat, 30 Mar 2002 09:02:41 +0000


R. David Murray wrote:
> This may all be a result of my misunderstanding how things
> currently work, but:
> 
> I noticed on the checkins list that Casey did the following:
> 
> 
>><browser:view name="RolePermissionsManagement"
>>              for="Zope.App.OFS.Memento.IAttributeMementoStorable."
>>              factory="Zope.App.Security.RolePermissionView." />
> 
> 
> It seems to me that the goal would be that this view would work for
> any object that supports the IMementoBag interface.

First I'll present some background which might be helpful to people who 
haven't looked at all of the interfaces and mechanisms involved in this. 
  Then, I'll present a solution.



Let's think about what you have, and where you want to get to.

We have a content object. We want to know if we can get it to store 
Role-Permissions information for us.

The IAttributeMementoStorable interface is a contract between a content 
object, and anything else, that says "you can use my __memobag__ 
attribute". The content object give others permission to use one of its 
attributes, and promises not to mess with that particular attribute.

A declaration, as above, can be interpreted as providing a quanta of 
declarative knowledge. It is saying something that shall be true; an 
affordance; a thing that may happen in the system.

So this particular declaration is saying "If you've got a content object 
that implements IAttributeMementoStorable, you can see its 
RolePermissionManagement view".


As IAttributeMementoStorable is only one particular way of associating 
an IMementoBag with a content object, we'll need other declarations for 
the other FooMementoStorable interfaces.

So, that's fine when we look at it from the point of view of the content 
object.


The problem with this is that whenever we create a new 
FooMementoStorable, we'll have to add declarations for all of the 
different views that work with IMementoBags.

This might be ok if there are only ever a couple of MementoStorable 
schemes. However, there is also the problem that when you add other 
views that work with IMementoBags, you'd have to add declarations for 
each of the MementoStorable schemes.


So, ideally, we want to say in one place how content objects can be 
associated with IMementoBags, and in another place what things can work 
with IMementoBags.


One way of solving this is, as RDM said, to declare that the 
RolePermissionsManagement view works with anything, and dynamically 
check adapters in the factory registered in the directive.

This is not a good solution, as RDM pointed out, because it adds a 
procesing overhead, and also because the whole thing has become less 
discoverable. That is, we've lost the explicit declaration that 
RolePermissionsManagement needs an IMementoBag.


My solution:

A better way of solving this is to expand the view registry so that it 
can register transitive relationships between adapters.
Consider these declarations:

   What you have                    What you can get

   IAttributeMementoStorable        IMementoBag
   IMementoBag                      RolePermissionsManagement view

In the zcml files, you'd declare that an adapter exists for adapting 
IAttributeMementoStorables into IMementoBags. We also say that the 
RolePermissionsManagement view needs an IMementoBag.

We add an attribute transitive="yes" to the 
IAttributeMementoStorable->IMementoBag declaration.

We need to change the component registries to have a two-phase 
initialisation. Inside the component registries, any adapters that get 
registered with transitive="yes" are registered as usual, and also added 
to a list for processing in the second phase.

After all the directives are registered, we go through the 
transitive="yes" list, and transitively add new adapter and view (and 
utility and service?) declarations based on the interfaces that the 
interface in the transitive="yes" list can adapt to. As we are doing 
this transitively, we keep on doing it until there is no more work to do.

This is quite an expensive process, which is why we don't want to do it 
for all the adapters in the system. So, we only declare to be transitive 
certain adapters that we know are needed transitively.

We may need a declaration that partially overrides an adapter 
declaration by adding transitive="yes" and keeping the rest of the 
declaration intact.


Then again, we might find that if we transitively register all adapters, 
that most of the second-phase work is a no-operation, and by default all 
adapters can be registered transitively.

--
Steve Alexander