Guide des Directives Bidji pour Templates FreeMarker
Introduction
Ce document décrit toutes les directives disponibles pour écrire des templates de génération de code avec BidjicTask. Les directives simplifient l’accès aux métadonnées des modèles Bidjim (entités, propriétés, relations) dans vos templates FreeMarker.
Date de création : 2026-02-06
Basé sur : BidjicTask.freemarkerize() - analyse complète du code source
Table des Matières
- Comment Utiliser ce Guide
- Syntaxe Générale
- Variables Disponibles
- Directives par Catégorie
- Exemples Complets
- Matrice d’Usage
- Pièges Courants
- Migration vers Nouvelle Syntaxe
Comment Utiliser ce Guide
Pour Commencer
- Lisez la section Syntaxe Générale pour comprendre les deux types de directives
- Consultez Variables Disponibles pour savoir quelles variables sont accessibles
- Parcourez les directives par catégorie pour trouver celle dont vous avez besoin
- Référez-vous aux Exemples Complets pour des cas d’usage concrets
Conventions
- 🟢 Active : Directive recommandée, stable
- 🟡 Utilisable : Directive fonctionnelle mais spécifique
- 🔴 Deprecated : À éviter, sera supprimée dans futures versions
- ⚠️ Attention : Nécessite précautions d’usage
Syntaxe Générale
Les directives Bidji utilisent deux syntaxes distinctes :
1. Syntaxe avec ? (Query/Fonction)
${entity?properties}
${entity?dataform_properties}
${property?type_or_string}
Usage : Appel de fonctions qui retournent des données calculées ou filtrées
2. Syntaxe avec .@ (Accès Attribut)
${entity.@name}
${entity.@package}
${property.@type}
Usage : Accès direct aux métadonnées de l’entité ou propriété
Variables Disponibles dans les Templates
Lorsque BidjicTask traite un template, il injecte automatiquement les variables suivantes :
| Variable | Type | Description | Exemple |
|---|---|---|---|
bidji |
Bidjim | Objet racine du modèle | ${bidji.entity} |
entity |
Entity | L’entité courante (depuis bidji.entity) |
${entity.@name} |
Model |
String | Nom du modèle (= nom fichier .bidjim) | ${Model} → “User” |
Package |
String | Package extrait du chemin du fichier | ${Package} → “com.myapp” |
Module |
String | Module extrait du chemin du fichier | ${Module} → “user” |
Model?api |
ModelHelper | Helper Java pour accès aux métadonnées | ${Model?api.get_entity_properties(entity)} |
Note : Les variables Package et Module sont extraites automatiquement du chemin du fichier .bidjim.
Exemple : com/myapp/user/User.bidjim → Package="com.myapp", Module="user", Model="User"
Directives par Catégorie
1. Application et Modèle
app?entities 🟢
Retourne la liste de toutes les entités de l’application.
Syntaxe :
${app?entities}
Retourne : List<Entity> - Liste des entités
Exemple :
[#foreach entity in app?entities]
- Entité : ${entity.@name}
[/#foreach]
Se transforme en : app.getEntities()
model?has_complex_types 🟢
Vérifie si le modèle utilise des types complexes (non primitifs).
Syntaxe :
${model?has_complex_types}
Retourne : boolean
Exemple :
[#if model?has_complex_types]
import java.util.*;
[/#if]
Se transforme en : Model?api.has_complex_types()
2. Entités - Propriétés
entity?properties 🟢
Retourne toutes les propriétés d’une entité.
Syntaxe :
${entity?properties}
Retourne : List<Map> - Liste de propriétés (chaque propriété est une Map avec @name, @type, etc.)
Exemple :
[#foreach property in entity?properties]
private ${property.@type} _${property.@name};
[/#foreach]
Se transforme en : Model?api.get_entity_properties(entity)
Usage typique : Génération de POJO complets, itération sur tous les champs
entity?native_properties 🟢
Retourne uniquement les propriétés de types primitifs (String, Integer, Boolean, etc.).
Syntaxe :
${entity?native_properties}
Retourne : List<Map> - Liste de propriétés natives
Exemple :
[#-- Générer uniquement les champs scalaires --]
[#foreach property in entity?native_properties]
private ${property.@type} ${property.@name};
[/#foreach]
Se transforme en : Model?api.get_native_properties(entity)
Différence avec entity?properties : Exclut les relations (1-N, N-N) et types complexes
entity?dataform_properties 🟢
Retourne les propriétés destinées aux formulaires de saisie.
Syntaxe :
${entity?dataform_properties}
Retourne : List<Map> - Liste de propriétés pour formulaires
Exemple :
<form>
[#foreach prop in entity?dataform_properties]
<label>${prop.@name}</label>
<input type="text" name="${prop.@name}" />
[/#foreach]
</form>
Se transforme en : Model?api.get_dataform_properties(entity)
Usage typique : Génération de formulaires HTML/JSP, écrans de création/édition
entity?datatable_properties 🟢
Retourne les propriétés destinées aux tableaux de données.
Syntaxe :
${entity?datatable_properties}
Retourne : List<Map> - Liste de propriétés pour tableaux
Exemple :
<table>
<thead>
[#foreach prop in entity?datatable_properties]
<th>${prop.@name}</th>
[/#foreach]
</thead>
</table>
Se transforme en : Model?api.get_datatable_properties(entity)
Usage typique : Génération de grilles de données, vues liste
entity?data_properties 🟢
Retourne les propriétés pour formulaires ET tableaux (union des deux).
Syntaxe :
${entity?data_properties}
Retourne : List<Map> - Liste de propriétés communes
Se transforme en : Model?api.get_data_properties(entity)
Usage typique : Génération de code qui traite à la fois formulaires et listes
3. Entités - Métadonnées
entity.@name 🟢
Nom de l’entité.
Syntaxe :
${entity.@name}
Retourne : String
Exemple :
public class ${entity.@name} {
// ...
}
Se transforme en : Model?api.get_entity_name(entity)
entity.@package 🟢
Package de l’entité.
Syntaxe :
${entity.@package}
Retourne : String
Exemple :
package com.mycompany.${entity.@package};
Se transforme en : Model?api.get_entity_package(entity)
entity.@module 🟢
Module de l’entité.
Syntaxe :
${entity.@module}
Retourne : String
Exemple :
// Module: ${entity.@module}
Se transforme en : Model?api.get_entity_module(entity)
entity.@icon 🟡
Icône associée à l’entité (pour interfaces utilisateur).
Syntaxe :
${entity.@icon}
Retourne : String - Nom de l’icône
Exemple :
<i class="icon-${entity.@icon}"></i>
Se transforme en : Model?api.get_entity_icon(entity)
entity.@taggable 🟡
Indique si l’entité est taggable.
Syntaxe :
${entity.@taggable}
Retourne : boolean
Se transforme en : Model?api.get_entity_taggable(entity)
entity.@delete 🟡
Indique si l’entité peut être supprimée.
Syntaxe :
${entity.@delete}
Retourne : boolean
Se transforme en : Model?api.get_entity_delete(entity)
entity.@default_sort 🟡
Champ de tri par défaut de l’entité.
Syntaxe :
${entity.@default_sort}
Retourne : String - Nom du champ
Exemple :
ORDER BY ${entity.@default_sort}
Se transforme en : entity.getDefaultSort() ⚠️ Appel direct, pas via ModelHelper
entity2.@name et entity2.@package 🟡
Identique à entity.@name et entity.@package mais pour une deuxième entité dans le contexte.
Usage : Lorsqu’on travaille avec des relations entre deux entités
Exemple :
[#assign target = Model?api.get_entity(relation.@type)]
// Relation: ${entity.@name} -> ${target.@name}
4. Entités - Interface Utilisateur
entity?detail_tabs 🟡
Retourne la liste des onglets pour la vue détail.
Syntaxe :
${entity?detail_tabs}
Retourne : List - Liste des onglets
Se transforme en : Model?api.get_detail_tabs(entity)
entity?has_detail_tabs 🟡
Vérifie si l’entité possède des onglets de détail.
Syntaxe :
${entity?has_detail_tabs}
Retourne : boolean
Exemple :
[#if entity?has_detail_tabs]
<div class="tabs">
[#foreach tab in entity?detail_tabs]
<div class="tab">${tab.name}</div>
[/#foreach]
</div>
[/#if]
Se transforme en : Model?api.has_detail_tabs(entity)
entity?first_datatable_tab 🟡
Retourne le premier onglet de type datatable.
Syntaxe :
${entity?first_datatable_tab}
Se transforme en : Model?api.first_datatable_tab(entity)
entity?has_filter_by_month 🟡
Vérifie si l’entité a un filtre par mois.
Syntaxe :
${entity?has_filter_by_month}
Retourne : boolean
Se transforme en : Model?api.has_filter_by_month(entity)
entity?is_monthly_table 🟡
Vérifie si l’entité utilise un widget de table mensuelle.
Syntaxe :
${entity?is_monthly_table}
Retourne : boolean
Se transforme en : Model?api.is_monthly_table(entity)
entity?has_table_footer 🟡
Vérifie si la table a un footer (totaux/agrégats).
Syntaxe :
${entity?has_table_footer}
Retourne : boolean
Se transforme en : Model?api.has_table_footer(entity)
5. Entités - Relations
entity?one_to_many_properties 🟢
Retourne les propriétés de type 1-to-many (collections).
Syntaxe :
${entity?one_to_many_properties}
Retourne : List<Map> - Liste des relations 1-N
Exemple :
[#foreach rel in entity?one_to_many_properties]
private List<${rel.@type}> ${rel.@name};
[/#foreach]
Se transforme en : Model?api.get_entity_one_to_many_properties(entity)
entity?many_to_many_properties 🟢
Retourne les propriétés de type many-to-many.
Syntaxe :
${entity?many_to_many_properties}
Retourne : List<Map> - Liste des relations N-N
Se transforme en : Model?api.get_entity_many_to_many_properties(entity)
entity?is_created_in 🟡
Vérifie si l’entité est créée dans le contexte d’une autre.
Syntaxe :
${entity?is_created_in}
Se transforme en : Model?api.is_created_in
⚠️ Note : Cette directive nécessite des paramètres supplémentaires - voir code source pour usage exact
entity?creates 🟡
Vérifie si l’entité crée d’autres entités.
Syntaxe :
${entity?creates}
Se transforme en : Model?api.creates
6. Entités - Logique Métier
entity?dump 🔧
Dump debug de la structure complète de l’entité.
Syntaxe :
${entity?dump}
Retourne : String - Représentation textuelle de l’entité
Usage : Debugging uniquement
Se transforme en : Model?api.dump_entity(entity)
7. Propriétés - Types et Valeurs
property?type_or_string 🟢
Retourne le type de la propriété, ou “string” par défaut.
Syntaxe :
${property?type_or_string}
Retourne : String - Type Java
Exemple :
[#foreach prop in entity?properties]
private ${prop?type_or_string} ${prop.@name};
[/#foreach]
Se transforme en : Model?api.get_property_type(property.@name, 'string', false)
property?nullable_type_or_string 🟢
Retourne le type de la propriété avec marqueur nullable (?string).
Syntaxe :
${property?nullable_type_or_string}
Retourne : String - Type avec ? si nullable
Exemple (Dart/Kotlin) :
String? name;
int? age;
Se transforme en : Model?api.get_property_type(property.@name, '?string', true)
property?dbtype 🟢
Retourne le type de base de données correspondant.
Syntaxe :
${property?dbtype}
Retourne : String - Type SQL
Exemple :
CREATE TABLE ${entity.@name} (
[#foreach prop in entity?properties]
${prop.@name} ${prop?dbtype},
[/#foreach]
);
Se transforme en : Model?api.get_property_dbtype(property.@name)
Mapping typique :
String→VARCHARInteger→INTDateTime→TIMESTAMP
property?default_value 🟢
Retourne la valeur par défaut de la propriété.
Syntaxe :
${property?default_value}
Retourne : String - Valeur par défaut
Exemple :
private String status = "${property?default_value}";
Se transforme en : Model?api.get_property_default_value(property.@name)
column?type_or_string / column?dbtype / column?default_value 🟡
Identique aux directives property?* mais pour les colonnes.
Usage : Contexte de génération de schémas de base de données
Se transforme en : Mêmes appels que property?* mais avec column.@name
column?is_property 🟡
Vérifie si une colonne correspond à une propriété de l’entité.
Syntaxe :
${column?is_property}
Retourne : boolean
Se transforme en : Model?api.has_property(column.@name)
8. Propriétés - Attributs (Deprecated) 🔴
⚠️ Les directives suivantes sont des ALIASES inutiles - utilisez directement .@ à la place !
property?kind_of_string → Utilisez property.@kind_of_string 🔴
Ancienne syntaxe :
[#if property?kind_of_string]
Nouvelle syntaxe (recommandée) :
[#if property.@kind_of_string]
Autres aliases deprecated :
property?kind_of_number→property.@kind_of_numberproperty?is_array→property.@is_arrayproperty?editable→property.@editableproperty?optionselect→property.@optionselectproperty?optionfilter→property.@optionfilterproperty?optioncomputed→property.@optioncomputed
Raison de la dépréciation : Ces directives sont de simples aliases qui n’apportent aucune valeur. L’accès direct .@ est plus clair.
9. Entités Imbriquées
nested?entity 🟢
Récupère la définition d’une entité référencée dans une propriété nested.
Syntaxe :
${nested?entity}
Retourne : Entity - Définition de l’entité
Exemple :
[#assign nestedEntity = nested?entity]
// Type nested: ${nestedEntity.@name}
Se transforme en : Model?api.get_entity(nested.@type)
nested?entity.@default_sort 🟢
Récupère le champ de tri par défaut d’une entité nested.
Syntaxe :
${nested?entity.@default_sort}
Se transforme en : Model?api.get_entity(nested.@type).getDefaultSort()
⚠️ Attention : Cette directive doit être appliquée AVANT nested?entity dans le preprocessing (ordre critique)
nested?properties 🟢
Récupère les propriétés d’une entité nested.
Syntaxe :
${nested?properties}
Se transforme en : Model?api.get_entity_properties(nested.@type)
nested?native_properties 🟢
Récupère les propriétés natives d’une entité nested.
Syntaxe :
${nested?native_properties}
Se transforme en : Model?api.get_native_properties(nested.@type)
10. Widgets
widget?property 🟡
Récupère la propriété associée à un widget.
Syntaxe :
${widget?property}
Retourne : Property - Définition de la propriété
Se transforme en : Model?api.get_entity_property(entity, widget.@property)
Usage typique : Génération d’interfaces utilisateur complexes avec widgets personnalisés
11. Debugging
property?dump 🔧
Dump debug de la structure complète de la propriété.
Syntaxe :
${property?dump}
Retourne : String - Représentation textuelle
Se transforme en : Model?api.dump_property(property)
Exemples Complets
Exemple 1 : Génération de POJO Java
[#assign entity = bidji.entity]
package com.mycompany.${entity.@package}.${entity.@module};
/**
* ${entity.@name} entity
*/
public class ${entity.@name} {
// ========== Propriétés natives ==========
[#foreach property in entity?native_properties]
private ${property.@type} ${property.@name};
[/#foreach]
// ========== Relations 1-N ==========
[#foreach rel in entity?one_to_many_properties]
private List<${rel.@type}> ${rel.@name} = new ArrayList<>();
[/#foreach]
// ========== Constructeur ==========
public ${entity.@name}() {
}
// ========== Getters/Setters ==========
[#foreach property in entity?properties]
public ${property.@type} get${property.@name?cap_first}() {
return this.${property.@name};
}
public void set${property.@name?cap_first}(${property.@type} ${property.@name}) {
this.${property.@name} = ${property.@name};
}
[/#foreach]
}
Exemple 2 : Génération de Schéma SQL
[#assign entity = bidji.entity]
CREATE TABLE ${entity.@name} (
id SERIAL PRIMARY KEY,
[#foreach prop in entity?native_properties]
${prop.@name} ${prop?dbtype}[#if prop?default_value??] DEFAULT '${prop?default_value}'[/#if],
[/#foreach]
created_at TIMESTAMP DEFAULT NOW()
);
[#-- Index sur le champ de tri par défaut --]
[#if entity.@default_sort??]
CREATE INDEX idx_${entity.@name}_${entity.@default_sort} ON ${entity.@name}(${entity.@default_sort});
[/#if]
Exemple 3 : Génération de Formulaire HTML
[#assign entity = bidji.entity]
<form id="form-${entity.@name}">
<h2>[#if entity.@icon??]<i class="${entity.@icon}"></i>[/#if] ${entity.@name}</h2>
[#foreach prop in entity?dataform_properties]
<div class="form-group">
<label for="${prop.@name}">${prop.@name?cap_first}</label>
[#if prop.@kind_of_string]
<input type="text" id="${prop.@name}" name="${prop.@name}" />
[#elseif prop.@kind_of_number]
<input type="number" id="${prop.@name}" name="${prop.@name}" />
[#else]
<input type="text" id="${prop.@name}" name="${prop.@name}" />
[/#if]
</div>
[/#foreach]
<button type="submit">Enregistrer</button>
</form>
Exemple 4 : Génération de Repository (DAO)
[#assign entity = bidji.entity]
package com.mycompany.${entity.@package}.repository;
import java.util.List;
import com.mycompany.${entity.@package}.${entity.@name};
public interface ${entity.@name}Repository {
${entity.@name} findById(Long id);
List<${entity.@name}> findAll();
[#if entity.@default_sort??]
List<${entity.@name}> findAllOrderBy${entity.@default_sort?cap_first}();
[/#if]
${entity.@name} save(${entity.@name} entity);
[#if entity.@delete]
void deleteById(Long id);
[/#if]
}
Matrice d’Usage des Directives
Tableau récapitulatif de la fréquence d’utilisation estimée des directives :
| Directive | Fréquence | Cas d’Usage Principaux | Complexité |
|---|---|---|---|
entity?properties |
⭐⭐⭐⭐⭐ | POJO, DTO, itération complète | Faible |
entity.@name |
⭐⭐⭐⭐⭐ | Noms de classes, tables | Très faible |
entity.@package |
⭐⭐⭐⭐⭐ | Packages Java/Python | Très faible |
entity?dataform_properties |
⭐⭐⭐⭐ | Formulaires UI | Moyenne |
entity?datatable_properties |
⭐⭐⭐⭐ | Grilles de données | Moyenne |
entity?native_properties |
⭐⭐⭐⭐ | Propriétés scalaires uniquement | Faible |
property?type_or_string |
⭐⭐⭐⭐ | Types Java/TypeScript | Moyenne |
property?dbtype |
⭐⭐⭐⭐ | Schémas SQL | Moyenne |
entity?one_to_many_properties |
⭐⭐⭐ | Relations collections | Moyenne |
entity.@module |
⭐⭐⭐ | Organisation multi-modules | Faible |
entity?many_to_many_properties |
⭐⭐ | Relations N-N | Moyenne |
entity.@default_sort |
⭐⭐ | Tri par défaut | Faible |
nested?entity |
⭐⭐ | Navigation relations | Élevée |
property?default_value |
⭐⭐ | Valeurs initiales | Faible |
entity?has_detail_tabs |
⭐ | UI complexe | Moyenne |
entity.@icon |
⭐ | Interfaces graphiques | Faible |
widget?property |
⭐ | UI widgets custom | Élevée |
| Deprecated | ❌ | Ne plus utiliser | - |
Légende Fréquence :
- ⭐⭐⭐⭐⭐ : Très fréquent (90%+ des templates)
- ⭐⭐⭐⭐ : Fréquent (60-90%)
- ⭐⭐⭐ : Occasionnel (30-60%)
- ⭐⭐ : Rare (10-30%)
- ⭐ : Très rare (<10%)
Pièges Courants
1. Ordre des Directives Nested ⚠️
Problème :
[#-- INCORRECT - L'ordre compte ! --]
${nested?entity}
${nested?entity.@default_sort} [#-- Ne fonctionnera pas ! --]
Solution :
[#-- CORRECT - default_sort d'abord --]
${nested?entity.@default_sort}
${nested?entity}
Raison : Le preprocessing applique les règles dans un ordre spécifique. nested?entity.@default_sort doit être transformé avant nested?entity, sinon il sera partiellement transformé et cassé.
2. Confusion entre ? et .@
Problème :
${property?name} [#-- Erreur ! --]
${entity?package} [#-- Erreur ! --]
Solution :
${property.@name} [#-- Correct --]
${entity.@package} [#-- Correct --]
Règle :
- Utilisez
?pour les fonctions (retournent des listes ou calculs) - Utilisez
.@pour les attributs (accès direct)
3. Directives Deprecated
Problème :
[#if property?kind_of_string] [#-- Deprecated ! --]
Solution :
[#if property.@kind_of_string] [#-- Correct --]
Raison : Les directives property?kind_of_* sont de simples aliases. Utilisez directement .@ pour plus de clarté.
4. Accès à entity2 au lieu d’entity
Problème : Utiliser entity2 sans raison
Solution : N’utilisez entity2 que dans les contextes où vous travaillez explicitement avec deux entités (ex: relations)
5. Oublier Model?api pour les nested
Problème :
[#assign target = nested.@type] [#-- Type brut, pas l'entité --]
Solution :
[#assign target = nested?entity] [#-- Récupère l'entité complète --]
Migration vers Nouvelle Syntaxe
Une nouvelle syntaxe plus claire est en cours de développement. Voici un aperçu :
Syntaxe Actuelle (Legacy)
[#foreach prop in entity?properties]
private ${prop.@type} ${prop.@name};
[/#foreach]
Nouvelle Syntaxe (Future)
[#foreach prop in bidji.entity.properties(entity)]
private ${bidji.property.type(prop)} ${bidji.property.name(prop)};
[/#foreach]
Avantages de la nouvelle syntaxe :
- ✅ Namespaces clairs (
bidji.entity.*,bidji.property.*) - ✅ Validation par FreeMarker (erreurs claires)
- ✅ Pas de preprocessing fragile
- ✅ Auto-complétion IDE possible
Pour plus d’informations : Voir doc/Refactoring.md section “Phase 3: Nouvelle Syntaxe”
Résumé des Directives par Fréquence
Directives Essentielles (à connaître absolument)
entity?properties [#-- Toutes les propriétés --]
entity.@name [#-- Nom de l'entité --]
entity.@package [#-- Package --]
property.@type [#-- Type de propriété --]
property.@name [#-- Nom de propriété --]
Directives Courantes
entity?native_properties [#-- Propriétés primitives --]
entity?dataform_properties [#-- Props pour formulaires --]
entity?datatable_properties [#-- Props pour tableaux --]
property?type_or_string [#-- Type avec fallback --]
property?dbtype [#-- Type SQL --]
entity?one_to_many_properties [#-- Relations 1-N --]
Directives Avancées
nested?entity [#-- Entité référencée --]
entity?has_detail_tabs [#-- UI complexe --]
widget?property [#-- Widgets custom --]
entity?dump [#-- Debug --]
Support et Contribution
Problème avec une directive ?
- Vérifiez la syntaxe dans ce guide
- Consultez les exemples complets
- Vérifiez les pièges courants
- Reportez un bug dans
doc/Refactoring.md
Ajouter une nouvelle directive ?
- Modifiez
BidjicTask.freemarkerize() - Mettez à jour ce document
- Ajoutez des tests dans
BidjicPreprocessorTest - Documentez dans
BidjicDirectivesReference.md
Document généré le : 2026-02-06 Version Bidji : dev Auteur : Analyse automatique du code source