package org.kefirsf.bb.proc; import org.kefirsf.bb.conf.Action; import java.text.MessageFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Класс переменной * * @author Kefir */ public class ProcVariable extends ProcNamedElement implements ProcPatternElement { private final java.util.regex.Pattern regex; private final boolean ghost; private final Action action; /** * Create named variable * * @param name variable name * @param regex regular expression pattern * @param ghost don't move the cursor after parsing * @param action the variable action. Rewrite, append, check */ public ProcVariable(String name, Pattern regex, boolean ghost, Action action) { super(name); this.regex = regex; this.ghost = ghost; this.action = action; } /** * Парсит элемент * * @param context контекст * @return true - если удалось распарсить константу * false - если не удалось */ public boolean parse(Context context, ProcPatternElement terminator) { Source source = context.getSource(); int offset = source.getOffset(); int end; if (terminator != null && !ghost) { end = terminator.findIn(source); if (end < 0) { if (regex == null) { return false; } else { end = source.length(); } } } else { end = source.length(); } CharSequence value = source.sub(end); // If define regex, then find this regex in value if (regex != null) { Matcher matcher = regex.matcher(value); if (matcher.lookingAt()) { int lend = matcher.end(); end = offset + lend; value = matcher.group(); } else { return false; } } // Old context value CharSequence old = (CharSequence) context.getAttribute(getName()); // Test this variable already defined and equals with this in this code scope CharSequence attr = (CharSequence) context.getLocalAttribute(getName()); if (attr == null || attr.equals(value)) { if (attr == null) { if (action == Action.rewrite) { setAttribute(context, value); } else { /* action == append */ if (old != null) { setAttribute(context, new StringBuilder().append(old).append(value)); } else { setAttribute(context, value); } } } if (!ghost) { source.incOffset(end - offset); } return true; } else { return false; } } /** * Определяет, что дальше в разбираемой строке находится нужная последовательность * * @param context current context * @return true если следующие символы в строке совпадают с pattern * false если не совпадают или строка кончилась */ public boolean isNextIn(Context context) { return regex == null || regex.matcher(context.getSource().subToEnd()).lookingAt(); } /** * Find this element * * @param source text source * @return start offset */ public int findIn(Source source) { if (regex != null) { Matcher matcher = regex.matcher(source.subToEnd()); if (matcher.find()) { return source.getOffset() + matcher.start(); } else { return -1; } } else { return -1; } } @Override public String toString() { return MessageFormat.format( "<var name=\"{0}\" regex=\"{1}\" action=\"{2}\" ghost=\"{3}\"/>", getName(), regex, action, ghost ); } }