/*******************************************************************************
* Copyright (c) 2009, 2016 Wind River Systems 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.tests.dsf;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.ILabelUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ITreeModelViewer;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.jface.viewers.TreePath;
/**
* @since 2.2
*/
public class ViewerUpdatesListener
implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener, IViewerUpdatesListenerConstants,
IStateUpdateListener, IPropertiesUpdateListener
{
private ITreeModelViewer fViewer;
private boolean fFailOnRedundantUpdates;
private Set<IViewerUpdate> fRedundantUpdates = new HashSet<IViewerUpdate>();
private boolean fFailOnMultipleModelUpdateSequences;
private boolean fMultipleModelUpdateSequencesObserved;
private boolean fFailOnMultipleLabelUpdateSequences;
private boolean fMultipleLabelUpdateSequencesObserved;
private Set<TreePath> fHasChildrenUpdatesScheduled = makeTreePathSet();
private Set<IViewerUpdate> fHasChildrenUpdatesRunning = new HashSet<IViewerUpdate>();
private Set<IViewerUpdate> fHasChildrenUpdatesCompleted = new HashSet<IViewerUpdate>();
private Map<TreePath, Set<Integer>> fChildrenUpdatesScheduled = makeTreePathMap();
private Set<IViewerUpdate> fChildrenUpdatesRunning = new HashSet<IViewerUpdate>();
private Set<IViewerUpdate> fChildrenUpdatesCompleted = new HashSet<IViewerUpdate>();
private Set<TreePath> fChildCountUpdatesScheduled = makeTreePathSet();
private Set<IViewerUpdate> fChildCountUpdatesRunning = new HashSet<IViewerUpdate>();
private Set<IViewerUpdate> fChildCountUpdatesCompleted = new HashSet<IViewerUpdate>();
private Set<TreePath> fLabelUpdates = makeTreePathSet();
private Set<IViewerUpdate> fLabelUpdatesRunning = new HashSet<IViewerUpdate>();
private Set<IViewerUpdate> fLabelUpdatesCompleted = new HashSet<IViewerUpdate>();
private Set<TreePath> fPropertiesUpdates = makeTreePathSet();
private Set<IViewerUpdate> fPropertiesUpdatesRunning = new HashSet<IViewerUpdate>();
private Set<IViewerUpdate> fPropertiesUpdatesCompleted = new HashSet<IViewerUpdate>();
// private Set<TreePath> fProxyModels = new HashSet<TreePath>();
private Set<TreePath> fStateUpdates = makeTreePathSet();
private boolean fContentSequenceStarted;
private boolean fContentSequenceComplete;
private boolean fLabelUpdatesStarted;
private boolean fLabelSequenceComplete;
private boolean fModelChangedComplete;
private boolean fStateSaveStarted;
private boolean fStateSaveComplete;
private boolean fStateRestoreStarted;
private boolean fStateRestoreComplete;
private int fContentUpdatesCounter;
private int fLabelUpdatesCounter;
private int fPropertiesUpdatesCounter;
private int fTimeoutInterval = 60000;
private long fTimeoutTime;
protected Set<TreePath> makeTreePathSet() {
return new HashSet<TreePath>();
}
protected <V> Map<TreePath, V> makeTreePathMap() {
return new HashMap<TreePath, V>();
}
public ViewerUpdatesListener(ITreeModelViewer viewer, boolean failOnRedundantUpdates, boolean failOnMultipleModelUpdateSequences) {
this(viewer);
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleModelUpdateSequences(failOnMultipleModelUpdateSequences);
}
public ViewerUpdatesListener() {
// No viewer to register with. Client will have to register the listener manually.
}
public ViewerUpdatesListener(ITreeModelViewer viewer) {
fViewer = viewer;
fViewer.addLabelUpdateListener(this);
fViewer.addModelChangedListener(this);
fViewer.addStateUpdateListener(this);
fViewer.addViewerUpdateListener(this);
}
public void dispose() {
if (fViewer != null) {
fViewer.removeLabelUpdateListener(this);
fViewer.removeModelChangedListener(this);
fViewer.removeStateUpdateListener(this);
fViewer.removeViewerUpdateListener(this);
fViewer = null;
}
}
public void setFailOnRedundantUpdates(boolean failOnRedundantUpdates) {
fFailOnRedundantUpdates = failOnRedundantUpdates;
}
public void setFailOnMultipleModelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
fFailOnMultipleModelUpdateSequences = failOnMultipleLabelUpdateSequences;
}
public void setFailOnMultipleLabelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
fFailOnMultipleLabelUpdateSequences = failOnMultipleLabelUpdateSequences;
}
/**
* Sets the the maximum amount of time (in milliseconds) that the update listener
* is going to wait. If set to -1, the listener will wait indefinitely.
*/
public void setTimeoutInterval(int milis) {
fTimeoutInterval = milis;
}
public void reset() {
fRedundantUpdates.clear();
fMultipleLabelUpdateSequencesObserved = false;
fMultipleModelUpdateSequencesObserved = false;
fHasChildrenUpdatesScheduled.clear();
fHasChildrenUpdatesRunning.clear();
fHasChildrenUpdatesCompleted.clear();
fChildrenUpdatesScheduled.clear();
fChildrenUpdatesRunning.clear();
fChildrenUpdatesCompleted.clear();
fChildCountUpdatesScheduled.clear();
fChildCountUpdatesRunning.clear();
fChildCountUpdatesCompleted.clear();
fLabelUpdates.clear();
fLabelUpdatesRunning.clear();
fLabelUpdatesCompleted.clear();
// fProxyModels.clear();
fContentSequenceStarted = false;
fContentSequenceComplete = false;
fLabelUpdatesStarted = false;
fLabelSequenceComplete = false;
fStateSaveStarted = false;
fStateSaveComplete = false;
fStateRestoreStarted = false;
fStateRestoreComplete = false;
fTimeoutTime = System.currentTimeMillis() + fTimeoutInterval;
resetModelChanged();
}
public void resetModelChanged() {
fModelChangedComplete = false;
}
public void addHasChildrenUpdate(TreePath path) {
fHasChildrenUpdatesScheduled.add(path);
}
public void removeHasChildrenUpdate(TreePath path) {
fHasChildrenUpdatesScheduled.remove(path);
}
public void addChildCountUpdate(TreePath path) {
fChildCountUpdatesScheduled.add(path);
}
public void removeChildreCountUpdate(TreePath path) {
fChildCountUpdatesScheduled.remove(path);
}
public void addChildreUpdate(TreePath path, int index) {
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(path);
if (childrenIndexes == null) {
childrenIndexes = new TreeSet<Integer>();
fChildrenUpdatesScheduled.put(path, childrenIndexes);
}
childrenIndexes.add(index);
}
public void removeChildrenUpdate(TreePath path, int index) {
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(path);
if (childrenIndexes != null) {
childrenIndexes.remove(Integer.valueOf(index));
if (childrenIndexes.isEmpty()) {
fChildrenUpdatesScheduled.remove(path);
}
}
}
public void addLabelUpdate(TreePath path) {
fLabelUpdates.add(path);
}
public void addPropertiesUpdate(TreePath path) {
fPropertiesUpdates.add(path);
}
public void removeLabelUpdate(TreePath path) {
fLabelUpdates.remove(path);
}
public void addStateUpdate(TreePath path) {
fStateUpdates.add(path);
}
public void removeStateUpdate(TreePath path) {
fStateUpdates.remove(path);
}
public boolean isFinished() {
return isFinished(ALL_UPDATES_COMPLETE);
}
public boolean isTimedOut() {
return fTimeoutInterval > 0 && fTimeoutTime < System.currentTimeMillis();
}
public boolean isFinished(int flags) {
if (isTimedOut()) {
throw new RuntimeException("Timed Out: " + toString(flags));
}
if (fFailOnRedundantUpdates && !fRedundantUpdates.isEmpty()) {
fail("Redundant Updates: " + fRedundantUpdates.toString());
}
if (fFailOnMultipleLabelUpdateSequences && !fMultipleLabelUpdateSequencesObserved) {
fail("Multiple label update sequences detected");
}
if (fFailOnMultipleModelUpdateSequences && fMultipleModelUpdateSequencesObserved) {
fail("Multiple viewer update sequences detected");
}
if ( (flags & LABEL_SEQUENCE_COMPLETE) != 0) {
if (!fLabelSequenceComplete) return false;
}
if ( (flags & LABEL_SEQUENCE_STARTED) != 0) {
if (!fLabelUpdatesStarted) return false;
}
if ( (flags & LABEL_UPDATES) != 0) {
if (!fLabelUpdates.isEmpty()) return false;
}
if ( (flags & CONTENT_SEQUENCE_STARTED) != 0) {
if (!fContentSequenceStarted) return false;
}
if ( (flags & CONTENT_SEQUENCE_COMPLETE) != 0) {
if (!fContentSequenceComplete) return false;
}
if ( (flags & HAS_CHILDREN_UPDATES_STARTED) != 0) {
if (fHasChildrenUpdatesRunning.isEmpty() && fHasChildrenUpdatesCompleted.isEmpty()) return false;
}
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
if (!fHasChildrenUpdatesScheduled.isEmpty()) return false;
}
if ( (flags & CHILD_COUNT_UPDATES_STARTED) != 0) {
if (fChildCountUpdatesRunning.isEmpty() && fChildCountUpdatesCompleted.isEmpty()) return false;
}
if ( (flags & CHILD_COUNT_UPDATES) != 0) {
if (!fChildCountUpdatesScheduled.isEmpty()) return false;
}
if ( (flags & CHILDREN_UPDATES_STARTED) != 0) {
if (fChildrenUpdatesRunning.isEmpty() && fChildrenUpdatesCompleted.isEmpty()) return false;
}
if ( (flags & CHILDREN_UPDATES) != 0) {
if (!fChildrenUpdatesScheduled.isEmpty()) return false;
}
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
if (!fModelChangedComplete) return false;
}
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
if (!fStateSaveComplete) return false;
}
if ( (flags & STATE_SAVE_STARTED) != 0) {
if (!fStateSaveStarted) return false;
}
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
if (!fStateRestoreComplete) return false;
}
if ( (flags & STATE_RESTORE_STARTED) != 0) {
if (!fStateRestoreStarted) return false;
}
// if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
// if (fProxyModels.size() != 0) return false;
// }
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
if (fContentUpdatesCounter != 0) {
return false;
}
}
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
if (fLabelUpdatesCounter != 0) {
return false;
}
}
if ( (flags & PROPERTY_UPDATES) != 0) {
if (!fPropertiesUpdates.isEmpty()) return false;
}
if ( (flags & PROPERTY_UPDATES_STARTED) != 0) {
if (fPropertiesUpdatesRunning.isEmpty() && fPropertiesUpdatesCompleted.isEmpty()) return false;
}
return true;
}
@Override
public void updateStarted(IViewerUpdate update) {
synchronized (this) {
fContentUpdatesCounter++;
if (update instanceof IHasChildrenUpdate) {
fHasChildrenUpdatesRunning.add(update);
} if (update instanceof IChildrenCountUpdate) {
fChildCountUpdatesRunning.add(update);
} else if (update instanceof IChildrenUpdate) {
fChildCountUpdatesRunning.add(update);
}
}
}
@Override
public void updateComplete(IViewerUpdate update) {
synchronized (this) {
fContentUpdatesCounter--;
}
if (!update.isCanceled()) {
if (update instanceof IHasChildrenUpdate) {
fHasChildrenUpdatesRunning.remove(update);
fHasChildrenUpdatesCompleted.add(update);
if (!fHasChildrenUpdatesScheduled.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
fRedundantUpdates.add(update);
}
} if (update instanceof IChildrenCountUpdate) {
fChildCountUpdatesRunning.remove(update);
fChildCountUpdatesCompleted.add(update);
if (!fChildCountUpdatesScheduled.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
fRedundantUpdates.add(update);
}
} else if (update instanceof IChildrenUpdate) {
fChildrenUpdatesRunning.remove(update);
fChildrenUpdatesCompleted.add(update);
int start = ((IChildrenUpdate)update).getOffset();
int end = start + ((IChildrenUpdate)update).getLength();
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(update.getElementPath());
if (childrenIndexes != null) {
for (int i = start; i < end; i++) {
childrenIndexes.remove(Integer.valueOf(i));
}
if (childrenIndexes.isEmpty()) {
fChildrenUpdatesScheduled.remove(update.getElementPath());
}
} else if (fFailOnRedundantUpdates) {
fRedundantUpdates.add(update);
}
}
}
}
@Override
public void viewerUpdatesBegin() {
if (fFailOnMultipleModelUpdateSequences && fContentSequenceComplete) {
fMultipleModelUpdateSequencesObserved = true;
}
fContentSequenceStarted = true;
}
@Override
public void viewerUpdatesComplete() {
fContentSequenceComplete = true;
}
@Override
public void labelUpdateComplete(ILabelUpdate update) {
synchronized (this) {
fLabelUpdatesRunning.remove(update);
fLabelUpdatesCompleted.add(update);
fLabelUpdatesCounter--;
}
if (!fLabelUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
fRedundantUpdates.add(update);
}
}
@Override
public void labelUpdateStarted(ILabelUpdate update) {
synchronized (this) {
fLabelUpdatesRunning.add(update);
fLabelUpdatesCounter++;
}
}
@Override
public void labelUpdatesBegin() {
if (fFailOnMultipleLabelUpdateSequences && fLabelSequenceComplete) {
fMultipleLabelUpdateSequencesObserved = true;
}
fLabelUpdatesStarted = true;
}
@Override
public void labelUpdatesComplete() {
fLabelSequenceComplete = true;
}
@Override
public void propertiesUpdatesStarted(IPropertiesUpdate[] updates) {
for (IPropertiesUpdate update : updates) {
fPropertiesUpdatesRunning.add(update);
fPropertiesUpdatesCounter++;
}
}
@Override
public void propertiesUpdateCompleted(IPropertiesUpdate update) {
synchronized (this) {
fPropertiesUpdatesRunning.remove(update);
fPropertiesUpdatesCompleted.add(update);
fPropertiesUpdatesCounter--;
}
if (!fPropertiesUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
fRedundantUpdates.add(update);
}
}
@Override
public void modelChanged(IModelDelta delta, IModelProxy proxy) {
fModelChangedComplete = true;
}
@Override
public void stateRestoreUpdatesBegin(Object input) {
fStateRestoreStarted = true;
}
@Override
public void stateRestoreUpdatesComplete(Object input) {
fStateRestoreComplete = true;
}
@Override
public void stateSaveUpdatesBegin(Object input) {
fStateSaveStarted = true;
}
@Override
public void stateSaveUpdatesComplete(Object input) {
fStateSaveComplete = true;
}
@Override
public void stateUpdateComplete(Object input, IViewerUpdate update) {
}
@Override
public void stateUpdateStarted(Object input, IViewerUpdate update) {
}
private String toString(int flags) {
StringBuilder buf = new StringBuilder("Viewer Update Listener");
if (fFailOnRedundantUpdates) {
buf.append("\n\t");
buf.append("fRedundantUpdates = ");
buf.append( toStringViewerUpdatesSet(fRedundantUpdates) );
}
if (fFailOnMultipleLabelUpdateSequences) {
buf.append("\n\t");
buf.append("fMultipleLabelUpdateSequencesObserved = ").append(fMultipleLabelUpdateSequencesObserved);
}
if (fFailOnMultipleModelUpdateSequences) {
buf.append("\n\t");
buf.append("fMultipleModelUpdateSequencesObserved = ").append(fMultipleModelUpdateSequencesObserved);
}
if ( (flags & LABEL_SEQUENCE_COMPLETE) != 0) {
buf.append("\n\t");
buf.append("fLabelSequenceComplete = ").append(fLabelSequenceComplete);
}
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
buf.append("\n\t");
buf.append("fLabelUpdatesRunning = ").append(fLabelUpdatesCounter);
}
if ( (flags & LABEL_SEQUENCE_STARTED) != 0) {
buf.append("\n\t");
buf.append("fLabelUpdatesRunning = ");
buf.append( toStringViewerUpdatesSet(fLabelUpdatesRunning) );
buf.append("\n\t");
buf.append("fLabelUpdatesCompleted = ");
buf.append( toStringViewerUpdatesSet(fLabelUpdatesCompleted) );
}
if ( (flags & LABEL_UPDATES) != 0) {
buf.append("\n\t");
buf.append("fLabelUpdates = ");
buf.append( toString(fLabelUpdates) );
}
if ( (flags & CONTENT_SEQUENCE_COMPLETE) != 0) {
buf.append("\n\t");
buf.append("fContentSequenceComplete = ").append(fContentSequenceComplete);
}
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
buf.append("\n\t");
buf.append("fContentUpdatesCounter = ").append(fContentUpdatesCounter);
}
if ( (flags & HAS_CHILDREN_UPDATES_STARTED) != 0) {
buf.append("\n\t");
buf.append("fHasChildrenUpdatesRunning = ");
buf.append( toStringViewerUpdatesSet(fHasChildrenUpdatesRunning) );
buf.append("\n\t");
buf.append("fHasChildrenUpdatesCompleted = ");
buf.append( toStringViewerUpdatesSet(fHasChildrenUpdatesCompleted) );
}
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
buf.append("\n\t");
buf.append("fHasChildrenUpdates = ");
buf.append( toString(fHasChildrenUpdatesScheduled) );
}
if ( (flags & CHILD_COUNT_UPDATES_STARTED) != 0) {
buf.append("\n\t");
buf.append("fChildCountUpdatesRunning = ");
buf.append( toStringViewerUpdatesSet(fChildCountUpdatesRunning) );
buf.append("\n\t");
buf.append("fChildCountUpdatesCompleted = ");
buf.append( toStringViewerUpdatesSet(fChildCountUpdatesCompleted) );
}
if ( (flags & CHILD_COUNT_UPDATES) != 0) {
buf.append("\n\t");
buf.append("fChildCountUpdates = ");
buf.append( toString(fChildCountUpdatesScheduled) );
}
if ( (flags & CHILDREN_UPDATES_STARTED) != 0) {
buf.append("\n\t");
buf.append("fChildrenUpdatesRunning = ");
buf.append( fChildrenUpdatesRunning );
buf.append("\n\t");
buf.append("fChildrenUpdatesCompleted = ");
buf.append( toStringViewerUpdatesSet(fChildrenUpdatesCompleted) );
}
if ( (flags & CHILDREN_UPDATES) != 0) {
buf.append("\n\t");
buf.append("fChildrenUpdates = ");
buf.append( toStringTreePathMap(fChildrenUpdatesScheduled) );
}
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
buf.append("\n\t");
buf.append("fModelChangedComplete = ").append(fModelChangedComplete);
}
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
buf.append("\n\t");
buf.append("fStateSaveComplete = ").append(fStateSaveComplete);
}
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
buf.append("\n\t");
buf.append("fStateRestoreComplete = ").append(fStateRestoreComplete);
}
// if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
// buf.append("\n\t");
// buf.append("fProxyModels = ").append(fProxyModels);
// }
if ( (flags & PROPERTY_UPDATES_STARTED) != 0) {
buf.append("\n\t");
buf.append("fPropertiesUpdatesRunning = ");
buf.append(toStringViewerUpdatesSet(fPropertiesUpdatesRunning));
buf.append("\n\t");
buf.append("fPropertiesUpdatesCompleted = ").append(fPropertiesUpdatesCompleted);
}
if ( (flags & PROPERTY_UPDATES) != 0) {
buf.append("\n\t");
buf.append("fPropertiesUpdates = ");
buf.append( toString(fPropertiesUpdates) );
}
if (fTimeoutInterval > 0) {
buf.append("\n\t");
buf.append("fTimeoutInterval = ").append(fTimeoutInterval);
}
return buf.toString();
}
private String toString(Set<TreePath> set) {
if (set.isEmpty()) {
return "(EMPTY)";
}
StringBuilder buf = new StringBuilder();
for (Iterator<TreePath> itr = set.iterator(); itr.hasNext(); ) {
buf.append("\n\t\t");
buf.append(toStringTreePath(itr.next()));
}
return buf.toString();
}
private String toStringViewerUpdatesSet(Set<IViewerUpdate> set) {
if (set.isEmpty()) {
return "(EMPTY)";
}
StringBuilder buf = new StringBuilder();
for (Iterator<IViewerUpdate> itr = set.iterator(); itr.hasNext(); ) {
buf.append("\n\t\t");
buf.append(toStringTreePath((itr.next()).getElementPath()));
}
return buf.toString();
}
private String toStringTreePathMap(Map<TreePath, Set<Integer>> map) {
if (map.isEmpty()) {
return "(EMPTY)";
}
StringBuilder buf = new StringBuilder();
for (Iterator<TreePath> itr = map.keySet().iterator(); itr.hasNext(); ) {
buf.append("\n\t\t");
TreePath path = itr.next();
buf.append(toStringTreePath(path));
Set<?> updates = map.get(path);
buf.append(" = ");
buf.append(updates.toString());
}
return buf.toString();
}
private String toStringTreePath(TreePath path) {
if (path.getSegmentCount() == 0) {
return "/";
}
StringBuilder buf = new StringBuilder();
for (int i = 0; i < path.getSegmentCount(); i++) {
buf.append("/");
buf.append(path.getSegment(i));
}
return buf.toString();
}
@Override
public String toString() {
return toString(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE | STATE_RESTORE_COMPLETE |
VIEWER_UPDATES_STARTED | LABEL_SEQUENCE_STARTED | PROPERTY_UPDATES | PROPERTY_UPDATES_STARTED);
}
}