001/* 002 * ============================================================================ 003 * Copyright © 2002-2023 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * 007 * Licensed to the public under the agreements of the GNU Lesser General Public 008 * License, version 3.0 (the "License"). You may obtain a copy of the License at 009 * 010 * http://www.gnu.org/licenses/lgpl.html 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 015 * License for the specific language governing permissions and limitations 016 * under the License. 017 */ 018 019package org.tquadrat.foundation.util.internal; 020 021import static java.util.Spliterator.IMMUTABLE; 022import static java.util.Spliterator.NONNULL; 023import static java.util.Spliterator.SIZED; 024import static org.apiguardian.api.API.Status.INTERNAL; 025import static org.tquadrat.foundation.lang.Objects.hash; 026import static org.tquadrat.foundation.lang.Objects.nonNull; 027import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 028 029import java.lang.reflect.Array; 030import java.util.Iterator; 031import java.util.NoSuchElementException; 032import java.util.Optional; 033import java.util.Spliterator; 034import java.util.Spliterators; 035import java.util.function.Consumer; 036import java.util.stream.Stream; 037import java.util.stream.StreamSupport; 038 039import org.apiguardian.api.API; 040import org.tquadrat.foundation.annotation.ClassVersion; 041import org.tquadrat.foundation.util.HeadTailList; 042 043/** 044 * The implementation for the interface 045 * {@link HeadTailList} 046 * 047 * @param <T> The element type of the list. 048 * 049 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 050 * @version $Id: HeadTailListImpl.java 1060 2023-09-24 19:21:40Z tquadrat $ 051 * @since 0.0.4 052 * 053 * @UMLGraph.link 054 */ 055@ClassVersion( sourceVersion = "$Id: HeadTailListImpl.java 1060 2023-09-24 19:21:40Z tquadrat $" ) 056@API( status = INTERNAL, since = "0.0.4" ) 057public final class HeadTailListImpl<T> implements HeadTailList<T> 058{ 059 /*---------------*\ 060 ====** Inner Classes **==================================================== 061 \*---------------*/ 062 /** 063 * The implementation of the interface 064 * {@link Iterator} 065 * for instances of 066 * {@link HeadTailListImpl} 067 * 068 * @param <T> The element type of the list. 069 * 070 * @author Thomas Thrien - thomas.thrien@tquadrat.org 071 * @version $Id: HeadTailListImpl.java 1060 2023-09-24 19:21:40Z tquadrat $ 072 * @since 0.0.4 073 * 074 * @UMLGraph.link 075 */ 076 @ClassVersion( sourceVersion = "$Id: HeadTailListImpl.java 1060 2023-09-24 19:21:40Z tquadrat $" ) 077 @API( status = INTERNAL, since = "0.0.4" ) 078 private static class IteratorImpl<T> implements Iterator<T> 079 { 080 /*------------*\ 081 ====** Attributes **=================================================== 082 \*------------*/ 083 /** 084 * The current list. 085 */ 086 private HeadTailList<T> m_CurrentList; 087 088 /*--------------*\ 089 ====** Constructors **================================================= 090 \*--------------*/ 091 /** 092 * Creates a new {@code IteratorImpl} instance. 093 * 094 * @param list The list to iterate. 095 */ 096 @SuppressWarnings( "BoundedWildcard" ) 097 public IteratorImpl( final HeadTailList<T> list ) 098 { 099 m_CurrentList = list; 100 } // IteratorImpl() 101 102 /*---------*\ 103 ====** Methods **====================================================== 104 \*---------*/ 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public final boolean hasNext() { return !m_CurrentList.isEmpty(); } 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public T next() 116 { 117 if( m_CurrentList.isEmpty() ) throw new NoSuchElementException( "Empty List!" ); 118 119 @SuppressWarnings( "OptionalGetWithoutIsPresent" ) 120 final var retValue = m_CurrentList.head().get(); 121 m_CurrentList = m_CurrentList.tail(); 122 123 //---* Done *------------------------------------------------------ 124 return retValue; 125 } // next() 126 } 127 // IteratorImpl() 128 129 /*------------*\ 130 ====** Attributes **======================================================= 131 \*------------*/ 132 /** 133 * The hash code for this instance. 134 */ 135 private final int m_HashCode; 136 137 /** 138 * The head element. 139 */ 140 private final T m_Head; 141 142 /** 143 * The size of the list. 144 */ 145 private final int m_Size; 146 147 /** 148 * The tail list. 149 */ 150 private final HeadTailList<T> m_Tail; 151 152 /*------------------------*\ 153 ====** Static Initialisations **=========================================== 154 \*------------------------*/ 155 /** 156 * The empty list. 157 */ 158 private static final HeadTailList<?> m_EmptyList = new HeadTailListImpl<>(); 159 160 /*--------------*\ 161 ====** Constructors **===================================================== 162 \*--------------*/ 163 /** 164 * Creates the empty {@code HeadTailListImpl} instance. 165 */ 166 private HeadTailListImpl() 167 { 168 m_Head = null; 169 m_Tail = this; 170 m_HashCode = 961; 171 m_Size = 0; 172 } // HeadTailListImpl() 173 174 /** 175 * Creates a new {@code HeadTailListImpl} instance. 176 * 177 * @param head The head element. 178 * @param tail The tail list. 179 */ 180 private HeadTailListImpl( final T head, final HeadTailList<T> tail ) 181 { 182 assert nonNull( head ) : "head is null"; 183 assert nonNull( tail ) : "tail is null"; 184 185 m_Head = head; 186 m_Tail = tail; 187 m_HashCode = hash( head, tail ); 188 m_Size = 1 + tail.size(); 189 } // HeadTailListImpl() 190 191 /*---------*\ 192 ====** Methods **========================================================== 193 \*---------*/ 194 /** 195 * {@inheritDoc} 196 */ 197 @Override 198 public final HeadTailList<T> add( final T element ) 199 { 200 final var retValue = new HeadTailListImpl<>( requireNonNullArgument( element, "element" ), this ); 201 202 //---* Done *---------------------------------------------------------- 203 return retValue; 204 } // add() 205 206 /** 207 * <p>{@summary Returns an empty list.}</p> 208 * <p>Each call to this method will return the same instance.</p> 209 * 210 * @param <E> The element type for the list. 211 * @return The empty list. 212 */ 213 @SuppressWarnings( "unchecked" ) 214 public static final <E> HeadTailList<E> empty() { return (HeadTailList<E>) m_EmptyList; } 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override 220 public final boolean equals( final Object o ) 221 { 222 var retValue = this == o; 223 if( !retValue && (o instanceof final HeadTailList<?> other) ) 224 { 225 retValue = (m_Size == other.size()) && (m_HashCode == other.hashCode()); 226 if( retValue ) 227 { 228 //noinspection OptionalGetWithoutIsPresent 229 retValue = m_Head.equals( other.head().get() ) 230 && m_Tail.equals( other.tail() ); 231 } 232 } 233 234 //---* Done *---------------------------------------------------------- 235 return retValue; 236 } // equals() 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override 242 public final void forEachReverse( final Consumer<? super T> action ) 243 { 244 internalForEachReverse( requireNonNullArgument( action, "action" ) ); 245 } // forEach() 246 247 /** 248 * This is the implementation of 249 * {@link #forEachReverse(Consumer)}; 250 * splitting this into two methods spares the null-check on each 251 * invocation. 252 * 253 * @param action The action. 254 */ 255 private final void internalForEachReverse( final Consumer<? super T> action ) 256 { 257 if( nonNull( m_Head ) ) 258 { 259 ((HeadTailListImpl<T>) m_Tail).internalForEachReverse( action ); 260 action.accept( m_Head ); 261 } 262 } // _forEachReverse() 263 264 /** 265 * {@inheritDoc} 266 */ 267 @Override 268 public final int hashCode() { return m_HashCode; } 269 270 /** 271 * {@inheritDoc} 272 */ 273 @Override 274 public final Optional<T> head() { return Optional.ofNullable( m_Head ); } 275 276 /** 277 * {@inheritDoc} 278 */ 279 @Override 280 public final boolean isEmpty() { return this == m_EmptyList; } 281 282 /** 283 * {@inheritDoc} 284 */ 285 @Override 286 public final Iterator<T> iterator() 287 { 288 final var retValue = new IteratorImpl<>( this ); 289 290 //---* Done *---------------------------------------------------------- 291 return retValue; 292 } // iterator() 293 294 /** 295 * {@inheritDoc} 296 */ 297 @Override 298 public final int size() { return m_Size; } 299 300 /** 301 * {@inheritDoc} 302 */ 303 @Override 304 public final Spliterator<T> spliterator() 305 { 306 @SuppressWarnings( "ConstantExpression" ) 307 final var retValue = Spliterators.spliterator( iterator(), (long) m_Size, SIZED | NONNULL | IMMUTABLE ); 308 309 //---* Done *---------------------------------------------------------- 310 return retValue; 311 } // spliterator() 312 313 /** 314 * {@inheritDoc} 315 */ 316 @Override 317 public final Stream<T> stream() 318 { 319 final var retValue = StreamSupport.stream( spliterator(), false ); 320 321 //---* Done *---------------------------------------------------------- 322 return retValue; 323 } // stream() 324 325 /** 326 * {@inheritDoc} 327 */ 328 @Override 329 public final HeadTailList<T> tail() { return m_Tail; } 330 331 /** 332 * {@inheritDoc} 333 */ 334 @Override 335 public final Object [] toArray() 336 { 337 final var retValue = new Object [m_Size]; 338 var index = 0; 339 for( final var t : this ) retValue [index++] = t; 340 341 //---* Done *---------------------------------------------------------- 342 return retValue; 343 } // toArray() 344 345 /** 346 * {@inheritDoc} 347 */ 348 @Override 349 @SuppressWarnings( "unchecked" ) 350 public final T [] toArray( final T [] target ) 351 { 352 final var retValue = requireNonNullArgument( target, "target" ).length >= m_Size ? target : (T []) Array.newInstance( target.getClass().getComponentType(), m_Size ); 353 var index = 0; 354 for( final var t : this ) retValue [index++] = t; 355 356 //---* Done *---------------------------------------------------------- 357 return retValue; 358 } // toArray() 359} 360// class HeadTailListImpl 361 362/* 363 * End of File 364 */