/* * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software distributed under the Licence * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the Licence for the specific language governing permissions and limitations under * the Licence. * * This product combines work with different licenses. See the "NOTICE" text file for details on the * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative * works that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egiz.eaaf.core.impl.utils; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utils to operate on Key/Value based configurations. * * @author tlenz * */ public class KeyValueUtils { private static final Logger log = LoggerFactory.getLogger(KeyValueUtils.class); public static final String KEY_DELIMITER = "."; public static final String CSV_DELIMITER = ","; public static final String KEYVVALUEDELIMITER = "="; public static final String DEFAULT_VALUE = "default"; /** * Convert Java properties into a Map String/String.
* Important: The key/values from properties must be of type String! * * @param properties Java {@link Properties} that should be converted * @return */ public static Map convertPropertiesToMap(final Properties properties) { return new HashMap((Map) properties); // INFO Java8 solution ;) // return properties.entrySet().stream().collect( // Collectors.toMap( // e -> e.getKey().toString(), // e -> e.getValue().toString() // ) // ); } /** * Extract the first child of an input key after a the prefix. * * @param key Full input key * @param prefix Prefix * @return Child key {String} if it exists or null */ public static String getFirstChildAfterPrefix(final String key, final String prefix) { final String idAfterPrefix = removePrefixFromKey(key, prefix); if (idAfterPrefix != null) { final int index = idAfterPrefix.indexOf(KEY_DELIMITER); if (index > 0) { final String adding = idAfterPrefix.substring(0, index); if (!adding.isEmpty()) { return adding; } } else if (!idAfterPrefix.isEmpty()) { return idAfterPrefix; } } return null; } /** * Extract the prefix from an input key. * * @param key Full input key * @param suffix Suffix of this key * @return Prefix {String} of the key or null if input key does not ends with * postfix string */ public static String getPrefixFromKey(final String key, final String suffix) { if (key != null && suffix != null && key.endsWith(suffix)) { final String idPreforeSuffix = key.substring(0, key.length() - suffix.length()); if (idPreforeSuffix.endsWith(KEY_DELIMITER)) { return idPreforeSuffix.substring(0, idPreforeSuffix.length() - 1); } else { return idPreforeSuffix; } } return null; } /** * Remove a prefix string from a key. * * @param key Full input key * @param prefix Prefix, which should be removed * @return The suffix of the input key or null if the input does not starts with * the prefix */ public static String removePrefixFromKey(final String key, String prefix) { if (prefix == null) { prefix = StringUtils.EMPTY; } if (key != null && key.startsWith(prefix)) { String afterPrefix = key.substring(prefix.length()); final int index = afterPrefix.indexOf(KEY_DELIMITER); if (index == 0) { afterPrefix = afterPrefix.substring(1); } return afterPrefix; } return null; } /** * Remove a prefix string from all keys in Map String/String of key/value pairs. * * @param keys Input data of key/value pairs * @param prefix Prefix which should be removed * @return Map String/String of key/value pairs without prefix in key, but never * null */ public static Map removePrefixFromKeys(final Map keys, final String prefix) { final Map result = new HashMap<>(); final Iterator> interator = keys.entrySet().iterator(); while (interator.hasNext()) { final Entry el = interator.next(); final String newKey = removePrefixFromKey(el.getKey(), prefix); if (StringUtils.isNotEmpty(newKey)) { result.put(newKey, el.getValue()); } } return result; } /** * Get a subset of key/value pairs which starts with a prefix string The Prefix * is removed from the key. * * @param keys Input data of key/value pairs * @param prefix Prefix string * @return Map String/String of key/value pairs without prefix in key, but never * null */ public static Map getSubSetWithPrefix(final Map keys, final String prefix) { return removePrefixFromKeys(keys, prefix); } /** * Add a prefix to key/value pairs to make the key absolute according to key * namespace convention. * * @param input Input key/value pairs which should be updated * @param prefix Key prefix, which should be added if the key is not * absolute * @param absolutIdentifier Key identifier, which indicates an absolute key * @return Map String/String of key/value pairs in which all keys are absolute * but never null */ public static Map makeKeysAbsolut(final Map input, final String prefix, final String absolutIdentifier) { final Map result = new HashMap<>(); final Iterator> interator = input.entrySet().iterator(); while (interator.hasNext()) { final Entry el = interator.next(); if (!el.getKey().startsWith(absolutIdentifier)) { // key is not absolute -> add prefix result.put(prefix + KEY_DELIMITER + el.getKey(), el.getValue()); } else { // key is absolute result.put(el.getKey(), el.getValue()); } } return result; } /** * Get the parent key string from an input key. * * @param key input key * @return parent key or the empty String if no parent exists */ public static String getParentKey(final String key) { if (StringUtils.isNotEmpty(key)) { final int index = key.lastIndexOf(KEY_DELIMITER); if (index > 0) { return key.substring(0, index); } } return StringUtils.EMPTY; } /** * Find the highest free list counter. * * @param input Array of list keys * @param listPrefix {String} prefix of the list * @return {int} highest free list counter */ public static int findNextFreeListCounter(final String[] input, final String listPrefix) { final List counters = new ArrayList<>(); if (input == null || input.length == 0) { return 0; } else { for (final String key : input) { final String listIndex = getFirstChildAfterPrefix(key, listPrefix); counters.add(Integer.parseInt(listIndex)); } Collections.sort(counters); return counters.get(counters.size() - 1) + 1; } } /** * Find the highest free list counter. * * @param keySet Set of list keys * @param listPrefix {String} prefix of the list * @return {int} highest free list counter */ public static int findNextFreeListCounter(final Set keySet, final String listPrefix) { if (keySet.isEmpty()) { return 0; } final String[] array = new String[keySet.size()]; keySet.toArray(array); return findNextFreeListCounter(array, listPrefix); } /** * Normalize a CSV encoded list of value of an key/value pair. * *

* This method removes all whitespace at the begin or the end of CSV values and * remove newLine signs at the end of value. The ',' is used as list delimiter *

* * @param value CSV encoded input data * @return normalized CSV encoded data or null if {value} is null or empty */ public static String normalizeCsvValueString(final String value) { String normalizedCodes = null; if (StringUtils.isNotEmpty(value)) { final String[] codes = value.split(CSV_DELIMITER); for (final String el : codes) { if (normalizedCodes == null) { normalizedCodes = StringUtils.chomp(el.trim()); } else { normalizedCodes += "," + StringUtils.chomp(el.trim()); } } } return normalizedCodes; } /** * Check a String if it is a comma separated list of values. * *

* This method uses the ',' as list delimiter. *

* * @param value CSV encoded input data * @return true if the input data contains a ',' and has more then 1 list * element, otherwise false */ public static boolean isCsvValueString(final String value) { if (StringUtils.isNotEmpty(value)) { final String[] codes = value.split(CSV_DELIMITER); if (codes.length >= 2 && StringUtils.isNotEmpty(codes[1].trim())) { return true; } } return false; } /** * Convert a CSV list to a List of CSV values.
*
* This method removes all whitespace at the begin or the end of CSV values and * remove newLine signs at the end of value. The ',' is used as list delimiter * * @param csv CSV encoded input data * @return List of CSV normalized values, but never null */ @Nonnull public static List getListOfCsvValues(@Nullable final String csv) { final List list = new ArrayList<>(); if (StringUtils.isNotEmpty(csv)) { final String[] values = csv.split(CSV_DELIMITER); for (final String el : values) { list.add(el.trim()); } } return list; } /** * Convert a List of String elements to a Map of Key/Value pairs.
* Every List element used as a key/value pair and the '=' sign represents the * delimiter between key and value * * @param elements List of key/value elements * @return Map of Key / Value pairs, but never null */ public static Map convertListToMap(final List elements) { final Map map = new HashMap<>(); for (final String el : elements) { if (el.contains(KEYVVALUEDELIMITER)) { final String[] split = el.split(KEYVVALUEDELIMITER); map.put(split[0], split[1]); } else { log.debug("Key/Value Mapper: '" + el + "' contains NO '='. Ignore it."); } } return map; } /** * This method remove all newline delimiter (\n or \r\n) from input data. * * @param value Input String * @return Input String without newline characters */ public static String removeAllNewlineFromString(final String value) { return value.replaceAll("(\\t|\\r?\\n)+", ""); } }