package com.temenos.interaction.core;
/*
* #%L
* interaction-core
* %%
* Copyright (C) 2012 - 2016 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.MultivaluedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper class for manipulating and transforming MultivaluedMap objects.
*
* @author dgroves
*
*/
public class MultivaluedMapHelper {
private MultivaluedMapHelper(){}
/**
* A MultivaluedMapHelper Strategy determines how values will be merged into the target map
* if there are duplicate keys.
*
* @author dgroves
*/
public static enum Strategy {
/**Overwrite duplicate keys' values.*/
FAVOUR_SRC,
/**Do not alter duplicate keys' values.*/
FAVOUR_DEST,
/**Append unique values to duplicate keys.*/
UNION
}
private static final Logger LOGGER = LoggerFactory.getLogger(MultivaluedMapHelper.class);
/**
* Merge two multivalued maps into a single map. Unique values will be handled in accordance to
* the chosen merge strategy, while unique entries will be replicated in the destination map.
* Null entry values will be replaced if the other map's entry value is not null,
* but null collection elements will be preserved.
*
* @param from The source map.
* @param to The target map that values will be merged into.
*/
public static <K, V> void merge(MultivaluedMap<K, V> from,
MultivaluedMap<K, V> to, Strategy transformation){
if(from == null || to == null){
LOGGER.error("Attempted to merge a null map");
return;
}
//use a LinkedList for faster insertion and removal
List<V> copiedValues = new LinkedList<V>();
for(Map.Entry<K, List<V>> entry : from.entrySet()){
if(!to.containsKey(entry.getKey())){
to.put(entry.getKey(), entry.getValue());
}else if(to.get(entry.getKey()) == null || transformation == Strategy.FAVOUR_SRC){
to.put(entry.getKey(), entry.getValue());
}else if(transformation == Strategy.UNION){
addAllIgnoreNullValue(entry.getValue(), copiedValues);
removeAllIgnoreNullValue(to.get(entry.getKey()), copiedValues);
addAllIgnoreNullValue(copiedValues, to.get(entry.getKey()));
copiedValues.clear();
}
}
}
private static <V> void addAllIgnoreNullValue(List<V> src, List<V> dest){
if(src != null && dest != null){
dest.addAll(src);
}
}
private static <V> void removeAllIgnoreNullValue(List<V> src, List<V> dest){
if(src != null && dest != null){
dest.removeAll(src);
}
}
}