blob: 527e5d73e0604a95a7ae52c7c3e6c652c7f96b52 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.sling.pipes.internal;
import org.apache.sling.pipes.PipeBindings;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.apache.sling.pipes.PipeBindings.INJECTED_SCRIPT_REGEXP;
/**
* utilities for user input
*/
public class CommandUtil {
static final String PAIR_SEP = ",";
static final String KEY_VALUE_SEP = "=";
static final String FIRST_KEY = "first";
static final String SECOND_KEY = "second";
static final String PN_JCR_MIXIN = "jcr:mixinTypes";
static final Pattern MIXINS_ARRAY_PATTERN = Pattern.compile("^\\s*\\[(.*)\\]\\s*$");
private static final Pattern UNEMBEDDEDSCRIPT_PATTERN = Pattern.compile("^(\\d+(\\.\\d+)?)|" + //21.42
"\\[.*]$|" + //['one','two']
"[\\w_\\-]+\\..+|" + //map.field...
"[\\w_\\-]+\\['.+']|" + //map['field']
"true$|false$|" + //boolean
"new .*|" + //instantiation
"(.*'$)"); // 'string'
static final String EXPR_TOKEN = "([^=]+|" + INJECTED_SCRIPT_REGEXP + ")+";
static final String CONFIGURATION_TOKEN = "\\s*(?<" + FIRST_KEY + ">" + EXPR_TOKEN + ")\\s*" + KEY_VALUE_SEP
+ "\\s*(?<" + SECOND_KEY + ">(" + EXPR_TOKEN + ")+)\\s*";
public static final Pattern CONFIGURATION_PATTERN = Pattern.compile(CONFIGURATION_TOKEN);
private CommandUtil() {
}
/**
* Checks arguments and throws exception if there is an issue
* @param params arguments to check
* @throws IllegalArgumentException exception thrown in case arguments are wrong
*/
public static void checkArguments(Object... params) {
if (params.length % 2 > 0){
throw new IllegalArgumentException("there should be an even number of arguments");
}
}
/**
* @param value
* @return eventually wrapped value
*/
static Object embedIfNeeded(Object value) {
if (value instanceof String) {
Matcher matcher = UNEMBEDDEDSCRIPT_PATTERN.matcher(value.toString());
if (matcher.matches()) {
return PipeBindings.embedAsScript(value.toString());
}
}
return value;
}
/**
* write key/value pairs into a map
* @param map target map
* @param embed flag indicating wether or not we should try to embed values in script tags,
* @param params key/value pairs to write into the map
*/
public static void writeToMap(Map<String, Object> map, boolean embed, Object... params){
for (int i = 0; i < params.length - 1; i += 2) {
map.put(params[i].toString(), embed ? embedIfNeeded(params[i + 1]) : params[i + 1]);
if (params[i].toString().equals(PN_JCR_MIXIN)) {
map.put(PN_JCR_MIXIN, handleMixins((String)params[i + 1]));
}
}
}
static String[] handleMixins(String value) {
Matcher matcher = MIXINS_ARRAY_PATTERN.matcher(value);
if (matcher.matches()) {
return Arrays.stream(matcher.group(1).split(PAIR_SEP))
.map(String::trim)
.collect(Collectors.toList()).toArray(new String[0]);
}
return new String[] { value };
}
/**
* @param input comma separated key=value pairs
* @param valueTransformer before adding it to the map, that function will be applied to found value
* @return map of key and (transformed) value
*/
public static Map<String, Object> stringToMap(@NotNull String input, UnaryOperator<String> valueTransformer) {
Map<String, Object> map = new HashMap<>();
for (String pair : input.split(PAIR_SEP) ){
Matcher matcher = CONFIGURATION_PATTERN.matcher(pair);
if (matcher.find()) {
map.put(matcher.group(FIRST_KEY), valueTransformer.apply(matcher.group(SECOND_KEY)));
}
}
return map;
}
/**
* @param o list of key value strings key1=value1,key2=value2,...
* @return String [] key1,value1,key2,value2,... corresponding to the pipe builder API
*/
public static String[] keyValuesToArray(List<String> o) {
List<String> args = new ArrayList<>();
if (o != null) {
for (String pair : o) {
Matcher matcher = CONFIGURATION_PATTERN.matcher(pair.trim());
if (matcher.matches()) {
args.add(matcher.group(FIRST_KEY));
args.add(matcher.group(SECOND_KEY));
}
}
}
return args.toArray(new String[args.size()]);
}
}