GEOSX
xmlWrapper.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
7  * Copyright (c) 2018-2020 TotalEnergies
8  * Copyright (c) 2019- GEOSX Contributors
9  * All rights reserved
10  *
11  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
12  * ------------------------------------------------------------------------------------------------------------
13  */
14 
19 #ifndef GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_
20 #define GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_
21 
22 // Source includes
23 #include "common/DataTypes.hpp"
24 #include "DefaultValue.hpp"
25 #include "common/GEOS_RAJA_Interface.hpp"
26 #include "LvArray/src/output.hpp"
27 #include "LvArray/src/input.hpp"
28 #include "codingUtilities/StringUtilities.hpp"
29 
30 // TPL includes
31 #include <pugixml.hpp>
32 
33 // System includes
34 #include <algorithm>
35 #include <sstream>
36 
37 namespace geos
38 {
39 
40 
48 namespace xmlWrapper
49 {
50 
52 using xmlResult = pugi::xml_parse_result;
53 
57 using xmlNode = pugi::xml_node;
58 
62 using xmlAttribute = pugi::xml_attribute;
63 
65 using xmlNodeType = pugi::xml_node_type;
66 
67 class xmlDocument;
68 
75 {
77  string filePath;
80  size_t const line;
83  size_t const offsetInLine;
86  size_t const offset;
87 
95  xmlAttributePos( string const & filePath, size_t line, size_t offsetInLine, size_t offset );
99  bool isFound() const;
103  string toString() const;
104 };
105 
112 {
115 
124  xmlNodePos( xmlDocument const & document, string const & filePath, size_t line, size_t offsetInLine, size_t offset );
128  bool isFound() const;
134  xmlAttributePos getAttributeLine( string const & attName ) const;
135 };
136 
145 {
146 public:
148  static constexpr size_t npos = string::npos;
149 
157  xmlDocument( const xmlDocument & ) = delete;
161  xmlDocument( xmlDocument && ) = default;
162 
171  xmlNode getChild( string const & name ) const;
175  string const & getOriginalBuffer() const;
182  string const * getOriginalBuffer( string const & filePath ) const;
191  string const & getFilePath() const;
199 
208  xmlResult loadString( string_view content, bool loadNodeFileInfo = false );
209 
217  xmlResult loadFile( string const & path, bool loadNodeFileInfo = false );
218 
224  xmlNode appendChild( string const & name );
231  xmlNode appendChild( xmlNodeType type = xmlNodeType::node_element );
232 
239  bool saveFile( string const & path ) const;
240 
251  void addIncludedXML( xmlNode & targetNode, int level = 0 );
252 
256  bool hasNodeFileInfo() const;
257 
258 private:
260  pugi::xml_document pugiDocument;
261 
263  map< string, string > m_originalBuffers;
265  string m_rootFilePath;
266 };
267 
274 constexpr char const filePathString[] = "__filePath__";
275 
282 constexpr char const charOffsetString[] = "__charOffset__";
283 
285 constexpr char const includedListTag[] = "Included";
286 
288 constexpr char const includedFileTag[] = "File";
289 
299 string buildMultipleInputXML( string_array const & inputFileList,
300  string const & outputDir = {} );
301 
306 bool isFileMetadataAttribute( string const & name );
307 
316 
323 void validateString( string const & value, Regex const & regex );
324 
333 void processInputException( std::exception const & ex, string const & targetAttributeName,
334  xmlWrapper::xmlNode const & targetNode,
335  xmlWrapper::xmlNodePos const & nodePos );
336 
347 template< typename T >
348 std::enable_if_t< traits::CanStreamInto< std::istringstream, T > >
349 stringToInputVariable( T & target, string const & value, Regex const & regex )
350 {
351  validateString( value, regex );
352 
353  std::istringstream ss( value );
354  ss >> target;
355  GEOS_THROW_IF( ss.fail() || !ss.eof(),
356  "Error detected while parsing string \"" << value <<
357  "\" to type " << LvArray::system::demangleType< T >(),
358  InputError );
359 }
360 
369 template< typename T, int SIZE >
370 void
371 stringToInputVariable( Tensor< T, SIZE > & target, string const & value, Regex const & regex );
372 
385 template< typename T, int NDIM, typename PERMUTATION >
386 std::enable_if_t< traits::CanStreamInto< std::istringstream, T > >
387 stringToInputVariable( Array< T, NDIM, PERMUTATION > & array, string const & value, Regex const & regex )
388 {
389  validateString( value, regex );
390 
391  LvArray::input::stringToArray( array, string( stringutilities::trimSpaces( value ) ) );
392 }
393 
395 
396 namespace internal
397 {
398 
401 IS_VALID_EXPRESSION( canParseVariable, T, stringToInputVariable( std::declval< T & >(), string(), Regex() ) );
402 
409 template< typename T >
410 static void equate( T & lhs, T const & rhs )
411 { lhs = rhs; }
412 
421 template< typename T, int NDIM, typename PERM >
422 static void equate( Array< T, NDIM, PERM > const & lhs, T const & rhs )
423 { lhs.template setValues< serialPolicy >( rhs ); }
424 
425 } // namespace internal
426 
431 
442 template< typename T, typename U >
443 std::enable_if_t< !internal::canParseVariable< T >, bool >
444 readAttributeAsType( T &, string const & name, Regex const &, xmlNode const &, U const & )
445 {
446  GEOS_THROW( "Cannot parse key with name ("<<name<<") with the given type " << LvArray::system::demangleType< T >(), InputError );
447 }
448 
462 template< typename T, typename T_DEF = T >
463 std::enable_if_t< internal::canParseVariable< T >, bool >
465  string const & name,
466  Regex const & regex,
467  xmlNode const & targetNode,
468  T_DEF const & defVal )
469 {
470  xmlAttribute const xmlatt = targetNode.attribute( name.c_str() );
471  if( !xmlatt.empty() )
472  {
473  // parse the string/attribute into a value
474  stringToInputVariable( rval, xmlatt.value(), regex );
475  return true;
476  }
477  else
478  {
479  // set the value to the default value
480  internal::equate( rval, defVal );
481  return false;
482  }
483 }
484 
497 template< typename T >
498 std::enable_if_t< internal::canParseVariable< T >, bool >
500  string const & name,
501  Regex const & regex,
502  xmlNode const & targetNode,
503  bool const required )
504 {
505  xmlAttribute const xmlatt = targetNode.attribute( name.c_str() );
506 
507  bool const success = !(xmlatt.empty() && required);
508 
509  if( success )
510  {
511  // parse the string/attribute into a value
512  stringToInputVariable( rval, xmlatt.value(), regex );
513  }
514  return success;
515 }
516 
528 template< typename T >
529 std::enable_if_t< !dataRepository::DefaultValue< T >::has_default_value, bool >
531  string const & name,
532  Regex const & regex,
533  xmlNode const & targetNode,
535 {
536  return readAttributeAsType( rval, name, regex, targetNode, false );
537 }
538 
551 template< typename T >
552 typename std::enable_if_t< dataRepository::DefaultValue< T >::has_default_value, bool >
554  string const & name,
555  Regex const & regex,
556  xmlNode const & targetNode,
557  dataRepository::DefaultValue< T > const & defVal )
558 {
559  return readAttributeAsType( rval, name, regex, targetNode, defVal.value );
560 }
561 
563 
564 }
565 
566 } /* namespace geos */
567 
568 #endif /*GEOS_DATAREPOSITORY_XMLWRAPPER_HPP_ */
#define GEOS_THROW(msg, TYPE)
Throw an exception.
Definition: Logger.hpp:129
#define GEOS_THROW_IF(EXP, msg, TYPE)
Conditionally throw an exception.
Definition: Logger.hpp:116
Lightweight wrapper around a c-array.
Definition: Tensor.hpp:30
Base template for ordered and unordered maps.
Definition: DataTypes.hpp:369
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:148
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:65
pugi::xml_node xmlNode
Definition: xmlWrapper.hpp:57
constexpr char const includedFileTag[]
XML tag name for included files.
Definition: xmlWrapper.hpp:288
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:349
void validateString(string const &value, Regex const &regex)
pugi::xml_attribute xmlAttribute
Definition: xmlWrapper.hpp:62
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:444
pugi::xml_parse_result xmlResult
Alias for the type of the result from an xml parse attempt.
Definition: xmlWrapper.hpp:52
constexpr char const charOffsetString[]
constexpr variable to hold node character offset from the start of the xml file.
Definition: xmlWrapper.hpp:282
bool isFileMetadataAttribute(string const &name)
constexpr char const includedListTag[]
XML tag name for included sections.
Definition: xmlWrapper.hpp:285
constexpr char const filePathString[]
constexpr variable to hold name for inserting the file path into the xml file.
Definition: xmlWrapper.hpp:274
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:182
array1d< string > string_array
A 1-dimensional array of geos::string types.
Definition: DataTypes.hpp:432
std::string_view string_view
String type.
Definition: DataTypes.hpp:134
Exception class used to report errors in user input.
Definition: Logger.hpp:464
The regular expression data for validating inputs. Use rtTypes to get the regex of a type,...
Definition: DataTypes.hpp:513
string filePath
Path of the file containing this element.
Definition: xmlWrapper.hpp:77
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:114