Skip to content

Instantly share code, notes, and snippets.

@mstr2
Created July 8, 2022 18:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mstr2/1efc9e866f81622253711a963bd272fc to your computer and use it in GitHub Desktop.
Save mstr2/1efc9e866f81622253711a963bd272fc to your computer and use it in GitHub Desktop.
package com.sun.javafx.binding;
import javafx.beans.InvalidationListener;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public abstract class ConcurrentExpressionHelper<T> extends ExpressionHelperBase {
public static <T> ConcurrentExpressionHelper<T> addListener(
ConcurrentExpressionHelper<T> helper, ObservableValue<T> observable, InvalidationListener listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
observable.getValue(); // validate observable
return helper == null ? new Invalidation1<>(observable, listener) : helper.addListener(listener);
}
public static <T> ConcurrentExpressionHelper<T> removeListener(
ConcurrentExpressionHelper<T> helper, InvalidationListener listener) {
if (listener == null) {
throw new NullPointerException();
}
return helper == null ? null : helper.removeListener(listener);
}
public static <T> ConcurrentExpressionHelper<T> addListener(
ConcurrentExpressionHelper<T> helper, ObservableValue<T> observable, ChangeListener<? super T> listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
return helper == null ? new Change1<>(observable, listener) : helper.addListener(listener);
}
public static <T> ConcurrentExpressionHelper<T> removeListener(
ConcurrentExpressionHelper<T> helper, ChangeListener<? super T> listener) {
if (listener == null) {
throw new NullPointerException();
}
return helper == null ? null : helper.removeListener(listener);
}
public static <T> void fireValueChangedEvent(ConcurrentExpressionHelper<T> helper) {
if (helper != null) {
helper.fireValueChangedEvent();
}
}
final ObservableValue<T> observable;
private ConcurrentExpressionHelper(ObservableValue<T> observable) {
this.observable = observable;
}
abstract ConcurrentExpressionHelper<T> addListener(InvalidationListener listener);
abstract ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener);
abstract ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener);
abstract ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener);
abstract void fireValueChangedEvent();
static class Invalidation1<T> extends ConcurrentExpressionHelper<T> {
final InvalidationListener listener1;
Invalidation1(ObservableValue<T> observable, InvalidationListener listener) {
super(observable);
this.listener1 = Objects.requireNonNull(listener);
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
return new Invalidation3<>(observable, listener1, listener, null);
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
return listener.equals(listener1) ? null : this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
return new Invalidation3Change3<>(observable, listener1, null, null, listener, null, null);
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
return this;
}
@Override
void fireValueChangedEvent() {
try {
listener1.invalidated(observable);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
static class Invalidation3<T> extends ConcurrentExpressionHelper<T> {
final InvalidationListener listener1;
final InvalidationListener listener2;
final InvalidationListener listener3;
Invalidation3(ObservableValue<T> observable,
InvalidationListener listener1,
InvalidationListener listener2,
InvalidationListener listener3) {
super(observable);
this.listener1 = Objects.requireNonNull(listener1);
this.listener2 = Objects.requireNonNull(listener2);
this.listener3 = listener3;
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
if (listener3 == null) {
return new Invalidation3<>(observable, listener1, listener2, listener);
}
var helper = new Generic<>(observable, listener1, listener2, listener3, null, null, null);
helper.invalidationListeners.add(listener);
return helper;
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
if (listener.equals(listener3)) {
return new Invalidation3<>(observable, listener1, listener2, null);
}
if (listener.equals(listener2)) {
return listener3 != null ?
new Invalidation3<>(observable, listener1, listener3, null) :
new Invalidation1<>(observable, listener1);
}
if (listener.equals(listener1)) {
return listener3 != null ?
new Invalidation3<>(observable, listener2, listener3, null) :
new Invalidation1<>(observable, listener2);
}
return this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
return new Invalidation3Change3<>(observable, listener1, listener2, listener3, listener, null, null);
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
return this;
}
@Override
void fireValueChangedEvent() {
fireValueChangedEvent(listener1);
fireValueChangedEvent(listener2);
fireValueChangedEvent(listener3);
}
private void fireValueChangedEvent(InvalidationListener listener) {
if (listener != null) {
try {
listener.invalidated(observable);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
}
static class Change1<T> extends ConcurrentExpressionHelper<T> {
final ChangeListener<? super T> listener;
T currentValue;
Change1(ObservableValue<T> observable, ChangeListener<? super T> listener) {
super(observable);
this.listener = listener;
this.currentValue = observable.getValue();
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
return new Invalidation3Change3<>(
observable, listener, null, null, this.listener, null, null);
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
return this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
return new Change3<>(observable, this.listener, listener, null);
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
return listener.equals(this.listener) ? null : this;
}
@Override
void fireValueChangedEvent() {
T oldValue = currentValue;
currentValue = observable.getValue();
if (!Objects.equals(currentValue, oldValue)) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
}
static class Change3<T> extends ConcurrentExpressionHelper<T> {
final ChangeListener<? super T> listener1;
final ChangeListener<? super T> listener2;
final ChangeListener<? super T> listener3;
T currentValue;
Change3(ObservableValue<T> observable,
ChangeListener<? super T> listener1,
ChangeListener<? super T> listener2,
ChangeListener<? super T> listener3) {
super(observable);
this.listener1 = Objects.requireNonNull(listener1);
this.listener2 = Objects.requireNonNull(listener2);
this.listener3 = listener3;
this.currentValue = observable.getValue();
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
return new Invalidation3Change3<>(
observable, listener, null, null, listener1, listener2, listener3);
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
return this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
if (listener3 == null) {
return new Change3<>(observable, listener1, listener2, listener);
}
var helper = new Generic<>(observable, null, null, null, listener1, listener2, listener3);
helper.changeListeners.add(listener);
return helper;
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
if (listener.equals(listener3)) {
return new Change3<>(observable, listener1, listener2, null);
}
if (listener.equals(listener2)) {
return listener3 != null ?
new Change3<>(observable, listener1, listener3, null) :
new Change1<>(observable, listener1);
}
if (listener.equals(listener1)) {
return listener3 != null ?
new Change3<>(observable, listener2, listener3, null) :
new Change1<>(observable, listener2);
}
return this;
}
@Override
void fireValueChangedEvent() {
T oldValue = currentValue;
currentValue = observable.getValue();
if (!Objects.equals(currentValue, oldValue)) {
fireValueChangedEvent(listener1, oldValue);
fireValueChangedEvent(listener2, oldValue);
fireValueChangedEvent(listener3, oldValue);
}
}
private void fireValueChangedEvent(ChangeListener<? super T> listener, T oldValue) {
if (listener != null) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
}
static class Invalidation3Change3<T> extends ConcurrentExpressionHelper<T> {
final InvalidationListener invalidate1;
final InvalidationListener invalidate2;
final InvalidationListener invalidate3;
final ChangeListener<? super T> change1;
final ChangeListener<? super T> change2;
final ChangeListener<? super T> change3;
T currentValue;
Invalidation3Change3(ObservableValue<T> observable,
InvalidationListener invalidate1,
InvalidationListener invalidate2,
InvalidationListener invalidate3,
ChangeListener<? super T> change1,
ChangeListener<? super T> change2,
ChangeListener<? super T> change3) {
super(observable);
this.invalidate1 = Objects.requireNonNull(invalidate1);
this.invalidate2 = invalidate2;
this.invalidate3 = invalidate3;
this.change1 = Objects.requireNonNull(change1);
this.change2 = change2;
this.change3 = change3;
this.currentValue = observable.getValue();
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
if (invalidate2 == null) {
return new Invalidation3Change3<>(
observable, invalidate1, listener, null, change1, change2, change3);
}
if (invalidate3 == null) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, listener, change1, change2, change3);
}
var helper = new Generic<>(observable, invalidate1, invalidate2, invalidate3, change1, change2, change3);
helper.invalidationListeners.add(listener);
return helper;
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
if (listener.equals(invalidate1)) {
if (invalidate2 == null) {
return change2 != null ?
new Change3<>(observable, change1, change2, change3) :
new Change1<>(observable, change1);
}
return new Invalidation3Change3<>(
observable, invalidate2, invalidate3, null, change1, change2, change3);
}
if (listener.equals(invalidate2)) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate3, null, change1, change2, change3);
}
if (listener.equals(invalidate3)) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, null, change1, change2, change3);
}
return this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
if (change2 == null) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, invalidate3, change1, listener, null);
}
if (change3 == null) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, invalidate3, change1, change2, listener);
}
var helper = new Generic<>(observable, invalidate1, invalidate2, invalidate3, change1, change2, change3);
helper.changeListeners.add(listener);
return helper;
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
if (listener.equals(change1)) {
if (change2 == null) {
return invalidate2 != null ?
new Invalidation3<>(observable, invalidate1, invalidate2, invalidate3) :
new Invalidation1<>(observable, invalidate1);
}
return new Invalidation3Change3<>(
observable, invalidate1, invalidate3, invalidate3, change2, change3, null);
}
if (listener.equals(change2)) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, invalidate3, change1, change3, null);
}
if (listener.equals(change3)) {
return new Invalidation3Change3<>(
observable, invalidate1, invalidate2, invalidate3, change1, change2, null);
}
return this;
}
@Override
void fireValueChangedEvent() {
fireValueChangedEvent(invalidate1);
fireValueChangedEvent(invalidate2);
fireValueChangedEvent(invalidate3);
T oldValue = currentValue;
currentValue = observable.getValue();
if (!Objects.equals(currentValue, oldValue)) {
fireValueChangedEvent(change1, oldValue);
fireValueChangedEvent(change2, oldValue);
fireValueChangedEvent(change3, oldValue);
}
}
private void fireValueChangedEvent(InvalidationListener listener) {
if (listener != null) {
try {
listener.invalidated(observable);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
private void fireValueChangedEvent(ChangeListener<? super T> listener, T oldValue) {
if (listener != null) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
}
static class Generic<T> extends ConcurrentExpressionHelper<T> {
final Queue<InvalidationListener> invalidationListeners = new ConcurrentLinkedQueue<>();
final Queue<ChangeListener<? super T>> changeListeners = new ConcurrentLinkedQueue<>();
T currentValue;
Generic(ObservableValue<T> observable,
InvalidationListener invalidate0,
InvalidationListener invalidate1,
InvalidationListener invalidate2,
ChangeListener<? super T> change0,
ChangeListener<? super T> change1,
ChangeListener<? super T> change2) {
super(observable);
if (invalidate0 != null) {
invalidationListeners.add(invalidate0);
if (invalidate1 != null) invalidationListeners.add(invalidate1);
if (invalidate2 != null) invalidationListeners.add(invalidate2);
}
if (change0 != null) {
currentValue = observable.getValue();
changeListeners.add(change0);
if (change1 != null) changeListeners.add(change1);
if (change2 != null) changeListeners.add(change2);
}
}
@Override
ConcurrentExpressionHelper<T> addListener(InvalidationListener listener) {
invalidationListeners.add(listener);
return this;
}
@Override
ConcurrentExpressionHelper<T> removeListener(InvalidationListener listener) {
invalidationListeners.remove(listener);
return this;
}
@Override
ConcurrentExpressionHelper<T> addListener(ChangeListener<? super T> listener) {
currentValue = observable.getValue();
changeListeners.add(listener);
return this;
}
@Override
ConcurrentExpressionHelper<T> removeListener(ChangeListener<? super T> listener) {
changeListeners.remove(listener);
return this;
}
@Override
void fireValueChangedEvent() {
for (InvalidationListener listener : invalidationListeners) {
try {
listener.invalidated(observable);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
T oldValue = currentValue;
currentValue = observable.getValue();
if (!Objects.equals(currentValue, oldValue)) {
for (ChangeListener<? super T> listener : changeListeners) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment