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.fluent;
018
019import java.io.File;
020import java.net.URL;
021
022import org.apache.commons.configuration2.CombinedConfiguration;
023import org.apache.commons.configuration2.FileBasedConfiguration;
024import org.apache.commons.configuration2.INIConfiguration;
025import org.apache.commons.configuration2.PropertiesConfiguration;
026import org.apache.commons.configuration2.XMLConfiguration;
027import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
028import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
029import org.apache.commons.configuration2.ex.ConfigurationException;
030
031//@formatter:off
032/**
033 * A convenience class which simplifies the creation of standard configurations and their builders.
034 * <p>
035 * Complex initializations of configuration builders can be done in a pretty straight-forward way by making use of the
036 * provided fluent API. However, if only default settings are used (and maybe a configuration file to be loaded has to
037 * be specified), this approach tends to become a bit verbose. This class was introduced to simplify the creation of
038 * configuration objects in such cases. It offers a bunch of methods which allow the creation of some standard
039 * configuration classes with default settings passing in only a minimum required parameters.
040 * </p>
041 * <p>
042 * An an example consider the creation of a {@code PropertiesConfiguration} object from a file. Using a builder, code
043 * like the following one would have to be written:
044 * </p>
045 * <pre>
046 * Parameters params = new Parameters();
047 * FileBasedConfigurationBuilder&lt;PropertiesConfiguration&gt; builder =
048 *   new FileBasedConfigurationBuilder&lt;PropertiesConfiguration&gt;(PropertiesConfiguration.class)
049 *     .configure(params.fileBased().setFile(new File(&quot;config.properties&quot;)));
050 * PropertiesConfiguration config = builder.getConfiguration();
051 * </pre>
052 * <p>
053 * With a convenience method of {@code Configurations} the same can be achieved with the following:
054 * </p>
055 * <pre>
056 * Configurations configurations = new Configurations();
057 * PropertiesConfiguration config = configurations.properties(new File(&quot;config.properties&quot;));
058 * </pre>
059 * <p>
060 * There are similar methods for constructing builder objects from which configurations can then be obtained.
061 * </p>
062 * <p>
063 * This class is thread-safe. A single instance can be created by an application and used in a central way to create
064 * configuration objects. When an instance is created a {@link Parameters} instance can be passed in. Otherwise, a
065 * default instance is created. In any case, the {@code Parameters} instance associated with a {@code Configurations}
066 * object can be used to define default settings for the configurations to be created.
067 * </p>
068 *
069 * @since 2.0
070 * @see org.apache.commons.configuration2.builder.DefaultParametersManager
071 */
072//@formatter:off
073public class Configurations {
074    /** The parameters object associated with this instance. */
075    private final Parameters parameters;
076
077    /**
078     * Creates a new {@code Configurations} instance with default settings.
079     */
080    public Configurations() {
081        this(null);
082    }
083
084    /**
085     * Creates a new instance of {@code Configurations} and initializes it with the specified {@code Parameters} object.
086     *
087     * @param params the {@code Parameters} (may be <b>null</b>, then a default instance is created)
088     */
089    public Configurations(final Parameters params) {
090        parameters = params != null ? params : new Parameters();
091    }
092
093    /**
094     * Creates a {@code CombinedConfiguration} instance from the content of the given file. This is a convenience method
095     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
096     * builder is created).
097     *
098     * @param file the file to be loaded
099     * @return a {@code CombinedConfiguration} object initialized from this file
100     * @throws ConfigurationException if an error occurred when loading the configuration
101     */
102    public CombinedConfiguration combined(final File file) throws ConfigurationException {
103        return combinedBuilder(file).getConfiguration();
104    }
105
106    /**
107     * Creates a {@code CombinedConfiguration} instance from the content of the file identified by the given path. This is a
108     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
109     * the scenes a builder is created).
110     *
111     * @param path the path to the file to be loaded
112     * @return a {@code CombinedConfiguration} object initialized from this URL
113     * @throws ConfigurationException if an error occurred when loading the configuration
114     */
115    public CombinedConfiguration combined(final String path) throws ConfigurationException {
116        return combinedBuilder(path).getConfiguration();
117    }
118
119    /**
120     * Creates a {@code CombinedConfiguration} instance from the content of the given URL. This is a convenience method
121     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
122     * builder is created).
123     *
124     * @param url the URL to be loaded
125     * @return a {@code CombinedConfiguration} object initialized from this URL
126     * @throws ConfigurationException if an error occurred when loading the configuration
127     */
128    public CombinedConfiguration combined(final URL url) throws ConfigurationException {
129        return combinedBuilder(url).getConfiguration();
130    }
131
132    /**
133     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given file to be loaded.
134     *
135     * @param file the file to be loaded
136     * @return the newly created {@code CombinedConfigurationBuilder}
137     */
138    public CombinedConfigurationBuilder combinedBuilder(final File file) {
139        return new CombinedConfigurationBuilder().configure(fileParams(file));
140    }
141
142    /**
143     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given path to the file to be
144     * loaded.
145     *
146     * @param path the path to the file to be loaded
147     * @return the newly created {@code CombinedConfigurationBuilder}
148     */
149    public CombinedConfigurationBuilder combinedBuilder(final String path) {
150        return new CombinedConfigurationBuilder().configure(fileParams(path));
151    }
152
153    /**
154     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given URL to be loaded.
155     *
156     * @param url the URL to be loaded
157     * @return the newly created {@code CombinedConfigurationBuilder}
158     */
159    public CombinedConfigurationBuilder combinedBuilder(final URL url) {
160        return new CombinedConfigurationBuilder().configure(fileParams(url));
161    }
162
163    /**
164     * Creates a configured builder for a file-based configuration of the specified type.
165     *
166     * @param configClass the configuration class
167     * @param <T> the type of the configuration to be constructed
168     * @return the newly created builder
169     * @since 2.6
170     */
171    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(final Class<T> configClass) {
172        return new FileBasedConfigurationBuilder<>(configClass);
173    }
174
175    /**
176     * Creates a configured builder for a file-based configuration of the specified type.
177     *
178     * @param configClass the configuration class
179     * @param params the parameters object for configuring the builder
180     * @param <T> the type of the configuration to be constructed
181     * @return the newly created builder
182     */
183    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(final Class<T> configClass,
184        final FileBasedBuilderParameters params) {
185        return createFileBasedBuilder(configClass).configure(params);
186    }
187
188    /**
189     * Creates an instance of the specified file-based configuration class from the content of the given file. This is a
190     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
191     * the scenes a builder is created).
192     *
193     * @param configClass the configuration class
194     * @param file the file to be loaded
195     * @param <T> the type of the configuration to be constructed
196     * @return a {@code FileBasedConfiguration} object initialized from this file
197     * @throws ConfigurationException if an error occurred when loading the configuration
198     */
199    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final File file) throws ConfigurationException {
200        return fileBasedBuilder(configClass, file).getConfiguration();
201    }
202
203    /**
204     * Creates an instance of the specified file-based configuration class from the content of the file identified by the
205     * given path. This is a convenience method which can be used if no builder is needed for managing the configuration
206     * object. (Although, behind the scenes a builder is created).
207     *
208     * @param configClass the configuration class
209     * @param path the path to the file to be loaded
210     * @param <T> the type of the configuration to be constructed
211     * @return a {@code FileBasedConfiguration} object initialized from this file
212     * @throws ConfigurationException if an error occurred when loading the configuration
213     */
214    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final String path) throws ConfigurationException {
215        return fileBasedBuilder(configClass, path).getConfiguration();
216    }
217
218    /**
219     * Creates an instance of the specified file-based configuration class from the content of the given URL. This is a
220     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
221     * the scenes a builder is created).
222     *
223     * @param configClass the configuration class
224     * @param url the URL to be loaded
225     * @param <T> the type of the configuration to be constructed
226     * @return a {@code FileBasedConfiguration} object initialized from this file
227     * @throws ConfigurationException if an error occurred when loading the configuration
228     */
229    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final URL url) throws ConfigurationException {
230        return fileBasedBuilder(configClass, url).getConfiguration();
231    }
232
233    /**
234     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the
235     * file to be loaded.
236     *
237     * @param configClass the configuration class
238     * @param file the file to be loaded
239     * @param <T> the type of the configuration to be constructed
240     * @return the new {@code FileBasedConfigurationBuilder}
241     */
242    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final File file) {
243        return createFileBasedBuilder(configClass, fileParams(file));
244    }
245
246    /**
247     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the
248     * path to the file to be loaded.
249     *
250     * @param configClass the configuration class
251     * @param path the path to the file to be loaded
252     * @param <T> the type of the configuration to be constructed
253     * @return the new {@code FileBasedConfigurationBuilder}
254     */
255    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final String path) {
256        return createFileBasedBuilder(configClass, fileParams(path));
257    }
258
259    /**
260     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the URL
261     * to the file to be loaded.
262     *
263     * @param configClass the configuration class
264     * @param url the URL to be loaded
265     * @param <T> the type of the configuration to be constructed
266     * @return the new {@code FileBasedConfigurationBuilder}
267     */
268    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final URL url) {
269        return createFileBasedBuilder(configClass, fileParams(url));
270    }
271
272    /**
273     * Convenience method for creating a parameters object for a file-based configuration.
274     *
275     * @return the newly created parameters object
276     */
277    private FileBasedBuilderParameters fileParams() {
278        return getParameters().fileBased();
279    }
280
281    /**
282     * Convenience method for creating a file-based parameters object initialized with the given file.
283     *
284     * @param file the file to be loaded
285     * @return the initialized parameters object
286     */
287    private FileBasedBuilderParameters fileParams(final File file) {
288        return fileParams().setFile(file);
289    }
290
291    /**
292     * Convenience method for creating a file-based parameters object initialized with the given file path.
293     *
294     * @param path the path to the file to be loaded
295     * @return the initialized parameters object
296     */
297    private FileBasedBuilderParameters fileParams(final String path) {
298        return fileParams().setFileName(path);
299    }
300
301    /**
302     * Convenience method for creating a file-based parameters object initialized with the given file.
303     *
304     * @param url the URL to be loaded
305     * @return the initialized parameters object
306     */
307    private FileBasedBuilderParameters fileParams(final URL url) {
308        return fileParams().setURL(url);
309    }
310
311    /**
312     * Gets the {@code Parameters} instance associated with this object.
313     *
314     * @return the associated {@code Parameters} object
315     */
316    public Parameters getParameters() {
317        return parameters;
318    }
319
320    /**
321     * Creates a {@code INIConfiguration} instance from the content of the given file. This is a convenience method which
322     * can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
323     * created).
324     *
325     * @param file the file to be loaded
326     * @return a {@code INIConfiguration} object initialized from this file
327     * @throws ConfigurationException if an error occurred when loading the configuration
328     */
329    public INIConfiguration ini(final File file) throws ConfigurationException {
330        return iniBuilder(file).getConfiguration();
331    }
332
333    /**
334     * Creates a {@code INIConfiguration} instance from the content of the file identified by the given path. This is a
335     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
336     * the scenes a builder is created).
337     *
338     * @param path the path to the file to be loaded
339     * @return a {@code INIConfiguration} object initialized from this file
340     * @throws ConfigurationException if an error occurred when loading the configuration
341     */
342    public INIConfiguration ini(final String path) throws ConfigurationException {
343        return iniBuilder(path).getConfiguration();
344    }
345
346    /**
347     * Creates a {@code INIConfiguration} instance from the content of the given URL. This is a convenience method which can
348     * be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
349     * created).
350     *
351     * @param url the URL to be loaded
352     * @return a {@code INIConfiguration} object initialized from this file
353     * @throws ConfigurationException if an error occurred when loading the configuration
354     */
355    public INIConfiguration ini(final URL url) throws ConfigurationException {
356        return iniBuilder(url).getConfiguration();
357    }
358
359    /**
360     * Creates a builder for a {@code INIConfiguration} and initializes it with the given file to be loaded.
361     *
362     * @param file the file to be loaded
363     * @return the newly created {@code FileBasedConfigurationBuilder}
364     */
365    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final File file) {
366        return fileBasedBuilder(INIConfiguration.class, file);
367    }
368
369    /**
370     * Creates a builder for a {@code INIConfiguration} and initializes it with the file file identified by the given path.
371     *
372     * @param path the path to the file to be loaded
373     * @return the newly created {@code FileBasedConfigurationBuilder}
374     */
375    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final String path) {
376        return fileBasedBuilder(INIConfiguration.class, path);
377    }
378
379    /**
380     * Creates a builder for a {@code INIConfiguration} and initializes it with the given URL to be loaded.
381     *
382     * @param url the URL to be loaded
383     * @return the newly created {@code FileBasedConfigurationBuilder}
384     */
385    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final URL url) {
386        return fileBasedBuilder(INIConfiguration.class, url);
387    }
388
389    /**
390     * Creates a {@code PropertiesConfiguration} instance from the content of the given file. This is a convenience method
391     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
392     * builder is created).
393     *
394     * @param file the file to be loaded
395     * @return a {@code PropertiesConfiguration} object initialized from this file
396     * @throws ConfigurationException if an error occurred when loading the configuration
397     */
398    public PropertiesConfiguration properties(final File file) throws ConfigurationException {
399        return propertiesBuilder(file).getConfiguration();
400    }
401
402    /**
403     * Creates a {@code PropertiesConfiguration} instance from the content of the file identified by the given path. This is
404     * a convenience method which can be used if no builder is needed for managing the configuration object. (Although,
405     * behind the scenes a builder is created).
406     *
407     * @param path the path to the file to be loaded
408     * @return a {@code PropertiesConfiguration} object initialized from this path
409     * @throws ConfigurationException if an error occurred when loading the configuration
410     */
411    public PropertiesConfiguration properties(final String path) throws ConfigurationException {
412        return propertiesBuilder(path).getConfiguration();
413    }
414
415    /**
416     * Creates a {@code PropertiesConfiguration} instance from the content of the given URL. This is a convenience method
417     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
418     * builder is created).
419     *
420     * @param url the URL to be loaded
421     * @return a {@code PropertiesConfiguration} object initialized from this URL
422     * @throws ConfigurationException if an error occurred when loading the configuration
423     */
424    public PropertiesConfiguration properties(final URL url) throws ConfigurationException {
425        return propertiesBuilder(url).getConfiguration();
426    }
427
428    /**
429     * Creates a builder for a {@code PropertiesConfiguration}.
430     *
431     * @return the newly created {@code FileBasedConfigurationBuilder}
432     * @since 2.6
433     */
434    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder() {
435        return createFileBasedBuilder(PropertiesConfiguration.class);
436    }
437
438    /**
439     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given file to be loaded.
440     *
441     * @param file the file to be loaded
442     * @return the newly created {@code FileBasedConfigurationBuilder}
443     */
444    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final File file) {
445        return fileBasedBuilder(PropertiesConfiguration.class, file);
446    }
447
448    /**
449     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given parameters to be loaded.
450     *
451     * @param parameters the parameters to be loaded
452     * @return the newly created {@code FileBasedConfigurationBuilder}
453     * @since 2.6
454     */
455    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final PropertiesBuilderParameters parameters) {
456        return propertiesBuilder().configure(parameters);
457    }
458
459    /**
460     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given path to the file to be
461     * loaded.
462     *
463     * @param path the path to the file to be loaded
464     * @return the newly created {@code FileBasedConfigurationBuilder}
465     */
466    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final String path) {
467        return fileBasedBuilder(PropertiesConfiguration.class, path);
468    }
469
470    /**
471     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given URL to be loaded.
472     *
473     * @param url the URL to be loaded
474     * @return the newly created {@code FileBasedConfigurationBuilder}
475     */
476    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final URL url) {
477        return fileBasedBuilder(PropertiesConfiguration.class, url);
478    }
479
480    /**
481     * Creates a {@code XMLConfiguration} instance from the content of the given file. This is a convenience method which
482     * can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
483     * created).
484     *
485     * @param file the file to be loaded
486     * @return a {@code XMLConfiguration} object initialized from this file
487     * @throws ConfigurationException if an error occurred when loading the configuration
488     */
489    public XMLConfiguration xml(final File file) throws ConfigurationException {
490        return xmlBuilder(file).getConfiguration();
491    }
492
493    /**
494     * Creates a {@code XMLConfiguration} instance from the content of the file identified by the given path. This is a
495     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
496     * the scenes a builder is created).
497     *
498     * @param path the path to the file to be loaded
499     * @return a {@code XMLConfiguration} object initialized from this file
500     * @throws ConfigurationException if an error occurred when loading the configuration
501     */
502    public XMLConfiguration xml(final String path) throws ConfigurationException {
503        return xmlBuilder(path).getConfiguration();
504    }
505
506    /**
507     * Creates a {@code XMLConfiguration} instance from the content of the given URL. This is a convenience method which can
508     * be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
509     * created).
510     *
511     * @param url the URL to be loaded
512     * @return a {@code XMLConfiguration} object initialized from this file
513     * @throws ConfigurationException if an error occurred when loading the configuration
514     */
515    public XMLConfiguration xml(final URL url) throws ConfigurationException {
516        return xmlBuilder(url).getConfiguration();
517    }
518
519    /**
520     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given file to be loaded.
521     *
522     * @param file the file to be loaded
523     * @return the newly created {@code FileBasedConfigurationBuilder}
524     */
525    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final File file) {
526        return fileBasedBuilder(XMLConfiguration.class, file);
527    }
528
529    /**
530     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given path to the file to be loaded.
531     *
532     * @param path the path to the file to be loaded
533     * @return the newly created {@code FileBasedConfigurationBuilder}
534     */
535    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final String path) {
536        return fileBasedBuilder(XMLConfiguration.class, path);
537    }
538
539    /**
540     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given URL to be loaded.
541     *
542     * @param url the URL to be loaded
543     * @return the newly created {@code FileBasedConfigurationBuilder}
544     */
545    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final URL url) {
546        return fileBasedBuilder(XMLConfiguration.class, url);
547    }
548
549}