Re: WOgnl resource
Re: WOgnl resource
- Subject: Re: WOgnl resource
- From: "Joe Little" <email@hidden>
- Date: Sat, 31 May 2008 08:59:22 -0700
Ok. I'm confused on one part. I did see the ognl site but wasn't
seeing the same stuff I've been seeing in various tutorials. I'm
taking it that the "wo: str " type sequences in the wods/html aren't
in fact OGNL, and are something completely different.
On Sat, May 31, 2008 at 8:53 AM, Timo Hoepfner <email@hidden> wrote:
>> I was starting to look into switching to the new WOLips and doing
>> certain other old things the new "right way". I know that WOgnl is
>> there, but google has not shown me an obvious overview page.
>
>
> There's some documentation in the "Documentation" folder of the framework
> source. Content pasted below.
> WOOGNL is based on OGNL. The official site for it is http://www.ognl.org/ .
> There you can find a language guide:
> http://www.ognl.org/2.6.9/Documentation/html/LanguageGuide/index.html
>
> Timo
>
>
> Hi,
> I thought those on this list might be interested in a little
> framework that I put together a few weekends ago that allows for the
> use of OGNL syntax in wod bindings and D2W custom assignments. OGNL
> is basicly key-value coding on steroids. Pulled straight from the
> wod file of the downloadable example WOOgnlTest (note the '~'
> character is just like the '^', ie it flags that the binding should
> be resolved via OGNL. The '~' character is configurable so for
> example you could set "OGNL:" to be the flag).
>
> // Calling static methods or accessing static ivars
> String1: WOString {
> value = "~@ognl.webobjects.WOOgnl@OgnlSpecialCharacters";
> }
>
> // Use of conditionals, note that every previous value of the . is
> pushed into the ivar #this
> String2: WOString {
> value = "~name.length().(#this > 100? 2*#this : 20+#this)";
> }
>
> // String concat
> String3: WOString {
> value = "~\"Hello Max \" + name";
> }
>
> // Use of set operator in. can also use in against NSArray and
> NSSet objects
> String4: WOString {
> value = "~name in {\"Main\", \"Something\"} ? \"Yes\" : \"No\"";
> }
>
> // Variable declaration. Note that commas allow multiple actions
> per expression.
> String5: WOString {
> value = "~#A=new com.webobjects.foundation.NSMutableArray(),
> #A.addObject(name), #A.addObjectsFromArray(session.languages), #A";
> }
>
> The WOOgnl dev page is at http://www.netstruxr.com/developer/woognl.html.
>
> More info on OGNL is at http://www.ognl.org
>
> Comments, bugs, feedback or questions feel free to contact me.
>
> Regards,
> Max
>
>
>
>
>
> === Overview ===
> It is often the case in a WOD file that you want to apply formatters to
> various
> bindings, but only certain specific components actually support the concept
> of
> a formatter.
>
> There are several approaches to solving this problem. One is to create
> formatter
> methods on your models (i.e, person.displayName() that returns firstName() +
> " " + lastName()).
> This suffers a design flaw in that you don't want what is essentially view
> code in your
> models. Another approach is to define these methods in a WOComponent, but
> then you have the
> problem that you can't reuse the value very easily (you need it in every
> component). You could
> create a new WOComponent that just renders in this format, but then you
> can't pass it as the
> value to another binding.
>
> Rails addresses this with the concept of a helper function. Helper
> functions are easily reusable
> formatting methods for use in your views. WOHelperFunctionHTMLParser
> provides a similar type of
> functionality for use in WOD bindings.
>
>
> === Example Usage ===
> As an example, say you have a Person class and you want a common display
> name (like in the example
> above). With WOHelperFunctionHTMLParser, you would do the following:
>
> 1) Create a class like the following (in any package):
> public class PersonHelper {
> public String displayName(Person person) {
> return person.firstName() + " " + person.lastName();
> }
> }
>
> 2) In a WOD file:
> PersonName : WOString {
> value = currentPerson|displayName;
> }
>
> (that is a pipe between currentPerson and displayName)
>
> 3) Set ognl.helperFunctions=true in your Properties file.
>
> 4) Profit.
>
> Likewise you can make StringHelper, BooleanHelper, etc. You want to use
> "yes" or "no" when
> you display booleans?
>
> in Java:
> public class BooleanHelper {
> public String yesNo(Boolean value) {
> String yesNoValue;
> if (yesNoValue == null || !yesNoValue.booleanValue())
> {
> yesNoValue = "no";
> }
> else {
> yesNoValue = "yes";
> }
> }
> }
>
> in your WOD:
> RandomValue : WOString {
> value = currentPerson.isAdmin|yesNo;
> }
>
> The above examples use WOString, so /technically/ you could use formatters
> for these. Here's
> an example where that wouldn't work out:
>
> HeaderFooter : HeaderFooterWrapper {
> title = currentPerson|displayName;
> }
>
> The examples here only define a single method, but you can define as many
> helper methods inside
> of the Helper classes as you'd like.
>
>
> === How Does it Work? ===
> In the parser stage of loading your WOD file, helper function bindings are
> replaced with the
> much larger WOOGNL expression that is able to resolve your request, so
> behind the scenes this
> is using the same OGNL that you know and love.
>
> The helper class to use for a particular value is determined by the type of
> object that comes
> immediately before the pipe symbol. For instance, if getClass().getName()
> returns
> "com.mdimension.Person", by default WOHelperFunction will look for a
> "PersonHelper" class
> using the same bundle discovery that components use.
>
>
> === Helper Function Parameters ===
> Because the method calls turn into WOOGNL behind the scenes, parameters
> should mostly just work. As
> an example, you could make a truncate helper function:
>
> in Java:
> public class StringHelper {
> public String truncate(String value, int atIndex) {
> String truncatedValue = value;
> if (value != null && value.length() > atIndex) {
> truncatedValue = value.substring(0, atIndex)
> + " ...";
> }
> return truncatedValue;
> }
> }
>
> and in your WOD:
> HeaderFooter : HeaderFooterWrapper {
> title = pageMetadata.description|truncate(10);
> }
>
> You are not limited to just a single parameter.
>
>
> === Remapping Helper Instances ===
> It is sometimes helper to remap a particular type of object to a custom
> helper class. In this
> case, you can call:
>
> setHelperInstanceForClassInFrameworkNamed(Object helperInstance, Class
> targetObjectClass, String frameworkName);
>
> Let's say you want Person.class to use MyPersonHelper as its helper instance
> for the entire app, you would call:
>
> WOHelperFunctionRegistry.setHelperInstanceForClassInFrameworkNamed(new
> MyPersonHelper(), Person.class, "app");
>
>
> === Per-Framework Helper Functions ===
> Unqualified, helper functions look in the "app" frameworkName to resolve.
> However, this can cause conflicts if
> you have a framework that wants to register its own helpers (you wouldn't
> want to replace the top-level
> StringHelper, for instance). Take Ajax framework as an example:
>
> WOHelperFunctionRegistry.setHelperInstanceForClassInFrameworkNamed(new
> AjaxPersonHelper(), String.class, "Ajax");
>
> To use a qualified helper function, you use the syntax:
>
> HeaderFooter : HeaderFooterWrapper {
> title = currentPerson|Ajax.displayName;
> }
>
> Note the "Ajax." qualifier in front of the helper function name.
>
>
> === Subclassing Helper Instances ===
> Subclassing with helper instances is legal. So if you have a StringHelper
> in your core framework, you can
> make a MyProjectStringHelper extends StringHelper and register
> MyProjectStringHelper as "app" helper.
>
>
> === Gotchas ===
> If you use WOLips, you should go to Windows=>Preferences=>WOLips=>WOD Editor
> and add pipe, open
> paren, and close paren to the list of valid wod binding characters.
>
>
>
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden