Here's where I'm at on templates.  Feel free to critique.

Goals (in order of importance):
1. Get data from an object model
2. Minimize or eliminate programmatic logic inside the template
3. Make as simple to read/write templates as possible
4. Give feedback on all possible errors
5. Make the data presentable -- follow established Java data formatting rules where possible
6. Speed
7. Allow extensibility without altering core code


Things to avoid:
1. Making a turing complete programming language out of the template language
2. Avoid tags that simply duplicate programmatic language structures (eg. <if> <else> <forEach>)
3. Second-guessing the data model (eg. getInt, getFloat, getString)
4. Programmatic tag libraries for macros (ie. Just use STX, stx:include and aggregate tranforms)


While I doubt my goals will draw much criticism, the latter group may. In my opinion, once you fall into if/else/forEach land, you've just rewritten XSP with attribute markers instead of <xsp:logic> markers. I'm probably a broken record here, but there is no difference between <if test="x"/> and if(x){}. If the templating process inevitably falls to them, assumptions about the template tools or that template authors must write them must be reconsidered. Simplicity and being terse are key. If an operation can be done with one attribute what would require three attributes (or one attribute with three directives) for Turing-completeness, pick the single, simple attribute that is not Turing-complete.

In addition, I'm wondering what folks think of the following:

-----------------------------
Template Typing/Formatting
-----------------------------

Data structures are largely uniform. If I query a bean for a user's age, it is highly unlikely that sometimes I will receive an integer and other times receive string or a date during the same data iteration. So in the efforts toward template simplification, how do we feel about these two items?

1. No explicit data typing by default (eg. ${user/sallary::#,###.00'/yr'} instead of something like ${formatNumber(user/sallary, '#,###.00\'/yr\'')}) or the current crop of <formatNumber/> and its ilk.

rationale: promotes the use of appropriate data types by the programmer and relieves the template author of needing to know about typing. The persistence mechanism most likely has a type specified (especially if a relational database is in use) and objects in Flow as well. Why force restatement in the template byt the person arguably least likely to make an informed decision on the subject? Just pass a format parameter and be done with it. If the format parameter doesn't fit, report the error (and location in the template).

2. Use and extension of the java.text.Format hierarchy for data formatting.

rationale: code reuse is maximized and avoids the proliferation of Cocoon-only APIs.

As was mentioned before, there are only so many formatting variants needed. I think this covers the bases:

boolean: a selection from two possibilities eg. true/false, yes/no, on/off.
integer (byte, short, int, long): separator placement, percentages, currency (precision with decimals by division), other bases (hex, octal, binary)
decimal (float, double): separator placement, percentages, currency, decimal precision
date/time: basically the SimpleDateFormat syntax featureset
strings (including char and char[]): substring, lowercase/uppercase (Is this a CSS concern?), xml fragments
unhandled objects: Object.toString() should cover this


Also, integer, decimal, and date/time parameters would have to handle locale. (Or would a template-wide locale setting in the sitemap be more appropriate?)

Missing(?) items are formatters for java.math.BigInteger and java.math.BigDecimal. Also perhaps support for InputStreams/Readers for larger content (treated as a string or xml InputSource I would assume). Also a mechanism to add/register new formatters.

By factoring out this code concern and relying upon java.text.Format implementations, the amount of Cocoon-specific code could be reduced while referencing "standard" formatting parameters.

Getting the appropriate format could be accomplished with a FormatFactory (for lack of a better name) with the following interface:

interface FormatFactory {
public java.text.Format getFormat (String params, Locale defaultLocale);
public java.text.Format getFormat (String params, Locale defaultLocale, Object value);
}


The first is called to see if the Format can be determined by the parameters. The second is called when no formatter was returned from the first so that the Object's type determines the formatter. As I said earlier, the types are usually uniform in any given data structure. Once the type is determined and the format set once, further iterations could skip this type check and just use the formatter. If there is no appropriate formatter for the type, a default formatter that simply calls .toString() would be used.

With this, formatting concerns are handled in code that's not intimately tied to (and easily separated from) any particular sitemap component and can reuse code not specifically made for Cocoon.


----------------------------- Macros -----------------------------

I strongly encourage the use of STX stylesheets for this. Let's say you have the following markup from the JXTG samples:

 <table>
   <tablerows list="${greatlakes}" color="blue"/>
 </table>

I'd prefer using an alternate namespace, but I digress. You make a STX stylesheet with the relevant protion:

 <stx:template match="tablerows">
   <jx:forEach var="item" items="[EMAIL PROTECTED]">
     <tr><td bgcolor="[EMAIL PROTECTED]">${item}</td></tr>
   </jx:forEach>
 </stx:template>

    or with attribute syntax

<stx:template match="tablerows">
<tr jx:forEach="item in [EMAIL PROTECTED]"><td bgcolor="[EMAIL PROTECTED]">${item}</td></tr>
</stx:template>


This is what is happening after all whether in Java or not, isn't it? Anyone want to tell me that this is harder and requires more knowledge than writing, compiling and installing a Java class? With this, macro languages can be far more dynamic and immediate to the problems at hand; syntactic sugar and simplification with no fear of side effects. Now, group all your macros together into a file called "form-macros.stx". Put any other macro groups in their own file as well. Then you combine them all into a file called macros.stx (or just have a directory generator run on a directory full of macro definition files and dynamically generate the aggregating stylesheet):

<stx:transform version="1.0" xmlns:stx="http://stx.sourceforge.net/2002/ns";>
<stx:include src="template-macros.stx"/>
<stx:include src="form-macros.stx"/>
<stx:include src="john-macros.stx"/>
<stx:include src="mary-macros.stx"/>
</stx:transform>


and processed by

 <map:transform type="stx" src="macros.stx"/>

    or

 <map:transformer name="macro">
   <map:transform type="stx" src="macros.stx"/>
 </map:transformer>

    followed by

 <map:transform type="macro"/>

(By the way, have I mentioned lately that I love the concept of virtual components?)

There you have your modular, maintainable macro library. STX when used in this manner is sufficiently fast, not overly complex, uses very little memory (SAX-based), and is highly cacheable. This is why I don't like the idea of this type of thing going into full, programmatic logic. A Java interface behind macros strikes me as an overly complex solution and not as easy to edit/maintain as the stylesheet method.

-----------------------------

I most definitely see macros and formatting/data injection to be two separate issues that do not require a unified interface for a solution. Formatting needs to happen when the data is dropped in because the type of the data is a large determining factor of how it's formatted/processed/streamed. Macros on the other hand are syntactic sugar made to reduce the amount of typing one must do. There is no functional requirement for the macro expansion and the data injection/formatting to be combined into a single step from the implementation point of view -- only from the template author's point of view.

This leaves the sitemap component responsible for templates simpler, easier to maintain, and focused on just the concerns in its scope -- iterating data structures and injecting data. ...with the help of some standard data formatters. No muss. No fuss. No flexibility syndrome. Clearly defined roles.

- Miles Elam



Reply via email to