A partir de JCMS 5.7.1, toutes les données de JCMS dérivant de la classe Data disposent d’un nouveau champ persistant, extraDataMap, qui permet de stocker des informations additionnelles.
Grâce à ce mécanisme, un module peut ajouter dynamiquement de nouveaux champs à un type de données existant. Il devient par exemple possible pour un module de géolocalisation d’ajouter les champs longitude et latitude aux membres, aux espaces de travail, aux publications...
Ce nouveau champ peut être utilisé de deux manières :
- Pour ajouter dynamiquement de nouveaux champs de saisis dans la plupart des formulaires JCMS (publication, catégorie, membre, groupe, espace de travail, document, …)
- Pour stocker, programmatiquement, des informations spécifiques dans une donnée. Par exemple, un DataController peut faire une signature MD5 d’un document et la stocker en extraData.
1. Ajout de nouveaux champs aux types existants
La déclaration des nouveaux champs se fait via les propriétés :
- Une première propriété sert à définir le mode d’édition et la valeur par défaut.
- Des propriétés de langues associées fournissent les libellés pour le formulaire d’édition.
La propriété de déclaration doit respecter la syntaxe suivante :
extra.Type.name(.editor): defaultValue
Avec :
Type: représente le type de donnée concerné (p. ex.Article,Member,Category, …)name: représente le nom de la donnée et, dans le cas d’un module doit commencer parjcmsplugin.(p. ex.jcmsplugin.geolocator)editor(optionnel) : représente le type d’éditeur pour ce champ. Par défaut, si cette partie est absente, l’éditeur est un champ texte (sur une ligne). Les autres valeurs possibles sont :numberpour un champ texte permettant d’éditer un nombre ;booleanpour un champ permettant de choisir une valeur booléenne (oui/non) ;areapour une zone de texte sur plusieurs lignes ;hiddenpour un champ caché.
defaultValue(optionnelle) : représente la valeur par défaut du champ.
Les propriétés de langues associées doivent avoir la même structure que la propriété de déclaration, sans la partie éditeur. Elles peuvent être accompagnées d’une seconde propriété avec le suffixe .help pour fournir une aide pour le champ.
Exemples
Dans cet exemple, on ajoute 3 nouveaux champs au membre :
- Le compte de messagerie instantanée
- Un booléen indiquant si le membre est externe à la société
- Le code postal
Pour ce faire, on ajoute les propriétés suivantes.
Dans le fichier WEB-INF/plugins/DemoPlugin/properties/plugin.prop :
# Membre : ajout du login de messagerie instantanée
extra.Member.jcmsplugin.demo.imlogin:
# Membre : ajout d’un booléen qui indique si le membre est externe
extra.Member.jcmsplugin.demo.external.boolean: false
# Membre : ajout du Code Postal
extra.Member.jcmsplugin.demo.zipcode.number: false
Dans le fichier WEB-INF/plugins/DemoPlugin/properties/languages/fr.prop :
extra.Member.jcmsplugin.demo.imlogin: Messagerie instantanée
extra.Member.jcmsplugin.demo.imlogin.help: Entrez l’identifiant de messagerie instantannée
extra.Member.jcmsplugin.demo.external: Membre externe
extra.Member.jcmsplugin.demo.zipcode: Code Postal
Dans le fichier WEB-INF/plugins/DemoPlugin/properties/languages/en.prop :
extra.Member.jcmsplugin.demo.imlogin: Instant Messenger
extra.Member.jcmsplugin.demo.imlogin.help: Enter the login for the Instant Messenger
extra.Member.jcmsplugin.demo.external: External
extra.Member.jcmsplugin.demo.zipcode: Zip Code
Lors de l’édition, ces nouveaux champs apparaissent à la suite des champs standards :
Fig. 1. Exemple de nouveaux champs ajouter sur les membres
2. API
Le champ extraDataMap est une Map dont les clés et les valeurs sont des String.
La classe Data fournit plusieurs méthodes pour manipuler ce champ :
getExtraData (String name): retourne la valeur associé à l’extraDataname.setExtraData(String name, String value): affecte value à l’extraDataname.removeExtraData(String name): supprime l’extraDataname.
Dans le cas d’une utilisation purement programmatique et si l’utilisateur n’a pas à avoir connaissance de ces données, il n’est pas nécessaire de déclarer les extraData dans les propriétés.
Attention ! Lors de la mise-à-jour de ce champ, il faut penser à dupliquer l’extraDataMap :
Publication copy = (Publication)pub.clone()
Map extraDataMap = copy.getExtraDataMap() ;
If (extraDataMap ! = null) {
copy.setExtraDataMap(new HashMap(extraDataMap)); } copy.setExtraData(key, value);
Exemple :
package com.jalios.jcmsplugin.demo;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.jalios.jcms.BasicDataController;
import com.jalios.jcms.Data;
import com.jalios.jcms.Member;
import com.jalios.jcms.Publication;
public class MailDataController extends BasicDataController {
private static final Logger logger = Logger.getLogger(MailDataController.class);
static int PSTATUS_DONE = -70;
static String WORKFLOW_ID = "wffomulaire";
public void afterWrite(Data data, int op, Member mbr, Map context) {
// Only process update
if (op != OP_UPDATE) {
return;
}
// Only process publication
if (!(data instanceof Publication)) {
return;
}
Publication pub = (Publication)data;
// Only process the submission workflow
if (!WORKFLOW_ID.equals(pub.getWorkflow().getId())) {
return;
}
// Only process publication in the DONE state
if (pub.getPstatus() != PSTATUS_DONE) {
return;
}
// Only process publication not already notified
if ("true".equals(pub.getExtraData("mailSent"))) {
return;
} // Send the mail sendMail(pub); // Update the data
Publication copy = (Publication)pub.clone();
Map extraDataMap = pub.getExtraDataMap();
if (extraDataMap != null) {
copy.setExtraDataMap(new HashMap(extraDataMap));
}
copy.setExtraData("mailSent", "true");
copy.performUpdate(mbr); } private void sendMail(Publication pub) { logger.debug("Send the mail ..."); // ... } }
3. ExtraData vs. ExtraInfo
La classe Data dispose d’un autre champ, extraInfoMap, qui peut paraître similaire au champ extraDataMap. Néanmoins, ils diffèrent sur 2 points :
extraInfoMap, contrairement àextraDataMap, n’est pas limitée auxStringmais peut stocker n’importe quel type de données.extraInfoMapest uneMapnon persistante. Son contenu est donc perdu à chaque redémarrage de JCMS. Elle est typiquement destinée à mettre en cache des informations associées à la donnée.
4. ExtraData vs. Extension
Jusqu’à JCMS 5.7.1, les extensions étaient la seule manière disponible pour ajouter des champs aux types non-extensibles (Member, Group, Category, Workspace, FileDocument). Avec les extraData, l’ajout de champ devient plus simple et surtout plus extensible. En particulier, il ne peut y avoir qu’une extension par type, ce qui pose problème si deux modules veulent déployer des extensions différentes pour un même type. En reposant sur une déclaration par les propriétés, les extraData sont mieux adaptées aux modules.
Néanmoins, les extraData sont plus limitées dans les types de champ qu’elles peuvent supporter à l’édition.
Pour les types de champs suivant, on préférera les extensions aux extraData :
- Les champs multivalués
- Les champs multilingues
- Champs textuels typés (wiki, wysiwyg, image, média, couleur, requête)
- Les champs Date ; sauf à stocker une représentation textuelle de la date.
- Les champs Liens sur donnée (Membre, Catégorie, Publication, Document, …) ; sauf à stocker l’identifiant de la donnée et à en accepter les conséquences (liaison faible sans contrôle d’intégrité)
- Les champs liés aux bases de données (SQL query, SQL result et DB Record)



