001/* 002 * ============================================================================ 003 * Copyright © 2014 by Dominic Fox. 004 * All Rights Reserved. 005 * ============================================================================ 006 * The MIT License (MIT) 007 * 008 * Permission is hereby granted, free of charge, to any person obtaining a copy 009 * of this software and associated documentation files (the "Software"), to 010 * deal in the Software without restriction, including without limitation the 011 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 012 * sell copies of the Software, and to permit persons to whom the Software is 013 * furnished to do so, subject to the following conditions: 014 * 015 * The above copyright notice and this permission notice shall be included in 016 * all copies or substantial portions of the Software. 017 * 018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 020 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 023 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 024 * IN THE SOFTWARE. 025 */ 026 027package org.tquadrat.foundation.stream.internal; 028 029import static org.apiguardian.api.API.Status.INTERNAL; 030import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 031 032import java.util.Optional; 033import java.util.Spliterator; 034import java.util.function.Consumer; 035import java.util.function.Function; 036 037import org.apiguardian.api.API; 038import org.tquadrat.foundation.annotation.ClassVersion; 039 040/** 041 * An implementation of 042 * {@link Spliterator} 043 * that which takes a seed value and applies a generator to create the next 044 * value, feeding each new value back into the generator to create subsequent 045 * values. If the generator returns 046 * {@link Optional#empty()}, 047 * then there are no more values. 048 * 049 * @author Dominic Fox 050 * @modified Thomas Thrien - thomas.thrien@tquadrat.org 051 * @version $Id: UnfoldSpliterator.java 1060 2023-09-24 19:21:40Z tquadrat $ 052 * @since 0.0.7 053 * 054 * @param <T> The type of the stream elements. 055 * 056 * @UMLGraph.link 057 */ 058@ClassVersion( sourceVersion = "$Id: UnfoldSpliterator.java 1060 2023-09-24 19:21:40Z tquadrat $" ) 059@API( status = INTERNAL, since = "0.0.7" ) 060public final class UnfoldSpliterator<T> implements Spliterator<T> 061{ 062 /*------------*\ 063 ====** Attributes **======================================================= 064 \*------------*/ 065 /** 066 * The current value. 067 */ 068 @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" ) 069 private Optional<T> m_Current; 070 071 /** 072 * The generator. 073 */ 074 private final Function<T,Optional<T>> m_Generator; 075 076 /*--------------*\ 077 ====** Constructors **===================================================== 078 \*--------------*/ 079 /** 080 * Creates a new {@code UnfoldSpliterator} instance. 081 * 082 * @param seed The initial value;may be {@code null}. 083 * @param generator The generator. 084 */ 085 private UnfoldSpliterator( final T seed, final Function<T,Optional<T>> generator ) 086 { 087 m_Current = Optional.of( seed ); 088 m_Generator = requireNonNullArgument( generator, "generator" ); 089 } // UnfoldSpliterator() 090 091 /*---------*\ 092 ====** Methods **========================================================== 093 \*---------*/ 094 /** 095 * {@inheritDoc} 096 */ 097 @Override 098 public final int characteristics() 099 { 100 @SuppressWarnings( "ConstantExpression" ) 101 final var retValue = IMMUTABLE & NONNULL & ORDERED; 102 103 //---* Done *---------------------------------------------------------- 104 return retValue; 105 } // characteristics() 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 public final long estimateSize() { return Long.MAX_VALUE; } 112 113 /** 114 * Factory for instances of {@code UnfoldSpliterator}. 115 * 116 * @param <T> The type of the stream elements. 117 * @param seed The initial value;may be {@code null}. 118 * @param generator The generator. 119 * @return The new instance. 120 */ 121 public static final <T> UnfoldSpliterator<T> over( final T seed, final Function<T,Optional<T>> generator ) 122 { 123 final var retValue = new UnfoldSpliterator<>( seed, generator ); 124 125 //---* Done *---------------------------------------------------------- 126 return retValue; 127 } // over 128 129 /** 130 * {@inheritDoc} 131 */ 132 @Override 133 public final boolean tryAdvance( final Consumer<? super T> action ) 134 { 135 m_Current.ifPresent( action ); 136 m_Current = m_Current.flatMap( m_Generator ); 137 final var retValue = m_Current.isPresent(); 138 139 //---* Done *---------------------------------------------------------- 140 return retValue; 141 } // tryAdvance() 142 143 /** 144 * {@inheritDoc} 145 */ 146 @Override 147 public Spliterator<T> trySplit() { return null; } 148} 149// class UnfoldSpliterator 150 151/* 152 * End of File 153 */