mardi 1 décembre 2015

Construire élégamment un arbre

C'est une opération classique, banale, et en même temps souvent très mal faite.
Les arbres d'objets sont courants : Swing, Html, rapports, Json. Mais en Java, ils sont souvent construits linéairement parce que Java est un langage impératif. Le résultat est peu lisible, source d'erreur dû aux confusions entre noeuds, et surtout pénible à maintenir.

Kotlin est aussi un langage impératif, mais il propose une petite astuce en associant les extensions de types et le passage de fonction en paramètre.

Je vous propose de créer un arbre de données pour Json, utile par exemple dans une servlet.

Une extension de type c'est ajouter une fonction sur un type déjà existant. Par exemple, créons une fonction pour récupérer le second élément d'une liste :
fun List<*>.second() = this.get(1)
val l = listOf("un", "deux", "trois")
println (l.second())
Ce code affiche "deux".

Le passage de fonction en paramètre est classique et reprend la syntaxe de Java 8.

L'astuce est de définir une fonction qui créé une HashMap et de lui passer en argument une extension de Map :
fun sub(init: MutableMap<String, Any>.() -> Unit): Map<String, Any> {
    val res = java.util.HashMap<String, Any>()
    res.init()
    return res
}

La génération de l'arbre est devenu arborescente, bien plus lisible et fiable :
val a = sub {
   put ("nom", "Abraham")
   put ("age", 70)
   put ("enfants", listOf(
      sub () {
         put ("nom", "Homer")
         put ("age", 40)
         put ("enfants", listOf(
            sub() {
               put ("nom", "Bart")
               put ("age", 10)
            },
            sub() {
               put ("nom", "Lisa")
               put ("age", 8)
            },
            sub() {
               put ("nom", "Lisa")
               put ("age", 1)
            }
         ))
      }
   ))
}
println(org.json.simple.JSONObject.toJSONString(a))

Ce code affiche :
{"enfants":[{"enfants":[{"nom":"Bart","age":10},{"nom":"Lisa","age":8},{"nom":"Maggie","age":1}],"nom":"Homer","age":40}],"nom":"Abraham","age":70}

La génération reste assez verbeuse parce que générique à tout document Json. Elle pourrait-être simplifiée en fonction des données à stocker dans le document.

Notez enfin que les listOf peuvent être remplacée par des boucles ou tout autre code de génération de données.

Aucun commentaire:

Enregistrer un commentaire