package fitnesse.slim; import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class SlimSymbol { public static final Pattern SYMBOL_PATTERN = Pattern .compile("\\$([A-Za-z\\p{L}][\\w\\p{L}]*)"); // This would be a better pattern as it allows to define the end of a symbol name with another $ sign // but this could break existing tests. See discussion in #790 // public static final Pattern SYMBOL_PATTERN = Pattern // .compile("\\$([A-Za-z\\p{L}][\\w\\p{L}]*)\\$?"); public static final Pattern SYMBOL_ASSIGNMENT_PATTERN = Pattern .compile("\\A\\s*\\$([A-Za-z\\p{L}][\\w\\p{L}]*)\\s*=\\s*\\Z"); protected String replacedString; private Matcher symbolMatcher; private int startingPosition; public static final String isSymbolAssignment(String content) { if (content == null) return null; Matcher matcher = SYMBOL_ASSIGNMENT_PATTERN.matcher(content); return matcher.find() ? matcher.group(1) : null; } public String replace(String s) { if(null == s) return null; // Don't replace assignments, return as is if (isSymbolAssignment(s) != null) return s; replacedString = s; symbolMatcher = SYMBOL_PATTERN.matcher(s); replaceAllSymbols(); return replacedString; } private void replaceAllSymbols() { startingPosition = 0; while (symbolFound()) replaceSymbol(); } private void replaceSymbol() { String value; String prefix; String suffix; String symbolName = symbolMatcher.group(1); value = formatSymbol(symbolName); prefix = replacedString.substring(0, symbolMatcher.start()); suffix = replacedString.substring(symbolMatcher.end()); replacedString = prefix + value + suffix; int replacementEnd = symbolMatcher.start() + value.length(); startingPosition = Math.min(replacementEnd, replacedString.length()); } protected String formatSymbol(String symbolName) { String value = getSymbolValue(symbolName); if (value == null) { // return the original match without any change if the symbol is not defined return symbolMatcher.group(); } else return formatSymbolValue(symbolName, value); } private boolean symbolFound() { symbolMatcher = SYMBOL_PATTERN.matcher(replacedString); return symbolMatcher.find(startingPosition); } protected String formatSymbolValue(String name, String value) { return value; } // implement this to access the Symbol Store protected abstract String getSymbolValue(String symbolName); }