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 org.apiguardian.api.API; 030import org.tquadrat.foundation.annotation.ClassVersion; 031 032import java.util.Spliterator; 033import java.util.function.Consumer; 034import java.util.function.Predicate; 035 036import static org.apiguardian.api.API.Status.INTERNAL; 037import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 038 039/** 040 * An implementation of 041 * {@link Spliterator} 042 * that takes elements from a stream while the given 043 * {@link Predicate Predicate} 044 * returns {@code true}. 045 * 046 * @author Dominic Fox 047 * @modified Thomas Thrien - thomas.thrien@tquadrat.org 048 * @version $Id: TakeWhileSpliterator.java 1119 2024-03-16 09:03:57Z tquadrat $ 049 * @since 0.0.7 050 * 051 * @param <T> The type of the stream elements. 052 * 053 * @UMLGraph.link 054 */ 055@ClassVersion( sourceVersion = "$Id: TakeWhileSpliterator.java 1119 2024-03-16 09:03:57Z tquadrat $" ) 056@API( status = INTERNAL, since = "0.0.7" ) 057public final class TakeWhileSpliterator<T> implements Spliterator<T> 058{ 059 /*------------*\ 060 ====** Attributes **======================================================= 061 \*------------*/ 062 /** 063 * The condition for the spliterator. 064 */ 065 private final Predicate<T> m_Condition; 066 067 /** 068 * Flag that indicates whether the condition still returns {@code true}. 069 */ 070 private boolean m_ConditionHolds = true; 071 072 /** 073 * The source. 074 */ 075 private final Spliterator<T> m_Source; 076 077 /*--------------*\ 078 ====** Constructors **===================================================== 079 \*--------------*/ 080 /** 081 * Creates a new {@code TakeWhileSpliterator} instance. 082 * 083 * @param source The source. 084 * @param condition The condition for the new instance. 085 */ 086 private TakeWhileSpliterator( final Spliterator<T> source, final Predicate<T> condition ) 087 { 088 m_Source = requireNonNullArgument( source, "source" ); 089 m_Condition = requireNonNullArgument( condition, "condition" ); 090 } // TakeWhileSpliterator() 091 092 /*---------*\ 093 ====** Methods **========================================================== 094 \*---------*/ 095 /** 096 * {@inheritDoc} 097 */ 098 @Override 099 public final int characteristics() 100 { 101 @SuppressWarnings( "ConstantExpression" ) 102 final var retValue = m_Source.characteristics() & ~SIZED; 103 104 //---* Done *---------------------------------------------------------- 105 return retValue; 106 } // characteristics() 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public final long estimateSize() { return m_ConditionHolds ? m_Source.estimateSize() : 0; } 113 114 /** 115 * Factory method for instances of {@code TakeWhileSpliterator}. 116 * 117 * @param <T> The type of the stream elements. 118 * @param source The source. 119 * @param condition The condition for the new instance. 120 * @return The new instance. 121 */ 122 public static final <T> TakeWhileSpliterator<T> over( final Spliterator<T> source, final Predicate<T> condition ) 123 { 124 final var retValue = new TakeWhileSpliterator<>( source, condition ); 125 126 //---* Done *---------------------------------------------------------- 127 return retValue; 128 } // over() 129 130 /** 131 * {@inheritDoc} 132 */ 133 @Override 134 public final boolean tryAdvance( final Consumer<? super T> action ) 135 { 136 final var retValue = m_ConditionHolds 137 && m_Source.tryAdvance( e -> 138 { 139 //noinspection NestedAssignment,PointlessBooleanExpression 140 if( (m_ConditionHolds = m_Condition.test( e )) == true ) 141 { 142 action.accept( e ); 143 } 144 }); 145 146 //---* Done *---------------------------------------------------------- 147 return retValue; 148 } // tryAdvance() 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override 154 public final Spliterator<T> trySplit(){ return null; } 155} 156// class TakeWhileSpliterator 157 158/* 159 * End of File 160 */