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.builder.combined;
018
019import java.util.Set;
020
021import org.apache.commons.configuration2.HierarchicalConfiguration;
022import org.apache.commons.configuration2.beanutils.XMLBeanDeclaration;
023
024/**
025 * <p>
026 * A specialized {@code BeanDeclaration} implementation that represents the
027 * declaration of a configuration source.
028 * </p>
029 * <p>
030 * Instances of this class are able to extract all information about a
031 * configuration source from the configuration definition file. The declaration
032 * of a configuration source is very similar to a bean declaration processed by
033 * {@code XMLBeanDeclaration}. There are very few differences, e.g. some
034 * reserved attributes like {@code optional} and {@code at}, and the fact that a
035 * bean factory is never needed.
036 * </p>
037 *
038 * @since 2.0
039 */
040public class ConfigurationDeclaration extends XMLBeanDeclaration
041{
042    /** Stores a reference to the associated configuration builder. */
043    private final CombinedConfigurationBuilder configurationBuilder;
044
045    /**
046     * Creates a new instance of {@code ConfigurationDeclaration} and
047     * initializes it.
048     *
049     * @param builder the associated configuration builder
050     * @param config the configuration this declaration is based onto
051     */
052    public ConfigurationDeclaration(final CombinedConfigurationBuilder builder,
053            final HierarchicalConfiguration<?> config)
054    {
055        super(config);
056        configurationBuilder = builder;
057    }
058
059    /**
060     * Returns the associated configuration builder.
061     *
062     * @return the configuration builder
063     */
064    public CombinedConfigurationBuilder getConfigurationBuilder()
065    {
066        return configurationBuilder;
067    }
068
069    /**
070     * Returns the value of the {@code at} attribute.
071     *
072     * @return the value of the {@code at} attribute (can be <b>null</b>)
073     */
074    public String getAt()
075    {
076        final String result =
077                this.getConfiguration().getString(
078                        CombinedConfigurationBuilder.ATTR_AT_RES);
079        return result == null ? this.getConfiguration().getString(
080                CombinedConfigurationBuilder.ATTR_AT) : result;
081    }
082
083    /**
084     * Returns a flag whether this is an optional configuration.
085     *
086     * @return a flag if this declaration points to an optional configuration
087     */
088    public boolean isOptional()
089    {
090        Boolean value =
091                this.getConfiguration().getBoolean(
092                        CombinedConfigurationBuilder.ATTR_OPTIONAL_RES, null);
093        if (value == null)
094        {
095            value =
096                    this.getConfiguration().getBoolean(
097                            CombinedConfigurationBuilder.ATTR_OPTIONAL,
098                            Boolean.FALSE);
099        }
100        return value.booleanValue();
101    }
102
103    /**
104     * Returns a flag whether this configuration should always be created and
105     * added to the resulting combined configuration. This flag is evaluated
106     * only for optional configurations whose normal creation has caused an
107     * error. If for such a configuration the {@code forceCreate} attribute is
108     * set and the corresponding configuration provider supports this mode, an
109     * empty configuration will be created and added to the resulting combined
110     * configuration.
111     *
112     * @return the value of the {@code forceCreate} attribute
113     */
114    public boolean isForceCreate()
115    {
116        return this.getConfiguration().getBoolean(
117                CombinedConfigurationBuilder.ATTR_FORCECREATE, false);
118    }
119
120    /**
121     * Returns a flag whether a builder with reloading support should be
122     * created. This may not be supported by all configuration builder
123     * providers.
124     *
125     * @return a flag whether a reloading builder should be created
126     */
127    public boolean isReload()
128    {
129        return getConfiguration().getBoolean(
130                CombinedConfigurationBuilder.ATTR_RELOAD, false);
131    }
132
133    /**
134     * Returns the name for the represented configuration source. The name is
135     * optional, so this method can return <b>null</b>.
136     *
137     * @return the name of the associated configuration source or <b>null</b>
138     */
139    public String getName()
140    {
141        return getConfiguration().getString(
142                CombinedConfigurationBuilder.ATTR_NAME);
143    }
144
145    /**
146     * Returns the name of the bean factory. For configuration source
147     * declarations always a reserved factory is used. This factory's name is
148     * returned by this implementation.
149     *
150     * @return the name of the bean factory
151     */
152    @Override
153    public String getBeanFactoryName()
154    {
155        return CombinedConfigurationBuilder.CONFIG_BEAN_FACTORY_NAME;
156    }
157
158    /**
159     * Returns the bean's class name. This implementation will always return
160     * <b>null</b>.
161     *
162     * @return the name of the bean's class
163     */
164    @Override
165    public String getBeanClassName()
166    {
167        return null;
168    }
169
170    /**
171     * {@inheritDoc} This implementation checks for additional reserved
172     * attribute names. Note that in some cases the presence of other attribute
173     * names determine whether a name is reserved or not. For instance, per
174     * default the attribute {@code config-at} is reserved. However, if this
175     * attribute is not present, the attribute {@code at} is also considered as
176     * a reserved attribute. (This is mainly done for dealing with legacy
177     * configuration files supported by earlier versions of this library.)
178     */
179    @Override
180    protected boolean isReservedAttributeName(final String name)
181    {
182        if (super.isReservedAttributeName(name))
183        {
184            return true;
185        }
186
187        final Set<String> attributes = getAttributeNames();
188        return (CombinedConfigurationBuilder.ATTR_ATNAME.equals(name) && !attributes
189                .contains(RESERVED_PREFIX
190                        + CombinedConfigurationBuilder.ATTR_ATNAME))
191                || (CombinedConfigurationBuilder.ATTR_OPTIONALNAME.equals(name) && !attributes
192                        .contains(RESERVED_PREFIX
193                                + CombinedConfigurationBuilder.ATTR_OPTIONALNAME));
194    }
195}