JAXXContext
Présentation
Ajout d'un context applicatif dans JAXX.
Le besoin initial de ce développement est de pouvoir facilement intégrer un context applicatif dans JAXX et de pouvoir l'utiliser dans les fichiers JAXX pour injecter par exemple des données dans les widgets.
jaxx.runtime.JAXXContext
Il s'agit du contrat de base du context applicatif.
Les entrées dans le context
Chaque donnée utilisable dans le context est caractérisée par deux propriétés :
- la type de l'objet
- un nom (facultatif) associé à la donnée
Le type de l'objet correspondant en fait à la classe de la donnée.
Le nom qui est facultatif permet de pouvoir distinguer plusieurs données d'un même type dans le context. Si le nom n'est pas utilisé pour caractériser une données on fixera alors sa valeur à null.
Afin de pouvoir caractériser les entrées dans le context, une classe a été définie jaxx.runtime.context.JAXXContextEntryDef.
Les méthodes de lecture
On a définit deux méthodes de lecture de données dans le context :
- getContextValue(Class) récupère la donnée non nommée dont le type correspond à celui passé.
- getContextValue(Class,String) récupère la donnée nommée dont le type correspond à celui passé.
Les méthodes d'écriture
On a définit quatre méthodes d'écriture de données dans le context :
- setContextValue(Object) enregistre dans le context la donnée non nommée.
- setContextValue(Object,String) enregistre dans le context la donnée nommée.
- removeContextValue(Class) supprime du context, la donnée non nommée dont le type est passé.
- removeContextValue(Class, String) supprime du context, la donnée nommée dont le type est passé.
Afin de pouvoir assurer une cohérence dans le context, chaque injection de donnée, sera toujours précédée par une suppression d'un éventuellement ancienne valeur qui aurait la même définition d'entrée.
L'héritage
Il est possible d'avoir une hériarchie de context qui s'enchaînent. Ce mécanisme a été mis en place pour répondre à un besion précis : chaque fichier JAXX donne lieu à une nouvelle classe qui possède son propre context.
On peut avoir des fichiers JAXX qui utilisent d'autres fichiers JAXX, il faut donc être capable de lier le context du composent parent avec ses fils.
La mise en place de l'héritage est transparente pour l'utilisateur : aucune méthode supplémentaire n'est requise.
Les implantations de context
jaxx.runtime.DefaultJAXXContext
Il s'agit de l'implantation par défaut utilisée par les objects JAXXObject (objets générés).
A noter que pour les opérations d'injection ou de suppression, on effectuera les opérations sur le context qui contient réellement la donnée, ce qui est important pour conserver la cohérence des contexts dans les contexts chaînés.
Pour traiter le context parent, aucune méthode publique supplémentaire n'a été rajoutée, il suffit d'injecter un objet de type JAXXContext non nommé qui le context courant qui sera détecté comme une entrée de type context.
Cette entrée spéciale ne sera pas stockée avec les autres entrées afin d'optimiser les algorithmes d'injection et de restitution.
jaxx.runtime.context.JAXXInitialContext
On a implanté un second type de context qui lui peut servir à l'initialisation des JAXXObject.
Ce second type de context ajoute des méthodes pour préparer le context avant l'instanciation des JAXXObject.
Ce context admet certaine limitation (pas de suppression dans le context), et apporte trois nouvelles méthodes :
- add(Object) : injecte dans le context une entrée non nommée et retourne l'instance du context.
- add(String,Object) : injecte dans le context une entrée nommé et retourne l'instance du context.
- to(JAXXContext) : injecte dans le context passé toutes les entrée du context.
Les méthodes add peuvent être chaînées comme dans l'exemple suivant :
JAXXInitialContext context = new JAXXInitialContext().add("string").add(0).add("currentDate",new Date());
Intégration dans les JAXXObject
Le traitement d'un fichier JAXX donne lieu à une classe qui possède le contrat jaxx.runtime.JAXXObject.
Ce contrat hérite donc du contrat JAXXContext (afin de pouvoir l'utiliser de manière transparente dans les fichiers JAXX).
Afin de simplifier la génération et les évolutions du context indépendemment des évolutions des JAXXObject, on utilise un pattern de délégation au sein des object générés.
Paramétrage de l'implantation du context
Une propriété a été rajoutée sur le plugin JAXX, afin de pouvoir préciser l'implantation de context à utiliser :
jaxx.jaxxContextImplementorClass
Il s'agit du nom qualifié de la classe d'implantation à utiliser.
Par défaut, si rien n'est renseigné, on utilisera un jaxx.runtime.DefaultJAXXContext.
Initialisation d'un JAXXObject
Un nouveau constructeur a été ajouté dans les JAXXObjet générés afin de pouvoir facilement initialisé un tel objet à partir d'un context parent, son unique paramètre est le context parent. Ce constructeur est capable de différencer le type de context passé :
- s'il s'agit d'un JAXXInitialContext, on recopie alors dans le context réel de l'objet toutes les entrées du context passé.
- sinon le context passé est simplement injecté dans le context de l'objet (et donc sera utilisé comme le context parent de celui de l'objet).
Voici un exemple d'initialisation d'un JAXXObject :
java.util.Date currentDate = new java.util.Date(); JAXXInitialContext context = new JAXXInitialContext().add("string").add(0).add("currentDate",currentDate); JAXXObject ui = new MyUI(context); assert "string".equals(myUI.getContextValue(String.class)); assert 0 == myUI.getContextValue(Integer.class); assert currentDate.equals(myUI.getContextValue(java.util.Date.class,"currentDate"));
A noter, que l'initialisation du context d'un JAXXObject sera toujours effectuée avant la méthode $initialize générée par le compilateur JAXX, ce qui permet de pouvoir utiliser le context pour l'initialisation des widgets dans les fichiers JAXX.