Created
March 17, 2015 21:35
-
-
Save fbiville/b9bfd232beaa719e8ebb to your computer and use it in GitHub Desktop.
Level 2 / exo 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fr.devoxx.niveau2.exo2.etape3; | |
import java.util.List; | |
import java.util.stream.Collectors; | |
import javax.annotation.Nonnull; | |
import javax.lang.model.element.Element; | |
import javax.lang.model.element.ExecutableElement; | |
import javax.lang.model.element.TypeElement; | |
import javax.lang.model.util.ElementFilter; | |
import javax.lang.model.util.Elements; | |
import javax.lang.model.util.Types; | |
/** | |
* DeepExplorer - | |
* | |
* @author Sébastien Lesaint | |
*/ | |
public class DeepExplorer { | |
@Nonnull | |
private final Elements elementUtils; | |
@Nonnull | |
private final Types typeUtils; | |
public DeepExplorer(@Nonnull Elements elementUtils, @Nonnull Types typeUtils) { | |
this.elementUtils = elementUtils; | |
this.typeUtils = typeUtils; | |
} | |
/** | |
* Extrait la liste des méthodes définies par la classe {@link fr.devoxx.niveau2.exo2.etape3.Employee} ainsi que | |
* celles héritées de {@link fr.devoxx.niveau2.exo2.etape3.Citizen} et {@link java.lang.Object}. | |
* <p> | |
* (astuce: un {@link javax.lang.model.element.ElementVisitor} bien écrit peut résoudre le problème mais il est plus | |
* simple de jeter un oeil {@link javax.lang.model.util.Elements}) | |
* </p> | |
* | |
* @param employeeTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape3.Employee} | |
* | |
* @return la liste des méthodes de {@link fr.devoxx.niveau2.exo2.etape3.Employee} plus celles héritées de | |
* {@link fr.devoxx.niveau2.exo2.etape3.Citizen} et {@link java.lang.Object} sous forme de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractAllMethods(@Nonnull TypeElement employeeTypeElement) { | |
List<? extends Element> allMembers = elementUtils.getAllMembers(employeeTypeElement); | |
return ElementFilter.methodsIn(allMembers); | |
} | |
/** | |
* Extrait la liste des méthodes héritées par la classe {@link fr.devoxx.niveau2.exo2.etape3.Employee}. | |
* <p> | |
* (indice: le {@link javax.lang.model.element.Element} retourné par la méthode | |
* {@link javax.lang.model.element.ExecutableElement#getEnclosingElement()} d'une méthode est la classe qui la | |
* définie) | |
* </p> | |
* <p> | |
* (remarque: comme indiqué dans la Javadoc de {@link javax.lang.model.element.Element}, deux instances doivent | |
* être comparée par leur méthode {@link java.lang.Object#equals(Object)}). | |
* </p> | |
* | |
* @param employeeTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape3.Employee} | |
* | |
* @return la méthode {@link fr.devoxx.niveau2.exo2.etape3.Citizen#sayGoodbye()} et les méthodes | |
* {@link java.lang.Object} sous forme de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractInheritedMethods(@Nonnull TypeElement employeeTypeElement) { | |
return extractAllMethods(employeeTypeElement).stream() | |
.filter(method -> !method.getEnclosingElement().equals(employeeTypeElement)) | |
.collect(Collectors.toList()); | |
} | |
/** | |
* Extrait la liste des méthodes héritées par la classe {@link fr.devoxx.niveau2.exo2.etape3.Employee} à l'exception | |
* de celles héritées de {@link java.lang.Object}. | |
* <p> | |
* (astuce: une instance de {@link javax.lang.model.element.Element} représentant n'importe qu'elle classe/interface | |
* disponible dans le class loader du Processor peut être récupérée grâce à la méthode | |
* {@link javax.lang.model.util.Elements#getTypeElement(CharSequence)}) | |
* </p> | |
* | |
* @param employeeTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape3.Employee} | |
* | |
* @return la liste des méthodes de {@link fr.devoxx.niveau2.exo2.etape3.Employee} et celles héritées | |
* {@link fr.devoxx.niveau2.exo2.etape3.Citizen} sous forme de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractInheritedMethodsButObjects(@Nonnull TypeElement employeeTypeElement) { | |
return extractInheritedMethods(employeeTypeElement).stream() | |
.filter(method -> !method.getEnclosingElement().equals(elementUtils.getTypeElement("java.lang.Object"))) | |
.collect(Collectors.toList()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fr.devoxx.niveau2.exo2.etape2; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
import javax.annotation.Nonnull; | |
import javax.lang.model.element.Element; | |
import javax.lang.model.element.Modifier; | |
import javax.lang.model.element.TypeElement; | |
import javax.lang.model.element.VariableElement; | |
import javax.lang.model.type.TypeMirror; | |
import javax.lang.model.util.ElementFilter; | |
import javax.lang.model.util.Elements; | |
import javax.lang.model.util.Types; | |
/** | |
* FieldsExplorer - | |
* | |
* @author Sébastien Lesaint | |
*/ | |
public class FieldsExplorer { | |
@Nonnull | |
private final Elements elementUtils; | |
@Nonnull | |
private final Types typeUtils; | |
public FieldsExplorer(@Nonnull Elements elementUtils, @Nonnull Types typeUtils) { | |
this.elementUtils = elementUtils; | |
this.typeUtils = typeUtils; | |
} | |
/** | |
* Extrait la liste des champs définis par la classe {@link fr.devoxx.niveau2.exo2.etape2.Cow} à partir du | |
* {@link TypeElement} qui la représente. | |
* <p> | |
* Les méthodes, constructors, champs sont des elements contenus dans l'élément de la classe. | |
* </p> | |
* <p> | |
* (astuce: connaissez-vous la classe {@link javax.lang.model.util.ElementFilter} ?) | |
* </p> | |
* | |
* @param cowTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape2.Cow} | |
* | |
* @return la liste des champs de la classe sous forme de {@link javax.lang.model.element.VariableElement} | |
*/ | |
public List<VariableElement> extractFields(@Nonnull TypeElement cowTypeElement) { | |
return ElementFilter.fieldsIn(cowTypeElement.getEnclosedElements()); | |
} | |
/** | |
* Extrait le type du champs "name" définis par la classe {@link fr.devoxx.niveau2.exo2.etape2.Cow} à partir du | |
* {@link TypeElement} qui la représente. | |
* <p> | |
* (astuce: la méthode {@link javax.lang.model.element.Name#contentEquals(CharSequence)} est bien pratique) | |
* </p> | |
* | |
* @param cowTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape2.Cow} | |
* | |
* @return le {@link TypeMirror} de {@link java.lang.String} pour le champs "name" dans la classe | |
* {@link fr.devoxx.niveau2.exo2.etape2.Cow}. | |
*/ | |
public TypeMirror extractNameFieldType(@Nonnull TypeElement cowTypeElement) { | |
return extractFields(cowTypeElement).stream() | |
.filter(field -> field.getSimpleName().contentEquals("name")) | |
.map(Element::asType) | |
.findFirst() | |
.get(); | |
} | |
/** | |
* Extrait les champs privés ou sans attribut de visibilité définis par la classe | |
* {@link fr.devoxx.niveau2.exo2.etape2.Cow} à partir du {@link TypeElement} qui la représente. | |
* | |
* @param cowTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape2.Cow} | |
* | |
* @return la liste des champs privés ou package protected de la classe sous la forme de {@link VariableElement}s | |
*/ | |
public List<VariableElement> extractPrivateAndPackageProtectedFields(@Nonnull TypeElement cowTypeElement) { | |
return extractFields(cowTypeElement).stream() | |
.filter( | |
field -> { | |
Set<Modifier> modifiers = field.getModifiers(); | |
return !modifiers.contains(Modifier.PROTECTED) && | |
!modifiers.contains(Modifier.PUBLIC); | |
} | |
).collect(Collectors.toList()); | |
} | |
/** | |
* Extrait les champs dépréciés définis par la classe {@link fr.devoxx.niveau2.exo2.etape2.Cow} à partir du | |
* {@link TypeElement} qui la représente. | |
* | |
* @param cowTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape2.Cow} | |
* | |
* @return la liste des champs déprécié de la classe sous la forme de {@link VariableElement}s | |
*/ | |
public List<VariableElement> extractDeprecatedField(@Nonnull TypeElement cowTypeElement) { | |
return extractFields(cowTypeElement).stream() | |
.filter(field -> field.getAnnotation(Deprecated.class) != null) | |
.collect(Collectors.toList()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fr.devoxx.niveau2.exo2.etape1; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
import java.util.stream.Stream; | |
import javax.annotation.Nonnull; | |
import javax.annotation.Nullable; | |
import javax.lang.model.element.Element; | |
import javax.lang.model.element.ExecutableElement; | |
import javax.lang.model.element.Modifier; | |
import javax.lang.model.element.TypeElement; | |
import javax.lang.model.type.TypeKind; | |
import javax.lang.model.type.TypeMirror; | |
import javax.lang.model.util.ElementFilter; | |
import javax.lang.model.util.Elements; | |
import javax.lang.model.util.Types; | |
/** | |
* MethodsExplorer - | |
* | |
* @author Sébastien Lesaint | |
*/ | |
public class MethodsExplorer { | |
@Nonnull | |
private final Elements elementUtils; | |
@Nonnull | |
private final Types typeUtils; | |
public MethodsExplorer(@Nonnull Elements elementUtils, @Nonnull Types typeUtils) { | |
this.elementUtils = elementUtils; | |
this.typeUtils = typeUtils; | |
} | |
/** | |
* Extrait la liste des méthodes définies par la classe {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du | |
* {@link TypeElement} qui la représente. | |
* <p> | |
* Les méthodes, fonctions, champs sont des elements contenus dans l'élément de la classe (ou de l'interface, | |
* d'ailleurs). | |
* </p> | |
* <p> | |
* (astuce: connaissez-vous la classe {@link javax.lang.model.util.ElementFilter} ?) | |
* </p> | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return la liste des méthodes (ie. pas les constructeurs) sous forme de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractMethods(@Nonnull TypeElement homerTypeElement) { | |
return ElementFilter.methodsIn(homerTypeElement.getEnclosedElements()); | |
} | |
/** | |
* Extrait la liste des constructeurs (en fait, un seul) définis par la classe | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du {@link TypeElement} qui la représente. | |
* <p> | |
* (astuce: avez-vous bien regardé la classe {@link javax.lang.model.util.ElementFilter} ?) | |
* </p> | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return une liste contenant le constructeur de {@link fr.devoxx.niveau2.exo2.etape1.Homer} sous forme de | |
* {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractConstructors(@Nonnull TypeElement homerTypeElement) { | |
return ElementFilter.constructorsIn(homerTypeElement.getEnclosedElements()); | |
} | |
/** | |
* Extrait la liste des constructeurs et méthodes publiques définis par la classe | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du {@link TypeElement} qui la représente. | |
* <p> | |
* (astuce: les attributs sont définis au niveau de l'interface {@link javax.lang.model.element.Element}) | |
* </p> | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return une liste contenant toutes les méthodes et constructeurs publiques de | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer} sous forme de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractPublicMethodsAndConstructors(@Nonnull TypeElement homerTypeElement) { | |
return Stream.concat( | |
extractConstructors(homerTypeElement).stream(), | |
extractMethods(homerTypeElement).stream().filter(method -> method.getModifiers().contains(Modifier.PUBLIC)) | |
).collect(Collectors.toList()); | |
} | |
/** | |
* Extrait la liste des méthodes et constructeurs publics définis par la classe qui retournent {@code void} | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du {@link TypeElement} qui la représente. | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return une liste contenant tous les fonctions publiques de {@link fr.devoxx.niveau2.exo2.etape1.Homer} sous forme | |
* de {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractPublicFunctions(@Nonnull TypeElement homerTypeElement) { | |
return extractPublicMethodsAndConstructors(homerTypeElement).stream() | |
.filter(method -> method.getReturnType().getKind() == TypeKind.VOID) | |
.collect(Collectors.toList()); | |
} | |
/** | |
* Extrait les méthodes "eatDonuts" définies par la classe {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du | |
* {@link TypeElement} qui la représente. | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return une liste contenant le constructeur de {@link fr.devoxx.niveau2.exo2.etape1.Homer} sous forme de | |
* {@link ExecutableElement} | |
*/ | |
public List<ExecutableElement> extractEatDonutsMethods(@Nonnull TypeElement homerTypeElement) { | |
return extractMethods(homerTypeElement).stream() | |
.filter(method -> method.getSimpleName().contentEquals("eatDonuts")) | |
.collect(Collectors.toList()); | |
} | |
/** | |
* Extrait la méthode "eatDonuts" non dépréciée définie par la classe {@link fr.devoxx.niveau2.exo2.etape1.Homer} à | |
* partir du {@link TypeElement} qui la représente. | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return le {@link ExecutableElement} qui représente la surcharge non dépréciée de la méthode "eatDonuts" | |
*/ | |
public ExecutableElement extractCurrentEatDonutsMethod(@Nonnull TypeElement homerTypeElement) { | |
return extractEatDonutsMethods(homerTypeElement).stream() | |
.filter(method -> method.getAnnotation(Deprecated.class) == null) | |
.findFirst() | |
.get(); | |
} | |
/** | |
* Extrait les paramètres portant l'annotation {@link javax.annotation.Nullable} des méthodes définies par la classe | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer} à partir du {@link TypeElement} qui la représente. | |
* <p> | |
* (indice: on peut obtenir le {@link TypeMirror} de tout {@link Element} via la méthode {@code asType()}) | |
* </p> | |
* | |
* @param homerTypeElement le {@link TypeElement} de la class {@link fr.devoxx.niveau2.exo2.etape1.Homer} | |
* | |
* @return un Set contenant le {@link TypeMirror} de {@link java.lang.String} et | |
* {@link fr.devoxx.niveau2.exo2.etape1.Homer.Flavor} | |
*/ | |
public Set<TypeMirror> extractTypeOfNullableParameters(@Nonnull TypeElement homerTypeElement) { | |
return extractMethods(homerTypeElement).stream() | |
.flatMap(method -> method.getParameters().stream()) | |
.filter(param -> param.getAnnotation(Nullable.class) != null) | |
.map(Element::asType) | |
.collect(Collectors.toSet()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment