|
|
@@ -0,0 +1,149 @@
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.collection;
|
|
|
+
|
|
|
+import net.ranides.assira.collection.lists.ListUtils;
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
+
|
|
|
+import java.io.Serializable;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Dynamic view with elements from merged collections.
|
|
|
+ * @param <T>
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ */
|
|
|
+public class FlatCollection<T> extends AbstractCollection<T> implements Serializable {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ private final Collection<Collection<T>> content = new LinkedList<>();
|
|
|
+
|
|
|
+ public FlatCollection() {
|
|
|
+ // do nothing
|
|
|
+ }
|
|
|
+
|
|
|
+ @SafeVarargs
|
|
|
+ public FlatCollection(Collection<T>... values) {
|
|
|
+ joinAll(Arrays.asList(values));
|
|
|
+ }
|
|
|
+
|
|
|
+ public FlatCollection(Collection<Collection<T>> values) {
|
|
|
+ joinAll(values);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Inserts into view specified collection.
|
|
|
+ * Note: It stores container, not actual elements from it.
|
|
|
+ * @param list
|
|
|
+ * @return this
|
|
|
+ */
|
|
|
+ public FlatCollection<T> join(Collection<T> list) {
|
|
|
+ content.add(list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /***
|
|
|
+ * Inserts into view specified collections.
|
|
|
+ * Note: It stores containers, not actual elements from them.
|
|
|
+ * @param list
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public final FlatCollection<T> joinAll(Collection<Collection<T>> list) {
|
|
|
+ content.addAll(list);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ int size = 0;
|
|
|
+ for(Collection<T> list : content) {
|
|
|
+ size += list.size();
|
|
|
+ }
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean contains(Object value) {
|
|
|
+ for(Collection<T> list : content) {
|
|
|
+ if( list.contains(value) ) { return true; }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean remove(Object value) {
|
|
|
+ for(Collection<T> c : content) {
|
|
|
+ if(c.remove(value)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ return new JoinIterator<>(content);
|
|
|
+ }
|
|
|
+
|
|
|
+ @NotNull
|
|
|
+ @Override
|
|
|
+ public Object[] toArray() {
|
|
|
+ return super.toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final class JoinIterator<T> implements Iterator<T> {
|
|
|
+
|
|
|
+ private final Iterator<Collection<T>> li;
|
|
|
+ private Iterator<T> ci;
|
|
|
+ private int csize;
|
|
|
+
|
|
|
+ public JoinIterator(Collection<Collection<T>> data) {
|
|
|
+ li = data.iterator();
|
|
|
+ csize = 0;
|
|
|
+ ci = Collections.emptyListIterator();
|
|
|
+
|
|
|
+ if(li.hasNext()) {
|
|
|
+ Collection<T> list = li.next();
|
|
|
+ csize = list.size();
|
|
|
+ ci = list.iterator();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasNext() {
|
|
|
+ if(ci.hasNext()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ while(li.hasNext()) {
|
|
|
+ Collection<T> list = li.next();
|
|
|
+ csize = list.size();
|
|
|
+ ci = list.iterator();
|
|
|
+ if(csize>0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T next() {
|
|
|
+ if(!hasNext()) {
|
|
|
+ throw new NoSuchElementException();
|
|
|
+ }
|
|
|
+ return ci.next();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void remove() {
|
|
|
+ ci.remove();
|
|
|
+ csize--;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|