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}.
229     *
230     * @return the newly created {@code FileBasedConfigurationBuilder}
231     * @since 2.6
232     */
233    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder()
234    {
235        return createFileBasedBuilder(PropertiesConfiguration.class);
236    }
237
238    /**
239     * Creates a builder for a {@code PropertiesConfiguration} and initializes
240     * it with the given file to be loaded.
241     *
242     * @param file the file to be loaded
243     * @return the newly created {@code FileBasedConfigurationBuilder}
244     */
245    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
246            final File file)
247    {
248        return fileBasedBuilder(PropertiesConfiguration.class, file);
249    }
250
251    /**
252     * Creates a builder for a {@code PropertiesConfiguration} and initializes
253     * it with the given parameters to be loaded.
254     *
255     * @param parameters the parameters to be loaded
256     * @return the newly created {@code FileBasedConfigurationBuilder}
257     * @since 2.6
258     */
259    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
260            PropertiesBuilderParameters parameters)
261    {
262        return propertiesBuilder().configure(parameters);
263    }
264
265    /**
266     * Creates a builder for a {@code PropertiesConfiguration} and initializes
267     * it with the given URL to be loaded.
268     *
269     * @param url the URL to be loaded
270     * @return the newly created {@code FileBasedConfigurationBuilder}
271     */
272    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
273            final URL url)
274    {
275        return fileBasedBuilder(PropertiesConfiguration.class, url);
276    }
277
278    /**
279     * Creates a builder for a {@code PropertiesConfiguration} and initializes
280     * it with the given path to the file to be loaded.
281     *
282     * @param path the path to the file to be loaded
283     * @return the newly created {@code FileBasedConfigurationBuilder}
284     */
285    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
286            final String path)
287    {
288        return fileBasedBuilder(PropertiesConfiguration.class, path);
289    }
290
291    /**
292     * Creates a {@code PropertiesConfiguration} instance from the content of
293     * the given file. This is a convenience method which can be used if no
294     * builder is needed for managing the configuration object. (Although,
295     * behind the scenes a builder is created).
296     *
297     * @param file the file to be loaded
298     * @return a {@code PropertiesConfiguration} object initialized from this
299     *         file
300     * @throws ConfigurationException if an error occurred when loading the
301     *         configuration
302     */
303    public PropertiesConfiguration properties(final File file)
304            throws ConfigurationException
305    {
306        return propertiesBuilder(file).getConfiguration();
307    }
308
309    /**
310     * Creates a {@code PropertiesConfiguration} instance from the content of
311     * the given URL. This is a convenience method which can be used if no
312     * builder is needed for managing the configuration object. (Although,
313     * behind the scenes a builder is created).
314     *
315     * @param url the URL to be loaded
316     * @return a {@code PropertiesConfiguration} object initialized from this
317     *         URL
318     * @throws ConfigurationException if an error occurred when loading the
319     *         configuration
320     */
321    public PropertiesConfiguration properties(final URL url)
322            throws ConfigurationException
323    {
324        return propertiesBuilder(url).getConfiguration();
325    }
326
327    /**
328     * Creates a {@code PropertiesConfiguration} instance from the content of
329     * the file identified by the given path. This is a convenience method which
330     * can be used if no builder is needed for managing the configuration
331     * object. (Although, behind the scenes a builder is created).
332     *
333     * @param path the path to the file to be loaded
334     * @return a {@code PropertiesConfiguration} object initialized from this
335     *         path
336     * @throws ConfigurationException if an error occurred when loading the
337     *         configuration
338     */
339    public PropertiesConfiguration properties(final String path)
340            throws ConfigurationException
341    {
342        return propertiesBuilder(path).getConfiguration();
343    }
344
345    /**
346     * Creates a builder for a {@code XMLConfiguration} and initializes it with
347     * 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<XMLConfiguration> xmlBuilder(final File file)
353    {
354        return fileBasedBuilder(XMLConfiguration.class, file);
355    }
356
357    /**
358     * Creates a builder for a {@code XMLConfiguration} and initializes it with
359     * the given URL to be loaded.
360     *
361     * @param url the URL to be loaded
362     * @return the newly created {@code FileBasedConfigurationBuilder}
363     */
364    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(final URL url)
365    {
366        return fileBasedBuilder(XMLConfiguration.class, url);
367    }
368
369    /**
370     * Creates a builder for a {@code XMLConfiguration} and initializes it with
371     * the given path to the file to be loaded.
372     *
373     * @param path the path to the file to be loaded
374     * @return the newly created {@code FileBasedConfigurationBuilder}
375     */
376    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(
377            final String path)
378    {
379        return fileBasedBuilder(XMLConfiguration.class, path);
380    }
381
382    /**
383     * Creates a {@code XMLConfiguration} instance from the content of the given
384     * file. This is a convenience method which can be used if no builder is
385     * needed for managing the configuration object. (Although, behind the
386     * scenes a builder is created).
387     *
388     * @param file the file to be loaded
389     * @return a {@code XMLConfiguration} object initialized from this file
390     * @throws ConfigurationException if an error occurred when loading the
391     *         configuration
392     */
393    public XMLConfiguration xml(final File file) throws ConfigurationException
394    {
395        return xmlBuilder(file).getConfiguration();
396    }
397
398    /**
399     * Creates a {@code XMLConfiguration} instance from the content of the given
400     * URL. This is a convenience method which can be used if no builder is
401     * needed for managing the configuration object. (Although, behind the
402     * scenes a builder is created).
403     *
404     * @param url the URL to be loaded
405     * @return a {@code XMLConfiguration} object initialized from this file
406     * @throws ConfigurationException if an error occurred when loading the
407     *         configuration
408     */
409    public XMLConfiguration xml(final URL url) throws ConfigurationException
410    {
411        return xmlBuilder(url).getConfiguration();
412    }
413
414    /**
415     * Creates a {@code XMLConfiguration} instance from the content of the file
416     * identified by the given path. This is a convenience method which can be
417     * used if no builder is needed for managing the configuration object.
418     * (Although, behind the scenes a builder is created).
419     *
420     * @param path the path to the file to be loaded
421     * @return a {@code XMLConfiguration} object initialized from this file
422     * @throws ConfigurationException if an error occurred when loading the
423     *         configuration
424     */
425    public XMLConfiguration xml(final String path) throws ConfigurationException
426    {
427        return xmlBuilder(path).getConfiguration();
428    }
429
430    /**
431     * Creates a builder for a {@code INIConfiguration} and initializes it with
432     * the given file to be loaded.
433     *
434     * @param file the file to be loaded
435     * @return the newly created {@code FileBasedConfigurationBuilder}
436     */
437    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final File file)
438    {
439        return fileBasedBuilder(INIConfiguration.class, file);
440    }
441
442    /**
443     * Creates a builder for a {@code INIConfiguration} and initializes it with
444     * the given URL to be loaded.
445     *
446     * @param url the URL to be loaded
447     * @return the newly created {@code FileBasedConfigurationBuilder}
448     */
449    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(final URL url)
450    {
451        return fileBasedBuilder(INIConfiguration.class, url);
452    }
453
454    /**
455     * Creates a builder for a {@code INIConfiguration} and initializes it with
456     * the file file identified by the given path.
457     *
458     * @param path the path to the file to be loaded
459     * @return the newly created {@code FileBasedConfigurationBuilder}
460     */
461    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(
462            final String path)
463    {
464        return fileBasedBuilder(INIConfiguration.class, path);
465    }
466
467    /**
468     * Creates a {@code INIConfiguration} instance from the content of the given
469     * file. This is a convenience method which can be used if no builder is
470     * needed for managing the configuration object. (Although, behind the
471     * scenes a builder is created).
472     *
473     * @param file the file to be loaded
474     * @return a {@code INIConfiguration} object initialized from this file
475     * @throws ConfigurationException if an error occurred when loading the
476     *         configuration
477     */
478    public INIConfiguration ini(final File file) throws ConfigurationException
479    {
480        return iniBuilder(file).getConfiguration();
481    }
482
483    /**
484     * Creates a {@code INIConfiguration} instance from the content of the given
485     * URL. This is a convenience method which can be used if no builder is
486     * needed for managing the configuration object. (Although, behind the
487     * scenes a builder is created).
488     *
489     * @param url the URL to be loaded
490     * @return a {@code INIConfiguration} object initialized from this file
491     * @throws ConfigurationException if an error occurred when loading the
492     *         configuration
493     */
494    public INIConfiguration ini(final URL url) throws ConfigurationException
495    {
496        return iniBuilder(url).getConfiguration();
497    }
498
499    /**
500     * Creates a {@code INIConfiguration} instance from the content of the file
501     * identified by the given path. This is a convenience method which can be
502     * used if no builder is needed for managing the configuration object.
503     * (Although, behind the scenes a builder is created).
504     *
505     * @param path the path to the file to be loaded
506     * @return a {@code INIConfiguration} object initialized from this file
507     * @throws ConfigurationException if an error occurred when loading the
508     *         configuration
509     */
510    public INIConfiguration ini(final String path) throws ConfigurationException
511    {
512        return iniBuilder(path).getConfiguration();
513    }
514
515    /**
516     * Creates a builder for a {@code CombinedConfiguration} and initializes it
517     * with the given file to be loaded.
518     *
519     * @param file the file to be loaded
520     * @return the newly created {@code CombinedConfigurationBuilder}
521     */
522    public CombinedConfigurationBuilder combinedBuilder(final File file)
523    {
524        return new CombinedConfigurationBuilder().configure(fileParams(file));
525    }
526
527    /**
528     * Creates a builder for a {@code CombinedConfiguration} and initializes it
529     * with the given URL to be loaded.
530     *
531     * @param url the URL to be loaded
532     * @return the newly created {@code CombinedConfigurationBuilder}
533     */
534    public CombinedConfigurationBuilder combinedBuilder(final URL url)
535    {
536        return new CombinedConfigurationBuilder().configure(fileParams(url));
537    }
538
539    /**
540     * Creates a builder for a {@code CombinedConfiguration} and initializes it
541     * with the given path to the file to be loaded.
542     *
543     * @param path the path to the file to be loaded
544     * @return the newly created {@code CombinedConfigurationBuilder}
545     */
546    public CombinedConfigurationBuilder combinedBuilder(final String path)
547    {
548        return new CombinedConfigurationBuilder().configure(fileParams(path));
549    }
550
551    /**
552     * Creates a {@code CombinedConfiguration} instance from the content of the
553     * given file. This is a convenience method which can be used if no builder
554     * is needed for managing the configuration object. (Although, behind the
555     * scenes a builder is created).
556     *
557     * @param file the file to be loaded
558     * @return a {@code CombinedConfiguration} object initialized from this file
559     * @throws ConfigurationException if an error occurred when loading the
560     *         configuration
561     */
562    public CombinedConfiguration combined(final File file)
563            throws ConfigurationException
564    {
565        return combinedBuilder(file).getConfiguration();
566    }
567
568    /**
569     * Creates a {@code CombinedConfiguration} instance from the content of the
570     * given URL. This is a convenience method which can be used if no builder
571     * is needed for managing the configuration object. (Although, behind the
572     * scenes a builder is created).
573     *
574     * @param url the URL to be loaded
575     * @return a {@code CombinedConfiguration} object initialized from this URL
576     * @throws ConfigurationException if an error occurred when loading the
577     *         configuration
578     */
579    public CombinedConfiguration combined(final URL url)
580            throws ConfigurationException
581    {
582        return combinedBuilder(url).getConfiguration();
583    }
584
585    /**
586     * Creates a {@code CombinedConfiguration} instance from the content of the
587     * file identified by the given path. This is a convenience method which can
588     * be used if no builder is needed for managing the configuration object.
589     * (Although, behind the scenes a builder is created).
590     *
591     * @param path the path to the file to be loaded
592     * @return a {@code CombinedConfiguration} object initialized from this URL
593     * @throws ConfigurationException if an error occurred when loading the
594     *         configuration
595     */
596    public CombinedConfiguration combined(final String path)
597            throws ConfigurationException
598    {
599        return combinedBuilder(path).getConfiguration();
600    }
601
602    /**
603     * Creates a configured builder for a file-based configuration of the
604     * specified type.
605     *
606     * @param configClass the configuration class
607     * @param <T> the type of the configuration to be constructed
608     * @return the newly created builder
609     * @since 2.6
610     */
611    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(
612            final Class<T> configClass)
613    {
614        return new FileBasedConfigurationBuilder<>(configClass);
615    }
616
617    /**
618     * Creates a configured builder for a file-based configuration of the
619     * specified type.
620     *
621     * @param configClass the configuration class
622     * @param params the parameters object for configuring the builder
623     * @param <T> the type of the configuration to be constructed
624     * @return the newly created builder
625     */
626    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(
627            final Class<T> configClass, final FileBasedBuilderParameters params)
628    {
629        return createFileBasedBuilder(configClass).configure(params);
630    }
631
632    /**
633     * Convenience method for creating a parameters object for a file-based
634     * configuration.
635     *
636     * @return the newly created parameters object
637     */
638    private FileBasedBuilderParameters fileParams()
639    {
640        return getParameters().fileBased();
641    }
642
643    /**
644     * Convenience method for creating a file-based parameters object
645     * initialized with the given file.
646     *
647     * @param file the file to be loaded
648     * @return the initialized parameters object
649     */
650    private FileBasedBuilderParameters fileParams(final File file)
651    {
652        return fileParams().setFile(file);
653    }
654
655    /**
656     * Convenience method for creating a file-based parameters object
657     * initialized with the given file.
658     *
659     * @param url the URL to be loaded
660     * @return the initialized parameters object
661     */
662    private FileBasedBuilderParameters fileParams(final URL url)
663    {
664        return fileParams().setURL(url);
665    }
666
667    /**
668     * Convenience method for creating a file-based parameters object
669     * initialized with the given file path.
670     *
671     * @param path the path to the file to be loaded
672     * @return the initialized parameters object
673     */
674    private FileBasedBuilderParameters fileParams(final String path)
675    {
676        return fileParams().setFileName(path);
677    }
678
679}