public class DefaultExpressionEngine extends Object implements ExpressionEngine
 A default implementation of the ExpressionEngine interface
 providing the "native" 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.
 
 The concrete symbols used by an instance are determined by a
 DefaultExpressionEngineSymbols object passed to the constructor.
 By providing a custom symbols object the syntax for querying properties in
 a hierarchical configuration can be altered.
 
Instances of this class are thread-safe and can be shared between multiple hierarchical configuration objects.
| Modifier and Type | Field and Description | 
|---|---|
| static DefaultExpressionEngine | INSTANCEA default instance of this class that is used as expression engine for
 hierarchical configurations per default. | 
| Constructor and Description | 
|---|
| DefaultExpressionEngine(DefaultExpressionEngineSymbols syms)Creates a new instance of  DefaultExpressionEngineand initializes
 its symbols. | 
| DefaultExpressionEngine(DefaultExpressionEngineSymbols syms,
                       NodeMatcher<String> nodeNameMatcher)Creates a new instance of  DefaultExpressionEngineand initializes
 its symbols and the matcher for comparing node names. | 
| Modifier and Type | Method and Description | 
|---|---|
| String | attributeKey(String parentKey,
            String attributeName)Returns the key of an attribute. | 
| <T> String | canonicalKey(T node,
            String parentKey,
            NodeHandler<T> handler)Determines a "canonical" key for the specified node in the
 expression language supported by this implementation. | 
| protected <T> T | findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt,
                T node,
                NodeHandler<T> handler)Finds the last existing node for an add operation. | 
| protected <T> void | findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart,
               T node,
               Collection<QueryResult<T>> results,
               NodeHandler<T> handler)Recursive helper method for evaluating a key. | 
| DefaultExpressionEngineSymbols | getSymbols()Returns the  DefaultExpressionEngineSymbolsobject associated with
 this instance. | 
| <T> String | nodeKey(T node,
       String parentKey,
       NodeHandler<T> handler)Returns the key for the specified node in the expression language
 supported by an implementation. | 
| <T> NodeAddData<T> | prepareAdd(T root,
          String key,
          NodeHandler<T> handler)
 Prepares Adding the property with the specified key. | 
| <T> List<QueryResult<T>> | query(T root,
     String key,
     NodeHandler<T> handler)Finds the nodes and/or attributes that are matched by the specified key. | 
public static final DefaultExpressionEngine INSTANCE
public DefaultExpressionEngine(DefaultExpressionEngineSymbols syms)
DefaultExpressionEngine and initializes
 its symbols.syms - the object with the symbols (must not be null)IllegalArgumentException - if the symbols are nullpublic DefaultExpressionEngine(DefaultExpressionEngineSymbols syms, NodeMatcher<String> nodeNameMatcher)
DefaultExpressionEngine and initializes
 its symbols and the matcher for comparing node names. The passed in
 matcher is always used when the names of nodes have to be matched against
 parts of configuration keys.syms - the object with the symbols (must not be null)nodeNameMatcher - the matcher for node names; can be null,
        then a default matcher is usedIllegalArgumentException - if the symbols are nullpublic DefaultExpressionEngineSymbols getSymbols()
DefaultExpressionEngineSymbols object associated with
 this instance.DefaultExpressionEngineSymbols used by this enginepublic <T> List<QueryResult<T>> query(T root, String key, NodeHandler<T> handler)
NodeHandler can be used to gather the required information from
 the node object. This method supports the syntax as described in the class
 comment.query in interface ExpressionEngineT - the type of the node to be processedroot - the root node of a hierarchy of nodeskey - the key to be evaluatedhandler - the NodeHandler for accessing the nodepublic <T> String nodeKey(T node, String parentKey, NodeHandler<T> handler)
getKeys() method. This implementation takes the
 given parent key, adds a property delimiter, and then adds the node's
 name.
 The name of the root node is a blank string. Note that no indices are
 returned.nodeKey in interface ExpressionEngineT - the type of the node to be processednode - the node, for which the key must be constructedparentKey - the key of this node's parent (can be null for
        the root node)handler - the NodeHandler for accessing the nodepublic String attributeKey(String parentKey, String attributeName)
ExpressionEngineparentKey must
 reference the parent node of the attribute. A concrete implementation
 must concatenate this parent key with the attribute name to a valid key
 for this attribute.attributeKey in interface ExpressionEngineparentKey - the key to the node owning this attributeattributeName - the name of the attribute in questionpublic <T> String canonicalKey(T node, String parentKey, NodeHandler<T> handler)
nodeKey();
 however, each key returned by this method has an index (except for the
 root node). The parent key is prepended to the name of the current node
 in any case and without further checks. If it is null, only the
 name of the current node with its index is returned.canonicalKey in interface ExpressionEngineT - the type of the node to be processednode - the node, for which the key must be constructedparentKey - the key of this node's parent (can be null for
        the root node)handler - the NodeHandler for accessing the nodepublic <T> NodeAddData<T> prepareAdd(T root, String key, NodeHandler<T> handler)
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 current 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 ExpressionEngineT - the type of the nodes to be dealt withroot - the root node of the nodes hierarchykey - the key of the new propertyhandler - the node handlerprotected <T> void findNodesForKey(DefaultConfigurationKey.KeyIterator keyPart, T node, Collection<QueryResult<T>> results, NodeHandler<T> handler)
T - the type of nodes to be dealt withkeyPart - the configuration key iteratornode - the current noderesults - here the found results are storedhandler - the node handlerprotected <T> T findLastPathNode(DefaultConfigurationKey.KeyIterator keyIt, T node, NodeHandler<T> handler)
T - the type of the nodes to be dealt withkeyIt - the key iteratornode - the current nodehandler - the node handlerCopyright © 2001–2020 The Apache Software Foundation. All rights reserved.