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 * @since 2.0 044 * @param <T> the type of nodes involved in this update operation 045 */ 046public class NodeUpdateData<T> 047{ 048 /** The map with the query results whose value has to be changed. */ 049 private final Map<QueryResult<T>, Object> changedValues; 050 051 /** The collection with the new values to be added. */ 052 private final Collection<Object> newValues; 053 054 /** The collection with query results about the nodes to be removed. */ 055 private final Collection<QueryResult<T>> removedNodes; 056 057 /** The key of the current update operation. */ 058 private final String key; 059 060 /** 061 * Creates a new instance of {@code NodeUpdateData} and initializes all its 062 * properties. All passed in collections are optional and can be 063 * <b>null</b>. 064 * 065 * @param changedValues the map defining the changed values 066 * @param newValues the collection with the new values 067 * @param removedNodes the collection with the nodes to be removed 068 * @param key the key of the update operation 069 */ 070 public NodeUpdateData(final Map<QueryResult<T>, Object> changedValues, 071 final Collection<Object> newValues, 072 final Collection<QueryResult<T>> removedNodes, final String key) 073 { 074 this.changedValues = copyMap(changedValues); 075 this.newValues = copyCollection(newValues); 076 this.removedNodes = copyCollection(removedNodes); 077 this.key = key; 078 } 079 080 /** 081 * Returns an unmodifiable map with the values to be changed. The keys of 082 * the map are the query results for the nodes affected, the values are the 083 * new values to be assigned to these nodes. 084 * 085 * @return the map with values to be changed 086 */ 087 public Map<QueryResult<T>, Object> getChangedValues() 088 { 089 return changedValues; 090 } 091 092 /** 093 * Returns a collection with the values to be newly added. For these values 094 * new nodes have to be created and added under the key stored in this 095 * object. 096 * 097 * @return the collection with new values 098 */ 099 public Collection<Object> getNewValues() 100 { 101 return newValues; 102 } 103 104 /** 105 * Adds a collection with the nodes to be removed. These nodes are no longer 106 * needed and have to be removed from the node model processing this 107 * request. 108 * 109 * @return the collection with nodes to be removed 110 */ 111 public Collection<QueryResult<T>> getRemovedNodes() 112 { 113 return removedNodes; 114 } 115 116 /** 117 * Returns the key for this update operation. 118 * 119 * @return the key for this operation 120 */ 121 public String getKey() 122 { 123 return key; 124 } 125 126 /** 127 * Creates an unmodifiable defensive copy of the passed in map which may be 128 * null. 129 * 130 * @param map the map to be copied 131 * @param <K> the type of the keys involved 132 * @param <V> the type of the values involved 133 * @return the unmodifiable copy 134 */ 135 private static <K, V> Map<K, V> copyMap(final Map<? extends K, ? extends V> map) 136 { 137 if (map == null) 138 { 139 return Collections.emptyMap(); 140 } 141 return Collections.unmodifiableMap(new HashMap<>(map)); 142 } 143 144 /** 145 * Creates an unmodifiable defensive copy of the passed in collection with 146 * may be null. 147 * 148 * @param col the collection to be copied 149 * @param <T> the element type of the collection 150 * @return the unmodifiable copy 151 */ 152 private static <T> Collection<T> copyCollection(final Collection<? extends T> col) 153 { 154 if (col == null) 155 { 156 return Collections.emptySet(); 157 } 158 return Collections.unmodifiableCollection(new ArrayList<>(col)); 159 } 160}