/******************************************************************************
* Copyright (c) 2015, 2016 itemis AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexander Nyßen (itemis AG) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.gef.common.collections;
import java.util.Set;
import com.google.common.collect.SetMultimap;
/**
* A {@link SetMultimapChangeListener} is the notification target for changes
* related to an {@link ObservableSetMultimap}.
*
* @param <K>
* The key type of the {@link ObservableSetMultimap}.
* @param <V>
* The value type of the {@link ObservableSetMultimap}.
*
* @author anyssen
*
*/
public interface SetMultimapChangeListener<K, V> {
/**
* Represents an elementary change done to an {@link ObservableSetMultimap},
* related to a single key but to potentially multiple values.
*
* @param <K>
* The key type of the {@link ObservableSetMultimap}.
* @param <V>
* The value type of the {@link ObservableSetMultimap}.
*/
public static abstract class Change<K, V> {
private final ObservableSetMultimap<K, V> source;
/**
* Creates a new (atomic) change associated with the given source
* {@link ObservableSetMultimap}.
*
* @param source
* The source of the change.
*/
public Change(ObservableSetMultimap<K, V> source) {
this.source = source;
}
/**
* The key associated with the current elementary sub-change.
* <p>
* This method depends on the state of the internal cursor that can be
* manipulated via {@link #next()} and {@link #reset()}.
*
* @return The key for which values were added or removed.
*/
public abstract K getKey();
/**
* Returns an unmodifiable {@link SetMultimap} that contains the
* previous contents of the source {@link ObservableSetMultimap} before
* the atomic change was applied.
* <p>
* This method does not depend on the state of the internal cursor, may
* thus be accessed independent on which elementary sub-change is
* currently processed.
*
* @return An unmodifiable {@link SetMultimap} representing the contents
* of the {@link ObservableSetMultimap} before the change.
*/
public abstract SetMultimap<K, V> getPreviousContents();
/**
* The source {@link ObservableSetMultimap} this (atomic) change is
* associated with.
* <p>
* This method does not depend on the state of the internal cursor, may
* thus be accessed independent on which elementary sub-change is
* currently processed.
*
* @return The source {@link ObservableSetMultimap}.
*/
public ObservableSetMultimap<K, V> getSetMultimap() {
return source;
}
/**
* Retrieves the values that were added for the given key in the current
* elementary sub-change.
* <p>
* This method depends on the state of the internal cursor that can be
* manipulated via {@link #next()} and {@link #reset()}.
*
* @return The values that have become associated with the key.
*/
public abstract Set<V> getValuesAdded();
/**
* Retrieves the values that were removed for the given key in the
* current elementary sub-change.
* <p>
* This method depends on the state of the internal cursor that can be
* manipulated via {@link #next()} and {@link #reset()}.
*
* @return The values previously associated with the key.
*/
public abstract Set<V> getValuesRemoved();
/**
* Places the internal cursor on the next elementary sub-change, so that
* it be processed using {@link #getKey()}, {@link #getValuesAdded()},
* and {@link #getValuesRemoved()}, {@link #wasAdded()}, and
* {@link #wasRemoved()}. This method has to be called initially to have
* the internal cursor point to the first elementary sub-change that is
* comprised.
*
* @return <code>true</code> if the internal cursor could be switched to
* the next elementary sub-change, <code>false</code> if the
* current elementary sub-change was the last change that is
* comprised.
*/
public abstract boolean next();
/**
* Reset the internal cursor to the initial state, so that the first
* elementary sub-change can be accessed by calling {@link #next()}.
*/
public abstract void reset();
/**
* Indicates whether elements were added to the
* {@link ObservableSetMultimap} during this elementary sub-change.
* <p>
* This method depends on the state of the internal cursor that can be
* manipulated via {@link #next()} and {@link #reset()}.
*
* @return <code>true</code> if new values or (key-value) entries were
* added to the {@link ObservableSetMultimap},
* <code>false</code> otherwise.
*/
public abstract boolean wasAdded();
/**
* Indicates whether elements were removed from the
* {@link ObservableSetMultimap} in the current elementary sub-change.
* <p>
* This method depends on the state of the internal cursor that can be
* manipulated via {@link #next()} and {@link #reset()}.
*
* @return <code>true</code> if old values or (key-value) entries were
* removed from the {@link ObservableSetMultimap},
* <code>false</code> otherwise.
*/
public abstract boolean wasRemoved();
}
/**
* Called after a change has been made to an {@link ObservableSetMultimap}.
* This method is called whenever a change to a single key is performed. In
* case of complex operation like {@link ObservableSetMultimap#clear()} or
* {@link ObservableSetMultimap#putAll(Object, Iterable)} multiple
* invocations will occur.
*
* @param change
* A {@link Change} object representing the changes that were
* performed on the source {@link ObservableSetMultimap}.
*/
void onChanged(Change<? extends K, ? extends V> change);
}