/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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 org.drools.core.phreak; import java.util.Collection; import java.util.Iterator; import org.drools.core.phreak.ReactiveObjectUtil.ModificationType; import org.drools.core.spi.Tuple; public class ReactiveCollection<T, W extends Collection<T>> extends AbstractReactiveObject implements Collection<T> { protected final W wrapped; public ReactiveCollection(W wrapped) { this.wrapped = wrapped; } @Override public int size() { return wrapped.size(); } @Override public boolean isEmpty() { return wrapped.isEmpty(); } @Override public boolean contains(Object o) { return wrapped.contains(o); } @Override public Object[] toArray() { return wrapped.toArray(); } @Override public <T> T[] toArray(T[] a) { return wrapped.toArray(a); } @Override public boolean containsAll(Collection<?> c) { return wrapped.containsAll(c); } @Override public boolean add(T t) { boolean result = wrapped.add(t); if (result) { ReactiveObjectUtil.notifyModification(t, getLeftTuples(), ModificationType.ADD); if (t instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) t).addLeftTuple(lts); } } } return result; } @Override public boolean addAll(Collection<? extends T> c) { boolean result = false; for ( T elem : c ) { result |= add(elem); } return result; } @Override public boolean removeAll(Collection<?> c) { boolean result = false; for ( Object elem : c ) { result |= remove(elem); } return result; } @Override public boolean retainAll(Collection<?> c) { boolean result = false; for ( T elem : wrapped ) { if ( !c.contains(elem) ) { result |= remove(elem); } } return result; } @Override public void clear() { for ( T elem : wrapped ) { wrapped.remove(elem); } } @Override public boolean remove(Object o) { boolean result = wrapped.remove(o); if (result) { if (o instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) o).removeLeftTuple(lts); } } ReactiveObjectUtil.notifyModification(o, getLeftTuples(), ModificationType.REMOVE); } return result; } @Override public Iterator<T> iterator() { return new ReactiveIterator<>( wrapped.iterator() ); } protected class ReactiveIterator<WI extends Iterator<T>> implements Iterator<T> { protected WI wrapped; protected T last; public ReactiveIterator(WI wrapped) { this.wrapped = wrapped; } @Override public boolean hasNext() { return wrapped.hasNext(); } @Override public T next() { last = wrapped.next(); return last; } @Override public void remove() { wrapped.remove(); // the line above either throws UnsupportedOperationException or follows with: if (last != null) { if (last instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) last).removeLeftTuple(lts); } } ReactiveObjectUtil.notifyModification(last, getLeftTuples(), ModificationType.REMOVE); last = null; } } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ReactiveCollection [").append(wrapped).append("]"); return builder.toString(); } // Reminder: no need to override boolean removeIf(Predicate<? super E> filter) // as it uses the collection's Iterator which in this case is already opportunely wrapped. }