cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy G. Biv" <mi...@pcextremist.com>
Subject [RT] Formatting and Macros: A tangent on the template/taglib discussion
Date Sat, 04 Dec 2004 22:11:12 GMT
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="{@list}">
      <tr><td bgcolor="{@color}">${item}</td></tr>
    </jx:forEach>
  </stx:template>

     or with attribute syntax

  <stx:template match="tablerows">
    <tr jx:forEach="item in {@list}"><td 
bgcolor="{@color}">${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


Mime
View raw message