package com.github.czyzby.lml.parser.impl.tag.macro;
import com.badlogic.gdx.utils.ObjectMap;
import com.github.czyzby.kiwi.util.common.Strings;
import com.github.czyzby.lml.parser.LmlParser;
import com.github.czyzby.lml.parser.impl.tag.AbstractMacroLmlTag;
import com.github.czyzby.lml.parser.tag.LmlTag;
import com.github.czyzby.lml.util.collection.IgnoreCaseStringMap;
/** Abstract base for loop and iteration-based macros.
*
* @author MJ */
public abstract class AbstractLoopLmlMacroTag extends AbstractMacroLmlTag {
/** Optional name of iteration argument. Note that when always using this name, nested loops (or multi-argument
* loops) are impossible to create. Used for iteration macros. */
public static final String ELEMENT_ATTRIBUTE = "element";
/** Optional name of the loop times argument. Used for loop macros. */
public static final String TIMES_ATTRIBUTE = "times";
private final String indexArgument;
public AbstractLoopLmlMacroTag(final LmlParser parser, final LmlTag parentTag, final StringBuilder rawTagData) {
super(parser, parentTag, rawTagData);
indexArgument = getTagName() + ":index";
}
@Override
public void handleDataBetweenTags(final CharSequence rawMacroContent) {
final StringBuilder contentBuilder = new StringBuilder(rawMacroContent.length());
final ObjectMap<String, String> arguments = new IgnoreCaseStringMap<String>();
while (hasNext()) {
arguments.put(indexArgument, String.valueOf(getIndex()));
next(arguments);
contentBuilder.append(replaceArguments(rawMacroContent, arguments));
}
if (Strings.isNotEmpty(contentBuilder)) {
appendTextToParse(contentBuilder);
}
}
/** @return true if macro should continue to be evaluated. */
protected abstract boolean hasNext();
/** @return current iteration index. Should generally return different value after each time
* {@link #next(ObjectMap)} is called. The method is called BEFORE {@link #next(ObjectMap)} during iteration
* to set current index argument in the loop, so next method can safely increment this value. */
protected abstract int getIndex();
/** Advances loop iteration.
*
* @param arguments might have to be adjusted with each iteration step. */
protected abstract void next(ObjectMap<String, String> arguments);
}