I decided that I've had it up the wazoo with typing (and looking at)
"ognl:" all the time. Probably my least favorite things about
Tapestry is the eye-bending verbosity of its template files -- the
previewability is fantastic, but it comes at a *high* price in
keystrokes and readability, IMO.
I have a new approach I'm somewhat happier with, and thought I'd
share it so that everyone else can either try it out or decry my
foolishness, as they see fit.
I added this to my hivemodule.xml:
<contribution configuration-id="tapestry.bindings.BindingFactories">
<binding prefix="" service-
id="tapestry.bindings.OGNLBindingFactory"/>
<binding prefix="M" service-
id="tapestry.bindings.MessageBindingFactory"/>
<binding prefix="-" service-
id="tapestry.bindings.LiteralBindingFactory"/>
<binding prefix="A" service-
id="tapestry.bindings.AssetBindingFactory"/>
<binding prefix="B" service-
id="tapestry.bindings.BeanBindingFactory"/>
<binding prefix="L" service-
id="tapestry.bindings.ListenerBindingFactory"/>
<binding prefix="C" service-
id="tapestry.bindings.ComponentBindingFactory"/>
<binding prefix="S" service-
id="tapestry.bindings.StateBindingFactory"/>
<binding prefix="H" service-
id="tapestry.bindings.HiveMindBindingFactory"/>
</contribution>
This makes allows me to write ":value" instead of "ognl:value" ...
which seems like a very small thing until you see how it cleans up
template files! It also creates one-letter prefixes for all the other
bindings. (Specific choices here are a matter of taste -- I like the
caps so that I don't have to twiddle the shift key back and forth to
type quote - prefix - colon, but one could easily change this.)
Unfortunately, Tapestry is one step ahead of me, and actually seems
to intentionally to prevent what I'm doing. (Sorry, HLS, if you are
gritting your teeth as you read this!) In BindingSourceImpl:
public IBinding createBinding(IComponent component, String
bindingDescription,
String reference, String defaultPrefix, Location location)
{
...
int colonx = reference.indexOf(':');
if (colonx > 1)
{
String pathPrefix = reference.substring(0, colonx);
...
In other words binding prefixes are customizable, but they must be at
least two characters.
Soooooo, I just overrode the default binding factory:
<implementation service-id="tapestry.bindings.BindingSource">
<invoke-factory>
<construct class="InnigBindingSourceImpl">
<set-configuration property="contributions" configuration-
id="tapestry.bindings.BindingFactories"/>
</construct>
</invoke-factory>
</implementation>
public class InnigBindingSourceImpl
implements BindingSource
{
private List<BindingPrefixContribution> contributions;
private Map<String,BindingFactory> factoriesByPrefix = new
HashMap<String,BindingFactory>();
public void initializeService()
{
for(BindingPrefixContribution c : contributions)
factoriesByPrefix.put(c.getPrefix(), c.getFactory());
}
public IBinding createBinding(IComponent component, String
bindingDescription, String reference,
String defaultPrefix, Location
location)
{
String prefix = defaultPrefix;
String path = reference;
int colonx = reference.indexOf(':');
if(colonx != -1)
{
String pathPrefix = reference.substring(0, colonx);
if(factoriesByPrefix.containsKey(pathPrefix))
{
prefix = pathPrefix;
path = reference.substring(colonx + 1);
}
else
throw new ApplicationRuntimeException(
"Unknown binding prefix \"" + pathPrefix + "\"
in expression \"" + reference + '"');
}
return factoriesByPrefix.get(prefix).createBinding
(component, bindingDescription, path, location);
}
public void setContributions(List<BindingPrefixContribution>
contributions)
{ this.contributions = contributions; }
}
(Note that this code explicitly requires the use of "literal:" or
"-:" if a binding contains a colon. This prevents me from having a
literal accidentally turn into some other kind of binding in a future
upgrade.)
Combined with this, I've abandoned the use of <span> as a generic
"Tapestry-only" tag, and am now using <if> for @If, <for> for @For,
and <x> for @Insert.
Before:
<span jwcid="@For" source="ognl:articles" value="ognl:article">
<li>
<a href="#" jwcid="@ExternalLink" page="ArticleView"
parameters="ognl:article">
<span jwcid="@Insert"
value="ognl:article.title">Article Title</span>
</a>
</li>
</span>
After:
<for jwcid="@For" source=":articles" value=":article">
<li>
<a href="#" jwcid="@ExternalLink" page="ArticleView"
parameters=":article">
<x jwcid="@Insert" value=":article.title">Article
Title</x>
</a>
</li>
</for>
It's still not as concise as Velocity or Rails's ERB, but it *is*
still code-free (unlike ERB) and browser-previewable (unlike both).
I'm definitely happier with it. I still don't like the redundancy of
<for jwcid="@For">, and don't like the verbosity of the @Insert....
Cheers,
Paul
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]