/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.
*/
package org.jboss.shrinkwrap.resolver.impl.maven.archive.plugins;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.jboss.shrinkwrap.resolver.impl.maven.util.Validate;
/**
* An utility class that allows type safe conversions from XPP3 configuration provided by Maven into Java objects
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
class ConfigurationUtils {
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param defaultValue Default value if no such key exists
* @return String representation of the value
*/
static String valueAsString(Map<String, Object> map, Key key, String defaultValue) {
Validate.notNullOrEmpty(key.key, "Key for plugin configuration must be set");
if (map.containsKey(key.key)) {
return map.get(key.key).toString().length() == 0 ? defaultValue : map.get(key.key).toString();
}
return defaultValue;
}
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param defaultValue Default value if no such key exists
* @return Boolean representation of the value
*/
static boolean valueAsBoolean(Map<String, Object> map, Key key, boolean defaultValue) {
return Boolean.parseBoolean(valueAsString(map, key, String.valueOf(defaultValue)));
}
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param basedir basedir can be different from current basedir
* @param defaultValue Default value if no such key exists
* @return File representation of the value
*/
static File valueAsFile(Map<String, Object> map, Key key, File basedir, File defaultValue) {
String value = valueAsString(map, key, null);
if (Validate.isNullOrEmpty(value)) {
return defaultValue;
}
File candidate = new File(value);
if (!candidate.isAbsolute() && (basedir != null && basedir.exists())) {
return new File(basedir, candidate.getPath());
}
return candidate;
}
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param defaultValue Default value if no such key exists
* @return Map representation of the value
*/
static Map<String, Object> valueAsMap(Map<String, Object> map, Key key, Map<String, Object> defaultValue) {
if (map.containsKey(key.key)) {
Object rawOrMap = map.get(key.key);
if (rawOrMap instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> submap = (Map<String, Object>) rawOrMap;
return submap;
} else {
return defaultValue;
}
}
return defaultValue;
}
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param defaultValue Default value if no such key exists
* @return Map representation of the values mapped into Strings
*/
static Map<String, String> valueAsMapOfStrings(Map<String, Object> map, Key key, Map<String, String> defaultValue) {
Map<String, Object> castedDefaultValue = new HashMap<String, Object>();
castedDefaultValue.putAll(defaultValue);
Map<String, Object> uncastedResult = valueAsMap(map, key, castedDefaultValue);
Map<String, String> castedResult = new HashMap<String, String>();
for (Map.Entry<String, Object> entry : uncastedResult.entrySet()) {
castedResult.put(entry.getKey(), entry.getValue() == null ? null : entry.getValue().toString());
}
return castedResult;
}
/**
* Fetches a value specified by key
*
* @param map XPP3 map equivalent
* @param key navigation key
* @param defaultValue Default value if no such key exists
* @return List representation of the value
*/
static List<String> valueAsStringList(Map<String, Object> map, Key key, List<String> defaultValue) {
Validate.notNullOrEmpty(key.key, "Key for plugin configuration must be set");
if (map.containsKey(key.key)) {
Object rawMapOrObject = map.get(key.key);
// handles non-nested content
if (key.subKey == null) {
if (rawMapOrObject == null) {
return defaultValue;
} else {
return tokenize(rawMapOrObject, key.delimiter);
}
}
// go for nested content
if (rawMapOrObject == null) {
return defaultValue;
} else if (!(rawMapOrObject instanceof Map)) {
return Arrays.asList(rawMapOrObject.toString());
}
// 1/ we can either have <excludes>foo,bar</excludes>
// 2/ or <excludes><exclude>foo</exclude><exclude>bar</exclude></excludes>
@SuppressWarnings("unchecked")
Map<String, Object> subMap = (Map<String, Object>) rawMapOrObject;
Object nestedRaw = subMap.get(key.subKey);
if (nestedRaw == null) {
return defaultValue;
}
// format 2/
else if (nestedRaw instanceof Iterable<?>) {
List<String> list = new ArrayList<String>();
for (Object nested : (Iterable<?>) nestedRaw) {
list.addAll(tokenize(nested, key.delimiter));
}
return list;
}
// format 1/
else {
return tokenize(nestedRaw, key.delimiter);
}
}
return defaultValue;
}
private static List<String> tokenize(Object object, String delimiter) {
List<String> list = new ArrayList<String>();
final StringTokenizer tokenizer = new StringTokenizer(object.toString(), delimiter);
while (tokenizer.hasMoreElements()) {
list.add(tokenizer.nextToken());
}
return list;
}
/**
* Represents a key that can be used to fetch values from XPP3 Configuration returned by Maven
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
static final class Key {
static final String DEFAULT_DELIMITER = ",";
String key;
String subKey;
String delimiter;
/**
* Constructs a simple key. It equals xpath {@code /key}.
*
* @param key name of the child to be fetched
*/
Key(String key) {
this.key = key;
this.delimiter = DEFAULT_DELIMITER;
}
/**
* Constructs a composed key. It equals either {@code /key} split by delimiter or all {@code /key/subKey} values
*
* @param key name of the child to be fetched
* @param subKey name of the grand children to be fetched
*/
Key(String key, String subKey) {
this.key = key;
this.subKey = subKey;
this.delimiter = DEFAULT_DELIMITER;
}
}
}