From 8be6cb96c31524cc489edb4a49aaa35bc1d197a0 Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Fri, 10 Jan 2020 17:36:23 +0100
Subject: [PATCH] Simplified code of forms with repeatable fieldsets

---
 .../calculator-list.component.ts              |   2 +-
 .../concrete/form-macrorugo-compound.ts       | 106 +++---------
 .../concrete/form-parallel-structures.ts      | 154 ++++++------------
 .../concrete/form-repeatable-fieldset.ts      |  46 ++++++
 .../definition/concrete/form-spp.ts           |  84 ++--------
 5 files changed, 124 insertions(+), 268 deletions(-)
 create mode 100644 src/app/formulaire/definition/concrete/form-repeatable-fieldset.ts

diff --git a/src/app/components/calculator-list/calculator-list.component.ts b/src/app/components/calculator-list/calculator-list.component.ts
index ef4840466..d9047b66f 100644
--- a/src/app/components/calculator-list/calculator-list.component.ts
+++ b/src/app/components/calculator-list/calculator-list.component.ts
@@ -134,7 +134,7 @@ export class CalculatorListComponent implements OnInit {
             if (f instanceof FormulaireMacrorugoCompound) {
                 for (const e of f.allFormElements) {
                     if (e instanceof FieldsetContainer) {
-                        e.addFromTemplate(0, 0, f.mrcNub.children[0]);
+                        e.addFromTemplate(0, 0, f.currentNub.getChildren()[0]);
                         break;
                     }
                 }
diff --git a/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts b/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts
index 359fbf1ed..cd4810da7 100644
--- a/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts
+++ b/src/app/formulaire/definition/concrete/form-macrorugo-compound.ts
@@ -1,18 +1,17 @@
-import { IObservable, MacroRugo, MacrorugoCompound, Nub, Props, Session } from "jalhyd";
+import { IObservable, Nub } from "jalhyd";
 
-import { FormulaireBase } from "./form-base";
 import { FieldSet } from "../../fieldset";
 import { FieldsetContainer } from "../../fieldset-container";
 import { FormulaireNode } from "../../formulaire-node";
-import { FieldsetTemplate } from "../../fieldset-template";
 import { NgParameter } from "../../ngparam";
 import { FormResultMacrorugoCompound } from "../form-result-macrorugo-compound";
 import { FormComputeMacrorugoCompound } from "../form-compute-macrorugo-compound";
+import { FormulaireRepeatableFieldset } from "./form-repeatable-fieldset";
 
 /**
  * Formulaire pour les passes à macrorugosités complexes
  */
-export class FormulaireMacrorugoCompound extends FormulaireBase {
+export class FormulaireMacrorugoCompound extends FormulaireRepeatableFieldset {
 
     /** id of select configuring apron type */
     private _apronTypeSelectId: string;
@@ -29,32 +28,20 @@ export class FormulaireMacrorugoCompound extends FormulaireBase {
         this._formCompute = new FormComputeMacrorugoCompound(this, (this._formResult as FormResultMacrorugoCompound));
     }
 
-    public get mrcNub(): MacrorugoCompound {
-        return this.currentNub as MacrorugoCompound;
-    }
-
-    private createMacroRugoNub(templ: FieldsetTemplate): Nub {
-        const params = {};
-        params["calcType"] = templ.calcTypeFromConfig;
-        return this.createMacroRugo(new Props(params));
-    }
-
-    /**
-     * ajoute un nub MacroRugo
-     * @param mr nub à ajouter
-     * @param after position après laquelle insérer le nub, à la fin sinon
-     */
-    private addMacroRugoNub(mr: MacroRugo, after?: number) {
-        this.mrcNub.addChild(mr, after);
+    protected parseOptions(json: {}) {
+        super.parseOptions(json);
+        this._apronTypeSelectId = this.getOption(json, "apronTypeSelectId");
     }
 
-    /**
-     * Asks JaLHyd to create a MacroRugo nub as a child of the current Calculator Module
-     * and return it; does not store it in the Session (for MacroRugo, not for Calculator Modules)
-     * @param p properties for the new Nub
-     */
-    protected createMacroRugo(p: Props): MacroRugo {
-        return Session.getInstance().createNub(p, this.mrcNub) as MacroRugo;
+    public afterParseFieldset(fs: FieldSet) {
+        // if Fieldset contains apron type selector
+        if (this._apronTypeSelectId) {
+            const sel = fs.getFormulaireNodeById(this._apronTypeSelectId);
+            if (sel) {
+                // on abonne le formulaire aux propriétés du FieldSet
+                fs.properties.addObserver(this);
+            }
+        }
     }
 
     public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet {
@@ -67,8 +54,8 @@ export class FormulaireMacrorugoCompound extends FormulaireBase {
             if (nub) { // use existing Nub (build interface based on model)
                 mrn = nub;
             } else {
-                mrn = this.createMacroRugoNub(data["template"]);
-                this.addMacroRugoNub(mrn as MacroRugo, after);
+                mrn = this.createChildNub(data["template"]);
+                this.currentNub.addChild(mrn, after);
             }
             res.setNub(mrn, false);
 
@@ -86,64 +73,13 @@ export class FormulaireMacrorugoCompound extends FormulaireBase {
         }
     }
 
-    protected parseOptions(json: {}) {
-        super.parseOptions(json);
-        this._apronTypeSelectId = this.getOption(json, "apronTypeSelectId");
-    }
-
-    public afterParseFieldset(fs: FieldSet) {
-        // if Fieldset contains apron type selector
-        if (this._apronTypeSelectId) {
-            const sel = fs.getFormulaireNodeById(this._apronTypeSelectId);
-            if (sel) {
-                // on abonne le formulaire aux propriétés du FieldSet
-                fs.properties.addObserver(this);
-            }
-        }
-    }
-
-    public moveFieldsetUp(fs: FieldSet) {
-        if (fs.nub instanceof MacroRugo) {
-            // déplacement du nub
-            fs.nub.parent.moveChildUp(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetUp(fs);
-
-            this.resetResults();
-        } else {
-            super.moveFieldsetUp(fs);
-        }
-    }
-
-    public moveFieldsetDown(fs: FieldSet) {
-        if (fs.nub instanceof MacroRugo) {
-            // déplacement du nub
-            fs.nub.parent.moveChildDown(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetDown(fs);
-
-            this.resetResults();
-        } else { super.moveFieldsetDown(fs); }
-    }
-
-    public removeFieldset(fs: FieldSet) {
-        if (fs.nub instanceof MacroRugo) {
-            // suppression du sous-nub dans le Nub parent
-            this.mrcNub.deleteChild(fs.nub.findPositionInParent());
-            // suppression du fieldset
-            this.fieldsetContainer.removeFieldset(fs);
-
-            this.resetResults();
-        } else { super.removeFieldset(fs); }
-    }
-
     protected completeParse(json: {}) {
         this.subscribeFieldsetContainer();
-        this.updateApronState(this.mrcNub.properties.getPropValue("inclinedApron"));
+        this.updateApronState(this.currentNub.properties.getPropValue("inclinedApron"));
         this._formResult.helpLinks = this._resultsHelpLinks;
     }
 
-    private get fieldsetContainer(): FieldsetContainer {
+    protected get fieldsetContainer(): FieldsetContainer {
         const n = this.getFormulaireNodeById("macrorugo_container");
         if (n === undefined || !(n instanceof FieldsetContainer)) {
             throw new Error("l'élément 'macrorugo_container' n'est pas du type FieldsetContainer");
@@ -189,7 +125,7 @@ export class FormulaireMacrorugoCompound extends FormulaireBase {
             for (const elt of this.allFormElements) {
                 if (elt instanceof FieldsetContainer) {
                     elt.clearKids();
-                    for (const c of this.mrcNub.children) {
+                    for (const c of this.currentNub.getChildren()) {
                         elt.addFromTemplate(0, undefined, c);
                     }
                 }
@@ -200,9 +136,7 @@ export class FormulaireMacrorugoCompound extends FormulaireBase {
     // interface Observer
 
     public update(sender: IObservable, data: any) {
-
         super.update(sender, data);
-
         if (sender instanceof FieldsetContainer) {
             switch (data.action) {
                 case "newFieldset":
diff --git a/src/app/formulaire/definition/concrete/form-parallel-structures.ts b/src/app/formulaire/definition/concrete/form-parallel-structures.ts
index c4b329135..2ed380c04 100644
--- a/src/app/formulaire/definition/concrete/form-parallel-structures.ts
+++ b/src/app/formulaire/definition/concrete/form-parallel-structures.ts
@@ -8,9 +8,9 @@ import { SelectField } from "../../select-field";
 import { NgParameter } from "../../ngparam";
 import { FieldsetTemplate } from "../../fieldset-template";
 import { FormulaireNode } from "../../formulaire-node";
-import { FormulaireBase } from "./form-base";
+import { FormulaireRepeatableFieldset } from "./form-repeatable-fieldset";
 
-export class FormulaireParallelStructure extends FormulaireBase {
+export class FormulaireParallelStructure extends FormulaireRepeatableFieldset {
 
     /**
      * id du select configurant le type d'ouvrage
@@ -26,63 +26,22 @@ export class FormulaireParallelStructure extends FormulaireBase {
         this._formCompute = new FormComputeParallelStructures(this, (this._formResult as FormResultFixedVar));
     }
 
-    private createStructNub(templ: FieldsetTemplate): Nub {
-        // !!! attention !!!
-        // Il doit y avoir cohérence dans le fichier de conf entre les valeurs defaultXXX et les valeurs possibles pour les select
-        // cad valeur par défaut du 1er select (type d'ouvrage), du 2ème (loi de débit).
-        // A terme, il faudrait analyser le fichier de conf (dépendances d'existence) pour déterminer automatiquement ces valeurs
-
-        const params = {};
-        params["calcType"] = templ.calcTypeFromConfig;
-        params["nodeType"] = templ.defaultNodeTypeFromConfig;
-        params["structureType"] = templ.defaultStructTypeFromConfig;
-        params["loiDebit"] = templ.defaultLoiDebitFromConfig;
-
-        return this.createStructure(new Props(params));
-    }
-
-    /**
-     * ajoute un Nub Structure
-     * @param st structure à ajouter
-     * @param after position après laquelle insérer la structure, à la fin sinon
-     */
-    private addStructureNub(st: Structure, after?: number) {
-        this.parallelStructureNub.addChild(st, after);
-    }
-
-    private get parallelStructureNub(): ParallelStructure {
-        return this.currentNub as ParallelStructure;
-    }
-
-    /**
-     * Asks JaLHyd to create a Structure Nub as a child of the current Calculator Module
-     * and return it; does not store it in the Session (for Structures, not for Calculator Modules)
-     * @param p properties for the new Nub
-     */
-    protected createStructure(p: Props): Structure {
-        return Session.getInstance().createNub(p, this.currentNub as ParallelStructure) as Structure;
-    }
+    protected parseOptions(json: {}) {
+        super.parseOptions(json);
 
-    /**
-     * Replaces the geiven Structure sn in the current calculator module,
-     * with a new one built with properties "params"
-     * @param sn Structure to replace
-     * @param params properties to build the new Nub (calcType, loiDebit...)
-     */
-    protected replaceNub(sn: Structure, params: Props): Nub {
-        const parent = (this.currentNub as ParallelStructure);
-        const newStructure = this.createStructure(params);
-        parent.replaceChildInplace(sn, newStructure);
-        return newStructure;
+        // id du select configurant le type d'ouvrage
+        this.__ouvrageSelectId = this.getOption(json, "ouvrageSelectId");
     }
 
-    /**
-     * Deleted the given child Nub in the current calculator module
-     * @param params properties to build the new Nub (calcType, loiDebit...)
-     */
-    protected deleteNub(sn: Structure) {
-        const parent = (this.currentNub as ParallelStructure);
-        parent.deleteChild(parent.getIndexForChild(sn));
+    public afterParseFieldset(fs: FieldSet) {
+        // si le FieldSet contient le select de type d'ouvrage
+        if (this.__ouvrageSelectId) {
+            const sel = fs.getFormulaireNodeById(this.__ouvrageSelectId);
+            if (sel) {
+                // on abonne le formulaire aux propriétés du FieldSet
+                fs.properties.addObserver(this);
+            }
+        }
     }
 
     public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet {
@@ -95,8 +54,8 @@ export class FormulaireParallelStructure extends FormulaireBase {
             if (nub) { // use existing Nub (build interface based on model)
                 sn = nub;
             } else {
-                sn = this.createStructNub(data["template"]);
-                this.addStructureNub(sn as Structure, after);
+                sn = this.createChildNub(data["template"]);
+                this.currentNub.addChild(sn, after);
             }
             res.setNub(sn, false);
 
@@ -114,58 +73,41 @@ export class FormulaireParallelStructure extends FormulaireBase {
         }
     }
 
-    protected parseOptions(json: {}) {
-        super.parseOptions(json);
-
-        // id du select configurant le type d'ouvrage
-        this.__ouvrageSelectId = this.getOption(json, "ouvrageSelectId");
-    }
-
-    public afterParseFieldset(fs: FieldSet) {
-        // si le FieldSet contient le select de type d'ouvrage
-        if (this.__ouvrageSelectId) {
-            const sel = fs.getFormulaireNodeById(this.__ouvrageSelectId);
-            if (sel) {
-                // on abonne le formulaire aux propriétés du FieldSet
-                fs.properties.addObserver(this);
-            }
-        }
-    }
+    protected createChildNub(templ: FieldsetTemplate): Nub {
+        // !!! attention !!!
+        // Il doit y avoir cohérence dans le fichier de conf entre les valeurs defaultXXX et les valeurs possibles pour les select
+        // cad valeur par défaut du 1er select (type d'ouvrage), du 2ème (loi de débit).
+        // A terme, il faudrait analyser le fichier de conf (dépendances d'existence) pour déterminer automatiquement ces valeurs
 
-    public moveFieldsetUp(fs: FieldSet) {
-        if (fs.nub instanceof Structure) {
-            // déplacement du nub
-            fs.nub.parent.moveChildUp(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetUp(fs);
+        const params = {};
+        params["calcType"] = templ.calcTypeFromConfig;
+        params["nodeType"] = templ.defaultNodeTypeFromConfig;
+        params["structureType"] = templ.defaultStructTypeFromConfig;
+        params["loiDebit"] = templ.defaultLoiDebitFromConfig;
 
-            this.resetResults();
-        } else {
-            super.moveFieldsetUp(fs);
-        }
+        return this.createStructure(new Props(params));
     }
 
-    public moveFieldsetDown(fs: FieldSet) {
-        if (fs.nub instanceof Structure) {
-            // déplacement du nub
-            fs.nub.parent.moveChildDown(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetDown(fs);
-
-            this.resetResults();
-        } else { super.moveFieldsetDown(fs); }
+    /**
+     * Asks JaLHyd to create a Structure Nub as a child of the current Calculator Module
+     * and return it; does not store it in the Session (for Structures, not for Calculator Modules)
+     * @param p properties for the new Nub
+     */
+    protected createStructure(p: Props): Structure {
+        return Session.getInstance().createNub(p, this.currentNub as ParallelStructure) as Structure;
     }
 
-    public removeFieldset(fs: FieldSet) {
-        if (fs.nub instanceof Structure) {
-            // suppression du sous-nub dans le Nub parent
-            this.deleteNub(fs.nub);
-
-            // suppression du fieldset
-            this.fieldsetContainer.removeFieldset(fs);
-
-            this.resetResults();
-        } else { super.removeFieldset(fs); }
+    /**
+     * Replaces the given Structure sn in the current calculator module,
+     * with a new one built with properties "params"
+     * @param sn Structure to replace
+     * @param params properties to build the new Nub (calcType, loiDebit...)
+     */
+    protected replaceNub(sn: Structure, params: Props): Nub {
+        const parent = (this.currentNub as ParallelStructure);
+        const newStructure = this.createStructure(params);
+        parent.replaceChildInplace(sn, newStructure);
+        return newStructure;
     }
 
     protected completeParse(json: {}) {
@@ -173,7 +115,7 @@ export class FormulaireParallelStructure extends FormulaireBase {
         this._formResult.helpLinks = this._resultsHelpLinks;
     }
 
-    private get fieldsetContainer(): FieldsetContainer {
+    protected get fieldsetContainer(): FieldsetContainer {
         const n = this.getFormulaireNodeById("struct_container");
         if (n === undefined || !(n instanceof FieldsetContainer)) {
             throw new Error("l'élément 'struct_container' n'est pas du type FieldsetContainer");
@@ -235,9 +177,7 @@ export class FormulaireParallelStructure extends FormulaireBase {
     // interface Observer
 
     public update(sender: any, data: any) {
-
         super.update(sender, data);
-
         if (sender instanceof FieldsetContainer) {
             switch (data.action) {
                 case "newFieldset":
diff --git a/src/app/formulaire/definition/concrete/form-repeatable-fieldset.ts b/src/app/formulaire/definition/concrete/form-repeatable-fieldset.ts
new file mode 100644
index 000000000..6cec8f90a
--- /dev/null
+++ b/src/app/formulaire/definition/concrete/form-repeatable-fieldset.ts
@@ -0,0 +1,46 @@
+import { FieldSet } from "../../fieldset";
+import { FieldsetContainer } from "../../fieldset-container";
+import { FormulaireBase } from "./form-base";
+import { FieldsetTemplate } from "../../fieldset-template";
+
+import { Props, Session, Nub } from "jalhyd";
+
+export abstract class FormulaireRepeatableFieldset extends FormulaireBase {
+
+    protected abstract get fieldsetContainer(): FieldsetContainer;
+
+    public moveFieldsetUp(fs: FieldSet) {
+        // déplacement du nub
+        fs.nub.parent.moveChildUp(fs.nub);
+        // déplacement du fieldset
+        this.fieldsetContainer.moveFieldsetUp(fs);
+        this.resetResults();
+    }
+
+    public moveFieldsetDown(fs: FieldSet) {
+        // déplacement du nub
+        fs.nub.parent.moveChildDown(fs.nub);
+        // déplacement du fieldset
+        this.fieldsetContainer.moveFieldsetDown(fs);
+        this.resetResults();
+    }
+
+    public removeFieldset(fs: FieldSet) {
+        // suppression du sous-nub dans le Nub parent
+        this.currentNub.deleteChild(fs.nub.findPositionInParent());
+        // suppression du fieldset
+        this.fieldsetContainer.removeFieldset(fs);
+        this.resetResults();
+    }
+
+    /**
+     * Asks JaLHyd to create a nub as a child of the current Calculator Module
+     * and return it; does not store it in the Session
+     * @param p properties for the new Nub
+     */
+    protected createChildNub(templ: FieldsetTemplate): Nub {
+        const params = {};
+        params["calcType"] = templ.calcTypeFromConfig;
+        return Session.getInstance().createNub(new Props(params), this.currentNub);
+    }
+}
diff --git a/src/app/formulaire/definition/concrete/form-spp.ts b/src/app/formulaire/definition/concrete/form-spp.ts
index 986d40301..e5430273c 100644
--- a/src/app/formulaire/definition/concrete/form-spp.ts
+++ b/src/app/formulaire/definition/concrete/form-spp.ts
@@ -1,23 +1,18 @@
-import { FormulaireBase } from "./form-base";
-import { FieldsetTemplate } from "../../fieldset-template";
+import { FormulaireRepeatableFieldset } from "./form-repeatable-fieldset";
 import { FieldSet } from "../../fieldset";
 import { FormulaireNode } from "../../formulaire-node";
 import { FieldsetContainer } from "../../fieldset-container";
 
-import { SPP, Nub, Props, Session, YAXN, IObservable } from "jalhyd";
+import { Nub, IObservable } from "jalhyd";
 
 /**
  * Formulaire pour "somme / produit de puissances"
  */
-export class FormulaireSPP extends FormulaireBase {
+export class FormulaireSPP extends FormulaireRepeatableFieldset {
 
     /** id of select configuring operation */
     private _operationSelectId: string;
 
-    public get sppNub(): SPP {
-        return this.currentNub as SPP;
-    }
-
     protected parseOptions(json: {}) {
         super.parseOptions(json);
         this._operationSelectId = this.getOption(json, "operationSelectId");
@@ -32,30 +27,6 @@ export class FormulaireSPP extends FormulaireBase {
         }
     }
 
-    private createYaxnNub(templ: FieldsetTemplate): Nub {
-        const params = {};
-        params["calcType"] = templ.calcTypeFromConfig;
-        return this.createYaxn(new Props(params));
-    }
-
-    /**
-     * ajoute un nub YAXN
-     * @param mr nub à ajouter
-     * @param after position après laquelle insérer le nub, à la fin sinon
-     */
-    private addYaxnNub(mr: YAXN, after?: number) {
-        this.sppNub.addChild(mr, after);
-    }
-
-    /**
-     * Asks JaLHyd to create a YAXN nub as a child of the current Calculator Module
-     * and return it; does not store it in the Session (for YAXN, not for Calculator Modules)
-     * @param p properties for the new Nub
-     */
-    protected createYaxn(p: Props): YAXN {
-        return Session.getInstance().createNub(p, this.sppNub) as YAXN;
-    }
-
     public createFieldset(parent: FormulaireNode, json: {}, data?: {}, nub?: Nub): FieldSet {
         if (json["calcType"] === "YAXN") {
             // indice après lequel insérer le nouveau FieldSet
@@ -66,8 +37,8 @@ export class FormulaireSPP extends FormulaireBase {
             if (nub) { // use existing Nub (build interface based on model)
                 mrn = nub;
             } else {
-                mrn = this.createYaxnNub(data["template"]);
-                this.addYaxnNub(mrn as YAXN, after);
+                mrn = this.createChildNub(data["template"]);
+                this.currentNub.addChild(mrn, after);
             }
             res.setNub(mrn, false);
 
@@ -85,39 +56,12 @@ export class FormulaireSPP extends FormulaireBase {
         }
     }
 
-    public moveFieldsetUp(fs: FieldSet) {
-        if (fs.nub instanceof YAXN) {
-            // déplacement du nub
-            fs.nub.parent.moveChildUp(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetUp(fs);
-
-            this.resetResults();
-        } else {
-            super.moveFieldsetUp(fs);
+    protected get fieldsetContainer(): FieldsetContainer {
+        const n = this.getFormulaireNodeById("yaxn_container");
+        if (n === undefined || !(n instanceof FieldsetContainer)) {
+            throw new Error("l'élément 'yaxn_container' n'est pas du type FieldsetContainer");
         }
-    }
-
-    public moveFieldsetDown(fs: FieldSet) {
-        if (fs.nub instanceof YAXN) {
-            // déplacement du nub
-            fs.nub.parent.moveChildDown(fs.nub);
-            // déplacement du fieldset
-            this.fieldsetContainer.moveFieldsetDown(fs);
-
-            this.resetResults();
-        } else { super.moveFieldsetDown(fs); }
-    }
-
-    public removeFieldset(fs: FieldSet) {
-        if (fs.nub instanceof YAXN) {
-            // suppression du sous-nub dans le Nub parent
-            this.sppNub.deleteChild(fs.nub.findPositionInParent());
-            // suppression du fieldset
-            this.fieldsetContainer.removeFieldset(fs);
-
-            this.resetResults();
-        } else { super.removeFieldset(fs); }
+        return n as FieldsetContainer;
     }
 
     // interface Observer
@@ -128,12 +72,4 @@ export class FormulaireSPP extends FormulaireBase {
             this.reset();
         }
     }
-
-    private get fieldsetContainer(): FieldsetContainer {
-        const n = this.getFormulaireNodeById("yaxn_container");
-        if (n === undefined || !(n instanceof FieldsetContainer)) {
-            throw new Error("l'élément 'yaxn_container' n'est pas du type FieldsetContainer");
-        }
-        return n as FieldsetContainer;
-    }
 }
-- 
GitLab