Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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;
/**
*
* A specialized configuration class that extends its base class by the ability
* of keeping more structure in the stored properties.
*
*
* 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.
*
*
* The hierarchical organization allows for a more sophisticated access to
* single properties. As an example consider the following XML document:
*
* 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.
*
*
* 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}.
*
*
* 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.
*
*
* Since the 1.3 release of Commons Configuration hierarchical
* configurations support an expression engine. 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.
*
*
* 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:
*
*
*
ADD_NODES
*
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.
*
CLEAR_TREE
*
The {@code clearTree()} method was called; the event object stores the
* key of the removed sub tree.
*
SUBNODE_CHANGED
*
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.
*
*
* 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.
*
*
* @since 2.0
* @param the type of the nodes managed by this hierarchical configuration
*/
public abstract class AbstractHierarchicalConfiguration extends AbstractConfiguration
implements Cloneable, NodeKeyResolver, HierarchicalConfiguration
{
/** The model for managing the data stored in this configuration. */
private NodeModel 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(final NodeModel 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()
{
final NodeHandler 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 getNodeModel()
{
beginRead(false);
try
{
return getModel();
}
finally
{
endRead();
}
}
/**
* Returns the expression engine used by this configuration. This method
* will never return null; 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 null,
* then the default expression engine will be used
* @since 1.3
*/
@Override
public void setExpressionEngine(final 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(final String key)
{
final List> results = fetchNodeList(key);
if (results.isEmpty())
{
return null;
}
final NodeHandler handler = getModel().getNodeHandler();
final List