com.cedarsoft.history.DelegatingObjectAccess Maven / Gradle / Ivy
package com.cedarsoft.history;
import com.cedarsoft.Lockable;
import com.cedarsoft.NullLock;
import com.cedarsoft.PartTimeObjectAdd;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
/**
* An object access that is based on the current selection
*/
public class DelegatingObjectAccess implements ObservableObjectAccess, PartTimeObjectAdd {
@NotNull
private final ElementsListener delegatingListener = new ElementsListener() {
public void elementsDeleted( @NotNull ElementsChangedEvent extends T> event ) {
for ( ElementsListener super T> listener : listeners ) {
listener.elementsDeleted( event );
}
}
public void elementsAdded( @NotNull ElementsChangedEvent extends T> event ) {
for ( ElementsListener super T> listener : listeners ) {
listener.elementsAdded( event );
}
}
public void elementsChanged( @NotNull ElementsChangedEvent extends T> event ) {
for ( ElementsListener super T> listener : listeners ) {
listener.elementsChanged( event );
}
}
};
@NotNull
private final List> listeners = new ArrayList>();
@NotNull
private final List> delegateListeners = new ArrayList>();
@NotNull
private final List partTimeListeners = new ArrayList();
/**
* Creates a new delegating object access
*
* @param currentDelegate the current delegate
*/
public DelegatingObjectAccess( @Nullable ObservableObjectAccess currentDelegate ) {
this.currentDelegate = currentDelegate;
}
/**
* Returns the current delegate
*
* @return the current delegate
*/
@NotNull
protected ObservableObjectAccess getCurrentDelegateSafe() {
if ( currentDelegate == null ) {
throw new IllegalStateException( "No current delegate available" );
}
return currentDelegate;
}
@Nullable
public ObservableObjectAccess getCurrentDelegate() {
return currentDelegate;
}
@Nullable
protected ObservableObjectAccess currentDelegate;
public boolean isCurrentDelegatingObjectAccessAvailable() {
return currentDelegate != null;
}
/**
* Sets the current delegate
*
* @param currentDelegate the current delegate
*/
public void setCurrentDelegate( @Nullable ObservableObjectAccess currentDelegate ) {
//noinspection ObjectEquality
if ( this.currentDelegate == currentDelegate ) {
return;
}
ObservableObjectAccess oldDelegate = this.currentDelegate;
this.currentDelegate = currentDelegate;
unregister( oldDelegate );
register();
//Notify the listeners
for ( DelegateListener delegateListener : delegateListeners ) {
delegateListener.delegateChanged( currentDelegate );
}
if ( this.currentDelegate == null ) { //has changed to *not* available
for ( PartTimeListener partTimeListener : partTimeListeners ) {
partTimeListener.addNotAvailable();
}
} else if ( oldDelegate == null ) { //has changed to available
for ( PartTimeListener partTimeListener : partTimeListeners ) {
partTimeListener.addAvailable();
}
}
}
private void register() {
ObservableObjectAccess delegate = currentDelegate;
if ( delegate != null ) {
ReadWriteLock lock = getLock();
lock.writeLock().lock();
try {
//Remove all meetings
for ( ElementsListener super T> listener : listeners ) {
listener.elementsAdded( new ElementsChangedEvent( delegate, delegate.getElements(), 0, delegate.getElements().size() - 1 ) );
}
delegate.addElementListener( delegatingListener );
} finally {
lock.writeLock().unlock();
}
}
}
private void unregister( @Nullable ObservableObjectAccess oldDelegate ) {
if ( oldDelegate == null ) {
return;
}
ReadWriteLock lock = getLock( oldDelegate );
lock.writeLock().lock();
try {
//Notify the listeners about removal of all elements
for ( ElementsListener super T> listener : listeners ) {
listener.elementsDeleted( new ElementsChangedEvent( oldDelegate, oldDelegate.getElements(), 0, oldDelegate.getElements().size() - 1 ) );
}
oldDelegate.removeElementListener( delegatingListener );
} finally {
lock.writeLock().unlock();
}
}
/**
* Returns the lock for the current delegate
*
* @return the lock for the current delegate
*/
@NotNull
public ReadWriteLock getLock() {
ObservableObjectAccess delegate = getCurrentDelegateSafe();
return getLock( delegate );
}
@NotNull
private ReadWriteLock getLock( @Nullable ObservableObjectAccess delegate ) {
if ( delegate != null && delegate instanceof Lockable ) {
return ( ( Lockable ) delegate ).getLock();
} else {
return NullLock.LOCK;
}
}
public void commit( @NotNull T element ) {
getCurrentDelegateSafe().commit( element );
}
@NotNull
public List extends T> getElements() {
if ( isCurrentDelegatingObjectAccessAvailable() ) {
return getCurrentDelegateSafe().getElements();
} else {
return Collections.emptyList();
}
}
public void add( @NotNull T element ) {
getCurrentDelegateSafe().add( element );
}
public void remove( @NotNull T element ) {
getCurrentDelegateSafe().remove( element );
}
public void addElementListener( @NotNull ElementsListener super T> listener ) {
this.listeners.add( listener );
}
public void removeElementListener( @NotNull ElementsListener super T> listener ) {
this.listeners.remove( listener );
}
public void addDelegateListener( @NotNull DelegateListener listener ) {
this.delegateListeners.add( listener );
}
public void removeDelegateListener( @NotNull DelegateListener listener ) {
this.delegateListeners.remove( listener );
}
public boolean canAdd() {
return isCurrentDelegatingObjectAccessAvailable();
}
public void addPartTimeListener( @NotNull PartTimeListener listener ) {
partTimeListeners.add( listener );
}
public void removePartTimeListener( @NotNull PartTimeListener listener ) {
partTimeListeners.remove( listener );
}
public interface DelegateListener {
/**
* Is called if the delegate has changed
*
* @param newDelegate the new delegate
*/
void delegateChanged( @Nullable ObservableObjectAccess newDelegate );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy