    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.configuration2.tree;
    018
    019import java.util.List;
    020
    021/**
    022 * <p>
    023 * Definition of an interface for evaluating keys for hierarchical
    024 * configurations.
    025 * </p>
    026 * <p>
    027 * An <em>expression engine</em> knows how to map a key for a configuration's
    028 * property to a single or a set of configuration nodes. Thus it defines the way
    029 * how properties are addressed in this configuration. Methods of a
    030 * configuration that have to handle property keys (e.g. {@code getProperty()}
    031 * or {@code addProperty()} do not interpret the passed in keys on their own,
    032 * but delegate this task to an associated expression engine. This expression
    033 * engine will then find out, which configuration nodes are addressed by the
    034 * key.
    035 * </p>
    036 * <p>
    037 * Separating the task of evaluating property keys from the configuration object
    038 * has the advantage that multiple different expression languages (i.e. ways for
    039 * querying or setting properties) can be supported. Just set a suitable
    040 * implementation of this interface as the configuration's expression engine,
    041 * and you can use the syntax provided by this implementation.
    042 * </p>
    043 * <p>
    044 * An {@code ExpressionEngine} can deal with nodes of different types. To
    045 * achieve this, a {@link NodeHandler} for the desired type must be passed to
    046 * the methods.
    047 * </p>
    048 *
    049 * @since 1.3
    050 */
    051public interface ExpressionEngine
    052{
    053    /**
    054     * Finds the nodes and/or attributes that are matched by the specified key.
    055     * This is the main method for interpreting property keys. An implementation
    056     * must traverse the given root node and its children to find all results
    057     * that are matched by the given key. If the key is not correct in the
    058     * syntax provided by that implementation, it is free to throw a (runtime)
    059     * exception indicating this error condition. The passed in
    060     * {@code NodeHandler} can be used to gather the required information from
    061     * the node object.
    062     *
    063     * @param <T> the type of the node to be processed
    064     * @param root the root node of a hierarchy of nodes
    065     * @param key the key to be evaluated
    066     * @param handler the {@code NodeHandler} for accessing the node
    067     * @return a list with the results that are matched by the key (should never
    068     *         be <b>null</b>)
    069     */
    070    <T> List<QueryResult<T>> query(T root, String key, NodeHandler<T> handler);
    071
    072    /**
    073     * Returns the key for the specified node in the expression language
    074     * supported by an implementation. This method is called whenever a property
    075     * key for a node has to be constructed, e.g. by the
    076     * {@link org.apache.commons.configuration2.Configuration#getKeys()
    077     * getKeys()} method.
    078     *
    079     * @param <T> the type of the node to be processed
    080     * @param node the node, for which the key must be constructed
    081     * @param parentKey the key of this node's parent (can be <b>null</b> for
    082     *        the root node)
    083     * @param handler the {@code NodeHandler} for accessing the node
    084     * @return this node's key
    085     */
    086    <T> String nodeKey(T node, String parentKey, NodeHandler<T> handler);
    087
    088    /**
    089     * Returns the key of an attribute. The passed in {@code parentKey} must
    090     * reference the parent node of the attribute. A concrete implementation
    091     * must concatenate this parent key with the attribute name to a valid key
    092     * for this attribute.
    093     *
    094     * @param parentKey the key to the node owning this attribute
    095     * @param attributeName the name of the attribute in question
    096     * @return the resulting key referencing this attribute
    097     */
    098    String attributeKey(String parentKey, String attributeName);
    099
    100    /**
    101     * Determines a &quot;canonical&quot; key for the specified node in the
    102     * expression language supported by this implementation. This means that
    103     * always a unique key if generated pointing to this specific node. For most
    104     * concrete implementations, this means that an index is added to the node
    105     * name to ensure that there are no ambiguities with child nodes having the
    106     * same names.
    107     *
    108     * @param <T> the type of the node to be processed
    109     * @param node the node, for which the key must be constructed
    110     * @param parentKey the key of this node's parent (can be <b>null</b> for
    111     *        the root node)
    112     * @param handler the {@code NodeHandler} for accessing the node
    113     * @return the canonical key of this node
    114     */
    115    <T> String canonicalKey(T node, String parentKey, NodeHandler<T> handler);
    116
    117    /**
    118     * Returns information needed for an add operation. This method gets called
    119     * when new properties are to be added to a configuration. An implementation
    120     * has to interpret the specified key, find the parent node for the new
    121     * elements, and provide all information about new nodes to be added.
    122     *
    123     * @param <T> the type of the node to be processed
    124     * @param root the root node
    125     * @param key the key for the new property
    126     * @param handler the {@code NodeHandler} for accessing the node
    127     * @return an object with all information needed for the add operation
    128     */
    129    <T> NodeAddData<T> prepareAdd(T root, String key, NodeHandler<T> handler);
    130}