IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

[JDK1.5] Obtenir Annotation à partir d'une String


Sujet :

Langage Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut [JDK1.5] Obtenir Annotation à partir d'une String
    Salut à tous...

    Je cherche (et je n'y arrive pas ) à récupérer une annotation (sous le type Annotation) à partir de son nom (String).

    Par exemple les annotations sont :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MaxLenght {
    	int value() default 60;
    }
     
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Name {
    	String value() default "";
    }
    J'ai essayé par Class.forName(String name) mais les type renvoyé sont incompatibles !
    J'ai essayé avec une HashMap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private static Map<String, Annotation> annoteMap = new HashMap<String, Annotation>();
    	static {
    		annoteMap.put("name", Name);
    		annoteMap.put("maxLenght", MaxLenght);
    	}
    Mais Name et MaxLenght sont non résolu et pourtant sont des annotations du même package.
    Les outils de l'API Reflect sont insuffisant : les arguments nécéssaires sont toujours les Annotations elles-même...

    Si quelqu'un a une idée, il sera le bienvenu... Je ne sais plus trop quoi essayer !
    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Je ne comprend pas très bien ce que tu veux faire... Donne une exemple concret (où tu met ton annotation et comment tu essaye de la récupérer).

    Un appel à la méthode getAnnotation() de l'objet représentant ton élément dans l'API de reflection devrait suffire, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaxLenght maxLenght = field.getAnnotation(MaxLenght.class);
    int value = maxLenght.value();
    a++

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut
    Excuse moi, j'ai pas du être très clair. Je m'explique :

    Voila une des méthodes que je dois réaliser. Il s'agit en fait d'une sorte d'encapsulation de la réflexion pour les annotations. J'ai ensuite d'autres méthodes identiques sur les annotations de Classe ou de Méthodes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static Class getFieldAnnotation(Class theClass, String field, String annotationValue) {
          Annotation[] annotations = null;
    		try {
    			annotations = theClass.getDeclaredField(field).getAnnotations();
    		} catch (NoSuchFieldException e) {...}
    		if (annotations.length != 0)
    			for (Annotation annotation : annotations) {
                //Est c'est là que je bloque pour comparer annotationValue avec le nom de chaque annotation
                //(le toString() renvoie le code complet de annotation)
                }
    }
    Ainsi, si un développeur utilise l'annotation MaxLength et/ou Name comme ceci dans son programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public class MaClasse {
    	@MaxLenght(value = 80)
    	@Name(value = "default_name")
    	private String named;
    ....
    }
    Je dois pouvoir avec cette méthode, récupérer la valeur de l'annotation ou à défault l'annotation elle-même en donnant en paramètre la classe utilisée, le nom du champ portant l'annotation, et le nom de l'annotation.
    Il n'y aura ainsi pas besoin d'aller chercher le code source de la classe développée pour savoir si l'utilisation de la classe est correct ou non.

    Mon problème est donc que je n'arrive pas à récupérer l'annotation MaxLenght ou Name (et donc sa valeur avec MaxLenght.value()) à partir de son nom en String, comme on pourrait le faire avec Class.forName() ou getDeclaredField(String field).

    Pour reprendre ton idée (j'ai déjà essayé)
    Un appel à la méthode getAnnotation() de l'objet représentant ton élément dans l'API de reflection devrait suffire, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaxLenght maxLenght = field.getAnnotation(MaxLenght.class);
    int value = maxLenght.value();
    Cette méthode prends en paramètre la classe, moi j'ai besoin de prendre en paramètre le Nom en String. et c'est cette conversion que je ne peux pas faire.

    Le but est au final de donner des indications ou des limites sur l'instanciation de MaClasse lorsque l'on veut l'utiliser.

    J'éspère que je me suis bien expliqué cette fois.
    Sinon dis-moi ce que tu comprends mal.
    En tout cas, merci beaucoup pour ton aide, je galère depuis 2 jours déjà... [/b]

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Si tu veux le nom court de l'annotation tu peux utiliser la méthode getSimpleName() de la classe Class, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	public static Class getFieldAnnotation(Class theClass, String field, String annotationValue) {
    	      Annotation[] annotations = null;
    	      try {
    	         annotations = theClass.getDeclaredField(field).getAnnotations();
    	         for (Annotation annotation : annotations) {
    	        	 if ( annotation.annotationType().getSimpleName().equals(annotationValue) ) {
    	        		 return annotation.annotationType();
    	        	 }
    	         }
    	      } catch (NoSuchFieldException e) {
    	    	  e.printStackTrace();
    	      }
    	      return null;
    	}
    Mais je ne sais pas si c'est bien ce que tu veux...



    Citation Envoyé par pitoubicou
    Mon problème est donc que je n'arrive pas à récupérer l'annotation MaxLenght ou Name (et donc sa valeur avec MaxLenght.value()) à partir de son nom en String, comme on pourrait le faire avec Class.forName() ou getDeclaredField(String field).
    Si c'est avec le nom complet tu dois pouvoir utiliser Class.forName() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Class c = Class.forName("packageName.MaxLenght");
    a++

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut
    Le getClass() sur une annotation donne quelquechose comme class $Proxy1 et donc le nom simple est $Proxy1. Je ne sais pas d'où ça sort.
    Elle est donc inutilisable.

    Le toString renvoyant le nom entier du style @myPackage.MaxLenght(value=60), je vais essayer de parser ça pour récupérer le nom myPackage.MaxLenght.

    Si tu as d'autres idées, n'hésite pas, merci

    EDIT :
    Le parser marche, je récupère bien le nom de l'Annotation.

    Le problème est que le Class.forName() marche, mais me renvoie la classe, et non l'annotation. Je ne peux donc pas obtenir la valeur de l'annotation avec value().

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par pitoubicou
    Le getClass() sur une annotation donne quelquechose comme class $Proxy1 et donc le nom simple est $Proxy1. Je ne sais pas d'où ça sort.
    Elle est donc inutilisable.
    C'est pour cela que j'ai utilisé la méthode annotationType() qui renvoit le type de l'annotation, alors que getClass() renvoit la classe de l'objet implémentant l'interface représenté par l'annotation. Ce type d'objet ne peux pas être crée directement et le JVM doit surement passé par un Proxy...

    Citation Envoyé par pitoubicou
    Le toString renvoyant le nom entier du style @myPackage.MaxLenght(value=60), je vais essayer de parser ça pour récupérer le nom myPackage.MaxLenght.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    annotation..annotationType().getSimpleName();
    Citation Envoyé par pitoubicou
    Si tu as d'autres idées, n'hésite pas, merci
    As-tu essayé le code que je t'ai donné ? Cela ne fonctionne pas ?

    Citation Envoyé par pitoubicou
    Le problème est que le Class.forName() marche, mais me renvoie la classe, et non l'annotation. Je ne peux donc pas obtenir la valeur de l'annotation avec value().
    C'est normal que cela te renvoit la classe puisque c'est fait pour ca... mais avec la classe tu peux obtenir l'annotation via getAnnotation(). Maintenant si tu ne type pas du tout tes annotations tu va être obligé de passer par de la reflection pour récupérer ses attributs, ce qui risque d'être assez fastidieux...

    a++

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut
    1000 excuses pour le code que tu m'avait donné, j'avais simplement essayé le getSimpleName sans le annotations.annotationType devant.
    Donc je te rassure, ta ligne marche et il me reconnait bien ma chaine de caractère !!! (OUF !)

    Mais je n'ai pas tout a fait compris ta dernière remarque :
    Maintenant si tu ne type pas du tout tes annotations tu va être obligé de passer par de la reflection pour récupérer ses attributs, ce qui risque d'être assez fastidieux...
    Je ne comprends pas l'expression typer ses annotation. Mon annotations est du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MaxLenght {
    	int value() default 60;
    }
    C'est pas typé ça ?? (int value() ??) ou je suis a coté de la plaque ?!!

    Passer pas la réflexion, tu veux je suppose dire : utiliser les getMethod() pour récupérer le String value() de l'annotation ?[/code]

    Enfin merci déjà pour l'aide apporté, ca m'a bien débloqué déjà !

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut
    Rebonjour,

    En fait, mon problème s'est simplifié maintenant que j'arrive à obtenir l'annotation à partir de son nom.

    Si mon annotation est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    @Documented
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MaxLenght {
    	int value() default 100;
    }
    et son utilisation est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public class MaClasse {
    	@MaxLenght(60)
    	private String name;
        .....
    }
    Peut-on arriver à obtenir, par la réflexion je suppose, la valeur modifiée 60.
    J'ai essayé d'utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    annotation.annotationType().getDeclaredMethod("value", new Class[0]).getDefaultValue();
    Mais, comme son nom l'indique elle me renvoie un int = 100, valeur par défault.
    J'ai essayé d'utiliser invoke() mais je ne pense pas que ca marche, et puis je suis pas arrivé à mettre les bon paramètres !
    Je n'arrive pas à trouver la bonne méthode pour récupérer cet objet modifié !

    Merci beaucoup pour votre aide !!!

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    C'est normal car getDefaultValue(), comme son nom l'indique, renvoit la valeur par défaut d'une méthode représentant un attribut d'une annotation.

    Si tu veux obtenir la valeur réelle il faut exécuter cette méthode sur ton annotation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		Method m = annotation.annotationType().getDeclaredMethod("value", new Class[0]);
    		Integer integer = (Integer) m.invoke(annotation);
    C'est ce que je disais sur la complexité de la reflection...
    Sans reflection et avec le type réel c'est nettement plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		MaxLenght maxLenghtAnnotation = xxx.getAnnotation(MaxLenght.class);
     
    		int value = maxLenghtAnnotation.value();
    a++

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2006
    Messages : 29
    Points : 30
    Points
    30
    Par défaut
    Bon ben merci beaucoup, ca marche impeccable.

    Voici le code de ma fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /**
             * The getClassAnnotation returns the object passed in value of the "annotationValue" annotation on the method "method" in the class "theClass" or one of its super class.<br>
             * Returns <b>null</b> otherwise.<br>
             * <br>
             * @param theClass the class or one of its super class where is the method.
             * @param method the name of the method where is the annotationValue.
             * @param annotationValue the name of the annotation class.
             * @return the object found in value. <b>null</b> if there is no annotation.
             */
    	public static Object getFieldMethod(Class theClass, String method, String annotationValue) {
    		if (theClass != null) {
    			Method m = getMethod(theClass, method);
    			if (m !=null) {
    				Annotation[] annotations = m.getDeclaredAnnotations();
    				if (annotations.length != 0) {
    					for (Annotation annotation : annotations) {
    						if (annotation.annotationType().getSimpleName().equals(annotationValue)) {
    							try {
    								return annotation.annotationType().getDeclaredMethod("value", new Class[0]).invoke(annotation);
    							} catch (NoSuchMethodException e) {
    								Log.error("No method value() in the annotation "+annotation.annotationType().getSimpleName()+" : ",e);
    							} catch (IllegalArgumentException e) {
    								Log.error("The method has been passed an illegal or inappropriate argument : ",e);
    							} catch (IllegalAccessException e) {
    								Log.error("The invoked method has no access to the specified method : ",e);
    							} catch (InvocationTargetException e) {
    								Log.error("The invoked method throws an exception : ",e);
    							}
    						}
    					}
    					Log.debug("No annotation "+annotationValue+" on the method " + method
    							+ " in the class " + theClass.getSimpleName()+" or one of its super class");
    				}else
    					Log.debug("No annotation on the method " + method
    							+ " in the class " + theClass.getSimpleName()+" or one of its super class");
    			} else
    				Log.debug("No method "+method+" in the class "+theClass.getSimpleName()+" or one of its super class");
    		} else
    			Log.debug("No class "+theClass.getName()+" exist");
    		return null;
    	}
    Donc la methode invoke marche très bien, fallait juste savoir l'utiliser (un seul argument suffit...) merci !
    Ta deuxième solution est, c'est sur, plus simple, mais je ne voulais ne pas avoir à importer mes classes d'annotation, car cette méthode doit marcher pour tout type d'annotation (MaxLenght, Name, MinValue, etc... ou toute annotion que l'on pourrait créer ensuite). Ces annotations ne doivent posséder qu'une seule méthode "value()".

    Bon, il me reste plus qu'à marquer tout ça en résolu !!! (ca fait plaisir )
    Merci encore adiGuba, tu m'as bien aidé !!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 18/01/2006, 16h26
  2. Réponses: 4
    Dernier message: 07/01/2006, 18h36
  3. [C#][TextBox] Comment obtenir la longeur d'une string
    Par l_ourson69 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 20/12/2005, 10h14
  4. Récupérer des floats à partir d'une string
    Par hamster dans le forum SL & STL
    Réponses: 8
    Dernier message: 09/06/2005, 08h10
  5. [DOM] Comment creer un DOM à partir d une String
    Par RolandB dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 24/04/2005, 18h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo