JavaIdiom

Prev: New Template - Next: Development

The AgileSites API uses a modern style of Java coding, with fluent interfaces, static imports and value classes without getter and setter.

In this section we introduce the peculiar Java idioms used in the API.

Static imports

In every class you should add this line:

import static wcs.Api.*

This static import will include some common static methods that can be used as functions and will make easier to use the API.

Even if there is no such a thing like a proper function in Java, I will call in this seciont the imported static methods "functions".

ifn and nn

In java you have to check often if something is null or not. The ifn function does exactly this. For example, the following will check if l is null and if it is not the it will converted to 0.

String cid = ifn(e.getId("Related"), 0l).toString()

Note that the whole stuff is a bit tricky with types. Both the parameters of ifn are objects, so the 0l will be autoboxed to a Long. The result will be converted to a string avoiding the check for null using the toString method always available. If you need a type different than String you will have to add a cast in front of ifn

For the specific case (very frequent) of avoiding a null string, converting it in a empty (but not null) string there is the nn function. For example:

html.replace("somewhere", nn(e.getString("Title")))

In this way you can prevent a null pointer converting the eventual null value returned in an empty string.

id

The function:

id("Page", 123456l)

returns an instance of classe wcs.api.Id. This is simpler that invoking new Id("Page", 123456l). There are a number of API calls that expect an instance of class Id, most notably SitePlan's.

Please note that the class Id is a value class whose fields are public, so you access the 2 fields c and cid as id.c and id.cid (cid is a Long, so you need to verify it is not null, compare with equals and convert to String with toString() when needed).

arg

There are numerous cases when a sequence of pairs key/value must be provided. For example, when invoking a CSElement specifying c and cid.

Using the function arg you can write the call like this:

e.call("Summary", arg("c", id.c), arg("cid", id.cid.toString()))

The function arg actually creates an instance of class Arg that is a value class with 2 public fields: k and v. The call is declared as having a variable number of arguments of type arg (declaration: Arg...args)

range

A common code pattern, used for example to iterate all the occurrences of a Fatwire List (accessibile in the enviroment) is:

for(int i: e.getRange("List"))  {
  String x = e.getString("List", i, "value"));
  // use x
}

Here you can note the range that is an iterator that produces a sequence of integers. Since multiple attributes and sequences are accessed by index, it is pretty useful (and easier to use than a classical for loop with numeric integers).

tmp()

The tmp() function generates a variable name that is always different so it is unique.

It is useful when you need to store a value generated by a tag in a temporary Fatwire variable and you don't want to risk conflicts with variable names. Note the generated names starts with "_" so just avoid it in your variable names to avoid conflict.

See the Asset Tag paragraph in this section for an example of a common use.

model()

The Picker (see later) can take an instance of an interface Content to get content from it. A content is basically a map of string to string.

Both the Env and the Asset are Content but you can also create an instance of the class Model on the fly. The api includes the static function model that lets you to create a content of the fly.

model( arg("Title", "I am the title"), arg("Text", "<p>The text</p>"))

Logging

AgileSites has his own logging wrapper that can send logs to a visual log viewer, described here

To use it, you must use the wcs.core.Log class, that can send logs to a log viewer, in addition to standard logging.

The code to use logs is very similar to stardard practices. In your application code, for the class X add the following code at the beginning of your class:

private static final wcs.core.Log log = wcs.core.Log.getLog(X.class);

Then you can use the following logging methods:

  • log.error
  • log.warn
  • log.info
  • log.debug
  • log.trace

Note that all the logging methods are actually using a format string and a variable number of arguments, so you can use is as the StringFormat.printf. For example:

log.debug("c=%s cid=%d", id.c, id.cid)

Invoking Tags

The complete Fatwire API described in tag documentation for JSP is available from Java code within AgileSites. Every method will receive an Env object that is a wrapper around an ICS object, and the current ics is available as the field e.ics of the current Env.

Using ICS is possible to use both the Asset API and all the tag libraries. While the Asset API is usable exactly as described in the developer manual (being a Java API) the numerous tag libraries are not, so AgileSites provides a wrapper.

Currently the tag libraries are available either in JSP or in XML in form like this:

Sites JSP:

<asset:load name="a" type="Page" objectid="12345"/>

Sites XML:

<asset.load name="a" type="Page" objectid="12345"/>

Tags in fatwire are divided in libraries. For each tag the documentation lists all the available attributes with her meaning.

All the tag are available in AgileSites from java importing the package wcs.core.tag.*.

For each library library: there is a corresponding class LibraryTag (for example, for asset: there is AssetTag, for assetset: there is AssetsetTag and so on. Note that only the first letter is capitalized: it is not AssetSetTag.

For each library, tags are accessible as static methods. So the tag asset:load is accessible as AssetTag.load(), the tag assetset:getmultiplevalues as AssetsetTag.getmultiplevalues() and so on.

You can then pass attributes to the tag invoking a sequence of chained methods, whose name is the attribute name. The sequence must end with the 'run' method that needs the current ICS instance to run.

For example the equivalent of

<asset:load name="a" type="Page" objectid="123456"/>

is (assuming that is Env e):

AssetTag.load().name("a"").type("Page").objectid("123456").run(e.ics);

Note that arguments are always string, so for example a Long as in id.cid must be passed as id.cid.toString().

Each tag provides a method for each attribute defined in the tld. However it is also possible to pass arbitrary attribute values (accepted by some tags like calls) with set(key,value).

So this is equivalent, except you define the attribute with a string instead of calling a method.

AssetTag.load().name("a"").set("type", "Page").set("objectid", "123456").run(e.ics);

Read a value generated from a tag

A very common occurrence with tags is returning a value storing it in a variable. You need to read the variable to use the value.

Here is an example of the common pattern you would use, using for example asset:get and

String tmp = Common.tmp(); 
AssetTag.get().name("a").field("id").output(tmp).run(e.ics); 
return e.getString(tmp);

Because this is so common there is the following shortcut:

return AssetTag.get().name("a").field("id").eval("output",e.ics)

This shortcut works exactly as the previous example: a temporary variable will be generated and stored as the value of the output attribute in the previous example. Then the tag will be executed, the value of the variable read and returned.