1 /******************************************************************************* 2 * Copyright (c) 2009, 2017 Cloudsmith Inc. and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * Cloudsmith Inc. - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.equinox.internal.p2.metadata.expression; 15 16 import java.util.*; 17 import org.eclipse.equinox.p2.metadata.index.IIndexProvider; 18 import org.eclipse.equinox.p2.query.IQueryResult; 19 20 public class RepeatableIterator<T> implements IRepeatableIterator<T> { 21 private final Collection<T> values; 22 private final Iterator<T> iterator; 23 24 @SuppressWarnings("unchecked") create(Object unknown)25 public static <T> IRepeatableIterator<T> create(Object unknown) { 26 if (unknown.getClass().isArray()) 27 return create((T[]) unknown); 28 if (unknown instanceof Iterator<?>) 29 return create((Iterator<T>) unknown); 30 if (unknown instanceof List<?>) 31 return create((List<T>) unknown); 32 if (unknown instanceof Collection<?>) 33 return create((Collection<T>) unknown); 34 if (unknown instanceof Map<?, ?>) 35 return create((Set<T>) ((Map<?, ?>) unknown).entrySet()); 36 if (unknown instanceof IQueryResult<?>) 37 return create((IQueryResult<T>) unknown); 38 if (unknown instanceof IIndexProvider<?>) 39 return create((IIndexProvider<T>) unknown); 40 throw new IllegalArgumentException("Cannot convert a " + unknown.getClass().getName() + " into an iterator"); //$NON-NLS-1$ //$NON-NLS-2$ 41 } 42 create(Iterator<T> iterator)43 public static <T> IRepeatableIterator<T> create(Iterator<T> iterator) { 44 return iterator instanceof IRepeatableIterator<?> ? ((IRepeatableIterator<T>) iterator).getCopy() : new RepeatableIterator<>(iterator); 45 } 46 create(Collection<T> values)47 public static <T> IRepeatableIterator<T> create(Collection<T> values) { 48 return new RepeatableIterator<>(values); 49 } 50 create(IQueryResult<T> values)51 public static <T> IRepeatableIterator<T> create(IQueryResult<T> values) { 52 return new QueryResultIterator<>(values); 53 } 54 create(T[] values)55 public static <T> IRepeatableIterator<T> create(T[] values) { 56 return new ArrayIterator<>(values); 57 } 58 create(IIndexProvider<T> values)59 public static <T> IRepeatableIterator<T> create(IIndexProvider<T> values) { 60 return new IndexProviderIterator<>(values); 61 } 62 RepeatableIterator(Iterator<T> iterator)63 RepeatableIterator(Iterator<T> iterator) { 64 HashSet<T> v = new HashSet<>(); 65 while (iterator.hasNext()) 66 v.add(iterator.next()); 67 values = v; 68 this.iterator = v.iterator(); 69 } 70 RepeatableIterator(Collection<T> values)71 RepeatableIterator(Collection<T> values) { 72 this.values = values; 73 this.iterator = values.iterator(); 74 } 75 76 @Override getCopy()77 public IRepeatableIterator<T> getCopy() { 78 return new RepeatableIterator<>(values); 79 } 80 81 @Override hasNext()82 public boolean hasNext() { 83 return iterator.hasNext(); 84 } 85 86 @Override next()87 public T next() { 88 return iterator.next(); 89 } 90 91 @Override remove()92 public void remove() { 93 throw new UnsupportedOperationException(); 94 } 95 96 @Override getIteratorProvider()97 public Object getIteratorProvider() { 98 return values; 99 } 100 101 static class ArrayIterator<T> implements IRepeatableIterator<T> { 102 private final T[] array; 103 private int position = -1; 104 ArrayIterator(T[] array)105 public ArrayIterator(T[] array) { 106 this.array = array; 107 } 108 109 @Override getIteratorProvider()110 public Object getIteratorProvider() { 111 return array; 112 } 113 114 @Override hasNext()115 public boolean hasNext() { 116 return position + 1 < array.length; 117 } 118 119 @Override next()120 public T next() { 121 if (++position >= array.length) 122 throw new NoSuchElementException(); 123 return array[position]; 124 } 125 126 @Override remove()127 public void remove() { 128 throw new UnsupportedOperationException(); 129 } 130 131 @Override getCopy()132 public IRepeatableIterator<T> getCopy() { 133 return new ArrayIterator<>(array); 134 } 135 } 136 137 static class IndexProviderIterator<T> implements IRepeatableIterator<T> { 138 private final IIndexProvider<T> indexProvider; 139 private final Iterator<T> iterator; 140 IndexProviderIterator(IIndexProvider<T> indexProvider)141 IndexProviderIterator(IIndexProvider<T> indexProvider) { 142 this.iterator = indexProvider.everything(); 143 this.indexProvider = indexProvider; 144 } 145 146 @Override getCopy()147 public IRepeatableIterator<T> getCopy() { 148 return new IndexProviderIterator<>(indexProvider); 149 } 150 151 @Override getIteratorProvider()152 public Object getIteratorProvider() { 153 return indexProvider; 154 } 155 156 @Override hasNext()157 public boolean hasNext() { 158 return iterator.hasNext(); 159 } 160 161 @Override next()162 public T next() { 163 return iterator.next(); 164 } 165 166 @Override remove()167 public void remove() { 168 throw new UnsupportedOperationException(); 169 } 170 } 171 172 static class QueryResultIterator<T> implements IRepeatableIterator<T> { 173 private final IQueryResult<T> queryResult; 174 175 private final Iterator<T> iterator; 176 QueryResultIterator(IQueryResult<T> queryResult)177 QueryResultIterator(IQueryResult<T> queryResult) { 178 this.queryResult = queryResult; 179 this.iterator = queryResult.iterator(); 180 } 181 182 @Override getCopy()183 public IRepeatableIterator<T> getCopy() { 184 return new QueryResultIterator<>(queryResult); 185 } 186 187 @Override getIteratorProvider()188 public Object getIteratorProvider() { 189 return queryResult; 190 } 191 192 @Override hasNext()193 public boolean hasNext() { 194 return iterator.hasNext(); 195 } 196 197 @Override next()198 public T next() { 199 return iterator.next(); 200 } 201 202 @Override remove()203 public void remove() { 204 throw new UnsupportedOperationException(); 205 } 206 } 207 } 208