Hello!
Context
See XWIKI-24872
The default HTMLDisplayer implementation, DefaultTemplateHTMLDisplayer, renders a value by looking for a template named after the displayed type, in this order:
html_displayer/[type]/[mode].vmhtml_displayer/[type].vmhtml_displayer/[mode].vmhtml_displayer/default.vm
How [type] is computed depends on the kind of Type:
- a plain
Classis named by its simple name, lowercased, soorg.xwiki.model.reference.SpaceReferenceresolves tohtml_displayer/spacereference.vm; - any other
Type, and in particular aParameterizedType, is named by its fully qualified serialization only, sojava.util.List<org.xwiki.model.reference.SpaceReference>can only ever resolve tohtml_displayer/java.util.list(org.xwiki.model.reference.spacereference).vm.
The author of a displayer for a SpaceReference writes spacereference.vm, while the author of a displayer for a List<SpaceReference> has to spell out both fully qualified names. The asymmetry has no functional reason, it is just how getTypeNames grew: the simple-name branch was added for Class in 10.11RC1 (8fe09eda9de) and the parameterized case fell into the generic ReflectionUtils.serializeType fallback.
This naming convention is a public extension point, since any extension can ship an html_displayer/*.vm template and since the displayer is callable from wiki pages through $services.displayer.html.
Proposal
Add a short name for parameterized types, built from the simple names of the raw type and of its type arguments, and look it up after the fully qualified one. For java.util.List<org.xwiki.model.reference.SpaceReference> the candidate type names would become, in order:
java.util.list(org.xwiki.model.reference.spacereference)list(spacereference)
which, combined with the mode, gives the full lookup order:
html_displayer/java.util.list(org.xwiki.model.reference.spacereference)/view.vm
html_displayer/java.util.list(org.xwiki.model.reference.spacereference).vm
html_displayer/list(spacereference)/view.vm
html_displayer/list(spacereference).vm
html_displayer/view.vm
html_displayer/default.vm
- Priority. The fully qualified name keeps the highest priority on purpose. Short names can collide:
List<org.xwiki.rendering.block.Block>andList<org.xwiki.contrib.myextension.Block>both shorten tolist(block). Keeping the fully qualified name first means a template can always target one precise type, and the short name stays a convenience for the common case. That collision risk is not new, by the way: it already exists for plain classes since 10.11RC1, where everyClassis named by its simple name only. - Nested type arguments. A type argument that is not a plain
Classwould still fall back to its serialized name, soList<List<Block>>would shorten tolist(java.util.list(org.xwiki.rendering.block.block)): only the outer raw type could be shortened. - Impact on existing installations. No Java signature changes, the modified method is private and in an
internalpackage, and Revapi reports no break. What changes is the resolution.
Opinion
+1 from me for the proposal as described, because:
- It removes an inconsistency rather than adding a feature: the same rule, “name the type by its simple name”, would apply to both kinds of types.
- Trying the fully qualified name first means that we don’t change how anything resolves today. We just add support for things that wouldn’t resolve before.
- Doing nothing and keeping
html_displayer/java.util.list(org.xwiki.model.reference.spacereference)/view.vmas the only possible file name for a common case looks off given we already have a system for simple class cases.
Conclusion
Two things I would like to settle before this is merged:
- Behaviour change. Do you think this behaviour change is legitimate, should we avoid it?
- Nested types. Should the shortening recurse into type arguments, so that
List<List<Block>>shortens all the way tolist(list(block)), or is stopping at the first level good enough given we don’t have a need for that deeper nesting yet?
I’d like to resolve this discussion quite quickly since it’s eventually a blocker for a roadmap ticket.
I am looking forward to your feedback ![]()
Lucas C.