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