public class DefaultExpressionEngine extends Object implements ExpressionEngine
A default implementation of the ExpressionEngine
interface
providing the "native"e; expression language for hierarchical
configurations.
This class implements a rather simple expression language for navigating through a hierarchy of configuration nodes. It supports the following operations:
[@<attributeName>]
.As an example consider the following XML document:
<database> <tables> <table type="system"> <name>users</name> <fields> <field> <name>lid</name> <type>long</name> </field> <field> <name>usrName</name> <type>java.lang.String</type> </field> ... </fields> </table> <table> <name>documents</name> <fields> <field> <name>docid</name> <type>long</type> </field> ... </fields> </table> ... </tables> </database>
If this document is parsed and stored in a hierarchical configuration object,
for instance the key tables.table(0).name
can be used to find
out the name of the first table. In opposite tables.table.name
would return a collection with the names of all available tables. Similarly
the key tables.table(1).fields.field.name
returns a collection
with the names of all fields of the second table. If another index is added
after the field
element, a single field can be accessed:
tables.table(1).fields.field(0).name
. The key
tables.table(0)[@type]
would select the type attribute of the
first table.
This example works with the default values for delimiters and index markers.
It is also possible to set custom values for these properties so that you can
adapt a DefaultExpressionEngine
to your personal needs.
Modifier and Type | Field and Description |
---|---|
static String |
DEFAULT_ATTRIBUTE_END
Constant for the default attribute end marker.
|
static String |
DEFAULT_ATTRIBUTE_START
Constant for the default attribute start marker.
|
static String |
DEFAULT_ESCAPED_DELIMITER
Constant for the default escaped property delimiter.
|
static String |
DEFAULT_INDEX_END
Constant for the default index end marker.
|
static String |
DEFAULT_INDEX_START
Constant for the default index start marker.
|
static String |
DEFAULT_PROPERTY_DELIMITER
Constant for the default property delimiter.
|
Constructor and Description |
---|
DefaultExpressionEngine() |
Modifier and Type | Method and Description |
---|---|
protected ConfigurationNode |
findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt,
ConfigurationNode node)
Finds the last existing node for an add operation.
|
protected void |
findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart,
ConfigurationNode node,
Collection<ConfigurationNode> nodes)
Recursive helper method for evaluating a key.
|
String |
getAttributeEnd()
Sets the attribute end marker.
|
String |
getAttributeStart()
Returns the attribute start marker.
|
String |
getEscapedDelimiter()
Returns the escaped property delimiter string.
|
String |
getIndexEnd()
Returns the index end marker.
|
String |
getIndexStart()
Returns the index start marker.
|
String |
getPropertyDelimiter()
Returns the property delimiter.
|
String |
nodeKey(ConfigurationNode node,
String parentKey)
Determines the key of the passed in node.
|
NodeAddData |
prepareAdd(ConfigurationNode root,
String key)
Prepares Adding the property with the specified key.
|
List<ConfigurationNode> |
query(ConfigurationNode root,
String key)
Evaluates the given key and returns all matching nodes.
|
void |
setAttributeEnd(String attributeEnd)
Sets the attribute end marker.
|
void |
setAttributeStart(String attributeStart)
Sets the attribute start marker.
|
void |
setEscapedDelimiter(String escapedDelimiter)
Sets the escaped property delimiter string.
|
void |
setIndexEnd(String indexEnd)
Sets the index end marker.
|
void |
setIndexStart(String indexStart)
Sets the index start marker.
|
void |
setPropertyDelimiter(String propertyDelimiter)
Sets the property delimiter.
|
public static final String DEFAULT_PROPERTY_DELIMITER
public static final String DEFAULT_ESCAPED_DELIMITER
public static final String DEFAULT_ATTRIBUTE_START
public static final String DEFAULT_ATTRIBUTE_END
public static final String DEFAULT_INDEX_START
public static final String DEFAULT_INDEX_END
public String getAttributeEnd()
public void setAttributeEnd(String attributeEnd)
attributeEnd
- the attribute end marker; can be null if no
end marker is neededpublic String getAttributeStart()
public void setAttributeStart(String attributeStart)
attributeStart
- the attribute start markerpublic String getEscapedDelimiter()
public void setEscapedDelimiter(String escapedDelimiter)
escapedDelimiter
- the escaped delimiter stringpublic String getIndexEnd()
public void setIndexEnd(String indexEnd)
indexEnd
- the index end markerpublic String getIndexStart()
public void setIndexStart(String indexStart)
indexStart
- the index start markerpublic String getPropertyDelimiter()
public void setPropertyDelimiter(String propertyDelimiter)
propertyDelimiter
- the property delimiterpublic List<ConfigurationNode> query(ConfigurationNode root, String key)
query
in interface ExpressionEngine
root
- the root nodekey
- the keypublic String nodeKey(ConfigurationNode node, String parentKey)
nodeKey
in interface ExpressionEngine
node
- the node whose key is to be determinedparentKey
- the key of this node's parentpublic NodeAddData prepareAdd(ConfigurationNode root, String key)
Prepares Adding the property with the specified key.
To be able to deal with the structure supported by hierarchical configuration implementations the passed in key is of importance, especially the indices it might contain. The following example should clarify this: Suppose the actual node structure looks like the following:
tables +-- table +-- name = user +-- fields +-- field +-- name = uid +-- field +-- name = firstName ... +-- table +-- name = documents +-- fields ...
In this example a database structure is defined, e.g. all fields of the
first table could be accessed using the key
tables.table(0).fields.field.name
. If now properties are
to be added, it must be exactly specified at which position in the
hierarchy the new property is to be inserted. So to add a new field name
to a table it is not enough to say just
config.addProperty("tables.table.fields.field.name", "newField");
The statement given above contains some ambiguity. For instance it is not
clear, to which table the new field should be added. If this method finds
such an ambiguity, it is resolved by following the last valid path. Here
this would be the last table. The same is true for the field
;
because there are multiple fields and no explicit index is provided, a
new name
property would be added to the last field - which
is probably not what was desired.
To make things clear explicit indices should be provided whenever
possible. In the example above the exact table could be specified by
providing an index for the table
element as in
tables.table(1).fields
. By specifying an index it can
also be expressed that at a given position in the configuration tree a
new branch should be added. In the example above we did not want to add
an additional name
element to the last field of the table,
but we want a complete new field
element. This can be
achieved by specifying an invalid index (like -1) after the element where
a new branch should be created. Given this our example would run:
config.addProperty("tables.table(1).fields.field(-1).name", "newField");
With this notation it is possible to add new branches everywhere. We
could for instance create a new table
element by
specifying
config.addProperty("tables.table(-1).fields.field.name", "newField2");
(Note that because after the table
element a new branch is
created indices in following elements are not relevant; the branch is new
so there cannot be any ambiguities.)
prepareAdd
in interface ExpressionEngine
root
- the root node of the nodes hierarchykey
- the key of the new propertyprotected void findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart, ConfigurationNode node, Collection<ConfigurationNode> nodes)
keyPart
- the configuration key iteratornode
- the actual nodenodes
- here the found nodes are storedprotected ConfigurationNode findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt, ConfigurationNode node)
keyIt
- the key iteratornode
- the actual nodeCopyright © 2001–2013 The Apache Software Foundation. All rights reserved.