1. Un moyen de suivre l'audience du site
A chaque fois qu'un utilisateur consulte une page, JCMS enregistre cette requête dans le journal des accès (1 fichier par jour). L'enregistrement comporte des informations sur la page consultée (titre, identifiant JCMS, catégorie courante, portail, ...) mais aussi sur l'utilisateur (identifiant du membre, adresse IP, ...)
Lorsqu'une analyse statistique est declenchée (manuellement ou de façon programmée), JCMS lit les fichiers d'accès, effectue les calculs
statistiques et produit un rapport statistique. Le rapport est construit selon un modèle qui est composé de portlets affichant chacune une métrique.
Pour produire des rapports statistiques basés sur le modèle standard, il suffit de paramétrer la portée de l'analyse (un mois, une semaine, ...) et la date de génération des rapport. Une fois ce paramètrage fait, JCMS produira périodiquement les rapports. Néanmoins, le système est ouvert et il est possible de changer la structure des rapports, la présentation des métriques est d'intégrer de nouvelles métriques.
1.1 Modèle de rapports
1.1.1 Rapports périodiques
JCMS permet de définir des modèles de rapport de statistiques. Ces modèles permettent de générer périodiquent des rapports. Ils se définissent dans l'onglet portlet des espaces de travail. La planification d'un rapport comporte 4 paramètres :
- Date de planification : la date de déclenchement de la première analyse ;
- Date de début d'analyse : les fichiers d'accès seront analysés depuis la date de départ ;
- Date de fin d'analyse : les fichiers d'accès seront analysés jusqu'a la date de fin ;
- Périodicité : les rapports seront générés et analysés périodiquement. Les trois dates précédentes seront décalées en conséquence.
Dans l'exemple ci-dessous, les rapports sont générés à partir du 1er novembre 2005 sur la période du 1er au 31 octobre 2005. Un rapport est ensuite généré tous les mois. Par exemple, le 1er décembre 2005 sur la période du 1er au 30 novembre 2005.

Planification de rapport
Pour paramétrer un rapport mensuel (du 1er au dernier jour du mois), il faut fixer la date de fin d'analyse sur un mois de 31 jours afin d'être assuré que tous les jours du mois seront pris en compte. Les mois de 28, 29 ou 30 jours seront correctement analysés. Si la date de fin d'analyse est fixée un autre jour par exemple le 15 (ou le 28), le rapport sera alors généré du 1er au 15.
1.1.2 Rapport multiple (plusieurs types de rapport)
Un modèle de rapport de statistiques est une page composée de portlets. Chacune des portlets analyse et présente une information (pages vues, visiteur, navigateurs, ...). Il est possible de construire plusieurs modèles de rapports de statistiques composés de portlets différentes. Ces portlets ne peuvent pas être récupérées et exploitées dans les pages portail du "Front Office".

Portlets composants un modèle de rapport
1.1.3 Analyse par espace de travail
Un modèle de rapport permet d'effectuer une analyse de statistiques pour un espace de travail ou sur l'ensemble du site (rapport global). La liste de ces modèles est définie dans les propriétés du site. Un modèle de rapport global génère :
- un rapport par espace de travail.
- un rapport présentant les résultats consolidés sur tous les espaces de travail.

Editeur de propriétés - Choix des modèles de rapport
1.2 Portlet Stat Metrics
Les portlets de statistiques sont chargées d'analyser et de présenter une information calculée à partir des fichiers de statistiques. Cette information est en générale une combinaison d'éléments composant les lignes de statistiques. Cette unité de mesure, est appelée métrique.

Edition PortletStatMetrics - Gabarit d'affichage: Moyenne/Horaire/Hebdomadaire
1.2.1 Présentation
Les portlets de statistiques sont uniquement utilisées par les modèles de rapport. Elles ne peuvent pas être affichées dans le portail. En standard, la Portlet Stat Metrics permet de travailler sur une métrique qui sera analysée puis présentée.
1.2.2 Taux de hits
Durant l'analyse, les portlets comptent le nombre d'occurrences de leur métrique. Par exemple si une portlet compte les téléchargements, chaque téléchargement incrémentera un compteur de +1. Ce calcul est appelé le "Taux de hit". L'affichage de la portlet présente ce taux.
1.2.3 Répartition horaire et hebdomadaire
Durant l'analyse, les portlets croisent le taux de hit avec la répartition horaire et hebdomadaire. Par exemple si une portlet compte les téléchargements, chaque téléchargement incrémentera un compteur de +1 pour le jour courant et pour l'heure courante. L'affichage de la portlet présente cette répartition.
1.2.4 Top 10
Durant l'analyse, les portlets comptent le taux de hit pour chaque métrique. Par exemple si une portlet compte les téléchargements, chaque téléchargement du document A incrémentera un compteur de +1 pour A. L'affichage de la portlet présente le top N de la métrique (Trié dans l'ordre décroissant).
1.2.5 Filtrage par zone
JCMS découpe implicitement le site en plusieurs zones: Espace d'administration (Admin), Espace de Travail (Work), Page portail (Public), ... Durant l'analyse, les portlets peuvent filtrer les résultats sur une zone restreinte. Cela permet d'obtenir des résultats plus pertinents. Par exemple ne tenir compte que des accès en "front office".
1.3 Evolutions futures
1.3.1 Export vers des produits tiers
JCMS ne permet pas en standard d'effectuer un export des statistiques vers des produits tiers. Ce développement est envisagé pour la prochaine version de JCMS. Néanmoins, il est possible de développer un gabarit d'affichage spécifique pour la PortletStatMatrics affichant du XML ou du CSV au lieu de XHTML.
1.3.2 Historisation ou Consolidation des rapports
JCMS ne permet pas en standard de consolider les rapports analysés. Par exemple, il n'est pas possible de fabriquer un rapport annuel sur la base de rapports mensuels. Pour le moment il faut effectuer une analyse annuelle séparée.
1.3.3 Consolidation entre réplicats
Les fichiers de statistiques sont générés pour chaque réplicat. JCMS ne permet pas en standard de consolider ces fichiers. Ce développement est envisagé dans une future version de JCMS. Des développements spécifiques ont déjà été effectués dans ce sens.
1.3.4 Remontée dans le Front Office
JCMS ne permet pas en standard de présenter les résultats de l'analyse des statistiques dans le Front Office. Il est possible par un développement spécifique, de générer une information (Image, XML) qui sera présentée dans le Front Office.
2. Mises en oeuvre
L'analyse des statistiques se fait en deux temps. Tout d'abord il faut alimenter les fichiers d'accès en naviguant sur le site puis lancer une analyse sur la période de navigation. Dans la configuration par défaut, l'enregistrement des accès est déjà activée.
Les fichiers d'accès sont générés dans le répertoire WEB-INF/data/stats/. Il est donc important de prévoir de l'espace disque nécessaire pour stocker ces fichiers.
Selon le paramètrage du modèle de rapport, le calcul des statistiques peut consommer beaucoup de mémoire et de temps processeur. Cette consommation peut engendrer une indisponibilité du site. Il est fortement préconisé de bien dimensionner la machine qui effectue la génération des rapports et de paramétrer cette génération pendant les heures creuses.
2.1 Configuration des propriétés
Activer l'écriture et l'analyse des modèles de rapport de statistiques.

Editeur de propriétés - Statistiques
2.1.1 Ecriture/Analyse
L'option Activer les écritures active l'enregistrement des accès. Cette option est activée par défaut.
L'option Activer l'analyse autorise l'exécution automatique ou manuelle d'analyse de statistiques. Cette option est activée par défaut. Si la volumétrie du site est importante, cette option devrait être désactivée en production (cf. 2.1)
2.1.2 Résolution DNS
L'option "Résoudre les noms DNS" permet de convertir les adresses IP en nom DNS. La résolution DNS à lieu lors de chaque accès à une page du site. Si le serveur DNS est distant ou peu performant cette option peut dégrader considérablement les performances de JCMS. Par défaut, elle est désactivée.
2.1.3 Modèle de rapport
Comme indiqué dans la section 1.1, les modèles de rapport définis dans cet interface sont des rapports globaux. L'analyse s'effectuera pour l'ensemble du site et pour chaque espace de travail.
2.2 Définition des modèle de rapport
Les rapports générés sont disponibles depuis l'administration du site ou des espaces de travail. Une liste des modèles de rapport disponibles est présentée. Cliquer sur un modèle de rapport pour visualiser son gabarit d'affichage.
2.2.1 Analyse ponctuelle d'un rapport
Le gabarit d'affichage d'un modèle de rapport permet de lancer une analyse ponctuelle. L'analyse peut porter sur tous les espaces de travail ou seulement sur l'espace courant. Le résultat de cette analyse est enregistré dans la session de l'utilisateur, il est donc possible d'ajuster les portlets ou leur gabarit sans relancer une analyse.

Analyse ponctuelle
Note: L'interface d'analyse ponctuelle indique la prochaine analyse automatique.
2.2.2 Enregistrement d'un rapport
Une fois l'analyse effectuée, il est possible d'enregistrer le rapport. Si l'option "Tous les espaces de travail" est activée, un rapport sera généré pour chaque espace de travail.

Liste des rapports générés
2.3 Paramétrage du Modèle de Rapport
Paramétrer le modèle de rapport par défaut pour que l'analyse s'effectue tous les mois. La section 1.1 décrit les différents champs à modifier.
3. Fonctionnement
Cette section présente une vision technique de l'analyse des statistiques. Elle explique quelles sont les informations stockées dans les fichiers des accès et comment ces informations sont exploitées. En fin de section, le développement d'une nouvelle portlet de statistiques est expliqué pas à pas.
3.1 Fichier des accès
3.1.1 Ecriture des accès
Le fichier admin/stat/doStat.jsp est chargé d'enregistrer les accès. Ce fichier est inclus par doEmptyHeader.jsp qui lui même est inclus par toutes les JSP. doStat.jsp fait appel à la méthode appendStatEntry() de la classe du StatManager. Cette méthode se charge de récupérer les attributs et paramètres de la requête pour enregistrer l'accès.
3.1.2 Paramètres stockés
Voici la liste des informations écrites pour chaque ligne des fichier accès.
| Variable JCMS | Attribut XML | Description ou Méthode utilisée | Exemple |
| STAT_IPADDRESS | ip | request.getRemoteAddr() + résolution DNS si nécessaire | 127.0.0.1 |
| STAT_DATESTART | startDate | Entier long représentant la date de début de la requête | 1151564783223 |
| STAT_DATEEND | endDate | Entier long représentant la date de fin de la requête | 1151564798174 |
| STAT_SERVERPORT | port | request.getServerPort() | 8080 |
| STAT_URID | urid | channel.getUrid() | j |
| STAT_METHODE | method | request.getMethod() | GET |
| STAT_REFERER | referer | request.getHeader("REFERER") | http://127.0.0.1:8080/index.jsp |
| STAT_SERVERNAME | serverName | request.getServerName() | 127.0.0.1 |
| STAT_URI | uri | request.getRequestURI() | /display.jsp |
| STAT_QUERYSTRING | qs | request.getQueryString() | id=j_5 |
| STAT_SESSIONID | sessionId | request.getSession(true).getId() | aPzLktRJLvF8 |
| STAT_LOCALE | locale | context.getUserLang() +"_"+ request.getLocale().getCountry() | fr_fr |
| STAT_USERAGENT | userAgent | request.getHeader("USER-AGENT") | Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4 |
| STAT_DATA | id | channel.getData(request.getParameter("id")) | j_5 |
| STAT_DATA_TYPE | type | Nom complet de la classe pour l'objet de type data représenté par le paramètre id | com.jalios.jcms.Category |
| STAT_PUBLICATION | pub | context.getPublication() | c_1234 |
| STAT_MEMBER | mid | context.getLoggedMember() | j_2 |
| STAT_WORKSPACE | workspace | context.getWorkspace() | j_4 |
| STAT_GROUPS | gids | loggedMember.getGroups() | j_3|j_4 |
| STAT_CURRENTCAT | ccat | context.getCurrentCategory() | j_5 |
| STAT_PORTALCAT | pcat | context.getCurrentCategory() | c_1000 |
| STAT_CTXTCAT | ctxtcat | context.getCtxCategories() | c_1236|c_1237 |
| STAT_AUDIENCEMENT | audiencement | loggedMember.getReadCategorySet() | c_1234|c_1235 |
| STAT_PORTAL | portal | context.getPortal() | j_12 |
| STAT_ZONE | zone | request.getAttribute(StatEntry.STAT_ZONE) | "Admin","Work","Public" |
| STAT_MEMO | memo | request.getAttribute(StatEntry.STAT_MEMO) | "" |
| STAT_NAME | name | request.getAttribute("title") | "Title of the page" |
| Custom Values | Custom Values | request.getAttribute("custom") Attention ! Cet attribut contient une Map attribut/valeur à rajouter aux statistiques |
3.1.3 Attributs de requête
L'attribut de requête "zone" permet de définir des zones à analyser dans le site. La plupart des portlets du modèle de rapport par défaut travaille uniquement sur la zone "Public" (Front office).
L'attribut de requête "memo" permet de rajouter une information aux lignes de statistiques. Cette information pourra être exploitée lors de l'analyse.
L'attribut de requête "custom" permet de rajouter une Map d'information aux lignes de statistiques. Les clés de la Map sont les attributs XML et les valeurs sont les valeurs XML. Ces informations pourront être exploitées lors de l'analyse.
3.2 Analyse
3.2.1 Du déclenchement au parsing des stats
|
Mécanique de l'analyse de statistiques |
La classe StatManager est le point d'entrée de l'analyse et du rendu des statistiques. La classe StatAnalyser est instanciée lors d'une analyse par le StaManager. Elle parse le flux des fichiers de statistiques. La classe StatHandler reçoit les lignes de statistiques et les transforme en objet StatEntry. Ces objets sont ensuite passés à une arborescence de StaListener. La classe StatListener est chargée de valider puis de stocker l'information. Deux méthodes sont appelées validateEntry() et processEntry(). Le stockage est effectué en appelant la méthode updateWorkspaceMap() |
3.2.2 API des listeners de stat
StatListener
L'interface StatListener représente un listener de Statistiques.
AbstractStatFieldListener
La classe AbstractStatFieldListener implémente StatListener et propose des méthodes utilitaires pour faciliter la validation et le traitement des statistiques:
- validateEntry
La méthode validateEntry(StatEntry entry) valide qu'un objet StatEntry correspond aux critères d'analyse de la portlet. Si la validation est fausse alors le reste du traitement n'est pas effectué pour cette ligne de statistiques. - processEntry
La méthode processEntry(StatEntry entry, Object workspace, Map workspaceMap) permet de sauvegarder les informations correspondant aux critères d'analyse de la portlet pour l'espace de travail donné. Cette sauvegarde peut se faire en appelant la méthodeupdateWorkspaceMap(). Pour obtenir les informations à traiter, il faut appeler la méthode getCurrentObjSet(). - getCurrentObjSet
La méthode getCurrentObjSet(String mapKey) retourne la collection d'objets en cours de traitement. Elle est très utile pour obtenir les objets traités par des sous listeners. Par exemple, pour analyser les articles imprimés, il faut brancher un ContentListener et un URLListener dans un nouveau AbstractStatFieldListener, puis appeler la méthode getCurrentObjSet() sur chacun des listeners pour obtenir l'URL et le contenu. - updateWorkspaceMap
La méthode updateWorkspaceMap(...) permet la mise à jour d'une métrique pour un espace de travail donné. Elle est en général appelée par la méthode processEntry(). Elle facilite l'enregistrement des données. Les données sont sauvegardées dans une arborescence d'ObjectIntTreeMap:

Arborescence des ObjectIntTreeMaps
La classe ObjectIntTreeMap représente une Map (de type TreeMap) dont les valeurs sont des entiers. Plusieurs méthodes permettent de manipuler ces données dans des arborescences d'ObjectIntTreeMap.
Certains listeners utilisent les "heures du jour", "les jours de la semaine", ou "les mois de l'année" en tant que données analysées.
D'autres listeners croisent 2 données. Dans ce cas, à la place du "compteur" il y a un pointeur vers une ObjectIntTreeMap supplémentaire ayant pour clef la deuxième donnée et comme valeur un compteur.
AbstractStatMultiListener
La classe AbstractStatMultiListener hérite de AbstractStatFieldListener et propose 2 nouvelles méthodes:
- addListener().
- removeListener().
Cette classe permet de fabriquer des listeners composés de plusieurs sous listeners. Par exemple, pour analyser les pages du "Portail A" affichant un "Article" on utilisera un nouveau AbstractStatMultiListener composé d'un PortalListener et d'un ContentListener.
Il existe beaucoup de classes dérivant d'AbstractStatMultiListener. La majeure partie de ces classes combinent des instances de StatFieldListener puis effectuent de petits traitements. Elles sont extrêmement simples et possèdent un constructeur par défaut pour être invoquées par la mécanique des statistiques.
Le constructeur de la classe AbstractStatMultiListener initialise jusqu'a 3 listeners afin de compter la répartition horaire, hebdomadaire et mensuelle (suivant la configuration de la portlet).
StatFieldListener
La classe StatFieldListener hérite de AbstractStatMultiListener. Elle valide et sauvegarde, de manière générique, un attribut de statistiques. La méthode getCurrentObjSet() permet à un AbstractStatMultiListener de récupérer le ou les champs qui viennent d'être validés. Elle est utilisée pour effectuer un traitement sur les objets.
3.2.3 Développement de listeners spécifiques
Les listeners spécifiques doivent être déclarés dans les portlets qui les utilisent. Il faut modifier le champ metrics de la PortletStatMetrics afin de rajouter le listener et son libellé.

Editeur de Type - Champs Metrics
3.2.4 Modifier le comportement cross listeners
La classe StatPolicy propose un certain nombre de "hook" permettant la modification du comportement des Portlets de statistiques. C'est un moyen simple de changer le comportement de l'analyse.
3.3 Affichage
3.3.1 Gabarit d'affichage d'un rapport
Le gabarit d'affichage d'un rapport est semblable à celui d'une PortletCollection (Ligne, Colonne). Une première étape consiste à itérer sur la liste des portlets, de les afficher et stocker leur rendu dans un buffer. Une seconde étape consiste à itérer sur ces buffers pour présenter les portlets en tableau ou en onglet.
Le gabarit types/PortletStatReport/doPortletStatTabReportFullDisplay.jsp est un bon point de départ pour développer un nouveau gabarit de rapport.
3.3.2 Gabarit d'affichage d'une portlet
Le gabarit d'affichage d'une PortletStatMetrics fonctionne de la même manière que toutes les autres portlets. Les données à afficher sont stockées en attribut de session. La JSP ../AbstractPortletStat/initStatParams.jsp permet la récupération du StatHandler, du StatListener et donc des données sauvegardées.
3.3.3 Le ChartTag et Beautifier
En général, les portlets présentent l'information sous la forme de tableaux ou de graphiques. Le ChartTag est un tag de JCMS qui présente des graphiques en HTML+CSS. Il est capable de présenter des données issues d'une arborescence d'ObjectIntTreeMap. C'est cette structure qui est utilisée par les statistiques.

Graphique du tag jalios:chart
Il est parfois nécessaire d'enrichir les données brutes. La classe Beautifier propose un mécanisme pour enrichir ces données et peut être passée en attribut du ChartTag afin d'améliorer les libellés des textes et légendes. Les listeners peuvent indiquer le beautifier ou le gabarit d'affichage à utiliser.
3.3.4 Générer plusieurs gabarits de rapports
La classe StatPolicy contient la méthode StatPolicy.checkGeneratedReports() qui permet d'enregistrer plusieurs rapports pour une même analyse. Par exemple pour générer un rapport HTML et XML. Elle prend en paramètre la liste des gabarits de rapports de statistiques à générer.
4. Exemples
4.1 Enrichissement des statistiques
Lorsqu'un serveur proxy est positionné en amont d'une application JCMS, toutes les adresses IP des requêtes émises sont celles du serveur. Le contenu des fichiers d'accès est donc faussé. Certains proxy, comme par exemple Squid, sauvegardent dans l'en-tête HTTP X-Forwarded-For l'adresse IP du client.
Pour cet exemple, on va donc enregistrer l'adresse IP du client socké dans X-Forwarded-For, développer un listener spécifique analysant des données à partir de fichier d'accès enrichies et présenter les résultats dans une portlet.
4.1.1 Ajout d'une information dans les fichiers des accès
Dans le JSP custom/jcms/doCustomHeader.jsp, on ecrit la valeur de l'en-tête X-Forwarded-For dans la Map custom.
<%
String ip = request.getHeader("X-Forwarded-For");
if (Util.notEmpty(ip)) {
Map statMap = (Map) request.getAttribute("custom");
if (statMap == null){
statMap = new TreeMap();
request.setAttribute("custom", statMap);
}
statMap.put("X-Forwarded-For", ip);
}
%>
Puis vérifier que les données sont écritent dans le fichier statistiques:
<stat ip="127.0.0.1" ... X-Forwarded-For="192.168.0.100" />
4.1.2 Création d'un listener dédié
Créer une classe qui hérite de la classe AbstractStatMultiListener. Créer et brancher un StatFieldListener sur les champs X-Forwarded-For.
public class ProxyListener extends AbstractStatMultiListener{
protected StatFieldListener proxyListener = null;
public ProxyListener(){
super(ALL_AREA);
// Create listeners
proxyListener = new StatFieldListener(ALL_AREA, "X-Forwarded-For", "Entry", true, null);
addListener(proxyListener);
}
}
Surcharger la méthode processEntry() pour récupérer les données validées par le listener. Enfin sauvegarder ces données avec la méthode updateWorkspaceMap().
public void processEntry(StatEntry entry, Object workspace, Map workspaceMap){
super.processEntry(entry,workspace,workspaceMap);
// Get validated values
SortedSet proxySet = proxyListener.getCurrentObjSet("entry");
if (Util.isEmpty(proxySet)){
return
}
// Backup metrics
String proxy = (String)proxySet.first();
updateWorkspaceMap(workspace , "Entry" , proxy, workspaceMap);
}
Déclarer le listener dans la PortletStatMetrics en modifiant le champ metrics comme expliqué dans la section 3.2
4.1.3 Création d'une portlet d'affichage
Editer le rapport standard et modifier l'une des portlets afin d'utiliser ce nouveau listener. Les prochains rapports générés afficheront la répartition avec les véritables IP.
4.2 Développement de la PortletStatDualMetrics
L'objectif de cet exercice est le développement d'une nouvelle portlet de statistiques. Les PortletStatMetrics analysent et présentent un type d'information. Ce développement permettra le recoupement de 2 types d'information. Par exemple, pour analyser les pages vues par les groupes.Cette portlet est desormais fournit en standard dans JCMS 5.6 et son code est accessible.
Liste des étapes:
- Créer une Portlet héritant de PortletStatMetrics (avec des champs supplémentaires) ;
- Développer et intégrer un listener spécifique ;
- Modifier le gabarit d'affichage.
Un des champs supplémentaires de la portlet doit contenir une liste des métriques à croiser. Ainsi la portlet référencera 2 métriques. Le listener spécifique va récupérer le listener standard associé à la première métrique, et créer le second. Puis il va modifier le mécanisme de sauvegarde pour enregistrer une métrique en fonction d'une autre. Le ChartTag sait présenter une information en fonction d'une autre. Le gabarit d'affichage sera ajusté en conséquence.
4.2.1 Création d'une Portlet spécifique
Créer une portlet PortletStatDualMetrics qui hérite de PortletStatMetrics. Ajouter un champ énuméré Metrique croisée permettant à l'utilisateur de choisir une deuxième métrique à analyser. Le contenu de ce champ correspond au champ Metrique de la PortletStatMetrics.

Création d'un type PortletStatDualMetrics avec un champ énuméré "Métrique croisée"
4.2.2 Création d'un listener spécifique
Créer un listener spécifique StatCrossingListener prenant en paramètre les 2 listeners de la portlet. Ce listener doit hériter de la classe AbstractStatMultiListener.
public StatCrossingListener(AbstractStatFieldListener listener1, AbstractStatFieldListener listener2) {
super(ALL_AREA);
this.listener1 = listener1;
this.listener2 = listener2;
}
Pour initialiser le listener il faut :
- Ajouter les listeners (1 et 2) passés en paramètre
- Affiner les autres listener enregistrés avec le
listener2(par exemple, la répartition horaire, hebdomadaire, ...)
public void init(PortletStat portlet, PortalElement report) {
addListener(listener1);
addListener(listener2);
super.init(portlet, report);
// Refine all other registred listener by listener 2;
for (Iterator it = listeners.iterator(); it.hasNext();) {
AbstractStatFieldListener listener = (AbstractStatFieldListener) it.next();
if (listener instanceof StatDateTimeListener){
StatDateTimeListener sdtl = (StatDateTimeListener) listener;
sdtl.setRefineListener(listener2);
sdtl.setRefineListenerKey("Entry");
}
}
}
Il n'est pas nécessaire d'implémenter la méthode validateEntry(). Les listeners 1 et 2 ajoutés vont automatiquement être validés par la méthode de la classe AbstractStatMultiListener.
Pour implémenter la méthode processEntry(), itérer sur les données validées par les listeners 1 et 2 pour mettre à jour la Map de données. Le travail s'effectue sur des Set car il peut y avoir plusieurs données analysées pour une ligne de statistiques. C'est le cas pour les groupes du membre.
public void processEntry(StatEntry entry, Object workspace, Map workspaceMap){
SortedSet curObjs1 = listener1.getCurrentObjSet("Entry");
SortedSet curObjs2 = listener2.getCurrentObjSet("Entry");
if (Util.isEmpty(curObjs1)){
return;
}
if (Util.isEmpty(curObjs2)){
return;
}
// Work on listener1 and listener2
for (Iterator it1 = curObjs1.iterator(); it1.hasNext();) {
Object itObj1 = (Object) it1.next();
for (Iterator it2 = curObjs2.iterator(); it2.hasNext();) {
Object itObj2 = (Object) it2.next();
updateWorkspaceMap(workspace, "Entry", itObj1, itObj2, workspaceMap);
}
}
// Do super implementation without listener1 and listener2
super.processEntry(entry,workspace,workspaceMap,skipListener);
}
4.2.3 Intégration du listener dans la mécanique des stats
Utiliser le hook proposé par la classe StatPolicy pour brancher le listener sur toutes les PortletStatDualMetrics. La méthode checkCreateStatListener() permet de fournir un listener spécifique pour une portlet donnée.
public static StatListener checkCreateStatListener(PortletStat portlet, PortalElement report, StatListener listener){
if (portlet instanceof generated.PortletStatDualMetrics){
generated.PortletStatDualMetrics psdm = (generated.PortletStatDualMetrics) portlet;
AbstractStatFieldListener listener1 = (AbstractStatFieldListener) listener;
AbstractStatFieldListener listener2 = (AbstractStatFieldListener) StatManager.createStatListener(portlet,report,psdm.getCrossingMetrics());
StatListener crossingListener = new StatCrossingListener(listener1,listener2);
return crossingListener;
}
return null;
}
4.2.4 Création d'un gabarit spécifique
Le listener spécifique StatCrossingListener est positionné pour la portlet PortletStatDualMetrics. Ce listener est capable d'analyser des données qu'il est maintenant nécessaire de présenter. Pour cela modifier le gabarit d'affichage fulldisplay :
<%@ include file='/jcore/doInitPage.jsp' %> <%@ include file='/jcore/portal/doPortletParams.jsp' %> <% generated.AbstractPortletStat box = (generated.AbstractPortletStat) portlet; %> <H1> <%= glp(box.getDisplayTitle(userLang)) %></H1> <%@ include file='../AbstractPortletStat/initStatParams.jsp' %> <% PortletStatMetrics plm = (PortletStatMetrics) box; %> <%@ include file='../AbstractPortletStat/displayAverage.jsp' %> <%@ include file='../AbstractPortletStat/displayTopChart.jsp' %> <%@ include file='../AbstractPortletStat/displayDateTimeChart.jsp' %>
Le fichier initStatParams.jsp récupère les données analysées pour la portlet. Une variable wsMap est positionnée avec ces données. Les fichiers displayAverage.jsp, displayTopChart.jsp et displayDateTimeChart.jsp présentent ces données.
<% ObjectIntTreeMap objMap = (ObjectIntTreeMap)wsMap.get("Entry");%>
<jalios:if predicate='<%= Util.notEmpty(objMap)%>'>
<%
com.jalios.util.Beautifier beautifier = listener.getBeautifier();
com.jalios.jtaglib.ChartTagBeautifier chartBeautifier = (beautifier instanceof com.jalios.jtaglib.ChartTagBeautifier) ? (com.jalios.jtaglib.ChartTagBeautifier)beautifier : new com.jalios.jtaglib.ChartTagBeautifier(beautifier);
%>
<jalios:chart dataMap='<%= objMap %>'
display='<%= "hchart" %>'
isPercent='<%= false %>'
sort='<%= "greater" %>'
max='<%= plm.getTopTen() %>'
fixHLengthWidth='<%= 15 %>'
colorFirst='<%= 0 %>'
colorRotate='<%= 2 %>'
locale='<%= userLocale %>'
unit='<%= glp("ui.statreport.lbl.hits") %>'
beautifier='<%= chartBeautifier %>'
mixedChart='<%= true %>'
/>
<br/><span style="font: bold 11px Arial, Helvetica, Sans-Serif; color: #880000;"><%= glp("ui.statreport.lbl.totalactivity",objMap.getSum()) %></span>
</jalios:if>
Ce gabarit d'affichage récupère les données analysées sous la forme d'un ObjectIntTreeMap (une arborescence). Puis passe ces données au tag <jalios:chart> qui est capable de présenter sous la forme d'un histogramme les ObjectIntTreeMap.
Français



