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