File indexing completed on 2024-05-19 03:51:49

0001 /*
0002     SPDX-FileCopyrightText: 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #ifndef MARBLE_GEOPARSER_H
0007 #define MARBLE_GEOPARSER_H
0008 
0009 #include <QPair>
0010 #include <QStack>
0011 #include <QXmlStreamReader>
0012 
0013 #include "geodata_export.h"
0014 
0015 namespace Marble
0016 {
0017 
0018 using GeoDataGenericSourceType = int;
0019 
0020 class GeoDocument;
0021 class GeoNode;
0022 class GeoStackItem;
0023 
0024 class GEODATA_EXPORT GeoParser : public QXmlStreamReader
0025 {
0026  public:
0027     typedef QPair<QString, QString> QualifiedName; // Tag Name & Namespace pair
0028 
0029     explicit GeoParser( GeoDataGenericSourceType sourceType );
0030     virtual ~GeoParser();
0031 
0032     /**
0033      * @brief Main API for reading the XML document.
0034      * This is the only method that is necessary to call to start the GeoParser.
0035      * To retrieve the resulting data see @see releaseDocument() and
0036      * @see releaseModel()
0037      */
0038     bool read( QIODevice* );
0039 
0040     /**
0041      * @brief retrieve the parsed document and reset the parser
0042      * If parsing was successful, retrieve the resulting document
0043      * and set the contained m_document pointer to 0.
0044      */
0045     GeoDocument* releaseDocument();
0046     GeoDocument* activeDocument() { return m_document; }
0047 
0048     // Used by tag handlers, to be overridden by GeoDataParser/GeoSceneParser
0049     virtual bool isValidElement( const QString& tagName ) const;
0050 
0051     // Used by tag handlers, to access a parent element's associated GeoStackItem
0052     GeoStackItem parentElement( unsigned int depth = 0 ) const;
0053 
0054     // Used by tag handlers, to emit a warning while parsing
0055     void raiseWarning( const QString& );
0056 
0057     // Used by tag handlers, to retrieve the value for an attribute of the currently parsed element
0058     QString attribute( const char* attributeName ) const;
0059 
0060 protected:
0061     /**
0062      * This method is intended to check if the current element being served by
0063      * the GeoParser is a valid Document Root element. This method is to be
0064      * implemented by GeoDataParser/GeoSceneParser and must check based on the
0065      * current XML Document type, e.g. KML, GPX etc.
0066      * @return @c true if the element is a valid document root.
0067      */
0068     virtual bool isValidRootElement() = 0;
0069 
0070     virtual GeoDocument* createDocument() const = 0;
0071 
0072 protected:
0073     GeoDocument* m_document;
0074     GeoDataGenericSourceType m_source;
0075 
0076 private:
0077     void parseDocument();
0078     QStack<GeoStackItem> m_nodeStack;
0079 };
0080 
0081 class GeoStackItem
0082 {
0083  public:
0084     GeoStackItem()
0085         : m_qualifiedName(),
0086           m_node( nullptr )
0087     {
0088     }
0089 
0090     GeoStackItem( const GeoParser::QualifiedName& qualifiedName, GeoNode* node )
0091         : m_qualifiedName( qualifiedName ),
0092           m_node( node )
0093     {
0094     }
0095 
0096     // Fast path for tag handlers
0097     bool represents( const char* tagName ) const
0098     {
0099         return m_node && tagName == m_qualifiedName.first;
0100     }
0101 
0102     // Helper for tag handlers. Does NOT guard against miscasting. Use with care.
0103     template<class T>
0104     T* nodeAs()
0105     {
0106         Q_ASSERT( dynamic_cast<T*>( m_node ) != nullptr );
0107         return static_cast<T*>(m_node);
0108     }
0109     
0110     template<class T>
0111     bool is() const
0112     {
0113         return nullptr != dynamic_cast<T*>(m_node);
0114     }
0115 
0116     GeoParser::QualifiedName qualifiedName() const { return m_qualifiedName; }
0117     GeoNode* associatedNode() const { return m_node; }
0118 
0119 private:
0120     friend class GeoParser;
0121     void assignNode( GeoNode* node ) { m_node = node; }
0122     GeoParser::QualifiedName m_qualifiedName;
0123     GeoNode* m_node;
0124 };
0125 
0126 }
0127 
0128 #endif