GEOS
xmlWrapper.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 Total, S.A
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_
21 #define GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_
22 
23 // Source includes
24 #include "common/DataTypes.hpp"
25 #include "DefaultValue.hpp"
26 #include "common/GEOS_RAJA_Interface.hpp"
27 #include "LvArray/src/output.hpp"
28 #include "LvArray/src/input.hpp"
30 #include "codingUtilities/RTTypes.hpp"
31 
32 // TPL includes
33 #include <pugixml.hpp>
34 
35 // System includes
36 #include <algorithm>
37 #include <sstream>
38 
39 namespace geos
40 {
41 
42 
50 namespace xmlWrapper
51 {
52 
54 using xmlResult = pugi::xml_parse_result;
55 
59 using xmlNode = pugi::xml_node;
60 
64 using xmlAttribute = pugi::xml_attribute;
65 
67 using xmlNodeType = pugi::xml_node_type;
68 
69 class xmlDocument;
70 
77 {
79  string filePath;
82  size_t const line;
85  size_t const offsetInLine;
88  size_t const offset;
89 
97  xmlAttributePos( string const & filePath, size_t line, size_t offsetInLine, size_t offset );
101  bool isFound() const;
105  string toString() const;
106 };
107 
114 {
117 
126  xmlNodePos( xmlDocument const & document, string const & filePath, size_t line, size_t offsetInLine, size_t offset );
130  bool isFound() const;
136  xmlAttributePos getAttributeLine( string const & attName ) const;
137 };
138 
147 {
148 public:
150  static constexpr size_t npos = string::npos;
151 
159  xmlDocument( const xmlDocument & ) = delete;
163  xmlDocument( xmlDocument && ) = default;
164 
173  xmlNode getChild( string const & name ) const;
177  string const & getOriginalBuffer() const;
184  string const * getOriginalBuffer( string const & filePath ) const;
193  string const & getFilePath() const;
201 
210  xmlResult loadString( string_view content, bool loadNodeFileInfo = false );
211 
219  xmlResult loadFile( string const & path, bool loadNodeFileInfo = false );
220 
226  xmlNode appendChild( string const & name );
233  xmlNode appendChild( xmlNodeType type = xmlNodeType::node_element );
234 
241  bool saveFile( string const & path ) const;
242 
253  void addIncludedXML( xmlNode & targetNode, int level = 0 );
254 
258  bool hasNodeFileInfo() const;
259 
260 private:
262  pugi::xml_document pugiDocument;
263 
265  map< string, string > m_originalBuffers;
267  string m_rootFilePath;
268 };
269 
276 constexpr char const filePathString[] = "__filePath__";
277 
284 constexpr char const charOffsetString[] = "__charOffset__";
285 
287 constexpr char const includedListTag[] = "Included";
288 
290 constexpr char const includedFileTag[] = "File";
291 
301 string buildMultipleInputXML( string_array const & inputFileList,
302  string const & outputDir = {} );
303 
308 bool isFileMetadataAttribute( string const & name );
309 
318 
325 void validateString( string const & value, Regex const & regex );
326 
335 void processInputException( std::exception const & ex, string const & targetAttributeName,
336  xmlWrapper::xmlNode const & targetNode,
337  xmlWrapper::xmlNodePos const & nodePos );
338 
349 template< typename T >
350 std::enable_if_t< traits::CanStreamInto< std::istringstream, T > >
351 stringToInputVariable( T & target, string const & value, Regex const & regex )
352 {
353  validateString( value, regex );
354 
355  std::istringstream ss( value );
356  ss >> target;
357  GEOS_THROW_IF( ss.fail() || !ss.eof(),
358  "Error detected while parsing string \"" << value <<
359  "\" to type " << LvArray::system::demangleType< T >(),
360  InputError );
361 }
362 
371 template< typename T, int SIZE >
372 void
373 stringToInputVariable( Tensor< T, SIZE > & target, string const & value, Regex const & regex );
374 
387 template< typename T, int NDIM, typename PERMUTATION >
388 std::enable_if_t< traits::CanStreamInto< std::istringstream, T > >
389 stringToInputVariable( Array< T, NDIM, PERMUTATION > & array, string const & value, Regex const & regex )
390 {
391  validateString( value, regex );
392 
393  LvArray::input::stringToArray( array, string( stringutilities::trimSpaces( value ) ) );
394 }
395 
397 
398 namespace internal
399 {
400 
403 IS_VALID_EXPRESSION( canParseVariable, T, stringToInputVariable( std::declval< T & >(), string(), Regex() ) );
404 
411 template< typename T >
412 static void equate( T & lhs, T const & rhs )
413 { lhs = rhs; }
414 
423 template< typename T, int NDIM, typename PERM >
424 static void equate( Array< T, NDIM, PERM > const & lhs, T const & rhs )
425 { lhs.template setValues< serialPolicy >( rhs ); }
426 
427 } // namespace internal
428 
433 
444 template< typename T, typename U >
445 std::enable_if_t< !internal::canParseVariable< T >, bool >
446 readAttributeAsType( T &, string const & name, Regex const &, xmlNode const &, U const & )
447 {
448  GEOS_THROW( "Cannot parse key with name ("<<name<<") with the given type " << LvArray::system::demangleType< T >(), InputError );
449 }
450 
464 template< typename T, typename T_DEF = T >
465 std::enable_if_t< internal::canParseVariable< T >, bool >
467  string const & name,
468  Regex const & regex,
469  xmlNode const & targetNode,
470  T_DEF const & defVal )
471 {
472  xmlAttribute const xmlatt = targetNode.attribute( name.c_str() );
473  if( !xmlatt.empty() )
474  {
475  // parse the string/attribute into a value
476  stringToInputVariable( rval, xmlatt.value(), regex );
477  return true;
478  }
479  else
480  {
481  // set the value to the default value
482  internal::equate( rval, defVal );
483  return false;
484  }
485 }
486 
499 template< typename T >
500 std::enable_if_t< internal::canParseVariable< T >, bool >
502  string const & name,
503  Regex const & regex,
504  xmlNode const & targetNode,
505  bool const required )
506 {
507  xmlAttribute const xmlatt = targetNode.attribute( name.c_str() );
508 
509  bool const success = !(xmlatt.empty() && required);
510 
511  if( success )
512  {
513  // parse the string/attribute into a value
514  stringToInputVariable( rval, xmlatt.value(), regex );
515  }
516  return success;
517 }
518 
530 template< typename T >
531 std::enable_if_t< !dataRepository::DefaultValue< T >::has_default_value, bool >
533  string const & name,
534  Regex const & regex,
535  xmlNode const & targetNode,
537 {
538  return readAttributeAsType( rval, name, regex, targetNode, false );
539 }
540 
553 template< typename T >
554 typename std::enable_if_t< dataRepository::DefaultValue< T >::has_default_value, bool >
556  string const & name,
557  Regex const & regex,
558  xmlNode const & targetNode,
559  dataRepository::DefaultValue< T > const & defVal )
560 {
561  return readAttributeAsType( rval, name, regex, targetNode, defVal.value );
562 }
563 
565 
566 }
567 
568 } /* namespace geos */
569 
570 #endif /*GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_ */
#define GEOS_THROW(msg, TYPE)
Throw an exception.
Definition: Logger.hpp:164
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
Definition: Logger.hpp:151
Lightweight wrapper around a c-array.
Definition: Tensor.hpp:31
Base template for ordered and unordered maps.
Definition: DataTypes.hpp:329
xmlNode appendChild(string const &name)
Add a root element to the document.
xmlDocument(xmlDocument &&)=default
move constructor
void addIncludedXML(xmlNode &targetNode, int level=0)
Function to add xml nodes from included files.
string const & getFilePath() const
map< string, string > const & getOriginalBuffers() const
bool saveFile(string const &path) const
Save the XML to a file.
xmlNode appendChild(xmlNodeType type=xmlNodeType::node_element)
Add a root element to the document.
string const & getOriginalBuffer() const
xmlDocument()
Construct an empty xmlDocument that waits to load something.
xmlNode getChild(string const &name) const
xmlNodePos getNodePosition(xmlWrapper::xmlNode const &node) const
If the node file information are loaded, compute the position of a node.
xmlDocument(const xmlDocument &)=delete
non-copyable
xmlResult loadString(string_view content, bool loadNodeFileInfo=false)
Load document from zero-terminated string. No encoding conversions are applied. Free any previously l...
static constexpr size_t npos
Error value for when an offset / line position is undefined.
Definition: xmlWrapper.hpp:150
xmlResult loadFile(string const &path, bool loadNodeFileInfo=false)
Load document from file. Free any previously loaded xml tree. Wrapper of pugi::xml_document::loadBuff...
string const * getOriginalBuffer(string const &filePath) const
internal::Helper< T > DefaultValue
A templated alias to hold default values.
pugi::xml_node_type xmlNodeType
Alias for the type variant of an xml node.
Definition: xmlWrapper.hpp:67
pugi::xml_node xmlNode
Definition: xmlWrapper.hpp:59
constexpr char const includedFileTag[]
XML tag name for included files.
Definition: xmlWrapper.hpp:290
std::enable_if_t< traits::CanStreamInto< std::istringstream, T > > stringToInputVariable(T &target, string const &value, Regex const &regex)
Parse a string and fill a variable with the value(s) in the string.
Definition: xmlWrapper.hpp:351
void validateString(string const &value, Regex const &regex)
pugi::xml_attribute xmlAttribute
Definition: xmlWrapper.hpp:64
std::enable_if_t< !internal::canParseVariable< T >, bool > readAttributeAsType(T &, string const &name, Regex const &, xmlNode const &, U const &)
Extract attribute in an xml tree, and translate its value into a typed variable. This SFINAE implemen...
Definition: xmlWrapper.hpp:446
pugi::xml_parse_result xmlResult
Alias for the type of the result from an xml parse attempt.
Definition: xmlWrapper.hpp:54
constexpr char const charOffsetString[]
constexpr variable to hold node character offset from the start of the xml file.
Definition: xmlWrapper.hpp:284
bool isFileMetadataAttribute(string const &name)
constexpr char const includedListTag[]
XML tag name for included sections.
Definition: xmlWrapper.hpp:287
constexpr char const filePathString[]
constexpr variable to hold name for inserting the file path into the xml file.
Definition: xmlWrapper.hpp:276
void processInputException(std::exception const &ex, string const &targetAttributeName, xmlWrapper::xmlNode const &targetNode, xmlWrapper::xmlNodePos const &nodePos)
Helper method to process an exception that has been thrown during xml parsing.
string buildMultipleInputXML(string_array const &inputFileList, string const &outputDir={})
Function to handle multiple input xml files.
LvArray::Array< T, NDIM, PERMUTATION, localIndex, LvArray::ChaiBuffer > Array
Multidimensional array type. See LvArray:Array for details.
Definition: DataTypes.hpp:142
array1d< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:392
std::string_view string_view
String type.
Definition: DataTypes.hpp:94
Exception class used to report errors in user input.
Definition: Logger.hpp:502
string filePath
Path of the file containing this element.
Definition: xmlWrapper.hpp:79
xmlAttributePos(string const &filePath, size_t line, size_t offsetInLine, size_t offset)
Constructor of this struct.
xmlAttributePos getAttributeLine(string const &attName) const
Compute the xmlAttributePos of an xml attribute.
xmlNodePos(xmlDocument const &document, string const &filePath, size_t line, size_t offsetInLine, size_t offset)
Constructor of this struct.
xmlDocument const & document
Reference of the main xmlDocument that contains all original file buffers.
Definition: xmlWrapper.hpp:116