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