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 org.apache.commons.configuration2.beanutils.BeanHelper;
020import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
021
022/**
023 * <p>
024 * A specialized implementation of {@code DefaultParametersHandler} that copies
025 * the properties of a {@link BuilderParameters} object (passed at construction
026 * time) onto the object to be initialized.
027 * </p>
028 * <p>
029 * Using this handler implementation makes specifying default values pretty
030 * straight-forward: Just create a corresponding parameters object, initialize
031 * it as desired, and pass it to this class. When invoked the handler uses
032 * functionality from <em>Commons BeanUtils</em> to copy all properties defined
033 * in the associated parameters object onto the target object. This is based on
034 * reflection. Properties not available for the target object are silently
035 * ignored. If an exception occurs during the copy operation, it is re-thrown as
036 * a runtime exception.
037 * </p>
038 * <p>
039 * Note that there is no default way to create a defensive copy of the passed in
040 * parameters object; therefore, the reference is stored. This makes it possible
041 * to change the parameters object later on, and the changes will be effective
042 * when initializing objects afterwards. Client code should not rely on this
043 * feature.
044 * </p>
045 *
046 * @since 2.0
047 */
048public class CopyObjectDefaultHandler implements
049        DefaultParametersHandler<Object>
050{
051    /** The source object with the properties to be initialized. */
052    private final BuilderParameters source;
053
054    /**
055     * Creates a new instance of {@code CopyObjectDefaultHandler} and
056     * initializes it with the specified source object. The properties defined
057     * by the source object are copied onto the objects to be initialized.
058     *
059     * @param src the source object (must not be <b>null</b>)
060     * @throws IllegalArgumentException if the source object is <b>null</b>
061     */
062    public CopyObjectDefaultHandler(final BuilderParameters src)
063    {
064        if (src == null)
065        {
066            throw new IllegalArgumentException(
067                    "Source object must not be null!");
068        }
069        source = src;
070    }
071
072    /**
073     * Returns the source object of this handler. This is the object whose
074     * properties are copied on the objects to be initialized.
075     *
076     * @return the source object of this {@code CopyObjectDefaultHandler}
077     */
078    public BuilderParameters getSource()
079    {
080        return source;
081    }
082
083    /**
084     * {@inheritDoc} This implementation uses
085     * {@code PropertyUtils.copyProperties()} to copy all defined properties
086     * from the source object onto the passed in parameters object. Both the map
087     * with properties (obtained via the {@code getParameters()} method of the
088     * source parameters object) and other properties of the source object are
089     * copied.
090     *
091     * @throws ConfigurationRuntimeException if an exception occurs
092     * @see BuilderParameters#getParameters()
093     */
094    @Override
095    public void initializeDefaults(final Object parameters)
096    {
097        try
098        {
099            BeanHelper.copyProperties(parameters, getSource()
100                    .getParameters());
101            BeanHelper.copyProperties(parameters, getSource());
102        }
103        catch (final Exception e)
104        {
105            // Handle all reflection-related exceptions the same way
106            throw new ConfigurationRuntimeException(e);
107        }
108    }
109}