Bart Molenkamp wrote:
I don't know your use cases, so maybe not the following is applicable at all, anyway:I've also been thinking about a simple method for displaying object
instances of different classes. E.g. I get an object from the flow layer, I need to decide how to format it. Instances of class "A" are formatted differently than instances from class "B". Now, this could be done using <jx:choose>, but that doesn't make the code more readable:
<!-- is object instanceof MyClass --> <jx:when test="object.getClass().getName() == 'com.MyClass'">
Even worse when you want to check if it is instanceof an interface:
<!-- is object instanceof MyInterface -->
<jx:when
test="${java.lang.Class.forName('com.MyInterface').isAssignableFrom(
object.getClass())}">
In the (often cited on this list) article: Enforcing Strict Model View Separation in Template Engines, by Terence Parr http://www.cs.usfca.edu/~parrt/papers/mvc.templates.pdf, a number of rules for strict separation between model and view are given. One of them is that the view shouldn't make any assumptions about data types of the model data. The view should only get displayable strings. If one start to depend on data types as in your code above, the template files must be supported by programmers rather than web designers. And the separation of concern between view and model start to get entangeled. Ok, knowing what Terence Parr _don't_ want us to do is not very helpfull ;)
As a solution to the problem he sugests MVCR (Model-View-Controller-Renderer), where the renderer is responsible for converting (Java) data types to displayable strings. The renderer can be responsible for localization of numbers etc as well. The renderer is an extra step between model and view.
The simplest possible renderer is to just implement toString() in the classes one is going to access in the view. But a better SoC is to have a separate rendering component. In this case the object from the model is first accessed by an expression in a suitable expression language and then the object is rendered to a displayable string by the rendering component and at last the displayable string is emited by the template engine.
So, how would the rendering component work? I think that we basically could reuse and extend the Convertor idea from CForms. The renderer check the type of the input object (and possibly the locale) and applies the apropriate convertor. The coupling between object type and convertor is decribed in a configuration file, much as in the form definition in CForms. It should also be easy to use custom converters, for own data types.
Typically one can reuse the same rendering configuration file for all templates.
---o0o---
I think the renderer component idea could give a better SoC in CForms as well. I have had a feeling that data type convertion is not a natural part of the model (form definition) for a while. A problem is that conversion configuration must be repeated each time the data type is used.
Ok, the idea is as follows: we have a converter component, that is like the renderer component above, but bidirectional. I.e. both rendering: data type -> displayable string and input conversion: input string -> data type. The converter is configured in the same way as described for the renderer above.
The convertor is used as a step between the form instance and the view for rendering the data types. And between the request object and the form instance during the population of the form instance.
Typically only one convertor configuration is needed for all ones forms. And we could distribute a localized default convertor configuration with Cocoon.
---o0o---
So, the basic idea is to factor out the type conversion functionallity from CForms and make it available for all rendering and input handling needs in Cocoon.
WDYT?
/Daniel
