/*
* Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved.
*
* This file is part of the Jspresso framework.
*
* Jspresso is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jspresso 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Jspresso. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jspresso.framework.util.event;
import java.util.Collections;
import java.util.Set;
import gnu.trove.set.hash.THashSet;
import gnu.trove.set.hash.TLinkedHashSet;
/**
* Helper class to ease the IValueChangeListener management.
*
* @author Vincent Vandenschrick
*/
public class ValueChangeSupport implements IValueChangeSource {
private Set<IValueChangeListener> inhibitedListeners;
private Set<IValueChangeListener> listeners;
private Object source;
/**
* Constructs a new value change support.
*
* @param source
* The source to which this ValueChangeSupport is attached. source
* will serve as {@code source} of fired ValueChangeEvent if no
* other is provided.
*/
public ValueChangeSupport(Object source) {
if (source == null) {
throw new NullPointerException();
}
this.source = source;
}
/**
* Registers a listener to be excluded (generally temporarily) from the
* notification process without being removed from the actual listeners
* collection.
*
* @param listener
* the excluded listener.
*/
public void addInhibitedListener(IValueChangeListener listener) {
if (inhibitedListeners == null && listener != null) {
inhibitedListeners = new THashSet<>(1);
}
if (inhibitedListeners != null) {
inhibitedListeners.add(listener);
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void addValueChangeListener(IValueChangeListener listener) {
if (listener != null) {
if (listeners == null) {
listeners = new TLinkedHashSet<>(1);
}
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
}
/**
* Fires a new {@code ValueChangeEvent} built with {@code source} as
* source and parameters as old and new values.
*
* @param oldValue
* The old connector's value
* @param newValue
* The new connector's value
*/
public void fireValueChange(Object oldValue, Object newValue) {
ValueChangeEvent evt = new ValueChangeEvent(source, oldValue, newValue);
fireValueChange(evt);
}
/**
* Propagates the {@code ValueChangeEvent} as is (i.e. without modifying
* its source) to the listeners.
*
* @param evt
* the propagated {@code ValueChangeEvent}
*/
public void fireValueChange(ValueChangeEvent evt) {
if (listeners != null && evt.needsFiring()) {
for (IValueChangeListener listener : listeners.toArray(new IValueChangeListener[listeners.size()])) {
if (inhibitedListeners == null
|| !inhibitedListeners.contains(listener)) {
if (listeners.contains(listener)) {
listener.valueChange(evt);
}
}
}
}
}
/**
* Gets the listeners.
*
* @return the listeners.
*/
@Override
public Set<IValueChangeListener> getValueChangeListeners() {
if (listeners != null) {
return new TLinkedHashSet<>(listeners);
}
return Collections.emptySet();
}
/**
* Gets whether the listener collection is empty.
*
* @return true if the listener collection is empty.
*/
public boolean isEmpty() {
return listeners == null || listeners.isEmpty();
}
/**
* Registers a listener to be re-included to the notification process without
* being re-added to the actual listeners collection.
*
* @param listener
* the previously excluded listener.
*/
public void removeInhibitedListener(IValueChangeListener listener) {
if (inhibitedListeners == null || listener == null) {
return;
}
inhibitedListeners.remove(listener);
if (inhibitedListeners.size() == 0) {
inhibitedListeners = null;
}
}
/**
* {@inheritDoc}
*/
@Override
public synchronized void removeValueChangeListener(
IValueChangeListener listener) {
if (listeners == null || listener == null) {
return;
}
listeners.remove(listener);
if (listeners.size() == 0) {
listeners = null;
}
}
}