/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.core.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.ObjectUtils;
import com.google.common.collect.MapDifference;
import com.google.common.collect.MapDifference.ValueDifference;
public final class ConfigUtils {
/**
* apply the differences to the given map (3-way-merge)
*
* @throws MergeException if the changes cannot be applied because of merge-conflicts
*/
public static <K, V> Map<K, V> updateMap(final Map<K, V> original, MapDifference<K, V> diff) throws MergeException {
Map<K, V> result = new HashMap<K, V>(original);
if (diff.areEqual()) {
return result;
}
for (Entry<K, V> entry : diff.entriesOnlyOnLeft().entrySet()) {
V originalValue = original.get(entry.getKey());
if (ObjectUtils.equals(originalValue, entry.getValue())) {
result.remove(entry.getKey());
}
}
for (Entry<K, V> entry : diff.entriesOnlyOnRight().entrySet()) {
K key = entry.getKey();
if (original.containsKey(key)) {
if (ObjectUtils.notEqual(original.get(key), entry.getValue())) {
throw new MergeException(String.format(
"tried to introduce a new value, but it was already there: %s (%s,%s)",
key, original.get(key), entry.getValue()));
}
}
result.put(entry.getKey(), entry.getValue());
}
for (Entry<K, ValueDifference<V>> entry : diff.entriesDiffering().entrySet()) {
K key = entry.getKey();
V originalValue = original.get(entry.getKey());
if (ObjectUtils.equals(originalValue, entry.getValue().leftValue())) {
// Map changed in diff only
result.put(key, entry.getValue().rightValue());
} else if (ObjectUtils.equals(originalValue, entry.getValue().rightValue())) {
// Diff would change value to value already in original Map
result.put(key, originalValue);
} else {
// Merge conflict, got 3 different Values
String errorMessage =
String
.format(
"Changes could not be applied, because original value differes from left-side of the"
+ "MapDifference: %s (%s,%s)", entry.getKey(), original.get(entry.getKey()),
entry.getValue());
throw new MergeException(errorMessage);
}
}
return result;
}
private ConfigUtils() {
}
}