Publié par

Il y a 11 ans -

Temps de lecture 4 minutes

Prenez le contrôle de Confluence avec Swizzle

Je vais vous révéler un secret à propos de notre célèbre Revue de Presse ! Elle est élaborée collectivement par l’ensemble des consultants de Xebia sous Confluence avant d’être publiée sur notre blog. L’utilisation d’un wiki permet de suivre facilement les différentes modifications (contribution, corrections, commentaires). Une fois celle-ci terminée, la page est archivée et une autre est créée, vide, afin de recevoir la prochaine version. La fin de l’année arrive, c’est l’heure de faire les statistiques 2008. L’une des questions que je me pose est « Quelle est la proportion des entrées de la revue de presse entre les différentes catégories (Actualité éditeurs / SSII, Agilité, RIA, SOA, …) ? »

Solution N°1 : Ouvrir dans le navigateur toutes les pages ‘Revue de Presse’ une par une et compter les entrées. Une revue de presses par semaine, 52 semaines … non

Solution N°2 : Utiliser une API. En effet Confluence expose ses principales fonctions par web services. Voici le wsdl. Plus de 7300 lignes, 238 opérations, 50 types. À ce moment-là, j’étais presque prêt à repasser à la solution N°1 quand je suis tombé au détour d’une recherche Google (Google est notre ami à tous !), sur le projet Swizzle…

Swizzle est un wrapper Java autour de l’api XML-RPC proposée par Confluence.

Installation

Rapide ! Swizzle est disponible dans le repository Maven


    org.codehaus.swizzle
    swizzle-confluence
    1.1

Principe

  • Une seule classe, org.codehaus.swizzle.confluence.Confluence, permet d’accéder aux différents services.
  • Un ensemble de POJO qui servent de paramètres d’entrée et de retour. Exemple : org.codehaus.swizzle.confluence.PageSummary.

Se connecter

String endpoint = "https://the.confluence.of.xebia.com/confluence/rpc/xmlrpc";
confluence = new Confluence(endpoint);
System.out.println("Connected to " + endpoint);

String username = "bmoussaud";
String password = "tiger";
confluence.login(username, password);

Si vous êtes dérrière un proxy, initialiser les variables d’environnement suivantes:

System.getProperties().put("proxySet",  "true");
System.getProperties().put("proxyHost", "17.240.34.194");
System.getProperties().put("proxyPort", "3128");

Retrouver une page

Les Revues de Presse sont archivées, comme l’ensemble du blog, par trimestre. Il faut donc :

  1. Retrouver la page correspondant à ce trimestre.
  2. Récupérer les pages filles.
  3. Filtrer pour ne garder que les articles « Revue de Presse ».
public List getRevuesDePresse(String quarter) throws Exception {
	List results = new ArrayList();
	Page page = confluence.getPage("Espace Xebia France", quarter); 	//#1
	List children = confluence.getChildren(page.getId());	//#2
	for (PageSummary pageSummary : children) {
		if (pageSummary.getTitle().contains(REVUE_DE_PRESSE)) {		//#3
			results.add(pageSummary);
		}
	}
	return results;
}
  • Une page est identifiée par son Id représenté par un type java.lang.String.
  • La classe PageSummary contient les informations minimales d’une page : Id, ParentId, Title, URL.
  • La classe Page contient toutes les informations de la page, y compris son contenu.

Analyser le contenu d’une page

La Revue de Presse contient 6 catégories principales (Actualité éditeurs / SSII, Agilité, RIA, SOA, …). Elles sont hiérarchisées en niveau 3 (syntaxe wiki h3.). Les différentes entrées de la revue de presse sont de niveau 4 (syntaxe wiki h4.). Il faut donc :

  1. Récupérer le contenu de la page.
  2. Filtrer les titres de niveau 3 et 4.
  3. Effectuer le comptage.
public Map countArticleByCategory(String pageId)
		throws Exception {
	String content = confluence.getPage(pageId).getContent();	// #1

	String currentCategory = null;
	String currentEntry = null;

	Pattern h3h4 = Pattern.compile("(^h3|^h4)
.(.*)",
					 Pattern.MULTILINE);		// #2

	Matcher matcher = h3h4.matcher(content);

	Map categories = newMap();
	while (matcher.find()) {
		//entrées vides
		if (matcher.group().contains("...")
				|| matcher.group().contains(".."))
			continue;
		// niveau 3
		if ("h3".equals(matcher.group(1))) {			// #2
			currentCategory = matcher.group(2).trim();
			categories.put(currentCategory, 0);
			continue;
		}
		// niveau 4
		if ("h4".equals(matcher.group(1))) {			// #2
			currentEntry = matcher.group(2);
			if (currentCategory != null
					&& categories.containsKey(currentCategory)) {
				int c = categories.get(currentCategory);
				categories.put(currentCategory, ++c);	// #3
			}
		}
	}
	return categories;
}

Conclusion

Il suffit maintenant :

  • D’assembler les deux méthodes.
  • De dumper les informations au format CSV.
  • D’ouvrir Excel.
  • De construire un tableau croisé dynamique.

et vous n’aurez pas les résultats !!

Pour en revenir à Swizzle / Confluence : l’encapsulation proposée est correcte et performante. Le seul point négatif : toutes les méthodes de la classe Confluence lancent des java.lang.Exceptions, non typées. Elles sont dans l’ensemble le résultat d’un comportement de type Runtime. J’aurais donc préféré une signature finissant par throws RuntimeException.

L’api permet également :

  • D’obtenir des informations sur l’historique des pages et des contributeurs, les commentaires, l’état de la page (nombre de verrous, supprimées, …).
  • De créer, déplacer et détruire des pages et des espaces.

Exemple : archivage des revues de presse :

void run(String newParent) throws Exception {
	System.out.println("Archivage des Revues de Presse dans "+newParent);
	myConfluence = new MyConfluence();
	List draftedRevuesDePresse = myConfluence.getDraftedRevuesDePresse();
	int count = 0;
	for (PageSummary pageSummary : draftedRevuesDePresse) {
		if (pageSummary.getTitle().startsWith("DRAFT"))
			continue;	
		myConfluence.moveTo(pageSummary,newParent);
	}
	System.out.println("Total "+count);
}
//....

public void moveTo(PageSummary pageSummary, String newParent)
		throws Exception {
	Page targetPage = confluence.getPage("XF", newParent);
	Page page = confluence.getPage(pageSummary.getId());
	System.out.println("Change Parent from '"
			+ confluence.getPage(page.getParentId()).getTitle() + "' to '"
			+ targetPage.getTitle() + "'");
	page.setParentId(targetPage.getId());		//Changement de Parent
	confluence.storePage(page);			//Applique les modifications
}

Swizzle propose également un wrapper sur les API exposées par Jira.
Note: Swizzle ne fonctionne que si l’option « API à distance (XML-RPC & SOAP) » est activée.

Publié par

Commentaire

3 réponses pour " Prenez le contrôle de Confluence avec Swizzle "

  1. Publié par , Il y a 11 ans

    WSDL qui pousse à faire du JAX-RPC? Pouah!
    A quand une interface JAX-RS?

  2. Publié par , Il y a 11 ans

    Et le résultat des statistiques ?

  3. Publié par , Il y a 11 ans

    A quand un bêtisier 2008 sur les perles de la programmation comme l’an dernier ?

    Nicolas

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.