/*******************************************************************************
 *  Copyright (c) 2000, 2018 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.debug.internal.core;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointListener;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IBreakpointManagerListener;
import org.eclipse.debug.core.IBreakpointsListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IBreakpointImportParticipant;
import org.eclipse.debug.core.model.ITriggerPoint;

import com.ibm.icu.text.MessageFormat;

/**
 * The breakpoint manager manages all registered breakpoints for the Debug plug-in. It is
 * instantiated by the Debug plug-in at startup.
 * <p>
 * <strong>Note:</strong> This manager is created while the Debug plug-in is started, but it
 * will not automatically be initialized. Client code that expects markers and breakpoints to be
 * initialized must call {@link #ensureInitialized()}.
 * </p>
 *
 * @see IBreakpointManager
 */
public class BreakpointManager implements IBreakpointManager, IResourceChangeListener {

	/**
	 * Constants for breakpoint add/remove/change updates
	 */
	private final static int ADDED = 0;
	private final static int REMOVED = 1;
	private final static int CHANGED = 2;

	/**
	 * A collection of breakpoints registered with this manager.
	 */
	private Vector<IBreakpoint> fBreakpoints;

	/**
	 * Map of breakpoint import participants.
	 * Map has the form:
	 * <pre>Map(String - marker_id, List of {@link IBreakpointImportParticipant})</pre>
	 */
	private HashMap<String, ArrayList<BreakpointImportParticipantDelegate>> fImportParticipants;

	/**
	 * A system default import participant that performs legacy comparison support
	 * when no participants are provided for a given type.
	 *
	 * @since 3.5
	 */
	private IBreakpointImportParticipant fDefaultParticipant;

	/**
	 * A collection of breakpoint markers that have received a POST_CHANGE notification
	 * that they have changed before a POST_BUILD notification of add. This allows us
	 * to tell if a marker has been created & changed since the breakpoint has been
	 * registered (see bug 138473).
	 */
	private final Set<IMarker> fPostChangMarkersChanged = new HashSet<>();

	/**
	 * A collection of breakpoint markers that have received a POST_BUILD notification
	 * of being added.
	 */
	private final Set<IMarker> fPostBuildMarkersAdded = new HashSet<>();

	/**
	 * Collection of breakpoints being added currently. Used to
	 * suppress change notification of "REGISTERED" attribute when
	 * being added.
	 */
	private final List<IBreakpoint> fSuppressChange = new ArrayList<>();

	/**
	 * A table of breakpoint extension points, keyed by
	 * marker type
	 * key: a marker type
	 * value: the breakpoint extension which corresponds to that marker type
	 */
	private final HashMap<String, IConfigurationElement> fBreakpointExtensions;

	/**
	 * Collection of markers that associates markers to breakpoints
	 * key: a marker
	 * value: the breakpoint which contains that marker
	 */
	private final HashMap<IMarker, IBreakpoint> fMarkersToBreakpoints;

	/**
	 * Collection of breakpoint listeners.
	 */
	private final ListenerList<IBreakpointListener> fBreakpointListeners = new ListenerList<>();

	/**
	 * Collection of (plural) breakpoint listeners.
	 */
	private ListenerList<IBreakpointsListener> fBreakpointsListeners= new ListenerList<>();

	/**
	 * Singleton resource delta visitor which handles marker
	 * additions, changes, and removals.
	 */
	private static BreakpointManagerVisitor fgVisitor;

	/**
	 * Collection of breakpoint manager listeners which are
	 * notified when this manager's state changes.
	 */
	private final ListenerList<IBreakpointManagerListener> fBreakpointManagerListeners = new ListenerList<>();

	/**
	 * Breakpoint which acts a the triggering point in a workspace.
	 */
	private final Set<IBreakpoint> fTriggerPointBreakpointList = new LinkedHashSet<>();

	/**
	 * Trigger points disabled by system after the first trigger point is
	 * enabled in a workspace.
	 */
	private final Set<IBreakpoint> fTriggerPointDisabledList = new LinkedHashSet<>();


	/**
	 * Listens to POST_CHANGE notifications of breakpoint markers to detect when
	 * a breakpoint is added & changed before the POST_BUILD add notification is
	 * sent.
	 */
	class PostChangeListener implements IResourceChangeListener {

		private PostChangeVisitor fVisitor = new PostChangeVisitor();

		@Override
		public void resourceChanged(IResourceChangeEvent event) {
			IResourceDelta delta= event.getDelta();
			if (delta != null) {
				try {
					delta.accept(fVisitor);
				} catch (CoreException ce) {
					DebugPlugin.log(ce);
				}
			}
		}

	}

	/**
	 * Default implementation of a breakpoint import participant
	 *
	 * @since 3.5
	 */
	class DefaultImportParticipant implements IBreakpointImportParticipant {

		@Override
		public boolean matches(Map<String, Object> attributes, IBreakpoint breakpoint) throws CoreException {
			//perform legacy comparison
			IMarker marker = breakpoint.getMarker();
			String type = (String) attributes.get("type"); //$NON-NLS-1$
			Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER);
			Object localline = marker.getAttribute(IMarker.LINE_NUMBER);
			String localtype = marker.getType();
			if (type.equals(localtype)) {
				if(line != null && line.equals(localline)) {
					return true;
				}
				else if(line == null) {
					return true;
				}
			}
			return false;
		}
		@Override
		public void verify(IBreakpoint breakpoint) throws CoreException {}
	}

	/**
	 * The listener
	 */
	private PostChangeListener fPostChangeListener = new PostChangeListener();

	class PostChangeVisitor implements IResourceDeltaVisitor {

		@Override
		public boolean visit(IResourceDelta delta) throws CoreException {
			if (delta == null) {
				return false;
			}
			for (IMarkerDelta markerDelta : delta.getMarkerDeltas()) {
				if (markerDelta.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) {
					switch (markerDelta.getKind()) {
						case IResourceDelta.ADDED :
							break;
						case IResourceDelta.REMOVED :
							break;
						case IResourceDelta.CHANGED :
							IMarker marker = markerDelta.getMarker();
							synchronized (fPostChangMarkersChanged) {
								if (!fPostBuildMarkersAdded.contains(marker)) {
									fPostChangMarkersChanged.add(marker);
								}
							}
							break;
						default:
							break;
					}
				}
			}
			return true;
		}

	}

	/**
	 * Constructs a new breakpoint manager.
	 */
	public BreakpointManager() {
		fMarkersToBreakpoints = new HashMap<>(10);
		fBreakpointExtensions = new HashMap<>(15);
	}

	/**
	 * Loads all the breakpoints on the given resource.
	 *
	 * @param resource the resource which contains the breakpoints
	 * @param notify whether to notify of the breakpoint additions
	 * @throws CoreException if a problem is encountered
	 */
	private void loadBreakpoints(IResource resource, boolean notify) throws CoreException {
		initBreakpointExtensions();
		List<IBreakpoint> added = new ArrayList<>();
		for (IMarker marker : getPersistedMarkers(resource)) {
			try {
				IBreakpoint breakpoint = createBreakpoint(marker);
				synchronized (fPostChangMarkersChanged) {
					fPostBuildMarkersAdded.add(marker);
				}
				if (breakpoint.isRegistered()) {
					added.add(breakpoint);

				}
				if (breakpoint instanceof ITriggerPoint && ((ITriggerPoint) breakpoint).isTriggerPoint()) {
					addTriggerPoint(breakpoint);
				}
			} catch (DebugException e) {
				DebugPlugin.log(e);
			}
		}
		addBreakpoints(added.toArray(new IBreakpoint[added.size()]), notify);
	}

	/**
	 * Returns the persisted markers associated with the given resource.
	 *
	 * Delete any invalid breakpoint markers. This is done at startup rather
	 * than shutdown, since the changes made at shutdown are not persisted as
	 * the workspace state has already been saved. See bug 7683.
	 *
	 * Since the <code>TRANSIENT</code> marker attribute/feature has been added,
	 * we no longer have to manually delete non-persisted markers - the platform
	 * does this for us (at shutdown, transient markers are not saved). However,
	 * the code is still present to delete non-persisted markers from old
	 * workspaces.
	 * @param resource the {@link IResource} to get markers for
	 * @return the complete listing of persisted markers for the given {@link IResource}
	 * @throws CoreException if a problem is encountered
	 */
	protected IMarker[] getPersistedMarkers(IResource resource) throws CoreException {
		final List<IMarker> delete = new ArrayList<>();
		List<IMarker> persisted = new ArrayList<>();
		for (IMarker marker : resource.findMarkers(IBreakpoint.BREAKPOINT_MARKER, true, IResource.DEPTH_INFINITE)) {
			// ensure the marker has a valid model identifier attribute
			// and delete the breakpoint if not
			String modelId = marker.getAttribute(IBreakpoint.ID, null);
			if (modelId == null) {
				// marker with old/invalid format - delete
				delete.add(marker);
			} else if (!marker.getAttribute(IBreakpoint.PERSISTED, true)) {
				// the breakpoint is marked as not to be persisted,
				// schedule for deletion
				delete.add(marker);
			} else {
				persisted.add(marker);
			}
		}
		// delete any markers that are not to be restored
		if (!delete.isEmpty()) {
			final IMarker[] delMarkers = delete.toArray(new IMarker[delete.size()]);
			IWorkspaceRunnable wr = pm -> {
				for (IMarker marker : delMarkers) {
					marker.delete();
				}
			};
			new BreakpointManagerJob(wr).schedule();
		}
		return persisted.toArray(new IMarker[persisted.size()]);
	}

	/**
	 * Removes this manager as a resource change listener
	 * and removes all breakpoint listeners.
	 */
	public void shutdown() {
		getWorkspace().removeResourceChangeListener(this);
		getWorkspace().removeResourceChangeListener(fPostChangeListener);
		fBreakpointListeners.clear();
		fBreakpointsListeners.clear();
		fBreakpointManagerListeners.clear();
		if(fImportParticipants != null) {
			fImportParticipants.clear();
			fImportParticipants = null;
			fDefaultParticipant = null;
		}
		if(fBreakpoints != null) {
			fBreakpoints.clear();
			fBreakpoints = null;
		}
		if(fMarkersToBreakpoints != null) {
			fMarkersToBreakpoints.clear();
		}
	}

	/**
	 * Find the defined breakpoint extensions and cache them for use in recreating
	 * breakpoints from markers.
	 */
	private void initBreakpointExtensions() {
		IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_BREAKPOINTS);
		for (IConfigurationElement element : ep.getConfigurationElements()) {
			String markerType = element.getAttribute(IConfigurationElementConstants.MARKER_TYPE);
			String className = element.getAttribute(IConfigurationElementConstants.CLASS);
			if (markerType == null) {
				DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + element.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: markerType", null)); //$NON-NLS-1$ //$NON-NLS-2$
			} else if (className == null){
				DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + element.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: class", null)); //$NON-NLS-1$ //$NON-NLS-2$
			} else {
				fBreakpointExtensions.put(markerType, element);
			}
		}
	}

	/**
	 * Convenience method to get the workspace
	 * @return the default {@link IWorkspace}
	 */
	private IWorkspace getWorkspace() {
		return ResourcesPlugin.getWorkspace();
	}

	/**
	 * @see IBreakpointManager#getBreakpoint(IMarker)
	 */
	@Override
	public IBreakpoint getBreakpoint(IMarker marker) {
		// ensure that breakpoints are initialized
		getBreakpoints0();
		return fMarkersToBreakpoints.get(marker);
	}

	@Override
	public IBreakpoint[] getBreakpoints() {
		IBreakpoint[] temp = new IBreakpoint[0];
		Vector<IBreakpoint> breakpoints = getBreakpoints0();
		synchronized (breakpoints) {
			temp = new IBreakpoint[breakpoints.size()];
			breakpoints.copyInto(temp);
		}
		return temp;
	}

	/**
	 * Ensures that this manager is initialized.
	 * <p>
	 * This manager is created while the Debug plug-in is started, but it will not automatically
	 * be initialized. Client code that expects markers and breakpoints to be initialized must call
	 * this method.
	 * </p>
	 *
	 * @since 3.8
	 */
	public void ensureInitialized() {
		getBreakpoints0();
	}

	/**
	 * The BreakpointManager waits to load the breakpoints
	 * of the workspace until a request is made to retrieve the
	 * breakpoints.
	 * @return the underlying {@link Vector} of breakpoints
	 */
	private synchronized Vector<IBreakpoint> getBreakpoints0() {
		if (fBreakpoints == null) {
			initializeBreakpoints();
		}
		return fBreakpoints;
	}

	@Override
	public IBreakpoint[] getBreakpoints(String modelIdentifier) {
		Vector<IBreakpoint> allBreakpoints = getBreakpoints0();
		synchronized (allBreakpoints) {
			ArrayList<IBreakpoint> temp = new ArrayList<>(allBreakpoints.size());
			for (IBreakpoint breakpoint : allBreakpoints) {
				String id= breakpoint.getModelIdentifier();
				if (id != null && id.equals(modelIdentifier)) {
					temp.add(breakpoint);
				}
			}
			return temp.toArray(new IBreakpoint[temp.size()]);
		}
	}

	/**
	 * Loads the list of breakpoints from the breakpoint markers in the
	 * workspace. Start listening to resource deltas.
	 */
	private void initializeBreakpoints() {
		setBreakpoints(new Vector<>(10));
		try {
			loadBreakpoints(getWorkspace().getRoot(), false);
			getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_BUILD);
			getWorkspace().addResourceChangeListener(fPostChangeListener, IResourceChangeEvent.POST_CHANGE);
		} catch (CoreException ce) {
			DebugPlugin.log(ce);
			setBreakpoints(new Vector<>(0));
		}
	}

	/**
	 * @see IBreakpointManager#isRegistered(IBreakpoint)
	 */
	@Override
	public boolean isRegistered(IBreakpoint breakpoint) {
		return getBreakpoints0().contains(breakpoint);
	}


	/**
	 * @see IBreakpointManager#removeBreakpoint(IBreakpoint, boolean)
	 */
	@Override
	public void removeBreakpoint(IBreakpoint breakpoint, boolean delete) throws CoreException {
		removeBreakpoints(new IBreakpoint[]{breakpoint}, delete);
	}

	/**
	 * @see IBreakpointManager#removeBreakpoints(IBreakpoint[], boolean)
	 */
	@Override
	public void removeBreakpoints(IBreakpoint[] breakpoints, final boolean delete) throws CoreException {
		final List<IBreakpoint> remove = new ArrayList<>(breakpoints.length);
		List<IBreakpoint> bps = getBreakpoints0();
		for (IBreakpoint breakpoint : breakpoints) {
			if (bps.contains(breakpoint)) {
				remove.add(breakpoint);
			}
		}
		if (!remove.isEmpty()) {
			for (IBreakpoint breakpoint : remove) {
				bps.remove(breakpoint);
				fMarkersToBreakpoints.remove(breakpoint.getMarker());
			}
			fireUpdate(remove, null, REMOVED);
			refreshTriggerpointDisplay();
			IWorkspaceRunnable r = monitor -> {
				for (IBreakpoint breakpoint : remove) {
					if (delete) {
						breakpoint.delete();
					} else {
						// if the breakpoint is being removed from the manager
						// because the project is closing, the breakpoint should
						// remain as registered, otherwise, the breakpoint should
						// be marked as unregistered
						IMarker marker = breakpoint.getMarker();
						if (marker.exists()) {
							IProject project = breakpoint.getMarker().getResource().getProject();
							if (project == null || project.isOpen()) {
								breakpoint.setRegistered(false);
							}
						}
					}
				}
			};
			getWorkspace().run(r, null, 0, null);
		}
	}

	/**
	 * Create a breakpoint for the given marker. The created breakpoint
	 * is of the type specified in the breakpoint extension associated
	 * with the given marker type.
	 *
	 * @param marker marker to create a breakpoint for
	 * @return a breakpoint on this marker
	 * @exception DebugException if breakpoint creation fails. Reasons for
	 *  failure include:
	 * <ol>
	 * <li>The breakpoint manager cannot determine what kind of breakpoint
	 *     to instantiate for the given marker type</li>
	 * <li>A lower level exception occurred while accessing the given marker</li>
	 * </ol>
	 */
	public IBreakpoint createBreakpoint(IMarker marker) throws DebugException {
		IBreakpoint breakpoint= fMarkersToBreakpoints.get(marker);
		if (breakpoint != null) {
			return breakpoint;
		}
		try {
			IConfigurationElement config = fBreakpointExtensions.get(marker.getType());
			if (config == null) {
				throw new DebugException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
 DebugException.CONFIGURATION_INVALID, MessageFormat.format(DebugCoreMessages.BreakpointManager_Missing_breakpoint_definition, new Object[] { marker.getType() }), null));
			}
			Object object = config.createExecutableExtension(IConfigurationElementConstants.CLASS);
			if (object instanceof IBreakpoint) {
				breakpoint = (IBreakpoint)object;
				breakpoint.setMarker(marker);
			} else {
				DebugPlugin.log(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "Breakpoint extension " + config.getDeclaringExtension().getUniqueIdentifier() + " missing required attribute: class", null)); //$NON-NLS-1$ //$NON-NLS-2$
			}
			return breakpoint;
		} catch (CoreException e) {
			throw new DebugException(e.getStatus());
		}
	}

	/**
	 * @see IBreakpointManager#addBreakpoint(IBreakpoint)
	 */
	@Override
	public void addBreakpoint(IBreakpoint breakpoint) throws CoreException {
		addBreakpoints(new IBreakpoint[]{breakpoint});
	}

	/**
	 * @see IBreakpointManager#addBreakpoints(IBreakpoint[])
	 */
	@Override
	public void addBreakpoints(IBreakpoint[] breakpoints) throws CoreException {
		addBreakpoints(breakpoints, true);
	}

	/**
	 * Registers the given breakpoints and notifies listeners if specified.
	 *
	 * @param breakpoints the breakpoints to register
	 * @param notify whether to notify listeners of the add
	 * @throws CoreException if a problem is encountered
	 */
	private void addBreakpoints(IBreakpoint[] breakpoints, boolean notify) throws CoreException {
		List<IBreakpoint> added = new ArrayList<>(breakpoints.length);
		final List<IBreakpoint> update = new ArrayList<>();
		for (IBreakpoint breakpoint : breakpoints) {
			if (!getBreakpoints0().contains(breakpoint)) {
				verifyBreakpoint(breakpoint);
				if (breakpoint.isRegistered()) {
					// If notify == false, the breakpoints are just being added at startup
					added.add(breakpoint);
					getBreakpoints0().add(breakpoint);
					fMarkersToBreakpoints.put(breakpoint.getMarker(), breakpoint);
				} else {
					// need to update the 'registered' and/or 'group' attributes
					update.add(breakpoint);
				}
			}
		}
		if (notify) {
			fireUpdate(added, null, ADDED);
		}
		if (!update.isEmpty()) {
			IWorkspaceRunnable r = monitor -> {
				List<IBreakpoint> bps = getBreakpoints0();
				for (IBreakpoint breakpoint : update) {
					bps.add(breakpoint);
					breakpoint.setRegistered(true);
					fMarkersToBreakpoints.put(breakpoint.getMarker(), breakpoint);
				}
			};
			// Need to suppress change notification, since this is really
			// an add notification
			fSuppressChange.addAll(update);
			getWorkspace().run(r, null, 0, null);
			fSuppressChange.removeAll(update);
			if (notify) {
				fireUpdate(update, null, ADDED);
			}
		}
	}

	/**
	 * Returns whether change notification is to be suppressed for the given breakpoint.
	 * Used when adding breakpoints and changing the "REGISTERED" attribute.
	 *
	 * @param breakpoint the breakpoint
	 * @return boolean whether change notification is suppressed
	 */
	protected boolean isChangeSuppressed(IBreakpoint breakpoint) {
		return fSuppressChange.contains(breakpoint);
	}

	/**
	 * @see IBreakpointManager#fireBreakpointChanged(IBreakpoint)
	 */
	@Override
	public void fireBreakpointChanged(IBreakpoint breakpoint) {
		if (getBreakpoints0().contains(breakpoint)) {
			List<IBreakpoint> changed = new ArrayList<>();
			changed.add(breakpoint);
			fireUpdate(changed, null, CHANGED);
		}
	}

	/**
	 * Verifies that the breakpoint marker has the minimal required attributes,
	 * and throws a debug exception if not.
	 * @param breakpoint the {@link IBreakpoint} to verify
	 * @throws DebugException if a problem is encountered
	 */
	private void verifyBreakpoint(IBreakpoint breakpoint) throws DebugException {
		try {
			String id= breakpoint.getModelIdentifier();
			if (id == null) {
				throw new DebugException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
					DebugException.CONFIGURATION_INVALID, DebugCoreMessages.BreakpointManager_Missing_model_identifier, null));
			}
		} catch (CoreException e) {
			throw new DebugException(e.getStatus());
		}
	}

	/**
	 * A resource has changed. Traverses the delta for breakpoint changes.
	 *
	 * @param event resource change event
	 */
	@Override
	public void resourceChanged(IResourceChangeEvent event) {
		IResourceDelta delta= event.getDelta();
		if (delta != null) {
			try {
				if (fgVisitor == null) {
					fgVisitor= new BreakpointManagerVisitor();
				}
				delta.accept(fgVisitor);
				fgVisitor.update();
			} catch (CoreException ce) {
				DebugPlugin.log(ce);
			}
		}
	}

	/**
	 * Visitor for handling resource deltas
	 */
	class BreakpointManagerVisitor implements IResourceDeltaVisitor {
		/**
		 * Moved markers
		 */
		private List<IMarker> fMoved = new ArrayList<>();
		/**
		 * Removed breakpoints
		 */
		private List<IBreakpoint> fRemoved = new ArrayList<>();

		/**
		 * Added breakpoints.
		 * @since 3.7
		 */
		private List<IBreakpoint> fAdded = new ArrayList<>();

		/**
		 * Changed breakpoints and associated marker deltas
		 */
		private List<IBreakpoint> fChanged = new ArrayList<>();
		private List<IMarkerDelta> fChangedDeltas = new ArrayList<>();

		/**
		 * Resets the visitor for a delta traversal - empties
		 * collections of removed/changed breakpoints.
		 */
		protected void reset() {
			fMoved.clear();
			fRemoved.clear();
			fAdded.clear();
			fChanged.clear();
			fChangedDeltas.clear();
		}

		/**
		 * Performs updates on accumulated changes, and fires change notification after
		 * a traversal. Accumulated updates are reset.
		 */
		public void update() {
			if (!fMoved.isEmpty()) {
				// delete moved markers
				IWorkspaceRunnable wRunnable= monitor -> {
					for (IMarker marker : fMoved) {
						marker.delete();
					}
				};
				try {
					getWorkspace().run(wRunnable, null, 0, null);
				} catch (CoreException e) {
				}
			}
			if (!fRemoved.isEmpty()) {
				try {
					removeBreakpoints(fRemoved.toArray(new IBreakpoint[fRemoved.size()]), false);
				} catch (CoreException e) {
					DebugPlugin.log(e);
				}
			}
			if (!fAdded.isEmpty()) {
				try {
					IWorkspaceRunnable runnable= monitor -> {
						for (IBreakpoint breakpoint : fAdded) {
							breakpoint.getMarker().setAttribute(DebugPlugin.ATTR_BREAKPOINT_IS_DELETED, false);
							breakpoint.setRegistered(true);
						}
					};
					getWorkspace().run(runnable, null, 0, null);
					addBreakpoints(fAdded.toArray(new IBreakpoint[fAdded.size()]), false);
				} catch (CoreException e) {
					DebugPlugin.log(e);
				}
			}
			if (!fChanged.isEmpty()) {
				fireUpdate(fChanged, fChangedDeltas, CHANGED);
			}
			reset();
		}

		/**
		 * @see IResourceDeltaVisitor#visit(IResourceDelta)
		 */
		@Override
		public boolean visit(IResourceDelta delta) {
			if (delta == null) {
				return false;
			}
			if (0 != (delta.getFlags() & IResourceDelta.OPEN) && 0 == (delta.getFlags() & IResourceDelta.MOVED_FROM)) {
				handleProjectResourceOpenStateChange(delta.getResource());
				return false;
			}
			for (IMarkerDelta markerDelta : delta.getMarkerDeltas()) {
				if (markerDelta.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) {
					switch (markerDelta.getKind()) {
						case IResourceDelta.ADDED :
							handleAddBreakpoint(delta, markerDelta.getMarker(), markerDelta);
							break;
						case IResourceDelta.REMOVED :
							handleRemoveBreakpoint(markerDelta.getMarker());
							break;
						case IResourceDelta.CHANGED :
							handleChangeBreakpoint(markerDelta.getMarker(), markerDelta);
							break;
						default:
							break;
					}
				}
			}

			return true;
		}

		/**
		 * Wrapper for handling adds
		 * @param rDelta the {@link IResourceDelta}
		 * @param marker the new {@link IMarker}
		 * @param mDelta the accompanying {@link IMarkerDelta}
		 */
		protected void handleAddBreakpoint(IResourceDelta rDelta, IMarker marker, IMarkerDelta mDelta) {
			if (0 != (rDelta.getFlags() & IResourceDelta.MOVED_FROM)) {
				// This breakpoint has actually been moved - already removed
				// from the Breakpoint manager during the remove callback.
				// Schedule the marker associated with the new resource for deletion.
				if (getBreakpoint(marker) == null) {
					fMoved.add(marker);
				}
			} else {
				// check if the an add & change have be combined into one add notification
				synchronized (fPostChangMarkersChanged) {
					if (fPostChangMarkersChanged.contains(marker)) {
						handleChangeBreakpoint(marker, mDelta);
						fPostChangMarkersChanged.remove(marker);
					} else if (marker.getAttribute(DebugPlugin.ATTR_BREAKPOINT_IS_DELETED, false) && getBreakpoint(marker) == null) {
						try { /*
							 * There may be breakpoints with matching resource
							 * and same line number
							 */
							IBreakpoint breakpoint = findMatchingBreakpoint(marker);
							if (breakpoint != null) {
								removeBreakpoint(breakpoint, true);
							}
							fAdded.add(createBreakpoint(marker));
						} catch (CoreException e) {
							DebugPlugin.log(e);
						}
					}
					fPostBuildMarkersAdded.add(marker);
				}
			}
		}

		/**
		 * To find a breakpoint with matching marker resources and line number.
		 *
		 * @param marker the {@link IMarker} for which existing breakpoint is
		 *            retrieved
		 * @return matching breakpoint if exists else return <code>null</code>
		 */
		private IBreakpoint findMatchingBreakpoint(IMarker marker) {
			try {
				Integer line = (Integer) marker.getAttribute(IMarker.LINE_NUMBER);
				for (IBreakpoint breakpoint : getBreakpoints0()) {
					IMarker bpMarker = breakpoint.getMarker();
					if (bpMarker != null && marker.getResource().equals(bpMarker.getResource()) && bpMarker.getAttribute(IMarker.LINE_NUMBER, -1) == (line == null ? -1 : line.intValue())) {
						return breakpoint;
					}
				}
			} catch (CoreException e) {
				// ignore
			}
			return null;
		}

		/**
		 * Wrapper for handling removes
		 * @param marker the {@link IMarker}
		 */
		protected void handleRemoveBreakpoint(IMarker marker) {
			synchronized (fPostChangMarkersChanged) {
				fPostChangMarkersChanged.remove(marker);
				fPostBuildMarkersAdded.remove(marker);
			}
			IBreakpoint breakpoint= getBreakpoint(marker);
			if (breakpoint != null) {
				fRemoved.add(breakpoint);
			}
		}

		/**
		 * Wrapper for handling changes
		 * @param marker the {@link IMarker} that was changed
		 * @param delta the {@link IMarkerDelta}
		 */
		protected void handleChangeBreakpoint(IMarker marker, IMarkerDelta delta) {
			IBreakpoint breakpoint= getBreakpoint(marker);
			if (breakpoint != null && isRegistered(breakpoint) && !isChangeSuppressed(breakpoint)) {
				fChanged.add(breakpoint);
				fChangedDeltas.add(delta);
			}
		}

		/**
		 * A project has been opened or closed.  Updates the breakpoints for
		 * that project
		 * @param project the {@link IProject} that was changed
		 */
		private void handleProjectResourceOpenStateChange(final IResource project) {
			if (!project.isAccessible()) {
				//closed
				for (@SuppressWarnings("unchecked") IBreakpoint breakpoint : (Vector<IBreakpoint>) getBreakpoints0().clone()) {
					IResource markerResource= breakpoint.getMarker().getResource();
					if (project.getFullPath().isPrefixOf(markerResource.getFullPath())) {
						fRemoved.add(breakpoint);
					}
				}
				return;
			}
			try {
				loadBreakpoints(project, true);
			} catch (CoreException e) {
				DebugPlugin.log(e);
			}
		}
	}

	/**
	 * @see IBreakpointManager#addBreakpointListener(IBreakpointListener)
	 */
	@Override
	public void addBreakpointListener(IBreakpointListener listener) {
		fBreakpointListeners.add(listener);
	}

	/**
	 * @see IBreakpointManager#removeBreakpointListener(IBreakpointListener)
	 */
	@Override
	public void removeBreakpointListener(IBreakpointListener listener) {
		fBreakpointListeners.remove(listener);
	}

	/**
	 * Notifies listeners of the adds/removes/changes
	 *
	 * @param breakpoints associated breakpoints
	 * @param deltas or <code>null</code>
	 * @param update type of change
	 */
	private void fireUpdate(List<IBreakpoint> breakpoints, List<IMarkerDelta> deltas, int update) {
		if (breakpoints.isEmpty()) {
			return;
		}
		IBreakpoint[] bpArray = breakpoints.toArray(new IBreakpoint[breakpoints.size()]);
		IMarkerDelta[] deltaArray = new IMarkerDelta[bpArray.length];
		if (deltas != null) {
			deltaArray = deltas.toArray(deltaArray);
		}
		// single listeners
		getBreakpointNotifier().notify(bpArray, deltaArray, update);

		// plural listeners
		getBreakpointsNotifier().notify(bpArray, deltaArray, update);
	}

	protected void setBreakpoints(Vector<IBreakpoint> breakpoints) {
		fBreakpoints = breakpoints;
	}

	/**
	 * @see IBreakpointManager#hasBreakpoints()
	 */
	@Override
	public boolean hasBreakpoints() {
		return !getBreakpoints0().isEmpty();
	}

	/**
	 * @see org.eclipse.debug.core.IBreakpointManager#addBreakpointListener(org.eclipse.debug.core.IBreakpointsListener)
	 */
	@Override
	public void addBreakpointListener(IBreakpointsListener listener) {
		fBreakpointsListeners.add(listener);
	}

	/**
	 * @see org.eclipse.debug.core.IBreakpointManager#removeBreakpointListener(org.eclipse.debug.core.IBreakpointsListener)
	 */
	@Override
	public void removeBreakpointListener(IBreakpointsListener listener) {
		fBreakpointsListeners.remove(listener);
	}

	private BreakpointNotifier getBreakpointNotifier() {
		return new BreakpointNotifier();
	}

	/**
	 * Notifies breakpoint listener (single breakpoint) in a safe runnable to
	 * handle exceptions.
	 */
	class BreakpointNotifier implements ISafeRunnable {

		private IBreakpointListener fListener;
		private int fType;
		private IMarkerDelta fDelta;
		private IBreakpoint fBreakpoint;

		/**
		 * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
		 */
		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		/**
		 * @see org.eclipse.core.runtime.ISafeRunnable#run()
		 */
		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
					fListener.breakpointAdded(fBreakpoint);
					break;
				case REMOVED:
					fListener.breakpointRemoved(fBreakpoint, fDelta);
					break;
				case CHANGED:
					fListener.breakpointChanged(fBreakpoint, fDelta);
					break;
				default:
					break;
			}
		}

		/**
		 * Notifies the listeners of the add/change/remove
		 *
		 * @param breakpoints the breakpoints that changed
		 * @param deltas the deltas associated with the change
		 * @param update the type of change
		 */
		public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) {
			fType = update;
			for (IBreakpointListener iBreakpointListener : fBreakpointListeners) {
				fListener = iBreakpointListener;
				for (int j = 0; j < breakpoints.length; j++) {
					fBreakpoint = breakpoints[j];
					fDelta = deltas[j];
					SafeRunner.run(this);
				}
			}
			fListener = null;
			fDelta = null;
			fBreakpoint = null;
		}
	}

	private BreakpointsNotifier getBreakpointsNotifier() {
		return new BreakpointsNotifier();
	}

	/**
	 * Notifies breakpoint listener (multiple breakpoints) in a safe runnable to
	 * handle exceptions.
	 */
	class BreakpointsNotifier implements ISafeRunnable {

		private IBreakpointsListener fListener;
		private int fType;
		private IMarkerDelta[] fDeltas;
		private IBreakpoint[] fNotifierBreakpoints;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		@Override
		public void run() throws Exception {
			switch (fType) {
				case ADDED:
					fListener.breakpointsAdded(fNotifierBreakpoints);
					break;
				case REMOVED:
					fListener.breakpointsRemoved(fNotifierBreakpoints, fDeltas);
					break;
				case CHANGED:
					fListener.breakpointsChanged(fNotifierBreakpoints, fDeltas);
					break;
				default:
					break;
			}
		}

		/**
		 * Notifies the listeners of the adds/changes/removes
		 *
		 * @param breakpoints the breakpoints that changed
		 * @param deltas the deltas associated with the changed breakpoints
		 * @param update the type of change
		 */
		public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) {
			fType = update;
			fNotifierBreakpoints = breakpoints;
			fDeltas = deltas;
			for (IBreakpointsListener iBreakpointsListener : fBreakpointsListeners) {
				fListener = iBreakpointsListener;
				SafeRunner.run(this);
			}
			fDeltas = null;
			fNotifierBreakpoints = null;
			fListener = null;
		}
	}

	@Override
	public boolean isEnabled() {
		return Platform.getPreferencesService().getBoolean(DebugPlugin.getUniqueIdentifier(), IInternalDebugCoreConstants.PREF_BREAKPOINT_MANAGER_ENABLED_STATE, true, null);
	}

	@Override
	public void setEnabled(final boolean enabled) {
		if (isEnabled() != enabled) {
			Preferences.setBoolean(DebugPlugin.getUniqueIdentifier(), IInternalDebugCoreConstants.PREF_BREAKPOINT_MANAGER_ENABLED_STATE, enabled, null);
			touchAllBreakpoints();
			new BreakpointManagerNotifier().notify(enabled);
		}
	}

	@Override
	public void addBreakpointManagerListener(IBreakpointManagerListener listener) {
		fBreakpointManagerListeners.add(listener);
	}

	@Override
	public void removeBreakpointManagerListener(IBreakpointManagerListener listener) {
		fBreakpointManagerListeners.remove(listener);
	}

	/**
	 * Notifies breakpoint manager listeners in a safe runnable to
	 * handle exceptions.
	 */
	class BreakpointManagerNotifier implements ISafeRunnable {

		private IBreakpointManagerListener fListener;
		private boolean fManagerEnabled;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception);  //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		@Override
		public void run() throws Exception {
			fListener.breakpointManagerEnablementChanged(fManagerEnabled);
		}

		/**
		 * Notifies the listeners of the enabled state change
		 *
		 * @param enabled whether the manager is enabled
		 */
		public void notify(boolean enabled) {
			fManagerEnabled= enabled;
			for (IBreakpointManagerListener iBreakpointManagerListener : fBreakpointManagerListeners) {
				fListener = iBreakpointManagerListener;
				SafeRunner.run(this);
			}
			fListener = null;
		}
	}

	/**
	 * Notifies breakpoint manager listeners in a safe runnable to handle
	 * exceptions.
	 */
	class BreakpointManagerTriggerPointNotifier implements ISafeRunnable {

		private IBreakpointManagerListener fListener;
		private IBreakpoint fManagerTriggerPoint;

		@Override
		public void handleException(Throwable exception) {
			IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$
			DebugPlugin.log(status);
		}

		@Override
		public void run() throws Exception {
			fListener.breakpointManagerTriggerPointChanged(fManagerTriggerPoint);
		}

		/**
		 * Notifies the listeners of the enabled state change
		 *
		 * @param triggerBreakpoint new breakpoint as trigger point
		 */
		public void notify(IBreakpoint triggerBreakpoint) {
			fManagerTriggerPoint = triggerBreakpoint;
			for (IBreakpointManagerListener iBreakpointManagerListener : fBreakpointManagerListeners) {
				fListener = iBreakpointManagerListener;
				SafeRunner.run(this);
			}
			fListener = null;
		}
	}

	class BreakpointManagerJob extends Job {

		private final IWorkspaceRunnable fRunnable;

		public BreakpointManagerJob (IWorkspaceRunnable wRunnable) {
			super("breakpoint manager job"); //$NON-NLS-1$
			fRunnable= wRunnable;
			setSystem(true);
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			try {
				getWorkspace().run(fRunnable, null, 0, null);
			} catch (CoreException ce) {
				DebugPlugin.log(ce);
			}
			return new Status(IStatus.OK, DebugPlugin.getUniqueIdentifier(), IStatus.OK, "", null); //$NON-NLS-1$
		}
	}

	@Override
	public String getTypeName(IBreakpoint breakpoint) {
		String typeName= null;
		IMarker marker = breakpoint.getMarker();
		if (marker != null) {
			try {
				IConfigurationElement element = fBreakpointExtensions.get(marker.getType());
				if (element != null) {
					typeName= element.getAttribute(IConfigurationElementConstants.NAME);
				}
			}
			catch (CoreException e) {}
		}
		return typeName;
	}

	@Override
	public IBreakpointImportParticipant[] getImportParticipants(String markertype) throws CoreException {
		initializeImportParticipants();
		ArrayList<BreakpointImportParticipantDelegate> list = fImportParticipants.get(markertype);
		if(list == null) {
			return new IBreakpointImportParticipant[] {fDefaultParticipant};
		}
		IBreakpointImportParticipant[] participants = new IBreakpointImportParticipant[list.size()];
		BreakpointImportParticipantDelegate delegate = null;
		for(int i = 0; i < list.size(); i++) {
			delegate = list.get(i);
			participants[i] = delegate.getDelegate();
		}
		if(participants.length == 0) {
			return new IBreakpointImportParticipant[] {fDefaultParticipant};
		}
		return participants;
	}

	/**
	 * Initializes the cache of breakpoint import participants. Does no work if the cache
	 * has already been initialized
	 */
	private synchronized void initializeImportParticipants() {
		if(fImportParticipants == null) {
			fImportParticipants = new HashMap<>();
			fDefaultParticipant = new DefaultImportParticipant();
			IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_BREAKPOINT_IMPORT_PARTICIPANTS);
			String type = null;
			ArrayList<BreakpointImportParticipantDelegate> list = null;
			for (IConfigurationElement element : ep.getConfigurationElements()) {
				type = element.getAttribute(IConfigurationElementConstants.TYPE);
				if(type != null) {
					list = fImportParticipants.get(type);
					if(list == null) {
						list = new ArrayList<>();
						fImportParticipants.put(type, list);
					}
					list.add(new BreakpointImportParticipantDelegate(element));
				}
			}
		}
	}

	@Override
	public IBreakpoint[] getTriggerPoints() {
		return fTriggerPointBreakpointList.toArray(new IBreakpoint[0]);
	}

	@Override
	public void addTriggerPoint(IBreakpoint triggerPoint) throws CoreException {
		if (triggerPoint == null) {
			return;
		}
		fTriggerPointBreakpointList.add(triggerPoint);
		new BreakpointManagerTriggerPointNotifier().notify(triggerPoint);
	}

	@Override
	public void removeTriggerPoint(IBreakpoint breakpoint) throws CoreException {
		if (breakpoint != null) {
			fTriggerPointBreakpointList.remove(breakpoint);
		}
	}

	@Override
	public void removeAllTriggerPoints() throws CoreException {
		IBreakpoint[] triggerPointBreakpointList = getTriggerPoints();
		for (IBreakpoint iBreakpoint : triggerPointBreakpointList) {
			if (iBreakpoint instanceof ITriggerPoint) {
				((ITriggerPoint) iBreakpoint).setTriggerPoint(false);
			}
		}
		refreshTriggerpointDisplay();
	}

	@Override
	public boolean hasActiveTriggerPoints() {
		if (fTriggerPointBreakpointList.isEmpty()) {
			return false;
		}
		for (IBreakpoint iBreakpoint : fTriggerPointBreakpointList) {
			try {
				if (iBreakpoint.isEnabled()) {
					return true;
				}
			} catch (CoreException e) {
				// ignore
			}
		}
		return false;
	}

	@Override
	public void enableTriggerPoints(IBreakpoint[] triggerPoints, boolean enable) {
		IBreakpoint[] triggerPointArray = triggerPoints;
		if (triggerPoints == null) {
			if (enable) {
				synchronized (fTriggerPointDisabledList) {
					triggerPointArray = fTriggerPointDisabledList.toArray(new IBreakpoint[0]);
				}
			} else {
				triggerPointArray = getTriggerPoints();
			}
		}
		List<IBreakpoint> toDisable = new ArrayList<>();
		for (IBreakpoint iBreakpoint : triggerPointArray) {
			try {
				IMarker m = iBreakpoint.getMarker();
				if (m != null && m.exists()) {
					if (!enable && iBreakpoint.isEnabled()) {
						toDisable.add(iBreakpoint);
					}
					iBreakpoint.setEnabled(enable);
				}
			} catch (CoreException e) {
				// ignore
			}
		}
		synchronized (fTriggerPointDisabledList) {
			fTriggerPointDisabledList.clear();
			if (!enable) {
				fTriggerPointDisabledList.addAll(toDisable);
			}
		}
	}

	@Override
	public void refreshTriggerpointDisplay() {
		touchAllBreakpoints();
	}

	/*
	 * Touch and refresh display of all breakpoints
	 */
	private void touchAllBreakpoints() {
		IWorkspaceRunnable runnable = monitor -> {
			for (IBreakpoint breakpoint : getBreakpoints()) {
				// Touch the marker (but don't actually change anything) so
				// that the icon in
				// the editor ruler will be updated (editors listen to
				// marker changes).
				try {
					breakpoint.getMarker().setAttribute(IBreakpoint.ENABLED, breakpoint.isEnabled());
				} catch (CoreException e) {
					// don't care if marker was already deleted
				}
			}
		};
		try {
			ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
		} catch (CoreException e) {
			DebugPlugin.log(e);
		}
	}
}

