14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/List.h"
16#include "arcane/utils/ValueConvert.h"
17#include "arcane/utils/Deleter.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/TraceAccessor.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/OStringStream.h"
23#include "arcane/utils/ScopedPtr.h"
24#include "arcane/utils/ApplicationInfo.h"
25#include "arcane/utils/NotImplementedException.h"
26#include "arcane/utils/CriticalSection.h"
28#include "arcane/core/ISubDomain.h"
29#include "arcane/core/IApplication.h"
30#include "arcane/core/IParallelMng.h"
31#include "arcane/core/IParallelSuperMng.h"
32#include "arcane/core/ICaseMng.h"
33#include "arcane/core/IModule.h"
34#include "arcane/core/CaseOptions.h"
35#include "arcane/core/XmlNode.h"
36#include "arcane/core/XmlNodeList.h"
37#include "arcane/core/XmlNodeIterator.h"
38#include "arcane/core/ICaseDocument.h"
39#include "arcane/core/ICaseFunctionProvider.h"
40#include "arcane/core/CaseNodeNames.h"
41#include "arcane/core/ISession.h"
42#include "arcane/core/CaseTable.h"
43#include "arcane/core/IMainFactory.h"
44#include "arcane/core/IIOMng.h"
45#include "arcane/core/ServiceFinder2.h"
46#include "arcane/core/ObservablePool.h"
47#include "arcane/core/ICaseDocumentVisitor.h"
48#include "arcane/core/ServiceBuilder.h"
49#include "arcane/core/internal/ICaseMngInternal.h"
51#include "arcane/impl/CaseDocumentLangTranslator.h"
62extern "C++" std::unique_ptr<ICaseDocumentVisitor>
63createPrintCaseDocumentVisitor(ITraceMng* tm,
const String& lang);
65extern "C++" ICaseDocumentFragment*
66arcaneCreateCaseDocumentFragment(ITraceMng* tm,IXmlDocumentHolder* document);
79 ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS();
92 void _searchInvalidOptions();
103 bool hasError()
const {
return m_has_error; }
104 const String& errorMessage()
const {
return m_error_message; }
120 auto begin()
const {
return m_begin; }
121 auto end()
const {
return m_end; }
127 if (m_begin >= m_end)
135 CaseOptionsList::const_iterator m_begin;
136 CaseOptionsList::const_iterator m_end;
156 return doc->fragment();
188 return m_observables[type];
208 String msgClassName()
const {
return "CaseMng"; }
217 bool m_treat_warning_as_error =
false;
218 bool m_allow_unknown_root_element =
true;
229 void _readFunctions();
232 void _checkTranslateDocument();
247void CaseMng::OptionsReader::
252 _searchInvalidOptions();
258void CaseMng::OptionsReader::
262 for( ICaseOptions* co : m_options){
263 co->read(read_phase);
270void CaseMng::OptionsReader::
271_searchInvalidOptions()
275 XmlNodeList invalid_elems;
276 for( ICaseOptions* co : m_options)
277 co->addInvalidChildren(invalid_elems);
284CaseMng(ISubDomain* sub_domain)
287, m_treat_warning_as_error(false)
289 if (!platform::getEnvironmentVariable(
"ARCANE_STRICT_CASEOPTION").null())
290 m_treat_warning_as_error =
true;
310extern "C++" ICaseMng*
311arcaneCreateCaseMng(ISubDomain* mng)
313 return new CaseMng(mng);
326 info() <<
"Reading the input data (phase1): language '"
327 <<
doc->language() <<
"', "
330 info() <<
"Reading the input data (phase2)";
333 doc->clearErrorsAndWarnings();
348 _checkTranslateDocument();
355_checkTranslateDocument()
359 String tr_lang = platform::getEnvironmentVariable(
"ARCANE_TRANSLATE_CASEDOCUMENT");
361 info() <<
"Generating translation for case file to lang=" <<
tr_lang;
365 std::ofstream
ofile(
"convert_info.txt");
375_printErrors(ICaseDocumentFragment* doc,
bool is_phase1)
381 if (!m_treat_warning_as_error){
383 if (doc->hasWarnings()){
385 doc->printWarnings(ostr());
386 pwarning() <<
"The input data are not coherent:\n\n" << ostr.str();
390 bool has_error = doc->hasError();
391 if (doc->hasWarnings() && m_treat_warning_as_error && !is_phase1)
396 if (m_treat_warning_as_error && doc->hasWarnings())
397 doc->printWarnings(ostr());
398 doc->printErrors(ostr());
399 ARCANE_FATAL(
"Input data are invalid:\n\n{0}",ostr.str());
420 info() <<
"NB_CASE_FUNCTION_PROVIDER_FACTORY = " << factories.size();
421 for(
const auto& factory : factories ){
424 info() <<
"FOUND CASE FUNCTION PROVIDER (V2)!";
425 cfp->registerCaseFunctions(
this);
443 log() <<
"Register case option <" <<
co->rootTagName() <<
">";
486 ErrorInfo
err_info = _readOneTable(node);
491 error() <<
" Error in element '" << node.xpathFullName() <<
"' : "
498 else if (node.isNamed(
"external-assembly")){
499 String assembly_name = node.expectedChild(
"assembly-name").value();
500 String class_name = node.expectedChild(
"class-name").value();
501 _readOneDotNetFunction(assembly_name,class_name);
504 warning() <<
"Unknown node in functions: " << node.xpathFullName();
515 auto table =
dynamic_cast<CaseTable*
>(icf_ref.get());
517 log() <<
"Table <" << table->name() <<
"> own "
518 << table->nbElement() <<
" element(s)";
525CaseMng::ErrorInfo CaseMng::
526_checkValidFunction(
const XmlNode& func_elem,CaseFunctionBuildInfo& cfbi)
530 String func_name = func_elem.attrValue(cnn->name_attribute);
531 if (func_name.null())
532 return ErrorInfo(String::format(
"missing attribute '{0}'",cnn->name_attribute));
534 cfbi.m_name = func_name;
536 return ErrorInfo(String::format(
"function '{0}' is defined several times",func_name));
538 String param_name = func_elem.attrValue(cnn->function_parameter);
539 if (param_name.null())
540 return ErrorInfo(String::format(
"missing attribute '{0}'",cnn->function_parameter));
542 String value_name = func_elem.attrValue(cnn->function_value);
543 if (value_name.null())
544 return ErrorInfo(String::format(
"missing attribute '{0}'",cnn->function_value));
546 String comul_name = func_elem.attrValue(
"comul");
547 String transform_x_name = func_elem.attrValue(
"comul-x");
549 cfbi.m_transform_param_func = transform_x_name;
550 cfbi.m_transform_value_func = comul_name;
552 String ustr_time(cnn->time_type);
553 String ustr_iteration(cnn->iteration_type);
555 String ustr_real(cnn->real_type);
556 String ustr_real3(cnn->real3_type);
557 String ustr_bool(cnn->bool_type);
558 String ustr_integer(cnn->integer_type);
559 String ustr_string(cnn->string_type);
561 UniqueArray<String> valid_param_strs = { ustr_time, ustr_real, ustr_iteration, ustr_integer };
565 if (param_name==ustr_time || param_name==ustr_real)
567 else if (param_name==ustr_iteration || param_name==ustr_integer)
570 return ErrorInfo(String::format(
"invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
571 param_name,cnn->function_parameter,String::join(
", ",valid_param_strs)));
573 cfbi.m_param_type = param_type;
575 UniqueArray<String> valid_value_strs = { ustr_real, ustr_real3, ustr_integer, ustr_bool, ustr_string };
579 if (value_name==ustr_real)
581 if (value_name==ustr_integer)
583 if (value_name==ustr_bool)
585 if (value_name==ustr_string)
587 if (value_name==ustr_real3)
590 return ErrorInfo(String::format(
"invalid value '{0}' for attribute '{1}'. Valid values are '{2}'.",
591 value_name,cnn->function_value,String::join(
", ",valid_value_strs)));
592 cfbi.m_value_type = value_type;
595 String deltat_coef_str = func_elem.attrValue(cnn->function_deltat_coef);
596 Real deltat_coef = 0.0;
597 if (!deltat_coef_str.null()){
598 if (builtInGetValue(deltat_coef,deltat_coef_str))
599 return ErrorInfo(String::format(
"Invalid value '{0}' for attribute '{1}. Can not convert to 'Real' type",
600 deltat_coef_str,cnn->function_deltat_coef));
601 cfbi.m_deltat_coef = deltat_coef;
602 info() <<
"Coefficient deltat for the function '" << func_name <<
"' = " << cfbi.m_deltat_coef;
611CaseMng::ErrorInfo CaseMng::
612_readOneTable(
const XmlNode& func_elem)
614 CaseFunctionBuildInfo cfbi(
traceMng());
616 ErrorInfo err_info = _checkValidFunction(func_elem,cfbi);
617 if (err_info.hasError())
622 String ustr_constant(cnn->function_constant);
623 String ustr_linear(cnn->function_linear);
624 String ustr_value(cnn->function_value);
626 String interpolation_name = func_elem.attrValue(cnn->function_interpolation);
627 if (interpolation_name.null())
628 return ErrorInfo(String::format(
"missing attribute '{0}'",cnn->function_interpolation));
632 if (interpolation_name==ustr_constant)
634 else if (interpolation_name==ustr_linear)
637 return ErrorInfo(String::format(
"Invalid value for attribute '{0}'. Valid values are '{1}' or '{2}'",
638 cnn->function_interpolation,ustr_constant,ustr_linear));
642 XmlNodeList func_value_list = func_elem.children(ustr_value);
643 Integer nb_func_value = func_value_list.size();
644 if (nb_func_value==0)
645 return ErrorInfo(
"The table has no values");
647 auto func =
new CaseTable(cfbi,interpolation_type);
654 for(
const auto& i : func_value_list ) {
655 String param_str = i.child(ustr_x).value();
656 String value_str = i.child(ustr_y).value();
659 if (param_str.null())
660 return ErrorInfo(String::format(
"index={0} element <x> is missing",value_index));
661 if (value_str.null())
662 return ErrorInfo(String::format(
"index={0} element <y> is missing",value_index));
666 if (error_number!=CaseTable::ErrNo){
667 String message =
"No info";
668 switch(error_number){
670 message = String::format(
"parameter '{0}' can not be converted to the 'param' type of the table",param_str);
673 message = String::format(
"value '{0}' can not be converted to the 'value' type of the table",value_str);
676 message =
"<x> lesser than previous <x>";
679 message =
"<x> greater than next <x>";
682 message =
"bad interval";
684 case CaseTable::ErrNo:
688 return ErrorInfo(String::format(
"index={0} : {1}",value_index,message));
699_readOneDotNetFunction(
const String& assembly_name,
const String& class_name)
703 if (!m_dotnet_provider.get()){
704 ServiceBuilder<ICaseFunctionDotNetProvider> sb(
subDomain());
705 m_dotnet_provider = sb.createReference(
"ArcaneDefaultDotNetCaseFunctionProvider",
SB_AllowNull);
706 if (!m_dotnet_provider.get())
707 ARCANE_FATAL(
"Can not create '.Net' case function provider. Check that the '.Net' runtime is loaded.");
710 m_dotnet_provider->registerCaseFunctions(
this,assembly_name,class_name);
733 if (!platform::getEnvironmentVariable(
"ARCANE_ALLOW_UNKNOWN_ROOT_ELEMENT").null())
734 m_allow_unknown_root_element =
true;
745 String name = node.name();
754 if (
co->rootTagName()==name){
760 if (m_allow_unknown_root_element)
761 pwarning() <<
"-- Unknown root option '" << node.xpathFullName() <<
"'";
770 perror() <<
"-- Unknown root option '" <<
xnode.xpathFullName() <<
"'";
772 pfatal() <<
"Unknown root option(s) in the input data. "
773 <<
"You can put these options inside <comment> tags to remove this error";
795 m_options_with_function.clear();
796 UniqueArray<CaseOptionBase*> col;
798 co->deepGetChildren(col);
800 for( CaseOptionBase* co : col ){
802 m_options_with_function.add(co);
816 auto v = createPrintCaseDocumentVisitor(
traceMng(),
lang);
817 info() <<
"-----------------------------------------------------";
819 info() <<
"Input data values:";
828 co->printChildren(
lang,0);
833 info() <<
"-----------------------------------------------------";
860findFunctionRef(
const String& name)
const
874 return findFunctionRef(name).get();
883 _removeFunction(
func,
false);
939 return m_case_document.get();
948 if (m_case_document.get())
958 info() <<
"XML Memory File:";
963 m_case_document = app->
mainFactory()->createCaseDocument(app,case_doc);
968 XmlNode root_elem = m_case_document->fragment()->rootElement();
969 if (root_elem.name()!=cnn->root){
970 pfatal() <<
"The root element <" << root_elem.name() <<
"> has to be <" << cnn->root <<
">";
973 if (root_elem.attrValue(cnn->code_name)!=code_name){
974 pfatal() <<
"The file is not a case of code '" << code_name <<
"'";
977 String case_codeversion = root_elem.attrValue(cnn->code_version);
980 if (case_codeversion!=code_version && case_codeversion!=code_version2){
982 pfatal() <<
"The version number of the file (" << case_codeversion
983 <<
") doesn't match the version of the code '"
984 << code_name <<
"' (" << code_version <<
").";
998 doc->clearErrorsAndWarnings();
1000 reader.addOption(
opt);
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classe gérant la traduction d'un jeu de données dans une autre langue.
Informations pour construire une instance de CaseFunction.
void internalReadOneOption(ICaseOptions *opt, bool is_phase1) override
Implémentation via ICaseMngInternal.
void setAllowUnkownRootElelement(bool v) override
Positionne l'autorisation des éléments inconnus à la racine du document.
void readOptions(bool is_phase1) override
Lit les options du jeu de donnée correspondant aux modules utilisés.
CaseFunctionList m_functions
Liste des fonctions.
bool m_is_function_read
Indique si les fonctions ont déjà été lues.
IObservable * observable(eCaseMngEventType type) override
Observable sur l'instance.
IApplication * application() override
Application associée.
void printOptions() override
Affiche les valeurs des options.
ISubDomain * subDomain() override
Gestionnaire de sous-domaine.
bool isTreatWarningAsError() const override
Indique si les avertissements dans le jeu de données doivent être traités comme des erreurs et provoq...
bool isAllowUnkownRootElelement() const override
Indique si les éléments inconnus à la racine du document sont autorisés.
ISubDomain * m_sub_domain
Gestionnaire de sous-domain.
void registerOptions(ICaseOptions *) override
Enregistre une liste d'options du jeu de donnée.
ICaseFunction * findFunction(const String &name) const override
Retourne la fonction de nom name ou nullptr s'il n'y en a pas.
ITraceMng * traceMng() override
Gestionnaire de traces.
void unregisterOptions(ICaseOptions *) override
Déseregistre une liste d'options du jeu de donnée.
void removeFunction(ICaseFunction *func, bool dofree) override
Supprime une fonction.
ICaseDocumentFragment * createDocumentFragment(IXmlDocumentHolder *document) override
Crée un fragment.
CaseOptionsList m_case_options_list
Liste des options du cas.
void setTreatWarningAsError(bool v) override
Positionne la manière de traiter les avertissements.
CaseOptionsCollection blocks() const override
Collection des blocs d'options.
void updateOptions(Real current_time, Real current_deltat, Integer current_iteration) override
Met à jour les options basée sur une table de marche en temps.
IMeshMng * meshMng() const override
Gestionnaire de maillage associé
CaseFunctionCollection functions() override
Retourne la liste des tables.
IPhysicalUnitSystem * physicalUnitSystem() const override
Système d'unité associé.
ICaseDocument * readCaseDocument(const String &filename, ByteConstArrayView bytes) override
Lit le document XML du jeu de données.
ICaseDocument * caseDocument() override
Document XML du jeu de données (peut être nul si pas de jeu de donneés)
ICaseMngInternal * _internalImpl() override
Implémentation interne.
void _searchInvalidOptions()
Recherche les options invalides du jeu de données.
void readFunctions() override
Lit les tables du jeu de donnée.
ICaseDocumentFragment * caseDocumentFragment() override
Fragment du Document XML associé au jeu de données (peut être nul si pas de jeu de donneés)
void addFunction(ICaseFunction *func) override
Ajoute la fonction func.
Noms des noeuds XML d'un jeu de données Arcane.
Classe de base d'une option du jeu de donnée.
eCurveType
Type de la courbe de la table.
@ CurveUnknown
Type de courbe inconnu.
@ CurveLinear
Courbe linéaire par morceau.
@ CurveConstant
Courbe constante par morceau.
eError
Type des erreurs retournées par la classe.
@ ErrCanNotConvertParamToRightType
Indique que la conversion du paramètre vers le type souhaité est impossible.
@ ErrBadRange
Indique qu'un indice d'un élément n'est pas valide.
@ ErrNotGreaterThanPrevious
Indique que le paramètre n'est pas supérieur au précédent.
@ ErrNotLesserThanNext
Indique que le paramètre n'est pas inférieur au suivant.
@ ErrCanNotConvertValueToRightType
Indique que la conversion de la valeur vers le type souhaité est impossible.
Integer count() const
Nombre d'éléments de la collection.
Section critique en multi-thread.
Interface de l'application.
virtual IMainFactory * mainFactory() const =0
Manufacture principale.
virtual String mainVersionStr() const =0
Numéro de version principal (sans la béta) de l'application.
virtual String majorAndMinorVersionStr() const =0
Numéro de version majeur et mineure sous la forme M.m.
virtual IParallelSuperMng * parallelSuperMng()=0
Gestionnaire superviseur du parallélisme.
virtual const ApplicationInfo & applicationInfo() const =0
Informations sur l'exécutable.
Interface d'une partie d'un jeu de données.
Interface d'une classe gérant un document XML du jeu de données.
virtual ICaseDocumentFragment * fragment()=0
Fragment correspondant à ce document.
virtual CaseNodeNames * caseNodeNames()=0
Retourne l'instance contenant les noms des noeuds XML par langage.
Interface d'une fonction du jeu de données.
eParamType
Type d'un paramètre d'une fonction.
@ ParamUnknown
Type de paramètre inconnu.
@ ParamReal
Paramètre de type Real.
@ ParamInteger
Paramètre de type Integer.
eValueType
Type d'une valeur d'une fonction.
@ ValueReal3
Valeur de type 'Real3'.
@ ValueUnknown
Type de la valeur inconnu.
@ ValueInteger
Valeur de type entière.
@ ValueString
Valeur de type chaîne de caractères.
@ ValueReal
Valeur de type réelle.
@ ValueBool
Valeur de type entière.
Partie interne de ICaseMng.
Interface du gestionnaire de cas.
Interface d'une liste d'options du jeu de données.
Interface du gestionnaire des entrées sorties.
Interface du gestionnaire des maillages.
Interface d'un observable.
Classe abstraite du superviseur de parallélisme.
Interface d'un système d'unité.
Interface du gestionnaire d'un sous-domaine.
virtual IApplication * application()=0
Application.
virtual IParallelMng * parallelMng()=0
Retourne le gestionnaire de parallélisme.
virtual IMeshMng * meshMng() const =0
Retourne le gestionnaire de maillage.
virtual ISession * session() const =0
Session.
virtual IPhysicalUnitSystem * physicalUnitSystem()=0
Système d'unité du sous-domaine.
Gestionnaire d'un document DOM.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Informations pour créer un service.
Liste de noeuds d'un arbre DOM.
@ ELEMENT
The node is an Element.
Vue constante d'un tableau de type T.
Interface du gestionnaire de traces.
static ThatClass create(InstanceType *t)
Créé une référence à partir de l'instance t.
Implémentation thread-safe d'un compteur de référence.
Chaîne de caractères unicode.
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Classe d'accès aux traces.
TraceMessage pwarning() const
TraceMessage log() const
Flot pour un message de log.
TraceMessage pfatal() const
Flot pour un message d'erreur fatale en parallèle.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage perror() const
TraceMessage info() const
Flot pour un message d'information.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
Positionne une classe de message.
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ SB_AllowNull
Autorise l'absence du service.
eCaseOptionReadPhase
Phases de la lecture.
eCaseMngEventType
Types des évènements supportés par ICaseMng.
@ BeginReadOptionsPhase2
Évènement généré avant de lire les options dans la phase 2.
@ BeginReadOptionsPhase1
Évènement généré avant de lire les options dans la phase 1.
Int32 Integer
Type représentant un entier.