/*******************************************************************************
 *  Copyright (c) 2000, 2020 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.text.MessageFormat;
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;

/**
 * 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());
				// If the breakpoint is a trigger point, remove else do nothing.
				removeTriggerPoint(breakpoint);
			}
			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);
					if (breakpoint instanceof ITriggerPoint && ((ITriggerPoint) breakpoint).isTriggerPoint()) {
						addTriggerPoint(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()]), true);
				} 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);
		}
	}
}

