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

org.infinispan.commons.util.Closeables Maven / Gradle / Ivy

There is a newer version: 15.1.0.Dev04
Show newest version
package org.infinispan.commons.util;

import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.BaseStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.reactivestreams.Publisher;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.disposables.Disposable;

/**
 * This class consists exclusively of static methods that operate on or return closeable interfaces.  This is helpful
 * when wanting to change a given interface to an appropriate closeable interface.
 * @since 8.0
 */
public class Closeables {
   private Closeables() { }

   /**
    * Takes a provided closeable iterator and wraps it appropriately so it can be used as a closeable spliterator that
    * will close the iterator when the spliterator is closed.
    * @param iterator The closeable iterator to change to a spliterator
    * @param size The approximate size of the iterator.  If no size is known {@link Long#MAX_VALUE} should be passed
    * @param characteristics The characteristics of the given spliterator as defined on the {@link Spliterator}
    *                        interface
    * @param  The type that is the same between the iterator and spliterator
    * @return A spliterator that when closed will close the provided iterator
    */
   public static  CloseableSpliterator spliterator(CloseableIterator iterator, long size,
                                                  int characteristics) {
      return new CloseableIteratorAsCloseableSpliterator<>(iterator, size, characteristics);
   }

   /**
    * Creates a closeable spliterator from the given spliterator that does nothing when close is called.
    * @param spliterator The spliterator to wrap to allow it to become a closeable spliterator.
    * @param  The type of the spliterators
    * @return A spliterator that does nothing when closed
    */
   public static  CloseableSpliterator spliterator(Spliterator spliterator) {
      if (spliterator instanceof CloseableSpliterator) {
         return (CloseableSpliterator) spliterator;
      }
      return new SpliteratorAsCloseableSpliterator<>(spliterator);
   }

   /**
    * Creates a closeable spliterator that when closed will close the underlying stream as well
    * @param stream The stream to change into a closeable spliterator
    * @param  The type of the stream
    * @return A spliterator that when closed will also close the underlying stream
    */
   public static  CloseableSpliterator spliterator(BaseStream> stream) {
      Spliterator spliterator = stream.spliterator();
      if (spliterator instanceof CloseableSpliterator) {
         return (CloseableSpliterator) spliterator;
      }
      return new StreamToCloseableSpliterator<>(stream, spliterator);
   }

   /**
    * Creates a closeable iterator that when closed will close the underlying stream as well
    * @param stream The stream to change into a closeable iterator
    * @param  The type of the stream
    * @return An iterator that when closed will also close the underlying stream
    */
   public static  CloseableIterator iterator(BaseStream> stream) {
      Iterator iterator = stream.iterator();
      if (iterator instanceof CloseableIterator) {
         return (CloseableIterator) iterator;
      }
      return new StreamToCloseableIterator<>(stream, iterator);
   }

   /**
    * Creates a closeable iterator from the given iterator that does nothing when close is called.
    * @param iterator The iterator to wrap to allow it to become a closeable iterator
    * @param  The type of the iterators
    * @return An iterator that does nothing when closed
    */
   public static  CloseableIterator iterator(Iterator iterator) {
      if (iterator instanceof CloseableIterator) {
         return (CloseableIterator) iterator;
      }
      return new IteratorAsCloseableIterator<>(iterator);
   }

   /**
    * Creates a stream that when closed will also close the underlying spliterator
    * @param spliterator spliterator to back the stream and subsequently close
    * @param parallel whether or not the returned stream is parallel or not
    * @param  the type of the stream
    * @return the stream to use
    */
   public static  Stream stream(CloseableSpliterator spliterator, boolean parallel) {
      Stream stream = StreamSupport.stream(spliterator, parallel);
      stream.onClose(spliterator::close);
      return stream;
   }

   /**
    * Creates a stream that when closed will also close the underlying iterator
    * @param iterator iterator to back the stream and subsequently close
    * @param parallel whether or not the returned stream is parallel or not
    * @param size the size of the iterator if known, otherwise {@link Long#MAX_VALUE} should be passed.
    * @param characteristics the characteristics of the iterator to be used
    * @param  the type of the stream
    * @return the stream to use
    */
   public static  Stream stream(CloseableIterator iterator, boolean parallel, long size, int characteristics) {
      Stream stream = StreamSupport.stream(Spliterators.spliterator(iterator, size, characteristics), parallel);
      stream.onClose(iterator::close);
      return stream;
   }

   private static class IteratorAsCloseableIterator implements CloseableIterator {
      private final Iterator iterator;

      public IteratorAsCloseableIterator(Iterator iterator) {
         this.iterator = iterator;
      }

      @Override
      public void close() {
         // This does nothing
      }

      @Override
      public boolean hasNext() {
         return iterator.hasNext();
      }

      @Override
      public E next() {
         return iterator.next();
      }

      @Override
      public void remove() {
         iterator.remove();
      }
   }

   private static class SpliteratorAsCloseableSpliterator implements CloseableSpliterator {
      private final Spliterator spliterator;

      public SpliteratorAsCloseableSpliterator(Spliterator spliterator) {
         this.spliterator = spliterator;
      }

      @Override
      public void close() {

      }

      @Override
      public boolean tryAdvance(Consumer action) {
         return spliterator.tryAdvance(action);
      }

      @Override
      public Spliterator trySplit() {
         return spliterator.trySplit();
      }

      @Override
      public long estimateSize() {
         return spliterator.estimateSize();
      }

      @Override
      public int characteristics() {
         return spliterator.characteristics();
      }
   }

   private static class CloseableIteratorAsCloseableSpliterator extends SpliteratorAsCloseableSpliterator {
      private final CloseableIterator iterator;

      CloseableIteratorAsCloseableSpliterator(CloseableIterator iterator, long size, int characteristics) {
         super(Spliterators.spliterator(iterator, size, characteristics));
         this.iterator = iterator;
      }

      @Override
      public void close() {
         this.iterator.close();
      }
   }

   private static class StreamToCloseableIterator extends IteratorAsCloseableIterator {
      private final BaseStream> stream;

      public StreamToCloseableIterator(BaseStream> stream, Iterator iterator) {
         super(iterator);
         this.stream = stream;
      }

      @Override
      public void close() {
         stream.close();
      }
   }

   private static class StreamToCloseableSpliterator extends SpliteratorAsCloseableSpliterator {
      private final BaseStream> stream;

      public StreamToCloseableSpliterator(BaseStream> stream, Spliterator spliterator) {
         super(spliterator);
         this.stream = stream;
      }

      @Override
      public void close() {
         stream.close();
      }
   }

   /**
    * Converts a {@link Publisher} to a {@link CloseableIterator} by utilizing items fetched into an array and
    * refetched as they are consumed from the iterator. The iterator when closed will also close the underlying
    * {@link org.reactivestreams.Subscription} when subscribed to the publisher.
    * @param publisher the publisher to convert
    * @param fetchSize how many entries to hold in memory at once in preparation for the iterators consumption
    * @param  value type
    * @return an iterator that when closed will cancel the subscription
    */
   public static  CloseableIterator iterator(Publisher publisher, int fetchSize) {
      // This iterator from rxjava3 implements Disposable akin to Closeable
      Flowable flowable = Flowable.fromPublisher(publisher);
      @SuppressWarnings("checkstyle:forbiddenmethod")
      Iterable iterable = flowable.blockingIterable(fetchSize);
      Iterator iterator = iterable.iterator();
      return new CloseableIterator() {
         @Override
         public void close() {
            ((Disposable) iterator).dispose();
         }

         @Override
         public boolean hasNext() {
            return iterator.hasNext();
         }

         @Override
         public E next() {
            return iterator.next();
         }
      };
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy