/* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v 2.0 * which accompanies this distribution and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt * * Contributors: * PARC initial implementation * ******************************************************************/ package org.aspectj.weaver; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; public final class Iterators { /** * Private constructor, nobody should ever make one of these */ private Iterators() { } /** * A getter represents a mapping function from Object to Iterator */ public interface Getter { Iterator get(A target); } /** * A filter represents a mapping function from Iterator to Iterator */ public interface Filter { Iterator filter(Iterator in); } /** * Create a new filter F that, when wrapped around another iterator I, creates a new iterator I' that will return only those * values of I that have not yet been returned by I', discarding duplicates. */ public static Filter dupFilter() { return new Filter() { final Set seen = new HashSet<>(); // should have weak ptrs? public Iterator filter(final Iterator in) { return new Iterator() { boolean fresh = false; T peek; public boolean hasNext() { if (fresh) { return true; } while (true) { if (!in.hasNext()) { return false; } peek = in.next(); if (!seen.contains(peek)) { fresh = true; return true; } else { peek = null; // garbage collection } } } public T next() { if (!hasNext()) { throw new NoSuchElementException(); } T ret = peek; seen.add(peek); peek = null; fresh = false; return ret; } public void remove() { throw new UnsupportedOperationException(); } }; } }; } /** * Creates an iterator that will return the elements of a specified array, in order. Like Arrays.asList(o).iterator(), without * all that pesky safety. */ public static Iterator array(final T[] o) { return new Iterator() { int i = 0; int len = (o == null) ? 0 : o.length; public boolean hasNext() { return i < len; } public T next() { if (i < len) { return o[i++]; } else { throw new NoSuchElementException(); } } public void remove() { throw new UnsupportedOperationException(); } }; } public static class ResolvedTypeArrayIterator implements Iterator { private ResolvedType[] array; private int index; private int len; private boolean wantGenerics; private List alreadySeen; // type signatures public ResolvedTypeArrayIterator(ResolvedType[] array, List alreadySeen, boolean wantGenerics) { assert array != null; this.array = array; this.wantGenerics = wantGenerics; this.len = array.length; this.index = 0; this.alreadySeen = alreadySeen; moveToNextNewOne(); } private void moveToNextNewOne() { while (index < len) { ResolvedType interfaceType = array[index]; if (!wantGenerics && interfaceType.isParameterizedOrGenericType()) { interfaceType = interfaceType.getRawType(); } String signature = interfaceType.getSignature(); if (!alreadySeen.contains(signature)) { break; } index++; } } public boolean hasNext() { return index < len; } public ResolvedType next() { if (index < len) { ResolvedType oo = array[index++]; if (!wantGenerics && (oo.isParameterizedType() || oo.isGenericType())) { oo = oo.getRawType(); } alreadySeen.add(oo.getSignature()); moveToNextNewOne(); return oo; } else { throw new NoSuchElementException(); } } public void remove() { throw new UnsupportedOperationException(); } } public static Iterator array(final ResolvedType[] o, final boolean genericsAware) { return new Iterator() { int i = 0; int len = (o == null) ? 0 : o.length; public boolean hasNext() { return i < len; } public ResolvedType next() { if (i < len) { ResolvedType oo = o[i++]; if (!genericsAware && (oo.isParameterizedType() || oo.isGenericType())) { return oo.getRawType(); } return oo; } else { throw new NoSuchElementException(); } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in A), G(i). */ public static Iterator mapOver(final Iterator a, final Getter g) { return new Iterator() { Iterator delegate = new Iterator() { public boolean hasNext() { if (!a.hasNext()) { return false; } A o = a.next(); delegate = append1(g.get(o), this); return delegate.hasNext(); } public B next() { if (!hasNext()) { throw new UnsupportedOperationException(); } return delegate.next(); } public void remove() { throw new UnsupportedOperationException(); } }; public boolean hasNext() { return delegate.hasNext(); } public B next() { return delegate.next(); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in I) i :: forall (i' in * g(i)) recur(i', g) */ public static Iterator recur(final A a, final Getter g) { return new Iterator() { Iterator delegate = one(a); public boolean hasNext() { return delegate.hasNext(); } public A next() { A next = delegate.next(); delegate = append(g.get(next), delegate); return next; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If * B is empty, simply returns A, and if A is empty, simply returns B. Do NOT USE if b.hasNext() is not idempotent. */ public static Iterator append(final Iterator a, final Iterator b) { if (!b.hasNext()) { return a; } return append1(a, b); } /** * creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If * A is empty, simply returns B. Guaranteed not to call B.hasNext() until A is empty. */ public static Iterator append1(final Iterator a, final Iterator b) { if (!a.hasNext()) { return b; } return new Iterator() { public boolean hasNext() { return a.hasNext() || b.hasNext(); } public T next() { if (a.hasNext()) { return a.next(); } if (b.hasNext()) { return b.next(); } throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * creates an iterator I based on a base iterator A and an object O. Returns the elements returned by A, followed by O. */ public static Iterator snoc(final Iterator first, final T last) { return new Iterator() { T last1 = last; public boolean hasNext() { return first.hasNext() || last1 != null; } public T next() { if (first.hasNext()) { return first.next(); } else if (last1 == null) { throw new NoSuchElementException(); } T ret = last1; last1 = null; return ret; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * creates an iterator I based on an object O. Returns O, once. */ public static Iterator one(final T it) { return new Iterator() { boolean avail = true; public boolean hasNext() { return avail; } public T next() { if (!avail) { throw new NoSuchElementException(); } avail = false; return it; } public void remove() { throw new UnsupportedOperationException(); } }; } }