package org.ovirt.engine.core.dal.dbbroker.auditloghandling;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.ovirt.engine.core.compat.backendcompat.TypeCompat;
/**
* The class is responsible to resolve a message which might contain variables into a clear text, where the variables
* are replaced with the expect value, either it was provided by an attribute of {@link AuditLogable} or by
* {@link AuditLogable#getCustomValues()}
*/
public class MessageResolver {
/**
* A pattern to match for variables within message, i.e. ${<alphanumeric/>...}
*/
private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\$\\{\\w*\\}");
static final String UNKNOWN_VARIABLE_VALUE = "<UNKNOWN>";
private static final String UNKNOWN_REASON_VALUE =
" No reason was returned for this operation failure. See logs for further details.";
private static final String REASON_TOKEN = "reason";
private static final String OPTIONAL_REASON_TOKEN = "optionalreason";
/**
* Resolves a message which contains place holders by replacing them with the value from the map.
*
* @param message
* A text representing a message with place holders
* @param values
* a map of the place holder to its values
* @return a resolved message
*/
public static String resolveMessage(String message, Map<String, String> values) {
Matcher matcher = VARIABLE_PATTERN.matcher(message);
StringBuffer buffer = new StringBuffer();
String value;
String token;
while (matcher.find()) {
token = matcher.group();
// remove leading ${ and trailing }
token = token.substring(2, token.length() - 1);
// get value from value map
value = values.get(token.toLowerCase());
if (value == null || value.isEmpty()) {
// replace value with UNKNOWN_VARIABLE_VALUE if value not defined
switch (token.toLowerCase()) {
case REASON_TOKEN:
value = UNKNOWN_REASON_VALUE;
break;
case OPTIONAL_REASON_TOKEN:
value = "";
break;
default:
value = UNKNOWN_VARIABLE_VALUE;
}
}
matcher.appendReplacement(buffer, Matcher.quoteReplacement(value)); // put the value into message
}
// append the rest of the message
matcher.appendTail(buffer);
return buffer.toString();
}
static String resolveMessage(String message, AuditLogable logable) {
String returnValue = message;
if (logable != null) {
Map<String, String> map = getAvailableValues(message, logable);
returnValue = resolveMessage(message, map);
}
return returnValue;
}
private static Set<String> resolvePlaceHolders(String message) {
Set<String> result = new HashSet<>();
Matcher matcher = VARIABLE_PATTERN.matcher(message);
String token;
while (matcher.find()) {
token = matcher.group();
// remove leading ${ and trailing }
token = token.substring(2, token.length() - 1);
result.add(token.toLowerCase());
}
return result;
}
private static Map<String, String> getAvailableValues(String message, AuditLogable logable) {
Map<String, String> returnValue = new HashMap<>(logable.getCustomValues());
Set<String> attributes = resolvePlaceHolders(message);
if (attributes != null && attributes.size() > 0) {
TypeCompat.getPropertyValues(logable, attributes, returnValue);
}
return returnValue;
}
}