package org.jboss.windup.config;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import org.apache.commons.lang3.SystemUtils;
import org.jboss.windup.config.metadata.RuleMetadataType;
import org.jboss.windup.util.exception.WindupException;
import org.ocpsoft.rewrite.config.Condition;
import org.ocpsoft.rewrite.config.Operation;
import org.ocpsoft.rewrite.config.Rule;
import org.ocpsoft.rewrite.config.RuleBuilder;
import org.ocpsoft.rewrite.context.Context;
/**
* Utils for the Metadata. Will be likely moved to Windup Utils.
*
* @author <a href="mailto:ozizka@redhat.com">Ondrej Zizka</a>
*/
public class RuleUtils
{
private static final int MAX_WIDTH = 80;
/**
* Describes given {@link Rule} as:
* <p>
* <code>ID: Phase - Provider [tags ...]".</code>
*/
public static String prettyPrintRule(Rule rule)
{
StringBuilder result = new StringBuilder();
if (rule instanceof Context)
{
final Context context = (Context) rule;
RuleProvider provider = (RuleProvider) context.get(RuleMetadataType.RULE_PROVIDER);
if (provider != null && provider.getMetadata() != null)
{
result.append(provider.getMetadata().getPhase().getSimpleName()).append(" - ");
result.append(provider.getMetadata().getID()).append(" - ");
}
if (rule.getId() != null)
result.append(rule.getId());
}
return result.toString();
}
/**
* Attempts to create a human-readable String representation of the provided rule.
*/
public static String ruleToRuleContentsString(Rule originalRule, int indentLevel)
{
if (originalRule instanceof Context && ((Context) originalRule).containsKey(RuleMetadataType.RULE_XML))
{
return (String) ((Context) originalRule).get(RuleMetadataType.RULE_XML);
}
if (!(originalRule instanceof RuleBuilder))
{
return wrap(originalRule.toString(), MAX_WIDTH, indentLevel);
}
final RuleBuilder rule = (RuleBuilder) originalRule;
StringBuilder result = new StringBuilder();
if (indentLevel == 0)
result.append("addRule()");
for (Condition condition : rule.getConditions())
{
String conditionToString = conditionToString(condition, indentLevel + 1);
if (!conditionToString.isEmpty())
{
result.append("\n");
insertPadding(result, indentLevel + 1);
result.append(".when(").append(wrap(conditionToString, MAX_WIDTH, indentLevel + 2)).append(")");
}
}
for (Operation operation : rule.getOperations())
{
String operationToString = operationToString(operation, indentLevel + 1);
if (!operationToString.isEmpty())
{
result.append("\n");
insertPadding(result, indentLevel + 1);
result.append(".perform(").append(wrap(operationToString, MAX_WIDTH, indentLevel + 2)).append(")");
}
}
if (rule.getId() != null && !rule.getId().isEmpty())
{
result.append("\n");
insertPadding(result, indentLevel);
result.append("withId(\"").append(rule.getId()).append("\")");
}
if (rule.priority() != 0)
{
result.append("\n");
insertPadding(result, indentLevel);
result.append(".withPriority(").append(rule.priority()).append(")");
}
return result.toString();
}
private static String conditionToString(Condition condition, int indentLevel)
{
if (condition instanceof RuleBuilder)
return ruleToRuleContentsString((RuleBuilder) condition, indentLevel + 1);
return condition == null ? "" : wrap(condition.toString(), MAX_WIDTH, indentLevel + 1);
}
private static String operationToString(Operation operation, int indentLevel)
{
if (operation instanceof RuleBuilder)
return ruleToRuleContentsString((RuleBuilder) operation, indentLevel + 1);
return operation == null ? "" : wrap(operation.toString(), MAX_WIDTH, indentLevel + 2);
}
private static String wrap(String str, int wrapLength, int indentLevel)
{
StringBuilder result = new StringBuilder();
try (StringReader sr = new StringReader(str))
{
BufferedReader br = new BufferedReader(sr);
String line = null;
try
{
while ((line = br.readLine()) != null)
{
result.append(wrapLine(line, wrapLength, indentLevel)).append("\n");
}
}
catch (IOException e)
{
throw new WindupException("Error... while reading a StringReader", e);
}
}
return result.toString();
}
private static String wrapLine(String str, int wrapLength, int indentLevel)
{
if (str == null)
{
return null;
}
if (wrapLength < 1)
{
wrapLength = 1;
}
int inputLineLength = str.length();
int offset = 0;
StringBuilder wrappedLine = new StringBuilder(inputLineLength + 32);
StringBuilder filler = new StringBuilder();
while ((inputLineLength - offset) > wrapLength)
{
if (str.charAt(offset) == '.')
{
offset++;
filler.append('.');
continue;
}
int spaceToWrapAt = str.lastIndexOf('.', wrapLength + offset);
if (spaceToWrapAt >= offset)
{
// normal case
if (wrappedLine.length() > 0)
{
insertPadding(wrappedLine, indentLevel);
}
wrappedLine.append(filler);
wrappedLine.append(str.substring(offset, spaceToWrapAt));
wrappedLine.append(SystemUtils.LINE_SEPARATOR);
offset = spaceToWrapAt;
}
else
{
// really long word or URL
// wrap really long word one line at a time
if (wrappedLine.length() > 0)
{
insertPadding(wrappedLine, indentLevel);
}
wrappedLine.append(filler);
wrappedLine.append(str.substring(offset, wrapLength + offset));
wrappedLine.append(SystemUtils.LINE_SEPARATOR);
offset += wrapLength;
}
filler.setLength(0);
}
// Whatever is left in line is short enough to just pass through
if (wrappedLine.length() > 0)
{
insertPadding(wrappedLine, indentLevel);
}
wrappedLine.append(filler);
wrappedLine.append(str.substring(offset));
return wrappedLine.toString();
}
private static void insertPadding(StringBuilder sb, int indentLevel)
{
for (int i = 0; i < indentLevel; i++)
{
sb.append("\t");
}
}
}