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

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IBreakpointImportParticipant;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.debug.core.IJavaWatchpoint;

/**
 * Default implementation covering the import of all platform Java breakpoints
 *
 * @since 3.5
 */
public class JavaBreakpointImportParticipant implements
		IBreakpointImportParticipant {

	// keep the last resource/timestamp with CU for optimization
	IResource lastResourceVerified = null;
	long lastResourceVerifiedTimeStamp = -1;
	CompilationUnit lastCompilationUnit = null;

	class BreakpointVerifier extends ASTVisitor {
		final int TYPE = 0;
		final int METHOD = 1;
		final int FIELD = 2;

		String fTypename = null;
		String fName = null;
		String fSignature = null;
		IBreakpoint fBreakpoint = null;
		CompilationUnit fUnit = null;
		Stack<String> fTypeNameStack = null;

		/**
		 * Constructor
		 *
		 * @param breakpoint
		 * @param unit
		 */
		public BreakpointVerifier(IBreakpoint breakpoint, CompilationUnit unit) {
			fTypename = getBreakpointTypeName(breakpoint);
			fName = getMemberName(breakpoint);
			fSignature = getMemberSignature(breakpoint);
			fBreakpoint = breakpoint;
			fUnit = unit;
			fTypeNameStack = new Stack<>();
		}

		/**
		 * Returns the value of the {@link JavaBreakpoint#TYPE_NAME} attribute
		 * from the breakpoint or <code>null</code>
		 *
		 * @param breakpoint
		 * @return the value of the type name attribute
		 */
		String getBreakpointTypeName(IBreakpoint breakpoint) {
			return breakpoint.getMarker().getAttribute(
					JavaBreakpoint.TYPE_NAME, null);
		}

		/**
		 * Returns the name of the member from the breakpoint attributes. The
		 * name will be one of (1) {@link JavaWatchpoint#FIELD_NAME}, if the
		 * breakpoint is a watchpoint, or (2)
		 * {@link JavaMethodBreakpoint#METHOD_NAME} if the breakpoint is a
		 * method or method entry breakpoint (3) <code>null</code> if there is
		 * no member name
		 *
		 * @param breakpoint
		 * @return the member name or <code>null</code>
		 */
		String getMemberName(IBreakpoint breakpoint) {
			if (breakpoint instanceof IJavaWatchpoint) {
				return breakpoint.getMarker().getAttribute(
						JavaWatchpoint.FIELD_NAME, null);
			}
			return breakpoint.getMarker().getAttribute(
					JavaMethodBreakpoint.METHOD_NAME, null);
		}

		/**
		 * Returns the signature of the member, defined with the
		 * {@link JavaMethodBreakpoint#METHOD_SIGNATURE} attribute, or
		 * <code>null</code>
		 *
		 * @param breakpoint
		 * @return the signature of the member or <code>null</code>
		 */
		String getMemberSignature(IBreakpoint breakpoint) {
			return breakpoint.getMarker().getAttribute(
					JavaMethodBreakpoint.METHOD_SIGNATURE, null);
		}

		/**
		 * Returns the fully qualified name of the enclosing type for the given
		 * node
		 *
		 * @param node
		 * @return the fully qualified name of the enclosing type
		 */
		private String getTypeName(ASTNode node) {
			return getTypeName(node, new StringBuilder());
		}

		/**
		 * Constructs the qualified name of the enclosing parent type
		 *
		 * @param node
		 *            the node to get the parent name for
		 * @param buffer
		 *            the buffer to write the name into
		 * @return the fully qualified name of the parent
		 */
		private String getTypeName(ASTNode node, StringBuilder buffer) {
			switch (node.getNodeType()) {
			case ASTNode.COMPILATION_UNIT: {
				CompilationUnit unit = (CompilationUnit) node;
				PackageDeclaration packageDeclaration = unit.getPackage();
				if (packageDeclaration != null) {
					buffer.insert(0, '.');
					buffer.insert(0, packageDeclaration.getName()
							.getFullyQualifiedName());
				}
				return String.valueOf(buffer);
			}
			default: {
				if (node instanceof AbstractTypeDeclaration) {
					AbstractTypeDeclaration typeDeclaration = (AbstractTypeDeclaration) node;
					ITypeBinding binding = typeDeclaration.resolveBinding();
					if (binding != null) {
						return binding.getBinaryName();
					}
					if (typeDeclaration.isPackageMemberTypeDeclaration()) {
						buffer.insert(0, typeDeclaration.getName()
								.getIdentifier());
					} else {
						buffer.insert(0, typeDeclaration.getName()
								.getFullyQualifiedName());
						buffer.insert(0, '$');
					}
				}
			}
			}
			return getTypeName(node.getParent(), buffer);
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclaration)
		 */
		@Override
		public boolean visit(TypeDeclaration node) {
			return doTypeVisit(node);
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.TypeDeclaration)
		 */
		@Override
		public void endVisit(TypeDeclaration node) {
			doEndTypeVisit();
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
		 */
		@Override
		public boolean visit(EnumDeclaration node) {
			return doTypeVisit(node);
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.EnumDeclaration)
		 */
		@Override
		public void endVisit(EnumDeclaration node) {
			doEndTypeVisit();
		}

		/**
		 * Cleans up after a type visit has ended
		 */
		private void doEndTypeVisit() {
			if (!fTypeNameStack.isEmpty()) {
				fTypeNameStack.pop();
			}
		}

		/**
		 * Visits the type node and return if children should be visited
		 *
		 * @param node
		 * @return true if child nodes should be visited false otherwise
		 */
		private boolean doTypeVisit(AbstractTypeDeclaration node) {
			SimpleName name = node.getName();
			String typename = getTypeName(node);
			fTypeNameStack.push(typename);
			if (!fTypename.startsWith(typename)) {
				// we are examining the wrong type stop and process other types
				return false;
			}
			if (fBreakpoint instanceof JavaClassPrepareBreakpoint
					&& name != null && typename.equals(fTypename)) {
				int charstart = name.getStartPosition();
				IMarker marker = fBreakpoint.getMarker();
				try {
					marker.setAttribute(IMarker.CHAR_START, charstart);
					marker.setAttribute(IMarker.CHAR_END,
							charstart + name.getLength());
				} catch (CoreException ce) {
				}
				// found the node we were looking for, do not visit children
				return false;
			}
			return fTypename.indexOf('$') > -1 || name != null;
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
		 */
		@Override
		public boolean visit(FieldDeclaration node) {
			if (!fTypename.equals(fTypeNameStack.peek())) {
				return false;
			}
			List<VariableDeclarationFragment> fragments = node.fragments();
			SimpleName name = null;
			IMarker marker = fBreakpoint.getMarker();
			int currentstart = marker.getAttribute(IMarker.CHAR_START, -1);
			for (VariableDeclarationFragment fragment : fragments) {
				name = fragment.getName();
				if (name != null && name.getFullyQualifiedName().equals(fName)) {
					// found field update the charstart / charend
					int charstart = name.getStartPosition();
					if (currentstart != charstart) {
						try {
							marker.setAttribute(IMarker.CHAR_START, charstart);
							marker.setAttribute(IMarker.CHAR_END, charstart
									+ name.getLength());
						} catch (CoreException ce) {
						}
					}
				}
			}
			return false;
		}

		/**
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
		 */
		@Override
		public boolean visit(MethodDeclaration node) {
			SimpleName name = node.getName();
			String typename = fTypeNameStack.peek();
			if (!fTypename.equals(typename) && !fTypename.startsWith(typename)) {
				return false;
			}
			if (name != null && name.getFullyQualifiedName().equals(fName)) {
				String sig = getMethodSignatureFromNode(node);
				if (sig != null) {
					sig = sig.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
					if (sig.equals(fSignature)) {
						IMarker marker = fBreakpoint.getMarker();
						int currentstart = marker.getAttribute(
								IMarker.CHAR_START, -1);
						int charstart = name.getStartPosition();
						if (currentstart != charstart) {
							try {
								marker.setAttribute(IMarker.CHAR_START,
										charstart);
								marker.setAttribute(IMarker.CHAR_END, charstart
										+ name.getLength());
							} catch (CoreException ce) {
							}
						}
					}
				}
			}
			// visit children in the event we have a class load breakpoint on a
			// local type
			return fBreakpoint instanceof JavaClassPrepareBreakpoint;
		}

		/**
		 * Creates a method signature from a specified {@link MethodDeclaration}
		 *
		 * @param node
		 * @return the signature for the given method node or <code>null</code>
		 */
		private String getMethodSignatureFromNode(MethodDeclaration node) {
			Assert.isNotNull(node);
			List<SingleVariableDeclaration> params = node.parameters();
			List<String> rparams = getParametersTypeNames(params);
			if (rparams.size() == params.size()) {
				if (!node.isConstructor()) {
					Type returnType = node.getReturnType2();
					if (returnType != null) {
						String rtype = getTypeSignature(returnType);
						if (rtype != null) {
							return Signature
									.createMethodSignature(
											rparams
													.toArray(new String[rparams
															.size()]), rtype);
						}
					}
				} else {
					StringBuilder buffer = new StringBuilder();
					buffer.append("<init>"); //$NON-NLS-1$
					collectSyntheticParam(node, rparams);
					buffer.append(Signature.createMethodSignature(
							rparams.toArray(new String[rparams
									.size()]), Signature.SIG_VOID));
					return buffer.toString();
				}
			}
			return null;
		}

		/**
		 * Returns the listing of the signatures of the parameters passed in
		 *
		 * @param rawparams
		 * @return a listing of signatures for the specified parameters
		 */
		private List<String> getParametersTypeNames(List<SingleVariableDeclaration> rawparams) {
			List<String> rparams = new ArrayList<>(rawparams.size());
			String pname = null;
			for (SingleVariableDeclaration param : rawparams) {
				pname = getTypeSignature(param.getType());
				if (pname != null) {
					rparams.add(pname);
				}
			}
			return rparams;
		}

		/**
		 * Processes the signature for the given {@link Type}
		 *
		 * @param type
		 *            the type to process
		 * @return the signature for the type or <code>null</code> if one could
		 *         not be derived
		 */
		private String getTypeSignature(Type type) {
			ITypeBinding binding = type.resolveBinding();
			if (binding == null) {
				return null;
			}
			switch (type.getNodeType()) {
			case ASTNode.PRIMITIVE_TYPE:
			case ASTNode.QUALIFIED_TYPE:
			case ASTNode.SIMPLE_TYPE: {
				return Signature.createTypeSignature(
						binding.getQualifiedName(), true);
			}
			case ASTNode.ARRAY_TYPE: {
				ArrayType a = (ArrayType) type;
				return Signature
						.createArraySignature(
								getTypeSignature(a.getElementType()),
								a.getDimensions());
			}
			case ASTNode.PARAMETERIZED_TYPE: {
				// we don't need to care about the other scoping types only the
				// base type
				return getTypeSignature(((ParameterizedType) type).getType());
			}
			}
			return null;
		}

		/**
		 * Collects the synthetic parameter of the fully qualified name of the
		 * enclosing context for a constructor of an inner type
		 *
		 * @param method
		 *            the constructor declaration
		 * @param rparams
		 *            the listing of parameters to add to
		 */
		private void collectSyntheticParam(final MethodDeclaration method,
				List<String> rparams) {
			Assert.isNotNull(method);
			if (isInTopLevelType(method)) {
				return;
			}
			ASTNode parent = method.getParent();
			StringBuilder name = new StringBuilder();
			while (parent != null) {
				parent = parent.getParent();
				if (parent instanceof AbstractTypeDeclaration) {
					AbstractTypeDeclaration type = (AbstractTypeDeclaration) parent;
					name.insert(0, type.getName().getFullyQualifiedName());
					if (type.isMemberTypeDeclaration()) {
						name.insert(0, '$');
					}
					continue;
				}
				if (parent instanceof CompilationUnit) {
					CompilationUnit cunit = (CompilationUnit) parent;
					PackageDeclaration pdec = cunit.getPackage();
					if (pdec != null) {
						name.insert(0, '.');
						name.insert(0, cunit.getPackage().getName()
								.getFullyQualifiedName());
					}
				}
			}
			name.insert(0, "L"); //$NON-NLS-1$
			name.append(';');
			if (name.length() > 2) {
				rparams.add(0, name.toString());
			}
		}

		/**
		 * Determines if the given {@link MethodDeclaration} is present in a top
		 * level type
		 *
		 * @param method
		 * @return
		 */
		private boolean isInTopLevelType(final MethodDeclaration method) {
			TypeDeclaration type = (TypeDeclaration) method.getParent();
			return type != null && type.isPackageMemberTypeDeclaration();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.debug.core.model.IBreakpointImportParticipant#matches(java
	 * .util.Map, org.eclipse.debug.core.model.IBreakpoint)
	 */
	@Override
	public boolean matches(Map<String, Object> attributes, IBreakpoint breakpoint)
			throws CoreException {
		if (attributes == null || breakpoint == null) {
			return false;
		}
		String type = (String) attributes.get("type"); //$NON-NLS-1$
		if (type == null) {
			return false;
		}
		if (!breakpoint.getMarker().getType().equals(type)) {
			return false;
		}
		if (breakpoint instanceof JavaClassPrepareBreakpoint) {
			return matchesClassBreakpoint(attributes,
					(JavaClassPrepareBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaExceptionBreakpoint) {
			return matchesExceptionBreakpoint(attributes,
					(JavaExceptionBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaMethodBreakpoint) {
			return matchesMethodBreakpoint(attributes,
					(JavaMethodBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaMethodEntryBreakpoint) {
			return matchesMethodEntryBreakpoint(attributes,
					(JavaMethodEntryBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaWatchpoint) {
			return matchesWatchpoint(attributes, (JavaWatchpoint) breakpoint);
		}
		if (breakpoint instanceof JavaStratumLineBreakpoint) {
			return matchesStratumLineBreakpoint(attributes,
					(JavaStratumLineBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaPatternBreakpoint) {
			return matchesPatternBreakpoint(attributes,
					(JavaPatternBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaTargetPatternBreakpoint) {
			return matchesTargetPatternBreakpoint(attributes,
					(JavaTargetPatternBreakpoint) breakpoint);
		}
		if (breakpoint instanceof JavaLineBreakpoint) {
			return matchesLineBreakpoint(attributes,
					(JavaLineBreakpoint) breakpoint);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.debug.core.model.IBreakpointImportParticipant#verify(org.
	 * eclipse.debug.core.model.IBreakpoint)
	 */
	@Override
	public void verify(IBreakpoint breakpoint) throws CoreException {
		IResource resource = breakpoint.getMarker().getResource();
		CompilationUnit unit = null;
		if (resource != null && resource.getType() == IResource.FILE) {
			if (resource.equals(lastResourceVerified)) {
				if (resource.getModificationStamp() == lastResourceVerifiedTimeStamp) {
					unit = lastCompilationUnit;
				}
			}
			if (unit == null) {
				ICompilationUnit cunit = JavaCore.createCompilationUnitFrom((IFile) resource);
				if (cunit != null) {
					ASTParser parser = ASTParser.newParser(AST.JLS4);
					parser.setSource(cunit);
					parser.setResolveBindings(true);
					unit = (CompilationUnit) parser.createAST(new NullProgressMonitor());
				}
			}
		}
		if (unit != null) {
			lastResourceVerified = resource;
			lastCompilationUnit = unit;
			lastResourceVerifiedTimeStamp = lastResourceVerified.getModificationStamp();
			if (breakpoint instanceof JavaClassPrepareBreakpoint
					|| breakpoint instanceof JavaWatchpoint
					|| breakpoint instanceof JavaMethodEntryBreakpoint
					|| breakpoint instanceof JavaMethodBreakpoint) {
				unit.accept(new BreakpointVerifier(breakpoint, unit));
			} else if (breakpoint instanceof JavaLineBreakpoint) {
				JavaLineBreakpoint bp = (JavaLineBreakpoint) breakpoint;
				// line breakpoint use the ValidBreakpointLocationLocator to
				// (re)place it
				int currentline = bp.getLineNumber();
				ValidBreakpointLocationLocator locator = new ValidBreakpointLocationLocator(
						unit, currentline, true, true);
				unit.accept(locator);
				int newline = locator.getLineLocation();
				if (locator.getLocationType() == ValidBreakpointLocationLocator.LOCATION_LINE) {
					if (currentline != newline) {
						if (locator.getFullyQualifiedTypeName() == null)
							throw new CoreException(Status.CANCEL_STATUS);
						bp.getMarker().setAttribute(JavaBreakpoint.TYPE_NAME,
								locator.getFullyQualifiedTypeName());
						bp.getMarker().setAttribute(IMarker.LINE_NUMBER,
								newline);
						int length = bp.getCharEnd() - bp.getCharStart();
						int pos = unit.getPosition(newline, 1);
						bp.getMarker().setAttribute(IMarker.CHAR_START, pos);
						bp.getMarker().setAttribute(IMarker.CHAR_END,
								pos + length);
					}
				} else {
					// the line breakpoint will not be a line breakpoint anymore
					// get rid of it
					throw new CoreException(Status.CANCEL_STATUS);
				}
			}
		}
	}

	/**
	 * Compares two attributes in a <code>null</code> safe way
	 *
	 * @param attr1
	 *            the first attribute
	 * @param attr2
	 *            the second attribute
	 * @return true if the attributes are equal, false otherwise. If both
	 *         attributes are <code>null</code> they are considered to be equal
	 */
	private boolean attributesEqual(Object attr1, Object attr2) {
		if (attr1 == null) {
			return attr2 == null;
		}
		if (attr2 == null) {
			return false;
		}
		return attr1.equals(attr2);
	}

	/**
	 * Returns if the given map of attributes matches the given line breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesLineBreakpoint(Map<String, Object> attributes,
			JavaLineBreakpoint breakpoint) throws CoreException {
		Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER);
		return breakpoint.getLineNumber() == (line == null ? -1 : line.intValue())
				&& attributesEqual(breakpoint.getTypeName(), attributes.get(JavaBreakpoint.TYPE_NAME));
	}

	/**
	 * Returns if the given map of attributes matches the given class prepare
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesClassBreakpoint(Map<String, Object> attributes,
			JavaClassPrepareBreakpoint breakpoint) throws CoreException {
		Integer type = (Integer) attributes
				.get(JavaClassPrepareBreakpoint.MEMBER_TYPE);
		return attributesEqual(breakpoint.getTypeName(),
				attributes.get(JavaBreakpoint.TYPE_NAME))
				&& breakpoint.getMemberType() == (type == null ? -1 : type
						.intValue());
	}

	/**
	 * Returns if the given map of attributes matches the given exception
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesExceptionBreakpoint(Map<String, Object> attributes,
			JavaExceptionBreakpoint breakpoint) throws CoreException {
		return attributesEqual(breakpoint.getTypeName(),
				attributes.get(JavaBreakpoint.TYPE_NAME));

	}

	/**
	 * Returns if the given map of attributes matches the given method
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesMethodBreakpoint(Map<String, Object> attributes,
			JavaMethodBreakpoint breakpoint) throws CoreException {
		return attributesEqual(breakpoint.getTypeName(),
				attributes.get(JavaBreakpoint.TYPE_NAME))
				&& attributesEqual(breakpoint.getMethodName(),
						attributes.get(JavaMethodBreakpoint.METHOD_NAME))
				&& attributesEqual(breakpoint.getMethodSignature(),
						attributes.get(JavaMethodBreakpoint.METHOD_SIGNATURE));
	}

	/**
	 * Returns if the given map of attributes matches the given method entry
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesMethodEntryBreakpoint(Map<String, Object> attributes,
			JavaMethodEntryBreakpoint breakpoint) throws CoreException {
		return attributesEqual(breakpoint.getTypeName(),
				attributes.get(JavaBreakpoint.TYPE_NAME))
				&& attributesEqual(breakpoint.getMethodName(),
						attributes.get(JavaMethodBreakpoint.METHOD_NAME))
				&& attributesEqual(breakpoint.getMethodSignature(),
						attributes.get(JavaMethodBreakpoint.METHOD_SIGNATURE));
	}

	/**
	 * Returns if the given map of attributes matches the given watchpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the watchpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesWatchpoint(Map<String, Object> attributes, JavaWatchpoint watchpoint)
			throws CoreException {
		return watchpoint.getFieldName().equals(
				attributes.get(JavaWatchpoint.FIELD_NAME))
				&& attributesEqual(watchpoint.getTypeName(),
						attributes.get(JavaBreakpoint.TYPE_NAME));
	}

	/**
	 * Returns if the given map of attributes matches the given stratum line
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesStratumLineBreakpoint(Map<String, Object> attributes,
			JavaStratumLineBreakpoint breakpoint) throws CoreException {
		Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER);
		return breakpoint.getLineNumber() == (line == null ? -1 : line
				.intValue())
				&& attributesEqual(breakpoint.getSourceName(),
						attributes.get(JavaLineBreakpoint.SOURCE_NAME))
				&& attributesEqual(breakpoint.getStratum(),
						attributes.get(JavaStratumLineBreakpoint.STRATUM))
				&& attributesEqual(breakpoint.getSourcePath(),
						attributes.get(JavaStratumLineBreakpoint.SOURCE_PATH));
	}

	/**
	 * Returns if the given map of attributes matches the given pattern
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesPatternBreakpoint(Map<String, Object> attributes,
			JavaPatternBreakpoint breakpoint) throws CoreException {
		Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER);
		return breakpoint.getLineNumber() == (line == null ? -1 : line
				.intValue())
				&& attributesEqual(breakpoint.getSourceName(),
						attributes.get(JavaLineBreakpoint.SOURCE_NAME)) &&
				// TDOD comparing pattern too restrictive??
				breakpoint.getPattern().equals(
						attributes.get(JavaPatternBreakpoint.PATTERN));
	}

	/**
	 * Returns if the given map of attributes matches the given target pattern
	 * breakpoint
	 *
	 * @param attributes
	 * @param breakpoint
	 * @return true if the attributes match the breakpoints' attributes, false
	 *         otherwise
	 * @throws CoreException
	 */
	private boolean matchesTargetPatternBreakpoint(Map<String, Object> attributes,
			JavaTargetPatternBreakpoint breakpoint) throws CoreException {
		Integer line = (Integer) attributes.get(IMarker.LINE_NUMBER);
		return breakpoint.getLineNumber() == (line == null ? -1 : line
				.intValue())
				&& attributesEqual(breakpoint.getTypeName(),
						attributes.get(JavaBreakpoint.TYPE_NAME))
				&& attributesEqual(breakpoint.getSourceName(),
						attributes.get(JavaLineBreakpoint.SOURCE_NAME));
	}
}
