Dernière modification : Dec 08 , 2024

Introduction

Vous devez construire un plugin Gradle en Groovy qui permette de générer des images à partir d'un répertoire de sources PlantUML.

Si vous ne connaissez pas PlantUML, vous pouvez découvrir ce générateur de diagrammes : PlantUML

Etape 1

Cloner le projet à l'adresse Squelette de plugin

Etape 2

Le projet contient les répertoires suivants :

 src/plantuml <=== where the plant UML diagrams are stored
 lib/plantuml-1.2022.5.jar
 build.gradle <== basic gradle file

Etape 3 : "créer la tache listPML"

Objectif de cette étape : créer une tâche qui liste les ressources PlantUML disponibles dans l'application

  • Créer la tâche dans le script build.gradle
  • Extraire la tâche dans une classe Groovy codée dans le script build.gradle
  • Externaliser les variables dans le projet

Etape 4 : créer la tâche "createOutputFolder"

Objectif de cette étape : créer une tâche qui liste les ressources PlantUML disponibles dans l'application

  • Créer la tâche dans le script build.gradle
  • Extraire la tâche dans une classe Groovy codée dans le script build.gradle
  • Vérifier que la tâche s'exécute tout le temps même quand le répertoire existe deja
  • Utiliser la notion de @OutputDirectory

Etape 5 : créer la tâche "createOutputFolder"

Objectif de cette étape : créer une tâche qui compile les ressources plantuml

  • Créer la tâche dans le script build.gradle
  • Extraire la tâche dans une classe Groovy codée dans le script build.gradle
  • Définir les entrées et les sorties de la tache

Attention les linputs et les outputs doîvent être initialisés

  • Implémenter la fonction

Vérifier ce qui se produit quand on exécute deux fois la fonction de génération Vérifier ce qui se produit quand un diagramme est modifié

Etape 6 : créer une tâche de zip des schémas

Objectif de cette étape : créer une tâche qui crée une archive avec les diagrammes.

  • Créer la tâche dans le script build.gradle
  • Extraire la tâche dans une classe Groovy codée dans le script build.gradle
  • Ajouter les dépendances a la tache buildPlantUML et createOutputFolder

Etape 7 : Déplacer le code dans buildSrc/

Nous allons déplacer tout le code dans buildSrc pour nettoyer le projet et préparer le plugin.

Rappel : le code source doit se trouver dans buildSrc/main/groovy

Si vous n'avez pas réussi la création de la tâche 6, utilisez ce code :

/**
 * Available tasks for the project
 *
 * <ul>
 *     <li>createOutputFolder</li> : task to create the output folder
 *     <li>listPML : list the available plant uml in the </li>
 *     <li>findOutdatedPML : list the PML that requires an update. </li>
 *     <li>buildPlantuml : build all the plantUml files</li>
 *     <li>plantUmlTest : test PlantUml installation</li>*
 *     <li>plantUmlGui : launch PlantUML Gui</li>*
 * </ul>
 */
 // build.gradle
plugins {
    id("application")
}


class ListPmlTask extends DefaultTask {
    @OutputFiles
    def getPlantFiles() {
        def plantFiles = project.fileTree('src/plantuml')
        plantFiles.include "**/*.puml"
        plantFiles.builtBy "listPML"
        return plantFiles
    }

    @TaskAction
    def listResources() {
        println "Liste des ressources PlantUML disponibles :"
        
        getPlantFiles().visit { FileVisitDetails details ->
            println details.relativePath
        }
    }
}

class CreateOutputFolderTask extends DefaultTask {
    @OutputDirectory
    def outputDir = project.file(project.buildDir.path + '/outputFolder')


    @TaskAction
    def creationDuRepertoireDeSortie() {
        //outputs.dir 'build/outputFolder'
        println "Création du répertoire de sortie"
        outputDir.mkdirs()
    }
}


abstract class PlantUMLCompilationTask extends DefaultTask {
    @Input
    abstract Property<FileTree> getPlantFiles()

    @Input 
    abstract Property<File> getOutputFolder()

    @TaskAction
    def generationSchemas() {
        
        println "Compilation des ressources PlantUML"
        // Implémenter la logique de compilation ici
        // Example: Generate PlantUML diagram from Groovy script
        def planTree = plantFiles.get()
        planTree.visit { pml -> 
            
            def plantUMLJarPath = project.projectDir.absolutePath +"/lib/plantuml-1.2022.5.jar"
            def inputPlantUMLFile = pml.file.absolutePath
            def outputImageFile = project.file(outputFolder.get().absolutePath + '/' + pml.name +".png")

            // Execute PlantUML command
            def command = "java -jar $plantUMLJarPath $inputPlantUMLFile -tpng -o $outputImageFile"
            println command
            def process = command.execute()
            process.waitFor()

            // Check if the command was successful
            if (process.exitValue() == 0) {
                println "PlantUML diagram generated successfully at: $outputImageFile"
            } else {
                println "Error generating PlantUML diagram. Check the PlantUML command and try again."
                println "Exit code: ${process.exitValue()}"
            }
        }
    }
}

tasks.register("listPML", ListPmlTask)
tasks.register("createOutputFolder", CreateOutputFolderTask)
tasks.register("compilePlantUML", PlantUMLCompilationTask) {
    dependsOn "createOutputFolder", "listPML"
    plantFiles = tasks.listPML.plantFiles
    outputFolder = tasks.createOutputFolder.outputDir
}


// build.gradle

task zipDiagrams(type: Zip) {
    dependsOn 'compilePlantUML', 'createOutputFolder'
    from 'build/outputFolder'
    archiveFileName = 'diagrams.zip'
    destinationDirectory = file('build')
}

tasks.named('build').get().dependsOn zipDiagrams

Etape 8 : Créer le plugin PlantUMLPlugin

En vous basant sur la documentation de Gradle, créez le plugin et déclarez les tâches dedans.

Créez une extension pour stocker la configuration.

Etape 9 : Créer deux sous projets

Créer un sous-projet plantuml dans le projet actuel et un projet no-plantuml.

Ce projet plantuml doit contenir les schémas plantuml, l'autre projet ne contient rien.

Lancer la tâche de génération des diagrammes, que se passe t'il au niveau des sous-projets ?

Utilisez l'instruction allprojects ou subprojects pour régler le problème.

Etape 10 : Optimisation

La tâche de génération plante quand un sous-projet ne contient pas de sources.

Tentez de résoudre le problème en utilisant onlyIf.

Améliorer la situation en utilisant une Input correcte et l'annotation :


    @SkipWhenEmpty
    @InputDirectory
    File contentDir

Etape 11 : Intégration

Utiliser la notion de configuration et de sourcesSet pour réupérer les répertoires et les schémas à analyser.

Solutions / Aide

Voici un exemple non optimisé qui peut être utilisé comme guide pour la suite des exercises :

/**
 * Available tasks for the project
 *
 * <ul>
 *     <li>createOutputFolder</li> : task to create the output folder
 *     <li>listPML : list the available plant uml in the </li>
 *     <li>findOutdatedPML : list the PML that requires an update. </li>
 *     <li>buildPlantuml : build all the plantUml files</li>
 *     <li>plantUmlTest : test PlantUml installation</li>*
 *     <li>plantUmlGui : launch PlantUML Gui</li>*
 * </ul>
 */
 // build.gradle
plugins {
    id("application")
}

task listPML {
    doLast {
        println "Liste des ressources PlantUML disponibles :"
        fileTree('src/plantuml').visit { FileVisitDetails details ->
            println details.relativePath
        }
    }
}


// build.gradle

task createOutputFolder {
    outputs.dir 'build/outputFolder'

    doLast {
        println "Création du répertoire de sortie"
        file('build/outputFolder').mkdirs()
    }
}

// build.gradle

task compilePlantUML {
    inputs.dir 'src/plantuml'
    outputs.dir 'build/outputFolder'

    doLast {
        println "Compilation des ressources PlantUML"
        // Implémenter la logique de compilation ici
    }
}

// build.gradle

task zipDiagrams(type: Zip) {
    dependsOn 'compilePlantUML', 'createOutputFolder'
    from 'build/outputFolder'
    archiveFileName = 'diagrams.zip'
    destinationDirectory = file('build')
}

tasks.named('build').get().dependsOn zipDiagrams

References