Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
CaseOptions.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/* CaseOptions.cc (C) 2000-2023 */
9/* */
10/* Data set options management. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/CaseOptions.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FatalErrorException.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/CaseNodeNames.h"
24#include "arcane/core/CaseOptionError.h"
25#include "arcane/core/ICaseDocumentVisitor.h"
26#include "arcane/core/MeshHandle.h"
27#include "arcane/core/IMeshMng.h"
28#include "arcane/core/IXmlDocumentHolder.h"
29#include "arcane/core/internal/ICaseMngInternal.h"
30#include "arcane/core/internal/ICaseOptionListInternal.h"
31
32#include "arcane/core/CaseOptionsMulti.h"
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43namespace AxlOptionsBuilder
44{
45 extern "C++" IXmlDocumentHolder*
46 documentToXml(const Document& d);
47}
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
57class CaseOptionsPrivate
58{
59 public:
60
61 CaseOptionsPrivate(ICaseMng* cm, const String& name)
62 : m_case_mng(cm)
63 , m_name(name)
64 , m_true_name(name)
65 , m_mesh_handle(cm->meshMng()->defaultMeshHandle())
66 {
67 }
68
69 CaseOptionsPrivate(ICaseOptionList* co_list, const String& name)
70 : m_case_mng(co_list->caseMng())
71 , m_name(name)
72 , m_true_name(name)
73 , m_mesh_handle(co_list->meshHandle())
74 {
75 if (m_mesh_handle.isNull())
76 m_mesh_handle = m_case_mng->meshMng()->defaultMeshHandle();
77 }
78
79 ~CaseOptionsPrivate()
80 {
81 delete m_own_case_document_fragment;
82 }
83
84 public:
85
86 ICaseOptionList* m_parent = nullptr;
87 ICaseMng* m_case_mng;
89 IModule* m_module = nullptr;
91 String m_name;
92 String m_true_name;
93 bool m_is_multi = false;
94 bool m_is_translated_name_set = false;
95 bool m_is_phase1_read = false;
96 StringDictionary m_name_translations;
98 bool m_is_case_mng_registered = false;
99 MeshHandle m_mesh_handle;
100 // non-null if we own our own document instance
101 ICaseDocumentFragment* m_own_case_document_fragment = nullptr;
102 Ref<ICaseMng> m_case_mng_ref;
103};
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
109CaseOptions(ICaseMng* cm, const String& name)
110: m_p(new CaseOptionsPrivate(cm, name))
111{
112 m_p->m_config_list = ICaseOptionListInternal::create(cm, this, XmlNode());
113 m_p->m_is_case_mng_registered = true;
114 cm->registerOptions(this);
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
121CaseOptions(ICaseOptionList* parent, const String& aname)
122: m_p(new CaseOptionsPrivate(parent, aname))
123{
124 m_p->m_config_list = ICaseOptionListInternal::create(parent, this, XmlNode());
125 _setParent(parent);
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
132CaseOptions(ICaseMng* cm, const String& aname, const XmlNode& parent_elem)
133: m_p(new CaseOptionsPrivate(cm, aname))
134{
135 m_p->m_config_list = ICaseOptionListInternal::create(cm, this, parent_elem);
136 m_p->m_is_case_mng_registered = true;
137 cm->registerOptions(this);
138}
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
144CaseOptions(ICaseOptionList* parent, const String& aname,
145 const XmlNode& parent_elem, bool is_optional, bool is_multi)
146: m_p(new CaseOptionsPrivate(parent, aname))
147{
148 ICaseOptionList* col = ICaseOptionListInternal::create(parent, this, parent_elem, is_optional, is_multi);
149 m_p->m_config_list = col;
150 _setParent(parent);
151 if (is_multi)
152 _setTranslatedName();
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
159CaseOptions(ICaseMng* cm, const String& aname, ICaseOptionList* config_list)
160: m_p(new CaseOptionsPrivate(cm, aname))
161{
162 m_p->m_config_list = config_list;
163 m_p->m_is_case_mng_registered = true;
164 cm->registerOptions(this);
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
171CaseOptions(ICaseOptionList* parent, const String& aname,
172 ICaseOptionList* config_list)
173: m_p(new CaseOptionsPrivate(parent->caseMng(), aname))
174{
175 m_p->m_config_list = config_list;
176 _setParent(parent);
177}
178
179/*---------------------------------------------------------------------------*/
180/*---------------------------------------------------------------------------*/
181
183CaseOptions(ICaseMng* cm, const XmlContent& xml_content)
184: m_p(new CaseOptionsPrivate(cm, "dynamic-options"))
185{
186 // This constructor is for dynamically created options
187 IXmlDocumentHolder* xml_doc = xml_content.m_document;
188 XmlNode parent_elem = xml_doc->documentNode().documentElement();
189 m_p->m_config_list = ICaseOptionListInternal::create(cm, this, parent_elem);
190 m_p->m_own_case_document_fragment = cm->_internalImpl()->createDocumentFragment(xml_doc);
191 // Keeps a reference to the ICaseMng in case this option
192 // is destroyed after the end of the calculation and the destruction of subdomains.
193 m_p->m_case_mng_ref = cm->toReference();
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
201{
202 detach();
203 if (m_p->m_is_case_mng_registered)
204 m_p->m_case_mng->unregisterOptions(this);
205 delete m_p;
206}
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
211/*---------------------------------------------------------------------------*/
212/*---------------------------------------------------------------------------*/
213
215detach()
216{
217 if (m_p->m_parent)
218 m_p->m_parent->removeChild(this);
219 m_p->m_parent = nullptr;
220 m_p->m_config_list = nullptr;
221}
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225
227rootTagTrueName() const
228{
229 return m_p->m_true_name;
230}
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
236rootTagName() const
237{
238 return m_p->m_name;
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
245isPresent() const
246{
247 return m_p->m_config_list->isPresent();
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
254xpathFullName() const
255{
256 return m_p->m_config_list->xpathFullName();
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
263addAlternativeNodeName(const String& lang, const String& name)
264{
265 // Translations should not be modified once the translated name
266 // has been set. This can happen with services if they have a translation
267 // in their axl. In this case, this last one overrides the parent option,
268 // which can make the names inconsistent.
269 if (m_p->m_is_translated_name_set)
270 return;
271 m_p->m_name_translations.add(lang, name);
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
277ICaseOptionList* CaseOptions::
278configList()
279{
280 return m_p->m_config_list.get();
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
286const ICaseOptionList* CaseOptions::
287configList() const
288{
289 return m_p->m_config_list.get();
290}
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
294
296caseServiceInfo() const
297{
298 return m_p->m_service_info;
299}
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
305caseModule() const
306{
307 return m_p->m_module;
308}
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312
315{
316 m_p->m_service_info = m;
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
324{
325 m_p->m_module = m;
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330
331ICaseMng* CaseOptions::
332caseMng() const
333{
334 return m_p->m_case_mng;
335}
336
337/*---------------------------------------------------------------------------*/
338/*---------------------------------------------------------------------------*/
339
340ITraceMng* CaseOptions::
341traceMng() const
342{
343 return m_p->m_case_mng->traceMng();
344}
345
346/*---------------------------------------------------------------------------*/
347/*---------------------------------------------------------------------------*/
348
350subDomain() const
351{
352 return m_p->m_case_mng->subDomain();
353}
354
355/*---------------------------------------------------------------------------*/
356/*---------------------------------------------------------------------------*/
357
358MeshHandle CaseOptions::
359meshHandle() const
360{
361 return m_p->m_mesh_handle;
362}
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
366
367IMesh* CaseOptions::
368mesh() const
369{
370 return meshHandle().mesh();
371}
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
375
376ICaseDocument* CaseOptions::
377caseDocument() const
378{
379 return caseMng()->caseDocument();
380}
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
385ICaseDocumentFragment* CaseOptions::
386caseDocumentFragment() const
387{
388 auto* x = m_p->m_own_case_document_fragment;
389 if (x)
390 return x;
391 return caseMng()->caseDocumentFragment();
392}
393
394/*---------------------------------------------------------------------------*/
395/*---------------------------------------------------------------------------*/
396
397void CaseOptions::
398_setMeshHandle(const MeshHandle& handle)
399{
400 traceMng()->info(5) << "SetMeshHandle for " << m_p->m_name << " mesh_name=" << handle.meshName();
401 m_p->m_mesh_handle = handle;
402}
403
404/*---------------------------------------------------------------------------*/
405/*---------------------------------------------------------------------------*/
406
407void CaseOptions::
408_setParent(ICaseOptionList* parent)
409{
410 parent->addChild(this);
411 m_p->m_parent = parent;
412 _setMeshHandle(parent->meshHandle());
413}
414
415/*---------------------------------------------------------------------------*/
416/*---------------------------------------------------------------------------*/
417
435{
436 if (mesh_name.empty()) {
437 // My mesh is that of my parent
438 if (m_p->m_parent)
439 _setMeshHandle(m_p->m_parent->meshHandle());
440 }
441 else {
442 // A mesh different from the default mesh is associated with the option.
443 // Retrieve the associated MeshHandle if it exists. If it doesn't,
444 // disable the option.
445 // If no mesh with the name we are looking for exists, do not allocate the service
446 MeshHandle* handle = caseMng()->meshMng()->findMeshHandle(mesh_name, false);
447 if (!handle) {
448 m_p->m_config_list->disable();
449 return true;
450 }
451 _setMeshHandle(*handle);
452 }
453 return false;
454}
455
456/*---------------------------------------------------------------------------*/
457/*---------------------------------------------------------------------------*/
458
459void CaseOptions::
460_setTranslatedName()
461{
462 String lang = caseDocumentFragment()->language();
463 if (m_p->m_is_translated_name_set)
464 traceMng()->info() << "WARNING: translated name already set for " << m_p->m_name;
465 if (lang.null())
466 m_p->m_name = m_p->m_true_name;
467 else {
468 String tr = m_p->m_name_translations.find(lang);
469 if (!tr.null()) {
470 m_p->m_name = tr;
471 }
472 }
473 m_p->m_is_translated_name_set = true;
474}
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
480translatedName(const String& lang) const
481{
482 if (!lang.null()) {
483 String tr = m_p->m_name_translations.find(lang);
484 if (!tr.null())
485 return tr;
486 }
487 return m_p->m_true_name;
488}
489
490/*---------------------------------------------------------------------------*/
491/*---------------------------------------------------------------------------*/
492
495{
496 return m_p->m_activate_function;
497}
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
502void CaseOptions::
503read(eCaseOptionReadPhase read_phase)
504{
505 ITraceMng* tm = traceMng();
506 bool is_phase1 = read_phase == eCaseOptionReadPhase::Phase1;
507 if (is_phase1 && m_p->m_is_phase1_read)
508 return;
509
510 if (is_phase1 && !m_p->m_is_translated_name_set)
511 _setTranslatedName();
512
513 m_p->m_config_list->readChildren(is_phase1);
514
515 if (is_phase1) {
516 ICaseDocumentFragment* doc = caseDocumentFragment();
517 // Read the activation function (if present)
518 XmlNode velem = m_p->m_config_list->rootElement();
519 CaseNodeNames* cnn = doc->caseNodeNames();
520 String func_activation_name = velem.attrValue(cnn->function_activation_ref);
521 if (!func_activation_name.null()) {
522 ICaseFunction* func = caseMng()->findFunction(func_activation_name);
523 if (!func) {
524 CaseOptionError::addError(doc, A_FUNCINFO, velem.xpathFullName(),
525 String::format("No function with the name '{0}' exists",
526 func_activation_name));
527 }
528 else if (func->paramType() != ICaseFunction::ParamReal) {
529 CaseOptionError::addError(doc, A_FUNCINFO, velem.xpathFullName(),
530 String::format("The function '{0}' requires a parameter of type 'time'",
531 func_activation_name));
532 }
533 else if (func->valueType() != ICaseFunction::ValueBool) {
534 CaseOptionError::addError(doc, A_FUNCINFO, velem.xpathFullName(),
535 String::format("The function '{0}' requires a parameter of type 'bool'",
536 func_activation_name));
537 }
538 else {
539 m_p->m_activate_function = func;
540 tm->info() << "Use the function '" << func->name() << "' to activate the option "
541 << velem.xpathFullName();
542 }
543 }
544 // Check that the 'function' element is not present
545 {
546 String func_name = velem.attrValue(cnn->function_ref);
547 if (!func_name.null())
548 CaseOptionError::addError(doc, A_FUNCINFO, velem.xpathFullName(),
549 String::format("Attribute <{0}> invalid.",
550 cnn->function_ref));
551 }
552 m_p->m_is_phase1_read = true;
553 }
554}
555
556/*---------------------------------------------------------------------------*/
557/*---------------------------------------------------------------------------*/
558
564{
565 m_p->m_config_list->_internalApi()->addInvalidChildren(nlist);
566}
567
568/*---------------------------------------------------------------------------*/
569/*---------------------------------------------------------------------------*/
570
571void CaseOptions::
572printChildren(const String& lang, int indent)
573{
574 m_p->m_config_list->printChildren(lang, indent);
575}
576
577/*---------------------------------------------------------------------------*/
578/*---------------------------------------------------------------------------*/
579
581visit(ICaseDocumentVisitor* visitor) const
582{
583 m_p->m_config_list->visit(visitor);
584}
585
586/*---------------------------------------------------------------------------*/
587/*---------------------------------------------------------------------------*/
588
591{
592 m_p->m_config_list->deepGetChildren(col);
593}
594
595/*---------------------------------------------------------------------------*/
596/*---------------------------------------------------------------------------*/
597
599createDynamic(ICaseMng* cm, const AxlOptionsBuilder::Document& options_doc)
600{
601 XmlContent content;
602
603 IXmlDocumentHolder* xml_doc = AxlOptionsBuilder::documentToXml(options_doc);
604 content.m_document = xml_doc;
605
606 auto* opt = new CaseOptions(cm, content);
608}
609
610/*---------------------------------------------------------------------------*/
611/*---------------------------------------------------------------------------*/
612
613Ref<ICaseOptions> CaseOptions::
614toReference()
615{
616 return makeRef<ICaseOptions>(this);
617}
618
619/*---------------------------------------------------------------------------*/
620/*---------------------------------------------------------------------------*/
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
625CaseOptionsMulti::
626CaseOptionsMulti(ICaseMng* cm, const String& aname, const XmlNode& parent_element,
627 Integer min_occurs, Integer max_occurs)
628: CaseOptions(cm, aname,
629 ICaseOptionListInternal::create(this, this, cm, parent_element,
630 min_occurs, max_occurs))
631{
632}
633
634/*---------------------------------------------------------------------------*/
635/*---------------------------------------------------------------------------*/
636
637CaseOptionsMulti::
638CaseOptionsMulti(ICaseOptionList* parent, const String& aname,
639 const XmlNode& parent_element,
640 Integer min_occurs, Integer max_occurs)
641: CaseOptions(parent, aname,
642 ICaseOptionListInternal::create(this, this, parent,
643 parent_element, min_occurs, max_occurs))
644{
645}
646
647/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649
650/*---------------------------------------------------------------------------*/
651/*---------------------------------------------------------------------------*/
652
653extern "C++" ARCANE_CORE_EXPORT ISubDomain*
654_arcaneDeprecatedGetSubDomain(ICaseOptions* opt)
655{
656 return opt->subDomain();
657}
658
659/*---------------------------------------------------------------------------*/
660/*---------------------------------------------------------------------------*/
661
662} // End namespace Arcane
663
664/*---------------------------------------------------------------------------*/
665/*---------------------------------------------------------------------------*/
Base class for 1D data vectors.
Data set 'ServiceInstance' option.
XML node names of an Arcane dataset.
static void addError(ICaseDocumentFragment *document, const TraceInfo &where, const String &node_name, const String &message, bool is_collective=false)
Generic error.
IModule * m_module
Associated module or 0 if none.
ICaseFunction * m_activate_function
Function indicating activation status.
IServiceInfo * m_service_info
Associated service or 0 if none.
Base class for a data set options list.
Definition CaseOptions.h:58
String xpathFullName() const override
Full name in XPath format corresponding to rootElement().
void addInvalidChildren(XmlNodeList &) override
Adds unrecognized elements to nlist.
bool isPresent() const override
True if the option is present in the file, false if it is the default value.
bool _setMeshHandleAndCheckDisabled(const String &mesh_name)
Positions the mesh associated with this option.
void setCaseServiceInfo(IServiceInfo *m) override
Associates service m with this data set.
void visit(ICaseDocumentVisitor *visitor) const override
Applies the visitor to this option.
void detach() override
void addAlternativeNodeName(const String &lang, const String &name) override
Adds a translation for the option name. Adds the option name name corresponding to language lang....
String rootTagName() const override
Returns the name of the element in the data set language.
String rootTagTrueName() const override
Returns the true name (non-translated) of the element.
ICaseFunction * activateFunction() override
Function indicating the activation status of the option.
void setCaseModule(IModule *m) override
Associates module m with this data set.
String translatedName(const String &lang) const override
Name in language lang of the option. Returns rootTagTrueName() if no translation exists.
virtual String name() const
Returns the name of the element in the data set language.
~CaseOptions() override
Frees resources.
IServiceInfo * caseServiceInfo() const override
Returns the associated service or 0 if none exists.
IModule * caseModule() const override
Returns the associated module or 0 if none exists.
CaseOptionsPrivate * m_p
Implementation.
ISubDomain * subDomain() const override
Associated sub-domain.
void deepGetChildren(Array< CaseOptionBase * > &col) override
Adds all child options to the list col.
CaseOptions(ICaseMng *cm, const String &name)
Constructs an options set.
Interface of a part of a dataset.
virtual CaseNodeNames * caseNodeNames()=0
Returns the instance containing the names of XML nodes by language.
virtual String language() const =0
Language used in the dataset.
Visitor interface for a dataset option.
Interface of a class managing an XML document of the dataset.
Interface of a dataset function.
@ ParamReal
Real type parameter.
@ ValueBool
Boolean type value.
virtual String name() const =0
function name
virtual eValueType valueType() const =0
Function value type.
virtual eParamType paramType() const =0
Function parameter type.
virtual ICaseDocumentFragment * createDocumentFragment(IXmlDocumentHolder *document)=0
Creates a fragment.
Case manager interface.
Definition ICaseMng.h:57
virtual ICaseMngInternal * _internalImpl()=0
Internal implementation.
virtual IMeshMng * meshMng() const =0
Associated mesh manager.
virtual ITraceMng * traceMng()=0
Trace manager.
virtual void registerOptions(ICaseOptions *)=0
Registers a list of dataset options.
Internal API of the data set options list interface.
Interface for a data set options list.
virtual ICaseMng * caseMng() const =0
Returns the case manager.
virtual MeshHandle meshHandle() const =0
Handle of the associated mesh.
Interface for a list of data set options.
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Searches for the mesh with name name.
virtual MeshHandle defaultMeshHandle() const =0
Handle for the default mesh.
Interface of a module.
Definition IModule.h:40
Interface for service or module information.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual TraceMessage info()=0
Stream for an information message.
Manager of a DOM document.
virtual XmlNode documentNode()=0
Document node. This node is null if the document does not exist.
Handle on a mesh.
Definition MeshHandle.h:48
IMesh * mesh() const
Associated mesh.
IMeshMng * meshMng() const
Associated mesh manager. nullptr if isNull() is true.
Reference to an instance.
Encapsulation of a pointer with a reference counter.
String find(const String &key, bool throw_exception=false) const
Returns the value associated with key.
bool null() const
Returns true if the string is null.
Definition String.cc:306
bool empty() const
True if the string is empty (null or "").
Definition String.cc:317
List of nodes of a DOM tree.
Definition XmlNodeList.h:36
Node of a DOM tree.
Definition XmlNode.h:51
String xpathFullName() const
XPath name of the node with its ancestors.
Definition XmlNode.cc:152
String attrValue(const String &name, bool throw_exception=false) const
Value of attribute name.
Definition XmlNode.cc:234
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
eCaseOptionReadPhase
Reading phases.
Int32 Integer
Type representing an integer.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.