From 950653960bf802913065b8e59b3a693d1455e526 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Thu, 25 Feb 2010 06:30:12 +0000 Subject: [PATCH] Separate SeqImpl out of Sequence, hiding it away in our impl package tree. Make Sequence an interface. We're going to change all of the places in Depot where we take a Collection as an argument and take an Iterable instead. We invariably just turn the Collection to an array, and we can just as well do that with an Iterable and be more flexible about what we accept. Iterables.toArray has a fast path for Iterable instances that also implement Collection, so we make SeqImpl implement Collection under the hood even though we don't advertise that in the Sequence interface because we don't want people using these as collections. What we really want is something in between Iterable and Collection that knows its size but otherwise does not allow mutation or containment checks. --- .../com/samskivert/depot/DepotRepository.java | 5 +- .../samskivert/depot/impl/util/SeqImpl.java | 105 ++++++++++++++++++ .../com/samskivert/depot/util/Sequence.java | 70 ++---------- 3 files changed, 117 insertions(+), 63 deletions(-) create mode 100644 src/java/com/samskivert/depot/impl/util/SeqImpl.java diff --git a/src/java/com/samskivert/depot/DepotRepository.java b/src/java/com/samskivert/depot/DepotRepository.java index 4c1e359..9013973 100644 --- a/src/java/com/samskivert/depot/DepotRepository.java +++ b/src/java/com/samskivert/depot/DepotRepository.java @@ -60,6 +60,7 @@ import com.samskivert.depot.impl.SQLBuilder; import com.samskivert.depot.impl.clause.DeleteClause; import com.samskivert.depot.impl.clause.UpdateClause; import com.samskivert.depot.impl.expression.ValueExp; +import com.samskivert.depot.impl.util.SeqImpl; import static com.samskivert.depot.Log.log; @@ -197,7 +198,7 @@ public abstract class DepotRepository public List loadAll (Collection> keys) throws DatabaseException { - return keys.isEmpty() ? Collections.emptyList() : + return keys.isEmpty() ? Collections.emptyList() : _ctx.invoke(new FindAllQuery.WithKeys(_ctx, keys)); } @@ -909,7 +910,7 @@ public abstract class DepotRepository */ protected Sequence map (Collection source, Function func) { - return Sequence.map(source, func); + return new SeqImpl(source, func); } protected PersistenceContext _ctx; diff --git a/src/java/com/samskivert/depot/impl/util/SeqImpl.java b/src/java/com/samskivert/depot/impl/util/SeqImpl.java new file mode 100644 index 0000000..8a68a28 --- /dev/null +++ b/src/java/com/samskivert/depot/impl/util/SeqImpl.java @@ -0,0 +1,105 @@ +// +// $Id$ +// +// Depot library - a Java relational persistence library +// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.depot.impl.util; + +import java.lang.reflect.Array; + +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterators; + +import com.samskivert.depot.util.Sequence; + +/** + * An implementation of {@link Sequence} which secretly implements {@link Collection} so that + * {@link Iterables#toArray} can efficiently turn it into an array. We use {@link + * Iterables#toArray} in various places in Depot, so we prefer to enable such efficience. + */ +public class SeqImpl extends AbstractCollection implements Sequence +{ + public SeqImpl (Collection source, Function func) + { + Preconditions.checkNotNull(source); + Preconditions.checkNotNull(func); + _source = source; + _func = func; + } + + // from interface Sequence and Collection + public Iterator iterator () + { + return Iterators.transform(_source.iterator(), _func); + } + + // from interface Sequence and Collection + public int size () + { + return _source.size(); + } + + // from interface Sequence and Collection + public boolean isEmpty () + { + return _source.isEmpty(); + } + + // from interface Sequence + public ArrayList toList () + { + return copyInto(new ArrayList(_source.size())); + } + + // from interface Sequence + public HashSet toSet () + { + return copyInto(new HashSet(_source.size())); + } + + // from interface Sequence + public T[] toArray (Class clazz) + // In a perfect world this would be S[] toArray (Class clazz) + { + @SuppressWarnings("unchecked") + T[] array = (T[]) Array.newInstance(clazz, _source.size()); + int index = 0; + for (F elem : _source) { + array[index++] = _func.apply(elem); + } + return array; + } + + protected > C copyInto (C coll) + { + for (F elem : _source) { + coll.add(_func.apply(elem)); + } + return coll; + } + + protected final Collection _source; + protected final Function _func; +} diff --git a/src/java/com/samskivert/depot/util/Sequence.java b/src/java/com/samskivert/depot/util/Sequence.java index c1c3b38..383201b 100644 --- a/src/java/com/samskivert/depot/util/Sequence.java +++ b/src/java/com/samskivert/depot/util/Sequence.java @@ -20,16 +20,11 @@ package com.samskivert.depot.util; -import java.lang.reflect.Array; - import java.util.ArrayList; -import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.common.collect.Iterators; /** * Provides read-only access to a sequence of elements. Note that these elements will generally be @@ -38,78 +33,31 @@ import com.google.common.collect.Iterators; * #toList} to convert the sequence to concrete list to avoid repeated application of the * conversion function on elements of the sequence. */ -public abstract class Sequence implements Iterable +public interface Sequence extends Iterable { - /** - * Applies the supplied mapping function to the elements in the supplied collection, returning - * a lazily created read-only view of the mapped elements. - */ - public static Sequence map (final Collection source, - final Function func) - { - Preconditions.checkNotNull(source); - Preconditions.checkNotNull(func); - return new Sequence() { - public Iterator iterator () { - return Iterators.transform(source.iterator(), func); - } - public int size () { - return source.size(); - } - public boolean isEmpty () { - return source.isEmpty(); - } - public ArrayList toList () { - return copyInto(new ArrayList(source.size())); - } - public HashSet toSet () { - return copyInto(new HashSet(source.size())); - } - // In a perfect world this would be S[] toArray (Class clazz) - public T[] toArray (Class clazz) { - @SuppressWarnings("unchecked") - T[] array = (T[]) Array.newInstance(clazz, source.size()); - int index = 0; - for (F elem : source) { - array[index++] = func.apply(elem); - } - return array; - } - protected > C copyInto (C coll) { - for (F elem : source) { - coll.add(func.apply(elem)); - } - return coll; - } - }; - } - - // from interface Iterable - public abstract Iterator iterator (); - /** * Returns the number of elements in this sequence. */ - public abstract int size (); + int size (); /** * Returns true if this sequence is empty, false if it contains at least one element. */ - public abstract boolean isEmpty (); + boolean isEmpty (); /** - * Converts this sequence into an ArrayList. + * Converts this sequence into an {@link ArrayList}. */ - public abstract ArrayList toList (); + ArrayList toList (); /** - * Converts this sequence into a HashSet. + * Converts this sequence into a {@link HashSet}. */ - public abstract HashSet toSet (); + HashSet toSet (); /** * Converts this sequence into an array. - * I wish this were S[] toArray (Class clazz); */ - public abstract T[] toArray (Class clazz); + T[] toArray (Class clazz); + // Ray wishes this were S[] toArray (Class clazz); }