blob: 7d912b5d1a49904a6a87802ca5a4ce6b5908e943 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.core.services.internal.context;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.e4.core.services.context.ContextChangeEvent;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.injector.IObjectProvider;
abstract class Computation {
Map dependencies = new HashMap();
void addDependency(IEclipseContext context, String name) {
Set properties = (Set) dependencies.get(context);
if (properties == null) {
properties = new HashSet(4);
dependencies.put(context, properties);
}
properties.add(name);
}
final void clear(IEclipseContext context, String name) {
doClear();
stopListening(context, name);
}
protected void doClear() {
}
protected void doHandleInvalid(ContextChangeEvent event, List scheduled) {
}
/**
* Computations must define equals because they are stored in a set.
*/
public abstract boolean equals(Object arg0);
final void handleInvalid(ContextChangeEvent event, List scheduled) {
IObjectProvider provider = event.getContext();
IEclipseContext context = ((ObjectProviderContext) provider).getContext();
String name = event.getName();
Set names = (Set) dependencies.get(context);
if (name == null && event.getEventType() == ContextChangeEvent.DISPOSE) {
clear(context, null);
doHandleInvalid(event, scheduled);
} else if (names != null && names.contains(name)) {
clear(context, name);
doHandleInvalid(event, scheduled);
}
}
final void handleUninjected(ContextChangeEvent event, List scheduled) {
doHandleInvalid(event, scheduled);
}
/**
* Computations must define hashCode because they are stored in a set.
*/
public abstract int hashCode();
private String mapToString(Map map) {
StringBuffer result = new StringBuffer('{');
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
result.append(entry.getKey());
result.append("->(");
Set set = (Set) entry.getValue();
for (Iterator it2 = set.iterator(); it2.hasNext();) {
String name = (String) it2.next();
result.append(name);
if (it2.hasNext()) {
result.append(",");
}
}
result.append(")");
if (it.hasNext()) {
result.append(",");
}
}
return result.toString();
}
/**
* Remove this computation from all contexts that are tracking it
*/
protected void removeAll(EclipseContext originatingContext) {
for (Iterator it = dependencies.keySet().iterator(); it.hasNext();) {
((EclipseContext) it.next()).listeners.remove(this);
}
dependencies.clear();
// Bug 304859
originatingContext.listeners.remove(this);
}
void startListening(EclipseContext originatingContext) {
if (EclipseContext.DEBUG)
System.out.println(toString() + " now listening to: " //$NON-NLS-1$
+ mapToString(dependencies));
for (Iterator it = dependencies.keySet().iterator(); it.hasNext();) {
EclipseContext c = (EclipseContext) it.next(); // XXX IEclipseContex
if (c.listeners.contains(this)) { // nested
for (Iterator exitsting = c.listeners.iterator(); exitsting.hasNext();) {
Computation existingComputation = (Computation) exitsting.next();
if (!equals(existingComputation))
continue;
for (Iterator newDependencies = dependencies.keySet().iterator(); newDependencies
.hasNext();) {
IEclipseContext newDepenecyContext = (IEclipseContext) newDependencies
.next();
if (existingComputation.dependencies.containsKey(newDepenecyContext))
((Set) existingComputation.dependencies.get(newDepenecyContext))
.addAll((Set) dependencies.get(newDepenecyContext));
else
existingComputation.dependencies.put(newDepenecyContext, dependencies
.get(newDepenecyContext));
}
break;
}
} else
c.listeners.add(this);
}
// Bug 304859
if (!dependencies.containsKey(originatingContext))
originatingContext.listeners.remove(this);
}
protected void stopListening(IEclipseContext context, String name) {
if (name == null) {
if (EclipseContext.DEBUG)
System.out.println(toString() + " no longer listening to " + context); //$NON-NLS-1$
dependencies.remove(context);
return;
}
Set properties = (Set) dependencies.get(context);
if (properties != null) {
if (EclipseContext.DEBUG)
System.out.println(toString() + " no longer listening to " + context + "," + name); //$NON-NLS-1$
// Bug 304859 - causes reordering of listeners
// ((EclipseContext) context).listeners.remove(this); // XXX
// IEclipseContext
properties.remove(name);
// if we no longer track any values in the context, remove dependency
if (properties.isEmpty())
dependencies.remove(context);
}
}
public Set dependsOnNames(IEclipseContext context) {
return (Set) dependencies.get(context);
}
}