blob: 7e957123c18687f0067c2c320960d3d6c1fdb2d7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.core.internal.contexts;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Listeners are held wrapped in weak references and are removed if no other [strong] reference
* exists.
*/
public class WeakGroupedListenerList {
public static class WeakComputationReference extends WeakReference<Computation> {
final private int hashCode;
public WeakComputationReference(Computation computation) {
super(computation);
hashCode = computation.hashCode();
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!WeakComputationReference.class.equals(obj.getClass()))
return super.equals(obj);
Computation computation = get();
Computation otherComputation = ((WeakComputationReference) obj).get();
if (computation == null && otherComputation == null)
return true;
if (computation == null || otherComputation == null)
return false;
return computation.equals(otherComputation);
}
}
private Map<String, HashSet<WeakComputationReference>> listeners = new HashMap<>(10, 0.8f);
synchronized public void add(String groupName, Computation computation) {
HashSet<WeakComputationReference> nameListeners = listeners.get(groupName);
if (nameListeners == null) {
nameListeners = new HashSet<>(30, 0.75f);
nameListeners.add(new WeakComputationReference(computation));
listeners.put(groupName, nameListeners);
}
nameListeners.add(new WeakComputationReference(computation));
}
synchronized public void remove(Computation computation) {
WeakComputationReference ref = new WeakComputationReference(computation);
Collection<HashSet<WeakComputationReference>> allListeners = listeners.values();
for (HashSet<WeakComputationReference> group : allListeners) {
group.remove(ref);
}
}
synchronized public Set<String> getNames() {
Set<String> tmp = listeners.keySet(); // clone internal name list
Set<String> usedNames = new HashSet<>(tmp.size());
usedNames.addAll(tmp);
return usedNames;
}
synchronized public void clear() {
listeners.clear();
}
synchronized public Set<Computation> getListeners() {
Collection<HashSet<WeakComputationReference>> collection = listeners.values();
Set<Computation> result = new HashSet<>();
for (HashSet<WeakComputationReference> set : collection) {
for (Iterator<WeakComputationReference> i = set.iterator(); i.hasNext();) {
WeakComputationReference ref = i.next();
Computation computation = ref.get();
if (computation == null || !computation.isValid()) {
i.remove(); // do a clean-up while we are here
} else
result.add(computation);
}
}
return result;
}
synchronized public Set<Computation> getListeners(String groupName) {
HashSet<WeakComputationReference> tmp = listeners.get(groupName);
if (tmp == null)
return null;
Set<Computation> result = new HashSet<>(tmp.size());
for (Iterator<WeakComputationReference> i = tmp.iterator(); i.hasNext();) {
WeakComputationReference ref = i.next();
Computation computation = ref.get();
if (computation == null || !computation.isValid()) {
i.remove(); // do a clean-up while we are here
} else
result.add(computation);
}
return result;
}
synchronized public void cleanup() {
boolean cleanGroups = false;
for (HashSet<WeakComputationReference> set : listeners.values()) {
for (Iterator<WeakComputationReference> i = set.iterator(); i.hasNext();) {
WeakComputationReference ref = i.next();
Computation computation = ref.get();
if (computation == null || !computation.isValid())
i.remove();
}
if (set.isEmpty())
cleanGroups = true;
}
if (cleanGroups) {
Set<Entry<String, HashSet<WeakComputationReference>>> entries = listeners.entrySet();
for (Iterator<Entry<String, HashSet<WeakComputationReference>>> i = entries.iterator(); i.hasNext();) {
Entry<String, HashSet<WeakComputationReference>> entry = i.next();
HashSet<WeakComputationReference> value = entry.getValue();
if (value == null || value.isEmpty())
i.remove();
}
}
}
}