/** * * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); You may not * use this file except in compliance with the License. You may obtain a copy of * the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.speedment.runtime.core.internal.manager.sql; import com.speedment.runtime.core.component.sql.SqlStreamOptimizer; import com.speedment.runtime.core.component.sql.SqlStreamOptimizerComponent; import com.speedment.runtime.core.component.sql.SqlStreamOptimizerInfo; import com.speedment.runtime.core.component.sql.override.SqlStreamTerminatorComponent; import com.speedment.runtime.core.db.AsynchronousQueryResult; import com.speedment.runtime.core.internal.stream.builder.pipeline.DoublePipeline; import com.speedment.runtime.core.internal.stream.builder.pipeline.IntPipeline; import com.speedment.runtime.core.internal.stream.builder.pipeline.LongPipeline; import com.speedment.runtime.core.internal.stream.builder.pipeline.ReferencePipeline; import com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminator; import com.speedment.runtime.core.stream.Pipeline; import com.speedment.runtime.core.util.StreamComposition; import java.util.Comparator; import java.util.Iterator; import static java.util.Objects.requireNonNull; import java.util.Optional; import java.util.PrimitiveIterator; import java.util.Spliterator; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.IntFunction; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collector; /** * A class that will terminate ENTITY streams. ENTITY is the original type. * * Type T is the final type after stream mappings. * * * @author pemi * @param <ENTITY> the entity type of the original stream, e.g. hares.stream() * is of type Hare * */ public final class SqlStreamTerminator<ENTITY> implements StreamTerminator { protected final String UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED = "This method has been disabled for this Stream type " + "because improper use will lead to resources not being freed up. " + "We regret any inconvenience caused by this. " + "If you want to concatenate two or more stream, please use the " + StreamComposition.class.getName() + "#concatAndAutoClose() method instead." + "Note: If you want to enable this functionality, please use the .withAllowStreamIteratorAndSpliterator() application builder " + "method. Be aware though, you are then responsible for closing the stream implicitly after use, ALWAYS"; private final SqlStreamTerminatorComponent sqlStreamTerminatorComponent; private final SqlStreamOptimizerComponent sqlStreamOptimizerComponent; private final SqlStreamOptimizerInfo<ENTITY> info; private final AsynchronousQueryResult<ENTITY> asynchronousQueryResult; private final boolean allowIteratorAndSpliterator; public SqlStreamTerminator( final SqlStreamOptimizerInfo<ENTITY> info, final AsynchronousQueryResult<ENTITY> asynchronousQueryResult, final SqlStreamOptimizerComponent sqlStreamOptimizerComponent, final SqlStreamTerminatorComponent sqlStreamTerminatorComponent, final boolean allowIteratorAndSpliterator ) { this.info = requireNonNull(info); this.asynchronousQueryResult = requireNonNull(asynchronousQueryResult); this.sqlStreamOptimizerComponent = requireNonNull(sqlStreamOptimizerComponent); this.sqlStreamTerminatorComponent = requireNonNull(sqlStreamTerminatorComponent); this.allowIteratorAndSpliterator = allowIteratorAndSpliterator; } //Todo: Remove this and split up responsibility public AsynchronousQueryResult<ENTITY> getAsynchronousQueryResult() { return asynchronousQueryResult; } @Override public <P extends Pipeline> P optimize(final P initialPipeline) { requireNonNull(initialPipeline); final SqlStreamOptimizer<ENTITY> optimizer = sqlStreamOptimizerComponent.get(initialPipeline, info.getDbmsType()); return optimizer.optimize(initialPipeline, info, asynchronousQueryResult); } @Override public <T> void forEach(ReferencePipeline<T> pipeline, Consumer<? super T> action) { sqlStreamTerminatorComponent.<ENTITY>getForEachTerminator().apply(info, this, pipeline, action); } @Override public <T> void forEachOrdered(ReferencePipeline<T> pipeline, Consumer<? super T> action) { sqlStreamTerminatorComponent.<ENTITY>getForEachOrderedTerminator().apply(info, this, pipeline, action); } @Override public <T> Object[] toArray(ReferencePipeline<T> pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getToArrayTerminator().apply(info, this, pipeline); } @Override public <T, A> A[] toArray(ReferencePipeline<T> pipeline, IntFunction<A[]> generator) { return sqlStreamTerminatorComponent.<ENTITY>getToArrayGeneratorTerminator().apply(info, this, pipeline, generator); } @Override public <T> T reduce(ReferencePipeline<T> pipeline, T identity, BinaryOperator<T> accumulator) { return sqlStreamTerminatorComponent.<ENTITY>getReduceIdentityTerminator().apply(info, this, pipeline, identity, accumulator); } @Override public <T, U> U reduce(ReferencePipeline<T> pipeline, U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) { return sqlStreamTerminatorComponent.<ENTITY>getReduceIdentityCombinerTerminator().apply(info, this, pipeline, identity, accumulator, combiner); } @Override public <T> Optional<T> reduce(ReferencePipeline<T> pipeline, BinaryOperator<T> accumulator) { return sqlStreamTerminatorComponent.<ENTITY>getReduceTerminator().apply(info, this, pipeline, accumulator); } @Override public <T, R> R collect(ReferencePipeline<T> pipeline, Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) { return sqlStreamTerminatorComponent.<ENTITY>getCollectSupplierAccumulatorCombinerTerminator().apply(info, this, pipeline, supplier, accumulator, combiner); } @Override public <T, R, A> R collect(ReferencePipeline<T> pipeline, Collector<? super T, A, R> collector) { return sqlStreamTerminatorComponent.<ENTITY>getCollectTerminator().apply(info, this, pipeline, collector); } @Override public <T> Optional<T> min(ReferencePipeline<T> pipeline, Comparator<? super T> comparator) { return sqlStreamTerminatorComponent.<ENTITY>getMinTerminator().apply(info, this, pipeline, comparator); } @Override public <T> Optional<T> max(ReferencePipeline<T> pipeline, Comparator<? super T> comparator) { return sqlStreamTerminatorComponent.<ENTITY>getMaxTerminator().apply(info, this, pipeline, comparator); } @Override public <T> long count(ReferencePipeline<T> pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getCountTerminator().apply(info, this, pipeline); } @Override public <T> boolean anyMatch(ReferencePipeline<T> pipeline, Predicate<? super T> predicate) { return sqlStreamTerminatorComponent.<ENTITY>getAnyMatchTerminator().apply(info, this, pipeline, predicate); } @Override public <T> boolean allMatch(ReferencePipeline<T> pipeline, Predicate<? super T> predicate) { return sqlStreamTerminatorComponent.<ENTITY>getAllMatchTerminator().apply(info, this, pipeline, predicate); } @Override public <T> boolean noneMatch(ReferencePipeline<T> pipeline, Predicate<? super T> predicate) { return sqlStreamTerminatorComponent.<ENTITY>getNoneMatchTerminator().apply(info, this, pipeline, predicate); } @Override public <T> Optional<T> findAny(ReferencePipeline<T> pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getFindAnyTerminator().apply(info, this, pipeline); } @Override public <T> Optional<T> findFirst(ReferencePipeline<T> pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getFindFirstTerminator().apply(info, this, pipeline); } @Override public <T> Iterator<T> iterator(ReferencePipeline<T> pipeline) { if (allowIteratorAndSpliterator) { return sqlStreamTerminatorComponent.<ENTITY>getIteratorTerminator().apply(info, this, pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } @Override public <T> Spliterator<T> spliterator(ReferencePipeline<T> pipeline) { if (allowIteratorAndSpliterator) { return sqlStreamTerminatorComponent.<ENTITY>getSpliteratorTerminator().apply(info, this, pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } ///////////// double @Override public long count(DoublePipeline pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getDoubleCountTerminator().apply(info, this, pipeline); } // Todo: Introduce delegator @Override public PrimitiveIterator.OfDouble iterator(DoublePipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.iterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } // Todo: Introduce delegator @Override public Spliterator.OfDouble spliterator(DoublePipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.spliterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } ///////////// int @Override public long count(IntPipeline pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getIntCountTerminator().apply(info, this, pipeline); } // Todo: Introduce delegator @Override public PrimitiveIterator.OfInt iterator(IntPipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.iterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } // Todo: Introduce delegator @Override public Spliterator.OfInt spliterator(IntPipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.spliterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } ///////////// long @Override public long count(LongPipeline pipeline) { return sqlStreamTerminatorComponent.<ENTITY>getLongCountTerminator().apply(info, this, pipeline); } // Todo: Introduce delegator @Override public PrimitiveIterator.OfLong iterator(LongPipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.iterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } // Todo: Introduce delegator @Override public Spliterator.OfLong spliterator(LongPipeline pipeline) { if (allowIteratorAndSpliterator) { return StreamTerminator.super.spliterator(pipeline); } throw new UnsupportedOperationException(UNSUPPORTED_BECAUSE_OF_CLOSE_MAY_NOT_BE_CALLED); } }