Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.dm.rf.android.internal.AbstractSparseIterable Maven / Gradle / Ivy
/**
* 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.github.dm.rf.android.internal;
import com.github.dm.rf.android.filter.AdvancedFilter;
import com.github.dm.rf.android.filter.Filter;
import com.github.dm.rf.android.filter.FilterBuilder;
import com.github.dm.rf.android.filter.Filters;
import com.github.dm.rf.android.iterator.BooleanSparseIterable;
import com.github.dm.rf.android.iterator.ElementSparseIterable;
import com.github.dm.rf.android.iterator.IntSparseIterable;
import com.github.dm.rf.android.iterator.LongSparseIterable;
import com.github.dm.rf.android.iterator.SparseIterable;
import com.github.dm.rf.android.translator.Translator;
import com.github.dm.rf.android.utils.BinarySearch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Abstract base implementation of a {@link SparseIterable}.
*
* This class implements the common logic shared among all the sparse iterable specializations,
* delegating to subclasses the handling of low level data.
*
* Created by davide-maestroni on 3/10/14.
*
* @param the element type.
*/
abstract class AbstractSparseIterable implements SparseIterable {
private FilterBuilderImpl, E> mExclusionBuilder;
private ArrayList> mFilters = new ArrayList>();
private FilterBuilderImpl, E> mInclusionBuilder;
public AbstractSparseIterable() {
}
AbstractSparseIterable(final AbstractSparseIterable other) {
mFilters.addAll(other.mFilters);
}
@Override
public boolean any(final Condition condition) {
int count = 0;
final SparseIterator iterator = iterator();
while (iterator.hasNext()) {
if (condition.onNext(iterator.next(), count++, iterator.originalIndex())) {
return true;
}
}
return false;
}
@Override
public FilterBuilder extends SparseIterable, E> but() {
if (mExclusionBuilder == null) {
mExclusionBuilder = new FilterBuilderImpl, E>(this, false);
}
return mExclusionBuilder;
}
@Override
public SparseIterable but(final Filter filter) {
mFilters.add(Filters.inverse(Filters.advanced(filter)));
return this;
}
@Override
public boolean contains(final Object element) {
return firstPositionOf(element) >= 0;
}
@Override
public boolean containsAll(final Object... elements) {
for (final Object element : elements) {
if (firstPositionOf(element) < 0) {
return false;
}
}
return true;
}
@Override
public boolean containsAll(final Iterable> elements) {
for (final Object element : elements) {
if (firstPositionOf(element) < 0) {
return false;
}
}
return true;
}
@Override
public boolean containsAny(final Object... elements) {
for (final Object element : elements) {
if (firstPositionOf(element) >= 0) {
return true;
}
}
return false;
}
@Override
public boolean containsAny(final Iterable> elements) {
for (final Object element : elements) {
if (firstPositionOf(element) >= 0) {
return true;
}
}
return false;
}
@Override
public int countOf(final Object element) {
int count = 0;
if (element == null) {
for (E e : this) {
if (e == null) {
++count;
}
}
} else {
for (E e : this) {
if (element.equals(e)) {
++count;
}
}
}
return count;
}
@Override
public SparseIterable doWhile(final Condition condition) {
int count = 0;
final SparseIterator iterator = iterator();
while (iterator.hasNext()) {
if (!condition.onNext(iterator.next(), count++, iterator.originalIndex())) {
return this;
}
}
return this;
}
@Override
public boolean each(final Condition condition) {
int count = 0;
final SparseIterator iterator = iterator();
while (iterator.hasNext()) {
if (!condition.onNext(iterator.next(), count++, iterator.originalIndex())) {
return false;
}
}
return true;
}
@Override
public int firstIndexOf(final Object element) {
if (element == null) {
return -1;
}
final SparseIterator iterator = filteredIterator(false);
while (iterator.hasNext()) {
final E next = iterator.next();
if (element.equals(next)) {
return iterator.originalIndex();
}
}
return -1;
}
@Override
public int firstPositionOf(final Object element) {
if (element == null) {
return -1;
}
int i = 0;
for (final E e : this) {
if (element.equals(e)) {
return i;
}
++i;
}
return -1;
}
@Override
public SparseIterable forEach(final Action action) {
int count = 0;
final SparseIterator iterator = iterator();
while (iterator.hasNext()) {
action.onNext(iterator.next(), count++, iterator.originalIndex());
}
return this;
}
@Override
public boolean isEqualTo(final Collection> collection) {
int count = 0;
for (final E element : this) {
if (!collection.contains(element)) {
return false;
}
++count;
}
return (count == collection.size());
}
@Override
public boolean isStrictlyEqualTo(final Iterable> iterable) {
final Iterator> iterator = iterable.iterator();
for (final E element : this) {
if (!iterator.hasNext()) {
return false;
}
if (element == null) {
if (iterator.next() != null) {
return false;
}
} else if (!element.equals(iterator.next())) {
return false;
}
}
return true;
}
@Override
public FilterBuilder extends SparseIterable, E> only() {
if (mInclusionBuilder == null) {
mInclusionBuilder = new FilterBuilderImpl, E>(this, true);
}
return mInclusionBuilder;
}
@Override
public SparseIterable only(final Filter filter) {
mFilters.add(Filters.advanced(filter));
return this;
}
@Override
public SparseIterable remove() {
final SparseIterator iterator = iterator();
while (iterator.hasNext()) {
iterator.next();
iterator.remove();
}
clearFilters();
return this;
}
@Override
public SparseIterable retain() {
final SparseIterator iterator = filteredIterator(false);
final SnapshotFilter filter = new SnapshotFilter();
filter.initialize(iterator);
final FilteredIterator filteredIterator =
new FilteredIterator(rawIterator(false), Filters.inverse(filter));
while (filteredIterator.hasNext()) {
filteredIterator.next();
filteredIterator.remove();
}
clearFilters();
return this;
}
@Override
public SparseIterable reverse() {
mFilters.add(new SnapshotFilter());
return this;
}
@Override
public BooleanSparseIterable toBooleans(final Translator translator) {
return new BooleanTranslatedIterable(copy(), translator);
}
@Override
public IntSparseIterable toIntegers(final Translator translator) {
return new IntTranslatedIterable(copy(), translator);
}
@Override
public LongSparseIterable toLongs(final Translator translator) {
return new LongTranslatedIterable(copy(), translator);
}
@Override
public SparseIterator iterator() {
return filteredIterator(false);
}
protected void clearFilters() {
boolean isReverse = false;
for (final AdvancedFilter filter : mFilters) {
if (filter instanceof SnapshotFilter) {
isReverse = !isReverse;
}
}
mFilters.clear();
if (isReverse) {
reverse();
}
}
/**
* Returns a copy of this instance.
* The backing sparse collection is retained in the process.
*
* @return the copy instance.
*/
protected abstract AbstractSparseIterable copy();
/**
* Returns the base iterator on which to apply this instance filters.
*
* @param isReverse whether to loop in reverse order.
* @return the iterator instance.
*/
protected abstract SparseIterator createIterator(boolean isReverse);
protected SparseIterator filteredIterator(final boolean isReverse) {
SparseIterator iterator = createIterator(isReverse);
final ArrayList> filters = mFilters;
if (filters.isEmpty()) {
return iterator;
}
boolean reverse = isReverse;
boolean skipFilter = true;
for (final AdvancedFilter filter : filters) {
if (filter instanceof SnapshotFilter) {
reverse = !reverse;
if (!skipFilter) {
filter.initialize(iterator);
}
iterator = createIterator(reverse);
iterator.reset();
} else {
filter.initialize(iterator);
iterator.reset();
skipFilter = false;
}
if (!skipFilter) {
iterator = new FilteredIterator(iterator, filter);
}
}
return iterator;
}
/**
* Returns the very basic iterator, without any filter applied, which loops through all the
* elements of the backing sparse collection.
*
* @param isReverse whether to loop in reverse order.
* @return the iterator instance.
*/
protected abstract SparseIterator rawIterator(boolean isReverse);
ElementSparseIterable toElements(final Translator translator) {
return new ElementTranslatedIterable(copy(), translator);
}
private static class BooleanTranslatedIterable extends BooleanSparseIterableImpl {
private final AbstractSparseIterable mIterable;
private final Translator mTranslator;
public BooleanTranslatedIterable(final AbstractSparseIterable iterable,
final Translator translator) {
mIterable = iterable;
mTranslator = translator;
}
BooleanTranslatedIterable(final BooleanTranslatedIterable other) {
super(other);
mIterable = other.mIterable;
mTranslator = other.mTranslator;
}
@Override
protected void clearFilters() {
super.clearFilters();
mIterable.clearFilters();
}
@Override
protected BooleanTranslatedIterable copy() {
return new BooleanTranslatedIterable(this);
}
@Override
protected SparseIterator createIterator(final boolean isReverse) {
final AbstractSparseIterable iterable;
if (isReverse) {
iterable = mIterable.copy();
iterable.reverse();
} else {
iterable = mIterable;
}
final SparseIterator iterator = iterable.filteredIterator(false);
return new TranslatedIterator(iterator, mTranslator);
}
@Override
protected SparseIterator rawIterator(final boolean isReverse) {
final SparseIterator iterator = mIterable.rawIterator(isReverse);
return new TranslatedIterator(iterator, mTranslator);
}
}
private static class ElementTranslatedIterable extends ElementSparseIterableImpl {
private final AbstractSparseIterable mIterable;
private final Translator mTranslator;
public ElementTranslatedIterable(final AbstractSparseIterable iterable,
final Translator translator) {
mIterable = iterable;
mTranslator = translator;
}
ElementTranslatedIterable(final ElementTranslatedIterable other) {
super(other);
mIterable = other.mIterable;
mTranslator = other.mTranslator;
}
@Override
protected ElementTranslatedIterable copy() {
return new ElementTranslatedIterable(this);
}
@Override
protected void clearFilters() {
super.clearFilters();
mIterable.clearFilters();
}
@Override
protected SparseIterator createIterator(final boolean isReverse) {
final AbstractSparseIterable iterable;
if (isReverse) {
iterable = mIterable.copy();
iterable.reverse();
} else {
iterable = mIterable;
}
final SparseIterator iterator = iterable.filteredIterator(false);
return new TranslatedIterator(iterator, mTranslator);
}
@Override
protected SparseIterator rawIterator(final boolean isReverse) {
final SparseIterator iterator = mIterable.rawIterator(isReverse);
return new TranslatedIterator(iterator, mTranslator);
}
}
/**
* Wrapper of a {@link SparseIterator} instance on which the specified filter is applied.
*
* @param the element type.
*/
private static class FilteredIterator implements SparseIterator {
private final Filter mFilter;
private final SparseIterator mIterator;
private int mCount;
private E mElement;
private boolean mHasNext;
public FilteredIterator(final SparseIterator wrapped, final Filter filter) {
mIterator = wrapped;
mFilter = filter;
}
@Override
public boolean hasNext() {
if (mHasNext) {
return true;
}
final Filter filter = mFilter;
final SparseIterator iterator = mIterator;
while (iterator.hasNext()) {
final E element = iterator.next();
if (filter.matches(element, mCount++, iterator.originalIndex())) {
mHasNext = true;
mElement = element;
return true;
}
}
return false;
}
@Override
public int originalIndex() {
return mIterator.originalIndex();
}
@Override
public void reset() {
mCount = 0;
mHasNext = false;
mElement = null;
mIterator.reset();
}
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
mHasNext = false;
final E element = mElement;
mElement = null;
return element;
}
@Override
public void remove() {
mIterator.remove();
}
}
private static class IntTranslatedIterable extends IntSparseIterableImpl {
private final AbstractSparseIterable mIterable;
private final Translator mTranslator;
public IntTranslatedIterable(final AbstractSparseIterable iterable,
final Translator translator) {
mIterable = iterable;
mTranslator = translator;
}
IntTranslatedIterable(final IntTranslatedIterable other) {
super(other);
mIterable = other.mIterable;
mTranslator = other.mTranslator;
}
@Override
protected IntTranslatedIterable copy() {
return new IntTranslatedIterable(this);
}
@Override
protected void clearFilters() {
super.clearFilters();
mIterable.clearFilters();
}
@Override
protected SparseIterator createIterator(final boolean isReverse) {
final AbstractSparseIterable iterable;
if (isReverse) {
iterable = mIterable.copy();
iterable.reverse();
} else {
iterable = mIterable;
}
final SparseIterator iterator = iterable.filteredIterator(false);
return new TranslatedIterator(iterator, mTranslator);
}
@Override
protected SparseIterator rawIterator(final boolean isReverse) {
final SparseIterator iterator = mIterable.rawIterator(isReverse);
return new TranslatedIterator(iterator, mTranslator);
}
}
private static class LongTranslatedIterable extends LongSparseIterableImpl {
private final AbstractSparseIterable mIterable;
private final Translator mTranslator;
public LongTranslatedIterable(final AbstractSparseIterable iterable,
final Translator translator) {
mIterable = iterable;
mTranslator = translator;
}
LongTranslatedIterable(final LongTranslatedIterable other) {
super(other);
mIterable = other.mIterable;
mTranslator = other.mTranslator;
}
@Override
protected LongTranslatedIterable copy() {
return new LongTranslatedIterable(this);
}
@Override
protected void clearFilters() {
super.clearFilters();
mIterable.clearFilters();
}
@Override
protected SparseIterator createIterator(final boolean isReverse) {
final AbstractSparseIterable iterable;
if (isReverse) {
iterable = mIterable.copy();
iterable.reverse();
} else {
iterable = mIterable;
}
final SparseIterator iterator = iterable.filteredIterator(false);
return new TranslatedIterator(iterator, mTranslator);
}
@Override
protected SparseIterator rawIterator(final boolean isReverse) {
final SparseIterator iterator = mIterable.rawIterator(isReverse);
return new TranslatedIterator(iterator, mTranslator);
}
}
/**
* This class is used to create a snapshot of which elements would be iterated after applying
* a set of filters.
* By employing such snapshot of element indexes we can than reverse the order of the iteration
* or the logic of the filters themselves.
*
* @param the element type.
*/
private static class SnapshotFilter implements AdvancedFilter {
private int mCount;
private int[] mPositions = new int[8];
@Override
public void initialize(final FilterIterator iterator) {
mCount = 0;
while (iterator.hasNext()) {
iterator.next();
add(iterator.originalIndex());
}
Arrays.sort(mPositions, 0, mCount);
}
@Override
public boolean matches(final E element, final int count, final int index) {
return BinarySearch.contains(mPositions, mCount, index);
}
private void add(final int pos) {
final int length = mPositions.length;
if (mCount >= length) {
final int[] newPositions = new int[length * 2];
System.arraycopy(mPositions, 0, newPositions, 0, length);
mPositions = newPositions;
}
mPositions[mCount++] = pos;
}
}
private static class TranslatedIterator implements SparseIterator {
private final SparseIterator mIterator;
private final Translator mTranslator;
public TranslatedIterator(final SparseIterator iterator,
final Translator translator) {
mIterator = iterator;
mTranslator = translator;
}
@Override
public int originalIndex() {
return mIterator.originalIndex();
}
@Override
public boolean hasNext() {
return mIterator.hasNext();
}
@Override
public O next() {
return mTranslator.translate(mIterator.next());
}
@Override
public void remove() {
mIterator.remove();
}
@Override
public void reset() {
mIterator.reset();
}
}
}