Arcane  v3.16.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CaseOptionExtended.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CaseOptionExtended.cc (C) 2000-2025 */
9/* */
10/* Option du jeu de données de type 'Extended'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/CaseOptionExtended.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/ApplicationInfo.h"
19#include "arcane/utils/CommandLineArguments.h"
20#include "arcane/utils/ParameterList.h"
21#include "arcane/utils/ParameterCaseOption.h"
22#include "arcane/utils/StringBuilder.h"
23
24#include "arcane/core/IApplication.h"
25#include "arcane/core/ICaseMng.h"
26#include "arcane/core/CaseOptionError.h"
27#include "arcane/core/ICaseDocumentVisitor.h"
28#include "arcane/core/XmlNodeList.h"
29#include "arcane/core/ICaseOptionList.h"
30#include "arcane/core/MeshHandle.h"
31#include "arcane/core/ICaseDocument.h"
32#include "arcane/core/CaseOptionException.h"
33#include "arcane/core/internal/StringVariableReplace.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43/*!
44 * \brief Cherche la valeur de l'option dans le jeu de données.
45 *
46 * La valeur trouvée est stockée dans \a m_value.
47 *
48 * Si la valeur n'est pas présente dans le jeu de données, regarde s'il
49 * existe une valeur par défaut et utilise cette dernière.
50 */
52_search(bool is_phase1)
53{
54 ITraceMng* tm = traceMng();
56 const ParameterCaseOption pco{ params.getParameterCaseOption(caseDocumentFragment()->language()) };
57 String full_xpath = String::format("{0}/{1}", rootElement().xpathFullName(), name());
58
59 // !!! En XML, on commence par 1 et non 0.
60 UniqueArray<Integer> option_in_param;
61
62 pco.indexesInParam(full_xpath, option_in_param, false);
63
64 XmlNodeList elem_list = rootElement().children(name());
65 Integer size = elem_list.size();
66 bool is_optional = isOptional();
67
68 if (size == 0 && option_in_param.empty() && is_optional) {
69 return;
70 }
71
72 Integer min_occurs = minOccurs();
73 Integer max_occurs = maxOccurs();
74
75 Integer max_in_param = 0;
76
77 // On regarde si l'utilisateur n'a pas mis un indice trop élevé pour l'option dans la ligne de commande.
78 if (!option_in_param.empty()) {
79 max_in_param = option_in_param[0];
80 for (Integer index : option_in_param) {
81 if (index > max_in_param)
82 max_in_param = index;
83 }
84 if (max_occurs >= 0) {
85 if (max_in_param > max_occurs) {
86 StringBuilder msg = "Bad number of occurences in command line (greater than max)";
87 msg += " index_max_in_param=";
88 msg += max_in_param;
89 msg += " max_occur=";
90 msg += max_occurs;
91 msg += " option=";
92 msg += full_xpath;
93 throw CaseOptionException(A_FUNCINFO, msg.toString(), true);
94 }
95 }
96 }
97
98 if (max_occurs >= 0) {
99 if (size > max_occurs) {
100 StringBuilder msg = "Bad number of occurences (greater than max)";
101 msg += " nb_occur=";
102 msg += size;
103 msg += " max_occur=";
104 msg += max_occurs;
105 msg += " option=";
106 msg += full_xpath;
107 throw CaseOptionException(A_FUNCINFO, msg.toString(), true);
108 }
109 }
110
111 // Il y aura toujours au moins min_occurs options.
112 // S'il n'y a pas assez l'options dans le jeu de données et dans les paramètres de la
113 // ligne de commande, on ajoute des services par défaut (si pas de défaut, il y aura un plantage).
114 Integer final_size = std::max(size, std::max(min_occurs, max_in_param));
115
116 if (is_phase1) {
117 _allocate(final_size);
118 m_values.resize(final_size);
119 }
120 else {
121 // D'abord, on aura les options du jeu de données : comme on ne peut pas définir un indice
122 // pour les options dans le jeu de données, elles seront forcément au début et seront contigües.
123 // Puis, s'il manque des options pour atteindre le min_occurs, on ajoute des options par défaut.
124 // S'il n'y a pas d'option par défaut, il y aura une exception.
125 // Enfin, l'utilisateur peut avoir ajouté des options à partir de la ligne de commande. On les ajoute alors.
126 // Si l'utilisateur souhaite modifier des valeurs du jeu de données à partir de la ligne de commande, on
127 // remplace les options au fur et à mesure de la lecture.
128 for (Integer i = 0; i < final_size; ++i) {
129 String str_val;
130
131 // Partie paramètres de la ligne de commande.
132 if (option_in_param.contains(i + 1)) {
133 str_val = pco.getParameterOrNull(full_xpath, i + 1, false);
134 }
135
136 // Partie jeu de données.
137 else if (i < size) {
138 XmlNode velem = elem_list[i];
139 if (!velem.null()) {
140 str_val = velem.value();
141 }
142 }
143
144 // Valeur par défaut.
145 if (str_val.null()) {
146 str_val = _defaultValue();
147 }
148 else {
149 // Dans un else : Le remplacement de symboles ne s'applique pas pour les valeurs par défault du .axl.
150 str_val = StringVariableReplace::replaceWithCmdLineArgs(params, str_val, true);
151 }
152
153 // Maintenant, ce plantage concerne aussi le cas où il n'y a pas de valeurs par défaut et qu'il n'y a
154 // pas assez d'options pour atteindre le min_occurs.
155 if (str_val.null()) {
157 name(),rootElement());
158 continue;
159 }
160 tm->info(5) << "TryConvert opt=" << _xpathFullName() << " i=" << i
161 << " mesh_name=" << parentOptionList()->meshHandle().meshName()
162 << " value=" << str_val;
163 bool is_bad = _tryToConvert(str_val,i);
164 if (is_bad){
165 m_values[i] = String();
167 name(),rootElement(),str_val,_typeName());
168 continue;
169 }
170 m_values[i] = str_val;
171 //ptr_value[i] = val;
172 //cerr << "** FOUND " << val << endl;
173 }
174 }
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
179
181print(const String& lang,std::ostream& o) const
182{
183 ARCANE_UNUSED(lang);
184 for( Integer i=0, s=_nbElem(); i<s; ++i )
185 o << m_values[i] << " ";
186}
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
190
192visit(ICaseDocumentVisitor* visitor) const
193{
194 visitor->applyVisitor(this);
195}
196
197/*---------------------------------------------------------------------------*/
198/*---------------------------------------------------------------------------*/
199
201setDefaultValue(const String& def_value)
202{
203 // Si on a une valeur donnée par l'utilisateur, on ne fait rien.
204 if (isPresent())
205 return;
206
207 // Valeur déjà initialisée. Dans ce cas on remplace aussi la valeur
208 // actuelle.
209 if (_isInitialized()){
210 bool is_bad = _tryToConvert(def_value);
211 if (is_bad){
212 m_value = String();
213 ARCANE_FATAL("Can not convert '{0}' to type '{1}' (option='{2}')",
214 def_value,_typeName(),xpathFullName());
215 }
216 m_value = def_value;
217 }
218
219 // La valeur par défaut n'a pas de langue associée.
220 _setDefaultValue(def_value);
221}
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225/*!
226 * \brief Cherche la valeur de l'option dans le jeu de donnée.
227 *
228 * La valeur trouvée est stockée dans \a m_value.
229 *
230 * Si la valeur n'est pas présente dans le jeu de donnée, regarde s'il
231 * existe une valeur par défaut et utilise cette dernière.
232 */
234_search(bool is_phase1)
235{
236 CaseOptionSimple::_search(is_phase1);
237 if (is_phase1)
238 return;
239 ITraceMng* tm = traceMng();
240 // Si l'option n'est pas présente dans le jeu de donnée, on prend
241 // l'option par défaut.
242 String str_val = (_element().null()) ? _defaultValue() : _element().value();
243 bool has_valid_value = true;
244 if (str_val.null()) {
245 m_value = String();
246 if (!isOptional()){
248 name(),rootElement());
249 return;
250 }
251 else
252 has_valid_value = false;
253 }
254 _setHasValidValue(has_valid_value);
255 if (has_valid_value){
256 tm->info(5) << "TryConvert opt=" << xpathFullName()
257 << " mesh_name=" << parentOptionList()->meshHandle().meshName()
258 << " value=" << str_val;
259 bool is_bad = _tryToConvert(str_val);
260 if (is_bad){
261 m_value = String();
263 name(),rootElement(),str_val,_typeName());
264 return;
265 }
266 m_value = str_val;
267 }
268 _setIsInitialized();
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
275print(const String& lang,std::ostream& o) const
276{
277 ARCANE_UNUSED(lang);
278 _checkIsInitialized();
279 if (hasValidValue())
280 o << m_value;
281 else
282 o << "undefined";
283}
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
289visit(ICaseDocumentVisitor* visitor) const
290{
291 visitor->applyVisitor(this);
292}
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
297} // End namespace Arcane
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
bool contains(ConstReferenceType v) const
Vrai si le tableau contient l'élément de valeur v.
const CommandLineArguments & commandLineArguments() const
Arguments de la ligne de commande.
String name() const
Retourne le nom de l'option correspondant au langage du jeu de données.
String _defaultValue() const
Retourne la valeur par défaut de l'option ou 0 s'il n'y en a pas.
ICaseMng * caseMng() const
Gestionnaire de cas.
ICaseDocumentFragment * caseDocumentFragment() const
Retourne le document associé à cette option.
bool isOptional() const
Permet de savoir si une option est optionnelle.
Integer maxOccurs() const
Nombre maximum d'occurences (pour une option multiple) (-1 == unbounded)
XmlNode rootElement() const
Retourne l'élément racine du DOM.
ITraceMng * traceMng() const
Gestionnaire de traces.
ICaseOptionList * parentOptionList() const
OptionList parent.
Integer minOccurs() const
Nombre minimum d'occurences (pour une option multiple)
static void addInvalidTypeError(ICaseDocumentFragment *document, const TraceInfo &where, const String &node_name, const XmlNode &parent, const String &value, const String &expected_type)
Erreur lorsqu'une valeur d'une jeu de données n'est pas du bon type. Cette erreur est collective.
static void addOptionNotFoundError(ICaseDocumentFragment *document, const TraceInfo &where, const String &node_name, const XmlNode &parent)
Erreur lorsqu'une option du jeu de données n'est pas trouvée. Cette erreur est collective.
Exception en rapport avec le jeu de données.
void _search(bool is_phase1) override
Cherche la valeur de l'option dans le jeu de donnée.
void setDefaultValue(const String &def_value)
Positionne la valeur par défaut de l'option.
void print(const String &lang, std::ostream &o) const override
Imprime la valeur de l'option dans le langage lang,sur le flot o.
void visit(ICaseDocumentVisitor *visitor) const override
Applique le visiteur sur cette option.
void print(const String &lang, std::ostream &o) const override
Imprime la valeur de l'option dans le langage lang,sur le flot o.
void _search(bool is_phase1) override
Cherche la valeur de l'option dans le jeu de données.
void visit(ICaseDocumentVisitor *visitor) const override
Applique le visiteur sur cette option.
String xpathFullName() const
Nom complet au format donné par la norme XPath.
bool hasValidValue() const
Indique si l'option a une valeur invalide.
bool isOptional() const
Indique si l'option est facultative.
bool isPresent() const
Retourne true si l'option est présente.
const ParameterList & parameters() const
Liste des paramètres.
virtual const ApplicationInfo & applicationInfo() const =0
Informations sur l'exécutable.
Interface du visiteur pour une option du jeu de données.
virtual IApplication * application()=0
Application associée.
virtual MeshHandle meshHandle() const =0
Handle du maillage associé
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Classe représentant l'ensemble des paramètres pouvant modifier les options du jeu de données.
Liste de paramètres.
ParameterCaseOption getParameterCaseOption(const String &language) const
Méthode permettant de récupérer un objet de type ParameterCaseOption.
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
Vecteur 1D de données avec sémantique par valeur (style STL).
Liste de noeuds d'un arbre DOM.
Definition XmlNodeList.h:33
Noeud d'un arbre DOM.
Definition XmlNode.h:51
String value() const
Valeur du noeud.
Definition XmlNode.cc:199
XmlNodeList children(const String &name) const
Ensemble des noeuds fils de ce noeud ayant pour nom name.
Definition XmlNode.cc:93
bool null() const
Vrai si le noeud est nul.
Definition XmlNode.h:294
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.