/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILogicalStructureType;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDisconnect;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.ITerminate;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.core.model.IWatchExpression;
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
import org.eclipse.debug.core.sourcelookup.containers.ZipEntryStorage;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.DefaultLabelProvider;
import org.eclipse.debug.internal.ui.views.variables.VariablesView;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugModelPresentationExtension;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IValueDetailListener;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IJavaArray;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaClassPrepareBreakpoint;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
import org.eclipse.jdt.debug.core.IJavaMethodEntryBreakpoint;
import org.eclipse.jdt.debug.core.IJavaModifiers;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaPatternBreakpoint;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaStratumLineBreakpoint;
import org.eclipse.jdt.debug.core.IJavaTargetPatternBreakpoint;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.core.IJavaWatchpoint;
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaExceptionBreakpoint;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIAllInstancesValue;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIReturnValueVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugModelMessages;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListEntryVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListValue;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListVariable;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaContendedMonitor;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwnedMonitor;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwningThread;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaWaitingThread;
import org.eclipse.jdt.internal.debug.ui.monitors.NoMonitorInformationElement;
import org.eclipse.jdt.internal.debug.ui.monitors.ThreadMonitorManager;
import org.eclipse.jdt.internal.debug.ui.snippeteditor.SnippetMessages;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.ui.ISharedImages;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.resource.CompositeImageDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;

import com.sun.jdi.ObjectCollectedException;

/**
 * Determines how to display java elements, including labels, images and editors.
 * @see IDebugModelPresentation
 */
public class JDIModelPresentation extends LabelProvider implements IDebugModelPresentationExtension, IColorProvider {

	/**
	 * Qualified names presentation property (value <code>"DISPLAY_QUALIFIED_NAMES"</code>).
	 * When <code>DISPLAY_QUALIFIED_NAMES</code> is set to <code>True</code>,
	 * this label provider should use fully qualified type names when rendering elements.
	 * When set to <code>False</code>, this label provider should use simple
	 * names when rendering elements.
	 * @see #setAttribute(String, Object)
	 */
	public final static String DISPLAY_QUALIFIED_NAMES= "DISPLAY_QUALIFIED_NAMES"; //$NON-NLS-1$

	protected HashMap<String, Object> fAttributes= new HashMap<>(3);

	static final Point BIG_SIZE= new Point(16, 16);

	private static org.eclipse.jdt.internal.debug.ui.ImageDescriptorRegistry fgDebugImageRegistry;

	/**
	 * Flag to indicate if image registry's referenced by this model presentation is initialized
	 */
	private static boolean fInitialized = false;

	protected static final String fgStringName= "java.lang.String"; //$NON-NLS-1$

	/******
	 * This constant is here for experimental purposes only and should not be used.
	 * It is used to store a suffix for a breakpoint's label in its marker.
	 * It is not officially supported and might be removed in the future.
	 * */
	private static final String BREAKPOINT_LABEL_SUFFIX = "JDT_BREAKPOINT_LABEL_SUFFIX"; //$NON-NLS-1$

	private JavaElementLabelProvider fJavaLabelProvider;

	public JDIModelPresentation() {
		super();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
	 */
	@Override
	public void dispose() {
		super.dispose();
		if (fJavaLabelProvider != null) {
			fJavaLabelProvider.dispose();
		}
		fAttributes.clear();
	}

	/**
	 * @see IDebugModelPresentation#computeDetail(IValue, IValueDetailListener)
	 */
	@Override
	public void computeDetail(IValue value, IValueDetailListener listener) {
		IJavaThread thread = getEvaluationThread((IJavaDebugTarget)value.getDebugTarget());
		if (thread == null) {
			listener.detailComputed(value, DebugUIMessages.JDIModelPresentation_no_suspended_threads);
		} else {
			JavaDetailFormattersManager.getDefault().computeValueDetail((IJavaValue)value, thread, listener);
		}
	}

	/**
	 * Returns a thread from the specified VM that can be
	 * used for an evaluation or <code>null</code> if
	 * none.
	 *
	 * @param debug target the target in which a thread is
	 * 	required
	 * @return thread or <code>null</code>
	 */
	public static IJavaThread getEvaluationThread(IJavaDebugTarget target) {
		IJavaStackFrame frame = EvaluationContextManager.getEvaluationContext((IWorkbenchWindow)null);
		IJavaThread thread = null;
		if (frame != null) {
			thread = (IJavaThread) frame.getThread();
		}
		if (thread != null && (!thread.getDebugTarget().equals(target) || (!thread.isSuspended() && !thread.isPerformingEvaluation()))) {
			// can only use suspended threads in the same target
			thread = null;
		}
		if (thread == null) {
			try {
				IThread[] threads = target.getThreads();
				for (int i = 0; i < threads.length; i++) {
					if (threads[i].isSuspended()) {
						thread = (IJavaThread)threads[i];
						break;
					}
				}
			} catch (DebugException e) {
				JDIDebugUIPlugin.log(e);
			}
		}
		return thread;
	}

	/**
	 * @see IDebugModelPresentation#getText(Object)
	 */
	@Override
	public String getText(Object item) {
		try {
			boolean showQualified= isShowQualifiedNames();
			if (item instanceof IJavaVariable) {
				return getVariableText((IJavaVariable) item);
			} else if (item instanceof IStackFrame) {
				StringBuilder label= new StringBuilder(getStackFrameText((IStackFrame) item));
				if (item instanceof IJavaStackFrame) {
					if (((IJavaStackFrame)item).isOutOfSynch()) {
						label.append(DebugUIMessages.JDIModelPresentation___out_of_synch__1);
					}
				}
				return label.toString();
			} else if (item instanceof IMarker) {
				IBreakpoint breakpoint = getBreakpoint((IMarker)item);
				if (breakpoint != null) {
					return getBreakpointText(breakpoint);
				}
				return null;
			} else if (item instanceof IBreakpoint) {
				return getBreakpointText((IBreakpoint)item);
			} else if (item instanceof IWatchExpression) {
				return getWatchExpressionText((IWatchExpression)item);
			} else if (item instanceof IExpression) {
				return getExpressionText((IExpression)item);
			} else if (item instanceof JavaOwnedMonitor) {
				return getJavaOwnedMonitorText((JavaOwnedMonitor)item);
			} else if (item instanceof JavaContendedMonitor) {
				return getJavaContendedMonitorText((JavaContendedMonitor)item);
			} else if (item instanceof JavaOwningThread) {
				return getJavaOwningTreadText((JavaOwningThread)item);
			} else if (item instanceof JavaWaitingThread) {
				return getJavaWaitingTreadText((JavaWaitingThread)item);
			} else if (item instanceof NoMonitorInformationElement) {
                return DebugUIMessages.JDIModelPresentation_5;
            } else {
				StringBuilder label= new StringBuilder();
				if (item instanceof IJavaThread) {
					label.append(getThreadText((IJavaThread) item, showQualified));
					if (((IJavaThread)item).isOutOfSynch()) {
						label.append(DebugUIMessages.JDIModelPresentation___out_of_synch__1);
					} else if (((IJavaThread)item).mayBeOutOfSynch()) {
						label.append(DebugUIMessages.JDIModelPresentation___may_be_out_of_synch__2);
					}
				} else if (item instanceof IJavaDebugTarget) {
					label.append(getDebugTargetText((IJavaDebugTarget) item));
					if (((IJavaDebugTarget)item).isOutOfSynch()) {
						label.append(DebugUIMessages.JDIModelPresentation___out_of_synch__1);
					} else if (((IJavaDebugTarget)item).mayBeOutOfSynch()) {
						label.append(DebugUIMessages.JDIModelPresentation___may_be_out_of_synch__2);
					}
				} else if (item instanceof IJavaValue) {
					label.append(getValueText((IJavaValue) item));
				}
				if (item instanceof ITerminate) {
					if (((ITerminate) item).isTerminated()) {
						label.insert(0, DebugUIMessages.JDIModelPresentation__terminated__2);
						return label.toString();
					}
				}
				if (item instanceof IDisconnect) {
					if (((IDisconnect) item).isDisconnected()) {
						label.insert(0, DebugUIMessages.JDIModelPresentation__disconnected__4);
						return label.toString();
					}
				}
				if (label.length() > 0) {
					return label.toString();
				}
			}
		} catch (CoreException e) {
			return DebugUIMessages.JDIModelPresentation__not_responding__6;
		}
		return null;
	}

	private String getJavaOwningTreadText(JavaOwningThread thread) throws CoreException {
		return getFormattedString(DebugUIMessages.JDIModelPresentation_0, getThreadText(thread.getThread().getThread(), isShowQualifiedNames()));
	}

	private String getJavaWaitingTreadText(JavaWaitingThread thread) throws CoreException {
		return getFormattedString(DebugUIMessages.JDIModelPresentation_1, getThreadText(thread.getThread().getThread(), isShowQualifiedNames()));
	}

	private String getJavaContendedMonitorText(JavaContendedMonitor monitor) throws DebugException {
		return getFormattedString(DebugUIMessages.JDIModelPresentation_2, getValueText(monitor.getMonitor().getMonitor()));
	}

	private String getJavaOwnedMonitorText(JavaOwnedMonitor monitor) throws DebugException {
		return getFormattedString(DebugUIMessages.JDIModelPresentation_3, getValueText(monitor.getMonitor().getMonitor()));
	}

	protected IBreakpoint getBreakpoint(IMarker marker) {
		return DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker);
		}

	/**
	 * Build the text for an IJavaThread.
	 */
	protected String getThreadText(IJavaThread thread, boolean qualified) throws CoreException {
		StringBuilder key = new StringBuilder("thread_"); //$NON-NLS-1$
		String[] args = null;
		IBreakpoint[] breakpoints= thread.getBreakpoints();
		if (thread.isDaemon()) {
			key.append("daemon_"); //$NON-NLS-1$
		}
		if (thread.isSystemThread()) {
			key.append("system_"); //$NON-NLS-1$
		}
		if (thread.isTerminated()) {
			key.append("terminated"); //$NON-NLS-1$
			args = new String[] {thread.getName()};
		} else if (thread.isStepping()) {
			key.append("stepping"); //$NON-NLS-1$
			args = new String[] {thread.getName()};
		} else if ((thread instanceof JDIThread && ((JDIThread)thread).isSuspendVoteInProgress()) && !thread.getDebugTarget().isSuspended()) {
			// show running when listener notification is in progress
			key.append("running"); //$NON-NLS-1$
			args = new String[] {thread.getName()};
		} else if (thread.isPerformingEvaluation() && breakpoints.length == 0) {
			key.append("evaluating"); //$NON-NLS-1$
			args = new String[] {thread.getName()};
		} else if (!thread.isSuspended()) {
			key.append("running"); //$NON-NLS-1$
			args = new String[] {thread.getName()};
		} else {
			key.append("suspended"); //$NON-NLS-1$
			if (breakpoints.length > 0) {
				IJavaBreakpoint breakpoint= (IJavaBreakpoint)breakpoints[0];
				for (int i= 0, numBreakpoints= breakpoints.length; i < numBreakpoints; i++) {
					if (BreakpointUtils.isProblemBreakpoint(breakpoints[i])) {
						// If a compilation error breakpoint exists, display it instead of the first breakpoint
						breakpoint= (IJavaBreakpoint)breakpoints[i];
						break;
					}
				}
				String typeName= getMarkerTypeName(breakpoint, qualified);
				if (BreakpointUtils.isProblemBreakpoint(breakpoint)) {
					IJavaStackFrame frame = (IJavaStackFrame)thread.getTopStackFrame();
					IMarker problem = null;
					if (frame != null) {
						problem = JavaDebugOptionsManager.getDefault().getProblem(frame);
					}
					if (problem != null) {
						key.append("_problem"); //$NON-NLS-1$
						String message = problem.getAttribute(IMarker.MESSAGE, DebugUIMessages.JDIModelPresentation_Compilation_error_1);
						args = new String[] {thread.getName(), message};
					}
				}
				// check args == null in case the exception is a compilation error
				if (breakpoint instanceof IJavaExceptionBreakpoint && args == null) {
					key.append("_exception"); //$NON-NLS-1$
					String exName = ((IJavaExceptionBreakpoint)breakpoint).getExceptionTypeName();
					if (exName == null) {
						exName = typeName;
					} else if (!qualified) {
						int index = exName.lastIndexOf('.');
						exName = exName.substring(index + 1);
					}
					if (exName != null) {
						args = new String[] { thread.getName(), exName };
					}
				} else if (breakpoint instanceof IJavaWatchpoint) {
					IJavaWatchpoint wp = (IJavaWatchpoint)breakpoint;
					String fieldName = wp.getFieldName();
					args = new String[] {thread.getName(), fieldName, typeName};
					if (wp.isAccessSuspend(thread.getDebugTarget())) {
						key.append("_fieldaccess"); //$NON-NLS-1$
					} else {
						key.append("_fieldmodification"); //$NON-NLS-1$
					}
				} else if (breakpoint instanceof IJavaMethodBreakpoint) {
					IJavaMethodBreakpoint me= (IJavaMethodBreakpoint)breakpoint;
					String methodName= me.getMethodName();
					args = new String[] {thread.getName(), methodName, typeName};
					if (me.isEntrySuspend(thread.getDebugTarget())) {
						key.append("_methodentry"); //$NON-NLS-1$
					} else {
						key.append("_methodexit"); //$NON-NLS-1$
					}
				} else if (breakpoint instanceof IJavaLineBreakpoint) {
					IJavaLineBreakpoint jlbp = (IJavaLineBreakpoint)breakpoint;
					int lineNumber= jlbp.getLineNumber();
					if (lineNumber > -1) {
						args = new String[] {thread.getName(), String.valueOf(lineNumber), typeName};
						if (BreakpointUtils.isRunToLineBreakpoint(jlbp)) {
							key.append("_runtoline"); //$NON-NLS-1$
						} else {
							key.append("_linebreakpoint"); //$NON-NLS-1$
						}
					}
				} else if (breakpoint instanceof IJavaClassPrepareBreakpoint) {
					key.append("_classprepare"); //$NON-NLS-1$
					args = new String[]{thread.getName(), getQualifiedName(breakpoint.getTypeName())};
				}
			}

			if (args == null) {
				// Otherwise, it's just suspended
				args =  new String[] {thread.getName()};
			}
		}
		try {
			return getFormattedString((String)DebugUIMessages.class.getDeclaredField(key.toString()).get(null), args);
		} catch (IllegalArgumentException e) {
			JDIDebugUIPlugin.log(e);
		} catch (SecurityException e) {
			JDIDebugUIPlugin.log(e);
		} catch (IllegalAccessException e) {
			JDIDebugUIPlugin.log(e);
		} catch (NoSuchFieldException e) {
			JDIDebugUIPlugin.log(e);
		}
		return DebugUIMessages.JDIModelPresentation_unknown_name__1;
	}

	/**
	 * Build the text for an IJavaDebugTarget.
	 */
	protected String getDebugTargetText(IJavaDebugTarget debugTarget) throws DebugException {
		String labelString= debugTarget.getName();
		if (debugTarget.isSuspended()) {
			labelString += DebugUIMessages.JDIModelPresentation_target_suspended;
		}
		return labelString;
	}

	/**
	 * Build the text for an IJavaValue.
	 *
	 * @param value the value to get the text for
	 * @return the value string
	 * @throws DebugException if something happens trying to compute the value string
	 */
	public String getValueText(IJavaValue value) throws DebugException {
		String refTypeName= value.getReferenceTypeName();
		String valueString= value.getValueString();
		boolean isString= refTypeName.equals(fgStringName);
		IJavaType type= value.getJavaType();
		String signature= null;
		if (type != null) {
			signature= type.getSignature();
		}
		if ("V".equals(signature)) { //$NON-NLS-1$
			valueString= DebugUIMessages.JDIModelPresentation__No_explicit_return_value__30;
		}
		boolean isObject= isObjectValue(signature);
		boolean isArray= value instanceof IJavaArray;
		StringBuilder buffer= new StringBuilder();
		if(isUnknown(signature)) {
			buffer.append(signature);
		} else if (isObject && !isString && (refTypeName.length() > 0)) {
			// Don't show type name for instances and references
			if (!(value instanceof JDIReferenceListValue || value instanceof JDIAllInstancesValue)){
				String qualTypeName= getQualifiedName(refTypeName).trim();
				if (isArray) {
					qualTypeName= adjustTypeNameForArrayIndex(qualTypeName, ((IJavaArray)value).getLength());
				}
				buffer.append(qualTypeName);
				buffer.append(' ');
			}
		}

		// Put double quotes around Strings
		if (valueString != null && (isString || valueString.length() > 0)) {
			if (isString) {
				buffer.append('"');
			}
			buffer.append(DefaultLabelProvider.escapeSpecialChars(valueString));
			if (isString) {
				buffer.append('"');
				if(value instanceof IJavaObject){
					buffer.append(" "); //$NON-NLS-1$
					buffer.append(NLS.bind(DebugUIMessages.JDIModelPresentation_118, new String[]{String.valueOf(((IJavaObject)value).getUniqueId())}));
				}
			}

		}

		// show unsigned value second, if applicable
		if (isShowUnsignedValues()) {
			buffer= appendUnsignedText(value, buffer);
		}
		// show hex value third, if applicable
		if (isShowHexValues()) {
			buffer= appendHexText(value, buffer);
		}
		// show byte character value last, if applicable
		if (isShowCharValues()) {
			buffer= appendCharText(value, buffer);
		}
		return buffer.toString().trim();
	}

	private StringBuilder appendUnsignedText(IJavaValue value, StringBuilder buffer) throws DebugException {
		String unsignedText= getValueUnsignedText(value);
		if (unsignedText != null) {
			buffer.append(" ["); //$NON-NLS-1$
			buffer.append(unsignedText);
			buffer.append("]"); //$NON-NLS-1$
		}
		return buffer;
	}

	protected StringBuilder appendHexText(IJavaValue value, StringBuilder buffer) throws DebugException {
		String hexText = getValueHexText(value);
		if (hexText != null) {
			buffer.append(" ["); //$NON-NLS-1$
			buffer.append(hexText);
			buffer.append("]"); //$NON-NLS-1$
		}
		return buffer;
	}

	protected StringBuilder appendCharText(IJavaValue value, StringBuilder buffer) throws DebugException {
		String charText= getValueCharText(value);
		if (charText != null) {
			buffer.append(" ["); //$NON-NLS-1$
			buffer.append(charText);
			buffer.append("]"); //$NON-NLS-1$
		}
		return buffer;
	}

	/**
	 * Returns <code>true</code> if the given signature is not <code>null</code> and
	 * matches the text '&lt;unknown&gt;'
	 *
	 * @param signature the signature to compare
	 * @return <code>true</code> if the signature matches '&lt;unknown&gt;'
	 * @since 3.6.1
	 */
	boolean isUnknown(String signature) {
		if(signature == null) {
			return false;
		}
		return JDIDebugModelMessages.JDIDebugElement_unknown.equals(signature);
	}

	/**
	 * Given a JNI-style signature String for a IJavaValue, return true
	 * if the signature represents an Object or an array of Objects.
	 *
	 * @param signature the signature to check
	 * @return <code>true</code> if the signature represents an object <code>false</code> otherwise
	 */
	public static boolean isObjectValue(String signature) {
		if (signature == null) {
			return false;
		}
		String type = Signature.getElementType(signature);
		char sigchar = type.charAt(0);
		if(sigchar == Signature.C_UNRESOLVED ||
				sigchar == Signature.C_RESOLVED) {
			return true;
		}
		return false;
	}

	/**
	 * Returns whether the image registry's have been retrieved.
	 *
	 * @return whether image registry's have been retrieved.
	 */
	public static boolean isInitialized() {
		return fgDebugImageRegistry != null;
	}

	/**
	 * Returns the type signature for this value if its type is primitive.
	 * For non-primitive types, null is returned.
	 */
	protected String getPrimitiveValueTypeSignature(IJavaValue value) throws DebugException {
		IJavaType type= value.getJavaType();
		if (type != null) {
			String sig= type.getSignature();
			if (sig != null && sig.length() == 1) {
				return sig;
			}
		}
		return null;
	}
	/**
	 * Returns the character string of a byte or <code>null</code> if
	 * the value can not be interpreted as a valid character.
	 */
	protected String getValueCharText(IJavaValue value) throws DebugException {
		String sig= getPrimitiveValueTypeSignature(value);
		if (sig == null) {
			return null;
		}
		String valueString= value.getValueString();
		long longValue;
		try {
			longValue= Long.parseLong(valueString);
		} catch (NumberFormatException e) {
			return null;
		}
		switch (sig.charAt(0)) {
			case 'B' : // byte
				longValue= longValue & 0xFF; // Only lower 8 bits
				break;
			case 'I' : // integer
				longValue= longValue & 0xFFFFFFFF; // Only lower 32 bits
				if (longValue > 0xFFFF || longValue < 0) {
					return null;
				}
				break;
			case 'S' : // short
				longValue= longValue & 0xFFFF; // Only lower 16 bits
				break;
			case 'J' :
				if (longValue > 0xFFFF || longValue < 0) {
					// Out of character range
					return null;
				}
				break;
			default :
				return null;
		}
		char charValue= (char)longValue;
		StringBuilder charText = new StringBuilder();
		if (Character.getType(charValue) == Character.CONTROL) {
			Character ctrl = new Character((char) (charValue + 64));
			charText.append('^');
			charText.append(ctrl);
			switch (charValue) { // common use
				case 0: charText.append(" (NUL)"); break; //$NON-NLS-1$
				case 8: charText.append(" (BS)"); break; //$NON-NLS-1$
				case 9: charText.append(" (TAB)"); break; //$NON-NLS-1$
				case 10: charText.append(" (LF)"); break; //$NON-NLS-1$
				case 13: charText.append(" (CR)"); break; //$NON-NLS-1$
				case 21: charText.append(" (NL)"); break; //$NON-NLS-1$
				case 27: charText.append(" (ESC)"); break; //$NON-NLS-1$
				case 127: charText.append(" (DEL)"); break; //$NON-NLS-1$
			}
		} else {
			charText.append(new Character(charValue));
		}
		return charText.toString();
	}

	@SuppressWarnings("deprecation")
	protected String getMarkerTypeName(IJavaBreakpoint breakpoint, boolean qualified) throws CoreException {
		String typeName= null;
		if (breakpoint instanceof IJavaPatternBreakpoint) {
			typeName = breakpoint.getMarker().getResource().getName();
		} else {
			typeName = breakpoint.getTypeName();
		}
		if (!qualified && typeName != null) {
			int index= typeName.lastIndexOf('.');
			if (index != -1) {
				typeName= typeName.substring(index + 1);
			}
		}
		return typeName;
	}

	/**
	 * Maps a Java element to an appropriate image.
	 *
	 * @see IDebugModelPresentation#getImage(Object)
	 */
	@Override
	public Image getImage(Object item) {

		initImageRegistries();

		try {
			if (item instanceof JDIReferenceListVariable) {
				return getReferencesImage(item);
			}
			if (item instanceof JDIReferenceListEntryVariable){
				return getReferenceImage(item);
			}
			if (item instanceof IJavaVariable) {
				return getVariableImage((IAdaptable) item);
			}
			if (item instanceof IMarker) {
				IBreakpoint bp = getBreakpoint((IMarker)item);
				if (bp != null && bp instanceof IJavaBreakpoint) {
					return getBreakpointImage((IJavaBreakpoint)bp);
				}
			}
			if (item instanceof IJavaBreakpoint) {
				return getBreakpointImage((IJavaBreakpoint)item);
			}
			if (item instanceof JDIThread) {
				JDIThread jt = (JDIThread) item;
				if (jt.isSuspendVoteInProgress()) {
					return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING);
				}
			}
			if (item instanceof IJavaStackFrame || item instanceof IJavaThread || item instanceof IJavaDebugTarget) {
				return getDebugElementImage(item);
			}
			if (item instanceof IJavaValue) {
				return JavaUI.getSharedImages().getImage(ISharedImages.IMG_FIELD_PUBLIC);
			}
			if (item instanceof IExpression) {
				return getExpressionImage(item);
			}
			if (item instanceof JavaOwnedMonitor) {
				return getJavaOwnedMonitorImage((JavaOwnedMonitor)item);
			}
			if (item instanceof JavaContendedMonitor) {
				return getJavaContendedMonitorImage((JavaContendedMonitor)item);
			}
			if (item instanceof JavaOwningThread) {
				return getJavaOwningThreadImage((JavaOwningThread)item);
			}
			if (item instanceof JavaWaitingThread) {
				return getJavaWaitingThreadImage((JavaWaitingThread)item);
			}
            if (item instanceof NoMonitorInformationElement) {
                return getDebugImageRegistry().get(new JDIImageDescriptor(
						getImageDescriptor(JavaDebugImages.IMG_OBJS_MONITOR), 0));
            }
		} catch (CoreException e) {
		    // no need to log errors - elements may no longer exist by the time we render them
		}
		return null;
	}

	/**
	 * Initialize image registry's that this model presentation references to
	 */
	private synchronized void initImageRegistries() {

		// if not initialized and this is called on the UI thread
		if (!fInitialized && Thread.currentThread().equals(JDIDebugUIPlugin.getStandardDisplay().getThread())) {
			// call get image registry's to force them to be created on the UI thread
			getDebugImageRegistry();
			JavaPlugin.getImageDescriptorRegistry();
			JavaUI.getSharedImages();
			fInitialized = true;
		}
	}

	/**
	 * @param thread
	 * @return
	 */
	private Image getJavaWaitingThreadImage(JavaWaitingThread thread) {
		JDIImageDescriptor descriptor;
		int flag= JDIImageDescriptor.IN_CONTENTION_FOR_MONITOR | (thread.getThread().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0);
		if (thread.isSuspended()) {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag);
		} else {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	/**
	 * @param thread
	 * @return
	 */
	private Image getJavaOwningThreadImage(JavaOwningThread thread) {
		JDIImageDescriptor descriptor;
		int flag= JDIImageDescriptor.OWNS_MONITOR | (thread.getThread().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0);
		if (thread.isSuspended()) {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED), flag);
		} else {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING), flag);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	/**
	 * @param monitor
	 * @return
	 */
	private Image getJavaContendedMonitorImage(JavaContendedMonitor monitor) {
		int flag= monitor.getMonitor().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0;
		JDIImageDescriptor descriptor= new JDIImageDescriptor(
				getImageDescriptor(JavaDebugImages.IMG_OBJS_CONTENDED_MONITOR), flag);
		return getDebugImageRegistry().get(descriptor);
	}

	/**
	 * @param monitor
	 * @return
	 */
	private Image getJavaOwnedMonitorImage(JavaOwnedMonitor monitor) {
		int flag= monitor.getMonitor().isInDeadlock() ? JDIImageDescriptor.IN_DEADLOCK : 0;
		JDIImageDescriptor descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_OWNED_MONITOR), flag);
		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getBreakpointImage(IJavaBreakpoint breakpoint) throws CoreException {
		if (breakpoint instanceof IJavaExceptionBreakpoint) {
			return getExceptionBreakpointImage((IJavaExceptionBreakpoint)breakpoint);
		} else if (breakpoint instanceof IJavaClassPrepareBreakpoint) {
			return getClassPrepareBreakpointImage((IJavaClassPrepareBreakpoint)breakpoint);
		}

		if (breakpoint instanceof IJavaLineBreakpoint && BreakpointUtils.isRunToLineBreakpoint((IJavaLineBreakpoint)breakpoint)) {
			return null;
		}
		return getJavaBreakpointImage(breakpoint);
	}

	protected Image getExceptionBreakpointImage(IJavaExceptionBreakpoint exception) throws CoreException {
		int flags= computeBreakpointAdornmentFlags(exception);
		JDIImageDescriptor descriptor= null;
		if ((flags & JDIImageDescriptor.ENABLED) == 0) {
			descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION_DISABLED), flags);
		} else if (exception.isChecked()) {
			descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_EXCEPTION), flags);
		} else {
			descriptor= new JDIImageDescriptor(getImageDescriptor(JavaDebugImages.IMG_OBJS_ERROR), flags);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getJavaBreakpointImage(IJavaBreakpoint breakpoint) throws CoreException {
		if (breakpoint instanceof IJavaMethodBreakpoint) {
			IJavaMethodBreakpoint mBreakpoint= (IJavaMethodBreakpoint)breakpoint;
			return getJavaMethodBreakpointImage(mBreakpoint);
		} else if (breakpoint instanceof IJavaWatchpoint) {
			IJavaWatchpoint watchpoint= (IJavaWatchpoint)breakpoint;
			return getJavaWatchpointImage(watchpoint);
		} else if (breakpoint instanceof IJavaMethodEntryBreakpoint) {
			IJavaMethodEntryBreakpoint meBreakpoint = (IJavaMethodEntryBreakpoint)breakpoint;
			return getJavaMethodEntryBreakpointImage(meBreakpoint);
		} else {
			int flags= computeBreakpointAdornmentFlags(breakpoint);
			JDIImageDescriptor descriptor= null;
			if (breakpoint.isEnabled()) {
				descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags);
			} else {
				descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags);
			}
			return getDebugImageRegistry().get(descriptor);
		}
	}

	protected Image getJavaMethodBreakpointImage(IJavaMethodBreakpoint mBreakpoint) throws CoreException {
		int flags= computeBreakpointAdornmentFlags(mBreakpoint);
		JDIImageDescriptor descriptor= null;
		if (mBreakpoint.isEnabled()) {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags);
		} else {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags);
		}

		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getJavaMethodEntryBreakpointImage(IJavaMethodEntryBreakpoint mBreakpoint) throws CoreException {
		int flags= computeBreakpointAdornmentFlags(mBreakpoint);
		JDIImageDescriptor descriptor= null;
		if (mBreakpoint.isEnabled()) {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT), flags);
		} else {
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED), flags);
		}

		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getClassPrepareBreakpointImage(IJavaClassPrepareBreakpoint breakpoint) throws CoreException {
		int flags= computeBreakpointAdornmentFlags(breakpoint);
		JDIImageDescriptor descriptor= null;
		if (breakpoint.getMemberType() == IJavaClassPrepareBreakpoint.TYPE_CLASS) {
			descriptor= new JDIImageDescriptor(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_CLASS), flags);
		} else {
			descriptor= new JDIImageDescriptor(JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INTERFACE), flags);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getJavaWatchpointImage(IJavaWatchpoint watchpoint) throws CoreException {
		int flags= computeBreakpointAdornmentFlags(watchpoint);
		JDIImageDescriptor descriptor= null;
		boolean enabled= (flags & JDIImageDescriptor.ENABLED) != 0;
		if (watchpoint.isAccess()) {
			if (watchpoint.isModification()) {
				//access and modification
				if (enabled) {
					descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT), flags);
				} else {
					descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags);
				}
			} else {
				if (enabled) {
					descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT), flags);
				} else {
					descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT_DISABLED), flags);
				}
			}
		} else if (watchpoint.isModification()) {
			if (enabled) {
				descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT), flags);
			} else {
				descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT_DISABLED), flags);
			}
		} else {
			//neither access nor modification
			descriptor= new JDIImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED), flags);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	protected Image getVariableImage(IAdaptable element) {
		CompositeImageDescriptor descriptor = new JavaElementImageDescriptor(
			computeBaseImageDescriptor(element), computeAdornmentFlags(element), BIG_SIZE);
		descriptor = new JDIElementImageDescriptor(descriptor, computeLogicalStructureAdornmentFlags(element), BIG_SIZE);
		Image image = JDIDebugUIPlugin.getImageDescriptorRegistry().get(descriptor);

		return image;
	}

	/**
	 * Returns the image associated with reference variables being used to display
	 * references to a root object.
	 *
	 * @param element
	 * @return image associated with reference variables
	 */
	protected Image getReferencesImage(Object element){
		return JavaDebugImages.get(JavaDebugImages.IMG_ELCL_ALL_REFERENCES);
	}

	/**
	 * Returns the image associated with reference variables being used to display
	 * references to a root object.
	 *
	 * @param element
	 * @return image associated with reference variables
	 */
	protected Image getReferenceImage(Object element){
		return JavaDebugImages.get(JavaDebugImages.IMG_OBJS_REFERENCE);
	}

	/**
	 * Returns the image associated with the given element or <code>null</code>
	 * if none is defined.
	 */
	protected Image getDebugElementImage(Object element) {
		ImageDescriptor image= null;
		if (element instanceof IJavaThread) {
			IJavaThread thread = (IJavaThread)element;
			// image also needs to handle suspended quiet
			if (thread.isSuspended() && !thread.isPerformingEvaluation() && !(thread instanceof JDIThread && ((JDIThread)thread).isSuspendVoteInProgress())) {
				image= DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED);
			} else if (thread.isTerminated()) {
				image= DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_TERMINATED);
			} else {
				image= DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING);
			}
		} else {
			image= DebugUITools.getDefaultImageDescriptor(element);
		}
		if (image == null) {
			return null;
		}
		int flags= computeJDIAdornmentFlags(element);
		JDIImageDescriptor descriptor= new JDIImageDescriptor(image, flags);
		return getDebugImageRegistry().get(descriptor);
	}

	/**
	 * Returns the image associated with the given element or <code>null</code>
	 * if none is defined.
	 */
	protected Image getExpressionImage(Object expression) {
		ImageDescriptor image= null;
		boolean bigSize = false;
		if (expression instanceof JavaInspectExpression) {
			image= JavaDebugImages.getImageDescriptor(JavaDebugImages.IMG_OBJ_JAVA_INSPECT_EXPRESSION);
			bigSize = true;
		}
		if (image == null) {
			return null;
		}
		JDIImageDescriptor descriptor= new JDIImageDescriptor(image, 0);
		if (bigSize) {
			descriptor.setSize(BIG_SIZE);
		}
		return getDebugImageRegistry().get(descriptor);
	}

	/**
	 * Returns the adornment flags for the given element.
	 * These flags are used to render appropriate overlay
	 * icons for the element.
	 */
	private int computeJDIAdornmentFlags(Object element) {
		try {
			if (element instanceof IJavaStackFrame) {
				IJavaStackFrame javaStackFrame = ((IJavaStackFrame)element);
				if (javaStackFrame.isOutOfSynch()) {
					return JDIImageDescriptor.IS_OUT_OF_SYNCH;
				}
				if (!javaStackFrame.isObsolete() && javaStackFrame.isSynchronized()) {
					return JDIImageDescriptor.SYNCHRONIZED;
				}
			}
			if (element instanceof IJavaThread) {
				int flag= 0;
				IJavaThread javaThread = ((IJavaThread)element);
				if (ThreadMonitorManager.getDefault().isInDeadlock(javaThread)) {
					flag= JDIImageDescriptor.IN_DEADLOCK;
				}
				if (javaThread.isOutOfSynch()) {
					return flag | JDIImageDescriptor.IS_OUT_OF_SYNCH;
				}
				if (javaThread.mayBeOutOfSynch()) {
					return flag | JDIImageDescriptor.MAY_BE_OUT_OF_SYNCH;
				}
				return flag;
			}
			if (element instanceof IJavaDebugTarget) {
				if (((IJavaDebugTarget)element).isOutOfSynch()) {
					return JDIImageDescriptor.IS_OUT_OF_SYNCH;
				}
				if (((IJavaDebugTarget)element).mayBeOutOfSynch()) {
					return JDIImageDescriptor.MAY_BE_OUT_OF_SYNCH;
				}
			}
		} catch (DebugException e) {
		    // no need to log errors - elements may no longer exist by the time we render them
		}
		return 0;
	}

	/**
	 * Returns the adornment flags for the given breakpoint.
	 * These flags are used to render appropriate overlay
	 * icons for the breakpoint.
	 */
	private int computeBreakpointAdornmentFlags(IJavaBreakpoint breakpoint)  {
		int flags= 0;
		try {
			if (breakpoint.isEnabled()) {
				flags |= JDIImageDescriptor.ENABLED;
			}
			if (breakpoint.isInstalled()) {
				flags |= JDIImageDescriptor.INSTALLED;
			}
			if (breakpoint.isTriggerPoint()) {
				flags |= JDIImageDescriptor.TRIGGER_POINT;
			} else if (DebugPlugin.getDefault().getBreakpointManager().hasActiveTriggerPoints()) {
				flags |= JDIImageDescriptor.TRIGGER_SUPPRESSED;
			}
			if (breakpoint instanceof IJavaLineBreakpoint) {
				if (((IJavaLineBreakpoint)breakpoint).isConditionEnabled()) {
					flags |= JDIImageDescriptor.CONDITIONAL;
				}
				if (breakpoint instanceof IJavaMethodBreakpoint) {
					IJavaMethodBreakpoint mBreakpoint= (IJavaMethodBreakpoint)breakpoint;
					if (mBreakpoint.isEntry()) {
						flags |= JDIImageDescriptor.ENTRY;
					}
					if (mBreakpoint.isExit()) {
						flags |= JDIImageDescriptor.EXIT;
					}
				}
				if (breakpoint instanceof IJavaMethodEntryBreakpoint) {
					flags |= JDIImageDescriptor.ENTRY;
				}
			} else if (breakpoint instanceof IJavaExceptionBreakpoint) {
				IJavaExceptionBreakpoint eBreakpoint= (IJavaExceptionBreakpoint)breakpoint;
				if (eBreakpoint.isCaught()) {
					flags |= JDIImageDescriptor.CAUGHT;
				}
				if (eBreakpoint.isUncaught()) {
					flags |= JDIImageDescriptor.UNCAUGHT;
				}
				if (eBreakpoint.getExclusionFilters().length > 0 || eBreakpoint.getInclusionFilters().length > 0) {
					flags |= JDIImageDescriptor.SCOPED;
				}
			}
		} catch (CoreException e) {
		}
		return flags;
	}

	private ImageDescriptor computeBaseImageDescriptor(IAdaptable element) {
		IJavaVariable javaVariable= element.getAdapter(IJavaVariable.class);
		if (javaVariable != null) {
			try {
				if (javaVariable.isLocal()) {
					return JavaDebugImages.getImageDescriptor(JavaDebugImages.IMG_OBJS_LOCAL_VARIABLE);
				}
				if (javaVariable.isPublic()) {
					return JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_FIELD_PUBLIC);
				}
				if (javaVariable.isProtected()) {
					return JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_FIELD_PROTECTED);
				}
				if (javaVariable.isPrivate()) {
					return JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_FIELD_PRIVATE);
				}
			} catch (DebugException e) {
			    // no need to log errors - elements may no longer exist by the time we render them
			}
		}
		if (javaVariable instanceof JDIReturnValueVariable) {

			JDIReturnValueVariable jdiReturnValueVariable = (JDIReturnValueVariable) javaVariable;
			if (!jdiReturnValueVariable.hasResult) {
				return JavaDebugImages.getImageDescriptor(JavaDebugImages.IMG_OBJS_METHOD_RESULT_DISABLED);
			}
			return JavaDebugImages.getImageDescriptor(JavaDebugImages.IMG_OBJS_METHOD_RESULT);
		}
		return JavaUI.getSharedImages().getImageDescriptor(ISharedImages.IMG_FIELD_DEFAULT);
	}

	private int computeAdornmentFlags(IAdaptable element) {
		int flags= 0;
		IJavaModifiers javaProperties = element.getAdapter(IJavaModifiers.class);
		try {
			if (javaProperties != null) {
				if (javaProperties.isFinal()) {
					flags |= JavaElementImageDescriptor.FINAL;
				}
				if (javaProperties.isStatic()) {
					flags |= JavaElementImageDescriptor.STATIC;
				}
			}
		} catch(DebugException e) {
			// no need to log errors - elements may no longer exist by the time we render them
		}
		return flags;
	}

	private int computeLogicalStructureAdornmentFlags(IAdaptable element) {
		int flags = 0;
		 if (element instanceof IVariable) {
            try {
                IValue value= ((IVariable) element).getValue();
                ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
				if (types.length == 0) {
					return flags; // no logical structure is defined for the value type
		        }
				ILogicalStructureType enabledType = DebugPlugin.getDefaultStructureType(types);
				if (enabledType == null) {
					return flags; // no logical structure is enabled for this type
				}
				IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
				for (IWorkbenchWindow window : windows) {
					IWorkbenchPage page = window.getActivePage();
					IViewPart viewPart = page.findView(IDebugUIConstants.ID_VARIABLE_VIEW);
					if (viewPart instanceof VariablesView) {
						if (((VariablesView) viewPart).isShowLogicalStructure()) {
							// a logical structure is enabled for this type and global toggle to show logical structure is on
							return flags |= JDIImageDescriptor.LOGICAL_STRUCTURE;
						}
						return flags;
					}
				}
            }catch (DebugException e) {
				DebugUIPlugin.log(e.getStatus());
            }
		}
        return flags;
	}

	/**
	 * @see IDebugModelPresentation#getEditorInput(Object)
	 */
	@Override
	public IEditorInput getEditorInput(Object item) {
		if (item instanceof IMarker) {
			item = getBreakpoint((IMarker)item);
		}
		if (item instanceof IJavaBreakpoint) {
			IType type = BreakpointUtils.getType((IJavaBreakpoint)item);
			if (type == null) {
				// if the breakpoint is not associated with a type, use its resource
				item = ((IJavaBreakpoint)item).getMarker().getResource();
			} else {
				item = type;
			}
		}
		if (item instanceof LocalFileStorage) {
			return new LocalFileStorageEditorInput((LocalFileStorage)item);
		}
		if (item instanceof ZipEntryStorage) {
			return new ZipEntryStorageEditorInput((ZipEntryStorage)item);
		}
		// for types that correspond to external files, return null so we do not
		// attempt to open a non-existing workspace file on the breakpoint (bug 184934)
		if (item instanceof IType) {
			IType type = (IType) item;
			if (!type.exists()) {
				return null;
			}
		}
		return EditorUtility.getEditorInput(item);
	}

	/**
	 * @see IDebugModelPresentation#getEditorId(IEditorInput, Object)
	 */
	@Override
	public String getEditorId(IEditorInput input, Object inputObject) {
		try {
			IEditorDescriptor descriptor= IDE.getEditorDescriptor(input.getName());
			return descriptor.getId();
		} catch (PartInitException e) {
			return null;
		}
	}

	/**
	 * @see IDebugModelPresentation#setAttribute(String, Object)
	 */
	@Override
	public void setAttribute(String id, Object value) {
		if (value == null) {
			return;
		}
		synchronized (fAttributes) {
			fAttributes.put(id, value);
		}
	}

	protected boolean isShowQualifiedNames() {
		synchronized (fAttributes) {
			Boolean showQualified= (Boolean) fAttributes.get(DISPLAY_QUALIFIED_NAMES);
			showQualified= showQualified == null ? Boolean.FALSE : showQualified;
			return showQualified.booleanValue();
		}
	}

	protected boolean isShowVariableTypeNames() {
		synchronized (fAttributes) {
			Boolean show= (Boolean) fAttributes.get(DISPLAY_VARIABLE_TYPE_NAMES);
			show= show == null ? Boolean.FALSE : show;
			return show.booleanValue();
		}
	}

	protected boolean isShowHexValues() {
		return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_SHOW_HEX);
	}

	protected boolean isShowCharValues() {
		return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_SHOW_CHAR);
	}

	protected boolean isShowUnsignedValues() {
		return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_SHOW_UNSIGNED);
	}

	protected String getVariableText(IJavaVariable var) {
		String varLabel= DebugUIMessages.JDIModelPresentation_unknown_name__1;
		try {
			varLabel= var.getName();
		} catch (DebugException exception) {
		}

		IJavaValue javaValue= null;
		try {
			javaValue = (IJavaValue) var.getValue();
		} catch (DebugException e1) {
		}
		boolean showTypes= isShowVariableTypeNames();
		StringBuilder buff= new StringBuilder();
		String typeName= DebugUIMessages.JDIModelPresentation_unknown_type__2;
		try {
			typeName= var.getReferenceTypeName();
			if (showTypes) {
				typeName= getQualifiedName(typeName);
			}
		} catch (DebugException exception) {
		}
		if (showTypes) {
			buff.append(typeName);
			buff.append(' ');
		}
		buff.append(varLabel);

		// add declaring type name if required
		if (var instanceof IJavaFieldVariable) {
			IJavaFieldVariable field = (IJavaFieldVariable)var;
			if (isDuplicateName(field)) {
				try {
					String decl = field.getDeclaringType().getName();
					buff.append(NLS.bind(" ({0})", new String[]{getQualifiedName(decl)})); //$NON-NLS-1$
				} catch (DebugException e) {
				}
			}
		}

		String valueString= getFormattedValueText(javaValue);

		//do not put the equal sign for array partitions
		if (valueString.length() != 0) {
			buff.append("= "); //$NON-NLS-1$
			buff.append(valueString);
		}
		return buff.toString();
	}

	/**
	 * Returns text for the given value based on user preferences to display
	 * toString() details.
	 *
	 * @param javaValue
	 * @return text
	 */
	public String getFormattedValueText(IJavaValue javaValue) {
		String valueString= DebugUIMessages.JDIModelPresentation_unknown_value__3;
		if (javaValue != null) {
			if (isShowLabelDetails(javaValue)) {
	    		valueString = getVariableDetail(javaValue);
	    		if (valueString == null) {
	    			valueString = DebugUIMessages.JDIModelPresentation_unknown_value__3;
	    		}
			} else {
				try {
					valueString= getValueText(javaValue);
				} catch (DebugException exception) {
				}
			}
		}
		return valueString;
	}

	/**
	 * Returns whether or not details should be shown in the
	 * label of the given variable.
	 * @param variable the variable
	 * @return whether or not details should be shown in the label
	 *  of the given variable
	 */
	public boolean isShowLabelDetails(IJavaValue value) {
		boolean showDetails= false;
		String details= JDIDebugUIPlugin.getDefault().getPreferenceStore().getString(IJDIPreferencesConstants.PREF_SHOW_DETAILS);
		if (details != null) {
			if (details.equals(IJDIPreferencesConstants.INLINE_ALL)) {
				showDetails= true;
			} else if (details.equals(IJDIPreferencesConstants.INLINE_FORMATTERS)){
				try {
					IJavaType javaType = value.getJavaType();
					JavaDetailFormattersManager manager= JavaDetailFormattersManager.getDefault();
					DetailFormatter formatter = manager.getAssociatedDetailFormatter(javaType);
					showDetails= formatter != null && formatter.isEnabled();
				} catch (DebugException e) {
				}
			}
		}
		return showDetails;
	}

	/**
	 * Returns the detail value for the given variable or <code>null</code>
	 * if none can be computed.
	 * @param variable the variable to compute the detail for
	 * @return the detail value for the variable
	 */
	private String getVariableDetail(IJavaValue value) {
		final String[] detail= new String[1];
		final Object lock= new Object();
		computeDetail(value, new IValueDetailListener() {
		    /* (non-Javadoc)
		     * @see org.eclipse.debug.ui.IValueDetailListener#detailComputed(org.eclipse.debug.core.model.IValue, java.lang.String)
		     */
		    @Override
			public void detailComputed(IValue computedValue, String result) {
		        synchronized (lock) {
		            detail[0]= result;
		            lock.notifyAll();
		        }
		    }
		});
		synchronized (lock) {
		    if (detail[0] == null) {
		        try {
		            lock.wait(5000);
		        } catch (InterruptedException e1) {
		            // Fall through
		        }
		    }
		}
		return detail[0];
	}

	protected String getExpressionText(IExpression expression) throws DebugException {
		boolean showTypes= isShowVariableTypeNames();
		StringBuilder buff= new StringBuilder();
		IJavaValue javaValue= (IJavaValue) expression.getValue();
		if (javaValue != null) {
			String typeName=null;
			try {
				typeName= javaValue.getReferenceTypeName();
			} catch (DebugException exception) {
				// ObjectCollectedException is an expected exception which will
				// occur if the inspected object has been garbage collected.
				if (exception.getStatus().getException() instanceof ObjectCollectedException) {
					return DebugUIMessages.JDIModelPresentation__garbage_collected_object__6;
				}
				throw exception;
			}
			if (showTypes ) {
				typeName= getQualifiedName(typeName);
				if (typeName.length() > 0) {
					buff.append(typeName);
					buff.append(' ');
				}
			}
		}
		// Edit the snippet to make it easily viewable in one line
		StringBuilder snippetBuffer = new StringBuilder();
		String snippet = expression.getExpressionText().trim();
		snippetBuffer.append('"');
		if (snippet.length() > 30){
			snippetBuffer.append(snippet.substring(0, 15));
			snippetBuffer.append(SnippetMessages.getString("SnippetEditor.ellipsis")); //$NON-NLS-1$
			snippetBuffer.append(snippet.substring(snippet.length() - 15));
		} else {
			snippetBuffer.append(snippet);
		}
		snippetBuffer.append('"');
		snippet = snippetBuffer.toString().replaceAll("[\n\r\t]+", " ");  //$NON-NLS-1$//$NON-NLS-2$
		buff.append(snippet);

		if (javaValue != null) {
			String valueString= getValueText(javaValue);
			if (valueString.length() > 0) {
				buff.append("= "); //$NON-NLS-1$
				buff.append(valueString);
			}
		}
		return buff.toString();
	}

	protected String getWatchExpressionText(IWatchExpression expression) throws DebugException {
		return getExpressionText(expression) + (expression.isEnabled() ? "" : DebugUIMessages.JDIModelPresentation_116); //$NON-NLS-1$
	}

	/**
	 * Given the reference type name of an array type, insert the array length
	 * in between the '[]' for the first dimension and return the result.
	 */
	protected String adjustTypeNameForArrayIndex(String typeName, int arrayIndex) {
		int firstBracket= typeName.indexOf("[]"); //$NON-NLS-1$
		if (firstBracket < 0) {
			return typeName;
		}
		StringBuilder buffer= new StringBuilder(typeName);
		buffer.insert(firstBracket + 1, Integer.toString(arrayIndex));
		return buffer.toString();
	}

	protected String getValueUnsignedText(IJavaValue value) throws DebugException {
		String sig= getPrimitiveValueTypeSignature(value);
		if (sig == null) {
			return null;
		}

		switch (sig.charAt(0)) {
			case 'B' : // byte
				int byteVal;
				try {
					byteVal= Integer.parseInt(value.getValueString());
				} catch (NumberFormatException e) {
					return null;
				}
				if (byteVal < 0) {
					byteVal = byteVal & 0xFF;
					return Integer.toString(byteVal);
				}
			default :
				return null;
		}
	}

	protected String getValueHexText(IJavaValue value) throws DebugException {
		String sig= getPrimitiveValueTypeSignature(value);
		if (sig == null) {
			return null;
		}

		StringBuilder buff= new StringBuilder();
		long longValue;
		char sigValue = sig.charAt(0);
		try {
			if (sigValue == 'C') {
				longValue = value.getValueString().charAt(0);
			} else {
				longValue= Long.parseLong(value.getValueString());
			}
		} catch (NumberFormatException e) {
			return null;
		}
		switch (sigValue) {
			case 'B' :
				buff.append("0x"); //$NON-NLS-1$
				// keep only the relevant bits for byte
				longValue &= 0xFF;
				buff.append(Long.toHexString(longValue));
				break;
			case 'I' :
				buff.append("0x"); //$NON-NLS-1$
				// keep only the relevant bits for integer
				longValue &= 0xFFFFFFFFl;
				buff.append(Long.toHexString(longValue));
				break;
			case 'S' :
				buff.append("0x"); //$NON-NLS-1$
				// keep only the relevant bits for short
				longValue = longValue & 0xFFFF;
				buff.append(Long.toHexString(longValue));
				break;
			case 'J' :
				buff.append("0x"); //$NON-NLS-1$
				buff.append(Long.toHexString(longValue));
				break;
			case 'C' :
				buff.append("\\u"); //$NON-NLS-1$
				String hexString= Long.toHexString(longValue);
				int length= hexString.length();
				while (length < 4) {
					buff.append('0');
					length++;
				}
				buff.append(hexString);
				break;
			default:
				return null;
		}
		return buff.toString();
	}

	@SuppressWarnings("deprecation")
	protected String getBreakpointText(IBreakpoint breakpoint) {
	    try {
	    	String label = null;
			if (breakpoint instanceof IJavaExceptionBreakpoint) {
				label = getExceptionBreakpointText((IJavaExceptionBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaWatchpoint) {
				label = getWatchpointText((IJavaWatchpoint)breakpoint);
			} else if (breakpoint instanceof IJavaMethodBreakpoint) {
				label = getMethodBreakpointText((IJavaMethodBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaPatternBreakpoint) {
				label = getJavaPatternBreakpointText((IJavaPatternBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaTargetPatternBreakpoint) {
				label = getJavaTargetPatternBreakpointText((IJavaTargetPatternBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaStratumLineBreakpoint) {
				label = getJavaStratumLineBreakpointText((IJavaStratumLineBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaLineBreakpoint) {
				label = getLineBreakpointText((IJavaLineBreakpoint)breakpoint);
			} else if (breakpoint instanceof IJavaClassPrepareBreakpoint) {
				label = getClassPrepareBreakpointText((IJavaClassPrepareBreakpoint)breakpoint);
			} else {
				// Should never get here
				return ""; //$NON-NLS-1$
			}
			String suffix = breakpoint.getMarker().getAttribute(BREAKPOINT_LABEL_SUFFIX, null);
			if (suffix == null) {
				return label;
			}
			StringBuilder buffer = new StringBuilder(label);
			buffer.append(suffix);
			return buffer.toString();
	    } catch (CoreException e) {
	    	// if the breakpoint has been deleted, don't log exception
	    	IMarker marker = breakpoint.getMarker();
			if (marker == null || !marker.exists()) {
	    		return DebugUIMessages.JDIModelPresentation_6;
	    	}
	        JDIDebugUIPlugin.log(e);
	        return DebugUIMessages.JDIModelPresentation_4;
	    }
	}

	/**
	 * @param breakpoint
	 * @return
	 */
	private String getJavaStratumLineBreakpointText(IJavaStratumLineBreakpoint breakpoint) throws CoreException {
		IMember member= BreakpointUtils.getMember(breakpoint);
		String sourceName = breakpoint.getSourceName();
		if (sourceName == null) {
		    sourceName = ""; //$NON-NLS-1$
		    IMarker marker = breakpoint.getMarker();
		    if (marker != null) {
		        IResource resource = marker.getResource();
		        if (resource.getType() == IResource.FILE) {
		            sourceName = resource.getName();
		        }
		    }
		}
		StringBuilder label= new StringBuilder(sourceName);
		appendLineNumber(breakpoint, label);
		appendHitCount(breakpoint, label);
		appendSuspendPolicy(breakpoint,label);
		appendThreadFilter(breakpoint, label);

		if (member != null) {
			label.append(" - "); //$NON-NLS-1$
			label.append(getJavaLabelProvider().getText(member));
		}

		return label.toString();
	}

	protected String getExceptionBreakpointText(IJavaExceptionBreakpoint breakpoint) throws CoreException {
		StringBuilder buffer = new StringBuilder();
		String typeName = breakpoint.getTypeName();
		if (typeName != null) {
			buffer.append(getQualifiedName(typeName));
		}
		appendHitCount(breakpoint, buffer);
		appendSuspendPolicy(breakpoint, buffer);
		//TODO remove the cast once the API freeze has thawed
		if(((JavaExceptionBreakpoint)breakpoint).isSuspendOnSubclasses()) {
			buffer.append(DebugUIMessages.JDIModelPresentation_117);
		}
		appendThreadFilter(breakpoint, buffer);
		if (breakpoint.getExclusionFilters().length > 0 || breakpoint.getInclusionFilters().length > 0) {
			buffer.append(DebugUIMessages.JDIModelPresentation___scoped__1);
		}
		appendInstanceFilter(breakpoint, buffer);
		String state= null;
		boolean c= breakpoint.isCaught();
		boolean u= breakpoint.isUncaught();
		if (c && u) {
			state= DebugUIMessages.JDIModelPresentation_caught_and_uncaught_60;
		} else if (c) {
			state= DebugUIMessages.JDIModelPresentation_caught_61;
		} else if (u) {
			state= DebugUIMessages.JDIModelPresentation_uncaught_62;
		}
		String label= null;
		if (state == null) {
			label= buffer.toString();
		} else {
			String format= DebugUIMessages.JDIModelPresentation__1____0__63;
			label= NLS.bind(format, new Object[] {state, buffer});
		}
		return label;
	}

	protected String getLineBreakpointText(IJavaLineBreakpoint breakpoint) throws CoreException {
		String typeName= breakpoint.getTypeName();
		IMember member= BreakpointUtils.getMember(breakpoint);
		StringBuilder label= new StringBuilder();
		if (typeName != null) {
			label.append(getQualifiedName(typeName));
		}
		appendLineNumber(breakpoint, label);
		appendHitCount(breakpoint, label);
		appendSuspendPolicy(breakpoint,label);
		appendThreadFilter(breakpoint, label);
		appendConditional(breakpoint, label);
		appendInstanceFilter(breakpoint, label);

		if (member != null) {
			label.append(" - "); //$NON-NLS-1$
			label.append(getJavaLabelProvider().getText(member));
		}

		return label.toString();
	}

	protected String getClassPrepareBreakpointText(IJavaClassPrepareBreakpoint breakpoint) throws CoreException {
		String typeName= breakpoint.getTypeName();
		StringBuilder label = new StringBuilder();
		if (typeName != null) {
			label.append(getQualifiedName(typeName));
		}
		appendHitCount(breakpoint, label);
		appendSuspendPolicy(breakpoint, label);
		return label.toString();
	}

	protected StringBuilder appendLineNumber(IJavaLineBreakpoint breakpoint, StringBuilder label) throws CoreException {
		int lineNumber= breakpoint.getLineNumber();
		if (lineNumber > 0) {
			label.append(" ["); //$NON-NLS-1$
			label.append(DebugUIMessages.JDIModelPresentation_line__65);
			label.append(' ');
			label.append(lineNumber);
			label.append(']');

		}
		return label;
	}

	protected StringBuilder appendHitCount(IJavaBreakpoint breakpoint, StringBuilder label) throws CoreException {
		int hitCount= breakpoint.getHitCount();
		if (hitCount > 0) {
			label.append(" ["); //$NON-NLS-1$
			label.append(DebugUIMessages.JDIModelPresentation_hit_count__67);
			label.append(' ');
			label.append(hitCount);
			label.append(']');
		}
		return label;
	}

	protected String getJavaPatternBreakpointText(@SuppressWarnings("deprecation") IJavaPatternBreakpoint breakpoint) throws CoreException {
		IResource resource= breakpoint.getMarker().getResource();
		IMember member= BreakpointUtils.getMember(breakpoint);
		StringBuilder label= new StringBuilder(resource.getName());
		appendLineNumber(breakpoint, label);
		appendHitCount(breakpoint, label);
		appendSuspendPolicy(breakpoint,label);
		appendThreadFilter(breakpoint, label);

		if (member != null) {
			label.append(" - "); //$NON-NLS-1$
			label.append(getJavaLabelProvider().getText(member));
		}

		return label.toString();
	}

	protected String getJavaTargetPatternBreakpointText(IJavaTargetPatternBreakpoint breakpoint) throws CoreException {
		IMember member= BreakpointUtils.getMember(breakpoint);
		StringBuilder label= new StringBuilder(breakpoint.getSourceName());
		appendLineNumber(breakpoint, label);
		appendHitCount(breakpoint, label);
		appendSuspendPolicy(breakpoint,label);
		appendThreadFilter(breakpoint, label);

		if (member != null) {
			label.append(" - "); //$NON-NLS-1$
			label.append(getJavaLabelProvider().getText(member));
		}

		return label.toString();
	}

	protected String getWatchpointText(IJavaWatchpoint watchpoint) throws CoreException {
		String typeName= watchpoint.getTypeName();
		IMember member= BreakpointUtils.getMember(watchpoint);
		StringBuilder label= new StringBuilder();
		if (typeName != null) {
			label.append(getQualifiedName(typeName));
		}
		appendHitCount(watchpoint, label);
		appendSuspendPolicy(watchpoint,label);
		appendThreadFilter(watchpoint, label);


		boolean access= watchpoint.isAccess();
		boolean modification= watchpoint.isModification();
		if (access && modification) {
			label.append(DebugUIMessages.JDIModelPresentation_access_and_modification_70);
		} else if (access) {
			label.append(DebugUIMessages.JDIModelPresentation_access_71);
		} else if (modification) {
			label.append(DebugUIMessages.JDIModelPresentation_modification_72);
		}

		label.append(" - "); //$NON-NLS-1$
		if (member != null) {
			label.append(getJavaLabelProvider().getText(member));
		} else {
			label.append(watchpoint.getFieldName());
		}

		return label.toString();
	}

	protected String getMethodBreakpointText(IJavaMethodBreakpoint methodBreakpoint) throws CoreException {
		String typeName= methodBreakpoint.getTypeName();
		IMember member= BreakpointUtils.getMember(methodBreakpoint);
		StringBuilder label= new StringBuilder();
		if (typeName != null) {
			label.append(getQualifiedName(typeName));
		}
		appendHitCount(methodBreakpoint, label);
		appendSuspendPolicy(methodBreakpoint,label);
		appendThreadFilter(methodBreakpoint, label);


		boolean entry = methodBreakpoint.isEntry();
		boolean exit = methodBreakpoint.isExit();
		if (entry && exit) {
			label.append(DebugUIMessages.JDIModelPresentation_entry_and_exit);
		} else if (entry) {
			label.append(DebugUIMessages.JDIModelPresentation_entry);
		} else if (exit) {
			label.append(DebugUIMessages.JDIModelPresentation_exit);
		}
		appendConditional(methodBreakpoint, label);

		if (member != null) {
			label.append(" - "); //$NON-NLS-1$
			label.append(getJavaLabelProvider().getText(member));
		} else {
			String methodSig= methodBreakpoint.getMethodSignature();
			String methodName= methodBreakpoint.getMethodName();
			if (methodSig != null) {
				label.append(" - "); //$NON-NLS-1$
				label.append(Signature.toString(methodSig, methodName, null, false, false));
			} else if (methodName != null) {
				label.append(" - "); //$NON-NLS-1$
				label.append(methodName);
			}
		}

		return label.toString();
	}

	protected String getStackFrameText(IStackFrame stackFrame) throws DebugException {
		IJavaStackFrame frame= stackFrame.getAdapter(IJavaStackFrame.class);
		if (frame != null) {
			StringBuilder label= new StringBuilder();

			String dec= DebugUIMessages.JDIModelPresentation_unknown_declaring_type__4;
			try {
				dec= frame.getDeclaringTypeName();
			} catch (DebugException exception) {
			}
			if (frame.isObsolete()) {
				label.append(DebugUIMessages.JDIModelPresentation__obsolete_method_in__1);
				label.append(dec);
				label.append('>');
				return label.toString();
			}

			boolean javaStratum= true;
			try {
				javaStratum = frame.getReferenceType().getDefaultStratum().equals("Java"); //$NON-NLS-1$
			} catch (DebugException e) {
			}

			if (javaStratum) {
				// receiver name
				String rec= DebugUIMessages.JDIModelPresentation_unknown_receiving_type__5;
				try {
					rec= frame.getReceivingTypeName();
				} catch (DebugException exception) {
				}
				label.append(getQualifiedName(rec));

				// append declaring type name if different
				if (!dec.equals(rec)) {
					label.append('(');
					label.append(getQualifiedName(dec));
					label.append(')');
				}
				// append a dot separator and method name
				label.append('.');
				try {
					label.append(frame.getMethodName());
				} catch (DebugException exception) {
					label.append(DebugUIMessages.JDIModelPresentation_unknown_method_name__6);
				}
				try {
					List<String> args= frame.getArgumentTypeNames();
					if (args.isEmpty()) {
						label.append("()"); //$NON-NLS-1$
					} else {
						label.append('(');
						Iterator<String> iter= args.iterator();
						while (iter.hasNext()) {
							label.append(getQualifiedName(iter.next()));
							if (iter.hasNext()) {
								label.append(", "); //$NON-NLS-1$
							} else if (frame.isVarArgs()) {
								label.replace(label.length() - 2, label.length(), "..."); //$NON-NLS-1$
							}
						}
						label.append(')');
					}
				} catch (DebugException exception) {
					label.append(DebugUIMessages.JDIModelPresentation__unknown_arguements___7);
				}
			} else {
				if (isShowQualifiedNames()) {
					label.append(frame.getSourcePath());
				} else {
					label.append(frame.getSourceName());
				}
			}

			try {
				int lineNumber= frame.getLineNumber();
				label.append(' ');
				label.append(DebugUIMessages.JDIModelPresentation_line__76);
				label.append(' ');
				if (lineNumber >= 0) {
					label.append(lineNumber);
				} else {
					label.append(DebugUIMessages.JDIModelPresentation_not_available);
					if (frame.isNative()) {
						label.append(' ');
						label.append(DebugUIMessages.JDIModelPresentation_native_method);
					}
				}
			} catch (DebugException exception) {
				label.append(DebugUIMessages.JDIModelPresentation__unknown_line_number__8);
			}

			if (!frame.wereLocalsAvailable()) {
				label.append(' ');
				label.append(DebugUIMessages.JDIModelPresentation_local_variables_unavailable);
			}

			return label.toString();

		}
		return null;
	}

	protected String getQualifiedName(String qualifiedName) {
		if (!isShowQualifiedNames()) {
			return removeQualifierFromGenericName(qualifiedName);
		}
		return qualifiedName;
	}

	/**
	 * Return the simple generic name from a qualified generic name
	 */
	public String removeQualifierFromGenericName(String qualifiedName) {
		if (qualifiedName.endsWith("...")) { //$NON-NLS-1$
			// handle variable argument name
			return removeQualifierFromGenericName(qualifiedName.substring(0, qualifiedName.length() - 3)) + "..."; //$NON-NLS-1$
		}
		if (qualifiedName.endsWith("[]")) { //$NON-NLS-1$
			// handle array type
			return removeQualifierFromGenericName(qualifiedName.substring(0, qualifiedName.length() - 2)) + "[]"; //$NON-NLS-1$
		}
		// check if the type has parameters
		int parameterStart= qualifiedName.indexOf('<');
		if (parameterStart == -1) {
			return getSimpleName(qualifiedName);
		}
		// get the list of the parameters and generates their simple name
		List<String> parameters= getNameList(qualifiedName.substring(parameterStart + 1, qualifiedName.length() - 1));
		StringBuilder name= new StringBuilder(getSimpleName(qualifiedName.substring(0, parameterStart)));
		name.append('<');
		Iterator<String> iterator= parameters.iterator();
		if (iterator.hasNext()) {
			name.append(removeQualifierFromGenericName(iterator.next()));
			while (iterator.hasNext()) {
				name.append(',').append(removeQualifierFromGenericName(iterator.next()));
			}
		}
		name.append('>');
		return name.toString();
	}

	/**
	 * Return the simple name from a qualified name (non-generic)
	 */
	private String getSimpleName(String qualifiedName) {
		int index = qualifiedName.lastIndexOf('.');
		if (index >= 0) {
			return qualifiedName.substring(index + 1);
		}
		return qualifiedName;
	}

	/**
	 * Decompose a comma separated list of generic names (String) to a list of generic names (List)
	 */
	private List<String> getNameList(String listName) {
		List<String> names= new ArrayList<>();
		StringTokenizer tokenizer= new StringTokenizer(listName, ",<>", true); //$NON-NLS-1$
		int enclosingLevel= 0;
		int startPos= 0;
		int currentPos= 0;
		while (tokenizer.hasMoreTokens()) {
			String token= tokenizer.nextToken();
			switch (token.charAt(0)) {
				case ',':
					if (enclosingLevel == 0) {
						names.add(listName.substring(startPos, currentPos));
						startPos= currentPos + 1;
					}
					break;
				case '<':
					enclosingLevel++;
					break;
				case '>':
					enclosingLevel--;
					break;
			}
			currentPos += token.length();
		}
		names.add(listName.substring(startPos));
		return names;
	}

	/**
	 * Plug in the single argument to the resource String for the key to get a formatted resource String
	 */
	public static String getFormattedString(String key, String arg) {
		return getFormattedString(key, new String[] {arg});
	}

	/**
	 * Plug in the arguments to the resource String for the key to get a formatted resource String
	 */
	public static String getFormattedString(String string, String[] args) {
		return NLS.bind(string, args);
	}

	interface IValueDetailProvider {
		public void computeDetail(IValue value, IJavaThread thread, IValueDetailListener listener) throws DebugException;
	}

	protected void appendSuspendPolicy(IJavaBreakpoint breakpoint, StringBuilder buffer) throws CoreException {
		if (breakpoint.getSuspendPolicy() == IJavaBreakpoint.SUSPEND_VM) {
			buffer.append(' ');
			buffer.append(DebugUIMessages.JDIModelPresentation_Suspend_VM);
		}
	}

	protected void appendThreadFilter(IJavaBreakpoint breakpoint, StringBuilder buffer) throws CoreException {
		if (breakpoint.getThreadFilters().length != 0) {
			buffer.append(' ');
			buffer.append(DebugUIMessages.JDIModelPresentation_thread_filtered);
		}
	}

	protected void appendConditional(IJavaLineBreakpoint breakpoint, StringBuilder buffer) throws CoreException {
		if (breakpoint.isConditionEnabled() && breakpoint.getCondition() != null) {
			buffer.append(' ');
			buffer.append(DebugUIMessages.JDIModelPresentation__conditional__2);
		}
	}

	protected void appendInstanceFilter(IJavaBreakpoint breakpoint, StringBuilder buffer) throws CoreException {
		IJavaObject[] instances = breakpoint.getInstanceFilters();
		for (int i = 0; i < instances.length; i++) {
			String instanceText= instances[i].getValueString();
			if (instanceText != null) {
				buffer.append(' ');
				buffer.append(NLS.bind(DebugUIMessages.JDIModelPresentation_instance_1, new String[] {instanceText}));
			}
		}
	}

	protected static org.eclipse.jdt.internal.debug.ui.ImageDescriptorRegistry getDebugImageRegistry() {
		if (fgDebugImageRegistry == null) {
			fgDebugImageRegistry = JDIDebugUIPlugin.getImageDescriptorRegistry();
		}
		return fgDebugImageRegistry;
	}

	protected JavaElementLabelProvider getJavaLabelProvider() {
		if (fJavaLabelProvider == null) {
			fJavaLabelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
		}
		return fJavaLabelProvider;
	}

	/**
	 * Returns whether the given field variable has the same name as any variables
	 */
	protected boolean isDuplicateName(IJavaFieldVariable variable) {
		IJavaReferenceType javaType= variable.getReceivingType();
		try {
			String[] names = javaType.getAllFieldNames();
			boolean found= false;
			for (int i = 0; i < names.length; i++) {
				if (variable.getName().equals(names[i])) {
					if (found) {
						return true;
					}
					found= true;
				}
			}
			return false;
		} catch (DebugException e) {
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
	 */
	@Override
	public Color getForeground(Object element) {
		if (element instanceof JavaContendedMonitor && ((JavaContendedMonitor)element).getMonitor().isInDeadlock()) {
			return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR);
		}
		if (element instanceof JavaOwnedMonitor && ((JavaOwnedMonitor)element).getMonitor().isInDeadlock()) {
			return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR);
		}
		if (element instanceof JavaWaitingThread && ((JavaWaitingThread)element).getThread().isInDeadlock()) {
			return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR);
		}
		if (element instanceof JavaOwningThread && ((JavaOwningThread)element).getThread().isInDeadlock()) {
			return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR);
		}
		if (element instanceof IJavaThread && ThreadMonitorManager.getDefault().isInDeadlock((IJavaThread)element)) {
			return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get(IJDIPreferencesConstants.PREF_THREAD_MONITOR_IN_DEADLOCK_COLOR);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
	 */
	@Override
	public Color getBackground(Object element) {
		return null;
	}

	private ImageDescriptor getImageDescriptor(String key) {
		return JavaDebugImages.getImageDescriptor(key);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.IDebugModelPresentationExtension#requiresUIThread(java.lang.Object)
	 */
	@Override
	public synchronized boolean requiresUIThread(Object element) {
		return !isInitialized();
	}
}
