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.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
075    /** The parameters object associated with this instance. */
076    private final Parameters parameters;
077
078    /**
079     * Creates a new {@code Configurations} instance with default settings.
080     */
081    public Configurations() {
082        this(null);
083    }
084
085    /**
086     * Creates a new instance of {@code Configurations} and initializes it with the specified {@code Parameters} object.
087     *
088     * @param params the {@code Parameters} (may be <strong>null</strong>, then a default instance is created)
089     */
090    public Configurations(final Parameters params) {
091        parameters = params != null ? params : new Parameters();
092    }
093
094    /**
095     * Creates a {@code CombinedConfiguration} instance from the content of the given file. This is a convenience method
096     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
097     * builder is created).
098     *
099     * @param file the file to be loaded
100     * @return a {@code CombinedConfiguration} object initialized from this file
101     * @throws ConfigurationException if an error occurred when loading the configuration
102     */
103    public CombinedConfiguration combined(final File file) throws ConfigurationException {
104        return combinedBuilder(file).getConfiguration();
105    }
106
107    /**
108     * Creates a {@code CombinedConfiguration} instance from the content of the file identified by the given path. This is a
109     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
110     * the scenes a builder is created).
111     *
112     * @param path the path to the file to be loaded
113     * @return a {@code CombinedConfiguration} object initialized from this URL
114     * @throws ConfigurationException if an error occurred when loading the configuration
115     */
116    public CombinedConfiguration combined(final String path) throws ConfigurationException {
117        return combinedBuilder(path).getConfiguration();
118    }
119
120    /**
121     * Creates a {@code CombinedConfiguration} instance from the content of the given URL. This is a convenience method
122     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
123     * builder is created).
124     *
125     * @param url the URL to be loaded
126     * @return a {@code CombinedConfiguration} object initialized from this URL
127     * @throws ConfigurationException if an error occurred when loading the configuration
128     */
129    public CombinedConfiguration combined(final URL url) throws ConfigurationException {
130        return combinedBuilder(url).getConfiguration();
131    }
132
133    /**
134     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given file to be loaded.
135     *
136     * @param file the file to be loaded
137     * @return the newly created {@code CombinedConfigurationBuilder}
138     */
139    public CombinedConfigurationBuilder combinedBuilder(final File file) {
140        return new CombinedConfigurationBuilder().configure(fileParams(file));
141    }
142
143    /**
144     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given path to the file to be
145     * loaded.
146     *
147     * @param path the path to the file to be loaded
148     * @return the newly created {@code CombinedConfigurationBuilder}
149     */
150    public CombinedConfigurationBuilder combinedBuilder(final String path) {
151        return new CombinedConfigurationBuilder().configure(fileParams(path));
152    }
153
154    /**
155     * Creates a builder for a {@code CombinedConfiguration} and initializes it with the given URL to be loaded.
156     *
157     * @param url the URL to be loaded
158     * @return the newly created {@code CombinedConfigurationBuilder}
159     */
160    public CombinedConfigurationBuilder combinedBuilder(final URL url) {
161        return new CombinedConfigurationBuilder().configure(fileParams(url));
162    }
163
164    /**
165     * Creates a configured builder for a file-based configuration of the specified type.
166     *
167     * @param configClass the configuration class
168     * @param <T> the type of the configuration to be constructed
169     * @return the newly created builder
170     * @since 2.6
171     */
172    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(final Class<T> configClass) {
173        return new FileBasedConfigurationBuilder<>(configClass);
174    }
175
176    /**
177     * Creates a configured builder for a file-based configuration of the specified type.
178     *
179     * @param configClass the configuration class
180     * @param params the parameters object for configuring the builder
181     * @param <T> the type of the configuration to be constructed
182     * @return the newly created builder
183     */
184    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(final Class<T> configClass,
185        final FileBasedBuilderParameters params) {
186        return createFileBasedBuilder(configClass).configure(params);
187    }
188
189    /**
190     * Creates an instance of the specified file-based configuration class from the content of the given file. This is a
191     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
192     * the scenes a builder is created).
193     *
194     * @param configClass the configuration class
195     * @param file the file to be loaded
196     * @param <T> the type of the configuration to be constructed
197     * @return a {@code FileBasedConfiguration} object initialized from this file
198     * @throws ConfigurationException if an error occurred when loading the configuration
199     */
200    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final File file) throws ConfigurationException {
201        return fileBasedBuilder(configClass, file).getConfiguration();
202    }
203
204    /**
205     * Creates an instance of the specified file-based configuration class from the content of the file identified by the
206     * given path. This is a convenience method which can be used if no builder is needed for managing the configuration
207     * object. (Although, behind the scenes a builder is created).
208     *
209     * @param configClass the configuration class
210     * @param path the path to the file to be loaded
211     * @param <T> the type of the configuration to be constructed
212     * @return a {@code FileBasedConfiguration} object initialized from this file
213     * @throws ConfigurationException if an error occurred when loading the configuration
214     */
215    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final String path) throws ConfigurationException {
216        return fileBasedBuilder(configClass, path).getConfiguration();
217    }
218
219    /**
220     * Creates an instance of the specified file-based configuration class from the content of the given URL. This is a
221     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
222     * the scenes a builder is created).
223     *
224     * @param configClass the configuration class
225     * @param url the URL to be loaded
226     * @param <T> the type of the configuration to be constructed
227     * @return a {@code FileBasedConfiguration} object initialized from this file
228     * @throws ConfigurationException if an error occurred when loading the configuration
229     */
230    public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final URL url) throws ConfigurationException {
231        return fileBasedBuilder(configClass, url).getConfiguration();
232    }
233
234    /**
235     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the
236     * file to be loaded.
237     *
238     * @param configClass the configuration class
239     * @param file the file to be loaded
240     * @param <T> the type of the configuration to be constructed
241     * @return the new {@code FileBasedConfigurationBuilder}
242     */
243    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final File file) {
244        return createFileBasedBuilder(configClass, fileParams(file));
245    }
246
247    /**
248     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the
249     * path to the file to be loaded.
250     *
251     * @param configClass the configuration class
252     * @param path the path to the file to be loaded
253     * @param <T> the type of the configuration to be constructed
254     * @return the new {@code FileBasedConfigurationBuilder}
255     */
256    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final String path) {
257        return createFileBasedBuilder(configClass, fileParams(path));
258    }
259
260    /**
261     * Creates a {@code FileBasedConfigurationBuilder} for the specified configuration class and initializes it with the URL
262     * to the file to be loaded.
263     *
264     * @param configClass the configuration class
265     * @param url the URL to be loaded
266     * @param <T> the type of the configuration to be constructed
267     * @return the new {@code FileBasedConfigurationBuilder}
268     */
269    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final URL url) {
270        return createFileBasedBuilder(configClass, fileParams(url));
271    }
272
273    /**
274     * Convenience method for creating a parameters object for a file-based configuration.
275     *
276     * @return the newly created parameters object
277     */
278    private FileBasedBuilderParameters fileParams() {
279        return getParameters().fileBased();
280    }
281
282    /**
283     * Convenience method for creating a file-based parameters object initialized with the given file.
284     *
285     * @param file the file to be loaded
286     * @return the initialized parameters object
287     */
288    private FileBasedBuilderParameters fileParams(final File file) {
289        return fileParams().setFile(file);
290    }
291
292    /**
293     * Convenience method for creating a file-based parameters object initialized with the given file path.
294     *
295     * @param path the path to the file to be loaded
296     * @return the initialized parameters object
297     */
298    private FileBasedBuilderParameters fileParams(final String path) {
299        return fileParams().setFileName(path);
300    }
301
302    /**
303     * Convenience method for creating a file-based parameters object initialized with the given file.
304     *
305     * @param url the URL to be loaded
306     * @return the initialized parameters object
307     */
308    private FileBasedBuilderParameters fileParams(final URL url) {
309        return fileParams().setURL(url);
310    }
311
312    /**
313     * Gets the {@code Parameters} instance associated with this object.
314     *
315     * @return the associated {@code Parameters} object
316     */
317    public Parameters getParameters() {
318        return parameters;
319    }
320
321    /**
322     * Creates a {@code INIConfiguration} instance from the content of the given file. This is a convenience method which
323     * can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
324     * created).
325     *
326     * @param file the file to be loaded
327     * @return a {@code INIConfiguration} object initialized from this file
328     * @throws ConfigurationException if an error occurred when loading the configuration
329     */
330    public INIConfiguration ini(final File file) throws ConfigurationException {
331        return iniBuilder(file).getConfiguration();
332    }
333
334    /**
335     * Creates a {@code INIConfiguration} instance from the content of the file identified by the given path. This is a
336     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
337     * the scenes a builder is created).
338     *
339     * @param path the path to the file to be loaded
340     * @return a {@code INIConfiguration} object initialized from this file
341     * @throws ConfigurationException if an error occurred when loading the configuration
342     */
343    public INIConfiguration ini(final String path) throws ConfigurationException {
344        return iniBuilder(path).getConfiguration();
345    }
346
347    /**
348     * Creates a {@code INIConfiguration} instance from the content of the given URL. This is a convenience method which can
349     * be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
350     * created).
351     *
352     * @param url the URL to be loaded
353     * @return a {@code INIConfiguration} object initialized from this file
354     * @throws ConfigurationException if an error occurred when loading the configuration
355     */
356    public INIConfiguration ini(final URL url) throws ConfigurationException {
357        return iniBuilder(url).getConfiguration();
358    }
359
360    /**
361     * Creates a builder for a {@code INIConfiguration} and initializes it with the given file to be loaded.
362     *
363     * @param file the file to be loaded
364     * @return the newly created {@code FileBasedConfigurationBuilder}
365     */
366    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final File file) {
367        return fileBasedBuilder(INIConfiguration.class, file);
368    }
369
370    /**
371     * Creates a builder for a {@code INIConfiguration} and initializes it with the file file identified by the given path.
372     *
373     * @param path the path to the file to be loaded
374     * @return the newly created {@code FileBasedConfigurationBuilder}
375     */
376    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final String path) {
377        return fileBasedBuilder(INIConfiguration.class, path);
378    }
379
380    /**
381     * Creates a builder for a {@code INIConfiguration} and initializes it with the given URL to be loaded.
382     *
383     * @param url the URL to be loaded
384     * @return the newly created {@code FileBasedConfigurationBuilder}
385     */
386    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final URL url) {
387        return fileBasedBuilder(INIConfiguration.class, url);
388    }
389
390    /**
391     * Creates a {@code PropertiesConfiguration} instance from the content of the given file. This is a convenience method
392     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
393     * builder is created).
394     *
395     * @param file the file to be loaded
396     * @return a {@code PropertiesConfiguration} object initialized from this file
397     * @throws ConfigurationException if an error occurred when loading the configuration
398     */
399    public PropertiesConfiguration properties(final File file) throws ConfigurationException {
400        return propertiesBuilder(file).getConfiguration();
401    }
402
403    /**
404     * Creates a {@code PropertiesConfiguration} instance from the content of the file identified by the given path. This is
405     * a convenience method which can be used if no builder is needed for managing the configuration object. (Although,
406     * behind the scenes a builder is created).
407     *
408     * @param path the path to the file to be loaded
409     * @return a {@code PropertiesConfiguration} object initialized from this path
410     * @throws ConfigurationException if an error occurred when loading the configuration
411     */
412    public PropertiesConfiguration properties(final String path) throws ConfigurationException {
413        return propertiesBuilder(path).getConfiguration();
414    }
415
416    /**
417     * Creates a {@code PropertiesConfiguration} instance from the content of the given URL. This is a convenience method
418     * which can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a
419     * builder is created).
420     *
421     * @param url the URL to be loaded
422     * @return a {@code PropertiesConfiguration} object initialized from this URL
423     * @throws ConfigurationException if an error occurred when loading the configuration
424     */
425    public PropertiesConfiguration properties(final URL url) throws ConfigurationException {
426        return propertiesBuilder(url).getConfiguration();
427    }
428
429    /**
430     * Creates a builder for a {@code PropertiesConfiguration}.
431     *
432     * @return the newly created {@code FileBasedConfigurationBuilder}
433     * @since 2.6
434     */
435    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder() {
436        return createFileBasedBuilder(PropertiesConfiguration.class);
437    }
438
439    /**
440     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given file to be loaded.
441     *
442     * @param file the file to be loaded
443     * @return the newly created {@code FileBasedConfigurationBuilder}
444     */
445    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final File file) {
446        return fileBasedBuilder(PropertiesConfiguration.class, file);
447    }
448
449    /**
450     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given parameters to be loaded.
451     *
452     * @param parameters the parameters to be loaded
453     * @return the newly created {@code FileBasedConfigurationBuilder}
454     * @since 2.6
455     */
456    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final PropertiesBuilderParameters parameters) {
457        return propertiesBuilder().configure(parameters);
458    }
459
460    /**
461     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given path to the file to be
462     * loaded.
463     *
464     * @param path the path to the file to be loaded
465     * @return the newly created {@code FileBasedConfigurationBuilder}
466     */
467    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final String path) {
468        return fileBasedBuilder(PropertiesConfiguration.class, path);
469    }
470
471    /**
472     * Creates a builder for a {@code PropertiesConfiguration} and initializes it with the given URL to be loaded.
473     *
474     * @param url the URL to be loaded
475     * @return the newly created {@code FileBasedConfigurationBuilder}
476     */
477    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(final URL url) {
478        return fileBasedBuilder(PropertiesConfiguration.class, url);
479    }
480
481    /**
482     * Creates a {@code XMLConfiguration} instance from the content of the given file. This is a convenience method which
483     * can be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
484     * created).
485     *
486     * @param file the file to be loaded
487     * @return a {@code XMLConfiguration} object initialized from this file
488     * @throws ConfigurationException if an error occurred when loading the configuration
489     */
490    public XMLConfiguration xml(final File file) throws ConfigurationException {
491        return xmlBuilder(file).getConfiguration();
492    }
493
494    /**
495     * Creates a {@code XMLConfiguration} instance from the content of the file identified by the given path. This is a
496     * convenience method which can be used if no builder is needed for managing the configuration object. (Although, behind
497     * the scenes a builder is created).
498     *
499     * @param path the path to the file to be loaded
500     * @return a {@code XMLConfiguration} object initialized from this file
501     * @throws ConfigurationException if an error occurred when loading the configuration
502     */
503    public XMLConfiguration xml(final String path) throws ConfigurationException {
504        return xmlBuilder(path).getConfiguration();
505    }
506
507    /**
508     * Creates a {@code XMLConfiguration} instance from the content of the given URL. This is a convenience method which can
509     * be used if no builder is needed for managing the configuration object. (Although, behind the scenes a builder is
510     * created).
511     *
512     * @param url the URL to be loaded
513     * @return a {@code XMLConfiguration} object initialized from this file
514     * @throws ConfigurationException if an error occurred when loading the configuration
515     */
516    public XMLConfiguration xml(final URL url) throws ConfigurationException {
517        return xmlBuilder(url).getConfiguration();
518    }
519
520    /**
521     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given file to be loaded.
522     *
523     * @param file the file to be loaded
524     * @return the newly created {@code FileBasedConfigurationBuilder}
525     */
526    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final File file) {
527        return fileBasedBuilder(XMLConfiguration.class, file);
528    }
529
530    /**
531     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given path to the file to be loaded.
532     *
533     * @param path the path to the file to be loaded
534     * @return the newly created {@code FileBasedConfigurationBuilder}
535     */
536    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final String path) {
537        return fileBasedBuilder(XMLConfiguration.class, path);
538    }
539
540    /**
541     * Creates a builder for a {@code XMLConfiguration} and initializes it with the given URL to be loaded.
542     *
543     * @param url the URL to be loaded
544     * @return the newly created {@code FileBasedConfigurationBuilder}
545     */
546    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final URL url) {
547        return fileBasedBuilder(XMLConfiguration.class, url);
548    }
549
550}