/*
* #%L
* gitools-utils
* %%
* Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package org.gitools.utils.textpattern;
import java.util.ArrayList;
import java.util.List;
public class TextPattern {
public List<Token> getTokens() {
return tokens;
}
public List<VariableToken> getVariableTokens() {
List<VariableToken> variableTokens = new ArrayList<>();
for (Token t : tokens) {
if (t instanceof VariableToken) {
variableTokens.add((VariableToken) t);
}
}
return variableTokens;
}
private final List<Token> tokens;
public TextPattern(String pattern) {
this.tokens = internalCompile(pattern);
}
private static List<Token> internalCompile(String pattern) {
List<Token> tokens = new ArrayList<>();
if (pattern == null) {
return tokens;
}
final StringBuilder buff = new StringBuilder();
final StringBuilder varBuff = new StringBuilder();
char state = 'C';
int pos = 0;
while (pos < pattern.length()) {
char ch = pattern.charAt(pos++);
switch (state) {
case 'C': // copying normal characters
if (ch == '$') {
state = '$';
} else {
buff.append(ch);
}
break;
case '$': // start of variable
if (ch == '{') {
state = 'V';
tokens.add(new TextToken(buff.toString()));
buff.setLength(0);
} else {
buff.append('$').append(ch);
state = 'C';
}
break;
case 'V': // reading name of variable
if (ch == '}') {
state = 'X';
} else {
varBuff.append(ch);
}
break;
case 'X': // expand variable
tokens.add(new VariableToken(varBuff.toString()));
varBuff.setLength(0);
pos--;
state = 'C';
break;
}
}
switch (state) {
case '$':
buff.append('$');
break;
case 'V':
buff.append("${").append(varBuff);
break;
case 'X':
tokens.add(new VariableToken(varBuff.toString()));
varBuff.setLength(0);
break;
}
if (buff.length() > 0) {
tokens.add(new TextToken(buff.toString()));
}
return tokens;
}
public String generate(VariableValueResolver resolver) {
StringBuilder sb = new StringBuilder();
for (Token token : tokens)
token.generate(resolver, sb);
return sb.toString();
}
public static interface VariableValueResolver {
String resolveValue(String variableName);
}
public static interface Token {
void generate(VariableValueResolver resolver, StringBuilder sb);
}
public static class TextToken implements Token {
private final String text;
public TextToken(String text) {
this.text = text;
}
@Override
public void generate(VariableValueResolver resolver, StringBuilder sb) {
sb.append(text);
}
@Override
public String toString() {
return text;
}
}
public static class VariableToken implements Token {
private final String variableName;
public VariableToken(String variableName) {
this.variableName = variableName;
}
public String getVariableName() {
return variableName;
}
@Override
public void generate(VariableValueResolver resolver, StringBuilder sb) {
sb.append(resolver.resolveValue(variableName));
}
@Override
public String toString() {
return variableName;
}
}
}