Iterables.java

/*
** Module   : Iterables.java
** Abstract : Helper methods which make convenient use of Iterable interface
**            and foreach loops.
**
** Copyright (c) 2010-2019, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------Description-----------------
** 001 SIY 20100804  @       Created initial version
** 002 SIY 20110112          Minor cleanups.
** 003 HC  20191211          Added reverseFrom and directFrom overloads.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.util;

import java.util.*;

/**
 * Set of helper methods for iterables.
 */
public class Iterables
{
   /**
    * Static factory method which returns reverse iterable for a given list.
    * 
    * @param   <T>
    *          List item type.
    * @param   list
    *          List.
    *          
    * @return  Instance of {@link Iterable} which performs iteration through
    *          elements in reverse order.
    */
   public static <T> Iterable<T> reverse(final List<T> list)
   {
      return new RevIterable<T>(list.listIterator(list.size())); 
   }

   /**
    * Create new reverse iterable which will traverse list starting from
    * given element.
    * 
    * @param   <T>
    *          List item type.
    * @param   list
    *          List.
    * @param   elem
    *          Initial element from which iteration will be started.
    *          Note that the element itself will not be returned.
    *          
    * @return  Instance of {@link Iterable} which performs iteration through
    *          elements in reverse order.
    */
   public static <T> Iterable<T> reverseFrom(List<T> list, T elem)
   {
      return reverseFrom(list, elem, false);
   }

   /**
    * Create new reverse iterable which will traverse list starting from
    * given element.
    *
    * @param   <T>
    *          List item type.
    * @param   list
    *          List.
    * @param   elem
    *          Initial element from which iteration will be started.
    * @param   inclusive
    *          When {@code true} the iterator will also include the initial element.
    *
    * @return  Instance of {@link Iterable} which performs iteration through
    *          elements in reverse order.
    */
   public static <T> Iterable<T> reverseFrom(List<T> list, T elem, boolean inclusive)
   {
      int idx = list.indexOf(elem);

      if (idx < 0)
         return null;

      if (inclusive)
      {
         idx++;
      }

      return new RevIterable<T>(list.listIterator(idx));
   }

   /**
    * Return iterable which traverses list in direct order starting from given 
    * element. 
    * 
    * @param   <T>
    *          List item type.
    * @param   list
    *          List.
    * @param   elem
    *          Initial element from which iteration will be started.
    *          Note that the element itself will not be returned.
    *          
    * @return  Instance of {@link Iterable} which performs iteration through
    *          elements in direct order.
    */
   public static <T> Iterable<T> directFrom(final List<T> list, T elem)
   {
      return directFrom(list, elem, false);
   }

   /**
    * Return iterable which traverses list in direct order starting from given
    * element.
    *
    * @param   <T>
    *          List item type.
    * @param   list
    *          List.
    * @param   elem
    *          Initial element from which iteration will be started.
    * @param   inclusive
    *          When {@code true} the iterator will also include the initial element.
    *
    * @return  Instance of {@link Iterable} which performs iteration through
    *          elements in direct order.
    */
   public static <T> Iterable<T> directFrom(final List<T> list, T elem, boolean inclusive)
   {
      final int idx = list.indexOf(elem);
      
      if (idx < 0)
         return null;
      
      final ListIterator<T> iter = list.listIterator(idx);

      if (!inclusive && iter.hasNext())
         iter.next();
      
      return new Iterable<T>()
      {
         /**
          * @see java.lang.Iterable#iterator()
          */
         @Override
         public Iterator<T> iterator()
         {
            return iter;
         }
      };
   }

   /**
    * Reverse iterable implementation.
    *
    * @param <T>
    */
   private static class RevIterable<T>
   implements Iterable<T>
   {
      /**
       * Underlying iterator.
       */
      private final ListIterator<T> iter;

      /**
       * Constructor.
       *
       * @param   iter
       */
      RevIterable(ListIterator<T> iter)
      {
         this.iter = iter;
      }

      /**
       * @see java.lang.Iterable#iterator()
       */
      @Override
      public Iterator<T> iterator()
      {
         return new Iterator<T>()
         {
            /**
             * @see java.util.Iterator#hasNext()
             */
            @Override
            public boolean hasNext()
            {
               return iter.hasPrevious();
            }

            /**
             * @see java.util.Iterator#next()
             */
            @Override
            public T next()
            {
               return iter.previous();
            }

            /**
             * @see java.util.Iterator#remove()
             */
            @Override
            public void remove()
            {
               throw new UnsupportedOperationException();
            }

         };
      }
   }
}