net.achalaggarwal.arbiter.config.ConfigurationMerger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arbiter Show documentation
Show all versions of arbiter Show documentation
Utility for generating Oozie workflows
/*
* Copyright 2015-2016 Etsy
*
* Licensed 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.
*
* -----------------------------------------------------------------------
*
* This file has been modified from its original licensed form.
* Modifications are Copyright (C) 2016 Achal Aggarwal (achalaggarwal.net).
*/
package net.achalaggarwal.arbiter.config;
import net.achalaggarwal.arbiter.exception.ConfigurationException;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.builder.CompareToBuilder;
import java.util.*;
/**
* Merges multiple Config objects together
* ActionTypes with the same name will be combined
*
* @author Andrew Johnson
*/
public class ConfigurationMerger {
private ConfigurationMerger() { }
/**
* Merge multiple configurations together
*
* @param configs The list of Config objects to merge
* @return A Config object representing the merger of all given Configs
*/
public static Config mergeConfiguration(List configs) throws ConfigurationException {
Config mergedConfig = new Config();
mergedConfig.setGlobal(mergeGlobal(configs));
mergedConfig.setKillName(mergeKillName(configs));
mergedConfig.setKillMessage(mergeKillMessage(configs));
mergedConfig.setActionTypes(mergeActionTypes(configs));
mergedConfig.setCredentials(mergeCredentials(configs));
return mergedConfig;
}
private static List mergeCredentials(List configs) throws ConfigurationException {
List credentials = new ArrayList<>();
Map> creds = new HashMap<>();
for (Config c : configs) {
for (Credential a : c.getCredentials()) {
String name = a.getName();
if (!creds.containsKey(name)) {
creds.put(name, Lists.newArrayList(a));
} else {
creds.get(name).add(a);
}
}
}
for (Map.Entry> entry : creds.entrySet()) {
if (entry.getValue().size() == 1) {
credentials.addAll(entry.getValue());
} else {
List value = entry.getValue();
Credential merged = new Credential();
merged.setName(entry.getKey());
// If the tag or xmlns differs, the configuration is invalid
if (!areAllValuesEqual(value, new Function() {
@Override
public String apply(Credential input) {
return input.getType();
}
})) {
throw new ConfigurationException("Type do not match for Credential " + entry.getKey());
}
merged.setProperties(mergeMaps(value, new Function>() {
@Override
public Map apply(Credential input) {
return input.getProperties();
}
}));
credentials.add(merged);
}
}
return credentials;
}
private static Global mergeGlobal(List configs) {
return getFirstNonNull(configs, new Function() {
@Override
public Global apply(Config input) {
return input.getGlobal();
}
});
}
private static String mergeKillMessage(List configs) {
return getFirstNonNull(configs, new Function() {
@Override
public String apply(Config input) {
return input.getKillMessage();
}
});
}
private static String mergeKillName(List configs) {
return getFirstNonNull(configs, new Function() {
@Override
public String apply(Config input) {
return input.getKillName();
}
});
}
private static List mergeActionTypes(List configs) throws ConfigurationException {
List actionTypes = new ArrayList<>();
Map> actions = new HashMap<>();
for (Config c : configs) {
for (ActionType a : c.getActionTypes()) {
String name = a.getName();
if (!actions.containsKey(name)) {
actions.put(name, Lists.newArrayList(a));
} else {
actions.get(name).add(a);
}
}
}
for (Map.Entry> entry : actions.entrySet()) {
if (entry.getValue().size() == 1) {
actionTypes.addAll(entry.getValue());
}
else {
List value = entry.getValue();
Collections.sort(value, new ActionTypePrecedenceComparator());
ActionType merged = new ActionType();
merged.setName(entry.getKey());
// If the tag or xmlns differs, the configuration is invalid
if (!areAllValuesEqual(value, new Function() {
@Override
public String apply(ActionType input) {
return input.getTag();
}
})) {
throw new ConfigurationException("Tags do not match for ActionType " + entry.getKey());
}
if (!areAllValuesEqual(value, new Function() {
@Override
public String apply(ActionType input) {
return input.getXmlns();
}
})) {
throw new ConfigurationException("xmlns do not match for ActionType " + entry.getKey());
}
merged.setTag(value.get(0).getTag());
merged.setXmlns(value.get(0).getXmlns());
merged.setProperties(mergeMaps(value, new Function>() {
@Override
public Map apply(ActionType input) {
return input.getProperties();
}
}));
merged.setDefaultArgs(mergeCollectionMaps(value, new Function>>() {
@Override
public Map> apply(ActionType input) {
return input.getDefaultArgs();
}
}));
actionTypes.add(merged);
}
}
return actionTypes;
}
/**
* Merge multiple configurations together
*
* @param configs The list of Config objects to merge
* @return A Config object representing the merger of all given Configs
*/
public static Config mergeConfiguration(Config... configs) throws ConfigurationException {
return mergeConfiguration(Arrays.asList(configs));
}
/**
* Merge a collection of maps where the values are themselves collections
* Every value in the values of the resulting map is unique
*
* @param actionTypes The collection of ActionTypes
* @param transformFunction The function that produces a map from an ActionType
* @param The type of values in the collection that is the value of the map
* @return A Map representing the merger of all input maps
*/
public static > Map mergeCollectionMaps(Collection actionTypes, Function> transformFunction) {
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy