All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.threadly.concurrent.ContainerHelper Maven / Gradle / Ivy

package org.threadly.concurrent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * Typically used only internally by the threadly library.  This class is designed to help with 
 * determining if a Runnable or Callable is contained at some  point within a chain of 
 * {@link CallableContainer} or {@link RunnableContainer}.
 * 
 * @since 1.0.0
 */
public final class ContainerHelper {
  /**
   * Attempts to remove the provided runnable from the source collection.  This uses the 
   * {@link Collection#remove(Object)} function to remove the container if it is found.
   * 
   * @since 2.0.0
   * @param source source collection to search over
   * @param compareTo Runnable to compare against in search
   * @return {@code true} if collection was modified
   */
  public static boolean remove(Collection source, 
                               Runnable compareTo) {
    Iterator it = source.iterator();
    while (it.hasNext()) {
      RunnableContainer rc = it.next();
      // we use source.remove() instead of it.remove() for usage with concurrent structures
      if (ContainerHelper.isContained(rc.getContainedRunnable(), compareTo) && source.remove(rc)) {
        return true;
      }
    }
    
    return false;
  }

  /**
   * Attempts to remove the provided callable from the source collection.  This uses the 
   * {@link Collection#remove(Object)} function to remove the container if it is found.
   * 
   * @since 2.0.0
   * @param source source collection to search over
   * @param compareTo Callable to compare against in search
   * @return {@code true} if collection was modified
   */
  public static boolean remove(Collection source, 
                               Callable compareTo) {
    Iterator it = source.iterator();
    while (it.hasNext()) {
      RunnableContainer rc = it.next();
      // we use source.remove() instead of it.remove() for usage with concurrent structures
      if (ContainerHelper.isContained(rc.getContainedRunnable(), compareTo) && source.remove(rc)) {
        return true;
      }
    }
    
    return false;
  }
  
  /**
   * Checks if the start runnable equals the compareTo runnable, or if the compareTo runnable is 
   * contained within a wrapper of the startRunnable.
   * 
   * @param startRunnable runnable to start search at
   * @param compareTo runnable to be comparing against
   * @return {@code true} if they are equivalent, or the compareTo runnable is contained within the start
   */
  public static boolean isContained(Runnable startRunnable, Runnable compareTo) {
    if (startRunnable.equals(compareTo)) {
      return true;
    }
    
    boolean containedAsRCCI = false;
    if (startRunnable instanceof RunnableContainer) {
      RunnableContainer rci = (RunnableContainer)startRunnable;
      containedAsRCCI = isContained(rci, compareTo);
    }
    if (containedAsRCCI) {
      return true;
    } else if (startRunnable instanceof CallableContainer) {
      CallableContainer cci = (CallableContainer)startRunnable;
      return isContained(cci, compareTo);
    } else {
      return false;
    }
  }

  /**
   * Checks if the compareTo runnable is contained by the provided 
   * {@link RunnableContainerInterface}.  If it's not we check to see if we can continue our 
   * search by looking for another {@link RunnableContainer}, or a {@link CallableContainer}.
   * 
   * @param rci Container to check contents of
   * @param compareTo Runnable to compare against
   * @return {@code true} if the runnable is contained at some point within the container
   */
  private static boolean isContained(RunnableContainer rci, Runnable compareTo) {
    while (true) {
      Runnable containedTask = rci.getContainedRunnable();
      if (containedTask != null) {
        if (containedTask.equals(compareTo)) {
          return true;
        } else if (containedTask instanceof CallableContainer && 
                   isContained((CallableContainer)containedTask, compareTo)) {
          return true;
        } else if (containedTask instanceof RunnableContainer) {
          // loop again
          rci = (RunnableContainer)containedTask;
        } else {
          return false;
        }
      } else {
        return false;
      }
    }
  }

  /**
   * Checks if the compareTo runnable is contained by the provided 
   * {@link CallableContainerInterface}.  If it's not we check to see if we can continue our 
   * search by looking for another {@link RunnableContainer}, or a {@link CallableContainer}.
   * 
   * @param cci Container to check contents of
   * @param compareTo Runnable to compare against
   * @return {@code true} if the runnable is contained at some point within the container
   */
  private static boolean isContained(CallableContainer cci, Runnable compareTo) {
    while (true) {
      Callable containedTask = cci.getContainedCallable();
      if (containedTask != null) {
        if (containedTask instanceof RunnableContainer && 
            isContained((RunnableContainer)containedTask, compareTo)) {
          return true;
        } else if (containedTask instanceof CallableContainer) {
          // loop again
          cci = (CallableContainer)containedTask;
        } else {
          return false;
        }
      } else {
        return false;
      }
    }
  }

  /**
   * Checks if the start runnable contains the provided callable.
   * 
   * @param startRunnable runnable to start search at
   * @param compareTo callable to be comparing against
   * @return {@code true} if the compareTo runnable is contained within the runnable
   */
  public static boolean isContained(Runnable startRunnable, Callable compareTo) {
    /* we have some awkward if/else logic in case we have a runnable the is both a 
     * CallableContainerInterface and a RunnableContainerInterface
     */
    boolean isContainedAsCCI = false;
    if (startRunnable instanceof CallableContainer) {
      CallableContainer cci = (CallableContainer)startRunnable;
      isContainedAsCCI = isContained(cci, compareTo);
    }
    if (isContainedAsCCI) {
      return true;
    } else if (startRunnable instanceof RunnableContainer) {
      RunnableContainer rci = (RunnableContainer)startRunnable;
      return isContained(rci, compareTo);
    } else {
      return false;
    }
  }

  private static boolean isContained(RunnableContainer rci, Callable compareTo) {
    while (true) {
      Runnable containedTask = rci.getContainedRunnable();
      if (containedTask != null) {
        if (containedTask instanceof CallableContainer && 
            isContained((CallableContainer)containedTask, compareTo)) {
          return true;
        } else if (containedTask instanceof RunnableContainer) {
          // loop again
          rci = (RunnableContainer)containedTask;
        } else {
          return false;
        }
      } else {
        return false;
      }
    }
  }

  /**
   * Checks if the compareTo runnable is contained by the provided 
   * {@link CallableContainerInterface}.  If it's not we check to see if we can continue our 
   * search by looking for another {@link RunnableContainer}, or a {@link CallableContainer}.
   * 
   * @param cci Container to check contents of
   * @param compareTo Callable to compare against
   * @return {@code true} if the callable is contained at some point within the container
   */
  private static boolean isContained(CallableContainer cci, Callable compareTo) {
    while (true) {
      Callable containedTask = cci.getContainedCallable();
      if (containedTask != null) {
        if (containedTask.equals(compareTo)) {
          return true;
        } else if (containedTask instanceof RunnableContainer && 
                   isContained((RunnableContainer)containedTask, compareTo)) {
          return true;
        } else if (containedTask instanceof CallableContainer) {
          // loop again
          cci = (CallableContainer)containedTask;
        } else {
          return false;
        }
      } else {
        return false;
      }
    }
  }
  
  /**
   * Takes in a list of runnable containers, and instead makes a list of the runnables which are 
   * contained in each item of the list.
   * 
   * @since 4.0.0
   * @param sourceList List of runnable containers to get interior runnable from
   * @return A list of runnables which were contained in the source list
   */
  public static List getContainedRunnables(List sourceList) {
    List result = new ArrayList<>(sourceList.size());
    Iterator it = sourceList.iterator();
    while (it.hasNext()) {
      result.add(it.next().getContainedRunnable());
    }
    
    return result;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy