LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - hugefileresolver.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 956 756 79.1 %
Date: 2012-04-28 Functions: 22 22 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: hugefileresolver.cpp 23675 2012-01-01 16:09:45Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of GMLReader::HugeFileResolver() method.
       6                 :  * Author:   Alessandro Furieri, a.furitier@lqt.it
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Alessandro Furieri
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  * 
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  * 
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  *
      29                 :  ******************************************************************************
      30                 :  * Contributor: Alessandro Furieri, a.furieri@lqt.it
      31                 :  * This module implents GML_SKIP_RESOLVE_ELEMS HUGE
      32                 :  * Developed for Faunalia ( http://www.faunalia.it) with funding from 
      33                 :  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
      34                 :  *
      35                 :  ****************************************************************************/
      36                 : 
      37                 : #include "gmlreader.h"
      38                 : #include "cpl_error.h"
      39                 : 
      40                 : #include "gmlreaderp.h"
      41                 : #include "gmlutils.h"
      42                 : #include "cpl_conv.h"
      43                 : #include "ogr_p.h"
      44                 : #include "cpl_string.h"
      45                 : #include "cpl_http.h"
      46                 : 
      47                 : #include <stack>
      48                 : 
      49                 : CPL_CVSID("$Id: hugefileresolver.cpp 23675 2012-01-01 16:09:45Z rouault $");
      50                 : 
      51                 : /****************************************************/
      52                 : /*      SQLite is absolutely required in order to   */
      53                 : /*      support the HUGE xlink:href resolver        */
      54                 : /****************************************************/
      55                 : 
      56                 : #ifdef HAVE_SQLITE
      57                 : #include <sqlite3.h>
      58                 : #endif
      59                 : 
      60                 : /* sqlite3_clear_bindings() isn't available in old versions of */
      61                 : /* sqlite3 */
      62                 : #if defined(HAVE_SQLITE) && SQLITE_VERSION_NUMBER >= 3006000
      63                 : 
      64                 : /* an internal helper struct supporting GML tags <Edge> */
      65                 : struct huge_tag
      66                 : {
      67                 :     CPLString           *gmlTagValue;
      68                 :     CPLString           *gmlId;
      69                 :     CPLString           *gmlNodeFrom;
      70                 :     CPLString           *gmlNodeTo;
      71                 :     int                 bIsNodeFromHref;
      72                 :     int                 bIsNodeToHref;
      73                 :     int                 bHasCoords;
      74                 :     int                 bHasZ;
      75                 :     double              xNodeFrom;
      76                 :     double              yNodeFrom;
      77                 :     double              zNodeFrom;
      78                 :     double              xNodeTo;
      79                 :     double              yNodeTo;
      80                 :     double              zNodeTo;
      81                 :     struct huge_tag     *pNext;
      82                 : };
      83                 : 
      84                 : /* an internal helper struct supporting GML tags xlink:href */
      85                 : struct huge_href
      86                 : {
      87                 :     CPLString           *gmlId;
      88                 :     CPLString           *gmlText;
      89                 :     const CPLXMLNode    *psParent;
      90                 :     const CPLXMLNode    *psNode;
      91                 :     int                 bIsDirectedEdge;
      92                 :     char                cOrientation;
      93                 :     struct huge_href    *pNext;
      94                 : };
      95                 : 
      96                 : /* an internal helper struct supporying GML rewriting */
      97                 : struct huge_child
      98                 : {
      99                 :     CPLXMLNode          *psChild;
     100                 :     struct huge_href    *pItem;
     101                 :     struct huge_child   *pNext;
     102                 : };
     103                 : 
     104                 : /* an internal helper struct supporting GML rewriting */
     105                 : struct huge_parent
     106                 : {
     107                 :     CPLXMLNode          *psParent;
     108                 :     struct huge_child   *pFirst;
     109                 :     struct huge_child   *pLast;
     110                 :     struct huge_parent  *pNext;
     111                 : };
     112                 : 
     113                 : /*
     114                 : / an internal helper struct supporting GML 
     115                 : / resolver for Huge Files (based on SQLite)
     116                 : */
     117                 : struct huge_helper
     118                 : {
     119                 :     sqlite3             *hDB;
     120                 :     sqlite3_stmt        *hNodes;
     121                 :     sqlite3_stmt        *hEdges;
     122                 :     CPLString           *nodeSrs;
     123                 :     struct huge_tag     *pFirst;
     124                 :     struct huge_tag     *pLast;
     125                 :     struct huge_href    *pFirstHref;
     126                 :     struct huge_href    *pLastHref;
     127                 :     struct huge_parent  *pFirstParent;
     128                 :     struct huge_parent  *pLastParent;
     129                 : };
     130                 : 
     131               4 : static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     132                 : {
     133                 : /* attempting to create SQLite tables */
     134                 :     const char          *osCommand;
     135               4 :     char                *pszErrMsg = NULL;
     136                 :     int                 rc;
     137               4 :     sqlite3             *hDB = helper->hDB;
     138                 :     sqlite3_stmt        *hStmt;
     139                 : 
     140                 :     /* DB table: NODES */
     141                 :     osCommand = "CREATE TABLE nodes ("
     142                 :                 "     gml_id VARCHAR PRIMARY KEY, "
     143                 :                 "     x DOUBLE, "
     144                 :                 "     y DOUBLE, "
     145               4 :                 "     z DOUBLE)";
     146               4 :     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     147               4 :     if( rc != SQLITE_OK )
     148                 :     {
     149                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     150                 :                   "Unable to create table nodes: %s",
     151               0 :                   pszErrMsg );
     152               0 :         sqlite3_free( pszErrMsg );
     153               0 :         return FALSE;
     154                 :     }
     155                 : 
     156                 :     /* DB table: GML_EDGES */
     157                 :     osCommand = "CREATE TABLE gml_edges ("
     158                 :                 "     gml_id VARCHAR PRIMARY KEY, "
     159                 :                 "     gml_string BLOB, "
     160                 :                 "     gml_resolved BLOB, "
     161                 :         "     node_from_id TEXT, "
     162                 :                 "     node_from_x DOUBLE, "
     163                 :                 "     node_from_y DOUBLE, "
     164                 :                 "     node_from_z DOUBLE, "
     165                 :         "     node_to_id TEXT, "
     166                 :                 "     node_to_x DOUBLE, "
     167                 :                 "     node_to_y DOUBLE, "
     168               4 :                 "     node_to_z DOUBLE)";
     169               4 :     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     170               4 :     if( rc != SQLITE_OK )
     171                 :     {
     172                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     173                 :                   "Unable to create table gml_edges: %s",
     174               0 :                   pszErrMsg );
     175               0 :         sqlite3_free( pszErrMsg );
     176               0 :         return FALSE;
     177                 :     }
     178                 : 
     179                 :     /* DB table: NODES / Insert cursor */
     180                 :     osCommand = "INSERT OR IGNORE INTO nodes (gml_id, x, y, z) "
     181               4 :                 "VALUES (?, ?, ?, ?)";
     182               4 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
     183               4 :     if( rc != SQLITE_OK )
     184                 :     {
     185                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     186               0 :                   "Unable to create INSERT stmt for: nodes" );
     187               0 :         return FALSE;
     188                 :     }
     189               4 :     helper->hNodes = hStmt;
     190                 : 
     191                 :     /* DB table: GML_EDGES / Insert cursor */
     192                 :     osCommand = "INSERT INTO gml_edges "
     193                 :                 "(gml_id, gml_string, gml_resolved, "
     194                 :                 "node_from_id, node_from_x, node_from_y, "
     195                 :                 "node_from_z, node_to_id, node_to_x, "
     196                 :                 "node_to_y, node_to_z) "
     197               4 :                 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
     198               4 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
     199               4 :     if( rc != SQLITE_OK )
     200                 :     {
     201                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     202               0 :                   "Unable to create INSERT stmt for: gml_edges" );
     203               0 :         return FALSE;
     204                 :     }
     205               4 :     helper->hEdges = hStmt;
     206                 : 
     207                 :     /* starting a TRANSACTION */
     208               4 :     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     209               4 :     if( rc != SQLITE_OK )
     210                 :     {
     211                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     212                 :                   "Unable to perform BEGIN TRANSACTION: %s",
     213               0 :                   pszErrMsg );
     214               0 :         sqlite3_free( pszErrMsg );
     215               0 :         return FALSE;
     216                 :     } 
     217                 : 
     218               4 :     return TRUE;
     219                 : }
     220                 : 
     221             140 : static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
     222                 :                                     const char *pszFromId,
     223                 :                                     const char *pszToId )
     224                 : {
     225                 : /* resolves an Edge definition */
     226             140 :     CPLXMLNode      *psDirNode_1 = NULL;
     227             140 :     CPLXMLNode      *psDirNode_2 = NULL;
     228             140 :     CPLXMLNode      *psOldNode_1 = NULL;
     229             140 :     CPLXMLNode      *psOldNode_2 = NULL;
     230             140 :     CPLXMLNode      *psNewNode_1 = NULL;
     231             140 :     CPLXMLNode      *psNewNode_2 = NULL;
     232             140 :     int             iToBeReplaced = 0;
     233             140 :     int             iReplaced = 0;
     234             140 :     if( psNode->eType == CXT_Element && EQUAL( psNode->pszValue, "Edge" ) )
     235                 :         ;
     236                 :     else
     237               0 :         return FALSE;
     238                 : 
     239             140 :     CPLXMLNode *psChild = psNode->psChild;
     240             840 :     while( psChild != NULL )
     241                 :     {
     242             560 :         if( psChild->eType == CXT_Element &&
     243                 :             EQUAL( psChild->pszValue, "directedNode" ) )
     244                 :         {
     245             280 :             char cOrientation = '+';
     246             280 :             CPLXMLNode *psOldNode = NULL;
     247             280 :             CPLXMLNode *psAttr = psChild->psChild;
     248             980 :             while( psAttr != NULL )
     249                 :             {
     250             420 :                 if( psAttr->eType == CXT_Attribute &&
     251                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
     252             192 :                     psOldNode = psAttr;
     253             420 :                 if( psAttr->eType == CXT_Attribute &&
     254                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
     255                 :                 {
     256             140 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
     257             140 :                     if( psOrientation != NULL )
     258                 :                     {
     259             140 :                         if( psOrientation->eType == CXT_Text )
     260             140 :                             cOrientation = *(psOrientation->pszValue);
     261                 :                     }
     262                 :                 }
     263             420 :                 psAttr = psAttr->psNext;
     264                 :             }
     265             280 :             if( psOldNode != NULL )
     266                 :             {
     267             192 :                 CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "Node");
     268             192 :                 CPLXMLNode *psGMLIdNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "gml:id");
     269             192 :                 if( cOrientation == '-' )
     270              98 :                     CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszFromId);
     271                 :                 else
     272              94 :                     CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszToId);
     273             192 :                 if( iToBeReplaced == 0 )
     274                 :                 {
     275             140 :                     psDirNode_1 = psChild;
     276             140 :                     psOldNode_1 = psOldNode;
     277             140 :                     psNewNode_1 = psNewNode;
     278                 :                 }
     279                 :                 else
     280                 :                 {
     281              52 :                     psDirNode_2 = psChild;
     282              52 :                     psOldNode_2 = psOldNode;
     283              52 :                     psNewNode_2 = psNewNode;
     284                 :                 }
     285             192 :                 iToBeReplaced++;
     286                 :             }
     287                 :         }
     288             560 :         psChild = psChild->psNext;
     289                 :     }
     290                 : 
     291                 :     /* rewriting the Edge GML definition */
     292             140 :     if( psDirNode_1 != NULL)
     293                 :     {
     294             140 :         if( psOldNode_1 != NULL )
     295                 :         {
     296             140 :             CPLRemoveXMLChild( psDirNode_1, psOldNode_1 );
     297             140 :             CPLDestroyXMLNode( psOldNode_1 );
     298             140 :             if( psNewNode_1 != NULL )
     299                 :             {
     300             140 :                 CPLAddXMLChild( psDirNode_1, psNewNode_1 );
     301             140 :                 iReplaced++;
     302                 :             }
     303                 :         }
     304                 :     }
     305             140 :     if( psDirNode_2 != NULL)
     306                 :     {
     307              52 :         if( psOldNode_2 != NULL )
     308                 :         {
     309              52 :             CPLRemoveXMLChild( psDirNode_2, psOldNode_2 );
     310              52 :             CPLDestroyXMLNode( psOldNode_2 );
     311              52 :             if( psNewNode_2 != NULL )
     312                 :             {
     313              52 :                 CPLAddXMLChild( psDirNode_2, psNewNode_2 );
     314              52 :                 iReplaced++;
     315                 :             }
     316                 :         }
     317                 :     }
     318             140 :     if( iToBeReplaced != iReplaced )
     319               0 :         return FALSE;
     320             140 : return TRUE;
     321                 : }
     322                 : 
     323               4 : static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     324                 : {
     325                 : /* identifying any not yet resolved <Edge> GML string */
     326                 :     const char          *osCommand;
     327               4 :     char                *pszErrMsg = NULL;
     328                 :     int rc;
     329               4 :     sqlite3             *hDB = helper->hDB;
     330                 :     sqlite3_stmt        *hQueryStmt;
     331                 :     sqlite3_stmt        *hUpdateStmt;
     332               4 :     int                 iCount = 0;
     333               4 :     int                 bError = FALSE;
     334                 : 
     335                 :     /* query cursor */
     336                 :     osCommand = "SELECT e.gml_id, e.gml_string, e.node_from_id, "
     337                 :                 "e.node_from_x, e.node_from_y, e.node_from_z, "
     338                 :                 "n1.gml_id, n1.x, n1.y, n1.z, e.node_to_id, "
     339                 :                 "e.node_to_x, e.node_to_y, e.node_to_z, "
     340                 :                 "n2.gml_id, n2.x, n2.y, n2.z "
     341                 :                 "FROM gml_edges AS e "
     342                 :                 "LEFT JOIN nodes AS n1 ON (n1.gml_id = e.node_from_id) "
     343               4 :                 "LEFT JOIN nodes AS n2 ON (n2.gml_id = e.node_to_id)";
     344               4 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hQueryStmt, NULL );
     345               4 :     if( rc != SQLITE_OK )
     346                 :     {
     347                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     348               0 :                   "Unable to create QUERY stmt for Edge resolver" );
     349               0 :         return FALSE;
     350                 :     }
     351                 : 
     352                 :     /* update cursor */
     353                 :     osCommand = "UPDATE gml_edges "
     354                 :                 "SET gml_resolved = ?, "
     355                 :                 "gml_string = NULL "
     356               4 :                 "WHERE gml_id = ?";
     357               4 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
     358               4 :     if( rc != SQLITE_OK )
     359                 :     {
     360                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     361               0 :                   "Unable to create UPDATE stmt for resolved Edges" );
     362               0 :         sqlite3_finalize ( hQueryStmt );
     363               0 :         return FALSE;
     364                 :     }
     365                 : 
     366                 :     /* starting a TRANSACTION */
     367               4 :     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     368               4 :     if( rc != SQLITE_OK )
     369                 :     {
     370                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     371                 :                   "Unable to perform BEGIN TRANSACTION: %s",
     372               0 :                   pszErrMsg );
     373               0 :         sqlite3_free( pszErrMsg );
     374               0 :         sqlite3_finalize ( hQueryStmt );
     375               0 :         sqlite3_finalize ( hUpdateStmt );
     376               0 :         return FALSE;
     377                 :     }
     378                 :     
     379                 :     /* looping on the QUERY result-set */
     380             162 :     while ( TRUE )
     381                 :     {
     382                 :         const char      *pszGmlId;
     383             166 :         const char      *pszGmlString = NULL;
     384                 :         int             bIsGmlStringNull;
     385             166 :         const char      *pszFromId = NULL;
     386                 :         int             bIsFromIdNull;
     387             166 :         double          xFrom = 0.0;
     388                 :         int             bIsXFromNull;
     389             166 :         double          yFrom = 0.0;
     390                 :         int             bIsYFromNull;
     391             166 :         double          zFrom = 0.0;
     392                 :         int             bIsZFromNull;
     393             166 :         const char      *pszNodeFromId = NULL;
     394                 :         int             bIsNodeFromIdNull;
     395             166 :         double          xNodeFrom = 0.0;
     396                 :         int             bIsXNodeFromNull;
     397             166 :         double          yNodeFrom = 0.0;
     398                 :         int             bIsYNodeFromNull;
     399             166 :         double          zNodeFrom = 0.0;
     400                 :         int             bIsZNodeFromNull;
     401             166 :         const char      *pszToId = NULL;
     402                 :         int             bIsToIdNull;
     403             166 :         double          xTo = 0.0;
     404                 :         int             bIsXToNull;
     405             166 :         double          yTo = 0.0;
     406                 :         int             bIsYToNull;
     407             166 :         double          zTo = 0.0;
     408                 :         int             bIsZToNull;
     409             166 :         const char      *pszNodeToId = NULL;
     410                 :         int             bIsNodeToIdNull;
     411             166 :         double          xNodeTo = 0.0;
     412                 :         int             bIsXNodeToNull;
     413             166 :         double          yNodeTo = 0.0;
     414                 :         int             bIsYNodeToNull;
     415             166 :         double          zNodeTo = 0.0;
     416                 :         int             bIsZNodeToNull;
     417                 : 
     418             166 :         rc = sqlite3_step( hQueryStmt );
     419             166 :         if( rc == SQLITE_DONE )
     420                 :             break;
     421             162 :         else if( rc == SQLITE_ROW )
     422                 :         {
     423             162 :             bError = FALSE;
     424             162 :             pszGmlId = (const char *) sqlite3_column_text( hQueryStmt, 0 );
     425             162 :             if( sqlite3_column_type( hQueryStmt, 1 ) == SQLITE_NULL )
     426              22 :                 bIsGmlStringNull = TRUE;
     427                 :             else
     428                 :             {
     429             140 :                 pszGmlString = (const char *) sqlite3_column_blob( hQueryStmt, 1 );
     430             140 :                 bIsGmlStringNull = FALSE;
     431                 :             }
     432             162 :             if( sqlite3_column_type( hQueryStmt, 2 ) == SQLITE_NULL )
     433               0 :                 bIsFromIdNull = TRUE;
     434                 :             else
     435                 :             {
     436             162 :                 pszFromId = (const char *) sqlite3_column_text( hQueryStmt, 2 );
     437             162 :                 bIsFromIdNull = FALSE;
     438                 :             }
     439             162 :             if( sqlite3_column_type( hQueryStmt, 3 ) == SQLITE_NULL )
     440               0 :                 bIsXFromNull = TRUE;
     441                 :             else
     442                 :             {
     443             162 :                 xFrom = sqlite3_column_double( hQueryStmt, 3 );
     444             162 :                 bIsXFromNull = FALSE;
     445                 :             }
     446             162 :             if( sqlite3_column_type( hQueryStmt, 4 ) == SQLITE_NULL )
     447               0 :                 bIsYFromNull = TRUE;
     448                 :             else
     449                 :             {
     450             162 :                 yFrom = sqlite3_column_double( hQueryStmt, 4 );
     451             162 :                 bIsYFromNull = FALSE;
     452                 :             }
     453             162 :             if( sqlite3_column_type( hQueryStmt, 5 ) == SQLITE_NULL )
     454             162 :                 bIsZFromNull = TRUE;
     455                 :             else
     456                 :             {
     457               0 :                 zFrom = sqlite3_column_double( hQueryStmt, 5 );
     458               0 :                 bIsZFromNull = FALSE;
     459                 :             }
     460             162 :             if( sqlite3_column_type( hQueryStmt, 6 ) == SQLITE_NULL )
     461               0 :                 bIsNodeFromIdNull = TRUE;
     462                 :             else
     463                 :             {
     464             162 :                 pszNodeFromId = (const char *) sqlite3_column_text( hQueryStmt, 6 );
     465             162 :                 bIsNodeFromIdNull = FALSE;
     466                 :             }
     467             162 :             if( sqlite3_column_type( hQueryStmt, 7 ) == SQLITE_NULL )
     468               0 :                 bIsXNodeFromNull = TRUE;
     469                 :             else
     470                 :             {
     471             162 :                 xNodeFrom = sqlite3_column_double( hQueryStmt, 7 );
     472             162 :                 bIsXNodeFromNull = FALSE;
     473                 :             }
     474             162 :             if( sqlite3_column_type( hQueryStmt, 8 ) == SQLITE_NULL )
     475               0 :                 bIsYNodeFromNull = TRUE;
     476                 :             else
     477                 :             {
     478             162 :                 yNodeFrom = sqlite3_column_double( hQueryStmt, 8 );
     479             162 :                 bIsYNodeFromNull = FALSE;
     480                 :             }
     481             162 :             if( sqlite3_column_type( hQueryStmt, 9 ) == SQLITE_NULL )
     482             162 :                 bIsZNodeFromNull = TRUE;
     483                 :             else
     484                 :             {
     485               0 :                 zNodeFrom = sqlite3_column_double( hQueryStmt, 9 );
     486               0 :                 bIsZNodeFromNull = FALSE;
     487                 :             }
     488             162 :             if( sqlite3_column_type( hQueryStmt, 10 ) == SQLITE_NULL )
     489               0 :                 bIsToIdNull = TRUE;
     490                 :             else
     491                 :             {
     492             162 :                 pszToId = (const char *) sqlite3_column_text( hQueryStmt, 10 );
     493             162 :                 bIsToIdNull = FALSE;
     494                 :             }
     495             162 :             if( sqlite3_column_type( hQueryStmt, 11 ) == SQLITE_NULL )
     496               0 :                 bIsXToNull = TRUE;
     497                 :             else
     498                 :             {
     499             162 :                 xTo = sqlite3_column_double( hQueryStmt, 11 );
     500             162 :                 bIsXToNull = FALSE;
     501                 :             }
     502             162 :             if( sqlite3_column_type( hQueryStmt, 12 ) == SQLITE_NULL )
     503               0 :                 bIsYToNull = TRUE;
     504                 :             else
     505                 :             {
     506             162 :                 yTo = sqlite3_column_double( hQueryStmt, 12 );
     507             162 :                 bIsYToNull = FALSE;
     508                 :             }
     509             162 :             if( sqlite3_column_type( hQueryStmt, 13 ) == SQLITE_NULL )
     510             162 :                 bIsZToNull = TRUE;
     511                 :             else
     512                 :             {
     513               0 :                 zTo = sqlite3_column_double( hQueryStmt, 13 );
     514               0 :                 bIsZToNull = FALSE;
     515                 :             }
     516             162 :             if( sqlite3_column_type( hQueryStmt, 14 ) == SQLITE_NULL )
     517               0 :                 bIsNodeToIdNull = TRUE;
     518                 :             else
     519                 :             {
     520             162 :                 pszNodeToId = (const char *) sqlite3_column_text( hQueryStmt, 14 );
     521             162 :                 bIsNodeToIdNull = FALSE;
     522                 :             }
     523             162 :             if( sqlite3_column_type( hQueryStmt, 15 ) == SQLITE_NULL )
     524               0 :                 bIsXNodeToNull = TRUE;
     525                 :             else
     526                 :             {
     527             162 :                 xNodeTo = sqlite3_column_double( hQueryStmt, 15 );
     528             162 :                 bIsXNodeToNull = FALSE;
     529                 :             }
     530             162 :             if( sqlite3_column_type( hQueryStmt, 16 ) == SQLITE_NULL )
     531               0 :                 bIsYNodeToNull = TRUE;
     532                 :             else
     533                 :             {
     534             162 :                 yNodeTo = sqlite3_column_double( hQueryStmt, 16 );
     535             162 :                 bIsYNodeToNull = FALSE;
     536                 :             }
     537             162 :             if( sqlite3_column_type( hQueryStmt, 17 ) == SQLITE_NULL )
     538             162 :                 bIsZNodeToNull = TRUE;
     539                 :             else
     540                 :             {
     541               0 :                 zNodeTo = sqlite3_column_double( hQueryStmt, 17 );
     542               0 :                 bIsZNodeToNull = FALSE;
     543                 :             }
     544                 : 
     545                 :             /* checking for consistency */
     546             162 :             if( bIsFromIdNull == TRUE || bIsXFromNull == TRUE ||
     547                 :                 bIsYFromNull == TRUE )
     548                 :             {
     549               0 :                 bError = TRUE;
     550                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     551                 :                           "Edge gml:id=\"%s\": invalid Node-from", 
     552               0 :                           pszGmlId );
     553                 :             }
     554                 :             else
     555                 :             {
     556             162 :                 if( bIsNodeFromIdNull == TRUE )
     557                 :                 {
     558               0 :                     bError = TRUE;
     559                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     560                 :                               "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
     561               0 :                               pszGmlId, pszFromId );
     562                 :                 }
     563             162 :                 else if( bIsXNodeFromNull == TRUE || bIsYNodeFromNull == TRUE )
     564                 :                 {
     565               0 :                     bError = TRUE;
     566                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     567                 :                               "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
     568               0 :                               pszGmlId, pszFromId );
     569                 :                 }
     570             162 :                 else if( xFrom != xNodeFrom || yFrom != yNodeFrom )
     571                 :                 {
     572               0 :                     bError = TRUE;
     573                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     574                 :                               "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
     575               0 :                               pszGmlId, pszFromId );
     576                 :                 }
     577                 :                 else
     578                 :                 {
     579             162 :                     if( bIsZFromNull == TRUE && bIsZNodeFromNull == TRUE )
     580                 : ;
     581               0 :                     else if(  bIsZFromNull == TRUE || bIsZNodeFromNull == TRUE )
     582                 :                     {
     583               0 :                         bError = TRUE;
     584                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
     585                 :                                   "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
     586               0 :                                   pszGmlId, pszFromId );
     587                 :                     }
     588               0 :                     else if( zFrom != zNodeFrom ) 
     589                 :                     {
     590               0 :                         bError = TRUE;
     591                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
     592                 :                                   "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
     593               0 :                                   pszGmlId, pszFromId );
     594                 :                     }
     595                 :                 }
     596                 :             }
     597             162 :             if( bIsToIdNull == TRUE || bIsXToNull == TRUE ||
     598                 :                 bIsYToNull == TRUE )
     599                 :             {
     600               0 :                 bError = TRUE;
     601                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     602                 :                           "Edge gml:id=\"%s\": invalid Node-to", 
     603               0 :                           pszGmlId );
     604                 :             }
     605                 :             else
     606                 :             {
     607             162 :                 if( bIsNodeToIdNull == TRUE )
     608                 :                 {
     609               0 :                     bError = TRUE;
     610                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     611                 :                               "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
     612               0 :                               pszGmlId, pszToId );
     613                 :                 }
     614             162 :                 else if( bIsXNodeToNull == TRUE || bIsYNodeToNull == TRUE )
     615                 :                 {
     616               0 :                     bError = TRUE;
     617                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     618                 :                               "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
     619               0 :                               pszGmlId, pszToId );
     620                 :                 }
     621             162 :                 else if( xTo != xNodeTo || yTo != yNodeTo )
     622                 :                 {
     623               0 :                     bError = TRUE;
     624                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     625                 :                               "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
     626               0 :                               pszGmlId, pszToId );
     627                 :                 }
     628                 :                 else
     629                 :                 {
     630             162 :                     if( bIsZToNull == TRUE && bIsZNodeToNull == TRUE )
     631                 : ;
     632               0 :                     else if(  bIsZToNull == TRUE || bIsZNodeToNull == TRUE )
     633                 :                     {
     634               0 :                         bError = TRUE;
     635                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
     636                 :                                   "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
     637               0 :                                   pszGmlId, pszToId );
     638                 :                     }
     639               0 :                     else if( zTo != zNodeTo ) 
     640                 :                     {
     641               0 :                         bError = TRUE;
     642                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
     643                 :                                   "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
     644               0 :                                   pszGmlId, pszToId );
     645                 :                     }
     646                 :                 }
     647                 :             }
     648                 : 
     649                 :             /* updating the resolved Node */
     650             162 :             if( bError == FALSE && bIsGmlStringNull == FALSE &&
     651                 :                 bIsFromIdNull == FALSE && bIsToIdNull == FALSE )
     652                 :             {
     653             140 :                 CPLXMLNode *psNode = CPLParseXMLString( pszGmlString );
     654             140 :                 if( psNode != NULL )
     655                 :                 {
     656             140 :                     if( gmlHugeResolveEdgeNodes( psNode, pszFromId,
     657                 :                                                  pszToId ) == TRUE )
     658                 :                     {
     659             140 :                         char * gmlText = CPLSerializeXMLTree(psNode);
     660             140 :                         sqlite3_reset ( hUpdateStmt );
     661             140 :                         sqlite3_clear_bindings ( hUpdateStmt );
     662                 :                         sqlite3_bind_blob( hUpdateStmt, 1, gmlText,
     663             140 :                                            strlen(gmlText), SQLITE_STATIC );
     664                 :                         sqlite3_bind_text( hUpdateStmt, 2, pszGmlId, -1,
     665             140 :                                            SQLITE_STATIC );
     666             140 :                         rc = sqlite3_step( hUpdateStmt );
     667             140 :                         if( rc != SQLITE_OK && rc != SQLITE_DONE )
     668                 :                         {
     669                 :                             CPLError( CE_Failure, CPLE_AppDefined,
     670                 :                                       "UPDATE resoved Edge \"%s\" sqlite3_step() failed:\n  %s",
     671               0 :                                       pszGmlId, sqlite3_errmsg(hDB) );
     672                 :                         }
     673             140 :                         CPLFree( gmlText );
     674             140 :                         iCount++;
     675             140 :                         if( (iCount % 1024) == 1023 )
     676                 :                         {
     677                 :                             /* committing the current TRANSACTION */
     678                 :                             rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL,
     679               0 :                                                &pszErrMsg );
     680               0 :                             if( rc != SQLITE_OK )
     681                 :                             {
     682                 :                                 CPLError( CE_Failure, CPLE_AppDefined, 
     683                 :                                           "Unable to perform COMMIT TRANSACTION: %s",
     684               0 :                                           pszErrMsg );
     685               0 :                                 sqlite3_free( pszErrMsg );
     686               0 :                                 return FALSE;
     687                 :                             }
     688                 :                             /* restarting a new TRANSACTION */
     689               0 :                             rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     690               0 :                             if( rc != SQLITE_OK )
     691                 :                             {
     692                 :                                 CPLError( CE_Failure, CPLE_AppDefined, 
     693                 :                                           "Unable to perform BEGIN TRANSACTION: %s",
     694               0 :                                           pszErrMsg );
     695               0 :                                 sqlite3_free( pszErrMsg );
     696               0 :                                 sqlite3_finalize ( hQueryStmt );
     697               0 :                                 sqlite3_finalize ( hUpdateStmt );
     698               0 :                                 return FALSE;
     699                 :                             }
     700                 :                         }
     701                 :                     }
     702             140 :                     CPLDestroyXMLNode( psNode );
     703                 :                 }
     704                 :             }
     705                 :         }
     706                 :         else
     707                 :         {
     708                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     709                 :                       "Edge resolver QUERY: sqlite3_step(%s)", 
     710               0 :                       sqlite3_errmsg(hDB) );
     711               0 :             sqlite3_finalize ( hQueryStmt );
     712               0 :             sqlite3_finalize ( hUpdateStmt );
     713               0 :             return FALSE;
     714                 :         }
     715                 :     }
     716               4 :     sqlite3_finalize ( hQueryStmt );
     717               4 :     sqlite3_finalize ( hUpdateStmt );
     718                 : 
     719                 :     /* committing the current TRANSACTION */
     720               4 :     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
     721               4 :     if( rc != SQLITE_OK )
     722                 :     {
     723                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     724                 :                   "Unable to perform COMMIT TRANSACTION: %s",
     725               0 :                   pszErrMsg );
     726               0 :         sqlite3_free( pszErrMsg );
     727               0 :         return FALSE;
     728                 :     }
     729               4 :     if( bError == TRUE )
     730               0 :         return FALSE;
     731               4 :     return TRUE;
     732                 : }
     733                 : 
     734             144 : static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
     735                 : {
     736                 : /* inserting any appropriate row into the SQLite DB */
     737                 :     int rc;
     738                 :     struct huge_tag *pItem;
     739                 : 
     740                 :     /* looping on GML tags */
     741             144 :     pItem = helper->pFirst;
     742             450 :     while ( pItem != NULL )
     743                 :     {
     744             162 :         if( pItem->bHasCoords == TRUE )
     745                 :         {
     746             162 :             if( pItem->gmlNodeFrom != NULL )
     747                 :             {
     748             162 :                 sqlite3_reset ( helper->hNodes );
     749             162 :                 sqlite3_clear_bindings ( helper->hNodes );
     750                 :                 sqlite3_bind_text( helper->hNodes, 1,
     751                 :                                    pItem->gmlNodeFrom->c_str(), -1,
     752             162 :                                    SQLITE_STATIC );
     753             162 :                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeFrom );
     754             162 :                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeFrom );
     755             162 :                 if( pItem->bHasZ == TRUE )
     756               0 :                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeFrom );
     757             162 :                 sqlite3_bind_null ( helper->hNodes, 5 );
     758             162 :                 rc = sqlite3_step( helper->hNodes );
     759             162 :                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
     760                 :                 {
     761                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     762                 :                               "sqlite3_step() failed:\n  %s", 
     763               0 :                               sqlite3_errmsg(helper->hDB) );
     764               0 :                               return FALSE;
     765                 :                 }
     766                 :             }
     767             162 :             if( pItem->gmlNodeTo != NULL )
     768                 :             {
     769             162 :                 sqlite3_reset ( helper->hNodes );
     770             162 :                 sqlite3_clear_bindings ( helper->hNodes );
     771                 :                 sqlite3_bind_text( helper->hNodes, 1, pItem->gmlNodeTo->c_str(),
     772             162 :                                    -1, SQLITE_STATIC );
     773             162 :                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeTo );
     774             162 :                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeTo );
     775             162 :                 if ( pItem->bHasZ == TRUE )
     776               0 :                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeTo );
     777             162 :                 sqlite3_bind_null ( helper->hNodes, 5 );
     778             162 :                 rc = sqlite3_step( helper->hNodes );
     779             162 :                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
     780                 :                 {
     781                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     782                 :                               "sqlite3_step() failed:\n  %s", 
     783               0 :                               sqlite3_errmsg(helper->hDB) );
     784               0 :                               return FALSE;
     785                 :                 }
     786                 :             }
     787                 :         }
     788                 : 
     789                 :         /* gml:id */
     790             162 :         sqlite3_reset( helper->hEdges );
     791             162 :         sqlite3_clear_bindings( helper->hEdges );
     792                 :         sqlite3_bind_text( helper->hEdges, 1, pItem->gmlId->c_str(), -1,
     793             162 :                            SQLITE_STATIC );
     794             184 :         if( pItem->bIsNodeFromHref == FALSE && pItem->bIsNodeToHref == FALSE )
     795                 :         {
     796              22 :             sqlite3_bind_null( helper->hEdges, 2 );
     797                 :             sqlite3_bind_blob( helper->hEdges, 3, pItem->gmlTagValue->c_str(),
     798                 :                                strlen( pItem->gmlTagValue->c_str() ),
     799              22 :                                SQLITE_STATIC );
     800                 :         }
     801                 :         else
     802                 :         {
     803                 :             sqlite3_bind_blob( helper->hEdges, 2, pItem->gmlTagValue->c_str(),
     804                 :                                strlen( pItem->gmlTagValue->c_str() ),
     805             140 :                                SQLITE_STATIC );
     806             140 :             sqlite3_bind_null( helper->hEdges, 3 );
     807                 :         }
     808             162 :         if( pItem->gmlNodeFrom != NULL )
     809                 :             sqlite3_bind_text( helper->hEdges, 4, pItem->gmlNodeFrom->c_str(),
     810             162 :                                -1, SQLITE_STATIC );
     811                 :         else
     812               0 :             sqlite3_bind_null( helper->hEdges, 4 );
     813             162 :         if( pItem->bHasCoords == TRUE )
     814                 :         {
     815             162 :             sqlite3_bind_double( helper->hEdges, 5, pItem->xNodeFrom );
     816             162 :             sqlite3_bind_double( helper->hEdges, 6, pItem->yNodeFrom );
     817             162 :             if( pItem->bHasZ == TRUE )
     818               0 :                 sqlite3_bind_double( helper->hEdges, 7, pItem->zNodeFrom );
     819                 :             else
     820             162 :                 sqlite3_bind_null( helper->hEdges, 7 );
     821                 :         }
     822                 :         else
     823                 :         {
     824               0 :             sqlite3_bind_null( helper->hEdges, 5 );
     825               0 :             sqlite3_bind_null( helper->hEdges, 6 );
     826               0 :             sqlite3_bind_null( helper->hEdges, 7 );
     827                 :         }
     828             162 :         if( pItem->gmlNodeTo != NULL )
     829                 :             sqlite3_bind_text( helper->hEdges, 8, pItem->gmlNodeTo->c_str(),
     830             162 :                                -1, SQLITE_STATIC );
     831                 :         else
     832               0 :             sqlite3_bind_null( helper->hEdges, 8 );
     833             162 :         if( pItem->bHasCoords == TRUE )
     834                 :         {
     835             162 :             sqlite3_bind_double( helper->hEdges, 9, pItem->xNodeTo );
     836             162 :             sqlite3_bind_double( helper->hEdges, 10, pItem->yNodeTo );
     837             162 :             if( pItem->bHasZ == TRUE )
     838               0 :                 sqlite3_bind_double( helper->hEdges, 11, pItem->zNodeTo );
     839                 :             else
     840             162 :                 sqlite3_bind_null( helper->hEdges, 11 );
     841                 :         }
     842                 :         else
     843                 :         {
     844               0 :             sqlite3_bind_null( helper->hEdges, 9 );
     845               0 :             sqlite3_bind_null( helper->hEdges, 10 );
     846               0 :             sqlite3_bind_null( helper->hEdges, 11 );
     847                 :         }
     848             162 :         rc = sqlite3_step( helper->hEdges );
     849             162 :         if( rc != SQLITE_OK && rc != SQLITE_DONE )
     850                 :         {
     851                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     852                 :                       "sqlite3_step() failed:\n  %s", 
     853               0 :                       sqlite3_errmsg(helper->hDB) );
     854               0 :             return FALSE;
     855                 :         }
     856             162 :         pItem = pItem->pNext;
     857                 :     }
     858             144 :     return TRUE;
     859                 : }
     860                 : 
     861             144 : static void gmlHugeFileReset( struct huge_helper *helper )
     862                 : {
     863                 : /* resetting an empty helper struct */
     864                 :     struct huge_tag *pNext;
     865             144 :     struct huge_tag *p = helper->pFirst;
     866                 : 
     867                 :     /* cleaning any previous item */
     868             450 :     while( p != NULL )
     869                 :     {
     870             162 :         pNext = p->pNext;
     871             162 :         if( p->gmlTagValue != NULL )
     872             162 :             delete p->gmlTagValue;
     873             162 :         if( p->gmlId != NULL )
     874             162 :             delete p->gmlId;
     875             162 :         if( p->gmlNodeFrom != NULL )
     876             162 :             delete p->gmlNodeFrom;
     877             162 :         if( p->gmlNodeTo != NULL )
     878             162 :             delete p->gmlNodeTo;
     879             162 :         delete p;
     880             162 :         p = pNext;
     881                 :     }
     882             144 :     helper->pFirst = NULL;
     883             144 :     helper->pLast = NULL;
     884             144 : }
     885                 : 
     886              28 : static void gmlHugeFileHrefReset( struct huge_helper *helper )
     887                 : {
     888                 : /* resetting an empty helper struct */
     889                 :     struct huge_href *pNext;
     890              28 :     struct huge_href *p = helper->pFirstHref;
     891                 : 
     892                 :     /* cleaning any previous item */
     893             302 :     while( p != NULL )
     894                 :     {
     895             246 :         pNext = p->pNext;
     896             246 :         if( p->gmlId != NULL )
     897             246 :             delete p->gmlId;
     898             246 :         if( p->gmlText != NULL )
     899             246 :             delete p->gmlText;
     900             246 :         delete p;
     901             246 :         p = pNext;
     902                 :     }
     903              28 :     helper->pFirstHref = NULL;
     904              28 :     helper->pLastHref = NULL;
     905              28 : }
     906                 : 
     907              28 : static int gmlHugeFileHrefCheck( struct huge_helper *helper )
     908                 : {
     909                 : /* testing for unresolved items */
     910              28 :     int bError = FALSE;
     911              28 :   struct huge_href *p = helper->pFirstHref;
     912             302 :   while( p != NULL )
     913                 :     {
     914             246 :     if( p->gmlText == NULL)
     915                 :     {
     916               0 :       bError = TRUE;
     917                 :       CPLError( CE_Failure, CPLE_AppDefined, 
     918                 :                       "Edge xlink:href\"%s\": unresolved match", 
     919               0 :                       p->gmlId->c_str() );
     920                 :     }
     921             246 :         p = p->pNext;
     922                 :     }
     923              28 :   if( bError == TRUE )
     924               0 :     return FALSE;
     925              28 :   return TRUE;
     926                 : }
     927                 : 
     928              28 : static void gmlHugeFileRewiterReset( struct huge_helper *helper )
     929                 : {
     930                 : /* resetting an empty helper struct */
     931                 :     struct huge_parent *pNext;
     932              28 :     struct huge_parent *p = helper->pFirstParent;
     933                 : 
     934                 :     /* cleaning any previous item */
     935             108 :     while( p != NULL )
     936                 :     {
     937              52 :         pNext = p->pNext;
     938                 :         struct huge_child *pChildNext;
     939              52 :         struct huge_child *pChild = p->pFirst;
     940             432 :         while( pChild != NULL )
     941                 :         {
     942             328 :             pChildNext = pChild->pNext;
     943             328 :             delete pChild;
     944             328 :             pChild = pChildNext;
     945                 :         }
     946              52 :         delete p;
     947              52 :         p = pNext;
     948                 :     }
     949              28 :     helper->pFirstParent = NULL;
     950              28 :     helper->pLastParent = NULL;
     951              28 : }
     952                 : 
     953             194 : static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
     954                 :                                             CPLString *gmlId,
     955                 :                                             CPLString *gmlFragment )
     956                 : {
     957                 : /* adding an item  into the linked list */
     958                 :     struct huge_tag *pItem;
     959                 : 
     960                 :     /* checking against duplicates */
     961             194 :     pItem = helper->pFirst;
     962             678 :     while( pItem != NULL )
     963                 :     {
     964             322 :         if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) )
     965              32 :             return NULL;
     966             290 :         pItem = pItem->pNext;
     967                 :     } 
     968                 : 
     969             162 :     pItem = new struct huge_tag;
     970             162 :     pItem->gmlId = gmlId;
     971             162 :     pItem->gmlTagValue = gmlFragment;
     972             162 :     pItem->gmlNodeFrom = NULL;
     973             162 :     pItem->gmlNodeTo = NULL;
     974             162 :     pItem->bHasCoords = FALSE;
     975             162 :     pItem->bHasZ = FALSE;
     976             162 :     pItem->pNext = NULL;
     977                 : 
     978                 :     /* appending the item to the linked list */
     979             162 :     if ( helper->pFirst == NULL )
     980             118 :         helper->pFirst = pItem;
     981             162 :     if ( helper->pLast != NULL )
     982              44 :         helper->pLast->pNext = pItem;
     983             162 :     helper->pLast = pItem;
     984             162 :     return pItem;
     985                 : }
     986                 : 
     987             246 : static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
     988                 :                                        CPLString *gmlId,
     989                 :                                        const CPLXMLNode *psParent,
     990                 :                                        const CPLXMLNode *psNode,
     991                 :                                        int bIsDirectedEdge,
     992                 :                                        char cOrientation )
     993                 : {
     994                 : /* inserting an item into the linked list */
     995                 :     struct huge_href *pItem;
     996                 : 
     997                 :     /* checking against duplicates */
     998             246 :     pItem = helper->pFirstHref;
     999            1640 :     while( pItem != NULL )
    1000                 :     {
    1001            1148 :         if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) &&
    1002                 :             pItem->psParent == psParent  && 
    1003                 :             pItem->psNode == psNode && 
    1004                 :             pItem->cOrientation == cOrientation &&
    1005                 :             pItem->bIsDirectedEdge == bIsDirectedEdge )
    1006                 :             {
    1007               0 :                 delete gmlId;
    1008               0 :                 return;
    1009                 :             }
    1010            1148 :             pItem = pItem->pNext;
    1011                 :     } 
    1012                 : 
    1013             246 :     pItem = new struct huge_href;
    1014             246 :     pItem->gmlId = gmlId;
    1015             246 :     pItem->gmlText = NULL;
    1016             246 :     pItem->psParent = psParent;
    1017             246 :     pItem->psNode = psNode;
    1018             246 :     pItem->bIsDirectedEdge = bIsDirectedEdge;
    1019             246 :     pItem->cOrientation = cOrientation;
    1020             246 :     pItem->pNext = NULL;
    1021                 : 
    1022                 :     /* appending the item to the linked list */
    1023             246 :     if ( helper->pFirstHref == NULL )
    1024              28 :         helper->pFirstHref = pItem;
    1025             246 :     if ( helper->pLastHref != NULL )
    1026             218 :         helper->pLastHref->pNext = pItem;
    1027             246 :     helper->pLastHref = pItem;
    1028                 : }
    1029                 : 
    1030             194 : static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
    1031                 : {
    1032                 : /* attempting to identify a gml:id value      */
    1033             194 :     *gmlId = NULL;
    1034             194 :     const CPLXMLNode *psChild = psNode->psChild;
    1035             388 :     while( psChild != NULL )
    1036                 :     {
    1037             194 :         if( psChild->eType == CXT_Attribute &&
    1038                 :             EQUAL( psChild->pszValue, "gml:id" ) )
    1039                 :         {
    1040             194 :             const CPLXMLNode *psIdValue = psChild->psChild;
    1041             194 :             if( psIdValue != NULL )
    1042                 :             {
    1043             194 :                 if( psIdValue->eType == CXT_Text )
    1044                 :                 {
    1045             194 :                     *gmlId = new CPLString(psIdValue->pszValue);
    1046             194 :                     return TRUE;
    1047                 :                 }
    1048                 :             }
    1049                 :         }
    1050               0 :         psChild = psChild->psNext;
    1051                 :     }
    1052               0 :     return FALSE;
    1053                 : }
    1054                 : 
    1055             162 : static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
    1056                 :                                    const CPLXMLNode * psNode,
    1057                 :                                    CPLString **nodeSrs )
    1058                 : {
    1059                 : /* 
    1060                 : / this function attempts to set coordinates for <Node> items
    1061                 : / when required (an <Edge> is expected to be processed)
    1062                 : */
    1063                 : 
    1064                 : /* attempting to fetch Node coordinates */
    1065             162 :     CPLXMLNode *psTopoCurve = CPLCreateXMLNode(NULL, CXT_Element, "TopoCurve");
    1066             162 :     CPLXMLNode *psDirEdge = CPLCreateXMLNode(psTopoCurve, CXT_Element, "directedEdge");
    1067             162 :     CPLXMLNode *psEdge = CPLCloneXMLTree((CPLXMLNode *)psNode);
    1068             162 :     CPLAddXMLChild( psDirEdge, psEdge );
    1069                 :     OGRGeometryCollection *poColl = (OGRGeometryCollection *)
    1070             162 :                                     GML2OGRGeometry_XMLNode( psTopoCurve, FALSE );
    1071             162 :     CPLDestroyXMLNode( psTopoCurve );
    1072             162 :     if( poColl != NULL )
    1073                 :     {
    1074             162 :         int iCount = poColl->getNumGeometries();
    1075             162 :         if( iCount == 1 )
    1076                 :         {
    1077             162 :             OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(0);
    1078             162 :             int type = wkbFlatten( poChild->getGeometryType());
    1079             162 :             if( type == wkbLineString )
    1080                 :             {
    1081             162 :                 OGRLineString *poLine = (OGRLineString *)poChild;
    1082             162 :                 int iPoints =  poLine->getNumPoints();
    1083             162 :                 if( iPoints >= 2 )
    1084                 :                 {
    1085             162 :                     pItem->bHasCoords = TRUE;
    1086             162 :                     pItem->xNodeFrom = poLine->getX( 0 );
    1087             162 :                     pItem->yNodeFrom = poLine->getY( 0 );
    1088             162 :                     pItem->xNodeTo = poLine->getX( iPoints - 1 );
    1089             162 :                     pItem->yNodeTo = poLine->getY( iPoints - 1 );
    1090             162 :                     if( poLine->getCoordinateDimension() == 3 )
    1091                 :                     {
    1092               0 :                         pItem->zNodeFrom = poLine->getZ( 0 );
    1093               0 :                         pItem->zNodeTo = poLine->getZ( iPoints - 1 );
    1094               0 :                         pItem->bHasZ = TRUE;
    1095                 :                     }
    1096                 :                     else
    1097             162 :                         pItem->bHasZ = FALSE;
    1098                 :                 }
    1099                 :             }
    1100                 :         }
    1101             162 :         delete poColl;
    1102                 :     }
    1103                 :   
    1104                 :     /* searching the <directedNode> sub-tags */
    1105             162 :     const CPLXMLNode *psChild = psNode->psChild;
    1106             972 :     while( psChild != NULL )
    1107                 :     {
    1108             648 :         if( psChild->eType == CXT_Element &&
    1109                 :             EQUAL( psChild->pszValue, "directedNode" ) )
    1110                 :         {
    1111             324 :             char cOrientation = '+';
    1112             324 :             const char *pszGmlId = NULL;
    1113             324 :             int bIsHref = FALSE;
    1114             324 :             const CPLXMLNode *psAttr = psChild->psChild;
    1115            1134 :             while( psAttr != NULL )
    1116                 :             {
    1117             486 :                 if( psAttr->eType == CXT_Attribute &&
    1118                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
    1119                 :                 {
    1120             192 :                     const CPLXMLNode *psHref = psAttr->psChild;
    1121             192 :                     if( psHref != NULL )
    1122                 :                     {
    1123             192 :                         if( psHref->eType == CXT_Text )
    1124                 :                         {
    1125             192 :                             pszGmlId = psHref->pszValue;
    1126             192 :                             bIsHref = TRUE;
    1127                 :                         }
    1128                 :                     }
    1129                 :                 }
    1130             486 :                 if( psAttr->eType == CXT_Attribute &&
    1131                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
    1132                 :                 {
    1133             162 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
    1134             162 :                     if( psOrientation != NULL )
    1135                 :                     {
    1136             162 :                         if( psOrientation->eType == CXT_Text )
    1137                 :                         {
    1138             162 :                             cOrientation = *(psOrientation->pszValue);
    1139                 :                         }
    1140                 :                     }
    1141                 :                 }
    1142             486 :                 if( psAttr->eType == CXT_Element &&
    1143                 :                     EQUAL( psAttr->pszValue, "Node" ) )
    1144                 :                 {
    1145             132 :                     const CPLXMLNode *psId = psAttr->psChild;
    1146             396 :                     while( psId != NULL )
    1147                 :                     {   
    1148             132 :                         if( psId->eType == CXT_Attribute &&
    1149                 :                             EQUAL( psId->pszValue, "gml:id" ) )
    1150                 :                         {
    1151             132 :                             const CPLXMLNode *psIdGml = psId->psChild;
    1152             132 :                             if( psIdGml != NULL )
    1153                 :                             {
    1154             132 :                                 if( psIdGml->eType == CXT_Text )
    1155                 :                                 {
    1156             132 :                                     pszGmlId = psIdGml->pszValue;
    1157             132 :                                     bIsHref = FALSE;
    1158                 :                                 }
    1159                 :                             }
    1160                 :                         }
    1161             132 :                         psId = psId->psNext;
    1162                 :                     }
    1163                 :                 }
    1164             486 :                 psAttr = psAttr->psNext;
    1165                 :             }
    1166             324 :             if( pszGmlId != NULL )
    1167                 :             {
    1168                 :                 CPLString* posNode;
    1169             324 :                 if( bIsHref == TRUE )
    1170                 :                 {
    1171             192 :                     if (pszGmlId[0] != '#')
    1172                 :                     {
    1173                 :                         CPLError(CE_Warning, CPLE_NotSupported,
    1174                 :                                  "Only values of xlink:href element starting with '#' are supported, "
    1175               0 :                                  "so %s will not be properly recognized", pszGmlId);
    1176                 :                     }
    1177             192 :                     posNode = new CPLString(pszGmlId+1);
    1178                 :                 }
    1179                 :                 else
    1180             132 :                     posNode = new CPLString(pszGmlId);
    1181             324 :                 if( cOrientation == '-' )
    1182                 :                 {
    1183             162 :                      pItem->gmlNodeFrom = posNode;
    1184             162 :                     pItem->bIsNodeFromHref = bIsHref;
    1185                 :                 }
    1186                 :                 else
    1187                 :                 {
    1188             162 :                     pItem->gmlNodeTo = posNode;
    1189             162 :                     pItem->bIsNodeToHref = bIsHref;
    1190                 :                 }
    1191             324 :                 pszGmlId = NULL;
    1192             324 :                 bIsHref = FALSE;
    1193             324 :                 cOrientation = '+';
    1194                 :             }
    1195                 :         }
    1196             648 :         psChild = psChild->psNext;
    1197                 :     }
    1198             162 : }
    1199                 : 
    1200             502 : static void gmlHugeFileCheckXrefs( struct huge_helper *helper, 
    1201                 :                                    const CPLXMLNode *psNode )
    1202                 : {
    1203                 : /* identifying <Edge> GML nodes */
    1204             502 :     if( psNode->eType == CXT_Element )
    1205                 :     {
    1206             502 :         if( EQUAL(psNode->pszValue, "Edge") == TRUE )
    1207                 :         {
    1208             194 :             CPLString *gmlId = NULL;
    1209             194 :             if( gmlHugeFindGmlId( psNode, &gmlId ) == TRUE )
    1210                 :             {
    1211             194 :                 char * gmlText = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1212             194 :                 CPLString *gmlValue = new CPLString(gmlText);
    1213             194 :                 CPLFree( gmlText );
    1214                 :                 struct huge_tag *pItem = gmlHugeAddToHelper( helper, gmlId,
    1215             194 :                                                              gmlValue );
    1216             194 :                 if( pItem != NULL )
    1217             162 :                     gmlHugeFileNodeCoords( pItem, psNode, &(helper->nodeSrs) );
    1218                 :                 else
    1219                 :                 {
    1220              32 :                     delete gmlId;
    1221              32 :                     delete gmlValue;
    1222                 :                 }
    1223                 :             }
    1224                 :         }
    1225                 :     }
    1226                 : 
    1227                 :     /* recursively scanning each Child GML node */
    1228             502 :     const CPLXMLNode *psChild = psNode->psChild;
    1229            2128 :     while( psChild != NULL )
    1230                 :     {
    1231            1124 :         if( psChild->eType == CXT_Element )
    1232                 :         {
    1233             930 :             if( EQUAL(psChild->pszValue, "Edge") == TRUE ||
    1234                 :                 EQUAL(psChild->pszValue, "directedEdge") == TRUE )
    1235                 :             {
    1236             296 :                 gmlHugeFileCheckXrefs( helper, psChild );
    1237                 :             }
    1238             930 :             if( EQUAL(psChild->pszValue, "directedFace") == TRUE )
    1239                 :             {
    1240              52 :                 const CPLXMLNode *psFace = psChild->psChild;
    1241              52 :                 if( psFace != NULL )
    1242                 :                 {
    1243              52 :                     if( psFace->eType == CXT_Element &&
    1244                 :                         EQUAL(psFace->pszValue, "Face") == TRUE)
    1245                 :                     {
    1246              48 :                         const CPLXMLNode *psDirEdge = psFace->psChild;
    1247             410 :                         while (psDirEdge != NULL)
    1248                 :                         {
    1249             314 :                             const CPLXMLNode *psEdge = psDirEdge->psChild;
    1250            1072 :                             while( psEdge != NULL)
    1251                 :                             {
    1252             444 :                                 if( psEdge->eType == CXT_Element &&
    1253                 :                                     EQUAL(psEdge->pszValue, "Edge") == TRUE)
    1254              30 :                                     gmlHugeFileCheckXrefs( helper, psEdge );
    1255             444 :                                 psEdge = psEdge->psNext;
    1256                 :                             }
    1257             314 :                             psDirEdge = psDirEdge->psNext;
    1258                 :                         }
    1259                 :                     }
    1260                 :                 }
    1261                 :             }
    1262                 :         }
    1263            1124 :         psChild = psChild->psNext;
    1264                 :     }
    1265                 : 
    1266                 :     /* recursively scanning each GML of the same level */
    1267             502 :     const CPLXMLNode *psNext = psNode->psNext;
    1268            1036 :     while( psNext != NULL )
    1269                 :     {
    1270              32 :         if( psNext->eType == CXT_Element )
    1271                 :         {
    1272              32 :             if( EQUAL(psNext->pszValue, "Edge") == TRUE ||
    1273                 :                 EQUAL(psNext->pszValue, "directedEdge") == TRUE )
    1274                 :             {
    1275              32 :                 gmlHugeFileCheckXrefs( helper, psNext );
    1276                 :             }
    1277                 :         }
    1278              32 :         psNext = psNext->psNext;
    1279                 :     }
    1280             502 : }
    1281                 : 
    1282               4 : static void gmlHugeFileCleanUp ( struct huge_helper *helper ) 
    1283                 : {
    1284                 : /* cleaning up any SQLite handle */
    1285               4 :     if( helper->hNodes != NULL )
    1286               0 :         sqlite3_finalize ( helper->hNodes );
    1287               4 :     if( helper->hEdges != NULL )
    1288               0 :         sqlite3_finalize ( helper->hEdges );
    1289               4 :     if( helper->hDB != NULL )
    1290               4 :         sqlite3_close( helper->hDB );
    1291               4 :     if( helper->nodeSrs != NULL )
    1292               0 :         delete helper->nodeSrs;
    1293               4 : }
    1294                 : 
    1295             656 : static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
    1296                 :                                           const CPLXMLNode *psParent,
    1297                 :                                           const CPLXMLNode *psNode )
    1298                 : {
    1299                 : /* identifying any xlink:href to be replaced */
    1300             656 :     if( psNode->eType == CXT_Element )
    1301                 :     {
    1302             656 :         if( EQUAL(psNode->pszValue, "directedEdge") == TRUE )
    1303                 :         {
    1304             408 :             char cOrientation = '+';
    1305             408 :             CPLXMLNode *psAttr = psNode->psChild;
    1306            1360 :             while( psAttr != NULL )
    1307                 :             {
    1308             544 :                 if( psAttr->eType == CXT_Attribute &&
    1309                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
    1310                 :                 {
    1311             136 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
    1312             136 :                     if( psOrientation != NULL )
    1313                 :                     {
    1314             136 :                         if( psOrientation->eType == CXT_Text )
    1315             136 :                             cOrientation = *(psOrientation->pszValue);
    1316                 :                     }
    1317                 :                 }
    1318             544 :                 psAttr = psAttr->psNext;
    1319                 :             }
    1320             408 :             psAttr = psNode->psChild;
    1321            1360 :             while( psAttr != NULL )
    1322                 :             {
    1323             544 :                 if( psAttr->eType == CXT_Attribute &&
    1324                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
    1325                 :                 {
    1326             246 :                     const CPLXMLNode *pszHref = psAttr->psChild;
    1327             246 :                     if( pszHref != NULL )
    1328                 :                     {
    1329             246 :                         if( pszHref->eType == CXT_Text )
    1330                 :                         {
    1331             246 :                             if (pszHref->pszValue[0] != '#')
    1332                 :                             {
    1333                 :                                 CPLError(CE_Warning, CPLE_NotSupported,
    1334                 :                                         "Only values of xlink:href element starting with '#' are supported, "
    1335               0 :                                         "so %s will not be properly recognized", pszHref->pszValue);
    1336                 :                             }
    1337             246 :                             CPLString *gmlId = new CPLString(pszHref->pszValue+1);
    1338                 :                             gmlHugeAddPendingToHelper( helper, gmlId, psParent,
    1339             246 :                                                        psNode, TRUE, cOrientation );
    1340                 :                         }
    1341                 :                     }
    1342                 :                 }
    1343             544 :                 psAttr = psAttr->psNext;
    1344                 :             }
    1345                 :         }
    1346                 :     }
    1347                 : 
    1348                 :     /* recursively scanning each Child GML node */
    1349             656 :     const CPLXMLNode *psChild = psNode->psChild;
    1350            2424 :     while( psChild != NULL )
    1351                 :     {
    1352            1112 :         if( psChild->eType == CXT_Element )
    1353                 :         {
    1354             674 :             if( EQUAL(psChild->pszValue, "directedEdge") == TRUE ||
    1355                 :                 EQUAL(psChild->pszValue, "directedFace") == TRUE ||
    1356                 :                 EQUAL(psChild->pszValue, "Face") == TRUE)
    1357                 :             {
    1358             512 :                 gmlHugeFileCheckPendingHrefs( helper, psNode, psChild );
    1359                 :             }
    1360                 :         }
    1361            1112 :         psChild = psChild->psNext;
    1362                 :     }
    1363                 : 
    1364                 :     /* recursively scanning each GML of the same level */
    1365             656 :     const CPLXMLNode *psNext = psNode->psNext;
    1366            2208 :     while( psNext != NULL )
    1367                 :     {
    1368             896 :         if( psNext->eType == CXT_Element )
    1369                 :         {
    1370             896 :             if( EQUAL(psNext->pszValue, "Face") == TRUE )
    1371                 :             {
    1372               0 :                 gmlHugeFileCheckPendingHrefs( helper, psParent, psNext );
    1373                 :             }
    1374                 :         }
    1375             896 :         psNext = psNext->psNext;
    1376                 :     }
    1377             656 : }
    1378                 : 
    1379             246 : static void gmlHugeSetHrefGmlText( struct huge_helper *helper,
    1380                 :                                    const char *pszGmlId,
    1381                 :                                    const char *pszGmlText )
    1382                 : {
    1383                 : /* setting the GML text for the corresponding gml:id */
    1384             246 :     struct huge_href *pItem = helper->pFirstHref;
    1385            1640 :     while( pItem != NULL )
    1386                 :     {
    1387            1394 :         if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) == TRUE )
    1388                 :         {
    1389             246 :             if( pItem->gmlText != NULL)
    1390               0 :                 delete pItem->gmlText;
    1391             246 :             pItem->gmlText = new CPLString( pszGmlText );
    1392             246 :             return;
    1393                 :         }
    1394            1148 :         pItem = pItem->pNext;
    1395                 :     }
    1396                 : }
    1397                 : 
    1398             246 : static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
    1399                 :                                               CPLXMLNode *psParent )
    1400                 : {
    1401                 : /* inserting a GML Node (parent) to be rewritted */
    1402             246 :     struct huge_parent *pItem = helper->pFirstParent;
    1403                 : 
    1404                 :     /* checking if already exists */
    1405             636 :     while( pItem != NULL )
    1406                 :     {
    1407             338 :         if( pItem->psParent == psParent )
    1408             194 :             return pItem;
    1409             144 :         pItem = pItem->pNext;
    1410                 :     }
    1411                 : 
    1412                 :     /* creating a new Parent Node */
    1413              52 :     pItem = new struct huge_parent;
    1414              52 :     pItem->psParent = psParent;
    1415              52 :     pItem->pFirst = NULL;
    1416              52 :     pItem->pLast = NULL;
    1417              52 :     pItem->pNext = NULL;
    1418              52 :     if( helper->pFirstParent == NULL )
    1419              28 :         helper->pFirstParent = pItem;
    1420              52 :     if( helper->pLastParent != NULL )
    1421              24 :         helper->pLastParent->pNext = pItem;
    1422              52 :     helper->pLastParent = pItem;
    1423                 : 
    1424                 :     /* inserting any Child node into the Parent */
    1425              52 :     CPLXMLNode *psChild = psParent->psChild;
    1426             432 :     while( psChild != NULL )
    1427                 :     {
    1428                 :         struct huge_child *pChildItem;
    1429             328 :         pChildItem = new struct huge_child;
    1430             328 :         pChildItem->psChild = psChild;
    1431             328 :         pChildItem->pItem = NULL;
    1432             328 :         pChildItem->pNext = NULL;
    1433             328 :         if( pItem->pFirst == NULL )
    1434              52 :             pItem->pFirst = pChildItem;
    1435             328 :         if( pItem->pLast != NULL )
    1436             276 :             pItem->pLast->pNext = pChildItem;
    1437             328 :         pItem->pLast = pChildItem;
    1438             328 :         psChild = psChild->psNext;
    1439                 :     }
    1440              52 :     return pItem;
    1441                 : }
    1442                 : 
    1443             246 : static int gmlHugeSetChild( struct huge_parent *pParent,
    1444                 :                             struct huge_href *pItem )
    1445                 : {
    1446                 : /* setting a Child Node to be rewritted */
    1447             246 :     struct huge_child *pChild = pParent->pFirst;
    1448            1424 :     while( pChild != NULL )
    1449                 :     {
    1450            1178 :          if( pChild->psChild == pItem->psNode )
    1451                 :          {
    1452             246 :             pChild->pItem = pItem;
    1453             246 :             return TRUE;
    1454                 :          }
    1455             932 :          pChild = pChild->pNext;
    1456                 :     }
    1457               0 :     return FALSE;
    1458                 : }
    1459                 : 
    1460              28 : static int gmlHugeResolveEdges( struct huge_helper *helper,
    1461                 :                                 CPLXMLNode *psNode, sqlite3 *hDB )
    1462                 : {
    1463                 : /* resolving GML <Edge> xlink:href */
    1464              28 :     CPLString      osCommand;
    1465                 :     sqlite3_stmt   *hStmtEdges;
    1466                 :     int            rc;
    1467              28 :     int            bIsComma = FALSE;
    1468              28 :     int            bError = FALSE;
    1469                 :     struct huge_href *pItem;
    1470                 :     struct huge_parent *pParent;
    1471                 : 
    1472                 :     /* query cursor [Edges] */
    1473                 :     osCommand = "SELECT gml_id, gml_resolved "
    1474                 :                 "FROM gml_edges "
    1475              28 :                 "WHERE gml_id IN (";
    1476              28 :     pItem = helper->pFirstHref;
    1477             302 :     while( pItem != NULL )
    1478                 :     {
    1479             246 :         if( bIsComma == TRUE )
    1480             218 :             osCommand += ", ";
    1481                 :         else
    1482              28 :             bIsComma = TRUE;
    1483             246 :         osCommand += "'";
    1484             246 :         osCommand += pItem->gmlId->c_str();
    1485             246 :         osCommand += "'";
    1486             246 :         pItem = pItem->pNext;
    1487                 :     }
    1488              28 :     osCommand += ")";
    1489              28 :     rc = sqlite3_prepare( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
    1490              28 :     if( rc != SQLITE_OK )
    1491                 :     {
    1492                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1493               0 :                   "Unable to create QUERY stmt for EDGES" );
    1494               0 :         return FALSE;
    1495                 :     }
    1496             246 :     while ( TRUE )
    1497                 :     {
    1498             274 :         rc = sqlite3_step( hStmtEdges );
    1499             274 :         if( rc == SQLITE_DONE )
    1500              28 :             break;
    1501             246 :         if ( rc == SQLITE_ROW )
    1502                 :         {
    1503                 :             const char *pszGmlId;
    1504             246 :             const char *pszGmlText = NULL;
    1505             246 :             pszGmlId = (const char *)sqlite3_column_text ( hStmtEdges, 0 );
    1506             246 :             if( sqlite3_column_type( hStmtEdges, 1 ) != SQLITE_NULL )
    1507             246 :                 pszGmlText = (const char *)sqlite3_column_text ( hStmtEdges, 1 );
    1508             246 :             gmlHugeSetHrefGmlText( helper, pszGmlId, pszGmlText );
    1509                 :         }
    1510                 :         else
    1511                 :         {
    1512                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1513                 :                       "Edge xlink:href QUERY: sqlite3_step(%s)", 
    1514               0 :                       sqlite3_errmsg(hDB) );
    1515               0 :             bError = TRUE;
    1516               0 :             break;
    1517                 :         }
    1518                 :     }
    1519              28 :     sqlite3_finalize ( hStmtEdges );
    1520              28 :     if( bError == TRUE )
    1521               0 :         return FALSE;
    1522                 : 
    1523                 :     /* indentifying any GML node to be rewritten */
    1524              28 :     pItem = helper->pFirstHref;
    1525             302 :     while( pItem != NULL )
    1526                 :     {
    1527             246 :         if( pItem->gmlText == NULL || pItem->psParent == NULL ||
    1528                 :             pItem->psNode == NULL )
    1529                 :         {
    1530               0 :             bError = TRUE;
    1531               0 :             break;
    1532                 :         }
    1533             246 :         pParent = gmlHugeFindParent( helper, (CPLXMLNode *)pItem->psParent );
    1534             246 :         if( gmlHugeSetChild( pParent, pItem ) == FALSE )
    1535                 :         {
    1536               0 :             bError = TRUE;
    1537               0 :             break;
    1538                 :         }
    1539             246 :         pItem = pItem->pNext;
    1540                 :     }
    1541                 : 
    1542              28 :     if( bError == FALSE )
    1543                 :     {
    1544                 :     /* rewriting GML nodes */
    1545              28 :         pParent = helper->pFirstParent;
    1546             108 :         while( pParent != NULL )
    1547                 :         {
    1548                 :             struct huge_child *pChild;
    1549                 : 
    1550                 :             /* removing any Child node from the Parent */
    1551              52 :             pChild = pParent->pFirst;
    1552             432 :             while( pChild != NULL )
    1553                 :             {
    1554             328 :                 CPLRemoveXMLChild( pParent->psParent, pChild->psChild );
    1555                 : 
    1556                 :                 /* destroyng any Child Node to be rewritten */
    1557             328 :                 if( pChild->pItem != NULL )
    1558             246 :                     CPLDestroyXMLNode( pChild->psChild );
    1559             328 :                 pChild = pChild->pNext;
    1560                 :             }
    1561                 : 
    1562                 :             /* rewriting the Parent Node */
    1563              52 :             pChild = pParent->pFirst;
    1564             432 :             while( pChild != NULL )
    1565                 :             {
    1566             328 :                 if( pChild->pItem == NULL )
    1567                 :                 {
    1568                 :                     /* reinserting any untouched Child Node */
    1569              82 :                     CPLAddXMLChild( pParent->psParent, pChild->psChild );
    1570                 :                 }
    1571                 :                 else
    1572                 :                 {
    1573                 :                     /* rewriting a Child Node */
    1574             246 :                     CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "directedEdge");
    1575             246 :                     if( pChild->pItem->cOrientation == '-' )
    1576                 :                     {
    1577             134 :                         CPLXMLNode *psOrientationNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "orientation");
    1578             134 :                         CPLCreateXMLNode(psOrientationNode, CXT_Text, "-");
    1579                 :                     }
    1580             246 :                     CPLXMLNode *psEdge = CPLParseXMLString(pChild->pItem->gmlText->c_str());
    1581             246 :                     CPLAddXMLChild( psNewNode, psEdge );
    1582             246 :                     CPLAddXMLChild( pParent->psParent, psNewNode );
    1583                 :                 }
    1584             328 :                 pChild = pChild->pNext;
    1585                 :             }
    1586              52 :             pParent = pParent->pNext;
    1587                 :         }
    1588                 :     }
    1589                 : 
    1590                 :     /* resetting the Rewrite Helper to an empty state */
    1591              28 :     gmlHugeFileRewiterReset( helper );
    1592              28 :     if( bError == TRUE )
    1593               0 :         return FALSE;
    1594              28 :     return TRUE;
    1595                 : }
    1596                 : 
    1597               4 : static int gmlHugeFileWriteResolved ( struct huge_helper *helper, 
    1598                 :                                       const char *pszOutputFilename, 
    1599                 :                                       GMLReader *pReader,
    1600                 :                                       int *m_bSequentialLayers ) 
    1601                 : {
    1602                 : /* writing the resolved GML file */
    1603                 :     VSILFILE       *fp;
    1604                 :     GMLFeature     *poFeature;
    1605                 :     const char     *osCommand;
    1606                 :     int            rc;
    1607               4 :     sqlite3        *hDB = helper->hDB;
    1608                 :     sqlite3_stmt   *hStmtNodes;
    1609               4 :     int            bError = FALSE;
    1610               4 :     int            iOutCount = 0;
    1611                 : 
    1612                 : /* -------------------------------------------------------------------- */
    1613                 : /*      Opening the resolved GML file                                   */
    1614                 : /* -------------------------------------------------------------------- */
    1615               4 :     fp = VSIFOpenL( pszOutputFilename, "w" );
    1616               4 :     if( fp == NULL )
    1617                 :     {
    1618                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1619               0 :                   "Failed to open %.500s to write.", pszOutputFilename );
    1620               0 :         return FALSE;
    1621                 :     }
    1622                 : 
    1623                 :     /* query cursor [Nodes] */
    1624                 :     osCommand = "SELECT gml_id, x, y, z "
    1625               4 :                 "FROM nodes";
    1626               4 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmtNodes, NULL );
    1627               4 :     if( rc != SQLITE_OK )
    1628                 :     {
    1629                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1630               0 :                   "Unable to create QUERY stmt for NODES" );
    1631               0 :         VSIFCloseL( fp );
    1632               0 :         return FALSE;
    1633                 :     }
    1634                 : 
    1635               4 :     VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); 
    1636                 :     VSIFPrintfL ( fp, "<ResolvedTopoFeatureCollection  "
    1637               4 :                       "xmlns:gml=\"http://www.opengis.net/gml\">\n" );   
    1638               4 :     VSIFPrintfL ( fp, "  <ResolvedTopoFeatureMembers>\n" );
    1639                 :     /* exporting Nodes */
    1640               4 :     GFSTemplateList *pCC = new GFSTemplateList();
    1641             132 :     while ( TRUE )
    1642                 :     {
    1643             136 :         rc = sqlite3_step( hStmtNodes );
    1644             136 :         if( rc == SQLITE_DONE )
    1645                 :             break;
    1646             132 :         if ( rc == SQLITE_ROW )
    1647                 :         {
    1648                 :             const char *pszGmlId;
    1649                 :             char* pszEscaped;
    1650                 :             double x;
    1651                 :             double y;
    1652             132 :             double z = 0.0;
    1653             132 :             int bHasZ = FALSE;
    1654             132 :             pszGmlId = (const char *)sqlite3_column_text ( hStmtNodes, 0 );
    1655             132 :             x = sqlite3_column_double ( hStmtNodes, 1 );
    1656             132 :             y = sqlite3_column_double ( hStmtNodes, 2 );
    1657             132 :             if ( sqlite3_column_type( hStmtNodes, 3 ) == SQLITE_FLOAT )
    1658                 :             {
    1659               0 :                 z = sqlite3_column_double ( hStmtNodes, 3 );
    1660               0 :                 bHasZ = TRUE;
    1661                 :             }
    1662                 : 
    1663                 :             /* inserting a node into the resolved GML file */
    1664             132 :             pCC->Update( "ResolvedNodes", TRUE );
    1665             132 :             VSIFPrintfL ( fp, "    <ResolvedNodes>\n" );
    1666             132 :             pszEscaped = CPLEscapeString( pszGmlId, -1, CPLES_XML );
    1667             132 :             VSIFPrintfL ( fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped );
    1668             132 :             CPLFree(pszEscaped);
    1669             132 :             VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1670             132 :             if ( helper->nodeSrs == NULL )
    1671                 :                 VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\">",
    1672             132 :                               ( bHasZ == TRUE ) ? 3 : 2 );
    1673                 :             else
    1674                 :             {
    1675               0 :                 pszEscaped = CPLEscapeString( helper->nodeSrs->c_str(), -1, CPLES_XML );
    1676                 :                 VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\""
    1677                 :                                   " srsName=\"%s\">",
    1678                 :                                   ( bHasZ == TRUE ) ? 3 : 2,
    1679               0 :                               pszEscaped );
    1680               0 :                 CPLFree(pszEscaped);
    1681                 :             }
    1682             132 :             if ( bHasZ == TRUE )
    1683                 :                 VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f %1.8f</gml:pos>"
    1684                 :                                   "</gml:Point>\n",
    1685               0 :                               x, y, z );
    1686                 :             else
    1687                 :                 VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f</gml:pos>"
    1688                 :                                   "</gml:Point>\n",
    1689             132 :                               x, y );
    1690             132 :             VSIFPrintfL ( fp, "      </ResolvedGeometry> \n" );
    1691             132 :             VSIFPrintfL ( fp, "    </ResolvedNodes>\n" );
    1692             132 :             iOutCount++;
    1693                 :         }
    1694                 :         else
    1695                 :         {
    1696                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1697                 :                       "ResolvedNodes QUERY: sqlite3_step(%s)", 
    1698               0 :             sqlite3_errmsg(hDB) );
    1699               0 :             sqlite3_finalize ( hStmtNodes );
    1700               0 :             return FALSE;
    1701                 :         }
    1702                 :     }
    1703               4 :     sqlite3_finalize ( hStmtNodes );
    1704                 : 
    1705                 :     /* processing GML features */
    1706             152 :     while( (poFeature = pReader->NextFeature()) != NULL )
    1707                 :     {
    1708             144 :         GMLFeatureClass *poClass = poFeature->GetClass();
    1709             144 :         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
    1710             144 :         int iPropCount = poClass->GetPropertyCount();
    1711                 :     
    1712             144 :         int b_has_geom = FALSE;
    1713             144 :         VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() ); 
    1714                 : 
    1715             504 :         for( int iProp = 0; iProp < iPropCount; iProp++ )
    1716                 :         {
    1717             360 :             GMLPropertyDefn *poPropDefn = poClass->GetProperty( iProp );
    1718             360 :             const char *pszPropName = poPropDefn->GetName();
    1719             360 :             const GMLProperty *poProp = poFeature->GetProperty( iProp );
    1720                 : 
    1721             360 :             if( poProp != NULL )
    1722                 :             {
    1723             720 :                 for( int iSub = 0; iSub < poProp->nSubProperties; iSub++ )
    1724                 :                 {
    1725             360 :                     char *gmlText = CPLEscapeString( poProp->papszSubProperties[iSub],
    1726                 :                                                     -1,
    1727             720 :                                                     CPLES_XML );
    1728                 :                     VSIFPrintfL ( fp, "      <%s>%s</%s>\n", 
    1729             360 :                                   pszPropName, gmlText, pszPropName ); 
    1730             360 :                     CPLFree( gmlText );
    1731                 :                 }
    1732                 :             }
    1733                 :         }
    1734                 : 
    1735             144 :         if( papsGeomList != NULL )
    1736                 :         {
    1737             144 :             int i = 0;
    1738             144 :             const CPLXMLNode *psNode = papsGeomList[i];
    1739             432 :             while( psNode != NULL )
    1740                 :             {
    1741             144 :                 char *pszResolved = NULL;
    1742                 :                 int bNotToBeResolved;
    1743             144 :                 if( psNode->eType != CXT_Element )
    1744               0 :                     bNotToBeResolved = TRUE;
    1745                 :                 else
    1746                 :                 {
    1747             288 :                     if( EQUAL(psNode->pszValue, "TopoCurve") == TRUE ||
    1748                 :                         EQUAL(psNode->pszValue, "TopoSurface") == TRUE )
    1749             144 :                         bNotToBeResolved = FALSE;
    1750                 :                     else
    1751               0 :                         bNotToBeResolved = TRUE;
    1752                 :                 }
    1753             144 :                 if( bNotToBeResolved == TRUE )
    1754                 :                 {
    1755               0 :                     VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1756               0 :                     pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1757               0 :                     VSIFPrintfL ( fp, "        %s\n", pszResolved );
    1758               0 :                     CPLFree( pszResolved );
    1759               0 :                     VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
    1760               0 :                     b_has_geom = TRUE;
    1761                 :                 }
    1762                 :                 else
    1763                 :                 {
    1764             144 :                     gmlHugeFileCheckPendingHrefs( helper, psNode, psNode );
    1765             144 :                     if( helper->pFirstHref == NULL )
    1766                 :                     {
    1767             116 :                         VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1768             116 :                         pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1769             116 :                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
    1770             116 :                         CPLFree( pszResolved );
    1771             116 :                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
    1772             116 :                         b_has_geom = TRUE;
    1773                 :                     }
    1774                 :                     else
    1775                 :                     {
    1776              28 :                         if( gmlHugeResolveEdges( helper, (CPLXMLNode *)psNode,
    1777                 :                                                          hDB ) == FALSE)
    1778               0 :                             bError = TRUE;
    1779              28 :                         if( gmlHugeFileHrefCheck( helper ) == FALSE )
    1780               0 :               bError = TRUE;
    1781              28 :                         VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1782              28 :                         pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1783              28 :                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
    1784              28 :                         CPLFree( pszResolved );
    1785              28 :                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
    1786              28 :                         b_has_geom = TRUE;
    1787              28 :                         gmlHugeFileHrefReset( helper );
    1788                 :                     }
    1789                 :                 }
    1790             144 :                 i++;
    1791             144 :                 psNode = papsGeomList[i];
    1792                 :             }
    1793                 :         }
    1794             144 :         pCC->Update( poClass->GetElementName(), b_has_geom );
    1795                 : 
    1796             144 :         VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() ); 
    1797                 : 
    1798             144 :         delete poFeature;
    1799             144 :         iOutCount++;
    1800                 :     }
    1801                 : 
    1802               4 :     VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" ); 
    1803               4 :     VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" ); 
    1804                 : 
    1805               4 :     VSIFCloseL( fp );
    1806                 :     
    1807               4 :     gmlUpdateFeatureClasses( pCC, pReader, m_bSequentialLayers );
    1808               4 :     if ( *m_bSequentialLayers == TRUE )
    1809               4 :         pReader->ReArrangeTemplateClasses( pCC );
    1810               4 :     delete pCC;
    1811               4 :     if( bError == TRUE || iOutCount == 0 )
    1812               0 :         return FALSE;
    1813               4 :     return TRUE;
    1814                 : }
    1815                 : 
    1816                 : /**************************************************************/
    1817                 : /*                                                            */
    1818                 : /* private member(s):                                         */
    1819                 : /* any other funtion is implemented as "internal" static,     */
    1820                 : /* so to make all the SQLite own stuff nicely "invisible"     */
    1821                 : /*                                                            */
    1822                 : /**************************************************************/
    1823                 : 
    1824               4 : int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
    1825                 :                                  const int bSqliteIsTempFile,
    1826                 :                                  const int iSqliteCacheMB )
    1827                 : 
    1828                 : {
    1829                 :     GMLFeature  *poFeature;
    1830               4 :     int iFeatureUID = 0;
    1831                 :     int rc;
    1832               4 :     sqlite3 *hDB = NULL;
    1833               4 :     CPLString osSQLiteFilename;
    1834               4 :     const char *pszSQLiteFilename = NULL;
    1835                 :     struct huge_helper helper;
    1836               4 :     char *pszErrMsg = NULL;
    1837                 : 
    1838                 :     /* initializing the helper struct */
    1839               4 :     helper.hDB = NULL;
    1840               4 :     helper.hNodes = NULL;
    1841               4 :     helper.hEdges = NULL;
    1842               4 :     helper.nodeSrs = NULL;
    1843               4 :     helper.pFirst = NULL;
    1844               4 :     helper.pLast = NULL;
    1845               4 :     helper.pFirstHref = NULL;
    1846               4 :     helper.pLastHref = NULL;
    1847               4 :     helper.pFirstParent = NULL;
    1848               4 :     helper.pLastParent = NULL;
    1849                 :   
    1850                 : /* -------------------------------------------------------------------- */
    1851                 : /*      Creating/Opening the SQLite DB file                             */
    1852                 : /* -------------------------------------------------------------------- */
    1853               4 :     osSQLiteFilename = CPLResetExtension( m_pszFilename, "sqlite" );
    1854               4 :     pszSQLiteFilename = osSQLiteFilename.c_str();
    1855                 : 
    1856                 :     VSIStatBufL statBufL;
    1857               4 :     if ( VSIStatExL ( pszSQLiteFilename, &statBufL, VSI_STAT_EXISTS_FLAG) == 0)
    1858                 :     {
    1859                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1860                 :                   "sqlite3_open(%s) failed:\n\tDB-file already exists", 
    1861               0 :                   pszSQLiteFilename );
    1862               0 :         return FALSE;
    1863                 :     }
    1864                 : 
    1865               4 :     rc = sqlite3_open( pszSQLiteFilename, &hDB );
    1866               4 :     if( rc != SQLITE_OK )
    1867                 :     {
    1868                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1869                 :                   "sqlite3_open(%s) failed: %s", 
    1870               0 :                   pszSQLiteFilename, sqlite3_errmsg( hDB ) );
    1871               0 :         return FALSE;
    1872                 :     }
    1873               4 :     helper.hDB = hDB;
    1874                 :   
    1875                 : /* 
    1876                 : * setting SQLite for max speed; this is intrinsically unsafe,
    1877                 : * and the DB file could be potentially damaged (power failure ...]
    1878                 : *
    1879                 : * but after all this one simply is a TEMPORARY FILE !!
    1880                 : * so there is no real risk condition
    1881                 : */
    1882                 :     rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL,
    1883               4 :                        &pszErrMsg );
    1884               4 :     if( rc != SQLITE_OK )
    1885                 :     {
    1886                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1887                 :                   "Unable to set PRAGMA synchronous = OFF: %s",
    1888               0 :                   pszErrMsg );
    1889               0 :         sqlite3_free( pszErrMsg );
    1890                 :     }
    1891                 :     rc = sqlite3_exec( hDB, "PRAGMA journal_mode = OFF", NULL, NULL,
    1892               4 :                        &pszErrMsg );
    1893               4 :     if( rc != SQLITE_OK )
    1894                 :     {
    1895                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1896                 :                   "Unable to set PRAGMA journal_mode = OFF: %s",
    1897               0 :                   pszErrMsg );
    1898               0 :         sqlite3_free( pszErrMsg );
    1899                 :     }
    1900                 :     rc = sqlite3_exec( hDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL,
    1901               4 :                        &pszErrMsg );
    1902               4 :     if( rc != SQLITE_OK )
    1903                 :     {
    1904                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1905                 :                   "Unable to set PRAGMA locking_mode = EXCLUSIVE: %s",
    1906               0 :                   pszErrMsg );
    1907               0 :         sqlite3_free( pszErrMsg );
    1908                 :     }
    1909                 :     
    1910                 :     /* setting the SQLite cache */
    1911               4 :     if( iSqliteCacheMB > 0 )
    1912                 :     {
    1913               0 :         int cache_size = iSqliteCacheMB * 1024;
    1914                 : 
    1915                 :         /* refusing to allocate more than 1GB */
    1916               0 :         if( cache_size > 1024 * 1024 )
    1917               0 :             cache_size = 1024 * 1024;
    1918                 :         char sqlPragma[1024];
    1919               0 :         sprintf( sqlPragma, "PRAGMA cache_size = %d", cache_size );
    1920               0 :         rc = sqlite3_exec( hDB, sqlPragma, NULL, NULL, &pszErrMsg );
    1921               0 :         if( rc != SQLITE_OK )
    1922                 :         {
    1923                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1924               0 :                       "Unable to set %s: %s", sqlPragma, pszErrMsg );
    1925               0 :             sqlite3_free( pszErrMsg );
    1926                 :         }
    1927                 :     }
    1928                 :   
    1929               4 :     if( !SetupParser() )
    1930                 :     {
    1931               0 :         gmlHugeFileCleanUp ( &helper );
    1932               0 :         return FALSE;
    1933                 :     }
    1934                 : 
    1935                 :     /* creating SQLite tables and Insert cursors */
    1936               4 :     if( gmlHugeFileSQLiteInit( &helper ) == FALSE )
    1937                 :     {
    1938               0 :         gmlHugeFileCleanUp ( &helper );
    1939               0 :         return FALSE;
    1940                 :     }
    1941                 : 
    1942                 :     /* processing GML features */
    1943             152 :     while( (poFeature = NextFeature()) != NULL )
    1944                 :     {
    1945             144 :         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
    1946             144 :         if (papsGeomList != NULL)
    1947                 :         {
    1948             144 :             int i = 0;
    1949             144 :             const CPLXMLNode *psNode = papsGeomList[i];
    1950             432 :             while(psNode)
    1951                 :             {
    1952             144 :                 gmlHugeFileCheckXrefs( &helper, psNode );
    1953                 :                 /* inserting into the SQLite DB any appropriate row */
    1954             144 :                 gmlHugeFileSQLiteInsert ( &helper );
    1955                 :                 /* resetting an empty helper struct */
    1956             144 :                 gmlHugeFileReset ( &helper );
    1957             144 :                 i ++;
    1958             144 :                 psNode = papsGeomList[i];
    1959                 :             }
    1960                 :         }
    1961             144 :         iFeatureUID++;
    1962             144 :         delete poFeature;
    1963                 :     }
    1964                 : 
    1965                 :     /* finalizing any SQLite Insert cursor */
    1966               4 :     if( helper.hNodes != NULL )
    1967               4 :         sqlite3_finalize ( helper.hNodes );
    1968               4 :     helper.hNodes = NULL;
    1969               4 :     if( helper.hEdges != NULL )
    1970               4 :         sqlite3_finalize ( helper.hEdges );
    1971               4 :     helper.hEdges = NULL;
    1972                 : 
    1973                 :     /* confirming the still pending TRANSACTION */
    1974               4 :     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
    1975               4 :     if( rc != SQLITE_OK )
    1976                 :     {
    1977                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1978                 :                   "Unable to perform COMMIT TRANSACTION: %s",
    1979               0 :                   pszErrMsg );
    1980               0 :         sqlite3_free( pszErrMsg );
    1981               0 :         return FALSE;
    1982                 :     }
    1983                 : 
    1984                 : /* attempting to resolve GML strings */
    1985               4 :     if( gmlHugeFileResolveEdges( &helper ) == FALSE )
    1986                 :     {
    1987               0 :         gmlHugeFileCleanUp ( &helper );
    1988               0 :         return FALSE;
    1989                 :     }
    1990                 :   
    1991                 :     /* restarting the GML parser */
    1992               4 :     if( !SetupParser() )
    1993                 :     {
    1994               0 :         gmlHugeFileCleanUp ( &helper );
    1995               0 :         return FALSE;
    1996                 :     }
    1997                 : 
    1998                 :     /* output: writing the revolved GML file */
    1999               4 :     if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this, 
    2000                 :                                    &m_bSequentialLayers ) == FALSE)
    2001                 :     {
    2002               0 :         gmlHugeFileCleanUp ( &helper );
    2003               0 :         return FALSE;
    2004                 :     }
    2005                 : 
    2006               4 :     gmlHugeFileCleanUp ( &helper );
    2007               4 :     if ( bSqliteIsTempFile == TRUE )
    2008               4 :         VSIUnlink( pszSQLiteFilename );
    2009               4 :     return TRUE;
    2010                 : }
    2011                 : 
    2012                 : /**************************************************************/
    2013                 : /*                                                            */
    2014                 : /* an alternative <xlink:href> resolver based on SQLite       */
    2015                 : /*                                                            */
    2016                 : /**************************************************************/
    2017               4 : int GMLReader::HugeFileResolver( const char *pszFile,
    2018                 :                                  int bSqliteIsTempFile,
    2019                 :                                  int iSqliteCacheMB )
    2020                 : 
    2021                 : {
    2022                 :     // Check if the original source file is set.
    2023               4 :     if( m_pszFilename == NULL )
    2024                 :     {
    2025                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2026                 :         "GML source file needs to be set first with "
    2027               0 :         "GMLReader::SetSourceFile()." );
    2028               0 :         return FALSE;
    2029                 :     }
    2030               4 :     if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == FALSE )
    2031               0 :         return FALSE;
    2032                 : 
    2033                 :     //set the source file to the resolved file
    2034               4 :     CleanupParser();
    2035               4 :     if (fpGML)
    2036               4 :         VSIFCloseL(fpGML);
    2037               4 :     fpGML = NULL;
    2038               4 :     CPLFree( m_pszFilename );
    2039               4 :     m_pszFilename = CPLStrdup( pszFile );
    2040               4 :     return TRUE;
    2041                 : }
    2042                 : 
    2043                 : #else  // HAVE_SQLITE
    2044                 : 
    2045                 : /**************************************************/
    2046                 : /*    if SQLite support isn't available we'll     */
    2047                 : /*    simply output an error message              */
    2048                 : /**************************************************/
    2049                 : 
    2050                 : int GMLReader::HugeFileResolver( const char *pszFile,
    2051                 :                                  int bSqliteIsTempFile,
    2052                 :                                  int iSqliteCacheMB )
    2053                 : 
    2054                 : {
    2055                 :     CPLError( CE_Failure, CPLE_NotSupported,
    2056                 :               "OGR was built without SQLite3 support\n"
    2057                 :               "... sorry, the HUGE GML resolver is unsupported\n" );
    2058                 :     return FALSE;
    2059                 : }
    2060                 : 
    2061                 : int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
    2062                 :                                  const int bSqliteIsTempFile,
    2063                 :                                  const int iSqliteCacheMB )
    2064                 : {
    2065                 :     CPLError( CE_Failure, CPLE_NotSupported,
    2066                 :               "OGR was built without SQLite3 support\n"
    2067                 :               "... sorry, the HUGE GML resolver is unsupported\n" );
    2068                 :     return FALSE;
    2069                 : }
    2070                 : 
    2071                 : #endif // HAVE_SQLITE

Generated by: LCOV version 1.7