L'annotazione @Convert
L'annotazione @Convert
serve ad individuare quali classi saranno soggette alla conversione in ContentValue
. La definizione dell'annotazione è la seguente:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Convert {
}
Come descritto in precedenza, la definizione di @Convert
è collocata nel progetto "Annotation". Ad esempio, la classe Persona
sarà decorata in questo modo:
@Convert
public class Persona {
public String nome;
public String cognome;
public int eta;
public int peso;
}
Una particolarità importante da tenere a mente è che le annotazioni non vengono ereditate. Annotare la classe Persona
non significa quindi annotare automaticamente anche tutte le classi che ne derivano.
Il processore di annotazioni
Un processore di annotazioni è una classe Java che consente di elaborare i file sorgenti passati al compilatore. Gli AP vengono agganciati alla fase di compilazione. Tra le loro particolarità bisogna sicuramente citare il fatto che vengono eseguiti in virtual machine separate. Normalmente un AP deriva dalla classe AbstractProcessor
. Di seguito è riportata la struttura base di un AP.
package it.html.jap;
public class ConvertProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment env){ ... }
@Override
public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { ... }
@Override
public Set<String> getSupportedAnnotationTypes() { ... }
@Override
public SourceVersion getSupportedSourceVersion() { ... }
}
Analizziamo brevemente lo scopo dei vari metodi:
Metodo | Descrizione |
---|---|
init(ProcessingEnvironment env) |
Viene invocato dall'annotation processing, prima dell'analisi delle classi da compilare, con un parametro di tipo ProcessingEnviroment che fornisce delle classi di utilià che si vedranno in seguito. |
process(Set<? extends TypeElement> annotations, RoundEnvironment env) |
Questo metodo contiene il codice per effettuare lo scan, elaborare le annotazioni e generare i file. Il parametro RoundEnviroment viene utilizzato per recuperare le classi con le annotazioni gestite dal processore. |
getSupportedAnnotationTypes() |
Restituisce l'insieme di annotazioni gestite dal processore. |
getSupportedSourceVersion() |
Specifica quale versione di Java è supportata. Per indicare che si vuole supportare fino all'ultima versione di Java disponibile deve restituire la costante SourceVersion.latestSupported() . |
Metodo init
È il metodo usato per inizializzare il processore di annotazioni. Normalmente dal parametro ProcessingEnvironment
, passato al metodo init
, si recuperano i riferimenti a:
- elements: una classe di utilità per lavorare con gli
Element
. - types: classe di utilità per lavorare con i
TypeMirror
. - filer: necessario a generare i file in output.
I processori di annotazione analizzano i sorgenti Java. Ogni componente della definizione di una classe viene identificato da un element
. Esistono vari tipi di element
che si differenziano in base a quello che rappresentano: il package, la classe, gli attributi o i metodi. Nel codice sottostante, per ogni parte della definizione della classe, all'interno dei commenti, viene riportato l'element
associato.
package it.html.jap; // PackageElement
public class Persona { // TypeElement
private int eta; // VariableElement
private String nome; // VariableElement
public Persona () {} // ExecuteableElement
public void setNome ( // ExecuteableElement
String value // TypeElement
) { ... }
public void setEta ( // ExecuteableElement
int value // TypeElement
) { ... }
}
Bisogna sempre tener presente che i file Java contengono codice strutturato. La rappresentazione con la quale lavorano i processori è una struttura ad albero di elementi. Per esempio, se si ha un TypeElement
che rappresenta public class Prova
, si può navigare attraverso i suoi figli mediante un codice molto simile al seguente:
TypeElement provaClass = ... ;
for (Element item : provaClass.getEnclosedElements()){ // itera sugli elementi figli
...
}
TypeElement
rappresenta gli elementi che si trovano nei file .java
come ad esempio le classi. TypeElement
, però non contiene le informazioni relative alla classe stessa. Dal TypeElement
si possono ottenere informazioni riguardanti la dichiarazione della classe, come ad esempio il suo nome, ma non informazioni inerenti la sua gerarchia (ad esempio la classe padre). Questo tipo di informazioni è accessibile mediante un oggetto di tipo TypeMirror
che si può ottenere da un element
mediante il metodo element.asType()
.