/*
* (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* vpasquier <vpasquier@nuxeo.com>
* slacoin <slacoin@nuxeo.com>
*/
package org.nuxeo.ecm.automation.core.trace;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.automation.OperationContext;
import org.nuxeo.ecm.automation.OperationType;
import org.nuxeo.ecm.automation.core.impl.InvokableMethod;
import org.nuxeo.ecm.automation.core.scripting.Expression;
/**
* @since 5.7.3
*/
public class Call {
private static final Log log = LogFactory.getLog(Call.class);
/**
* Black listing of mvel expressions which should not be evaluated by the Automation traces for debugging purpose
*
* @since 8.1
*/
public static final String[] MVEL_BLACK_LIST_EXPR = new String[] { "getNextId" };
protected final String chainId;
protected final String aliases;
protected final OperationType type;
protected final List<Trace> nested = new LinkedList<Trace>();
protected final Details details;
protected Call(OperationType chain, OperationType op, Details details) {
type = op;
chainId = chain.getId();
aliases = Arrays.toString(chain.getAliases());
this.details = details;
}
public Call(OperationType chain, OperationType op) {
this(chain, op, new Details());
}
public Call(OperationType chain, OperationContext context, OperationType type, InvokableMethod method,
Map<String, Object> parms) {
this(chain, type, new Details(context, method, parms));
}
protected static class Details {
protected final Map<String, Object> parameters = new HashMap<>();
protected final Map<String, Object> variables = new HashMap<>();
protected final InvokableMethod method;
protected final Object input;
protected Object output;
protected Details() {
method = null;
input = null;
}
protected Details(OperationContext context, InvokableMethod method, Map<String, Object> parms) {
this.method = method;
input = context.getInput();
variables.putAll(context);
parms.forEach(new Evaluator(context)::inject);
}
protected class Evaluator {
protected final OperationContext context;
protected Evaluator(OperationContext context) {
this.context = context;
}
protected void inject(String key, Object value) {
if (!(value instanceof Expression)) {
parameters.put(key, value);
return;
}
Expression exp = (Expression) value;
for (String mvelExpr : MVEL_BLACK_LIST_EXPR) {
if (exp.getExpr().contains(mvelExpr)) {
parameters.put(key, new ExpressionParameter(key,
String.format("Cannot be evaluated in traces when using '%s' expression", mvelExpr)));
return;
}
}
try {
parameters.put(key, new ExpressionParameter(key, exp.eval(context)));
return;
} catch (RuntimeException e) {
log.warn("Cannot evaluate mvel expression for parameter: " + key, e);
}
}
}
}
/**
* @since 7.1
*/
public static class ExpressionParameter {
protected final String parameterId;
protected final Object parameterValue;
public ExpressionParameter(String parameterId, Object parameterValue) {
this.parameterId = parameterId;
this.parameterValue = parameterValue;
}
public Object getParameterValue() {
return parameterValue;
}
public String getParameterId() {
return parameterId;
}
}
public OperationType getType() {
return type;
}
public InvokableMethod getMethod() {
return details.method;
}
public Map<String, Object> getParameters() {
return details.parameters;
}
public Map<String, Object> getVariables() {
return details.variables;
}
public Object getInput() {
return details.input;
}
public Object getOutput() {
return details.output;
}
public List<Trace> getNested() {
return nested;
}
public String getChainId() {
return chainId;
}
public String getAliases() {
return aliases;
}
}