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