/* * 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.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.drools.core.phreak.ReactiveObjectUtil.ModificationType; import org.drools.core.spi.Tuple; public class ReactiveList<T> extends ReactiveCollection<T, List<T>> implements List<T>{ public ReactiveList() { this(new ArrayList<T>()); } public ReactiveList(List<T> wrapped) { super(wrapped); } @Override public boolean addAll(int index, Collection<? extends T> c) { boolean result = wrapped.addAll(index, c); if (result) { for ( T element : c ) { ReactiveObjectUtil.notifyModification(element, getLeftTuples(), ModificationType.ADD); if ( element instanceof ReactiveObject ) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) element).addLeftTuple(lts); } } } } return result; } @Override public T get(int index) { return wrapped.get(index); } @Override public T set(int index, T element) { T previous = wrapped.set(index, element); if ( previous != element ) { // this is indeed intended != to check by reference ReactiveObjectUtil.notifyModification(element, getLeftTuples(), ModificationType.ADD); if ( element instanceof ReactiveObject ) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) element).addLeftTuple(lts); } } if (previous instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) previous).removeLeftTuple(lts); } } ReactiveObjectUtil.notifyModification(previous, getLeftTuples(), ModificationType.REMOVE); } return previous; } @Override public void add(int index, T element) { wrapped.add(index, element); ReactiveObjectUtil.notifyModification(element, getLeftTuples(), ModificationType.ADD); if ( element instanceof ReactiveObject ) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) element).addLeftTuple(lts); } } } @Override public T remove(int index) { T result = wrapped.remove(index); if (result instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) result).removeLeftTuple(lts); } } ReactiveObjectUtil.notifyModification(result, getLeftTuples(), ModificationType.REMOVE); return result; } @Override public int indexOf(Object o) { return wrapped.indexOf(o); } @Override public int lastIndexOf(Object o) { return wrapped.lastIndexOf(o); } @Override public List<T> subList(int fromIndex, int toIndex) { ReactiveList<T> result = new ReactiveList<T>( wrapped.subList(fromIndex, toIndex) ); for ( Tuple lts : getLeftTuples() ) { result.addLeftTuple( lts ); } return result; } @Override public ListIterator<T> listIterator() { return new ReactiveListIterator( wrapped.listIterator() ); } @Override public ListIterator<T> listIterator(int index) { return new ReactiveListIterator( wrapped.listIterator(index) ); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ReactiveList[").append(wrapped).append("]"); return builder.toString(); } private class ReactiveListIterator extends ReactiveIterator<ListIterator<T>> implements ListIterator<T> { public ReactiveListIterator(ListIterator<T> wrapped) { super(wrapped); } @Override public int nextIndex() { return wrapped.nextIndex(); } @Override public int previousIndex() { return wrapped.previousIndex(); } @Override public boolean hasPrevious() { return wrapped.hasPrevious(); } @Override public T previous() { last = wrapped.previous(); return last; } @Override public void set(T e) { // As per ListIterator spec, This call can be made only if neither remove nor add have been called after the last call to next or previous: if ( last != null ) { wrapped.set(e); if ( last != e ) { // this is indeed intended != to check by reference ReactiveObjectUtil.notifyModification(e, getLeftTuples(), ModificationType.ADD); if ( e instanceof ReactiveObject ) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) e).addLeftTuple(lts); } } if (last instanceof ReactiveObject) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) last).removeLeftTuple(lts); } } ReactiveObjectUtil.notifyModification(last, getLeftTuples(), ModificationType.REMOVE); } last = e; } } @Override public void add(T e) { wrapped.add(e); // the line above either throws UnsupportedOperationException or follows with: ReactiveObjectUtil.notifyModification(e, getLeftTuples(), ModificationType.ADD); if ( e instanceof ReactiveObject ) { for (Tuple lts : getLeftTuples()) { ((ReactiveObject) e).addLeftTuple(lts); } } last = null; } } }