Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
CaseOptionEnum.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* CaseOptionEnum.cc (C) 2000-2023 */
9/* */
10/* Enumerated data set option. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/CaseOptionEnum.h"
15
16#include "arcane/utils/Array.h"
17#include "arcane/utils/ITraceMng.h"
18
19#include "arcane/core/ICaseFunction.h"
20#include "arcane/core/ICaseMng.h"
21#include "arcane/core/ICaseDocument.h"
22#include "arcane/core/StringDictionary.h"
23#include "arcane/core/CaseOptionError.h"
24#include "arcane/core/ICaseDocumentVisitor.h"
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29namespace Arcane
30{
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
36CaseOptionName(const String& aname)
37: m_true_name(aname)
38, m_translations(0)
39{
40}
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
47: m_true_name(rhs.m_true_name)
48, m_translations(0)
49{
50 if (rhs.m_translations)
51 m_translations = new StringDictionary(*rhs.m_translations);
52}
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
59{
60 delete m_translations;
61}
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
67addAlternativeNodeName(const String& lang, const String& name)
68{
69 if (!m_translations)
70 m_translations = new StringDictionary();
71 m_translations->add(lang, name);
72}
73
74/*---------------------------------------------------------------------------*/
75/*---------------------------------------------------------------------------*/
76
78name(const String& lang) const
79{
80 if (!m_translations || lang.null())
81 return m_true_name;
82 String s = m_translations->find(lang);
83 if (s.null())
84 return m_true_name;
85 return s;
86}
87
88/*---------------------------------------------------------------------------*/
89/*---------------------------------------------------------------------------*/
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
94CaseOptionEnumValue::
95CaseOptionEnumValue(const String& name, int value)
96: CaseOptionName(name)
97, m_value(value)
98{
99}
100
101CaseOptionEnumValue::
102CaseOptionEnumValue(const CaseOptionEnumValue& rhs)
103: CaseOptionName(rhs)
104, m_value(rhs.m_value)
105{
106}
107
108CaseOptionEnumValue::
109~CaseOptionEnumValue()
110{
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116/*---------------------------------------------------------------------------*/
117/*---------------------------------------------------------------------------*/
118
121: m_enum_values(new EnumValueList())
122{
123}
124
127{
128 for (auto i : (*m_enum_values)) {
129 delete i;
130 }
131 delete m_enum_values;
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
138enumValue(Integer index) const
139{
140 return (*m_enum_values)[index];
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
147addEnumValue(CaseOptionEnumValue* value, bool do_clone)
148{
149 CaseOptionEnumValue* svalue = value;
150 if (do_clone)
151 svalue = new CaseOptionEnumValue(*value);
152 m_enum_values->add(svalue);
153}
154
156nbEnumValue() const
157{
158 return m_enum_values->size();
159}
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
165valueOfName(const String& name, const String& lang, int& value) const
166{
167 for (auto ev : (*m_enum_values)) {
168 const String& n = ev->name(lang);
169 if (n == name) {
170 value = ev->value();
171 return false;
172 }
173 }
174 return true;
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
179
181nameOfValue(int value, const String& lang) const
182{
183 String s;
184 for (auto ev : (*m_enum_values)) {
185 if (ev->value() == value) {
186 s = ev->name(lang);
187 break;
188 }
189 }
190 return s;
191}
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
195
197getValidNames(const String& lang, StringArray& names) const
198{
199 for (auto ev : (*m_enum_values)) {
200 names.add(ev->name(lang));
201 }
202}
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
210CaseOptionEnum::
211CaseOptionEnum(const CaseOptionBuildInfo& cob, const String& type_name)
212: CaseOptionSimple(cob)
213, m_type_name(type_name)
214, m_enum_values(new CaseOptionEnumValues())
215{
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
221CaseOptionEnum::
222~CaseOptionEnum()
223{
224 delete m_enum_values;
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230void CaseOptionEnum::
231_search(bool is_phase1)
232{
233 CaseOptionSimple::_search(is_phase1);
234 if (!is_phase1)
235 return;
236 bool is_default = _element().null();
237 String str_val = (is_default) ? _defaultValue() : _element().value();
238 bool has_valid_value = true;
239 if (str_val.null()) {
240 if (!isOptional()) {
242 name(), rootElement());
243
244 return;
245 }
246 else
247 has_valid_value = false;
248 }
249 _setHasValidValue(has_valid_value);
250
251 if (has_valid_value) {
252 String lang;
253 // The default value does not have an associated language. Therefore, it
254 // should not be attempted to convert it.
255 if (!is_default)
256 lang = caseDocumentFragment()->language();
257 int value = 0;
258 bool is_bad = m_enum_values->valueOfName(str_val, lang, value);
259
260 if (is_bad) {
261 StringUniqueArray valid_values;
262 m_enum_values->getValidNames(lang, valid_values);
264 name(), rootElement(), str_val, m_type_name, valid_values);
265 return;
266 }
267 _setOptionValue(value);
268 }
269
270 _setIsInitialized();
271}
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
276void CaseOptionEnum::
277_setEnumDefaultValue(int def_value)
278{
279 // If a value is provided by the user, do nothing.
280 if (isPresent())
281 return;
282
283 // Value already initialized. In this case, the current value is also replaced
284 if (_isInitialized())
285 _setOptionValue(def_value);
286
287 // The default value does not have an associated language.
288 _setDefaultValue(m_enum_values->nameOfValue(def_value, String()));
289}
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293
295print(const String& lang, std::ostream& o) const
296{
297 _checkIsInitialized();
298 int v = _optionValue();
299 o << "'" << m_enum_values->nameOfValue(v, lang) << "' (" << v << ")";
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
306visit(ICaseDocumentVisitor* visitor) const
307{
308 visitor->applyVisitor(this);
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
314void CaseOptionEnum::
315_updateFromFunction(Real current_time, Integer current_iteration)
316{
317 _checkIsInitialized();
318 ICaseFunction* func = function();
319 ITraceMng* msg = caseMng()->traceMng();
321 int current_value = _optionValue();
322 String new_str = m_enum_values->nameOfValue(current_value, lang);
323 switch (func->paramType()) {
325 new_str = _convertFunctionRealToString(func, current_time);
326 break;
328 new_str = _convertFunctionIntegerToString(func, current_iteration);
329 break;
331 break;
332 }
333 int new_value = 0;
334 bool is_bad = m_enum_values->valueOfName(new_str, lang, new_value);
335 if (is_bad) {
336 StringUniqueArray valid_values;
337 m_enum_values->getValidNames(lang, valid_values);
339 name(), rootElement(), new_str, m_type_name, valid_values);
340 return;
341 //throw CaseOptionException("get_value",name(),rootElement(),new_str,m_type_name);
342 }
343 msg->debug() << "New value for enum option <" << name() << "> " << new_value;
344 bool has_changed = new_value != current_value;
345 _setChangedSinceLastIteration(has_changed);
346 if (has_changed)
347 _setOptionValue(new_value);
348}
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
353/*---------------------------------------------------------------------------*/
354/*---------------------------------------------------------------------------*/
355
356CaseOptionMultiEnum::
357CaseOptionMultiEnum(const CaseOptionBuildInfo& cob, const String& type_name)
358: CaseOptionBase(cob)
359, m_type_name(type_name)
360, m_enum_values(new CaseOptionEnumValues())
361{
362}
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
366
367CaseOptionMultiEnum::
368~CaseOptionMultiEnum()
369{
370 delete m_enum_values;
371}
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
375
376void CaseOptionMultiEnum::
377_search(bool is_phase1)
378{
379 XmlNodeList elem_list = rootElement().children(name());
380
381 Integer size = elem_list.size();
382 _checkMinMaxOccurs(size);
383 if (size == 0)
384 return;
385
386 if (is_phase1) {
387 _allocate(size);
388
389 const String& lang = caseDocumentFragment()->language();
390
391 for (Integer index = 0; index < size; ++index) {
392 XmlNode velem = elem_list[index];
393 // If the option is not present in the dataset, the default option is taken.
394 String str_val = (velem.null()) ? _defaultValue() : velem.value();
395 if (str_val.null()) {
396 CaseOptionError::addOptionNotFoundError(caseDocumentFragment(), A_FUNCINFO,
397 name(), rootElement());
398 continue;
399 //throw CaseOptionException("get_value",name(),rootElement());
400 }
401
402 int value = 0;
403 bool is_bad = m_enum_values->valueOfName(str_val, lang, value);
404
405 if (is_bad) {
406 StringUniqueArray valid_values;
407 m_enum_values->getValidNames(lang, valid_values);
409 name(), rootElement(), str_val, m_type_name, valid_values);
410 continue;
411 //throw CaseOptionException("get_value",name(),rootElement(),str_val,m_type_name);
412 }
413 else
414 _setOptionValue(index, value);
415 }
416 }
417}
418
419/*---------------------------------------------------------------------------*/
420/*---------------------------------------------------------------------------*/
421
423print(const String& lang, std::ostream& o) const
424{
425 for (Integer i = 0, s = _nbElem(); i < s; ++i) {
426 int v = _optionValue(i);
427 o << "'" << m_enum_values->nameOfValue(v, lang) << "' (" << v << ")";
428 }
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
435visit(ICaseDocumentVisitor* visitor) const
436{
437 visitor->applyVisitor(this);
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443} // End namespace Arcane
444
445/*---------------------------------------------------------------------------*/
446/*---------------------------------------------------------------------------*/
void add(ConstReferenceType val)
Adds element val to the end of the array.
Base class for a data set option.
String name() const
Returns the option name corresponding to the data set language.
String _defaultValue() const
Returns the default value of the option or 0 if none exists.
ICaseMng * caseMng() const
Case manager.
ICaseDocumentFragment * caseDocumentFragment() const
Returns the document associated with this option.
XmlNode rootElement() const
Returns the root element of the DOM.
String nameOfValue(int value, const String &lang) const
Returns the name corresponding to the value value for the language lang.
CaseOptionEnumValues()
Constructs the instance.
UniqueArray< CaseOptionEnumValue * > EnumValueList
Type of the value list.
void getValidNames(const String &lang, StringArray &names) const
Fills names with valid names for the language lang.
~CaseOptionEnumValues()
Releases resources.
bool valueOfName(const String &name, const String &lang, int &value) const
Returns the value of the enumeration having the name name.
Integer nbEnumValue() const
Returns the number of enumeration values.
CaseOptionEnumValue * enumValue(Integer index) const
Returns the i-th value.
void addEnumValue(CaseOptionEnumValue *value, bool do_clone)
Adds the enumeration value value. The instance becomes the owner of value, which is destroyed when it...
virtual void print(const String &lang, std::ostream &o) const
Prints the option value in the language lang, to the stream o.
virtual void _setOptionValue(int v)=0
Sets the option value to v.
virtual int _optionValue() const =0
Returns the option value.
virtual void visit(ICaseDocumentVisitor *visitor) const
Applies the visitor to this option.
static void addInvalidTypeError(ICaseDocumentFragment *document, const TraceInfo &where, const String &node_name, const XmlNode &parent, const String &value, const String &expected_type)
Error when a dataset value is not of the correct type. This error is collective.
static void addOptionNotFoundError(ICaseDocumentFragment *document, const TraceInfo &where, const String &node_name, const XmlNode &parent)
Error when a dataset option is not found. This error is collective.
virtual void visit(ICaseDocumentVisitor *visitor) const
Applies the visitor to this option.
virtual Integer _nbElem() const =0
Returns the number of elements in the array.
virtual void print(const String &lang, std::ostream &o) const
Prints the option value in the language lang, to the stream o.
virtual void _allocate(Integer size)=0
Allocates an array for size elements.
virtual int _optionValue(Integer index) const =0
Returns the enumeration value for index index.
virtual void _setOptionValue(Integer index, int v)=0
String name(const String &lang) const
returns the name of the option in the language lang. If no translation is available in the language l...
virtual ~CaseOptionName()
Releases resources.
CaseOptionName(const String &true_name)
Constructs a name option true_name.
void addAlternativeNodeName(const String &lang, const String &tname)
Adds a translation for the option name. Adds the name tname corresponding to the language lang....
Base class for simple options (single value).
ICaseFunction * function() const override
Function associated with this option (0 if none).
bool isOptional() const
Indicates if the option is optional.
bool isPresent() const
Returns true if the option is present.
virtual String language() const =0
Language used in the dataset.
Visitor interface for a dataset option.
@ ParamUnknown
Unknown parameter type.
@ ParamReal
Real type parameter.
@ ParamInteger
Integer type parameter.
virtual eParamType paramType() const =0
Function parameter type.
virtual ITraceMng * traceMng()=0
Trace manager.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Stream for a debug message.
bool null() const
Returns true if the string is null.
Definition String.cc:306
XmlNodeList children(const String &name) const
Set of child nodes of this node having the name name.
Definition XmlNode.cc:102
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< String > StringArray
Dynamic one-dimensional array of strings.
Definition UtilsTypes.h:145
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:359