/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.configuration2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.sync.NoOpSynchronizer;
import org.apache.commons.configuration2.tree.ConfigurationNodeVisitorAdapter;
import org.apache.commons.configuration2.tree.DefaultExpressionEngine;
import org.apache.commons.configuration2.tree.ExpressionEngine;
import org.apache.commons.configuration2.tree.NodeAddData;
import org.apache.commons.configuration2.tree.NodeHandler;
import org.apache.commons.configuration2.tree.NodeKeyResolver;
import org.apache.commons.configuration2.tree.NodeModel;
import org.apache.commons.configuration2.tree.NodeTreeWalker;
import org.apache.commons.configuration2.tree.NodeUpdateData;
import org.apache.commons.configuration2.tree.QueryResult;

/**
 * <p>
 * A specialized configuration class that extends its base class by the ability
 * of keeping more structure in the stored properties.
 * </p>
 * <p>
 * There are some sources of configuration data that cannot be stored very well
 * in a {@code BaseConfiguration} object because then their structure is lost.
 * This is for instance true for XML documents. This class can deal with such
 * structured configuration sources by storing the properties in a tree-like
 * organization. The exact storage structure of the underlying data does not
 * matter for the configuration instance; it uses a {@link NodeModel} object for
 * accessing it.
 * </p>
 * <p>
 * The hierarchical organization allows for a more sophisticated access to
 * single properties. As an example consider the following XML document:
 * </p>
 *
 * <pre>
 * &lt;database&gt;
 *   &lt;tables&gt;
 *     &lt;table&gt;
 *       &lt;name&gt;users&lt;/name&gt;
 *       &lt;fields&gt;
 *         &lt;field&gt;
 *           &lt;name&gt;lid&lt;/name&gt;
 *           &lt;type&gt;long&lt;/name&gt;
 *         &lt;/field&gt;
 *         &lt;field&gt;
 *           &lt;name&gt;usrName&lt;/name&gt;
 *           &lt;type&gt;java.lang.String&lt;/type&gt;
 *         &lt;/field&gt;
 *        ...
 *       &lt;/fields&gt;
 *     &lt;/table&gt;
 *     &lt;table&gt;
 *       &lt;name&gt;documents&lt;/name&gt;
 *       &lt;fields&gt;
 *         &lt;field&gt;
 *           &lt;name&gt;docid&lt;/name&gt;
 *           &lt;type&gt;long&lt;/type&gt;
 *         &lt;/field&gt;
 *         ...
 *       &lt;/fields&gt;
 *     &lt;/table&gt;
 *     ...
 *   &lt;/tables&gt;
 * &lt;/database&gt;
 * </pre>
 *
 * <p>
 * If this document is parsed and stored in a hierarchical configuration object
 * (which can be done by one of the sub classes), there are enhanced
 * possibilities of accessing properties. Per default, the keys for querying
 * information can contain indices that select a specific element if there are
 * multiple hits.
 * </p>
 * <p>
 * For instance the key {@code tables.table(0).name} can be used to find out the
 * name of the first table. In opposite {@code tables.table.name} would return a
 * collection with the names of all available tables. Similarly the key
 * {@code 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
 * {@code field} element, a single field can be accessed:
 * {@code tables.table(1).fields.field(0).name}.
 * </p>
 * <p>
 * There is a {@code getMaxIndex()} method that returns the maximum allowed
 * index that can be added to a given property key. This method can be used to
 * iterate over all values defined for a certain property.
 * </p>
 * <p>
 * Since the 1.3 release of <em>Commons Configuration</em> hierarchical
 * configurations support an <em>expression engine</em>. This expression engine
 * is responsible for evaluating the passed in configuration keys and map them
 * to the stored properties. The examples above are valid for the default
 * expression engine, which is used when a new
 * {@code AbstractHierarchicalConfiguration} instance is created. With the
 * {@code setExpressionEngine()} method a different expression engine can be
 * set. For instance with
 * {@link org.apache.commons.configuration2.tree.xpath.XPathExpressionEngine}
 * there is an expression engine available that supports configuration keys in
 * XPATH syntax.
 * </p>
 * <p>
 * In addition to the events common for all configuration classes, hierarchical
 * configurations support some more events that correspond to some specific
 * methods and features. For those events specific event type constants in
 * {@code ConfigurationEvent} exist:
 * </p>
 * <dl>
 * <dt><em>ADD_NODES</em></dt>
 * <dd>The {@code addNodes()} method was called; the event object contains the
 * key, to which the nodes were added, and a collection with the new nodes as
 * value.</dd>
 * <dt><em>CLEAR_TREE</em></dt>
 * <dd>The {@code clearTree()} method was called; the event object stores the
 * key of the removed sub tree.</dd>
 * <dt><em>SUBNODE_CHANGED</em></dt>
 * <dd>A {@code SubnodeConfiguration} that was created from this configuration
 * has been changed. The value property of the event object contains the
 * original event object as it was sent by the subnode configuration.</dd>
 * </dl>
 * <p>
 * Whether an {@code AbstractHierarchicalConfiguration} object is thread-safe or
 * not depends on the underlying {@code NodeModel} and the
 * {@link org.apache.commons.configuration2.sync.Synchronizer Synchronizer}
 * it is associated with. Some {@code NodeModel} implementations are inherently
 * thread-safe; they do not require a special {@code Synchronizer}. (Per
 * default, a dummy {@code Synchronizer} is used which is not thread-safe!) The
 * methods for querying or updating configuration data invoke this
 * {@code Synchronizer} accordingly. When accessing the configuration's root
 * node directly, the client application is responsible for proper
 * synchronization. This is achieved by calling the methods
 * {@link #lock(org.apache.commons.configuration2.sync.LockMode) lock()},
 * and {@link #unlock(org.apache.commons.configuration2.sync.LockMode) unlock()} with a proper
 * {@link org.apache.commons.configuration2.sync.LockMode LockMode} argument.
 * In any case, it is recommended to not access the
 * root node directly, but to use corresponding methods for querying or updating
 * configuration data instead. Direct manipulations of a configuration's node
 * structure circumvent many internal mechanisms and thus can cause undesired
 * effects. For concrete subclasses dealing with specific node structures, this
 * situation may be different.
 * </p>
 *
 * @version $Id$
 * @since 2.0
 * @param <T> the type of the nodes managed by this hierarchical configuration
 */
public abstract class AbstractHierarchicalConfiguration<T> extends AbstractConfiguration
    implements Cloneable, NodeKeyResolver<T>, HierarchicalConfiguration<T>
{
    /** The model for managing the data stored in this configuration. */
    private NodeModel<T> model;

    /** Stores the expression engine for this instance.*/
    private ExpressionEngine expressionEngine;

    /**
     * Creates a new instance of {@code AbstractHierarchicalConfiguration} and
     * sets the {@code NodeModel} to be used.
     *
     * @param nodeModel the {@code NodeModel}
     */
    protected AbstractHierarchicalConfiguration(NodeModel<T> nodeModel)
    {
        model = nodeModel;
    }

    /**
     * {@inheritDoc} This implementation handles synchronization and delegates
     * to {@code getRootElementNameInternal()}.
     */
    @Override
    public final String getRootElementName()
    {
        beginRead(false);
        try
        {
            return getRootElementNameInternal();
        }
        finally
        {
            endRead();
        }
    }

    /**
     * Actually obtains the name of the root element. This method is called by
     * {@code getRootElementName()}. It just returns the name of the root node.
     * Subclasses that treat the root element name differently can override this
     * method.
     *
     * @return the name of this configuration's root element
     */
    protected String getRootElementNameInternal()
    {
        NodeHandler<T> nodeHandler = getModel().getNodeHandler();
        return nodeHandler.nodeName(nodeHandler.getRootNode());
    }

    /**
     * {@inheritDoc} This implementation returns the configuration's
     * {@code NodeModel}. It is guarded by the current {@code Synchronizer}.
     */
    @Override
    public NodeModel<T> getNodeModel()
    {
        beginRead(false);
        try
        {
            return getModel();
        }
        finally
        {
            endRead();
        }
    }

    /**
     * Returns the expression engine used by this configuration. This method
     * will never return <b>null</b>; if no specific expression engine was set,
     * the default expression engine will be returned.
     *
     * @return the current expression engine
     * @since 1.3
     */
    @Override
    public ExpressionEngine getExpressionEngine()
    {
        return (expressionEngine != null) ? expressionEngine
                : DefaultExpressionEngine.INSTANCE;
    }

    /**
     * Sets the expression engine to be used by this configuration. All property
     * keys this configuration has to deal with will be interpreted by this
     * engine.
     *
     * @param expressionEngine the new expression engine; can be <b>null</b>,
     * then the default expression engine will be used
     * @since 1.3
     */
    @Override
    public void setExpressionEngine(ExpressionEngine expressionEngine)
    {
        this.expressionEngine = expressionEngine;
    }

    /**
     * Fetches the specified property. This task is delegated to the associated
     * expression engine.
     *
     * @param key the key to be looked up
     * @return the found value
     */
    @Override
    protected Object getPropertyInternal(String key)
    {
        List<QueryResult<T>> results = fetchNodeList(key);

        if (results.isEmpty())
        {
            return null;
        }
        else
        {
            NodeHandler<T> handler = getModel().getNodeHandler();
            List<Object> list = new ArrayList<Object>();
            for (QueryResult<T> result : results)
            {
                Object value = valueFromResult(result, handler);
                if (value != null)
                {
                    list.add(value);
                }
            }

            if (list.size() < 1)
            {
                return null;
            }
            else
            {
                return (list.size() == 1) ? list.get(0) : list;
            }
        }
    }

    /**
     * Adds the property with the specified key. This task will be delegated to
     * the associated {@code ExpressionEngine}, so the passed in key
     * must match the requirements of this implementation.
     *
     * @param key the key of the new property
     * @param obj the value of the new property
     */
    @Override
    protected void addPropertyInternal(String key, Object obj)
    {
        addPropertyToModel(key, getListDelimiterHandler().parse(obj));
    }

    /**
     * {@inheritDoc} This method is not called in the normal way (via
     * {@code addProperty()} for hierarchical configurations because all values
     * to be added for the property have to be passed to the model in a single
     * step. However, to allow derived classes to add an arbitrary value as an
     * object, a special implementation is provided here. The passed in object
     * is not parsed as a list, but passed directly as only value to the model.
     */
    @Override
    protected void addPropertyDirect(String key, Object value)
    {
        addPropertyToModel(key, Collections.singleton(value));
    }

    /**
     * Helper method for executing an add property operation on the model.
     *
     * @param key the key of the new property
     * @param values the values to be added for this property
     */
    private void addPropertyToModel(String key, Iterable<?> values)
    {
        getModel().addProperty(key, values, this);
    }

    /**
     * Adds a collection of nodes at the specified position of the configuration
     * tree. This method works similar to {@code addProperty()}, but
     * instead of a single property a whole collection of nodes can be added -
     * and thus complete configuration sub trees. E.g. with this method it is
     * possible to add parts of another {@code BaseHierarchicalConfiguration}
     * object to this object. If the passed in key refers to
     * an existing and unique node, the new nodes are added to this node.
     * Otherwise a new node will be created at the specified position in the
     * hierarchy. Implementation node: This method performs some book-keeping
     * and then delegates to {@code addNodesInternal()}.
     *
     * @param key the key where the nodes are to be added; can be <b>null</b>,
     * then they are added to the root node
     * @param nodes a collection with the {@code Node} objects to be
     * added
     */
    @Override
    public final void addNodes(String key, Collection<? extends T> nodes)
    {
        if (nodes == null || nodes.isEmpty())
        {
            return;
        }

        beginWrite(false);
        try
        {
            fireEvent(ConfigurationEvent.ADD_NODES, key, nodes, true);
            addNodesInternal(key, nodes);
            fireEvent(ConfigurationEvent.ADD_NODES, key, nodes, false);
        }
        finally
        {
            endWrite();
        }
    }

    /**
     * Actually adds a collection of new nodes to this configuration. This
     * method is called by {@code addNodes()}. It can be overridden by
     * subclasses that need to adapt this operation.
     *
     * @param key the key where the nodes are to be added; can be <b>null</b>,
     *        then they are added to the root node
     * @param nodes a collection with the {@code Node} objects to be added
     * @since 2.0
     */
    protected void addNodesInternal(String key, Collection<? extends T> nodes)
    {
        getModel().addNodes(key, nodes, this);
    }

    /**
     * Checks if this configuration is empty. Empty means that there are no keys
     * with any values, though there can be some (empty) nodes.
     *
     * @return a flag if this configuration is empty
     */
    @Override
    protected boolean isEmptyInternal()
    {
        return !nodeDefined(getModel().getNodeHandler().getRootNode());
    }

    /**
     * Checks if the specified key is contained in this configuration. Note that
     * for this configuration the term &quot;contained&quot; means that the key
     * has an associated value. If there is a node for this key that has no
     * value but children (either defined or undefined), this method will still
     * return <b>false </b>.
     *
     * @param key the key to be checked
     * @return a flag if this key is contained in this configuration
     */
    @Override
    protected boolean containsKeyInternal(String key)
    {
        return getPropertyInternal(key) != null;
    }

    /**
     * Sets the value of the specified property.
     *
     * @param key the key of the property to set
     * @param value the new value of this property
     */
    @Override
    protected void setPropertyInternal(String key, Object value)
    {
        getModel().setProperty(key, value, this);
    }

    /**
     * {@inheritDoc} This implementation delegates to the expression engine.
     */
    @Override
    public List<QueryResult<T>> resolveKey(T root, String key,
            NodeHandler<T> handler)
    {
        return getExpressionEngine().query(root, key, handler);
    }

    /**
     * {@inheritDoc} This implementation delegates to {@code resolveKey()} and
     * then filters out attribute results.
     */
    @Override
    public List<T> resolveNodeKey(T root, String key, NodeHandler<T> handler)
    {
        List<QueryResult<T>> results = resolveKey(root, key, handler);
        List<T> targetNodes = new LinkedList<T>();
        for (QueryResult<T> result : results)
        {
            if (!result.isAttributeResult())
            {
                targetNodes.add(result.getNode());
            }
        }
        return targetNodes;
    }

    /**
     * {@inheritDoc} This implementation delegates to the expression engine.
     */
    @Override
    public NodeAddData<T> resolveAddKey(T root, String key,
            NodeHandler<T> handler)
    {
        return getExpressionEngine().prepareAdd(root, key, handler);
    }

    /**
     * {@inheritDoc} This implementation executes a query for the given key and
     * constructs a {@code NodeUpdateData} object based on the results. It
     * determines which nodes need to be changed and whether new ones need to be
     * added or existing ones need to be removed.
     */
    @Override
    public NodeUpdateData<T> resolveUpdateKey(T root, String key,
            Object newValue, NodeHandler<T> handler)
    {
        Iterator<QueryResult<T>> itNodes = fetchNodeList(key).iterator();
        Iterator<?> itValues = getListDelimiterHandler().parse(newValue).iterator();
        Map<QueryResult<T>, Object> changedValues =
                new HashMap<QueryResult<T>, Object>();
        Collection<Object> additionalValues = null;
        Collection<QueryResult<T>> removedItems = null;

        while (itNodes.hasNext() && itValues.hasNext())
        {
            changedValues.put(itNodes.next(), itValues.next());
        }

        // Add additional nodes if necessary
        if (itValues.hasNext())
        {
            additionalValues = new LinkedList<Object>();
            while (itValues.hasNext())
            {
                additionalValues.add(itValues.next());
            }
        }

        // Remove remaining nodes
        if (itNodes.hasNext())
        {
            removedItems = new LinkedList<QueryResult<T>>();
            while (itNodes.hasNext())
            {
                removedItems.add(itNodes.next());
            }
        }

        return new NodeUpdateData<T>(changedValues, additionalValues,
                removedItems, key);
    }

    /**
     * {@inheritDoc} This implementation uses the expression engine to generate a
     * canonical key for the passed in node. For this purpose, the path to the
     * root node has to be traversed. The cache is used to store and access keys
     * for nodes encountered on the path.
     */
    @Override
    public String nodeKey(T node, Map<T, String> cache, NodeHandler<T> handler)
    {
        List<T> path = new LinkedList<T>();
        T currentNode = node;
        String key = cache.get(node);
        while (key == null && currentNode != null)
        {
            path.add(0, currentNode);
            currentNode = handler.getParent(currentNode);
            key = cache.get(currentNode);
        }

        for (T n : path)
        {
            String currentKey = getExpressionEngine().canonicalKey(n, key, handler);
            cache.put(n, currentKey);
            key = currentKey;
        }

        return key;
    }

    /**
     * Clears this configuration. This is a more efficient implementation than
     * the one inherited from the base class. It delegates to the node model.
     */
    @Override
    protected void clearInternal()
    {
        getModel().clear(this);
    }

    /**
     * Removes all values of the property with the given name and of keys that
     * start with this name. So if there is a property with the key
     * &quot;foo&quot; and a property with the key &quot;foo.bar&quot;, a call
     * of {@code clearTree("foo")} would remove both properties.
     *
     * @param key the key of the property to be removed
     */
    @Override
    public final void clearTree(String key)
    {
        beginWrite(false);
        try
        {
            fireEvent(ConfigurationEvent.CLEAR_TREE, key, null, true);
            Object nodes = clearTreeInternal(key);
            fireEvent(ConfigurationEvent.CLEAR_TREE, key, nodes, false);
        }
        finally
        {
            endWrite();
        }
    }

    /**
     * Actually clears the tree of elements referenced by the given key. This
     * method is called by {@code clearTree()}. Subclasses that need to adapt
     * this operation can override this method. This base implementation
     * delegates to the node model.
     *
     * @param key the key of the property to be removed
     * @return an object with information about the nodes that have been removed
     *         (this is needed for firing a meaningful event of type
     *         CLEAR_TREE)
     * @since 2.0
     */
    protected Object clearTreeInternal(String key)
    {
        return getModel().clearTree(key, this);
    }

    /**
     * Removes the property with the given key. Properties with names that start
     * with the given key (i.e. properties below the specified key in the
     * hierarchy) won't be affected. This implementation delegates to the node+
     * model.
     *
     * @param key the key of the property to be removed
     */
    @Override
    protected void clearPropertyDirect(String key)
    {
        getModel().clearProperty(key, this);
    }

    /**
     * {@inheritDoc} This implementation is slightly more efficient than the
     * default implementation. It does not iterate over the key set, but
     * directly queries its size after it has been constructed. Note that
     * constructing the key set is still an O(n) operation.
     */
    @Override
    protected int sizeInternal()
    {
        return visitDefinedKeys().getKeyList().size();
    }

    /**
     * Returns an iterator with all keys defined in this configuration.
     * Note that the keys returned by this method will not contain any
     * indices. This means that some structure will be lost.
     *
     * @return an iterator with the defined keys in this configuration
     */
    @Override
    protected Iterator<String> getKeysInternal()
    {
        return visitDefinedKeys().getKeyList().iterator();
    }

    /**
     * Creates a {@code DefinedKeysVisitor} and visits all defined keys with it.
     *
     * @return the visitor after all keys have been visited
     */
    private DefinedKeysVisitor visitDefinedKeys()
    {
        DefinedKeysVisitor visitor = new DefinedKeysVisitor();
        NodeHandler<T> nodeHandler = getModel().getNodeHandler();
        NodeTreeWalker.INSTANCE.walkDFS(nodeHandler.getRootNode(), visitor,
                nodeHandler);
        return visitor;
    }

    /**
     * Returns an iterator with all keys defined in this configuration that
     * start with the given prefix. The returned keys will not contain any
     * indices. This implementation tries to locate a node whose key is the same
     * as the passed in prefix. Then the subtree of this node is traversed, and
     * the keys of all nodes encountered (including attributes) are added to the
     * result set.
     *
     * @param prefix the prefix of the keys to start with
     * @return an iterator with the found keys
     */
    @Override
    protected Iterator<String> getKeysInternal(String prefix)
    {
        DefinedKeysVisitor visitor = new DefinedKeysVisitor(prefix);
        if (containsKey(prefix))
        {
            // explicitly add the prefix
            visitor.getKeyList().add(prefix);
        }

        List<QueryResult<T>> results = fetchNodeList(prefix);
        NodeHandler<T> handler = getModel().getNodeHandler();

        for (QueryResult<T> result : results)
        {
            if (!result.isAttributeResult())
            {
                for (T c : handler.getChildren(result.getNode()))
                {
                    NodeTreeWalker.INSTANCE.walkDFS(c, visitor, handler);
                }
                visitor.handleAttributeKeys(prefix, result.getNode(), handler);
            }
        }

        return visitor.getKeyList().iterator();
    }

    /**
     * Returns the maximum defined index for the given key. This is useful if
     * there are multiple values for this key. They can then be addressed
     * separately by specifying indices from 0 to the return value of this
     * method. If the passed in key is not contained in this configuration,
     * result is -1.
     *
     * @param key the key to be checked
     * @return the maximum defined index for this key
     */
    @Override
    public final int getMaxIndex(String key)
    {
        beginRead(false);
        try
        {
            return getMaxIndexInternal(key);
        }
        finally
        {
            endRead();
        }
    }

    /**
     * Actually retrieves the maximum defined index for the given key. This
     * method is called by {@code getMaxIndex()}. Subclasses that need to adapt
     * this operation have to override this method.
     *
     * @param key the key to be checked
     * @return the maximum defined index for this key
     * @since 2.0
     */
    protected int getMaxIndexInternal(String key)
    {
        return fetchNodeList(key).size() - 1;
    }

    /**
     * Creates a copy of this object. This new configuration object will contain
     * copies of all nodes in the same structure. Registered event listeners
     * won't be cloned; so they are not registered at the returned copy.
     *
     * @return the copy
     * @since 1.2
     */
    @Override
    public Object clone()
    {
        beginRead(false);
        try
        {
            @SuppressWarnings("unchecked") // clone returns the same type
            AbstractHierarchicalConfiguration<T> copy =
                    (AbstractHierarchicalConfiguration<T>) super.clone();
            copy.setSynchronizer(NoOpSynchronizer.INSTANCE);
            copy.cloneInterpolator(this);
            copy.setSynchronizer(ConfigurationUtils.cloneSynchronizer(getSynchronizer()));
            copy.model = cloneNodeModel();

            return copy;
        }
        catch (CloneNotSupportedException cex)
        {
            // should not happen
            throw new ConfigurationRuntimeException(cex);
        }
        finally
        {
            endRead();
        }
    }

    /**
     * Creates a clone of the node model. This method is called by
     * {@code clone()}.
     *
     * @return the clone of the {@code NodeModel}
     * @since 2.0
     */
    protected abstract NodeModel<T> cloneNodeModel();

    /**
     * Helper method for resolving the specified key.
     *
     * @param key the key
     * @return a list with all results selected by this key
     */
    protected List<QueryResult<T>> fetchNodeList(String key)
    {
        NodeHandler<T> nodeHandler = getModel().getNodeHandler();
        return resolveKey(nodeHandler.getRootNode(), key, nodeHandler);
    }

    /**
     * Checks if the specified node is defined.
     *
     * @param node the node to be checked
     * @return a flag if this node is defined
     */
    protected boolean nodeDefined(T node)
    {
        DefinedVisitor<T> visitor = new DefinedVisitor<T>();
        NodeTreeWalker.INSTANCE.walkBFS(node, visitor, getModel().getNodeHandler());
        return visitor.isDefined();
    }

    /**
     * Returns the {@code NodeModel} used by this configuration. This method is
     * intended for internal use only. Access to the model is granted without
     * any synchronization. This is in contrast to the &quot;official&quot;
     * {@code getNodeModel()} method which is guarded by the configuration's
     * {@code Synchronizer}.
     *
     * @return the node model
     */
    protected NodeModel<T> getModel()
    {
        return model;
    }

    /**
     * Extracts the value from a query result.
     *
     * @param result the {@code QueryResult}
     * @param handler the {@code NodeHandler}
     * @return the value of this result (may be <b>null</b>)
     */
    private Object valueFromResult(QueryResult<T> result, NodeHandler<T> handler)
    {
        return result.isAttributeResult() ? result.getAttributeValue(handler)
                : handler.getValue(result.getNode());
    }

    /**
     * A specialized visitor that checks if a node is defined.
     * &quot;Defined&quot; in this terms means that the node or at least one of
     * its sub nodes is associated with a value.
     *
     */
    private static class DefinedVisitor<T> extends
            ConfigurationNodeVisitorAdapter<T>
    {
        /** Stores the defined flag. */
        private boolean defined;

        /**
         * Checks if iteration should be stopped. This can be done if the first
         * defined node is found.
         *
         * @return a flag if iteration should be stopped
         */
        @Override
        public boolean terminate()
        {
            return isDefined();
        }

        /**
         * Visits the node. Checks if a value is defined.
         *
         * @param node the actual node
         */
        @Override
        public void visitBeforeChildren(T node, NodeHandler<T> handler)
        {
            defined =
                    handler.getValue(node) != null
                            || !handler.getAttributes(node).isEmpty();
        }

        /**
         * Returns the defined flag.
         *
         * @return the defined flag
         */
        public boolean isDefined()
        {
            return defined;
        }
    }

    /**
     * A specialized visitor that fills a list with keys that are defined in a
     * node hierarchy.
     */
    private class DefinedKeysVisitor extends
            ConfigurationNodeVisitorAdapter<T>
    {
        /** Stores the list to be filled. */
        private final Set<String> keyList;

        /** A stack with the keys of the already processed nodes. */
        private final Stack<String> parentKeys;

        /**
         * Default constructor.
         */
        public DefinedKeysVisitor()
        {
            keyList = new LinkedHashSet<String>();
            parentKeys = new Stack<String>();
        }

        /**
         * Creates a new {@code DefinedKeysVisitor} instance and sets the
         * prefix for the keys to fetch.
         *
         * @param prefix the prefix
         */
        public DefinedKeysVisitor(String prefix)
        {
            this();
            parentKeys.push(prefix);
        }

        /**
         * Returns the list with all defined keys.
         *
         * @return the list with the defined keys
         */
        public Set<String> getKeyList()
        {
            return keyList;
        }

        /**
         * {@inheritDoc} This implementation removes this
         * node's key from the stack.
         */
        @Override
        public void visitAfterChildren(T node, NodeHandler<T> handler)
        {
            parentKeys.pop();
        }

        /**
         * {@inheritDoc} If this node has a value, its key is added
         * to the internal list.
         */
        @Override
        public void visitBeforeChildren(T node, NodeHandler<T> handler)
        {
            String parentKey = parentKeys.isEmpty() ? null
                    : parentKeys.peek();
            String key = getExpressionEngine().nodeKey(node, parentKey, handler);
            parentKeys.push(key);
            if (handler.getValue(node) != null)
            {
                keyList.add(key);
            }
            handleAttributeKeys(key, node, handler);
        }

        /**
         * Appends all attribute keys of the current node.
         *
         * @param parentKey the parent key
         * @param node the current node
         * @param handler the {@code NodeHandler}
         */
        public void handleAttributeKeys(String parentKey, T node,
                NodeHandler<T> handler)
        {
            for (String attr : handler.getAttributes(node))
            {
                keyList.add(getExpressionEngine().attributeKey(parentKey, attr));
            }
        }
    }
}
