Ressourcenmarkierungen

Sie wissen bereits, dass Plug-ins spezielle Dateierweiterungen definieren und Editoren ergänzen können, die spezielle Bearbeitungsfunktionen für diese Dateitypen zur Verfügung stellen. Während der Bearbeitung (oder Erstellung) einer Ressource muss ein Plug-in möglicherweise Ressourcen kennzeichnen, um dem Benutzer Fehler oder andere Informationen mitzuteilen. Diese Informationen werden durch den Mechanismus einer Ressourcenmarkierung verwaltet.

Eine Markierung funktioniert wie ein gelber Post-it-Sticker, der an einer Ressource angebracht wird. Auf der Markierung können Sie Informationen zu einem Fehler (z. B. Position und Wertigkeit) oder eine auszuführende Task angeben. Sie können auch einfach eine Position für eine Markierung als Lesezeichen angeben.

Innerhalb einer Ressource können Benutzer ganz schnell auf die so gekennzeichnete Position springen. Die Benutzerschnittstelle der Workbench unterstützt die Darstellung von Lesezeichen, Unterbrechungspunkten, Tasks und Fehlern neben dem Editor. Diese Markierungen können auch als Elemente in Sichten (z. B. der Sicht "Tasks" oder der Sicht "Lesezeichen") angezeigt werden.

Die API für Plattformressourcen definiert Methoden, mit denen Markierungen erstellt sowie Markierungswerte festgelegt werden können und die Plattform durch neue Markierungstypen ergänzt werden kann. Die Verwaltung der Markierungen erfolgt durch die Plattform, aber das Erstellen, Entfernen und die Attributwerte werden durch das Plug-in gesteuert.

Markierungen sind als kleine Objekte konzipiert, die quasi keinen Systemaufwand verursachen. Ein einziges Projekt könnte Hunderte und sogar Tausende Markierungen enthalten. Der Java-Compiler verwendet beispielsweise eine Markierung für jeden Fehler, den er im Quellcode findet.

Die Plattform entfernt zwar Markierungen, die gelöschten Ressourcen zugeordnet waren, aber das Entfernen von nicht mehr aktuellen Markierungen, die für eine weiterhin vorhandene Ressource keine Gültigkeit mehr haben, ist Aufgabe des Plug-ins.

Operationen für Markierungen

Die Bearbeitung einer Markierung ist ähnlich wie die Bearbeitung einer Ressource. Markierungen sind Kennungsobjekte. Sie können zwar eine Markierungskennung aus einer Ressource abrufen, ob die Markierung jedoch tatsächlich vorhanden ist, können Sie nur ermitteln, wenn Sie das Protokoll exists() verwenden oder versuchen, die Markierung auf andere Weise zu verarbeiten. Sobald Sie festgestellt haben, dass eine Markierung vorhanden ist, können Sie benannte Attribute abfragen, die ihr möglicherweise zugeordnet wurden.

Eigner von Markierungen ist die Plattform, die auch ihre Verwaltung übernimmt. Die Plattform achtet darauf, dass Markierungen persistent gemacht werden, und informierte Listener-Funktionen, wenn Markierungen hinzugefügt, gelöscht oder geändert werden. Für die Erstellung aller erforderlichen Markierungen, die Änderung ihrer Attribute und das Entfernen von nicht mehr benötigten Markierungen sind Plug-ins zuständig.

Markierung erstellen

Markierungen werden nicht direkt über einen Konstruktor erstellt. Sie werden unter Verwendung einer Methode für ein Factory-Dienstprogramm (IResource.createMarker()) erstellt, das für die zugeordnete Ressource ausgeführt wird.

   IMarker marker = file.createMarker(IMarker.TASK);

Um eine Markierung zu erstellen, die global gültig - also keiner bestimmten Ressource zugeordnet - ist, können Sie das Stammverzeichnis des Arbeitsbereichs (IWorkspace.getRoot()) als Ressource angeben.

Markierung löschen

Der Code für das Löschen einer Markierung ist im Folgenden dargestellt:

   try {
      marker.delete();
      } catch (CoreException e) {
      // Ein Fehler ist aufgetreten
   }

Wenn eine Markierung gelöscht wird, gilt ihr Markierungsobjekt (Kennung) als nicht mehr aktuell. Plug-ins sollten das Protokoll IMarker.exists() verwenden, um sicherzustellen, dass ein Markierungsobjekt noch gültig ist.

Markierungen können im Stapelbetrieb gelöscht werden, indem eine Ressource zum Löschen ihrer Markierungen angewiesen wird. Diese Methode ist hilfreich, wenn viele Markierungen auf einmal entfernt werden sollen oder wenn einzelne Markierungsverweise oder -IDs nicht verfügbar sind.

   int depth = IResource.DEPTH_INFINITE;
   try {
      resource.deleteMarkers(IMarker.PROBLEM, true, depth);
      } catch (CoreException e) {
      // Ein Fehler ist aufgetreten
   }

Beim Löschen einer Gruppe von Markierungen geben Sie einen zu löschenden Markierungstyp an (z. B. IMarker.PROBLEM). Alternativ können Sie durch Angabe von null alle Markierungen löschen. Das zweite Argument gibt an, ob auch Markierungen eines Subtyps gelöscht werden sollen. (Die Subtypen werden im Abschnitt über die Definition neuer Markierungstypen näher erläutert.)  Das Argument depth steuert die Tiefe der Löschoperation.

Zum Löschen von Markierungen können Sie auch IWorkspace.deleteMarkers(IMarker []) verwenden.

Attribute für Markierungen

Für eine bestimmte Markierung können Sie die zugeordnete Ressource, ihre ID (die in Bezug auf diese Ressource eindeutig ist) und ihren Typ abfragen. Außerdem können Sie über generische Attribute auf weitere Informationen zugreifen.

Jeder Markierungstyp verfügt über eine spezifische Gruppe von Attributen, die durch den Ersteller des Markierungstyps mit Hilfe von Namenskonventionen angegeben werden. Die Schnittstelle IMarker definiert eine Gruppe von Konstanten, die die Standardattributnamen (und einige der erwarteten Werte) für die Markierungstypen der Plattform enthält. Die folgende Methode bearbeitet Attribute unter Verwendung der Plattformkonstanten.

   IMarker marker = file.createMarker(IMarker.TASK);
   if (marker.exists()) {
   try {
         marker.setAttribute(IMarker.MESSAGE, "Beispiel für Markierungsnachricht");
         marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
      } catch (CoreException e) {
         // Dieser Fall muss verarbeitet werden, wenn die Markierung nicht mehr vorhanden ist
   }

Attribute werden generisch als Name-/Wertpaare verwaltet, in denen die Namen durch Zeichenfolgen angegeben sind und der Wert einer der unterstützten Werttypen (Boolescher Wert, Integer, Zeichenfolge) sein kann. Durch die Beschränkung auf diese Werttypen kann die Plattform die Markierungen auf schnelle und einfache Weise zu permanenten Markierungen machen.

Markierungen abfragen

Ressourcen können nach ihren Markierungen sowie den Markierungen ihrer untergeordneten Ressourcen abgefragt werden. Wenn Sie beispielsweise das Stammverzeichnis des Arbeitsbereichs mit einer uneingeschränkten Tiefe (Attribut "depth") abfragen, werden alle Markierungen im Arbeitsbereich berücksichtigt.

   IMarker[] problems = null;
   int depth = IResource.DEPTH_INFINITE;
   try {
      problems = resource.findMarkers(IMarker.PROBLEM, true, depth);
      } catch (CoreException e) {
      // Ein Fehler ist aufgetreten
   }

Das durch findMarkers zurückgegebene Ergebnis ist von den übergebenen Argumenten abhängig. Im oben dargestellten Snippet sollten alle Markierungen des Typs PROBLEM gesucht werden, die in der Ressource sowie allen ihren direkten und indirekten untergeordneten Ressourcen vorkommen.

Wenn Sie den Wert null als Markierungstyp übergeben, erhalten Sie alle Markierungstypen, die der Ressource zugeordnet sind. Das zweite Argument gibt an, ob auch die untergeordneten Ressourcen der Ressource berücksichtigt werden sollen. Mit dem Argument depth wird die Tiefe der Suche gesteuert, wenn auch die untergeordneten Ressourcen der Ressource durchsucht werden sollen. Für die Tiefe können Sie die Werte DEPTH_ZERO (nur die angegebene Ressource), DEPTH_ONE (die angegebene Ressource und alle ihre direkten untergeordneten Ressourcen) oder DEPTH_INFINITE (die Ressource sowie alle ihre direkten und indirekten Nachfahren) angeben.

Markierungspermanenz

Die Standardmarkierungen der Plattform (Task, Problem und Lesezeichen) sind permanente Markierungen. Dies bedeutet, dass ihr jeweiliger Status auch über die Beendigung und den Neustart der Workbench hinweg gespeichert bleibt. Markierungen mit einem permanenten Typ können jedoch selektiv als transient definiert werden, indem das reservierte Attribut transient auf "true" gesetzt wird.

Neue Markierungstypen, die durch Plug-ins deklariert werden, sind nur dann permanent, wenn sie explizit als permanente Markierungen deklariert werden.

Plattform durch neue Markierungstypen erweitern

Plug-ins können durch Verwendung des Erweiterungspunkts org.eclipse.core.resources.markers eigene Markierungstypen deklarieren. Die Standardmarkierungstypen für Probleme, Tasks und Lesezeichen werden durch die Plattform in der Formatierungsdatei des Plug-ins deklariert.

   <extension
      id="problemmarker" 
      point="org.eclipse.core.resources.markers" 
      name="%problemName">
      <super type="org.eclipse.core.resources.marker"/>
      <persistent value="true"/>
      <attribute name="severity"/>
      <attribute name="message"/>
      <attribute name="location"/>
      </extension>
   <extension
      id="taskmarker" 
      point="org.eclipse.core.resources.markers" 
      name="%taskName">
      <super type="org.eclipse.core.resources.marker"/>
      <persistent value="true"/>
      <attribute name="priority"/>
      <attribute name="message"/>
      <attribute name="done"/>
      <attribute name="userEditable"/>      
      </extension>
   <extension
      id="bookmark" 
      point="org.eclipse.core.resources.markers" 
      name="%bookmarkName">
      <super type="org.eclipse.core.resources.marker"/>
      <persistent value="true"/>
      <attribute name="message"/>
      <attribute name="location"/>
      </extension>

Neue Markierungstypen werden durch eine Mehrfachübernahme aus vorhandenen Markierungstypen abgeleitet. Neue Markierungstypen übernehmen alle Attribute aus ihren Supertypen und fügen neue Attribute hinzu, die im Rahmen der Deklaration definiert werden. Außerdem übernehmen sie transitiv die Attribute aus den Supertypen ihrer Supertypen. Die folgende Formatierung definiert einen neuen Markierungstyp im hypothetischen Plug-in com.example.markers:

   <extension
      id="mymarker"
      point="org.eclipse.core.resources.markers" />
   <extension
      id="myproblem"
      point="org.eclipse.core.resources.markers">
      <super type="org.eclipse.core.resources.problemmarker"/>
      <super type="com.example.markers.mymarker"/>
      <attribute name="myAttribute" />
      <persistent value="true" />
      </extension>

Bitte beachten Sie, dass der Typ org.eclipse.core.resources.problemmarker eigentlich einer der vordefinierten Typen (IMarker.PROBLEM) ist. 

Der einzige Aspekt eines Supertyps für eine Markierung, der nicht übernommen wird, ist seine Permanenzeigenschaft. Der Standardwert für die Permanenz (persistence) lautet "false". Daher müssen alle Markierungstypen, die permanent sein sollen, explizit <persistent value="true"/> angeben.

Nachdem der neue Markierungstyp in der Manifestdatei des Plug-ins deklariert wurde, können Sie Exemplare des Markierungstyps com.example.markers.myproblem erstellen und das Attribut myAttribute ganz nach Ihren Vorstellungen festlegen oder abrufen.

Durch die Deklaration neuer Attribute können Sie Daten, die Sie an anderen Stellen (in Sichten und Editoren) verwenden wollen, bestimmte Markierungen zuordnen. Die Markierungen eines bestimmten Typs müssen nicht für alle deklarierten Attribute Werte enthalten. Die Attributdeklarationen dienen eher dem Lösen von Problemen, die sich hinsichtlich der Namenskonvention ergeben könnten (jeder Benutzer sollte beispielsweise die Beschreibung einer Markierung unter "message" angeben), als einer Vorgabe des Inhalts.

   public IMarker createMyMarker(IResource resource) {
   try {
         IMarker marker = resource.createMarker("com.example.markers.myproblem");
         marker.setAttribute("myAttribute", "MYVALUE");
         return marker;
      } catch (CoreException e) {
         // Die Fälle, in denen der Attributwert zurückgewiesen wird, müssen verarbeitet werden
      }
   }

Ihre eigenen Markierungstypen können Sie auf dieselbe Weise wie die Markierungstypen der Plattform abfragen. Die unten angegebene Methode findet alle Markierungen des Typs mymarkers, die der angegebenen Zielressource sowie allen ihren Nachfahren zugeordnet sind. Außerdem findet diese Methode alle Markierungen des Typs myproblems, da das Argument includeSubtypes mit der Einstellung "true" übergeben wird.

   public IMarker[] findMyMarkers(IResource target) {
      String type = "com.example.markers.mymarker";
      IMarker[] markers = target.findMarkers(type, true, IResource.DEPTH_INFINITE);
   }

Copyright IBM Corporation und Andere 2000, 2003.