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;
018
019import java.util.Collection;
020import java.util.Collections;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.Map;
024
025import org.apache.commons.configuration2.ConfigurationUtils;
026import org.apache.commons.configuration2.ImmutableConfiguration;
027import org.apache.commons.configuration2.Initializable;
028import org.apache.commons.configuration2.beanutils.BeanDeclaration;
029import org.apache.commons.configuration2.beanutils.BeanHelper;
030import org.apache.commons.configuration2.beanutils.ConstructorArg;
031import org.apache.commons.configuration2.event.Event;
032import org.apache.commons.configuration2.event.EventListener;
033import org.apache.commons.configuration2.event.EventListenerList;
034import org.apache.commons.configuration2.event.EventListenerRegistrationData;
035import org.apache.commons.configuration2.event.EventSource;
036import org.apache.commons.configuration2.event.EventType;
037import org.apache.commons.configuration2.ex.ConfigurationException;
038import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
039import org.apache.commons.configuration2.reloading.ReloadingController;
040
041/**
042 * <p>
043 * An implementation of the {@code ConfigurationBuilder} interface which is able
044 * to create different concrete {@code ImmutableConfiguration} implementations based on
045 * reflection.
046 * </p>
047 * <p>
048 * When constructing an instance of this class the concrete
049 * {@code ImmutableConfiguration} implementation class has to be provided. Then
050 * properties for the new {@code ImmutableConfiguration} instance can be set. The first
051 * call to {@code getConfiguration()} creates and initializes the new
052 * {@code ImmutableConfiguration} object. It is cached and returned by subsequent calls.
053 * This cache - and also the initialization properties set so far - can be
054 * flushed by calling one of the {@code reset()} methods. That way other
055 * {@code ImmutableConfiguration} instances with different properties can be created.
056 * </p>
057 * <p>
058 * If the newly created {@code ImmutableConfiguration} object implements the
059 * {@code Initializable} interface, its {@code initialize()} method is called
060 * after all initialization properties have been set. This way a concrete
061 * implementation class can perform arbitrary initialization steps.
062 * </p>
063 * <p>
064 * There are multiple options for setting up a {@code BasicConfigurationBuilder}
065 * instance:
066 * </p>
067 * <ul>
068 * <li>All initialization properties can be set in one or multiple calls of the
069 * {@code configure()} method. In each call an arbitrary number of
070 * {@link BuilderParameters} objects can be passed. The API allows method
071 * chaining and is intended to be used from Java code.</li>
072 * <li>If builder instances are created by other means - e.g. using a dependency
073 * injection framework -, the fluent API approach may not be suitable. For those
074 * use cases it is also possible to pass in all initialization parameters as a
075 * map. The keys of the map have to match initialization properties of the
076 * {@code ImmutableConfiguration} object to be created, the values are the corresponding
077 * property values. For instance, the key <em>throwExceptionOnMissing</em> in
078 * the map will cause the method {@code setThrowExceptionOnMissing()} on the
079 * {@code ImmutableConfiguration} object to be called with the corresponding value as
080 * parameter.</li>
081 * </ul>
082 * <p>
083 * A builder instance can be constructed with an <em>allowFailOnInit</em>
084 * flag. If set to <strong>true</strong>, exceptions during initialization
085 * of the configuration are ignored; in such a case an empty configuration
086 * object is returned. A use case for this flag is a scenario in which a
087 * configuration is optional and created on demand the first time configuration
088 * data is to be stored. Consider an application that stores user-specific
089 * configuration data in the user's home directory: When started for the first
090 * time by a new user there is no configuration file; so it makes sense to
091 * start with an empty configuration object. On application exit, settings
092 * can be stored in this object and written to the associated file. Then they
093 * are available on next application start.
094 * </p>
095 * <p>
096 * This class is thread-safe. Multiple threads can modify initialization
097 * properties and call {@code getConfiguration()}. However, the intended use
098 * case is that the builder is configured by a single thread first. Then
099 * {@code getConfiguration()} can be called concurrently, and it is guaranteed
100 * that always the same {@code ImmutableConfiguration} instance is returned until the
101 * builder is reset.
102 * </p>
103 *
104 * @since 2.0
105 * @param <T> the concrete type of {@code ImmutableConfiguration} objects created by this
106 *        builder
107 */
108public class BasicConfigurationBuilder<T extends ImmutableConfiguration> implements
109        ConfigurationBuilder<T>
110{
111    /** The class of the objects produced by this builder instance. */
112    private final Class<? extends T> resultClass;
113
114    /** An object managing the event listeners registered at this builder. */
115    private final EventListenerList eventListeners;
116
117    /** A flag whether exceptions on initializing configurations are allowed. */
118    private final boolean allowFailOnInit;
119
120    /** The map with current initialization parameters. */
121    private Map<String, Object> parameters;
122
123    /** The current bean declaration. */
124    private BeanDeclaration resultDeclaration;
125
126    /** The result object of this builder. */
127    private volatile T result;
128
129    /**
130     * Creates a new instance of {@code BasicConfigurationBuilder} and
131     * initializes it with the given result class. No initialization properties
132     * are set.
133     *
134     * @param resCls the result class (must not be <b>null</b>)
135     * @throws IllegalArgumentException if the result class is <b>null</b>
136     */
137    public BasicConfigurationBuilder(final Class<? extends T> resCls)
138    {
139        this(resCls, null);
140    }
141
142    /**
143     * Creates a new instance of {@code BasicConfigurationBuilder} and
144     * initializes it with the given result class and an initial set of builder
145     * parameters. The <em>allowFailOnInit</em> flag is set to
146     * <strong>false</strong>.
147     *
148     * @param resCls the result class (must not be <b>null</b>)
149     * @param params a map with initialization parameters
150     * @throws IllegalArgumentException if the result class is <b>null</b>
151     */
152    public BasicConfigurationBuilder(final Class<? extends T> resCls, final Map<String, Object> params)
153    {
154        this(resCls, params, false);
155    }
156
157    /**
158     * Creates a new instance of {@code BasicConfigurationBuilder} and
159     * initializes it with the given result class, an initial set of builder
160     * parameters, and the <em>allowFailOnInit</em> flag. The map with
161     * parameters may be <b>null</b>, in this case no initialization parameters
162     * are set.
163     *
164     * @param resCls the result class (must not be <b>null</b>)
165     * @param params a map with initialization parameters
166     * @param allowFailOnInit a flag whether exceptions on initializing a newly
167     *        created {@code ImmutableConfiguration} object are allowed
168     * @throws IllegalArgumentException if the result class is <b>null</b>
169     */
170    public BasicConfigurationBuilder(final Class<? extends T> resCls,
171            final Map<String, Object> params, final boolean allowFailOnInit)
172    {
173        if (resCls == null)
174        {
175            throw new IllegalArgumentException("Result class must not be null!");
176        }
177
178        resultClass = resCls;
179        this.allowFailOnInit = allowFailOnInit;
180        eventListeners = new EventListenerList();
181        updateParameters(params);
182    }
183
184    /**
185     * Returns the result class of this builder. The objects produced by this
186     * builder have the class returned here.
187     *
188     * @return the result class of this builder
189     */
190    public Class<? extends T> getResultClass()
191    {
192        return resultClass;
193    }
194
195    /**
196     * Returns the <em>allowFailOnInit</em> flag. See the header comment for
197     * information about this flag.
198     *
199     * @return the <em>allowFailOnInit</em> flag
200     */
201    public boolean isAllowFailOnInit()
202    {
203        return allowFailOnInit;
204    }
205
206    /**
207     * Sets the initialization parameters of this builder. Already existing
208     * parameters are replaced by the content of the given map.
209     *
210     * @param params the new initialization parameters of this builder; can be
211     *        <b>null</b>, then all initialization parameters are removed
212     * @return a reference to this builder for method chaining
213     */
214    public synchronized BasicConfigurationBuilder<T> setParameters(
215            final Map<String, Object> params)
216    {
217        updateParameters(params);
218        return this;
219    }
220
221    /**
222     * Adds the content of the given map to the already existing initialization
223     * parameters.
224     *
225     * @param params the map with additional initialization parameters; may be
226     *        <b>null</b>, then this call has no effect
227     * @return a reference to this builder for method chaining
228     */
229    public synchronized BasicConfigurationBuilder<T> addParameters(
230            final Map<String, Object> params)
231    {
232        final Map<String, Object> newParams =
233                new HashMap<>(getParameters());
234        if (params != null)
235        {
236            newParams.putAll(params);
237        }
238        updateParameters(newParams);
239        return this;
240    }
241
242    /**
243     * Appends the content of the specified {@code BuilderParameters} objects to
244     * the current initialization parameters. Calling this method multiple times
245     * will create a union of the parameters provided.
246     *
247     * @param params an arbitrary number of objects with builder parameters
248     * @return a reference to this builder for method chaining
249     * @throws NullPointerException if a <b>null</b> array is passed
250     */
251    public BasicConfigurationBuilder<T> configure(final BuilderParameters... params)
252    {
253        final Map<String, Object> newParams = new HashMap<>();
254        for (final BuilderParameters p : params)
255        {
256            newParams.putAll(p.getParameters());
257            handleEventListenerProviders(p);
258        }
259
260        return setParameters(newParams);
261    }
262
263    /**
264     * {@inheritDoc} This implementation creates the result configuration on
265     * first access. Later invocations return the same object until this builder
266     * is reset. The double-check idiom for lazy initialization is used (Bloch,
267     * Effective Java, item 71).
268     */
269    @Override
270    public T getConfiguration() throws ConfigurationException
271    {
272        fireBuilderEvent(new ConfigurationBuilderEvent(this,
273                ConfigurationBuilderEvent.CONFIGURATION_REQUEST));
274
275        T resObj = result;
276        boolean created = false;
277        if (resObj == null)
278        {
279            synchronized (this)
280            {
281                resObj = result;
282                if (resObj == null)
283                {
284                    result = resObj = createResult();
285                    created = true;
286                }
287            }
288        }
289
290        if (created)
291        {
292            fireBuilderEvent(new ConfigurationBuilderResultCreatedEvent(this,
293                    ConfigurationBuilderResultCreatedEvent.RESULT_CREATED,
294                    resObj));
295        }
296        return resObj;
297    }
298
299    /**
300     * {@inheritDoc} This implementation also takes care that the event listener
301     * is added to the managed configuration object.
302     *
303     * @throws IllegalArgumentException if the event type or the listener is
304     *         <b>null</b>
305     */
306    @Override
307    public <E extends Event> void addEventListener(
308            final EventType<E> eventType, final EventListener<? super E> listener)
309    {
310        installEventListener(eventType, listener);
311    }
312
313    /**
314     * {@inheritDoc} This implementation also takes care that the event listener
315     * is removed from the managed configuration object.
316     */
317    @Override
318    public <E extends Event> boolean removeEventListener(
319            final EventType<E> eventType, final EventListener<? super E> listener)
320    {
321        fetchEventSource().removeEventListener(eventType, listener);
322        return eventListeners.removeEventListener(eventType, listener);
323    }
324
325    /**
326     * Clears an existing result object. An invocation of this method causes a
327     * new {@code ImmutableConfiguration} object to be created the next time
328     * {@link #getConfiguration()} is called.
329     */
330    public void resetResult()
331    {
332        T oldResult;
333        synchronized (this)
334        {
335            oldResult = result;
336            result = null;
337            resultDeclaration = null;
338        }
339
340        if (oldResult != null)
341        {
342            removeEventListeners(oldResult);
343        }
344        fireBuilderEvent(new ConfigurationBuilderEvent(this,
345                ConfigurationBuilderEvent.RESET));
346    }
347
348    /**
349     * Removes all initialization parameters of this builder. This method can be
350     * called if this builder is to be reused for creating result objects with a
351     * different configuration.
352     */
353    public void resetParameters()
354    {
355        setParameters(null);
356    }
357
358    /**
359     * Resets this builder. This is a convenience method which combines calls to
360     * {@link #resetResult()} and {@link #resetParameters()}.
361     */
362    public synchronized void reset()
363    {
364        resetParameters();
365        resetResult();
366    }
367
368    /**
369     * Connects this builder with a {@code ReloadingController}. With this
370     * method support for reloading can be added to an arbitrary builder object.
371     * Event listeners are registered at the reloading controller and this
372     * builder with connect both objects:
373     * <ul>
374     * <li>When the reloading controller detects that a reload is required, the
375     * builder's {@link #resetResult()} method is called; so the managed result
376     * object is invalidated.</li>
377     * <li>When a new result object has been created the controller's reloading
378     * state is reset, so that new changes can be detected again.</li>
379     * </ul>
380     *
381     * @param controller the {@code ReloadingController} to connect to (must not
382     *        be <b>null</b>)
383     * @throws IllegalArgumentException if the controller is <b>null</b>
384     */
385    public final void connectToReloadingController(
386            final ReloadingController controller)
387    {
388        if (controller == null)
389        {
390            throw new IllegalArgumentException(
391                    "ReloadingController must not be null!");
392        }
393        ReloadingBuilderSupportListener.connect(this, controller);
394    }
395
396    /**
397     * Creates a new, initialized result object. This method is called by
398     * {@code getConfiguration()} if no valid result object exists. This base
399     * implementation performs two steps:
400     * <ul>
401     * <li>{@code createResultInstance()} is called to create a new,
402     * uninitialized result object.</li>
403     * <li>{@code initResultInstance()} is called to process all initialization
404     * parameters.</li>
405     * </ul>
406     * It also evaluates the <em>allowFailOnInit</em> flag, i.e. if
407     * initialization causes an exception and this flag is set, the exception is
408     * ignored, and the newly created, uninitialized configuration is returned.
409     * Note that this method is called in a synchronized block.
410     *
411     * @return the newly created result object
412     * @throws ConfigurationException if an error occurs
413     */
414    protected T createResult() throws ConfigurationException
415    {
416        final T resObj = createResultInstance();
417
418        try
419        {
420            initResultInstance(resObj);
421        }
422        catch (final ConfigurationException cex)
423        {
424            if (!isAllowFailOnInit())
425            {
426                throw cex;
427            }
428        }
429
430        return resObj;
431    }
432
433    /**
434     * Creates the new, uninitialized result object. This is the first step of
435     * the process of producing a result object for this builder. This
436     * implementation uses the {@link BeanHelper} class to create a new object
437     * based on the {@link BeanDeclaration} returned by
438     * {@link #getResultDeclaration()}. Note: This method is invoked in a
439     * synchronized block.
440     *
441     * @return the newly created, yet uninitialized result object
442     * @throws ConfigurationException if an exception occurs
443     */
444    protected T createResultInstance() throws ConfigurationException
445    {
446        final Object bean = fetchBeanHelper().createBean(getResultDeclaration());
447        checkResultInstance(bean);
448        return getResultClass().cast(bean);
449    }
450
451    /**
452     * Initializes a newly created result object. This is the second step of the
453     * process of producing a result object for this builder. This
454     * implementation uses the {@link BeanHelper} class to initialize the
455     * object's property based on the {@link BeanDeclaration} returned by
456     * {@link #getResultDeclaration()}. Note: This method is invoked in a
457     * synchronized block. This is required because internal state is accessed.
458     * Sub classes must not call this method without proper synchronization.
459     *
460     * @param obj the object to be initialized
461     * @throws ConfigurationException if an error occurs
462     */
463    protected void initResultInstance(final T obj) throws ConfigurationException
464    {
465        fetchBeanHelper().initBean(obj, getResultDeclaration());
466        registerEventListeners(obj);
467        handleInitializable(obj);
468    }
469
470    /**
471     * Returns the {@code BeanDeclaration} that is used to create and initialize
472     * result objects. The declaration is created on first access (by invoking
473     * {@link #createResultDeclaration(Map)}) based on the current
474     * initialization parameters.
475     *
476     * @return the {@code BeanDeclaration} for dynamically creating a result
477     *         object
478     * @throws ConfigurationException if an error occurs
479     */
480    protected final synchronized BeanDeclaration getResultDeclaration()
481            throws ConfigurationException
482    {
483        if (resultDeclaration == null)
484        {
485            resultDeclaration = createResultDeclaration(getFilteredParameters());
486        }
487        return resultDeclaration;
488    }
489
490    /**
491     * Returns a (unmodifiable) map with the current initialization parameters
492     * set for this builder. The map is populated with the parameters set using
493     * the various configuration options.
494     *
495     * @return a map with the current set of initialization parameters
496     */
497    protected final synchronized Map<String, Object> getParameters()
498    {
499        if (parameters != null)
500        {
501            return parameters;
502        }
503        return Collections.emptyMap();
504    }
505
506    /**
507     * Obtains the {@code BeanHelper} object to be used when dealing with bean
508     * declarations. This method checks whether this builder was configured with
509     * a specific {@code BeanHelper} instance. If so, this instance is used.
510     * Otherwise, the default {@code BeanHelper} is returned.
511     *
512     * @return the {@code BeanHelper} to be used
513     */
514    protected final BeanHelper fetchBeanHelper()
515    {
516        final BeanHelper helper =
517                BasicBuilderParameters.fetchBeanHelper(getParameters());
518        return helper != null ? helper : BeanHelper.INSTANCE;
519    }
520
521    /**
522     * Creates a new {@code BeanDeclaration} which is used for creating new
523     * result objects dynamically. This implementation creates a specialized
524     * {@code BeanDeclaration} object that is initialized from the given map of
525     * initialization parameters. The {@code BeanDeclaration} must be
526     * initialized with the result class of this builder, otherwise exceptions
527     * will be thrown when the result object is created. Note: This method is
528     * invoked in a synchronized block.
529     *
530     * @param params a snapshot of the current initialization parameters
531     * @return the {@code BeanDeclaration} for creating result objects
532     * @throws ConfigurationException if an error occurs
533     */
534    protected BeanDeclaration createResultDeclaration(
535            final Map<String, Object> params) throws ConfigurationException
536    {
537        return new BeanDeclaration()
538        {
539            @Override
540            public Map<String, Object> getNestedBeanDeclarations()
541            {
542                // no nested beans
543                return Collections.emptyMap();
544            }
545
546            @Override
547            public Collection<ConstructorArg> getConstructorArgs()
548            {
549                // no constructor arguments
550                return Collections.emptySet();
551            }
552
553            @Override
554            public Map<String, Object> getBeanProperties()
555            {
556                // the properties are equivalent to the parameters
557                return params;
558            }
559
560            @Override
561            public Object getBeanFactoryParameter()
562            {
563                return null;
564            }
565
566            @Override
567            public String getBeanFactoryName()
568            {
569                return null;
570            }
571
572            @Override
573            public String getBeanClassName()
574            {
575                return getResultClass().getName();
576            }
577        };
578    }
579
580    /**
581     * Copies all {@code EventListener} objects registered at this builder to
582     * the specified target configuration builder. This method is intended to be
583     * used by derived classes which support inheritance of their properties to
584     * other builder objects.
585     *
586     * @param target the target configuration builder (must not be <b>null</b>)
587     * @throws NullPointerException if the target builder is <b>null</b>
588     */
589    protected synchronized void copyEventListeners(
590            final BasicConfigurationBuilder<?> target)
591    {
592        copyEventListeners(target, eventListeners);
593    }
594
595    /**
596     * Copies all event listeners in the specified list to the specified target
597     * configuration builder. This method is intended to be used by derived
598     * classes which have to deal with managed configuration builders that need
599     * to be initialized with event listeners.
600     *
601     * @param target the target configuration builder (must not be <b>null</b>)
602     * @param listeners the event listeners to be copied over
603     * @throws NullPointerException if the target builder is <b>null</b>
604     */
605    protected void copyEventListeners(final BasicConfigurationBuilder<?> target,
606            final EventListenerList listeners)
607    {
608        target.eventListeners.addAll(listeners);
609    }
610
611    /**
612     * Adds the specified event listener to this object. This method is called
613     * by {@code addEventListener()}, it does the actual listener registration.
614     * Because it is final it can be called by sub classes in the constructor if
615     * there is already the need to register an event listener.
616     *
617     * @param eventType the event type object
618     * @param listener the listener to be registered
619     * @param <E> the event type
620     */
621    protected final <E extends Event> void installEventListener(
622            final EventType<E> eventType, final EventListener<? super E> listener)
623    {
624        fetchEventSource().addEventListener(eventType, listener);
625        eventListeners.addEventListener(eventType, listener);
626    }
627
628    /**
629     * Sends the specified builder event to all registered listeners.
630     *
631     * @param event the event to be fired
632     */
633    protected void fireBuilderEvent(final ConfigurationBuilderEvent event)
634    {
635        eventListeners.fire(event);
636    }
637
638    /**
639     * Replaces the current map with parameters by a new one.
640     *
641     * @param newParams the map with new parameters (may be <b>null</b>)
642     */
643    private void updateParameters(final Map<String, Object> newParams)
644    {
645        final Map<String, Object> map = new HashMap<>();
646        if (newParams != null)
647        {
648            map.putAll(newParams);
649        }
650        parameters = Collections.unmodifiableMap(map);
651    }
652
653    /**
654     * Registers the available event listeners at the given object. This method
655     * is called for each result object created by the builder.
656     *
657     * @param obj the object to initialize
658     */
659    private void registerEventListeners(final T obj)
660    {
661        final EventSource evSrc = ConfigurationUtils.asEventSource(obj, true);
662        for (final EventListenerRegistrationData<?> regData : eventListeners
663                .getRegistrations())
664        {
665            registerListener(evSrc, regData);
666        }
667    }
668
669    /**
670     * Removes all available event listeners from the given result object. This
671     * method is called when the result of this builder is reset. Then the old
672     * managed configuration should no longer generate events.
673     *
674     * @param obj the affected result object
675     */
676    private void removeEventListeners(final T obj)
677    {
678        final EventSource evSrc = ConfigurationUtils.asEventSource(obj, true);
679        for (final EventListenerRegistrationData<?> regData : eventListeners
680                .getRegistrations())
681        {
682            removeListener(evSrc, regData);
683        }
684    }
685
686    /**
687     * Returns an {@code EventSource} for the current result object. If there is
688     * no current result or if it does not extend {@code EventSource}, a dummy
689     * event source is returned.
690     *
691     * @return the {@code EventSource} for the current result object
692     */
693    private EventSource fetchEventSource()
694    {
695        return ConfigurationUtils.asEventSource(result, true);
696    }
697
698    /**
699     * Checks whether the specified parameters object implements the
700     * {@code EventListenerProvider} interface. If so, the event listeners it
701     * provides are added to this builder.
702     *
703     * @param params the parameters object
704     */
705    private void handleEventListenerProviders(final BuilderParameters params)
706    {
707        if (params instanceof EventListenerProvider)
708        {
709            eventListeners.addAll(((EventListenerProvider) params)
710                    .getListeners());
711        }
712    }
713
714    /**
715     * Checks whether the class of the result configuration is compatible with
716     * this builder's result class. This is done to ensure that only objects of
717     * the expected result class are created.
718     *
719     * @param inst the result instance to be checked
720     * @throws ConfigurationRuntimeException if an invalid result class is
721     *         detected
722     */
723    private void checkResultInstance(final Object inst)
724    {
725        if (!getResultClass().isInstance(inst))
726        {
727            throw new ConfigurationRuntimeException(
728                    "Incompatible result object: " + inst);
729        }
730    }
731
732    /**
733     * Returns a map with initialization parameters where all parameters
734     * starting with the reserved prefix have been filtered out.
735     *
736     * @return the filtered parameters map
737     */
738    private Map<String, Object> getFilteredParameters()
739    {
740        final Map<String, Object> filteredMap =
741                new HashMap<>(getParameters());
742        for (final Iterator<String> it = filteredMap.keySet().iterator(); it
743                .hasNext();)
744        {
745            final String key = it.next();
746            if (key.startsWith(BuilderParameters.RESERVED_PARAMETER_PREFIX))
747            {
748                it.remove();
749            }
750        }
751        return filteredMap;
752    }
753
754    /**
755     * Performs special initialization of the result object. This method is
756     * called after parameters have been set on a newly created result instance.
757     * If supported by the result class, the {@code initialize()} method is now
758     * called.
759     *
760     * @param obj the newly created result object
761     */
762    private void handleInitializable(final T obj)
763    {
764        if (obj instanceof Initializable)
765        {
766            ((Initializable) obj).initialize();
767        }
768    }
769
770    /**
771     * Registers an event listener at an event source object.
772     *
773     * @param evSrc the event source
774     * @param regData the registration data object
775     * @param <E> the type of the event listener
776     */
777    private static <E extends Event> void registerListener(final EventSource evSrc,
778            final EventListenerRegistrationData<E> regData)
779    {
780        evSrc.addEventListener(regData.getEventType(), regData.getListener());
781    }
782
783    /**
784     * Removes an event listener from an event source object.
785     *
786     * @param evSrc the event source
787     * @param regData the registration data object
788     * @param <E> the type of the event listener
789     */
790    private static <E extends Event> void removeListener(final EventSource evSrc,
791            final EventListenerRegistrationData<E> regData)
792    {
793        evSrc.removeEventListener(regData.getEventType(), regData.getListener());
794    }
795}