/** * The given name has been modified or removed in this context. Invalidate all local value * computations and listeners that depend on this name. */ public void invalidate(String name, int eventType, Object oldValue, Set<Scheduled> scheduled) { ContextChangeEvent event = new ContextChangeEvent(this, eventType, null, name, oldValue); ValueComputation computation = localValueComputations.get(name); if (computation != null) { if (computation.shouldRemove(event)) { localValueComputations.remove(name); Collection<HashSet<Computation>> allListeners = listeners.values(); for (HashSet<Computation> group : allListeners) { group.remove(computation); } } computation.handleInvalid(event, scheduled); } HashSet<Computation> namedComputations = listeners.get(name); if (namedComputations != null) { for (Computation listener : namedComputations) { listener.handleInvalid(event, scheduled); } } // invalidate this name in child contexts for (EclipseContext childContext : getChildren()) { childContext.invalidate(name, eventType, oldValue, scheduled); } }
public boolean containsKey(String name, boolean localOnly) { if (isSetLocally(name)) return true; if (localOnly) return false; EclipseContext parent = getParent(); if (parent != null && parent.containsKey(name, localOnly)) return true; return false; }
private void collectDependentNames(Set<String> usedNames) { Set<String> tmp = listeners.keySet(); // clone internal name list usedNames.addAll(tmp); for (EclipseContext childContext : getChildren()) { childContext.collectDependentNames(usedNames); } }
protected EclipseContext getRoot() { EclipseContext current = this; EclipseContext root; do { root = current; current = current.getParent(); } while (current != null); return root; }
public void addWaiting(Computation cp) { // traverse to the root node EclipseContext parent = getParent(); if (parent != null) { parent.addWaiting(cp); return; } if (waiting == null) // could happen on re-parent waiting = Collections.synchronizedList(new ArrayList<Computation>()); waiting.add(cp); }
public void setParent(IEclipseContext parent) { EclipseContext parentContext = (EclipseContext) localValues.get(PARENT); if (parent == parentContext) return; // no-op if (parentContext != null) parentContext.removeChild(this); Set<Scheduled> scheduled = new LinkedHashSet<Scheduled>(); handleReparent((EclipseContext) parent, scheduled); localValues.put(PARENT, parent); if (parent != null) ((EclipseContext) parent).addChild(this); processScheduled(scheduled); return; }
private void handleReparent(EclipseContext newParent, Set<Scheduled> scheduled) { // TBD should we lock waiting list while doing reparent? // Add "boolean inReparent" on the root context and process right away? processWaiting(); // 1) everybody who depends on me: I need to collect combined list of names injected Set<String> usedNames = new HashSet<String>(); collectDependentNames(usedNames); // 2) for each used name: for (Iterator<String> i = usedNames.iterator(); i.hasNext(); ) { String name = i.next(); if (localValues.containsKey(name)) continue; // it is a local value Object oldValue = get(name); Object newValue = (newParent != null) ? newParent.get(name) : null; if (oldValue != newValue) invalidate(name, ContextChangeEvent.ADDED, oldValue, scheduled); } ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.ADDED, null, null, null); for (Computation computation : localValueComputations.values()) { Collection<HashSet<Computation>> allListeners = listeners.values(); for (HashSet<Computation> group : allListeners) { group.remove(computation); } computation.handleInvalid(event, scheduled); } localValueComputations.clear(); }
public void processWaiting() { // traverse to the root node EclipseContext parent = getParent(); if (parent != null) { parent.processWaiting(); return; } if (waiting == null) return; // create update notifications Computation[] ls = waiting.toArray(new Computation[waiting.size()]); waiting.clear(); ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.UPDATE, null, null, null); for (int i = 0; i < ls.length; i++) { if (ls[i] instanceof TrackableComputationExt) ((TrackableComputationExt) ls[i]).update(event); } }
@Override public synchronized void resumeRecording() { Stack<Computation> current = EclipseContext.getCalculatedComputations(); Computation plug = current.pop(); if (plug != null) throw new IllegalArgumentException( "Internal error in nested computation processing"); //$NON-NLS-1$ }
public boolean internalModify(String name, Object value, Set<Scheduled> scheduled) { boolean containsKey = localValues.containsKey(name); if (containsKey) { if (!checkModifiable(name)) { String tmp = "Variable " + name + " is not modifiable in the context " + toString(); //$NON-NLS-1$ //$NON-NLS-2$ throw new IllegalArgumentException(tmp); } Object oldValue = localValues.put(name, value); if (value != oldValue) invalidate(name, ContextChangeEvent.ADDED, oldValue, scheduled); return true; } EclipseContext parent = getParent(); if (parent != null) return parent.internalModify(name, value, scheduled); return false; }
/* * (non-Javadoc) * * @see org.eclipse.e4.core.services.context.IEclipseContext#dispose() */ public void dispose() { // dispose of child contexts first for (EclipseContext childContext : getChildren()) { childContext.dispose(); } ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.DISPOSE, null, null, null); Set<Scheduled> scheduled = new LinkedHashSet<Scheduled>(); Set<Computation> allComputations = getListeners(); listeners.clear(); allComputations.addAll(activeRATs); activeRATs.clear(); for (Computation computation : allComputations) { computation.handleInvalid(event, scheduled); } processScheduled(scheduled); synchronized (notifyOnDisposal) { for (IContextDisposalListener listener : notifyOnDisposal) { listener.disposed(this); } } localValueComputations.clear(); // if this was the parent's active child, deactivate it EclipseContext parent = getParent(); if (parent != null) { if (this == parent.getActiveChild()) parent.set(ACTIVE_CHILD, null); } localValues.clear(); if (parent != null) parent.removeChild(this); if (debugAddOn != null) debugAddOn.notify(this, IEclipseContextDebugger.EventType.DISPOSED, null); }
public void deactivate() { EclipseContext parent = getParent(); if (parent == null) return; if (this != parent.getActiveChild()) return; // this is not an active context; return parent.set(ACTIVE_CHILD, null); }
public void activate() { EclipseContext parent = getParent(); if (parent == null) return; if (this == parent.getActiveChild()) return; parent.set(ACTIVE_CHILD, this); }
@Override public synchronized void pauseRecording() { Stack<Computation> current = EclipseContext.getCalculatedComputations(); current.push(null); }