Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
CaseDocument.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/* CaseDocument.cc (C) 2000-2023 */
9/* */
10/* Class managing an XML document of the dataset. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ScopedPtr.h"
15#include "arcane/utils/TraceAccessor.h"
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/Array.h"
19
20#include "arcane/core/XmlNode.h"
21#include "arcane/core/IXmlDocumentHolder.h"
22#include "arcane/core/ICaseDocument.h"
23#include "arcane/core/CaseNodeNames.h"
24#include "arcane/core/CaseOptionError.h"
25#include "arcane/core/DomUtils.h"
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30namespace Arcane
31{
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36class CaseDocumentFragment
37: public TraceAccessor
39{
40 public:
41
42 CaseDocumentFragment(ITraceMng* tm, IXmlDocumentHolder* document);
43
44 ~CaseDocumentFragment()
45 {
46 delete m_case_node_names;
47 }
48
49 public:
50
51 void init();
52
53 public:
54
55 IXmlDocumentHolder* documentHolder() override { return m_doc_holder.get(); }
56 XmlNode documentNode() override { return m_document_node; }
57 XmlNode rootElement() override { return m_root_elem; }
58 String language() const override { return m_language; }
59 String defaultCategory() const override { return m_default_category; }
60 CaseNodeNames* caseNodeNames() override { return m_case_node_names; }
61
62 public:
63
64 void addError(const CaseOptionError& case_error) override;
65 void addWarning(const CaseOptionError& case_error) override;
66 bool hasError() const override;
67 bool hasWarnings() const override;
68 void printErrors(std::ostream& o) override;
69 void printWarnings(std::ostream& o) override;
70 void clearErrorsAndWarnings() override;
71
72 public:
73
74 ICaseDocumentFragment* fragment() { return this; }
75
76 public:
77
78 CaseNodeNames* m_case_node_names = nullptr;
79 ScopedPtrT<IXmlDocumentHolder> m_doc_holder;
80 XmlNode m_document_node;
81 XmlNode m_root_elem;
82 String m_language;
83 String m_default_category;
84 UniqueArray<CaseOptionError> m_errors;
85 UniqueArray<CaseOptionError> m_warnings;
86
87 private:
88
89 void _assignLanguage(const String& langname);
90 void _printErrorsOrWarnings(std::ostream& o, ConstArrayView<CaseOptionError> errors);
91};
92
93/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95
99class CaseDocument
100: public TraceAccessor
101, public ICaseDocument
102{
103 public:
104
105 CaseDocument(ITraceMng* sm, IXmlDocumentHolder* document);
106 ~CaseDocument() override;
107
108 void build() override;
109 ICaseDocument* clone() override;
110
111 public:
112
114 IXmlDocumentHolder* documentHolder() override { return m_fragment.m_doc_holder.get(); }
115 XmlNode documentNode() override { return m_fragment.m_document_node; }
116 XmlNode rootElement() override { return m_fragment.m_root_elem; }
117 String language() const override { return m_fragment.m_language; }
118 String defaultCategory() const override { return m_fragment.m_default_category; }
119 CaseNodeNames* caseNodeNames() override { return m_fragment.m_case_node_names; }
120 void addError(const CaseOptionError& case_error) override { m_fragment.addError(case_error); }
121 void addWarning(const CaseOptionError& case_error) override { m_fragment.addWarning(case_error); }
122 bool hasError() const override { return m_fragment.hasError(); }
123 bool hasWarnings() const override { return m_fragment.hasWarnings(); }
124 void printErrors(std::ostream& o) override { m_fragment.printErrors(o); }
125 void printWarnings(std::ostream& o) override { m_fragment.printWarnings(o); }
126 void clearErrorsAndWarnings() override { m_fragment.clearErrorsAndWarnings(); }
128
129 public:
130
131 XmlNode arcaneElement() override { return m_arcane_elem; }
132 XmlNode configurationElement() override { return m_configuration_elem; }
133
134 XmlNode timeloopElement() override { return m_timeloop_elem; }
135 XmlNode titleElement() override { return m_title_elem; }
136 XmlNode descriptionElement() override { return m_description_elem; }
137 XmlNode modulesElement() override { return m_modules_elem; }
138 XmlNode servicesElement() override { return m_services_elem; }
139
140 const XmlNodeList& meshElements() override { return m_mesh_elems; }
141
142 XmlNode meshesElement() override { return m_meshes_elem; }
143
144 XmlNode functionsElement() override { return m_functions_elem; }
145
146 String userClass() const override { return m_user_class; }
147 void setUserClass(const String& value) override;
148
149 String codeName() const override { return m_code_name; }
150 void setCodeName(const String& value) override;
151
152 String codeVersion() const override { return m_code_version; }
153 void setCodeVersion(const String& value) override;
154
155 String codeUnitSystem() const override { return m_code_unit_system; }
156 void setCodeUnitSystem(const String& value) override;
157
158 void setDefaultCategory(const String& v) override { m_fragment.m_default_category = v; }
159
160 ICaseDocumentFragment* fragment() override { return m_fragment.fragment(); }
161
162 public:
163
164 // Sets the language. Must be done before calling build.
165 void setLanguage(const String& language)
166 {
167 if (!m_fragment.m_language.null())
168 ARCANE_FATAL("Language already set");
169 m_fragment.m_language = language;
170 }
171
172 private:
173
174 CaseDocumentFragment m_fragment;
175
176 XmlNode m_arcane_elem;
177 XmlNode m_configuration_elem;
178 XmlNode m_timeloop_elem;
179 XmlNode m_title_elem;
180 XmlNode m_description_elem;
181 XmlNode m_modules_elem;
182 XmlNode m_services_elem;
183 XmlNodeList m_mesh_elems;
184 XmlNode m_functions_elem;
185 XmlNode m_meshes_elem;
186
187 String m_user_class;
188 String m_code_name;
189 String m_code_version;
190 String m_code_unit_system;
191
192 private:
193
194 XmlNode _forceCreateChild(XmlNode& parent, const String& us);
195};
196
197/*---------------------------------------------------------------------------*/
198/*---------------------------------------------------------------------------*/
199
200extern "C++" ICaseDocumentFragment*
201arcaneCreateCaseDocumentFragment(ITraceMng* tm, IXmlDocumentHolder* document)
202{
203 auto* doc = new CaseDocumentFragment(tm, document);
204 doc->init();
205 return doc;
206}
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
211extern "C++" ICaseDocument*
212arcaneCreateCaseDocument(ITraceMng* tm, IXmlDocumentHolder* document)
213{
214 ICaseDocument* doc = new CaseDocument(tm, document);
215 doc->build();
216 return doc;
217}
218
219/*---------------------------------------------------------------------------*/
220/*---------------------------------------------------------------------------*/
221
222extern "C++" ICaseDocument*
223arcaneCreateCaseDocument(ITraceMng* tm, const String& lang)
224{
225 IXmlDocumentHolder* xml_doc = domutils::createXmlDocument();
226 CaseDocument* doc = new CaseDocument(tm, xml_doc);
227 if (!lang.null())
228 doc->setLanguage(lang);
229 doc->build();
230 return doc;
231}
232
233/*---------------------------------------------------------------------------*/
234/*---------------------------------------------------------------------------*/
235
236CaseDocumentFragment::
237CaseDocumentFragment(ITraceMng* tm, IXmlDocumentHolder* document)
238: TraceAccessor(tm)
239, m_case_node_names(new CaseNodeNames(String()))
240, m_doc_holder(document)
241, m_document_node(m_doc_holder->documentNode())
242{
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248CaseDocument::
249CaseDocument(ITraceMng* tm, IXmlDocumentHolder* document)
250: TraceAccessor(tm)
251, m_fragment(tm, document)
252{
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
258CaseDocument::
259~CaseDocument()
260{
261}
262
263/*---------------------------------------------------------------------------*/
264/*---------------------------------------------------------------------------*/
265
266void CaseDocumentFragment::
267init()
268{
269 CaseNodeNames* cnn = caseNodeNames();
270
271 m_root_elem = m_document_node.documentElement();
272 if (m_root_elem.null()) {
273 // New case, French language by default for now.
274 if (m_language.null())
275 m_language = String("fr");
276 _assignLanguage(m_language);
277 cnn = caseNodeNames();
278 m_root_elem = m_document_node.createAndAppendElement(cnn->root, String());
279 m_root_elem.setAttrValue(cnn->lang_attribute, m_language);
280 }
281
282 m_language = m_root_elem.attrValue(cnn->lang_attribute);
283
284 if (m_language.null()) {
285 ARCANE_FATAL("Attribute '{0}' not specified in the element <{1}>",
286 cnn->lang_attribute, m_root_elem.name());
287 }
288 else
289 _assignLanguage(m_language);
290}
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
294
296build()
297{
298 m_fragment.init();
299
300 // These nodes have a name independent of the language.
301 m_arcane_elem = _forceCreateChild(m_fragment.m_root_elem, "arcane");
302 m_configuration_elem = _forceCreateChild(m_arcane_elem, "configuration");
303
304 // Do not do before 'm_fragment.init()'
306
307 // NOTE: If elements are added or changed, the corresponding conversion must
308 // be updated in CaseDocumentLangTranslator
309 m_timeloop_elem = _forceCreateChild(m_arcane_elem, cnn->timeloop);
310 m_title_elem = _forceCreateChild(m_arcane_elem, cnn->title);
311 m_description_elem = _forceCreateChild(m_arcane_elem, cnn->description);
312 m_modules_elem = _forceCreateChild(m_arcane_elem, cnn->modules);
313 m_services_elem = _forceCreateChild(m_arcane_elem, cnn->services);
314
315 XmlNode& root_elem = m_fragment.m_root_elem;
316
317 _forceCreateChild(root_elem, cnn->mesh);
318 m_mesh_elems = root_elem.children(cnn->mesh);
319
320 m_functions_elem = _forceCreateChild(root_elem, cnn->functions);
321 m_meshes_elem = root_elem.child(cnn->meshes);
322
323 m_user_class = root_elem.attrValue(cnn->user_class);
324 m_code_name = root_elem.attrValue(cnn->code_name);
325 m_code_version = root_elem.attrValue(cnn->code_version);
326 m_code_unit_system = root_elem.attrValue(cnn->code_unit);
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
333clone()
334{
335 throw NotImplementedException(A_FUNCINFO);
336}
337
338/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
340
341void CaseDocumentFragment::
342_assignLanguage(const String& langname)
343{
344 delete m_case_node_names;
345 m_case_node_names = new CaseNodeNames(langname);
346}
347
348/*---------------------------------------------------------------------------*/
349/*---------------------------------------------------------------------------*/
350
351XmlNode CaseDocument::
352_forceCreateChild(XmlNode& parent, const String& name)
353{
354 XmlNode node(parent.child(name));
355 if (node.null())
356 node = parent.createAndAppendElement(name, String());
357 return node;
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
364setUserClass(const String& value)
365{
366 m_user_class = value;
367 m_fragment.m_root_elem.setAttrValue(caseNodeNames()->user_class, value);
368}
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
372
374setCodeName(const String& value)
375{
376 m_code_name = value;
377 m_fragment.m_root_elem.setAttrValue(caseNodeNames()->code_name, value);
378}
379
380/*---------------------------------------------------------------------------*/
381/*---------------------------------------------------------------------------*/
382
384setCodeVersion(const String& value)
385{
386 m_code_version = value;
387 m_fragment.m_root_elem.setAttrValue(caseNodeNames()->code_version, value);
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
394setCodeUnitSystem(const String& value)
395{
396 m_code_unit_system = value;
397 m_fragment.m_root_elem.setAttrValue(caseNodeNames()->code_unit, value);
398}
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
402
403/*---------------------------------------------------------------------------*/
404/*---------------------------------------------------------------------------*/
405
407addError(const CaseOptionError& case_error)
408{
409 m_errors.add(case_error);
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
416addWarning(const CaseOptionError& case_error)
417{
418 m_warnings.add(case_error);
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424bool CaseDocumentFragment::
425hasError() const
426{
427 return m_errors.size() != 0;
428}
429
430/*---------------------------------------------------------------------------*/
431/*---------------------------------------------------------------------------*/
432
433bool CaseDocumentFragment::
434hasWarnings() const
435{
436 return m_warnings.size() != 0;
437}
438
439/*---------------------------------------------------------------------------*/
440/*---------------------------------------------------------------------------*/
441
443printErrors(std::ostream& o)
444{
445 _printErrorsOrWarnings(o, m_errors);
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
452printWarnings(std::ostream& o)
453{
454 _printErrorsOrWarnings(o, m_warnings);
455}
456
457/*---------------------------------------------------------------------------*/
458/*---------------------------------------------------------------------------*/
459
462{
463 m_errors.clear();
464 m_warnings.clear();
465}
466
467/*---------------------------------------------------------------------------*/
468/*---------------------------------------------------------------------------*/
469
470void CaseDocumentFragment::
471_printErrorsOrWarnings(std::ostream& o, ConstArrayView<CaseOptionError> errors)
472{
473 for (const CaseOptionError& error : errors) {
474 if (arcaneIsCheck()) {
475 o << "TraceFile: " << error.trace().file() << ":" << error.trace().line() << '\n';
476 o << "TraceFunc: " << error.trace().name() << '\n';
477 }
478 o << '<' << error.nodeName() << "> : " << error.message() << '\n';
479 }
480}
481
482/*---------------------------------------------------------------------------*/
483/*---------------------------------------------------------------------------*/
484
485} // End namespace Arcane
486
487/*---------------------------------------------------------------------------*/
488/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
void printWarnings(std::ostream &o) override
Writes the warnings to the stream o.
CaseNodeNames * caseNodeNames() override
Returns the instance containing the names of XML nodes by language.
String language() const override
Language used in the dataset.
void printErrors(std::ostream &o) override
Writes the errors to the stream o.
String defaultCategory() const override
Category used for default values.
IXmlDocumentHolder * documentHolder() override
Returns the XML document of the dataset. This pointer remains the property of this class and is destr...
void addError(const CaseOptionError &case_error) override
Adds an error to the dataset.
void clearErrorsAndWarnings() override
Clears the recorded error and warning messages.
XmlNode documentNode() override
Returns the document node.
void addWarning(const CaseOptionError &case_error) override
Adds a warning to the dataset.
XmlNode rootElement() override
Returns the root element.
Class managing an XML document of the dataset.
XmlNode rootElement() override
Returns the root element.
XmlNode meshesElement() override
Element containing the list of meshes (new mechanism) (can be null).
String codeUnitSystem() const override
Name of the document's unit system.
XmlNode arcaneElement() override
Returns the information element for Arcane.
String codeName() const override
Name of the case code.
ICaseDocument * clone() override
Clones the document.
void setDefaultCategory(const String &v) override
Sets the category used for default values.
const XmlNodeList & meshElements() override
Returns the root element of the mesh information.
XmlNode descriptionElement() override
Returns the element containing the case description.
void addWarning(const CaseOptionError &case_error) override
Adds a warning to the dataset.
void setUserClass(const String &value) override
Sets the name of the case usage class.
XmlNode functionsElement() override
Returns the root element of the functions.
String userClass() const override
Name of the case usage class.
XmlNode documentNode() override
Returns the document node.
XmlNode modulesElement() override
Returns the element containing the module descriptions.
CaseNodeNames * caseNodeNames() override
Returns the instance containing the names of XML nodes by language.
void setCodeVersion(const String &value) override
Sets the version number of the code.
void setCodeUnitSystem(const String &value) override
Sets the name of the document's unit system.
XmlNode timeloopElement() override
Returns the element containing the time loop choice.
String defaultCategory() const override
Category used for default values.
XmlNode configurationElement() override
Returns the configuration information element.
XmlNode titleElement() override
Returns the element containing the case title.
void printWarnings(std::ostream &o) override
Writes the warnings to the stream o.
IXmlDocumentHolder * documentHolder() override
Returns the XML document of the dataset. This pointer remains the property of this class and is destr...
void addError(const CaseOptionError &case_error) override
Adds an error to the dataset.
ICaseDocumentFragment * fragment() override
Fragment corresponding to this document.
void build() override
Constructs the instance.
void setCodeName(const String &value) override
Sets the name of the case code.
XmlNode servicesElement() override
Returns the element containing the service descriptions.
String codeVersion() const override
Version number of the code corresponding to the case.
void printErrors(std::ostream &o) override
Writes the errors to the stream o.
String language() const override
Language used in the dataset.
void clearErrorsAndWarnings() override
Clears the recorded error and warning messages.
XML node names of an Arcane dataset.
Error in the dataset.
Constant view of an array of type T.
Interface of a part of a dataset.
Interface of a class managing an XML document of the dataset.
Manager of a DOM document.
bool null() const
Returns true if the string is null.
Definition String.cc:306
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage error() const
Flow for an error message.
List of nodes of a DOM tree.
Definition XmlNodeList.h:36
Node of a DOM tree.
Definition XmlNode.h:51
String attrValue(const String &name, bool throw_exception=false) const
Value of attribute name.
Definition XmlNode.cc:234
XmlNode child(const String &name) const
Child node of this node with name name.
Definition XmlNode.cc:73
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 --
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66