    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.Collection;
    020
    021/**
    022 * <p>
    023 * Definition of an interface describing a model based on a nodes structure.
    024 * </p>
    025 * <p>
    026 * This interface can be used for dealing with hierarchical, tree-like data. It
    027 * defines basic operations for manipulating the tree structure which use keys
    028 * to select the nodes affected.
    029 * </p>
    030 * <p>
    031 * The idea behind this interface is that concrete implementations can be used
    032 * by hierarchical configurations. This makes it possible to integrate various
    033 * hierarchical structures with the API of a hierarchical configuration, e.g.
    034 * configuration nodes stored in memory, JNDI contexts, or other structures. The
    035 * configuration object interacts with the underlying data structure via this
    036 * interface. For more complex operations access to an {@link ExpressionEngine}
    037 * may be required in order to interpret the passed in keys. For these purposes
    038 * a {@link NodeKeyResolver} has to be provided which knows how to deal with
    039 * keys.
    040 * </p>
    041 *
    042 * @since 2.0
    043 * @param <T> the type of the nodes managed by this model
    044 */
    045public interface NodeModel<T>
    046{
    047    /**
    048     * Sets a new root node for this model. The whole structure is replaced by
    049     * the new node and its children.
    050     *
    051     * @param newRoot the new root node to be set (can be <b>null</b>, then an
    052     *        empty root node is set)
    053     */
    054    void setRootNode(T newRoot);
    055
    056    /**
    057     * Returns a {@code NodeHandler} for dealing with the nodes managed by this
    058     * model.
    059     *
    060     * @return the {@code NodeHandler}
    061     */
    062    NodeHandler<T> getNodeHandler();
    063
    064    /**
    065     * Adds a new property to this node model consisting of an arbitrary number
    066     * of values. The key for the add operation is provided. For each value a
    067     * new node has to be added. The passed in resolver is queried for a
    068     * {@link NodeAddData} object defining the add operation to be performed.
    069     *
    070     * @param key the key
    071     * @param values the values to be added at the position defined by the key
    072     * @param resolver the {@code NodeKeyResolver}
    073     */
    074    void addProperty(String key, Iterable<?> values, NodeKeyResolver<T> resolver);
    075
    076    /**
    077     * Adds a collection of new nodes to this model. This operation corresponds
    078     * to the {@code addNodes()} method of the {@code HierarchicalConfiguration}
    079     * interface. The new nodes are either added to an existing node (if the
    080     * passed in key selects exactly one node) or to a newly created node. The
    081     * passed in {@code NodeKeyResolver} is used to interpret the given key.
    082     *
    083     * @param key the key
    084     * @param nodes the collection of nodes to be added (may be <b>null</b>)
    085     * @param resolver the {@code NodeKeyResolver}
    086     * @throws IllegalArgumentException if the key references an attribute (of
    087     *         course, it is not possible to add something to an attribute)
    088     */
    089    void addNodes(String key, Collection<? extends T> nodes,
    090            NodeKeyResolver<T> resolver);
    091
    092    /**
    093     * Changes the value of a property. This is a more complex operation as it
    094     * might involve adding, updating, or deleting nodes and attributes from the
    095     * model. The object representing the new value is passed to the
    096     * {@code NodeKeyResolver} which will produce a corresponding
    097     * {@link NodeUpdateData} object. Based on the content of this object,
    098     * update operations are performed.
    099     *
    100     * @param key the key
    101     * @param value the new value for this property (to be evaluated by the
    102     *        {@code NodeKeyResolver})
    103     * @param resolver the {@code NodeKeyResolver}
    104     */
    105    void setProperty(String key, Object value, NodeKeyResolver<T> resolver);
    106
    107    /**
    108     * Removes the sub trees defined by the given key from this model. All nodes
    109     * selected by this key are retrieved from the specified
    110     * {@code NodeKeyResolver} and removed from the model.
    111     *
    112     * @param key the key selecting the properties to be removed
    113     * @param resolver the {@code NodeKeyResolver}
    114     * @return an object with information about the data removed
    115     */
    116    Object clearTree(String key, NodeKeyResolver<T> resolver);
    117
    118    /**
    119     * Clears the value of a property. This method is similar to
    120     * {@link #clearTree(String, NodeKeyResolver)}: However, the nodes
    121     * referenced by the passed in key are not removed completely, but only
    122     * their value is set to <b>null</b>.
    123     *
    124     * @param key the key selecting the properties to be cleared
    125     * @param resolver the {@code NodeKeyResolver}
    126     */
    127    void clearProperty(String key, NodeKeyResolver<T> resolver);
    128
    129    /**
    130     * Removes all data from this model.
    131     *
    132     * @param resolver the {@code NodeKeyResolver}
    133     */
    134    void clear(NodeKeyResolver<T> resolver);
    135
    136    /**
    137     * Returns a representation of the data stored in this model in form of a
    138     * nodes hierarchy of {@code ImmutableNode} objects. A concrete model
    139     * implementation can use an arbitrary means to store its data. When a
    140     * model's data is to be used together with other functionality of the
    141     * <em>Configuration</em> library (e.g. when combining multiple
    142     * configuration sources) it has to be transformed into a common format.
    143     * This is done by this method. {@code ImmutableNode} is a generic
    144     * representation of a hierarchical structure. Thus, it should be possible
    145     * to generate a corresponding structure from arbitrary model data.
    146     *
    147     * @return the root node of an in-memory hierarchy representing the data
    148     *         stored in this model
    149     */
    150    ImmutableNode getInMemoryRepresentation();
    151}