com.sun.javafx.binding.SetExpressionHelper Maven / Gradle / Ivy
/*
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.binding;
import javafx.beans.InvalidationListener;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableSetValue;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener;
import java.util.Arrays;
/**
*/
public abstract class SetExpressionHelper extends ExpressionHelperBase {
//------------------------------------------------------------------------------------------------------------------
// Static methods
public static SetExpressionHelper addListener(SetExpressionHelper helper, ObservableSetValue observable, InvalidationListener listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
observable.getValue(); // validate observable
return (helper == null)? new SingleInvalidation<>(observable, listener) : helper.addListener(listener);
}
public static SetExpressionHelper removeListener(SetExpressionHelper helper, InvalidationListener listener) {
if (listener == null) {
throw new NullPointerException();
}
return (helper == null)? null : helper.removeListener(listener);
}
public static SetExpressionHelper addListener(SetExpressionHelper helper, ObservableSetValue observable, ChangeListener super ObservableSet> listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
return (helper == null)? new SingleChange<>(observable, listener) : helper.addListener(listener);
}
public static SetExpressionHelper removeListener(SetExpressionHelper helper, ChangeListener super ObservableSet> listener) {
if (listener == null) {
throw new NullPointerException();
}
return (helper == null)? null : helper.removeListener(listener);
}
public static SetExpressionHelper addListener(SetExpressionHelper helper, ObservableSetValue observable, SetChangeListener super E> listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
return (helper == null)? new SingleSetChange<>(observable, listener) : helper.addListener(listener);
}
public static SetExpressionHelper removeListener(SetExpressionHelper helper, SetChangeListener super E> listener) {
if (listener == null) {
throw new NullPointerException();
}
return (helper == null)? null : helper.removeListener(listener);
}
public static void fireValueChangedEvent(SetExpressionHelper helper) {
if (helper != null) {
helper.fireValueChangedEvent();
}
}
public static void fireValueChangedEvent(SetExpressionHelper helper, SetChangeListener.Change extends E> change) {
if (helper != null) {
helper.fireValueChangedEvent(change);
}
}
//------------------------------------------------------------------------------------------------------------------
// Common implementations
protected final ObservableSetValue observable;
protected SetExpressionHelper(ObservableSetValue observable) {
this.observable = observable;
}
protected abstract SetExpressionHelper addListener(InvalidationListener listener);
protected abstract SetExpressionHelper removeListener(InvalidationListener listener);
protected abstract SetExpressionHelper addListener(ChangeListener super ObservableSet> listener);
protected abstract SetExpressionHelper removeListener(ChangeListener super ObservableSet> listener);
protected abstract SetExpressionHelper addListener(SetChangeListener super E> listener);
protected abstract SetExpressionHelper removeListener(SetChangeListener super E> listener);
protected abstract void fireValueChangedEvent();
protected abstract void fireValueChangedEvent(SetChangeListener.Change extends E> change);
//------------------------------------------------------------------------------------------------------------------
// Implementations
private static class SingleInvalidation extends SetExpressionHelper {
private final InvalidationListener listener;
private SingleInvalidation(ObservableSetValue observable, InvalidationListener listener) {
super(observable);
this.listener = listener;
}
@Override
protected SetExpressionHelper addListener(InvalidationListener listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(InvalidationListener listener) {
return (listener.equals(this.listener))? null : this;
}
@Override
protected SetExpressionHelper addListener(ChangeListener super ObservableSet> listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(ChangeListener super ObservableSet> listener) {
return this;
}
@Override
protected SetExpressionHelper addListener(SetChangeListener super E> listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(SetChangeListener super E> listener) {
return this;
}
@Override
protected void fireValueChangedEvent() {
listener.invalidated(observable);
}
@Override
protected void fireValueChangedEvent(SetChangeListener.Change extends E> change) {
listener.invalidated(observable);
}
}
private static class SingleChange extends SetExpressionHelper {
private final ChangeListener super ObservableSet> listener;
private ObservableSet currentValue;
private SingleChange(ObservableSetValue observable, ChangeListener super ObservableSet> listener) {
super(observable);
this.listener = listener;
this.currentValue = observable.getValue();
}
@Override
protected SetExpressionHelper addListener(InvalidationListener listener) {
return new Generic<>(observable, listener, this.listener);
}
@Override
protected SetExpressionHelper removeListener(InvalidationListener listener) {
return this;
}
@Override
protected SetExpressionHelper addListener(ChangeListener super ObservableSet> listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(ChangeListener super ObservableSet> listener) {
return (listener.equals(this.listener))? null : this;
}
@Override
protected SetExpressionHelper addListener(SetChangeListener super E> listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(SetChangeListener super E> listener) {
return this;
}
@Override
protected void fireValueChangedEvent() {
final ObservableSet oldValue = currentValue;
currentValue = observable.getValue();
if (currentValue != oldValue) {
listener.changed(observable, oldValue, currentValue);
}
}
@Override
protected void fireValueChangedEvent(SetChangeListener.Change extends E> change) {
listener.changed(observable, currentValue, currentValue);
}
}
private static class SingleSetChange extends SetExpressionHelper {
private final SetChangeListener super E> listener;
private ObservableSet currentValue;
private SingleSetChange(ObservableSetValue observable, SetChangeListener super E> listener) {
super(observable);
this.listener = listener;
this.currentValue = observable.getValue();
}
@Override
protected SetExpressionHelper addListener(InvalidationListener listener) {
return new Generic<>(observable, listener, this.listener);
}
@Override
protected SetExpressionHelper removeListener(InvalidationListener listener) {
return this;
}
@Override
protected SetExpressionHelper addListener(ChangeListener super ObservableSet> listener) {
return new Generic<>(observable, listener, this.listener);
}
@Override
protected SetExpressionHelper removeListener(ChangeListener super ObservableSet> listener) {
return this;
}
@Override
protected SetExpressionHelper addListener(SetChangeListener super E> listener) {
return new Generic<>(observable, this.listener, listener);
}
@Override
protected SetExpressionHelper removeListener(SetChangeListener super E> listener) {
return (listener.equals(this.listener))? null : this;
}
@Override
protected void fireValueChangedEvent() {
final ObservableSet oldValue = currentValue;
currentValue = observable.getValue();
if (currentValue != oldValue) {
final SimpleChange change = new SimpleChange<>(observable);
if (currentValue == null) {
for (final E element : oldValue) {
listener.onChanged(change.setRemoved(element));
}
} else if (oldValue == null) {
for (final E element : currentValue) {
listener.onChanged(change.setAdded(element));
}
} else {
for (final E element : oldValue) {
if (!currentValue.contains(element)) {
listener.onChanged(change.setRemoved(element));
}
}
for (final E element : currentValue) {
if (!oldValue.contains(element)) {
listener.onChanged(change.setAdded(element));
}
}
}
}
}
@Override
protected void fireValueChangedEvent(final SetChangeListener.Change extends E> change) {
listener.onChanged(new SimpleChange<>(observable, change));
}
}
private static class Generic extends SetExpressionHelper {
private InvalidationListener[] invalidationListeners;
private ChangeListener super ObservableSet>[] changeListeners;
private SetChangeListener super E>[] setChangeListeners;
private int invalidationSize;
private int changeSize;
private int setChangeSize;
private boolean locked;
private ObservableSet currentValue;
private Generic(ObservableSetValue observable, InvalidationListener listener0, InvalidationListener listener1) {
super(observable);
this.invalidationListeners = new InvalidationListener[] {listener0, listener1};
this.invalidationSize = 2;
}
private Generic(ObservableSetValue observable, ChangeListener super ObservableSet> listener0, ChangeListener super ObservableSet> listener1) {
super(observable);
this.changeListeners = new ChangeListener[] {listener0, listener1};
this.changeSize = 2;
this.currentValue = observable.getValue();
}
private Generic(ObservableSetValue observable, SetChangeListener super E> listener0, SetChangeListener super E> listener1) {
super(observable);
this.setChangeListeners = new SetChangeListener[] {listener0, listener1};
this.setChangeSize = 2;
this.currentValue = observable.getValue();
}
private Generic(ObservableSetValue observable, InvalidationListener invalidationListener, ChangeListener super ObservableSet> changeListener) {
super(observable);
this.invalidationListeners = new InvalidationListener[] {invalidationListener};
this.invalidationSize = 1;
this.changeListeners = new ChangeListener[] {changeListener};
this.changeSize = 1;
this.currentValue = observable.getValue();
}
private Generic(ObservableSetValue observable, InvalidationListener invalidationListener, SetChangeListener super E> listChangeListener) {
super(observable);
this.invalidationListeners = new InvalidationListener[] {invalidationListener};
this.invalidationSize = 1;
this.setChangeListeners = new SetChangeListener[] {listChangeListener};
this.setChangeSize = 1;
this.currentValue = observable.getValue();
}
private Generic(ObservableSetValue observable, ChangeListener super ObservableSet> changeListener, SetChangeListener super E> listChangeListener) {
super(observable);
this.changeListeners = new ChangeListener[] {changeListener};
this.changeSize = 1;
this.setChangeListeners = new SetChangeListener[] {listChangeListener};
this.setChangeSize = 1;
this.currentValue = observable.getValue();
}
@Override
protected SetExpressionHelper addListener(InvalidationListener listener) {
if (invalidationListeners == null) {
invalidationListeners = new InvalidationListener[] {listener};
invalidationSize = 1;
} else {
final int oldCapacity = invalidationListeners.length;
if (locked) {
final int newCapacity = (invalidationSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
} else if (invalidationSize == oldCapacity) {
invalidationSize = trim(invalidationSize, invalidationListeners);
if (invalidationSize == oldCapacity) {
final int newCapacity = (oldCapacity * 3)/2 + 1;
invalidationListeners = Arrays.copyOf(invalidationListeners, newCapacity);
}
}
invalidationListeners[invalidationSize++] = listener;
}
return this;
}
@Override
protected SetExpressionHelper removeListener(InvalidationListener listener) {
if (invalidationListeners != null) {
for (int index = 0; index < invalidationSize; index++) {
if (listener.equals(invalidationListeners[index])) {
if (invalidationSize == 1) {
if ((changeSize == 1) && (setChangeSize == 0)) {
return new SingleChange<>(observable, changeListeners[0]);
} else if ((changeSize == 0) && (setChangeSize == 1)) {
return new SingleSetChange<>(observable, setChangeListeners[0]);
}
invalidationListeners = null;
invalidationSize = 0;
} else if ((invalidationSize == 2) && (changeSize == 0) && (setChangeSize == 0)) {
return new SingleInvalidation<>(observable, invalidationListeners[1-index]);
} else {
final int numMoved = invalidationSize - index - 1;
final InvalidationListener[] oldListeners = invalidationListeners;
if (locked) {
invalidationListeners = new InvalidationListener[invalidationListeners.length];
System.arraycopy(oldListeners, 0, invalidationListeners, 0, index+1);
}
if (numMoved > 0) {
System.arraycopy(oldListeners, index+1, invalidationListeners, index, numMoved);
}
invalidationSize--;
if (!locked) {
invalidationListeners[invalidationSize] = null; // Let gc do its work
}
}
break;
}
}
}
return this;
}
@Override
protected SetExpressionHelper addListener(ChangeListener super ObservableSet> listener) {
if (changeListeners == null) {
changeListeners = new ChangeListener[] {listener};
changeSize = 1;
} else {
final int oldCapacity = changeListeners.length;
if (locked) {
final int newCapacity = (changeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
changeListeners = Arrays.copyOf(changeListeners, newCapacity);
} else if (changeSize == oldCapacity) {
changeSize = trim(changeSize, changeListeners);
if (changeSize == oldCapacity) {
final int newCapacity = (oldCapacity * 3)/2 + 1;
changeListeners = Arrays.copyOf(changeListeners, newCapacity);
}
}
changeListeners[changeSize++] = listener;
}
if (changeSize == 1) {
currentValue = observable.getValue();
}
return this;
}
@Override
protected SetExpressionHelper removeListener(ChangeListener super ObservableSet> listener) {
if (changeListeners != null) {
for (int index = 0; index < changeSize; index++) {
if (listener.equals(changeListeners[index])) {
if (changeSize == 1) {
if ((invalidationSize == 1) && (setChangeSize == 0)) {
return new SingleInvalidation<>(observable, invalidationListeners[0]);
} else if ((invalidationSize == 0) && (setChangeSize == 1)) {
return new SingleSetChange<>(observable, setChangeListeners[0]);
}
changeListeners = null;
changeSize = 0;
} else if ((changeSize == 2) && (invalidationSize == 0) && (setChangeSize == 0)) {
return new SingleChange<>(observable, changeListeners[1-index]);
} else {
final int numMoved = changeSize - index - 1;
final ChangeListener super ObservableSet>[] oldListeners = changeListeners;
if (locked) {
changeListeners = new ChangeListener[changeListeners.length];
System.arraycopy(oldListeners, 0, changeListeners, 0, index+1);
}
if (numMoved > 0) {
System.arraycopy(oldListeners, index+1, changeListeners, index, numMoved);
}
changeSize--;
if (!locked) {
changeListeners[changeSize] = null; // Let gc do its work
}
}
break;
}
}
}
return this;
}
@Override
protected SetExpressionHelper addListener(SetChangeListener super E> listener) {
if (setChangeListeners == null) {
setChangeListeners = new SetChangeListener[] {listener};
setChangeSize = 1;
} else {
final int oldCapacity = setChangeListeners.length;
if (locked) {
final int newCapacity = (setChangeSize < oldCapacity)? oldCapacity : (oldCapacity * 3)/2 + 1;
setChangeListeners = Arrays.copyOf(setChangeListeners, newCapacity);
} else if (setChangeSize == oldCapacity) {
setChangeSize = trim(setChangeSize, setChangeListeners);
if (setChangeSize == oldCapacity) {
final int newCapacity = (oldCapacity * 3)/2 + 1;
setChangeListeners = Arrays.copyOf(setChangeListeners, newCapacity);
}
}
setChangeListeners[setChangeSize++] = listener;
}
if (setChangeSize == 1) {
currentValue = observable.getValue();
}
return this;
}
@Override
protected SetExpressionHelper removeListener(SetChangeListener super E> listener) {
if (setChangeListeners != null) {
for (int index = 0; index < setChangeSize; index++) {
if (listener.equals(setChangeListeners[index])) {
if (setChangeSize == 1) {
if ((invalidationSize == 1) && (changeSize == 0)) {
return new SingleInvalidation<>(observable, invalidationListeners[0]);
} else if ((invalidationSize == 0) && (changeSize == 1)) {
return new SingleChange<>(observable, changeListeners[0]);
}
setChangeListeners = null;
setChangeSize = 0;
} else if ((setChangeSize == 2) && (invalidationSize == 0) && (changeSize == 0)) {
return new SingleSetChange<>(observable, setChangeListeners[1-index]);
} else {
final int numMoved = setChangeSize - index - 1;
final SetChangeListener super E>[] oldListeners = setChangeListeners;
if (locked) {
setChangeListeners = new SetChangeListener[setChangeListeners.length];
System.arraycopy(oldListeners, 0, setChangeListeners, 0, index+1);
}
if (numMoved > 0) {
System.arraycopy(oldListeners, index+1, setChangeListeners, index, numMoved);
}
setChangeSize--;
if (!locked) {
setChangeListeners[setChangeSize] = null; // Let gc do its work
}
}
break;
}
}
}
return this;
}
@Override
protected void fireValueChangedEvent() {
if ((changeSize == 0) && (setChangeSize == 0)) {
notifyListeners(currentValue, null);
} else {
final ObservableSet oldValue = currentValue;
currentValue = observable.getValue();
notifyListeners(oldValue, null);
}
}
@Override
protected void fireValueChangedEvent(final SetChangeListener.Change extends E> change) {
final SimpleChange mappedChange = (setChangeSize == 0)? null : new SimpleChange<>(observable, change);
notifyListeners(currentValue, mappedChange);
}
private void notifyListeners(ObservableSet oldValue, SimpleChange change) {
final InvalidationListener[] curInvalidationList = invalidationListeners;
final int curInvalidationSize = invalidationSize;
final ChangeListener super ObservableSet>[] curChangeList = changeListeners;
final int curChangeSize = changeSize;
final SetChangeListener super E>[] curListChangeList = setChangeListeners;
final int curListChangeSize = setChangeSize;
try {
locked = true;
for (int i = 0; i < curInvalidationSize; i++) {
curInvalidationList[i].invalidated(observable);
}
if ((currentValue != oldValue) || (change != null)) {
for (int i = 0; i < curChangeSize; i++) {
curChangeList[i].changed(observable, oldValue, currentValue);
}
if (curListChangeSize > 0) {
if (change != null) {
for (int i = 0; i < curListChangeSize; i++) {
curListChangeList[i].onChanged(change);
}
} else {
change = new SimpleChange<>(observable);
if (currentValue == null) {
for (final E element : oldValue) {
change.setRemoved(element);
for (int i = 0; i < curListChangeSize; i++) {
curListChangeList[i].onChanged(change);
}
}
} else if (oldValue == null) {
for (final E element : currentValue) {
change.setAdded(element);
for (int i = 0; i < curListChangeSize; i++) {
curListChangeList[i].onChanged(change);
}
}
} else {
for (final E element : oldValue) {
if (!currentValue.contains(element)) {
change.setRemoved(element);
for (int i = 0; i < curListChangeSize; i++) {
curListChangeList[i].onChanged(change);
}
}
}
for (final E element : currentValue) {
if (!oldValue.contains(element)) {
change.setAdded(element);
for (int i = 0; i < curListChangeSize; i++) {
curListChangeList[i].onChanged(change);
}
}
}
}
}
}
}
} finally {
locked = false;
}
}
}
public static class SimpleChange extends SetChangeListener.Change {
private E old;
private E added;
private boolean addOp;
public SimpleChange(ObservableSet set) {
super(set);
}
public SimpleChange(ObservableSet set, SetChangeListener.Change extends E> source) {
super(set);
old = source.getElementRemoved();
added = source.getElementAdded();
addOp = source.wasAdded();
}
public SimpleChange setRemoved(E old) {
this.old = old;
this.added = null;
addOp = false;
return this;
}
public SimpleChange setAdded(E added) {
this.old = null;
this.added = added;
addOp = true;
return this;
}
@Override
public boolean wasAdded() {
return addOp;
}
@Override
public boolean wasRemoved() {
return !addOp;
}
@Override
public E getElementAdded() {
return added;
}
@Override
public E getElementRemoved() {
return old;
}
@Override
public String toString() {
return addOp ? "added " + added : "removed " + old;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy