blob: d6b18b4517f8c57959e1c6510e9bf96db125e9f7 [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.unomi.persistence.elasticsearch.conditions;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.util.IOUtils;
import org.apache.lucene.analysis.charfilter.MappingCharFilterFactory;
import org.apache.lucene.analysis.util.ClasspathResourceLoader;
import org.apache.unomi.api.conditions.Condition;
import org.mvel2.MVEL;
import org.mvel2.ParserConfiguration;
import org.mvel2.ParserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ConditionContextHelper {
private static final Logger logger = LoggerFactory.getLogger(ConditionContextHelper.class);
private static Map<String,Serializable> mvelExpressions = new ConcurrentHashMap<>();
private static MappingCharFilterFactory mappingCharFilterFactory;
static {
Map<String,String> args = new HashMap<>();
args.put("mapping", "mapping-FoldToASCII.txt");
mappingCharFilterFactory = new MappingCharFilterFactory(args);
try {
mappingCharFilterFactory.inform(new ClasspathResourceLoader(ConditionContextHelper.class.getClassLoader()));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Condition getContextualCondition(Condition condition, Map<String, Object> context) {
if (!hasContextualParameter(condition.getParameterValues())) {
return condition;
}
@SuppressWarnings("unchecked")
Map<String, Object> values = (Map<String, Object>) parseParameter(context, condition.getParameterValues());
if (values == null) {
return null;
}
Condition n = new Condition(condition.getConditionType());
n.setParameterValues(values);
return n;
}
@SuppressWarnings("unchecked")
private static Object parseParameter(Map<String, Object> context, Object value) {
if (value instanceof String) {
if (((String) value).startsWith("parameter::") || ((String) value).startsWith("script::")) {
String s = (String) value;
if (s.startsWith("parameter::")) {
return context.get(StringUtils.substringAfter(s, "parameter::"));
} else if (s.startsWith("script::")) {
String script = StringUtils.substringAfter(s, "script::");
if (!mvelExpressions.containsKey(script)) {
ParserConfiguration parserConfiguration = new ParserConfiguration();
parserConfiguration.setClassLoader(ConditionContextHelper.class.getClassLoader());
mvelExpressions.put(script,MVEL.compileExpression(script, new ParserContext(parserConfiguration)));
}
return MVEL.executeExpression(mvelExpressions.get(script), context);
}
}
} else if (value instanceof Map) {
Map<String, Object> values = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) {
Object parameter = parseParameter(context, entry.getValue());
if (parameter == null) {
return null;
}
values.put(entry.getKey(), parameter);
}
return values;
} else if (value instanceof List) {
List<Object> values = new ArrayList<Object>();
for (Object o : ((List<?>) value)) {
Object parameter = parseParameter(context, o);
if (parameter != null) {
values.add(parameter);
}
}
return values;
}
return value;
}
private static boolean hasContextualParameter(Object value) {
if (value instanceof String) {
if (((String) value).startsWith("parameter::") || ((String) value).startsWith("script::")) {
return true;
}
} else if (value instanceof Map) {
for (Object o : ((Map<?, ?>) value).values()) {
if (hasContextualParameter(o)) {
return true;
}
}
} else if (value instanceof List) {
for (Object o : ((List<?>) value)) {
if (hasContextualParameter(o)) {
return true;
}
}
}
return false;
}
public static String[] foldToASCII(String[] s) {
if (s != null) {
for (int i = 0; i < s.length; i++) {
s[i] = foldToASCII(s[i]);
}
}
return s;
}
public static String foldToASCII(String s) {
if (s != null) {
s = s.toLowerCase();
StringReader stringReader = new StringReader(s);
Reader foldedStringReader = mappingCharFilterFactory.create(stringReader);
try {
return IOUtils.toString(foldedStringReader);
} catch (IOException e) {
logger.error("Error folding to ASCII string " + s, e);
}
}
return null;
}
public static <T> List<T> foldToASCII(List<T> s) {
if (s != null) {
return Lists.transform(s, new Function<T, T>() {
@Override
public T apply(T o) {
if (o instanceof String) {
return (T) ConditionContextHelper.foldToASCII((String) o);
}
return o;
}
});
}
return null;
}
}