Carsten Ziegeler wrote:

Daniel Fagerstrom wrote:
The current behaviour is flawed as we already know from e.g. the case with the I18N transformer where dynamic resolution is used when static is what would have been expected. With lazy loading things get even worse as resolution during the setup phase also can become dynamic.

It is time that we solve this problem once and for all.
Yeah, sure, I totally agree. But providing two different source
resolvers creates imho more confusion than it really helps.
No, it is the current solution where two fundamentally different behaviours are tried to be solved with one component through a clever (and AFAIK completely undocumented) hack.

The solution I propose will remove the confussion as the resolvers behave in a intuitive and easy to understand way. Let me explain.

Static resolution
=================

If you have relative path in a component configuration most (all?) would suspect that the relative path would be relative to the location of the file the configuration is part of. This behaviour is called static resolution as it is resolved relative to its configuration

Now in the implementation of your component you need a resolver to resolve the relative path. You get that resolver from the service manager that the component is part of. IMO the resolver should resolve relative the base path of the service manager (i.e. the base path of the configuration file) *always*. I.e. both during setup and during use, and both if the component is eager or lazy loaded.

This should be the default situation and follows the principle of least supprise. It would be great if we could make this the behaviour of the CocoonSourceResolver, but that would probably break user code somewhere so we can't. We should at least offer and recomend this kind of resolver and migrate our own code to use it.

Sitemap components
==================

Sitemap components are setup in two steps first in the component configuration where they are defined and then in the sitemap where they are used. The expected behaviour is relative paths in the component configuration is resolved relative to the location of the component configuration. And that relative paths in the use of the sitemap component is resolved relative to the location of the sitemap where it is used.

If the sitemap component is defined and used in different locations we see that we need two different reolvers to get resolution right. In Cocoon that is solved by geting a resolver from the service manager for the resolution relative to the component configuration (or this would be the case with a static resolver as described above, the current situation is more complicated).

Sitemap components implements the interface SitemapModelComponent, that has a setUp method that is called when the component is used. The setUp method have a resolver as parameter, the surrounding infrastructure calls it with a resolver that resolves relative the location of the sitemap where the sitemap component is used. By using this resolver the sitemap component implementer can get relative paths in the use of the sitemap component resolved in the right way.

                         --- o0o ---

These two cases takes care about almost all situations. And it solves the issues we have from e.g. the I18N transformer as well as the new ones from lazy loading. What needs to be done (besides from implementing the mechanism as described in an earlier mail), is to replace uses of the CocoonSourceResolver with the static variant and to be more careful about what resolver is used for component configuration relative respectively use relative resolution in some sitemap components.

For those who don't want to update their code the CocoonSourceResolver will work as it has all the time, including its quirks in lazy mode.

Dynamic resolution
==================

For completeness I describe a more special case that we might or might not want to support. Suppose that you want to implement a component that behaves like a sitemap component in the way that it can get relative paths both when you configure it and when you use it. But that you not is using it from the tree engine and because of that cannot use the infrastructure that takes care of SitemapModelComponents. An example of that could be a component that you are using in a flowscript.

For such a component you might want to resolve paths that you get during use of it relative to the context it is used in. For this case we also need a dynamic resolver.

The current situation
=====================

So what about the current situation? The CocoonSourceResolver resolves a relative path relative to the currently used processor (sitemap) if there is one, otherwise it resolves relative the context root.

For an eager loading component this means that during setup of a global component (in cocoon.xconf) the resolution will be relative the context root. And for a component that is defined in a sitemap it will be setup relative that sitemap which is the current one.

This far everything is fine. But if one wait with the resolution of a relative path from the setup phase to the use phase as for the I18N transformer, there will be a suprise. The relative path will be resolved relative the (sub) sitemap where it was used instead, there is no mechanism to get resolution relative the configuration anymore.

Also for sitemap components one can use the resolver from the service manager instead of that injected with the SitemapModelComponent interaface, as the resolver change behaviour from setup to use.

For lazy loading the situation is even worse as all resolution will be relative the sitemap where the component happen to be used instead of relative the configuration location.

                         --- o0o ---

You say that it's the developer who decides how sources are resolved
(what the base for relative resolving is). Now, what about having an
i18n transformer configured in the main sitemap once with all the
configuration and then the transformer is used in several sub sitemaps.
Each sub sitemaps has the same set of catalogs. So in this case, the
transformer is configured once in the main sitemap with relative paths
and the paths are resolved in a sub sitemap relative to the sub sitemap.
Ok, this might be a constructed case, but I think the point is, the
developer can't always decide.
So, again why not using the following:
<map:transform src="my-class">
  <map:parameter name="config-file"
value="static://relativ_to_this_sitemap"/>

and
<map:transform src="my-class">
  <map:parameter name="config-file" value="relativ_to_the_usage_sitemap"/>
I agree about that your case is constructed ;) I have explained above what the main cases are and that it in general it is the components designers responsibility to decide what resolution strategy that should be used. For the I18N case I find the current (dynamic resolution) behaviour rather unintuitive, and considering user complaints I'm not the only one. So the default behaviour should instead be static resolution.

If you find a real use case for needing to let the user decide, we could instead have a dynamic protocol for dynamic reolution for the few cases where somebody would like that.

Everything stays the way it is and you can force source resolving to be
relative to the defining sitemap by using the protocol.
I don't want it to stay as it is as the current behavior is flawed and that it gets even worse with lazy component loading.

What I propose is similar to the current system but behaves in an intuitive way, and we also keep back compability for those who don't need lazy loading and can live with the current behaviour.

/Daniel

Reply via email to