// Copyright 2010 The Apache Software Foundation // // 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 org.apache.tapestry5.func; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; /** * Implementation of {@link Flow} based on an internal array of objects. * * @since 5.2.0 */ class ArrayFlow<T> extends AbstractFlow<T> { private final T[] values; private final int start, count; // Guarded by this private Flow<T> rest; /** Creates an ArrayFlow from the values in the other flow. */ ArrayFlow(Flow<T> flow) { this(toMutableList(flow)); } @SuppressWarnings("unchecked") ArrayFlow(Collection<T> values) { this((T[]) values.toArray()); } ArrayFlow(T[] values) { this(values, 0, values.length); } ArrayFlow(T[] values, int start, int count) { this.values = values; this.start = start; this.count = count; } @Override public Flow<T> each(Worker<? super T> worker) { for (int i = 0; i < count; i++) worker.work(values[start + i]); return this; } @Override public <A> A reduce(Reducer<A, T> reducer, A initial) { assert reducer != null; A accumulator = initial; for (int i = 0; i < count; i++) { T value = values[start + i]; accumulator = reducer.reduce(accumulator, value); } return accumulator; } @Override public List<T> toList() { return Arrays.asList(values).subList(start, start + count); } @Override public Flow<T> reverse() { if (values.length < 2) return this; List<T> newValues = new ArrayList<T>(); newValues.addAll(Arrays.asList(values)); Collections.reverse(newValues); return new ArrayFlow<T>(newValues); } @Override public boolean isEmpty() { return false; } @Override protected List<T> toMutableList() { List<T> result = new ArrayList<T>(count); for (int i = 0; i < count; i++) { result.add(values[start + i]); } return result; } @Override @SuppressWarnings("unchecked") public Flow<T> sort() { if (values.length < 2) return this; List<Comparable> newValues = (List<Comparable>) toMutableList(); Collections.sort(newValues); return new ArrayFlow<T>((List<T>) newValues); } @Override public Flow<T> sort(Comparator<T> comparator) { assert comparator != null; if (values.length < 2) return this; List<T> newValues = toMutableList(); Collections.sort(newValues, comparator); return new ArrayFlow<T>(newValues); } @Override public Iterator<T> iterator() { return toList().iterator(); } @Override public T first() { return values[start]; } @Override public synchronized Flow<T> rest() { if (rest == null) rest = buildRest(); return rest; } private Flow<T> buildRest() { if (count < 2) return F.emptyFlow(); return new ArrayFlow<T>(values, start + 1, count - 1); } @Override public int count() { return count; } @Override public Flow<T> take(int length) { if (length < 1) return F.emptyFlow(); return new ArrayFlow<T>(values, start, Math.min(count, length)); } @Override public Flow<T> drop(int length) { assert length >= 0; if (length == 0) return this; if (length >= count) return F.emptyFlow(); return new ArrayFlow<T>(values, start + length, count - length); } }