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 * @version $Id: CopyObjectDefaultHandler.java 1842194 2018-09-27 22:24:23Z ggregory $
047 * @since 2.0
048 */
049public class CopyObjectDefaultHandler implements
050        DefaultParametersHandler<Object>
051{
052    /** The source object with the properties to be initialized. */
053    private final BuilderParameters source;
054
055    /**
056     * Creates a new instance of {@code CopyObjectDefaultHandler} and
057     * initializes it with the specified source object. The properties defined
058     * by the source object are copied onto the objects to be initialized.
059     *
060     * @param src the source object (must not be <b>null</b>)
061     * @throws IllegalArgumentException if the source object is <b>null</b>
062     */
063    public CopyObjectDefaultHandler(final BuilderParameters src)
064    {
065        if (src == null)
066        {
067            throw new IllegalArgumentException(
068                    "Source object must not be null!");
069        }
070        source = src;
071    }
072
073    /**
074     * Returns the source object of this handler. This is the object whose
075     * properties are copied on the objects to be initialized.
076     *
077     * @return the source object of this {@code CopyObjectDefaultHandler}
078     */
079    public BuilderParameters getSource()
080    {
081        return source;
082    }
083
084    /**
085     * {@inheritDoc} This implementation uses
086     * {@code PropertyUtils.copyProperties()} to copy all defined properties
087     * from the source object onto the passed in parameters object. Both the map
088     * with properties (obtained via the {@code getParameters()} method of the
089     * source parameters object) and other properties of the source object are
090     * copied.
091     *
092     * @throws ConfigurationRuntimeException if an exception occurs
093     * @see BuilderParameters#getParameters()
094     */
095    @Override
096    public void initializeDefaults(final Object parameters)
097    {
098        try
099        {
100            BeanHelper.copyProperties(parameters, getSource()
101                    .getParameters());
102            BeanHelper.copyProperties(parameters, getSource());
103        }
104        catch (final Exception e)
105        {
106            // Handle all reflection-related exceptions the same way
107            throw new ConfigurationRuntimeException(e);
108        }
109    }
110}