All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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, 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, 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(); } } }