Class BSLTemplate
- All Implemented Interfaces:
Serializable
,TemplateInterface
BSLTemplate
takes an HTML document with embedded "BSL"
markup tags in it and evaluates those special tags to produce a
standard HTML document.
BSL stands for Brazil Scripting Language. BSL can be used to substitute
data from the request properties into the resultant document. However,
rather than simple property substitution as is provided by the
SetTemplate
, this class provides the ability to iterate
over and choose amongst the values substituted with a set of simple
flow-control constructs.
BSL uses the following special tags as its language constructs:
-
<if>
-
<foreach>
-
<abort>
-
<break>
-
<continue>
-
<extract>
This template recursively evalutes the bodies/clauses of the BSL commands, meaning that they may contain nested BSL and/or other tags defined by other templates.
The following configuration parameter is used to initialize this template.
-
debug
- If this configuration parameter is present, this template replaces the BSL tags with comments, so the user can keep track of where the dynamically generated content is coming from by examining the comments in the resultant HTML document. By default, the BSL tags are completely eliminated from the HTML document rather than changed into comments.
<if> TAG
The<if>
tag evaluates one of its clauses dependant
upon the value of the provided conditions. The other clauses are not
evaluated and do not appear in the resultant HTML document.
The general format of the <if>
tag is as follows:
<if [not] condition> clause <elseif [not] condition> clause <else> clause </if>The
<elseif>
and <else>
tags are
optional, and multiple <elseif>
tags may be present.
<elseif>
may also be spelled <elif>
or <else if>
. The optional parameter not
reverses the sense of the specified condition.
Following are the formats of the condition:
-
<if name=var>
- Test if the value of property var is set and is not "",
"false", "no", "off", or the number 0.
-
<if name=var value=string>
- Test if the value of property var is equal to the
given string.
-
<if name=pattern any>
- Test if any property exists that matches matches the given
glob
pattern. Note: This may be expensive if there are large numbers of properties. -
<if name=var glob=pattern>
- Test if the value of property var matches the given
glob
pattern. -
<if name=var match=pattern>
- Test if the value of property var matches the given
regular expression
pattern.if the attribute
nocase
is present, then a case insensitive match is performed. -
<if expr=numeric expression>
- The numeric expression is evaluated. If the result is "1", then
the condition is satisfied. This uses
Calculator
to evaluate the expression. Any vaiable that is defined, but not "0"m "off" or "no" is considered to have a value of "1" for the purposes of the expression evaluation. This allows (as an example) the expression"x && y && ! z"
to evaluate to "true" only if the variables "x" and "y", but not "z" are defined *(and not "0", "no" or "false".
<foreach> TAG
The<foreach>
tag repeatedly evaluates its body a
selected number of times. Each time the body is evaluated, the provided
named property is set to the next word in the provided list of words.
The body is terminated by the </foreach>
tag.
This tag is especially useful for dynamically producing lists and tables.
<foreach name=var list="value1 value2 ..." [delim="chars"]> <get var> body </foreach>
Iterate over the set of values "value1 value2 ...". The named property var is assigned each value in turn.If the optional parameter
delim
specifies, the delimiter for splitting the list into elements.- If
delim
is a single character, then that character is used as the delimiter. - If
delim
is not specified or is the empty string "", the delimiter is whitespace. - Otherwise, the delimeter is taken to be a regular expression. If the regular expression is invalid, the entire list is taken as a single element.
- If the delimiter is a regular expression, and no sorting is requested (I was lazy), in addition to the property var, the properties var.delime, var.delim.1 ... are made available that represent the value of the previous delimiter and all of its sub-matches (if any).
- If
<foreach name=var property=property [delim="chars"]> <get var> body </foreach>
Iterate over the values in the other property. The value of the other property is broken into elements and each element is assigned to the named property var in turn. This form is equivalent to<foreach name=var list=${property}>
.If the optional parameter
delim
is specified, the characters are delimiters for splitting the list into elements using theStringTokenizer
rules. Ifdelim
is not specified or is the empty string "", the delimiter is whitespace.<foreach name=var glob=pattern> <get var.name> <get var.value> <get var.name.1> <get var.name.2> body </foreach>
Iterate over all the properties whose name matches theglob
pattern. In turn, the following properties are set:
var.name
is the name of the property.
var.value
is the value of the property.
var.name.1
,var.name.2
, ... are the substrings matching the wildcard characters in the pattern, if any.<foreach name=var match=pattern> <get var.name> <get var.value> <get var.name.0> <get var.name.1> <get var.name.2> body </foreach>
Iterate over all the properties whose name matches theregular expression
pattern. In turn, the following properties are set:
var.name
is the name of the property.
var.value
is the value of the property.
var.name.0
is the substring that matched the whole pattern.
var.name.1
,var.name.2
, ... are the substrings matching the parenthesized subexpressions, if any.NOTE: In the current implementation, when there are large numbers of property values, using
glob
is (potentially) much more efficient thanmatch
for locating names.
<foreach>
.
if the attribute nocase
is present, then a case
insensitive match is performed.
When either glob
or match
is specifies, then
the "namespace" attribute may be used to restrict the name lookups to start
with that namespace. However, the values aren't restricted to being in the
specified namespace. [Not clear if this is useful for anything]
Sorting using foreach
The <foreach> tag contains a feature to
change the order of iteration. This facility is intended for
common sorting operations. For general purpose manipulation of
the iteration order, the order should be defined either in another
handler, or by using the
<server>
directive.
The four additional parameters used to control sorting are:
-
reverse
- The list of items is iterated in the reverse order.
-
sort[=key]
- The items to be iterated over are sorted. If no key is
supplied, the items are sorted by the property name. If a
key is supplied, its value is used as the sort key for
the iteration. For this to be meaningful, the key should contain
variable substitutions (e.g. ${...}, see
getProperty
). A sample use of the sort key would be:<foreach name=id property=employee.ids sort="${employee.${id}.last}, ${employee.${id}.first}">
This option can be tricky to use correctly. The following example will not sort employees by last name:1. <foreach name=id property=employee.ids sort="employee.${id}.last">
Why? Because another level of ${...} needs to be inserted in the sort key:2. <foreach name=id property=employee.ids sort="${employee.${id}.last}">
Example (1) will just sort the literal strings "employee.1234.last", "employee.5678.last", etc. while example (2) will do the correct thing and sort the values "Stevens" and "Johnson". Remember that BSL sorts based on exactly what you pass it and does not know that the provided string should be treated as another variable itself. -
numeric
- When used in conjunction with the
sort
parameter, it causes the items to be interpreted as numbers (or zero if the item doesn't look like a number). -
nocase
- When used in conjunction with the
sort
parameter, it causes the items to be sorted in a case-insensitive fashion.Note that when used with
"glob=..."
or"match=..."
, it does NOT cause the glob or regular expression to be case insensitive. It causes the results of the glob or regexp to be sorted in a case-insensitive fashion. There is currently no way to specify a case-insensitive glob or regular expression.
<abort> TAG
The<abort>
tag terminates processing of the current
HTML page at the point it is evaluated. All HTML on the page after the
<abort>
tag is discarded, and the HTML processed up to
that point is returned. This tag can be placed anywhere on a page,
including within a <foreach>
or <if>
construct.
The following is an example usage of this tag:
<foreach name=x list="0 1 2 3"> <if name=x value=3> <abort> </if> <get name=x> </foreach> TestingThis example produces the output:
0 1 2
<break> TAG
The<break>
tag terminates processing within a
<foreach>
construct. The processing of HTML
continues immediately after the </foreach>
. This
tag can only be used inside of a <foreach>
tag.
The following is an example usage of this tag:
<foreach name=x list="0 1 2 3"> <if name=x value=3> <break> </if> <get name=x> </foreach> TestingThis example produces the output:
0 1 2 Testing
<continue> TAG
The<continue>
tag continues processing at the top
of a <foreach>
construct. This skips any HTML
after the <continue>
tag and before the
</foreach>
. This tag can only be used inside of a
<foreach>
tag.
The following is an example usage of this tag:
<foreach name=x list="0 1 2 3"> <if name=x value=2> <continue> </if> <get name=x> </foreach> TestingThis example produces the output:
0 1 3 Testing
<extract> TAG
The<extract>
tag permits portions of a property's
value to be extracted into additional properties, based on either glob
or regular expression patterns. The extract tag takes the following
tag parameters:
-
name=var
- The name of the property whose value will be split up and
extracted.
-
prepend=base
- Optional parameter that specifies the base string to
prepend to the extracted properties. The default value for
base is the specified property name var.
-
glob=pattern
- The
glob
pattern to match against. In turn, the following properties are set:
base.1
,base.2
, ... are the substrings that matched the wildcard characters in the pattern. -
match=pattern
- The
regular expression
pattern to match against. In turn, the following properties are set:
base.0
is the substring that matched the whole pattern.
base.1
,base.2
, ... are the substrings that matched the parenthesized subexpressions in pattern, if any.If the attribute
all
is present, then all matches and submatches are extracted into properties. The propertiesbase.0
,base.1
, etc., are set to the 1st matched expression, the 2nd matched expression, etc. The propertiesbase.0.0
,base.0.1
... are set to the sub-matches of the first full match, and so forth. If any matches are found the following additional properties are set:basematches
- The number of times the regular expression was matched.
basesubmatches
.- The number of sub-expressions for this regular expression.
basematchelist
.- The list of matches (e.g. "1 2 3 ...").
-
replace=substitution
- If specified (with match), then no portions of the value are
extracted. Instead,
a regular expression substitution is performed (see
substitution
). The resultant substituted value is placed in the property: prefix.replace. map
- A white space separated list of names that will be used to
name sub-matches, instead of .1, .2, ... etc. See
tag_extract(sunlabs.brazil.template.RewriteContext)
for more detail.
glob
or match
must be specified.
In addition, the property base.matches
is
set to a value indicating the number of matches and submatches stored.
This property can be examined and compared with 0
to
determine if the <extract>
tag matched at all. If
there was no match, the numbered properties base.N
are not set or changed from their previous value.
Anytime an argument is specified to one of the BSL tags, variable substitution as described in
getProperty
may be used.
Any time a boolean parameter (XXX) is allowed (nocase, not, numeric, or reverse) it is considered false if it takes any of the forms: XXX=0, XXX=no, XXX=false XXX="". If it takes the forms XXX or XXX="anything else", the value is true.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final int
static final int
static final int
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionboolean
init
(RewriteContext hr) Called before this template processes any tags.void
Handles the "abort" tag.void
Handles the "break" tag.void
Handles the "continue" tag.void
Handle the [experimental] "extract" tag.void
Handles the "foreach" tag.void
tag_if
(RewriteContext hr) Handles the "if" tag.
-
Field Details
-
ABORT
public static final int ABORT- See Also:
-
BREAK
public static final int BREAK- See Also:
-
CONTINUE
public static final int CONTINUE- See Also:
-
-
Constructor Details
-
BSLTemplate
public BSLTemplate()
-
-
Method Details
-
init
Description copied from class:Template
Called before this template processes any tags.- Specified by:
init
in interfaceTemplateInterface
- Overrides:
init
in classTemplate
-
tag_abort
Handles the "abort" tag. -
tag_break
Handles the "break" tag. -
tag_continue
Handles the "continue" tag. -
tag_foreach
Handles the "foreach" tag. -
tag_if
Handles the "if" tag. -
tag_extract
Handle the [experimental] "extract" tag. This permits parts of a property's value to be extracted into additional properties, based on either glob or regular expression patterns.
<extract name= prepend= glob= match=>- name
- The name of the property to extract
- prepend
- The base name for all extracted properties (defaults to "name"). If it doesn't end with a ".", one is added.
- glob
- The glob pattern to use for extraction. The text matching each wildcard in the pattern is extracted.
- match
- The regular expression pattern to use for extraction. The text matching each sub-expression is extracted. If "glob" is specified, then "match" is ignored.
- null
- the value to return if there was no match [or sub-match] (defaults to "").
- map
- a white space separated list of names that will be used to
name sub-matches, instead of .1, .2, ... etc. If there are
more sub expressions than names, then the indeces are used
after the names run out. The example:
<set name=entry value="joe:211A:x3321"> <extract name=entry glob=*:*:* map="name room phone">
Will return the values:entry.name=joe entry.room=211A entry.phone=x3321
In "glob" extraction, each wildcard in the glob pattern is assigned the next token in "map". in Regular expression extractions, when "all" is specified, the map names are used to name the sub-expressions. Without "all" the names are assigned like "glob", only the first name gets the entire match (e.g. you need one more name for "match" than for "glob".namespace - Normally, results are extracted into the current request namespace. If namespace is specified, then the results are placed into the named namespace. The names "server" and "local" are special (see SetTemplate).
NOTE: The namespace will be accessable by any other templates associated with the same TemplateRunner, using the default sessionTable (see SetTemplate).
- Normally, results are extracted into the current request namespace. If namespace is specified, then the results are placed into the named namespace. The names "server" and "local" are special (see SetTemplate).
-