<commit_before>package org.apache.velocity.tools.generic;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import org.apache.velocity.util.ArrayIterator;
import org.apache.velocity.util.EnumerationIterator;
import org.apache.velocity.tools.config.DefaultKey;

/**
 * <p>
 * A convenience tool to use with #foreach loops. It wraps a list
 * to let the designer specify a condition to terminate the loop,
 * and reuse the same list in different loops.
 * </p>
 * <p>
 * Example of use:
 * <pre>
 *  Java
 *  ----
 *  context.put("mill", new IteratorTool());
 *
 *
 *  VTL
 *  ---
 *
 *  #set ($list = [1, 2, 3, 5, 8, 13])
 *  #set ($numbers = $mill.wrap($list))
 *
 *  #foreach ($item in $numbers)
 *  #if ($item < 8) $numbers.more()#end
 *  #end
 *
 *  $numbers.more()
 *
 *
 *  Output
 *  ------
 *
 *   1 2 3 5
 *  8
 *
 * Example toolbox.xml config (if you want to use this with VelocityView):
 * &lt;tool&gt;
 *   &lt;key&gt;mill&lt;/key&gt;
 *   &lt;scope&gt;request&lt;/scope&gt;
 *   &lt;class&gt;org.apache.velocity.tools.generic.IteratorTool&lt;/class&gt;
 * &lt;/tool&gt;
 * </pre>
 * </p>
 * <p>
 * <b>Warning:</b> It is not recommended to use hasNext() with this
 * tool as it is used to control the #foreach. Use hasMore() instead.
 * </p>
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id$
 */
@DefaultKey("mill")
public class IteratorTool implements Iterator {


    private Object wrapped;
    private Iterator iterator;
    private boolean wantMore;
    private boolean cachedNext;
    protected Object next;


    /**
     * Create a IteratorTool instance to use as tool.
     * When it is created this way, the tool returns a new
     * instance each time wrap() is called. This is
     * useful when you want to allow the designers to create instances.
     */
    public IteratorTool()
    {
        this(null);
    }


    /**
     * Create a IteratorTool instance to use in #foreach.
     *
     * @param wrapped The list to wrap.
     */
    public IteratorTool(Object wrapped)
    {
        internalWrap(wrapped);
    }


    /**
     * Wraps a list with the tool.
     * <br>The list can be an array, a Collection, a Map, an Iterator
     * or an Enumeration.
     * <br>If the list is a Map, the tool iterates over the values.
     * <br>If the list is an Iterator or an Enumeration, the tool can
     * be used only once.
     *
     * @param list The list to wrap.
     * @return A new wrapper if this object is used as a tool, or
     *         itself if it is a wrapper.
     */
    public IteratorTool wrap(Object list)
    {
        if (this.wrapped == null)
        {
            return new IteratorTool(list);
        }
        else if (list != null)
        {
            internalWrap(list);
            return this;
        }
        else
        {
            throw new IllegalArgumentException("Need a valid list to wrap");
        }
    }


    /**
     * Wraps a list with the tool. This object can therefore
     * be used instead of the list itself in a #foreach.
     * The list can be an array, a Collection, a Map, an
     * Iterator or an Enumeration.
     * <br>- If the list is a Map, the tool iterates over the values.
     * <br>- If the list is an Iterator or an Enumeration, the tool
     * can be used only once.
     *
     * @param wrapped The list to wrap.
     */
    private void internalWrap(Object wrapped)
    {
        if (wrapped != null)
        {
            /* rip-off from org/apache/velocity/runtime/directive/ForEach.java */
            if (wrapped.getClass().isArray())
            {
                this.iterator = new ArrayIterator((Object[])wrapped);
            }
            else if (wrapped instanceof Collection)
            {
                this.iterator = ((Collection)wrapped).iterator();
            }
            else if (wrapped instanceof Map)
            {
                this.iterator = ((Map)wrapped).values().iterator();
            }
            else if (wrapped instanceof Iterator)
            {
                this.iterator = (Iterator)wrapped;
            }
            else if (wrapped instanceof Enumeration)
            {
                this.iterator = new EnumerationIterator((Enumeration)wrapped);
            }
            else
            {
                /* Don't know what is the object.
                 * Should we put it in a one-item array? */
                throw new IllegalArgumentException("Don't know how to wrap this list");
            }<commit_msg>improve error message for unwrappable objects<commit_after>package org.apache.velocity.tools.generic;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import org.apache.velocity.util.ArrayIterator;
import org.apache.velocity.util.EnumerationIterator;
import org.apache.velocity.tools.config.DefaultKey;

/**
 * <p>
 * A convenience tool to use with #foreach loops. It wraps a list
 * to let the designer specify a condition to terminate the loop,
 * and reuse the same list in different loops.
 * </p>
 * <p>
 * Example of use:
 * <pre>
 *  Java
 *  ----
 *  context.put("mill", new IteratorTool());
 *
 *
 *  VTL
 *  ---
 *
 *  #set ($list = [1, 2, 3, 5, 8, 13])
 *  #set ($numbers = $mill.wrap($list))
 *
 *  #foreach ($item in $numbers)
 *  #if ($item < 8) $numbers.more()#end
 *  #end
 *
 *  $numbers.more()
 *
 *
 *  Output
 *  ------
 *
 *   1 2 3 5
 *  8
 *
 * Example toolbox.xml config (if you want to use this with VelocityView):
 * &lt;tool&gt;
 *   &lt;key&gt;mill&lt;/key&gt;
 *   &lt;scope&gt;request&lt;/scope&gt;
 *   &lt;class&gt;org.apache.velocity.tools.generic.IteratorTool&lt;/class&gt;
 * &lt;/tool&gt;
 * </pre>
 * </p>
 * <p>
 * <b>Warning:</b> It is not recommended to use hasNext() with this
 * tool as it is used to control the #foreach. Use hasMore() instead.
 * </p>
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id$
 */
@DefaultKey("mill")
public class IteratorTool implements Iterator {


    private Object wrapped;
    private Iterator iterator;
    private boolean wantMore;
    private boolean cachedNext;
    protected Object next;


    /**
     * Create a IteratorTool instance to use as tool.
     * When it is created this way, the tool returns a new
     * instance each time wrap() is called. This is
     * useful when you want to allow the designers to create instances.
     */
    public IteratorTool()
    {
        this(null);
    }


    /**
     * Create a IteratorTool instance to use in #foreach.
     *
     * @param wrapped The list to wrap.
     */
    public IteratorTool(Object wrapped)
    {
        internalWrap(wrapped);
    }


    /**
     * Wraps a list with the tool.
     * <br>The list can be an array, a Collection, a Map, an Iterator
     * or an Enumeration.
     * <br>If the list is a Map, the tool iterates over the values.
     * <br>If the list is an Iterator or an Enumeration, the tool can
     * be used only once.
     *
     * @param list The list to wrap.
     * @return A new wrapper if this object is used as a tool, or
     *         itself if it is a wrapper.
     */
    public IteratorTool wrap(Object list)
    {
        if (this.wrapped == null)
        {
            return new IteratorTool(list);
        }
        else if (list != null)
        {
            internalWrap(list);
            return this;
        }
        else
        {
            throw new IllegalArgumentException("Need a valid list to wrap");
        }
    }


    /**
     * Wraps a list with the tool. This object can therefore
     * be used instead of the list itself in a #foreach.
     * The list can be an array, a Collection, a Map, an
     * Iterator or an Enumeration.
     * <br>- If the list is a Map, the tool iterates over the values.
     * <br>- If the list is an Iterator or an Enumeration, the tool
     * can be used only once.
     *
     * @param wrapped The list to wrap.
     */
    private void internalWrap(Object wrapped)
    {
        if (wrapped != null)
        {
            /* rip-off from org/apache/velocity/runtime/directive/ForEach.java */
            if (wrapped.getClass().isArray())
            {
                this.iterator = new ArrayIterator((Object[])wrapped);
            }
            else if (wrapped instanceof Collection)
            {
                this.iterator = ((Collection)wrapped).iterator();
            }
            else if (wrapped instanceof Map)
            {
                this.iterator = ((Map)wrapped).values().iterator();
            }
            else if (wrapped instanceof Iterator)
            {
                this.iterator = (Iterator)wrapped;
            }
            else if (wrapped instanceof Enumeration)
            {
                this.iterator = new EnumerationIterator((Enumeration)wrapped);
            }
            else
            {
                /* Don't know what is the object.
                 * Should we put it in a one-item array? */
                throw new IllegalArgumentException("Don't know how to wrap: "+wrapped);
            }
{'fraction_non_alphanumeric': 0.103929968336748, 'fraction_numerical': 0.003166325200223505, 'mean_word_length': 2.1650456822870616, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, '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': '828760', 'n_tokens_mistral': 3117, 'n_tokens_neox': 3017, 'n_words': 1132}