    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.tree;
    018
    019import java.util.ArrayList;
    020import java.util.Collection;
    021import java.util.Collections;
    022import java.util.HashMap;
    023import java.util.Map;
    024
    025/**
    026 * <p>
    027 * A simple data class used by node models to store parameters of an update
    028 * operation.
    029 * </p>
    030 * <p>
    031 * The {@code Configuration} interface provides a method for setting the value
    032 * of a given key. The passed in value can be a single object or a collection of
    033 * values. This makes an update operation rather complicated because a
    034 * collection of query results selected by the passed in key has to be matched
    035 * to another collection of values - and both collections can have different
    036 * sizes. Therefore, an update operation may involve changing of existing nodes,
    037 * adding new nodes (if there are more values than currently existing nodes),
    038 * and removing nodes (if there are more existing nodes than provided values).
    039 * This class collects all this information making it possible to actually
    040 * perform the update based on a passed in instance.
    041 * </p>
    042 *
    043 * @version $Id: NodeUpdateData.java 1842194 2018-09-27 22:24:23Z ggregory $
    044 * @since 2.0
    045 * @param <T> the type of nodes involved in this update operation
    046 */
    047public class NodeUpdateData<T>
    048{
    049    /** The map with the query results whose value has to be changed. */
    050    private final Map<QueryResult<T>, Object> changedValues;
    051
    052    /** The collection with the new values to be added. */
    053    private final Collection<Object> newValues;
    054
    055    /** The collection with query results about the nodes to be removed. */
    056    private final Collection<QueryResult<T>> removedNodes;
    057
    058    /** The key of the current update operation. */
    059    private final String key;
    060
    061    /**
    062     * Creates a new instance of {@code NodeUpdateData} and initializes all its
    063     * properties. All passed in collections are optional and can be
    064     * <b>null</b>.
    065     *
    066     * @param changedValues the map defining the changed values
    067     * @param newValues the collection with the new values
    068     * @param removedNodes the collection with the nodes to be removed
    069     * @param key the key of the update operation
    070     */
    071    public NodeUpdateData(final Map<QueryResult<T>, Object> changedValues,
    072            final Collection<Object> newValues,
    073            final Collection<QueryResult<T>> removedNodes, final String key)
    074    {
    075        this.changedValues = copyMap(changedValues);
    076        this.newValues = copyCollection(newValues);
    077        this.removedNodes = copyCollection(removedNodes);
    078        this.key = key;
    079    }
    080
    081    /**
    082     * Returns an unmodifiable map with the values to be changed. The keys of
    083     * the map are the query results for the nodes affected, the values are the
    084     * new values to be assigned to these nodes.
    085     *
    086     * @return the map with values to be changed
    087     */
    088    public Map<QueryResult<T>, Object> getChangedValues()
    089    {
    090        return changedValues;
    091    }
    092
    093    /**
    094     * Returns a collection with the values to be newly added. For these values
    095     * new nodes have to be created and added under the key stored in this
    096     * object.
    097     *
    098     * @return the collection with new values
    099     */
    100    public Collection<Object> getNewValues()
    101    {
    102        return newValues;
    103    }
    104
    105    /**
    106     * Adds a collection with the nodes to be removed. These nodes are no longer
    107     * needed and have to be removed from the node model processing this
    108     * request.
    109     *
    110     * @return the collection with nodes to be removed
    111     */
    112    public Collection<QueryResult<T>> getRemovedNodes()
    113    {
    114        return removedNodes;
    115    }
    116
    117    /**
    118     * Returns the key for this update operation.
    119     *
    120     * @return the key for this operation
    121     */
    122    public String getKey()
    123    {
    124        return key;
    125    }
    126
    127    /**
    128     * Creates an unmodifiable defensive copy of the passed in map which may be
    129     * null.
    130     *
    131     * @param map the map to be copied
    132     * @param <K> the type of the keys involved
    133     * @param <V> the type of the values involved
    134     * @return the unmodifiable copy
    135     */
    136    private static <K, V> Map<K, V> copyMap(final Map<? extends K, ? extends V> map)
    137    {
    138        if (map == null)
    139        {
    140            return Collections.emptyMap();
    141        }
    142        return Collections.unmodifiableMap(new HashMap<>(map));
    143    }
    144
    145    /**
    146     * Creates an unmodifiable defensive copy of the passed in collection with
    147     * may be null.
    148     *
    149     * @param col the collection to be copied
    150     * @param <T> the element type of the collection
    151     * @return the unmodifiable copy
    152     */
    153    private static <T> Collection<T> copyCollection(final Collection<? extends T> col)
    154    {
    155        if (col == null)
    156        {
    157            return Collections.emptySet();
    158        }
    159        return Collections.unmodifiableCollection(new ArrayList<>(col));
    160    }
    161}