<commit_before>package io.toolisticon.annotationprocessortoolkit.templating.templateblocks;

import io.toolisticon.annotationprocessortoolkit.templating.ModelPathResolver;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Used to handle for loops in templates.
 */
public class ForTemplateBlock implements TemplateBlock {

    private final static Pattern ATTRIBUTE_PATTERN = Pattern.compile("\\s*(\\w+?)\\s*[:]\\s*((?:\\w|[.])+?)\\s*");


    private final String loopVariableName;
    private final String accessPath;
    private final String templateString;

    private TemplateBlockBinder binder;


    public ForTemplateBlock(String attributeString, String templateString) {

        if (attributeString == null || attributeString.trim().isEmpty()) {
            throw new IllegalArgumentException("for command has no attribute string.");
        }

        Matcher matcher = ATTRIBUTE_PATTERN.matcher(attributeString);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("for command has an invalid attribute string.");
        }

        this.loopVariableName = matcher.group(1);
        this.accessPath = matcher.group(2);
        this.templateString = templateString;


        binder = new TemplateBlockBinder(templateString);

    }


    @Override
    public TemplateBlockType getTemplateBlockType() {
        return TemplateBlockType.FOR;
    }

    @Override
    public String getContent(Map<String, Object> outerVariables) {

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.putAll(outerVariables);

        // get array or List
        Object values = ModelPathResolver.resolveModelPath(outerVariables, accessPath).getValue();

        StringBuilder stringBuilder = new StringBuilder();
        if (values != null) {


            if (values.getClass().isArray()) {


                for (Object value : (Object[]) values) {

                    // now update variables
                    variables.put(loopVariableName, value);
                    stringBuilder.append(binder.getContent(variables));

                }

            } else if (values instanceof List) {

                for (Object value : (List) values) {

                    // now update variables
                    variables.put(loopVariableName, value);
                    stringBuilder.append(binder.getContent(variables));

                }

            }


        }

        return stringBuilder.toString();

    }


    public TemplateBlockBinder getBinder() {
        return binder;
    }

    public void setBinder(TemplateBlockBinder binder) {
        this.binder = binder;
    }

    public String getLoopVariableName() {
        return loopVariableName;
    }
<commit_msg>Support  iterations of Collections instead of List in FOR templates.<commit_after>package io.toolisticon.annotationprocessortoolkit.templating.templateblocks;

import io.toolisticon.annotationprocessortoolkit.templating.ModelPathResolver;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Used to handle for loops in templates.
 */
public class ForTemplateBlock implements TemplateBlock {

    private final static Pattern ATTRIBUTE_PATTERN = Pattern.compile("\\s*(\\w+?)\\s*[:]\\s*((?:\\w|[.])+?)\\s*");


    private final String loopVariableName;
    private final String accessPath;
    private final String templateString;

    private TemplateBlockBinder binder;


    public ForTemplateBlock(String attributeString, String templateString) {

        if (attributeString == null || attributeString.trim().isEmpty()) {
            throw new IllegalArgumentException("for command has no attribute string.");
        }

        Matcher matcher = ATTRIBUTE_PATTERN.matcher(attributeString);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("for command has an invalid attribute string.");
        }

        this.loopVariableName = matcher.group(1);
        this.accessPath = matcher.group(2);
        this.templateString = templateString;


        binder = new TemplateBlockBinder(templateString);

    }


    @Override
    public TemplateBlockType getTemplateBlockType() {
        return TemplateBlockType.FOR;
    }

    @Override
    public String getContent(Map<String, Object> outerVariables) {

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.putAll(outerVariables);

        // get array or List
        Object values = ModelPathResolver.resolveModelPath(outerVariables, accessPath).getValue();

        StringBuilder stringBuilder = new StringBuilder();
        if (values != null) {


            if (values.getClass().isArray()) {


                for (Object value : (Object[]) values) {

                    // now update variables
                    variables.put(loopVariableName, value);
                    stringBuilder.append(binder.getContent(variables));

                }

            } else if (values instanceof Collection) {

                for (Object value : (Collection) values) {

                    // now update variables
                    variables.put(loopVariableName, value);
                    stringBuilder.append(binder.getContent(variables));

                }

            }


        }

        return stringBuilder.toString();

    }


    public TemplateBlockBinder getBinder() {
        return binder;
    }

    public void setBinder(TemplateBlockBinder binder) {
        this.binder = binder;
    }

    public String getLoopVariableName() {
        return loopVariableName;
    }

{'fraction_non_alphanumeric': 0.09626038781163435, 'fraction_numerical': 0.0006925207756232687, 'mean_word_length': 2.513990267639903, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3322530', 'n_tokens_mistral': 1496, 'n_tokens_neox': 1391, 'n_words': 347}