Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/InseeFr/ARC.git into chec…
Browse files Browse the repository at this point in the history
…kmarx2
  • Loading branch information
Nolife999 committed May 24, 2024
2 parents 403c6d8 + ece88d7 commit d9fa51d
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ private void exportExecutorTableToParquet(Connection connection, TableToRetrieve
}
query.append("SELECT * FROM " + attachedTableName(connectionIndex, table.getTableName()));
}

executeCopy(connection, query, outputFileName);

if (checkNotEmpty(connection, query)) {
executeCopy(connection, query, outputFileName);
}

}

Expand All @@ -150,7 +152,36 @@ private void exportCoordinatorTableToParquet(Connection connection, TableToRetri

GenericPreparedStatementBuilder query = new GenericPreparedStatementBuilder();
query.append("SELECT * FROM " + attachedTableName(ArcDatabase.COORDINATOR.getIndex(), table.getTableName()));
executeCopy(connection, query, outputFileName);

if (checkNotEmpty(connection, query)) {
executeCopy(connection, query, outputFileName);
}
}

/**
* check if the table selected by the query is not empty
* @param connection
* @param selectQuery
* @return true if the table contains at least 1 line, false if not
* @throws SQLException
*/
protected boolean checkNotEmpty(Connection connection, GenericPreparedStatementBuilder selectQuery)
throws SQLException {
GenericPreparedStatementBuilder query = new GenericPreparedStatementBuilder();
query.append("SELECT count(*) FROM (").append(selectQuery).append(" LIMIT 1) a;\n");

int countLine;
try (PreparedStatement stmt = connection.prepareStatement(query.toString())) {
stmt.execute();

try (ResultSet rs = stmt.getResultSet())
{
rs.next();
countLine = rs.getInt(1);
}
}

return (countLine == 1);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.insee.arc.core.service.p6export.parquet;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.File;
Expand Down Expand Up @@ -70,6 +71,12 @@ public void exportParquetTestOnExecutor() throws SQLException, IOException, ArcE
assertTrue(f.contains("test_table2.parquet"));

}

@Test
public void checkNotEmptyTest() throws SQLException {
assertTrue(checkNotEmpty(InitializeQueryTest.c, new GenericPreparedStatementBuilder("SELECT * FROM (VALUES (1),(2),(3)) t (col)")));
assertFalse(checkNotEmpty(InitializeQueryTest.c, new GenericPreparedStatementBuilder("SELECT 1 WHERE 1=0")));
}

/**
* Create a test table on target connection with several common types of data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,39 @@
# MVC et DAO dans ARC
# Construire une page dans arc-web

L'architecture modèle-vue-contrôleur (MVC) est une architecture logicielle qui consiste à séparer en modules distincts l'affichage, le métier et les données d'une page, pour rendre le code plus maintenable et compartimenté. Cette architecture peut être complétée par des objets d'accès aux données (DAO) qui regroupent les connexions et requêtes faites sur les données persistantes.

Dans **arc-web**, chaque page Web peut contenir plusieurs vues, et à chaque vue sont associés un contrôleur, un modèle et une méthode d'accès aux données. Une page Web dans `fr.insee.arc.web.gui` est un package contenant les packages `controller` (contrôleurs de la page), `dao` (objet d'accès à Postgres), `model` (modèles de la page) et `service` (vues de la page). Le framework Web MVC de Spring est utilisé.

### Le package `controller`
Ce document est une aide pour la création ou la modification de pages Web dans ARC.

Il se compose de tous les contrôleurs d'une même page, soit un ensemble de classes `ControllerView[Nom de la vue]`. Les classes contrôleur font le lien entre les requêtes HTTP et les actions du service en invoquant le modèle de données.

Une classe contrôleur est annotée `@Controller` dans Spring, et hérite de `ServiceView[Nom de la vue]`.
## Vue d'ensemble des fichiers constituant une page Web dans ARC

Les méthodes d'une classe contrôleur sont généralement de la forme :
```java=
@RequestMapping("/fonctionnalite")
public String fonctionnaliteAction(Model model) {
return fonctionnalite(model);
}
```
- `fonctionnalite` est une action de la vue, implémentée dans la classe service.
- l'annotation `@RequestMapping` permet d'associer une requête HTTP à cette action du contrôleur.
### Nouveaux fichiers

### Le package `dao`
- Composante java : `arc-web/src/main/java/fr/insee/arc/web/gui/nouvellepage`
- Couche contrôleur : `/controller` avec 1 fichier Controller par vue
- Couche DAO : `/dao` avec 1 fichier DAO
- Couche modèle : `/model` avec 1 fichier Model + 1 fichier View par vue
- Couche service : `/service` avec 1 fichier Interactor + 1 fichier Service par vue
- Page jsp : `arc-web/src/main/webapp/WEB-INF/jsp/nouvellepage.jsp`
- Fichier js : `arc-web/src/main/webapp/js/nouvellepage.js` (ne contient que la config)

Il se compose de la seule classe `[Nom de la page]Dao`. La classe DAO concentre toutes les requêtes SQL accédant à la base Postgres de ARC.
### Fichiers à modifier

La classe DAO hérite de `VObjectHelperDao` qui regroupe quelques méthodes utiles. Elle inclut les attributs `VObjectService` pour le lien avec le VObject, et `DataObjectService` pour la connexion à Postgres.
- `arc-web/src/main/resources/messages_[en&fr].properties` : libellés avec localisation
- `arc-web/src/main/webapp/WEB-INF/jsp/tiles/header.jsp` ou tout autre page pertinente, pour ajouter un lien vers la nouvelle page

Les méthodes de la classe DAO concernent généralement une seule requête SQL. Les méthodes d'initialisation des VObject, par exemple, sont de la forme :
## Les fichiers Java : le patron MVC

```java=
public void initializeViewUn(VObject viewUn) {
ViewEnum dataModelUn = ViewEnum.TABLE;
ArcPreparedStatementBuilder query = new ArcPreparedStatementBuilder();
query.append(SQL.SELECT);
// reste de la requête
Map<String, String> defaultInputFields = new HashMap<>();
vObjectService.initialize(viewUn, query,
dataObjectService.getView(dataModelUn), defaultInputFields);
}
```
L'architecture modèle-vue-contrôleur (MVC) est une architecture logicielle qui consiste à séparer en modules distincts l'affichage, le métier et les données d'une page, pour rendre le code plus maintenable et compartimenté. Cette architecture peut être complétée par des objets d'accès aux données (DAO) qui regroupent les connexions et requêtes faites sur les données persistantes.

- `ViewEnum` est une énumération des tables de ARC.
- Pour éviter les injections, il convient d'utiliser des `ArcPreparedStatementBuilder` pour formuler les requêtes SQL. L'énumération `SQL` contient les principaux mots-clés comme `SELECT` ou `FROM`.
- `defaultInputFields` sont les valeurs par défaut du VObject. Dans cet exemple, il n'y a pas de valeurs par défaut donc la `HashMap` est laissée vide.
Dans **arc-web**, chaque page Web peut contenir plusieurs vues, et à chaque vue sont associés un contrôleur, un modèle et une méthode d'accès aux données. Dans `fr.insee.arc.web.gui`, une page Web XXX affichant des vues YYY est un package `XXX` contenant des packages correspondant aux différentes couches du modèle MVC :
- la couche **modèle** (`model`), avec
- une classe composant **ModelXXX**, contenant toutes les vues de la page XXX,
- pour chaque vue une classe **ViewYYY** ;
- la couche **service** (`service`), avec
- une classe service **InteractorXXX** ou **XXXAction** pour initialiser la page et les VObjects,
- pour chaque vue une classe **ServiceViewYYY**, devant contenir si nécessaire les actions de base du VObject : selectYYY, sortYYY, addYYY, updateYYY, deleteYYY ;
- la couche **contrôleur** (`controller`), avec pour chaque vue une classe contrôleur **ControllerViewYYY** liant les requêtes Web aux actions du service.
- la couche **DAO** (`DAO`), avec une classe DAO **XXXDAO** gérant les requêtes à envoyer à la base de données.

Le framework Web MVC de Spring est utilisé.

### Le package `model`

Expand Down Expand Up @@ -166,3 +156,126 @@ public String doFonctionnalite(Model model) {
return generateDisplay(model, RESULT_SUCCESS);
}
```

### Le package `controller`

Il se compose de tous les contrôleurs d'une même page, soit un ensemble de classes `ControllerView[Nom de la vue]`. Les classes contrôleur font le lien entre les requêtes HTTP et les actions du service en invoquant le modèle de données.

Une classe contrôleur est annotée `@Controller` dans Spring, et hérite de `ServiceView[Nom de la vue]`.

Les méthodes d'une classe contrôleur sont généralement de la forme :
```java=
@RequestMapping("/fonctionnalite")
public String fonctionnaliteAction(Model model) {
return fonctionnalite(model);
}
```
- `fonctionnalite` est une action de la vue, implémentée dans la classe service.
- l'annotation `@RequestMapping` permet d'associer une requête HTTP à cette action du contrôleur.

### Le package `dao`

Il se compose de la seule classe `[Nom de la page]Dao`. La classe DAO concentre toutes les requêtes SQL accédant à la base Postgres de ARC.

La classe DAO hérite de `VObjectHelperDao` qui regroupe quelques méthodes utiles. Elle inclut les attributs `VObjectService` pour le lien avec le VObject, et `DataObjectService` pour la connexion à Postgres.

Les méthodes de la classe DAO concernent généralement une seule requête SQL. Les méthodes d'initialisation des VObject, par exemple, sont de la forme :

```java=
public void initializeViewUn(VObject viewUn) {
ViewEnum dataModelUn = ViewEnum.TABLE;
ArcPreparedStatementBuilder query = new ArcPreparedStatementBuilder();
query.append(SQL.SELECT);
// reste de la requête
Map<String, String> defaultInputFields = new HashMap<>();
vObjectService.initialize(viewUn, query,
dataObjectService.getView(dataModelUn), defaultInputFields);
}
```

- `ViewEnum` est une énumération des tables de ARC.
- Pour éviter les injections, il convient d'utiliser des `ArcPreparedStatementBuilder` pour formuler les requêtes SQL. L'énumération `SQL` contient les principaux mots-clés comme `SELECT` ou `FROM`.
- `defaultInputFields` sont les valeurs par défaut du VObject. Dans cet exemple, il n'y a pas de valeurs par défaut donc la `HashMap` est laissée vide.

## La page jsp : l'utilisation de VObject

Un **VObject** est un objet à inclure dans une jsp qui permet d'afficher sur une page web, un tableau de valeurs dynamique et éditable.

### Pré-requis du projet

Pour faire fonctionner VObject dans le projet, ARC a besoin de :
- `templateVObject.jsp` dans le répertoire jsp
- `component.js` dans le répertoire js
- le framework Bootstrap

### Inclure le VObject dans la page

Dans le fichier jsp, à l'endroit où inclure le VObject, écrire :

```htmlembedded=
<c:set var="view" value="${viewYYY}" scope="request"/>
<c:import url="tiles/templateVObject.jsp">
<c:param name="nom" value ="valeur" />
...
</c:import>
```
Autant de paramètres que nécessaire peuvent être ajoutés avec la syntaxe `<c:param name="nom" value ="valeur" />`. Les paramètres disponibles ont les noms et valeurs suivantes :
- **taille** renseigne la largeur du VObject dans la page, en prenant des valeurs entre **col-md-1** et **col-md-12** (valeurs entières uniquement), par défaut le VObject prend toute la largeur disponible

Les paramètres suivants permettent d'afficher des boutons et fonctionnalités en renseignant la valeur **true**. Par défaut la valeur est **false** et ils ne sont pas affichés :
- **btnSelect** pour afficher le bouton de rafraîchissement
- **btnSee** pour afficher le bouton de vue (pour le fonctionnement d'anciens écrans, plus nécessaire)
- **btnSort** pour permettre de trier les colonnes en cliquant sur leur nom
- **btnAdd** pour afficher le bouton d'ajout d'entrée (**ligneAdd** doit être activé pour remplir l'entrée à ajouter)
- **btnUpdate** pour afficher le bouton de mise à jour, qui permet de modifier le tableau directement et d'enregistrer les modifications
- **btnDelete** pour afficher le bouton de suppression d'entrée (**checkbox** doit être activé pour sélectionner l'entrée à supprimer)
- **ligneAdd** pour afficher la ligne d'ajout d'entrée en bas du tableau
- **ligneFilter** pour afficher la ligne de filtrage des entrées en haut du tableau
- **checkbox** pour afficher les cases à cocher à gauche de chaque entrée
- **multiSelection** pour autoriser la sélection de plusieurs cases à cocher (inutile si **checkbox** est désactivé)

### Fiches d'aide aux utilisateurs

En haut à droite de chaque vObject se trouve un bouton **(?)** : sur ARC, il renvoie vers [une page de documentation utilisateur](https://github.com/InseeFr/ARC/blob/master/user-guide/ihm_views_doc.md), en redirigeant automatiquement vers la partie de cette page portant le nom de la vue. Ces fiches de documentation décrivent le contenu des vObject avec éventuellement des explications, cas d'utilisation ou bonnes pratiques.

## Autres fichiers à (éventuellement) modifier

### Gestion du texte et sa localisation

ARC est disponible en français et en anglais. Les fichiers `messages_fr.properties` et `messages_en.properties` de `arc-web/src/main/resources/` permettent de gérer la localisation des différents textes de l'IHM.

Les messages localisés peuvent être intégrés à la page de différentes manières.

#### Directement sur la page jsp

On utilise alors spring message :
```jsp
<spring:message code="mon.message"/>
```
À utiliser notamment pour les headers de page.

#### Pour un nom de vObject

On précise dans le constructeur de ViewYYY.java :
```java
this.setTitle("view.yyy");
```
La vue affichera le nom correspondant à `view.yyy`.

#### Pour un nom de colonne

On précise dans la définition de la columnMap de ViewYYY.java :
```java
columnMap.put("maColonne", new ColumnRendering(true, "label.maColonne", "50%", "text", null, true));
```
La colonne affichera le nom correspondant à `label.maColonne`.

### Ajouter un lien vers la page dans le header

Dans le fichier `header.jsp`, dans la catégorie adéquate, ajouter
```jsp
<c:import url="tiles/template_header_link.jsp"><c:param name="linkRef" value="maPage"/><c:param name="linkId" value="maPage"/></c:import>
```
Le paramètre `linkRef` va chercher dans `action.maPage` le nom du endpoint à aller chercher. `action.maPage` doit être bien renseigné dans `messages_fr.properties` et `messages_en.properties`.

Le paramètre `linkId` va chercher dans `header.maPage` le titre de la page pour en faire l'intitulé du lien cliquable.
46 changes: 0 additions & 46 deletions user-guide/ria-guide/vobject_utilisation.md

This file was deleted.

0 comments on commit d9fa51d

Please sign in to comment.