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