/*******************************************************************************
* (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License v2.0 which accompany this distribution.
*
* The Apache License is available at
* http://www.apache.org/licenses/LICENSE-2.0
*
*******************************************************************************/
package io.cloudslang.lang.runtime.bindings;
/*******************************************************************************
* (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License v2.0 which accompany this distribution.
*
* The Apache License is available at
* http://www.apache.org/licenses/LICENSE-2.0
*
*******************************************************************************/
import io.cloudslang.lang.entities.SystemProperty;
import io.cloudslang.lang.entities.bindings.Input;
import io.cloudslang.lang.entities.bindings.values.Value;
import io.cloudslang.lang.entities.bindings.values.ValueFactory;
import io.cloudslang.lang.entities.utils.ExpressionUtils;
import io.cloudslang.lang.runtime.bindings.scripts.ScriptEvaluator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InputsBinding extends AbstractBinding {
@Autowired
private ScriptEvaluator scriptEvaluator;
/**
* Binds the inputs to a new result map
*
* @param inputs : the inputs to bind
* @param context : initial context
* @return : a new map with all inputs resolved (does not include initial context)
*/
public Map<String, Value> bindInputs(List<Input> inputs, Map<String, ? extends Value> context,
Set<SystemProperty> systemProperties) {
Map<String, Value> resultContext = new HashMap<>();
//we do not want to change original context map
Map<String, Value> srcContext = new HashMap<>(context);
for (Input input : inputs) {
bindInput(input, srcContext, resultContext, systemProperties);
}
return resultContext;
}
private void bindInput(Input input, Map<String, ? extends Value> context, Map<String, Value> targetContext,
Set<SystemProperty> systemProperties) {
Value value;
String inputName = input.getName();
Validate.notEmpty(inputName);
String errorMessagePrefix = "Error binding input: '" + inputName;
try {
value = resolveValue(input, context, targetContext, systemProperties);
} catch (Throwable t) {
throw new RuntimeException(errorMessagePrefix + "', \n\tError is: " + t.getMessage(), t);
}
if (input.isRequired() && isEmpty(value)) {
throw new RuntimeException("Input with name: \'" + inputName + "\' is Required, but value is empty");
}
validateStringValue(errorMessagePrefix, value);
targetContext.put(inputName, value);
}
private Value resolveValue(Input input, Map<String, ? extends Value> context,
Map<String, ? extends Value> targetContext, Set<SystemProperty> systemProperties) {
Value value = null;
//we do not want to change original context map
Map<String, Value> scriptContext = new HashMap<>(context);
String inputName = input.getName();
Value valueFromContext = context.get(inputName);
boolean sensitive = input.getValue() != null && input.getValue().isSensitive() ||
valueFromContext != null && valueFromContext.isSensitive();
if (!input.isPrivateInput()) {
value = ValueFactory.create(valueFromContext, sensitive);
}
if (isEmpty(value)) {
Value rawValue = input.getValue();
String expressionToEvaluate = ExpressionUtils.extractExpression(rawValue == null ? null : rawValue.get());
if (expressionToEvaluate != null) {
if (context.containsKey(inputName)) {
scriptContext.put(inputName, valueFromContext);
}
//so you can resolve previous inputs already bound
scriptContext.putAll(targetContext);
value = scriptEvaluator.evalExpr(expressionToEvaluate, scriptContext, systemProperties,
input.getFunctionDependencies());
value = ValueFactory.create(value, sensitive);
} else if ((value == null && rawValue != null) ||
(containsEmptyStringOrNull(value) && doesNotContainNull(rawValue))) {
value = rawValue;
}
}
return value;
}
private boolean containsEmptyStringOrNull(Value value) {
return value != null &&
(value.get() == null || value.get().equals(""));
}
private boolean doesNotContainNull(Value value) {
return value != null && value.get() != null;
}
private boolean isEmpty(Value value) {
return value == null || value.get() == null || value.get().equals("");
}
}