/******************************************************************************* * Copyright (c) 2007, 2009 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.ui.internal.views.markers; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.internal.ide.Policy; import org.eclipse.ui.views.markers.MarkerViewUtil; import org.eclipse.ui.views.markers.internal.MarkerMessages; import org.eclipse.ui.views.markers.internal.MarkerTypesModel; import com.ibm.icu.text.CollationKey; import com.ibm.icu.text.Collator; /** * The MarkerEntry is the class that wrappers an {@link IMarker} for display in * an {@link ExtendedMarkersView}. * * @since 3.4 * */ class MarkerEntry extends MarkerSupportItem implements IAdaptable { static { Platform.getAdapterManager().registerAdapters(new IAdapterFactory() { /* * (non-Javadoc) * * @see * org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang * .Object, java.lang.Class) */ public Object getAdapter(Object adaptableObject, Class adapterType) { if (adapterType == IMarker.class && adaptableObject instanceof MarkerEntry) return ((MarkerEntry) adaptableObject).getMarker(); return null; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() */ public Class[] getAdapterList() { return new Class[] { IMarker.class }; } }, MarkerEntry.class); } // The key for the string we built for display private static final Object LOCATION_STRING = "LOCATION_STRING"; //$NON-NLS-1$ private MarkerCategory category; private Map cache = null; /** * Set the MarkerEntry to be stale, if discovered at any point of time * of its use.This will greatly speed up a lot of parts of the view. * @since 3.6 */ private boolean stale; /** * Important: * access to these fields must be via methods, they must be in sync and their * values should reflect correctly the state of the other */ private IMarker marker; /** * Create a new instance of the receiver. * * @param marker */ public MarkerEntry(IMarker marker) { this.marker = marker; stale = false; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { if (adapter.equals(IMarker.class)) return marker; return null; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.provisional.views.markers.MarkerItem#getAttributeValue(java.lang.String, * boolean) */ public boolean getAttributeValue(String attribute, boolean defaultValue) { Object value = getAttributeValue(attribute); if (value == null) return defaultValue; return ((Boolean) value).booleanValue(); } /* * (non-Javadoc) * * @see org.eclipse.ui.views.markers.MarkerItem#getAttributeValue(java.lang.String, * int) */ public int getAttributeValue(String attribute, int defaultValue) { Object value = getAttributeValue(attribute); if (value == null) return defaultValue; return ((Integer) value).intValue(); } /** * Return the Object that is the marker value for attribute. Return null if * it is not found. * * @param attribute * @return Object or <code>null</code> */ Object getAttributeValue(String attribute) { Object value = getCache().get(attribute); if(value == null) { if(stale){ return value; } try { value = marker.getAttribute(attribute); } catch (CoreException e) { checkIfMarkerStale() ; value = null; } if(value != null) { getCache().put(attribute, value); } } if (value instanceof CollationKey) return ((CollationKey) value).getSourceString(); return value; } /* (non-Javadoc) * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getAttributeValue(java.lang.String, java.lang.String) */ public String getAttributeValue(String attribute, String defaultValue) { Object value = getAttributeValue(attribute); if (value == null) return defaultValue; // The following toString() is a no-op for string attribute // values (which we expect!), but safeguards against clients // who used non-String objects (e.g. Integer) as attribute values, // see bug 218249. return value.toString(); } /** * Get the category of the receiver. * * @return {@link MarkerCategory} */ MarkerCategory getCategory() { return category; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getChildren() */ MarkerSupportItem[] getChildren() { return MarkerSupportInternalUtilities.EMPTY_MARKER_ITEM_ARRAY; } /** * Get the CollationKey for the string attribute. * * @param attribute * @param defaultValue * the defaultValue if the value is not set * @return CollationKey */ CollationKey getCollationKey(String attribute, String defaultValue) { String attributeValue; Object value = getCache().get(attribute); if (value != null) { // Only return a collation key otherwise //use the value to generate it if (value instanceof CollationKey) return (CollationKey) value; attributeValue = value.toString(); } else { attributeValue = getAttributeValue(attribute, defaultValue); } if (attributeValue.length() == 0) return MarkerSupportInternalUtilities.EMPTY_COLLATION_KEY; CollationKey key = Collator.getInstance().getCollationKey( attributeValue); getCache().put(attribute, key); return key; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getCreationTime() */ long getCreationTime() { if(stale){ return -1; } try { return marker.getCreationTime(); } catch (CoreException e) { checkIfMarkerStale(); Policy.handle(e); return -1; } } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getDescription() */ String getDescription() { return getAttributeValue(IMarker.MESSAGE, MarkerSupportInternalUtilities.UNKNOWN_ATRRIBTE_VALUE_STRING); } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getID() */ long getID() { return marker.getId(); } /* * (non-Javadoc) * * @see org.eclipse.ui.views.markers.MarkerItem#getLocation() */ public String getLocation() { if(stale||checkIfMarkerStale()){ return MarkerSupportInternalUtilities.UNKNOWN_ATRRIBTE_VALUE_STRING; } if (getCache().containsKey(LOCATION_STRING)) { Object value = getCache().get(LOCATION_STRING); if (value instanceof CollationKey) return ((CollationKey) value).getSourceString(); return (String) value; } // Is the location override set? String locationString = getAttributeValue(IMarker.LOCATION, MarkerSupportInternalUtilities.EMPTY_STRING); if (locationString.length() > 0) { getCache().put(LOCATION_STRING, locationString); return locationString; } // No override so use line number int lineNumber = getAttributeValue(IMarker.LINE_NUMBER, -1); String lineNumberString; if (lineNumber < 0) lineNumberString = MarkerMessages.Unknown; else lineNumberString = NLS.bind(MarkerMessages.label_lineNumber, Integer.toString(lineNumber)); getCache().put(LOCATION_STRING, lineNumberString); return lineNumberString; } /* * (non-Javadoc) * * @see org.eclipse.ui.views.markers.MarkerItem#getMarker() */ public IMarker getMarker() { return marker; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getMarkerTypeName() */ String getMarkerTypeName() { if(stale){ return NLS.bind(MarkerMessages.FieldMessage_WrongType, marker .toString()); } try { return MarkerTypesModel.getInstance().getType(marker.getType()) .getLabel(); } catch (CoreException e) { checkIfMarkerStale() ; Policy.handle(e); return NLS.bind(MarkerMessages.FieldMessage_WrongType, marker .toString()); } } String getMarkerTypeId() { if(stale){ return NLS.bind(MarkerMessages.FieldMessage_WrongType, marker .toString()); } try { return marker.getType(); } catch (CoreException e) { checkIfMarkerStale(); Policy.handle(e); return NLS.bind(MarkerMessages.FieldMessage_WrongType, marker .toString()); } } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#getParent() */ MarkerSupportItem getParent() { return category; } /* * (non-Javadoc) * * @see org.eclipse.ui.views.markers.MarkerItem#getPath() */ public String getPath() { String folder = getAttributeValue(MarkerViewUtil.PATH_ATTRIBUTE, null); if (folder != null) { return folder; } if (stale||checkIfMarkerStale()) { return MarkerSupportInternalUtilities.UNKNOWN_ATRRIBTE_VALUE_STRING; } IPath path = marker.getResource().getFullPath(); int n = path.segmentCount() - 1; // n is the number of segments // in container, not path if (n <= 0) { return super.getPath(); } folder = path.removeLastSegments(1).removeTrailingSeparator() .toString(); getCache().put(MarkerViewUtil.PATH_ATTRIBUTE, folder); return folder; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.views.markers.MarkerSupportItem#isConcrete() */ boolean isConcrete() { return true; } /** * Set the category to markerCategory. * * @param markerCategory */ void setCategory(MarkerCategory markerCategory) { category = markerCategory; } /** * Set the marker for the receiver. * * @param marker * The marker to set. */ void setMarker(IMarker marker) { this.marker = marker; // reset stale stale = false; clearCache(); } /** * Get the cache for the receiver. Create if neccessary. * * @return {@link HashMap} */ Map getCache() { if (cache == null) cache = new HashMap(2); return cache; } /** * Clear the cached values for performance reasons. */ void clearCache() { cache = null; } /** * @return true if the marker does not exist * else false */ boolean checkIfMarkerStale() { if (stale) { return true; } if (marker == null || !marker.exists()) { stale = true; } return stale; } /** * * @return true if the {@link MarkerEntry} is stale,i.e. the marker does not * exist. A false value can mean that marker's state of existence was * never captured or that it exists.#checkIfMarkerExists() will * accurately indicate its state. */ boolean getStaleState() { return stale; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((marker == null) ? 0 : marker.hashCode()); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof MarkerEntry)) { return false; } MarkerEntry other = (MarkerEntry) obj; if (marker == null) { if (other.marker != null) { return false; } } else if (!marker.equals(other.marker)) { return false; } return true; } }