Indicatori di risorse

I plug-in possono definire estensioni file specializzate e fornire editor che offrono funzioni di modifica specializzate per questi tipi di file.  Durante il corso della modifica (o della creazione) di una risorsa, un plug-in può avere bisogno di codificare le risorse per comunicare problemi o altre informazioni all'utente. Il meccanismo degli indicatori di risorse viene utilizzato per gestire questo tipo di informazioni.

Un indicatore è come un promemoria adesivo attaccato alla risorsa. Sull'indicatore è possibile registrare informazioni relative ad un problema (ad es., la posizione o la gravità) o ad un'attività da eseguire.  Oppure, è possibile registrare semplicemente una posizione come avviene con un segnalibro. 

Gli utenti possono passare rapidamente alla posizione contrassegnata dall'indicatore all'interno di una risorsa. L'interfaccia utente del workbench supporta la presentazione di segnalibri, punti di interruzione, attività e problemi sull'editor.  Questi indicatori possono anche essere visualizzati come voci in visualizzazioni, ad esempio nelle visualizzazioni delle attività o dei segnalibri.

L'API delle risorse della piattaforma definisce metodi per la creazione di indicatori, per l'impostazione dei relativi valori e per l'estensione della piattaforma con i nuovi tipi di indicatori. Mentre la piattaforma gestisce gli indicatori, sono i plug-in che ne controllano la creazione, la rimozione e i valori di attributo.

Gli indicatori sono previsti come oggetti leggeri e di piccole dimensioni. In un singolo progetto possono essere presenti centinaia o anche migliaia di indicatori.  Ad esempio, il compilatore Java utilizza un indicatore per contrassegnare ogni problema rilevato nel codice sorgente.

La piattaforma eliminerà gli indicatori allegati alle risorse che vengono cancellate, ma i plug-in sono responsabili della rimozione di indicatori non aggiornati e non più applicabili ad una risorsa ancora esistente.

Operazioni di indicatori

L'utilizzo di indicatori è simile all'utilizzo di una risorsa.  Gli indicatori sono oggetti handle.  È possibile ottenere un handle di indicatore da una risorsa, ma non è possibile determinare se esiste effettivamente fino a quando non si utilizza il protocollo exists() o non si prova a utilizzarlo.  Una volta stabilita l'esistenza di un indicatore, è possibile individuare la risorsa a cui appartiene, effettuare la query del relativo id oppure degli attributi denominati che potrebbero essergli stati assegnati.

Gli indicatori sono posseduti e gestiti dalla piattaforma, la quale ne cura la persistenza e notifica ai listener quando un indicatore viene aggiunto, cancellato o modificato.  I plug-in sono responsabili della creazione di qualsiasi indicatore necessario, della modifica degli attributi e della rimozione degli stessi indicatori quando questi non sono più necessari.

Creazione di indicatori

Gli indicatori non vengono creati direttamente mediante un costruttore. Vengono creati utilizzando un metodo factory (IResource.createMarker()) sulla risorsa associata.

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

Per creare un indicatore di ambito globale (non associato ad alcuna risorsa specifica), è possibile utilizzare come risorsa la radice dell'area di lavoro (IWorkspace.getRoot()).

Cancellazione di indicatori

Il codice per la cancellazione di un indicatore è riportato di seguito.

try {
    marker.delete();
} catch (CoreException e) {
    // Qualcosa è andata male
}

Quando un indicatore viene cancellato, il relativo oggetto indicatore (handle) assumerà uno stato "non aggiornato." I plug-in dovranno utilizzare il protocollo IMarker.exists() per assicurarsi che un oggetto indicatore sia ancora valido.

Gli indicatori possono essere cancellati in batch richiedendo ad una risorsa di cancellare i propri indicatori. Questo metodo è utile quando si rimuovono molti indicatori nello stesso momento oppure i riferimenti o gli id di singoli indicatori non sono disponibili.

int depth = IResource.DEPTH_INFINITE;
try {
    resource.deleteMarkers(IMarker.PROBLEM, true, depth);
} catch (CoreException e) {
    // qualcosa è andata male
}

Durante la cancellazione di una gruppo di indicatori, l'utente specifica un tipo di indicatore da cancellare, ad esempio IMarker.PROBLEM, oppure null per cancellare tutti gli indicatori. Il secondo argomento indica se si desidera cancellare gli indicatori di sottotipo.  (I sottotipi verranno illustrati quando si definiscono i nuovi tipi di indicatori.)  L'argomento depth controlla la profondità dell'operazione di cancellazione. 

È anche possibile cancellare gli indicatori utilizzando deleteMarkers(IMarker []).

Attributi degli indicatori

Dato un indicatore, l'utente può individuarne la risorsa associata, l'id (univoco e relativo a tale risorsa) e il tipo. È anche possibile accedere ad ulteriori informazioni attraverso attributi generici.

Ogni tipo di indicatore dispone di una serie specifica di attributi che sono definiti dal creatore del tipo di indicatore utilizzando convenzioni di denominazione.  L'interfaccia IMarker definisce una serie di costanti che contengono i nomi degli attributi standard (ad alcuni dei valori previsti) per i tipi di indicatori della piattaforma. Il metodo seguente agisce sugli attributi utilizzando le costanti della piattaforma.

IMarker marker = file.createMarker(IMarker.TASK);
if (marker.exists())
   try {
        marker.setAttribute(IMarker.MESSAGE, "A sample marker message");
        marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
    } catch (CoreException e) {
        // È necessario gestire il caso in cui la risorsa non esiste
    }

Gli attributi vengono generalmente conservati come coppie nome/valore, in cui i nomi sono costituiti da stringhe e un valore può corrispondere a uno qualsiasi dei tipi di valore supportati (boolean, integer, string). La limitazione sui tipi di valore consente alla piattaforma di conservare in modo rapido e semplice gli indicatori.

Query degli indicatori

È possibile eseguire una query delle risorse per individuare i rispettivi indicatori e gli indicatori dei relativi elementi secondari. Ad esempio, la query con profondità infinita eseguita sulla directory principale dell'area di lavoro considera tutti gli indicatori presenti nell'area di lavoro.

IMarker[] problems = null;
int depth = IResource.DEPTH_INFINITE;
try {
    problems = resource.findMarkers(IMarker.PROBLEM, true, depth);
} catch (CoreException e) {
    // qualcosa è andata male
}

Il risultato restituito da findMarkers dipende dagli argomenti trasmessi.  Nel frammento di codice precedente, si ricercavano tutti gli indicatori di tipo PROBLEM presenti nella risorsa e in tutti i discendenti diretti e indiretti. 

Se si trasmette null come tipo di indicatore, tutti i tipi di indicatore verranno associati alla risorsa. Il secondo argomento specifica se si desidera esaminare gli elementi secondari della risorsa.  L'argomento depth controlla la profondità della ricerca quando si intende esaminare gli elementi secondari della risorsa. La profondità può corrispondere a DEPTH_ZERO (solo la risorsa specificata), DEPTH_ONE (la risorsa e tutti gli elementi secondari diretti) oppure DEPTH_INFINITE (la risorsa e tutti i discendenti diretti e indiretti).

Persistenza degli indicatori

Gli indicatori standard della piattaforma (attività, problema e segnalibro) sono persistenti. Ciò significa che il loro stato verrà salvato agli avvii e alle chiusure del workbench.

I nuovi tipi di indicatori dichiarati dai plug-in non sono persistenti a meno che non siano dichiarati come tali.

Estensione della piattaforma con nuovi tipi di indicatori

I plug-in sono in grado di dichiarare i propri tipi di indicatori utilizzando il punto di estensione org.eclipse.core.resources.markers. I tipi di indicatori standard per problemi, attività e segnalibri, vengono dichiarati dalla piattaforma nel tag del plug-in delle risorse.

<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"/>
</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>

I nuovi tipi di indicatori derivano dagli indicatori esistenti utilizzando varie eredità. I nuovi tipi di indicatori ereditano tutti gli attributi dai rispettivi supertipi e aggiungono qualsiasi nuovo attributo definito come parte della dichiarazione. Inoltre, ereditano attributi anche per transitività dai supertipi dei relativi supertipi. Il codice seguente definisce un nuovo tipo di indicatore in un ipotetico 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>

Notare che il tipo org.eclipse.core.resources.problemmarker è in realtà uno dei tipi predefiniti (IMarker.PROBLEM). 

L'unico aspetto di un supertipo di indicatore che non viene ereditato è il flag di persistenza.  Il valore predefinito per la persistenza è false, quindi tutti i tipi di indicatori che devono essere persistenti devono specificare <persistent value="true"/>.

Dopo aver dichiarato il nuovo tipo di indicatore nel file manifest del plug-in, è possibile creare istanze del tipo di indicatore com.example.markers.myproblem e impostare o richiamare liberamente l'attributo myAttribute.

La dichiarazione di nuovi attributi consente all'utente di associare i dati agli indicatori che si decide di utilizzare (nelle visualizzazioni e negli editor). Gli indicatori di un particolare tipo non devono disporre di valori per tutti gli attributi dichiarati. Le dichiarazioni degli attributi sono maggiori per la risoluzione di problemi relativi alla convenzione di denominazione (quindi tutti utilizzano "messaggio" per riferirsi alla descrizione di un indicatore) che per la limitazione del contenuto.

public IMarker createMyMarker(IResource resource) {
   try {
        IMarker marker = resource.createMarker("com.example.markers.myproblem");
        marker.setAttribute("myAttribute", "MYVALUE");
        return marker;
    } catch (CoreException e) {
        // È necessario gestire i casi in cui il valore dell'attributo viene rifiutato
    }
}

È possibile eseguire una query dei propri tipi di indicatori nello stesso modo in cui si esegue una query dei tipi di indicatori della piattaforma.  Il metodo riportato di seguito effettua la ricerca di tutti gli indicatori mymarkers associati alla specifica risorsa di destinazione e di tutti i discendenti. Notare che verranno rilevati anche tutti i myproblems dato che, per l'argomento di includeSubtypes, viene definito un valore true.

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