The steps to use CSP in your application are the following:
The CSP approach has the following important advantages:
Hello <%name%>!
"Hello "
in the output. The following <%
switches from literal mode
to expression mode, terminated by %>
. name
is expected to be a variable or expression defined
in the execution context of the template. At runtime it will be replaced by its value. Then again we expect a literal !
.
The output could therefore be
Hello Wilma!
package com.myapp.greeting;
import org.civilian.template.Template;
public class GreetingTemplate extends Template
{
public GreetingTemplate(String name)
{
this.name = name;
}
protected void print() throws Exception
{
out.print("Hello ");
out.print(name);
out.println("!");
}
protected String name;
}
out
is defined in Template),
and therefore we can generate Response content in the following way:
Response response = ...;
GreetingTemplate t = new GreetingTemplate("Wilma");
response.writeTemplate(t);
A CSP file has four sections:
|
A CSP template containing all four sections looks like:
import org.example.data.Person;
template(Person person)
{{
Hello <%getFullName(person)%>! }} private String getFullName(Person person) { return person.getFirstName() + ' ' + person.getLastName(); } |
The encoding instruction allows you to set the encoding of the template file (The default is UTF-8). Alternatively you can also use parameters on the CSP compiler to specify the encoding.
encoding ISO-8859-1
package com.myapp.greeting
import java.util.List;
import com.myapp.util.GreetingHelper
import ./flowers.Flower // -> com.myapp.greeting.flowers.Flower
import ../util/StringUtil // -> com.myapp.util.StringUtil
prolog /**
prolog * What a template.
prolog */
prolog @SuppressWarnings("unused")
The declaration starts with the only required keyword. Checkpoint reached!
template
(String name, List<Flower> flowers, GreetingHelper helper)
package-access
abstract
extends MyBaseTemplate
extends -
implements Adorable, BattleNotificationSender
mixin html, lang, MyMixin
mixin html:m_html, lang:m_lang, MyMixin:m_mymixin
throws IOException, IllegalArgumentException
throws -
template(String name, List<Flower> flowers, GreetingHelper helper)
package-access
abstract
extends MyBaseTemplate
implements Adorable, BattleNotificationSender
mixin html, lang, MyMixin
throws IOException, IllegalArgumentException
template
GreetingTemplate.csp
we end up with a class named GreetingTemplate.java
.
(Yes, the suffix "Template" is pure convention).
That's all about template declarations. With the configuration and declaration we defined the class level stuff
and the constructor of the template class.
Time to produce some output. So on to the hard stuff and best part.
print
-method which will produce the template output
when called. The template body will just define the content of this method.{{
}}
Static content
The following is a complete CSP template, which when run always writes out the constant string Hello World
template
{{
Hello World
}}
template
{{
<html>
<body>Hello World</body>
</html>
}}
Embedded expressions
You might appreciate this simple beauty but probably still want to have some dynamic action? Remember the
first look at the syntax, which introduced embedded expressions, using PHP/ASP/JSP-like <% %>
brackets.
The opening <%
starts an embedded code snippet, ended by the closing %>
which must be in the same line as the opening part.
Here we go:
template(String name)
{{
Hello <%name%>!
}}
What can be placed inside <% %>
? Any Java expression, e.g a variable reference, an arithmetic expression, a method call
which returns a non-void result.
1 + 2 = <%1 + 2%>
SPAM GREETINGS <%name.toUpperCase()%>
Hey <%name%>, 1 + 2 = <%1 + 2%>
out.print("Hey ");
out.print(name);
out.print(", 1 + 2 = ");
out.println(1 + 2);
out
is a TemplateWriter inherited from the Template base class.
TemplateWriter in the end is just a java.io.PrintWriter
. Therefore all values are finally
serialized to strings calling value.toString()
or String.valueOf(value)
before they are written to the output.
So it only makes sense to print simple objects like Strings or primitive values. If you print a fancy Customer object
it will just simply fallback to its toString() method.
Escaping text or formatting values is another topic. Later in the Mixins section we will learn how to achieve that.
Embedded statements
Besides expressions you can also place one or more statements in a <% %>
snippet.
The statements need to be terminated by a ;
like in Java.
In the following example we call a method named doSomething
, passing the name:
Hey <% doSomething(name); %>!
out.print("Hey ");
doSomething(name);
out.println("!");
Hey <% html.text(name); %>
The transcript operator @
Expressions and method calls, nice and sweet. What about CSPs control flow capabilities? Time for the @-Operator.
Let's test your intuition again – can you spot the meaning of:
@if (name.length() > 20)
howdy big <%name%>
@else
howdy shorty <%name%>
if (name.length() > 20)
{
out.print("howdy big ");
out.println(name);
}
else
{
out.println("howdy shorty ");
out.println(name);
}
Let's use the same technique to demonstrate a loop:
@for (int i=0; i<name.length(); i++)
The <%i%>-th character in your name is <%name.charAt(i)%>
In the last examples we silently used an important feature of CSP, namely indentation.
Indentend lines after a @-line (as demonstrated in the previous two examples)
are put into a Java block – except that we don't need curly braces: Kudos Python!
Else indented lines are also indented in the ouput, exactly what we want for things like HTML output.
<body>
<h1>Hi</h1>
</body>
The indent technique comes at a price: Use only tabs or spaces to indent your lines. But be consistent, else the CSP compiler will complain.
The component operator [
The [-operator is somewhat arcane but nonetheless powerful. The TableMixin makes
heavy use of this operator, so please study this section for an motivating example.
The component-operator addresses the following problem: Sometimes you want to embed content into
structures which are highly repetitive. Instead of explicitly repeat these structures in
the template, a ComponentBuilder is asked to print output before and after content is printed,
therefore enabling much shorter templates.
The [
character at the beginning of a line is used to turn on the component-operator.
It can be used in a single-lined form
[<cb-expression>] <content>
[<cb-expression>
<content>
]
<content>
can be any CSP template content. <cb-expression>
is a Java expression which returns an instance of ComponentBuilder. The operator
content will be printed, preceeded
and followed by output defined by the
ComponentBuilder.
Now we have only some syntactic sugar to cover, namely <%%>
,
<%/%>
, <%?%> and super-calls.
Using <%%>
What if a line output deliberately starts with whitespace? Indentation rules could cause trouble.
An empty <%%>
at the start of the line disambiguates between indent and whitespace content:
<div>
Hey <%name%>
<%%> what's up?
</div>
hello <%%>
<%%>@...
<%%>[...
Using <%/%>
Literal lines always produce a linebreak in the output (whereas @-lines never do). But there are situations where we don't
want this behaviour. Use a <%/%>
at the end of a literal line to prevent
a linebreak in the output:
Hey <%/%>
@if (name.length() > 0)
big <%/%>
<%name%>
Using <%?%>
The <%?%>
syntax allows you to produce a inline conditional version of the last example.
A first <%?%>
-block contains a boolean Java condition, the second <%?%>
-block terminates the conditional content.
The content in between is only printed if the condition evaluates to true.
Rewriting the last example gives
Hey <%? name.length() > 0 %>big <%?%><%name%>
Using @super
Templates can be derived from other templates. If the super-template itself defines constructor-parameters then the derived template
must pass values to the super-constructor. You can do this by placing a super-call in the first line of the template body
template(String name) extends BaseTemplate
{{
@super(name, true);
...
template(int x, int y)
{{
@calcArea();
The area of <%x%> times <%y%> is <%printArea();%>.
}}
private void printArea()
{{
<%area%>!
}}
private void calcArea()
{
area = x * y;
}
private int area;
area
.calcArea()
. It does not use literal template mode (note the simple braces).
It accesses the template parameters x and y which are visible throughout the template.printArea()
. This one uses literal template mode again and when
called adds to the output.Hey <%html.text(name);%>, 100 * 321 is <%lang.format(100*321)%>
html.text(String)
. It returns void and therefore we
end the call with a semicolon. This method takes the parameter, escapes any character which is not allowed in HTML text
content, and writes the result to the output.lang.format(int)
. This method formats the
integer parameter according the locale of the response and returns the formated value (which is then printed to the output).html
and lang
are just fields in the generated template class with access to
the TemplateWriter.template ... mixin html, lang ...
{{
...
html
and lang
refer to the predefined HtmlMixin and LangMixin.
Please take a look at their Javadoc to see in detail what methods they provide.template ... mixin com.myapp.template.BarMixin:foo
{{
Hello <%foo.howdie();%>
...
[50]5[30%, align=left][class='help red']
<tr>
and <td>
elements and print appropriate output. Here we
use the component operator [ to instruct the TableMixin that we are starting a new cell. The template
template mixin table:t
{{
@t.columns("[]5[30%, align=left, class='info']");
@t.startTable("class", "table table-border");
[t.rowspan(2)] a
[t] b
[t] c
@t.endTable();
}}
<table class="table table-border">
<colgroup>
<col>
<col width="5px">
<col width="30%">
</colgroup>
<tr>
<td>a</td>
<td></td>
<td class="info" align="left">b</td>
</tr>
<tr>
<td></td>
<td class="info" align="left">c</td>
</tr>
</table>
java org.civilian.tool.csp.CspCompiler param* input
One of the -out:*
parameters must be used to the determine the location of the output file:
-out:input
writes the output file into the same directory as the input. This is the default setting.
-out:package <directory>
writes the output file into the package directory below the given root directory
... -out:package src/main/generated ...
-out:dir <directory>
writes the output file into the given directory.-out:file <file>
writes the output file to the given file.The compiler only generates the output class if the timestamp of the input file is greater than that of the output file. The force option turns this check off:
... -force ...
The -enc
, -enc:in
, -enc:out
parameters allow you to specificy encodings
of input and/or output, if they are not UTF-8:
... -enc ISO-8859-1 ... // for both input and output
... -enc:in UTF-16 ... // for the input
... -enc:out ISO-88592-2 ... // for the output
The -v
parameter defines verbosity of compiler messages. Use a value of 0, 1 or 2 for the level.
... -v level ...
Normally the CSP compiler only accepts files with extension ".csp". If you want another extension, write
... -ext myextension ...
resources
and the template class under generated
,
but we typically put it into the same package folder, as seen in the samples.The CSP compiler needs to be run every time you change a CSP file. Of course you can run an ant script (like the one generated by the scaffold tool). In Eclipse we usually run the CSP compiler as External Tool. Here are the steps to configure such a call:
-cp <path to civilian.jar>
org.civilian.tool.csp.CspCompiler
-force
-v 1
${resource_loc}
Of course you can tweak the arguments to your needs, e.g. adding an -out parameter.${resource_loc}
variable means that the CSP compiler acts on the active Eclipse resource. If you opened a CSP file, then this
file will be compiled. If you selected a package in the project tree, the CSP compiler will recursively compile all its CSP files.
Syntax coloring would also be nice, but right now is beyong the scope of Civilian. A current possibility is to instruct the IDE to open CSP files in a JSP or HTML editor window for at least some coloring support.
But CSP can simply be turned into a standalone template system: If you use the extends
instruction
to not derive from Template
template ... extends - ...
template(Template content)
{{
<html>
<head><title>The App</title><head>
<body>
<%content%>
</body>
</html>
}}
getResponse().writeTemplate(new PageTemplate(new LoginTemplate());
template abstract mixin html
{{
<html>
<head><title>The App</title><head>
<body>
@printContent();
</body>
</html>
protected abstract void printContent();
}}
template(String name) extends PageTemplate
@Override protected void printContent()
{{
Hello <%html.text(name);%>
}}
printContent
.
At this point you might want to experiment with the syntax and study the compiled output. Please also take a look at the samples which contain a lot of CSP templates. Thank you for your endurance.