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-12-26 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               2 : static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     132                 : {
     133                 : /* attempting to create SQLite tables */
     134                 :     const char          *osCommand;
     135               2 :     char                *pszErrMsg = NULL;
     136                 :     int                 rc;
     137               2 :     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               2 :                 "     z DOUBLE)";
     146               2 :     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     147               2 :     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               2 :                 "     node_to_z DOUBLE)";
     169               2 :     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     170               2 :     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               2 :                 "VALUES (?, ?, ?, ?)";
     182               2 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
     183               2 :     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               2 :     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               2 :                 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
     198               2 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
     199               2 :     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               2 :     helper->hEdges = hStmt;
     206                 : 
     207                 :     /* starting a TRANSACTION */
     208               2 :     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     209               2 :     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               2 :     return TRUE;
     219                 : }
     220                 : 
     221              70 : static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
     222                 :                                     const char *pszFromId,
     223                 :                                     const char *pszToId )
     224                 : {
     225                 : /* resolves an Edge definition */
     226              70 :     CPLXMLNode      *psDirNode_1 = NULL;
     227              70 :     CPLXMLNode      *psDirNode_2 = NULL;
     228              70 :     CPLXMLNode      *psOldNode_1 = NULL;
     229              70 :     CPLXMLNode      *psOldNode_2 = NULL;
     230              70 :     CPLXMLNode      *psNewNode_1 = NULL;
     231              70 :     CPLXMLNode      *psNewNode_2 = NULL;
     232              70 :     int             iToBeReplaced = 0;
     233              70 :     int             iReplaced = 0;
     234              70 :     if( psNode->eType == CXT_Element && EQUAL( psNode->pszValue, "Edge" ) )
     235                 :         ;
     236                 :     else
     237               0 :         return FALSE;
     238                 : 
     239              70 :     CPLXMLNode *psChild = psNode->psChild;
     240             420 :     while( psChild != NULL )
     241                 :     {
     242             280 :         if( psChild->eType == CXT_Element &&
     243                 :             EQUAL( psChild->pszValue, "directedNode" ) )
     244                 :         {
     245             140 :             char cOrientation = '+';
     246             140 :             CPLXMLNode *psOldNode = NULL;
     247             140 :             CPLXMLNode *psAttr = psChild->psChild;
     248             490 :             while( psAttr != NULL )
     249                 :             {
     250             210 :                 if( psAttr->eType == CXT_Attribute &&
     251                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
     252              96 :                     psOldNode = psAttr;
     253             210 :                 if( psAttr->eType == CXT_Attribute &&
     254                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
     255                 :                 {
     256              70 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
     257              70 :                     if( psOrientation != NULL )
     258                 :                     {
     259              70 :                         if( psOrientation->eType == CXT_Text )
     260              70 :                             cOrientation = *(psOrientation->pszValue);
     261                 :                     }
     262                 :                 }
     263             210 :                 psAttr = psAttr->psNext;
     264                 :             }
     265             140 :             if( psOldNode != NULL )
     266                 :             {
     267              96 :                 CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "Node");
     268              96 :                 CPLXMLNode *psGMLIdNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "gml:id");
     269              96 :                 if( cOrientation == '-' )
     270              49 :                     CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszFromId);
     271                 :                 else
     272              47 :                     CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszToId);
     273              96 :                 if( iToBeReplaced == 0 )
     274                 :                 {
     275              70 :                     psDirNode_1 = psChild;
     276              70 :                     psOldNode_1 = psOldNode;
     277              70 :                     psNewNode_1 = psNewNode;
     278                 :                 }
     279                 :                 else
     280                 :                 {
     281              26 :                     psDirNode_2 = psChild;
     282              26 :                     psOldNode_2 = psOldNode;
     283              26 :                     psNewNode_2 = psNewNode;
     284                 :                 }
     285              96 :                 iToBeReplaced++;
     286                 :             }
     287                 :         }
     288             280 :         psChild = psChild->psNext;
     289                 :     }
     290                 : 
     291                 :     /* rewriting the Edge GML definition */
     292              70 :     if( psDirNode_1 != NULL)
     293                 :     {
     294              70 :         if( psOldNode_1 != NULL )
     295                 :         {
     296              70 :             CPLRemoveXMLChild( psDirNode_1, psOldNode_1 );
     297              70 :             CPLDestroyXMLNode( psOldNode_1 );
     298              70 :             if( psNewNode_1 != NULL )
     299                 :             {
     300              70 :                 CPLAddXMLChild( psDirNode_1, psNewNode_1 );
     301              70 :                 iReplaced++;
     302                 :             }
     303                 :         }
     304                 :     }
     305              70 :     if( psDirNode_2 != NULL)
     306                 :     {
     307              26 :         if( psOldNode_2 != NULL )
     308                 :         {
     309              26 :             CPLRemoveXMLChild( psDirNode_2, psOldNode_2 );
     310              26 :             CPLDestroyXMLNode( psOldNode_2 );
     311              26 :             if( psNewNode_2 != NULL )
     312                 :             {
     313              26 :                 CPLAddXMLChild( psDirNode_2, psNewNode_2 );
     314              26 :                 iReplaced++;
     315                 :             }
     316                 :         }
     317                 :     }
     318              70 :     if( iToBeReplaced != iReplaced )
     319               0 :         return FALSE;
     320              70 : return TRUE;
     321                 : }
     322                 : 
     323               2 : static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     324                 : {
     325                 : /* identifying any not yet resolved <Edge> GML string */
     326                 :     const char          *osCommand;
     327               2 :     char                *pszErrMsg = NULL;
     328                 :     int rc;
     329               2 :     sqlite3             *hDB = helper->hDB;
     330                 :     sqlite3_stmt        *hQueryStmt;
     331                 :     sqlite3_stmt        *hUpdateStmt;
     332               2 :     int                 iCount = 0;
     333               2 :     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               2 :                 "LEFT JOIN nodes AS n2 ON (n2.gml_id = e.node_to_id)";
     344               2 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hQueryStmt, NULL );
     345               2 :     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               2 :                 "WHERE gml_id = ?";
     357               2 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
     358               2 :     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               2 :     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     368               2 :     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              81 :     while ( TRUE )
     381                 :     {
     382                 :         const char      *pszGmlId;
     383              83 :         const char      *pszGmlString = NULL;
     384                 :         int             bIsGmlStringNull;
     385              83 :         const char      *pszFromId = NULL;
     386                 :         int             bIsFromIdNull;
     387              83 :         double          xFrom = 0.0;
     388                 :         int             bIsXFromNull;
     389              83 :         double          yFrom = 0.0;
     390                 :         int             bIsYFromNull;
     391              83 :         double          zFrom = 0.0;
     392                 :         int             bIsZFromNull;
     393              83 :         const char      *pszNodeFromId = NULL;
     394                 :         int             bIsNodeFromIdNull;
     395              83 :         double          xNodeFrom = 0.0;
     396                 :         int             bIsXNodeFromNull;
     397              83 :         double          yNodeFrom = 0.0;
     398                 :         int             bIsYNodeFromNull;
     399              83 :         double          zNodeFrom = 0.0;
     400                 :         int             bIsZNodeFromNull;
     401              83 :         const char      *pszToId = NULL;
     402                 :         int             bIsToIdNull;
     403              83 :         double          xTo = 0.0;
     404                 :         int             bIsXToNull;
     405              83 :         double          yTo = 0.0;
     406                 :         int             bIsYToNull;
     407              83 :         double          zTo = 0.0;
     408                 :         int             bIsZToNull;
     409              83 :         const char      *pszNodeToId = NULL;
     410                 :         int             bIsNodeToIdNull;
     411              83 :         double          xNodeTo = 0.0;
     412                 :         int             bIsXNodeToNull;
     413              83 :         double          yNodeTo = 0.0;
     414                 :         int             bIsYNodeToNull;
     415              83 :         double          zNodeTo = 0.0;
     416                 :         int             bIsZNodeToNull;
     417                 : 
     418              83 :         rc = sqlite3_step( hQueryStmt );
     419              83 :         if( rc == SQLITE_DONE )
     420                 :             break;
     421              81 :         else if( rc == SQLITE_ROW )
     422                 :         {
     423              81 :             bError = FALSE;
     424              81 :             pszGmlId = (const char *) sqlite3_column_text( hQueryStmt, 0 );
     425              81 :             if( sqlite3_column_type( hQueryStmt, 1 ) == SQLITE_NULL )
     426              11 :                 bIsGmlStringNull = TRUE;
     427                 :             else
     428                 :             {
     429              70 :                 pszGmlString = (const char *) sqlite3_column_blob( hQueryStmt, 1 );
     430              70 :                 bIsGmlStringNull = FALSE;
     431                 :             }
     432              81 :             if( sqlite3_column_type( hQueryStmt, 2 ) == SQLITE_NULL )
     433               0 :                 bIsFromIdNull = TRUE;
     434                 :             else
     435                 :             {
     436              81 :                 pszFromId = (const char *) sqlite3_column_text( hQueryStmt, 2 );
     437              81 :                 bIsFromIdNull = FALSE;
     438                 :             }
     439              81 :             if( sqlite3_column_type( hQueryStmt, 3 ) == SQLITE_NULL )
     440               0 :                 bIsXFromNull = TRUE;
     441                 :             else
     442                 :             {
     443              81 :                 xFrom = sqlite3_column_double( hQueryStmt, 3 );
     444              81 :                 bIsXFromNull = FALSE;
     445                 :             }
     446              81 :             if( sqlite3_column_type( hQueryStmt, 4 ) == SQLITE_NULL )
     447               0 :                 bIsYFromNull = TRUE;
     448                 :             else
     449                 :             {
     450              81 :                 yFrom = sqlite3_column_double( hQueryStmt, 4 );
     451              81 :                 bIsYFromNull = FALSE;
     452                 :             }
     453              81 :             if( sqlite3_column_type( hQueryStmt, 5 ) == SQLITE_NULL )
     454              81 :                 bIsZFromNull = TRUE;
     455                 :             else
     456                 :             {
     457               0 :                 zFrom = sqlite3_column_double( hQueryStmt, 5 );
     458               0 :                 bIsZFromNull = FALSE;
     459                 :             }
     460              81 :             if( sqlite3_column_type( hQueryStmt, 6 ) == SQLITE_NULL )
     461               0 :                 bIsNodeFromIdNull = TRUE;
     462                 :             else
     463                 :             {
     464              81 :                 pszNodeFromId = (const char *) sqlite3_column_text( hQueryStmt, 6 );
     465              81 :                 bIsNodeFromIdNull = FALSE;
     466                 :             }
     467              81 :             if( sqlite3_column_type( hQueryStmt, 7 ) == SQLITE_NULL )
     468               0 :                 bIsXNodeFromNull = TRUE;
     469                 :             else
     470                 :             {
     471              81 :                 xNodeFrom = sqlite3_column_double( hQueryStmt, 7 );
     472              81 :                 bIsXNodeFromNull = FALSE;
     473                 :             }
     474              81 :             if( sqlite3_column_type( hQueryStmt, 8 ) == SQLITE_NULL )
     475               0 :                 bIsYNodeFromNull = TRUE;
     476                 :             else
     477                 :             {
     478              81 :                 yNodeFrom = sqlite3_column_double( hQueryStmt, 8 );
     479              81 :                 bIsYNodeFromNull = FALSE;
     480                 :             }
     481              81 :             if( sqlite3_column_type( hQueryStmt, 9 ) == SQLITE_NULL )
     482              81 :                 bIsZNodeFromNull = TRUE;
     483                 :             else
     484                 :             {
     485               0 :                 zNodeFrom = sqlite3_column_double( hQueryStmt, 9 );
     486               0 :                 bIsZNodeFromNull = FALSE;
     487                 :             }
     488              81 :             if( sqlite3_column_type( hQueryStmt, 10 ) == SQLITE_NULL )
     489               0 :                 bIsToIdNull = TRUE;
     490                 :             else
     491                 :             {
     492              81 :                 pszToId = (const char *) sqlite3_column_text( hQueryStmt, 10 );
     493              81 :                 bIsToIdNull = FALSE;
     494                 :             }
     495              81 :             if( sqlite3_column_type( hQueryStmt, 11 ) == SQLITE_NULL )
     496               0 :                 bIsXToNull = TRUE;
     497                 :             else
     498                 :             {
     499              81 :                 xTo = sqlite3_column_double( hQueryStmt, 11 );
     500              81 :                 bIsXToNull = FALSE;
     501                 :             }
     502              81 :             if( sqlite3_column_type( hQueryStmt, 12 ) == SQLITE_NULL )
     503               0 :                 bIsYToNull = TRUE;
     504                 :             else
     505                 :             {
     506              81 :                 yTo = sqlite3_column_double( hQueryStmt, 12 );
     507              81 :                 bIsYToNull = FALSE;
     508                 :             }
     509              81 :             if( sqlite3_column_type( hQueryStmt, 13 ) == SQLITE_NULL )
     510              81 :                 bIsZToNull = TRUE;
     511                 :             else
     512                 :             {
     513               0 :                 zTo = sqlite3_column_double( hQueryStmt, 13 );
     514               0 :                 bIsZToNull = FALSE;
     515                 :             }
     516              81 :             if( sqlite3_column_type( hQueryStmt, 14 ) == SQLITE_NULL )
     517               0 :                 bIsNodeToIdNull = TRUE;
     518                 :             else
     519                 :             {
     520              81 :                 pszNodeToId = (const char *) sqlite3_column_text( hQueryStmt, 14 );
     521              81 :                 bIsNodeToIdNull = FALSE;
     522                 :             }
     523              81 :             if( sqlite3_column_type( hQueryStmt, 15 ) == SQLITE_NULL )
     524               0 :                 bIsXNodeToNull = TRUE;
     525                 :             else
     526                 :             {
     527              81 :                 xNodeTo = sqlite3_column_double( hQueryStmt, 15 );
     528              81 :                 bIsXNodeToNull = FALSE;
     529                 :             }
     530              81 :             if( sqlite3_column_type( hQueryStmt, 16 ) == SQLITE_NULL )
     531               0 :                 bIsYNodeToNull = TRUE;
     532                 :             else
     533                 :             {
     534              81 :                 yNodeTo = sqlite3_column_double( hQueryStmt, 16 );
     535              81 :                 bIsYNodeToNull = FALSE;
     536                 :             }
     537              81 :             if( sqlite3_column_type( hQueryStmt, 17 ) == SQLITE_NULL )
     538              81 :                 bIsZNodeToNull = TRUE;
     539                 :             else
     540                 :             {
     541               0 :                 zNodeTo = sqlite3_column_double( hQueryStmt, 17 );
     542               0 :                 bIsZNodeToNull = FALSE;
     543                 :             }
     544                 : 
     545                 :             /* checking for consistency */
     546              81 :             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              81 :                 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              81 :                 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              81 :                 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              81 :                     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              81 :             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              81 :                 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              81 :                 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              81 :                 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              81 :                     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              81 :             if( bError == FALSE && bIsGmlStringNull == FALSE &&
     651                 :                 bIsFromIdNull == FALSE && bIsToIdNull == FALSE )
     652                 :             {
     653              70 :                 CPLXMLNode *psNode = CPLParseXMLString( pszGmlString );
     654              70 :                 if( psNode != NULL )
     655                 :                 {
     656              70 :                     if( gmlHugeResolveEdgeNodes( psNode, pszFromId,
     657                 :                                                  pszToId ) == TRUE )
     658                 :                     {
     659              70 :                         char * gmlText = CPLSerializeXMLTree(psNode);
     660              70 :                         sqlite3_reset ( hUpdateStmt );
     661              70 :                         sqlite3_clear_bindings ( hUpdateStmt );
     662                 :                         sqlite3_bind_blob( hUpdateStmt, 1, gmlText,
     663              70 :                                            strlen(gmlText), SQLITE_STATIC );
     664                 :                         sqlite3_bind_text( hUpdateStmt, 2, pszGmlId, -1,
     665              70 :                                            SQLITE_STATIC );
     666              70 :                         rc = sqlite3_step( hUpdateStmt );
     667              70 :                         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              70 :                         CPLFree( gmlText );
     674              70 :                         iCount++;
     675              70 :                         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              70 :                     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               2 :     sqlite3_finalize ( hQueryStmt );
     717               2 :     sqlite3_finalize ( hUpdateStmt );
     718                 : 
     719                 :     /* committing the current TRANSACTION */
     720               2 :     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
     721               2 :     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               2 :     if( bError == TRUE )
     730               0 :         return FALSE;
     731               2 :     return TRUE;
     732                 : }
     733                 : 
     734              72 : 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              72 :     pItem = helper->pFirst;
     742             225 :     while ( pItem != NULL )
     743                 :     {
     744              81 :         if( pItem->bHasCoords == TRUE )
     745                 :         {
     746              81 :             if( pItem->gmlNodeFrom != NULL )
     747                 :             {
     748              81 :                 sqlite3_reset ( helper->hNodes );
     749              81 :                 sqlite3_clear_bindings ( helper->hNodes );
     750                 :                 sqlite3_bind_text( helper->hNodes, 1,
     751                 :                                    pItem->gmlNodeFrom->c_str(), -1,
     752              81 :                                    SQLITE_STATIC );
     753              81 :                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeFrom );
     754              81 :                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeFrom );
     755              81 :                 if( pItem->bHasZ == TRUE )
     756               0 :                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeFrom );
     757              81 :                 sqlite3_bind_null ( helper->hNodes, 5 );
     758              81 :                 rc = sqlite3_step( helper->hNodes );
     759              81 :                 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              81 :             if( pItem->gmlNodeTo != NULL )
     768                 :             {
     769              81 :                 sqlite3_reset ( helper->hNodes );
     770              81 :                 sqlite3_clear_bindings ( helper->hNodes );
     771                 :                 sqlite3_bind_text( helper->hNodes, 1, pItem->gmlNodeTo->c_str(),
     772              81 :                                    -1, SQLITE_STATIC );
     773              81 :                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeTo );
     774              81 :                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeTo );
     775              81 :                 if ( pItem->bHasZ == TRUE )
     776               0 :                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeTo );
     777              81 :                 sqlite3_bind_null ( helper->hNodes, 5 );
     778              81 :                 rc = sqlite3_step( helper->hNodes );
     779              81 :                 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              81 :         sqlite3_reset( helper->hEdges );
     791              81 :         sqlite3_clear_bindings( helper->hEdges );
     792                 :         sqlite3_bind_text( helper->hEdges, 1, pItem->gmlId->c_str(), -1,
     793              81 :                            SQLITE_STATIC );
     794              92 :         if( pItem->bIsNodeFromHref == FALSE && pItem->bIsNodeToHref == FALSE )
     795                 :         {
     796              11 :             sqlite3_bind_null( helper->hEdges, 2 );
     797                 :             sqlite3_bind_blob( helper->hEdges, 3, pItem->gmlTagValue->c_str(),
     798                 :                                strlen( pItem->gmlTagValue->c_str() ),
     799              11 :                                SQLITE_STATIC );
     800                 :         }
     801                 :         else
     802                 :         {
     803                 :             sqlite3_bind_blob( helper->hEdges, 2, pItem->gmlTagValue->c_str(),
     804                 :                                strlen( pItem->gmlTagValue->c_str() ),
     805              70 :                                SQLITE_STATIC );
     806              70 :             sqlite3_bind_null( helper->hEdges, 3 );
     807                 :         }
     808              81 :         if( pItem->gmlNodeFrom != NULL )
     809                 :             sqlite3_bind_text( helper->hEdges, 4, pItem->gmlNodeFrom->c_str(),
     810              81 :                                -1, SQLITE_STATIC );
     811                 :         else
     812               0 :             sqlite3_bind_null( helper->hEdges, 4 );
     813              81 :         if( pItem->bHasCoords == TRUE )
     814                 :         {
     815              81 :             sqlite3_bind_double( helper->hEdges, 5, pItem->xNodeFrom );
     816              81 :             sqlite3_bind_double( helper->hEdges, 6, pItem->yNodeFrom );
     817              81 :             if( pItem->bHasZ == TRUE )
     818               0 :                 sqlite3_bind_double( helper->hEdges, 7, pItem->zNodeFrom );
     819                 :             else
     820              81 :                 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              81 :         if( pItem->gmlNodeTo != NULL )
     829                 :             sqlite3_bind_text( helper->hEdges, 8, pItem->gmlNodeTo->c_str(),
     830              81 :                                -1, SQLITE_STATIC );
     831                 :         else
     832               0 :             sqlite3_bind_null( helper->hEdges, 8 );
     833              81 :         if( pItem->bHasCoords == TRUE )
     834                 :         {
     835              81 :             sqlite3_bind_double( helper->hEdges, 9, pItem->xNodeTo );
     836              81 :             sqlite3_bind_double( helper->hEdges, 10, pItem->yNodeTo );
     837              81 :             if( pItem->bHasZ == TRUE )
     838               0 :                 sqlite3_bind_double( helper->hEdges, 11, pItem->zNodeTo );
     839                 :             else
     840              81 :                 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              81 :         rc = sqlite3_step( helper->hEdges );
     849              81 :         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              81 :         pItem = pItem->pNext;
     857                 :     }
     858              72 :     return TRUE;
     859                 : }
     860                 : 
     861              72 : static void gmlHugeFileReset( struct huge_helper *helper )
     862                 : {
     863                 : /* resetting an empty helper struct */
     864                 :     struct huge_tag *pNext;
     865              72 :     struct huge_tag *p = helper->pFirst;
     866                 : 
     867                 :     /* cleaning any previous item */
     868             225 :     while( p != NULL )
     869                 :     {
     870              81 :         pNext = p->pNext;
     871              81 :         if( p->gmlTagValue != NULL )
     872              81 :             delete p->gmlTagValue;
     873              81 :         if( p->gmlId != NULL )
     874              81 :             delete p->gmlId;
     875              81 :         if( p->gmlNodeFrom != NULL )
     876              81 :             delete p->gmlNodeFrom;
     877              81 :         if( p->gmlNodeTo != NULL )
     878              81 :             delete p->gmlNodeTo;
     879              81 :         delete p;
     880              81 :         p = pNext;
     881                 :     }
     882              72 :     helper->pFirst = NULL;
     883              72 :     helper->pLast = NULL;
     884              72 : }
     885                 : 
     886              14 : static void gmlHugeFileHrefReset( struct huge_helper *helper )
     887                 : {
     888                 : /* resetting an empty helper struct */
     889                 :     struct huge_href *pNext;
     890              14 :     struct huge_href *p = helper->pFirstHref;
     891                 : 
     892                 :     /* cleaning any previous item */
     893             151 :     while( p != NULL )
     894                 :     {
     895             123 :         pNext = p->pNext;
     896             123 :         if( p->gmlId != NULL )
     897             123 :             delete p->gmlId;
     898             123 :         if( p->gmlText != NULL )
     899             123 :             delete p->gmlText;
     900             123 :         delete p;
     901             123 :         p = pNext;
     902                 :     }
     903              14 :     helper->pFirstHref = NULL;
     904              14 :     helper->pLastHref = NULL;
     905              14 : }
     906                 : 
     907              14 : static int gmlHugeFileHrefCheck( struct huge_helper *helper )
     908                 : {
     909                 : /* testing for unresolved items */
     910              14 :     int bError = FALSE;
     911              14 :   struct huge_href *p = helper->pFirstHref;
     912             151 :   while( p != NULL )
     913                 :     {
     914             123 :     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             123 :         p = p->pNext;
     922                 :     }
     923              14 :   if( bError == TRUE )
     924               0 :     return FALSE;
     925              14 :   return TRUE;
     926                 : }
     927                 : 
     928              14 : static void gmlHugeFileRewiterReset( struct huge_helper *helper )
     929                 : {
     930                 : /* resetting an empty helper struct */
     931                 :     struct huge_parent *pNext;
     932              14 :     struct huge_parent *p = helper->pFirstParent;
     933                 : 
     934                 :     /* cleaning any previous item */
     935              54 :     while( p != NULL )
     936                 :     {
     937              26 :         pNext = p->pNext;
     938                 :         struct huge_child *pChildNext;
     939              26 :         struct huge_child *pChild = p->pFirst;
     940             216 :         while( pChild != NULL )
     941                 :         {
     942             164 :             pChildNext = pChild->pNext;
     943             164 :             delete pChild;
     944             164 :             pChild = pChildNext;
     945                 :         }
     946              26 :         delete p;
     947              26 :         p = pNext;
     948                 :     }
     949              14 :     helper->pFirstParent = NULL;
     950              14 :     helper->pLastParent = NULL;
     951              14 : }
     952                 : 
     953              97 : 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              97 :     pItem = helper->pFirst;
     962             339 :     while( pItem != NULL )
     963                 :     {
     964             161 :         if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) )
     965              16 :             return NULL;
     966             145 :         pItem = pItem->pNext;
     967                 :     } 
     968                 : 
     969              81 :     pItem = new struct huge_tag;
     970              81 :     pItem->gmlId = gmlId;
     971              81 :     pItem->gmlTagValue = gmlFragment;
     972              81 :     pItem->gmlNodeFrom = NULL;
     973              81 :     pItem->gmlNodeTo = NULL;
     974              81 :     pItem->bHasCoords = FALSE;
     975              81 :     pItem->bHasZ = FALSE;
     976              81 :     pItem->pNext = NULL;
     977                 : 
     978                 :     /* appending the item to the linked list */
     979              81 :     if ( helper->pFirst == NULL )
     980              59 :         helper->pFirst = pItem;
     981              81 :     if ( helper->pLast != NULL )
     982              22 :         helper->pLast->pNext = pItem;
     983              81 :     helper->pLast = pItem;
     984              81 :     return pItem;
     985                 : }
     986                 : 
     987             123 : 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             123 :     pItem = helper->pFirstHref;
     999             820 :     while( pItem != NULL )
    1000                 :     {
    1001             574 :         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             574 :             pItem = pItem->pNext;
    1011                 :     } 
    1012                 : 
    1013             123 :     pItem = new struct huge_href;
    1014             123 :     pItem->gmlId = gmlId;
    1015             123 :     pItem->gmlText = NULL;
    1016             123 :     pItem->psParent = psParent;
    1017             123 :     pItem->psNode = psNode;
    1018             123 :     pItem->bIsDirectedEdge = bIsDirectedEdge;
    1019             123 :     pItem->cOrientation = cOrientation;
    1020             123 :     pItem->pNext = NULL;
    1021                 : 
    1022                 :     /* appending the item to the linked list */
    1023             123 :     if ( helper->pFirstHref == NULL )
    1024              14 :         helper->pFirstHref = pItem;
    1025             123 :     if ( helper->pLastHref != NULL )
    1026             109 :         helper->pLastHref->pNext = pItem;
    1027             123 :     helper->pLastHref = pItem;
    1028                 : }
    1029                 : 
    1030              97 : static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
    1031                 : {
    1032                 : /* attempting to identify a gml:id value      */
    1033              97 :     *gmlId = NULL;
    1034              97 :     const CPLXMLNode *psChild = psNode->psChild;
    1035             194 :     while( psChild != NULL )
    1036                 :     {
    1037              97 :         if( psChild->eType == CXT_Attribute &&
    1038                 :             EQUAL( psChild->pszValue, "gml:id" ) )
    1039                 :         {
    1040              97 :             const CPLXMLNode *psIdValue = psChild->psChild;
    1041              97 :             if( psIdValue != NULL )
    1042                 :             {
    1043              97 :                 if( psIdValue->eType == CXT_Text )
    1044                 :                 {
    1045              97 :                     *gmlId = new CPLString(psIdValue->pszValue);
    1046              97 :                     return TRUE;
    1047                 :                 }
    1048                 :             }
    1049                 :         }
    1050               0 :         psChild = psChild->psNext;
    1051                 :     }
    1052               0 :     return FALSE;
    1053                 : }
    1054                 : 
    1055              81 : 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              81 :     CPLXMLNode *psTopoCurve = CPLCreateXMLNode(NULL, CXT_Element, "TopoCurve");
    1066              81 :     CPLXMLNode *psDirEdge = CPLCreateXMLNode(psTopoCurve, CXT_Element, "directedEdge");
    1067              81 :     CPLXMLNode *psEdge = CPLCloneXMLTree((CPLXMLNode *)psNode);
    1068              81 :     CPLAddXMLChild( psDirEdge, psEdge );
    1069                 :     OGRGeometryCollection *poColl = (OGRGeometryCollection *)
    1070              81 :                                     GML2OGRGeometry_XMLNode( psTopoCurve, FALSE );
    1071              81 :     CPLDestroyXMLNode( psTopoCurve );
    1072              81 :     if( poColl != NULL )
    1073                 :     {
    1074              81 :         int iCount = poColl->getNumGeometries();
    1075              81 :         if( iCount == 1 )
    1076                 :         {
    1077              81 :             OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(0);
    1078              81 :             int type = wkbFlatten( poChild->getGeometryType());
    1079              81 :             if( type == wkbLineString )
    1080                 :             {
    1081              81 :                 OGRLineString *poLine = (OGRLineString *)poChild;
    1082              81 :                 int iPoints =  poLine->getNumPoints();
    1083              81 :                 if( iPoints >= 2 )
    1084                 :                 {
    1085              81 :                     pItem->bHasCoords = TRUE;
    1086              81 :                     pItem->xNodeFrom = poLine->getX( 0 );
    1087              81 :                     pItem->yNodeFrom = poLine->getY( 0 );
    1088              81 :                     pItem->xNodeTo = poLine->getX( iPoints - 1 );
    1089              81 :                     pItem->yNodeTo = poLine->getY( iPoints - 1 );
    1090              81 :                     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              81 :                         pItem->bHasZ = FALSE;
    1098                 :                 }
    1099                 :             }
    1100                 :         }
    1101              81 :         delete poColl;
    1102                 :     }
    1103                 :   
    1104                 :     /* searching the <directedNode> sub-tags */
    1105              81 :     const CPLXMLNode *psChild = psNode->psChild;
    1106             486 :     while( psChild != NULL )
    1107                 :     {
    1108             324 :         if( psChild->eType == CXT_Element &&
    1109                 :             EQUAL( psChild->pszValue, "directedNode" ) )
    1110                 :         {
    1111             162 :             char cOrientation = '+';
    1112             162 :             const char *pszGmlId = NULL;
    1113             162 :             int bIsHref = FALSE;
    1114             162 :             const CPLXMLNode *psAttr = psChild->psChild;
    1115             567 :             while( psAttr != NULL )
    1116                 :             {
    1117             243 :                 if( psAttr->eType == CXT_Attribute &&
    1118                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
    1119                 :                 {
    1120              96 :                     const CPLXMLNode *psHref = psAttr->psChild;
    1121              96 :                     if( psHref != NULL )
    1122                 :                     {
    1123              96 :                         if( psHref->eType == CXT_Text )
    1124                 :                         {
    1125              96 :                             pszGmlId = psHref->pszValue;
    1126              96 :                             bIsHref = TRUE;
    1127                 :                         }
    1128                 :                     }
    1129                 :                 }
    1130             243 :                 if( psAttr->eType == CXT_Attribute &&
    1131                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
    1132                 :                 {
    1133              81 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
    1134              81 :                     if( psOrientation != NULL )
    1135                 :                     {
    1136              81 :                         if( psOrientation->eType == CXT_Text )
    1137                 :                         {
    1138              81 :                             cOrientation = *(psOrientation->pszValue);
    1139                 :                         }
    1140                 :                     }
    1141                 :                 }
    1142             243 :                 if( psAttr->eType == CXT_Element &&
    1143                 :                     EQUAL( psAttr->pszValue, "Node" ) )
    1144                 :                 {
    1145              66 :                     const CPLXMLNode *psId = psAttr->psChild;
    1146             198 :                     while( psId != NULL )
    1147                 :                     {   
    1148              66 :                         if( psId->eType == CXT_Attribute &&
    1149                 :                             EQUAL( psId->pszValue, "gml:id" ) )
    1150                 :                         {
    1151              66 :                             const CPLXMLNode *psIdGml = psId->psChild;
    1152              66 :                             if( psIdGml != NULL )
    1153                 :                             {
    1154              66 :                                 if( psIdGml->eType == CXT_Text )
    1155                 :                                 {
    1156              66 :                                     pszGmlId = psIdGml->pszValue;
    1157              66 :                                     bIsHref = FALSE;
    1158                 :                                 }
    1159                 :                             }
    1160                 :                         }
    1161              66 :                         psId = psId->psNext;
    1162                 :                     }
    1163                 :                 }
    1164             243 :                 psAttr = psAttr->psNext;
    1165                 :             }
    1166             162 :             if( pszGmlId != NULL )
    1167                 :             {
    1168                 :                 CPLString* posNode;
    1169             162 :                 if( bIsHref == TRUE )
    1170                 :                 {
    1171              96 :                     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              96 :                     posNode = new CPLString(pszGmlId+1);
    1178                 :                 }
    1179                 :                 else
    1180              66 :                     posNode = new CPLString(pszGmlId);
    1181             162 :                 if( cOrientation == '-' )
    1182                 :                 {
    1183              81 :                      pItem->gmlNodeFrom = posNode;
    1184              81 :                     pItem->bIsNodeFromHref = bIsHref;
    1185                 :                 }
    1186                 :                 else
    1187                 :                 {
    1188              81 :                     pItem->gmlNodeTo = posNode;
    1189              81 :                     pItem->bIsNodeToHref = bIsHref;
    1190                 :                 }
    1191             162 :                 pszGmlId = NULL;
    1192             162 :                 bIsHref = FALSE;
    1193             162 :                 cOrientation = '+';
    1194                 :             }
    1195                 :         }
    1196             324 :         psChild = psChild->psNext;
    1197                 :     }
    1198              81 : }
    1199                 : 
    1200             251 : static void gmlHugeFileCheckXrefs( struct huge_helper *helper, 
    1201                 :                                    const CPLXMLNode *psNode )
    1202                 : {
    1203                 : /* identifying <Edge> GML nodes */
    1204             251 :     if( psNode->eType == CXT_Element )
    1205                 :     {
    1206             251 :         if( EQUAL(psNode->pszValue, "Edge") == TRUE )
    1207                 :         {
    1208              97 :             CPLString *gmlId = NULL;
    1209              97 :             if( gmlHugeFindGmlId( psNode, &gmlId ) == TRUE )
    1210                 :             {
    1211              97 :                 char * gmlText = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1212              97 :                 CPLString *gmlValue = new CPLString(gmlText);
    1213              97 :                 CPLFree( gmlText );
    1214                 :                 struct huge_tag *pItem = gmlHugeAddToHelper( helper, gmlId,
    1215              97 :                                                              gmlValue );
    1216              97 :                 if( pItem != NULL )
    1217              81 :                     gmlHugeFileNodeCoords( pItem, psNode, &(helper->nodeSrs) );
    1218                 :                 else
    1219                 :                 {
    1220              16 :                     delete gmlId;
    1221              16 :                     delete gmlValue;
    1222                 :                 }
    1223                 :             }
    1224                 :         }
    1225                 :     }
    1226                 : 
    1227                 :     /* recursively scanning each Child GML node */
    1228             251 :     const CPLXMLNode *psChild = psNode->psChild;
    1229            1064 :     while( psChild != NULL )
    1230                 :     {
    1231             562 :         if( psChild->eType == CXT_Element )
    1232                 :         {
    1233             465 :             if( EQUAL(psChild->pszValue, "Edge") == TRUE ||
    1234                 :                 EQUAL(psChild->pszValue, "directedEdge") == TRUE )
    1235                 :             {
    1236             148 :                 gmlHugeFileCheckXrefs( helper, psChild );
    1237                 :             }
    1238             465 :             if( EQUAL(psChild->pszValue, "directedFace") == TRUE )
    1239                 :             {
    1240              26 :                 const CPLXMLNode *psFace = psChild->psChild;
    1241              26 :                 if( psFace != NULL )
    1242                 :                 {
    1243              26 :                     if( psFace->eType == CXT_Element &&
    1244                 :                         EQUAL(psFace->pszValue, "Face") == TRUE)
    1245                 :                     {
    1246              24 :                         const CPLXMLNode *psDirEdge = psFace->psChild;
    1247             205 :                         while (psDirEdge != NULL)
    1248                 :                         {
    1249             157 :                             const CPLXMLNode *psEdge = psDirEdge->psChild;
    1250             536 :                             while( psEdge != NULL)
    1251                 :                             {
    1252             222 :                                 if( psEdge->eType == CXT_Element &&
    1253                 :                                     EQUAL(psEdge->pszValue, "Edge") == TRUE)
    1254              15 :                                     gmlHugeFileCheckXrefs( helper, psEdge );
    1255             222 :                                 psEdge = psEdge->psNext;
    1256                 :                             }
    1257             157 :                             psDirEdge = psDirEdge->psNext;
    1258                 :                         }
    1259                 :                     }
    1260                 :                 }
    1261                 :             }
    1262                 :         }
    1263             562 :         psChild = psChild->psNext;
    1264                 :     }
    1265                 : 
    1266                 :     /* recursively scanning each GML of the same level */
    1267             251 :     const CPLXMLNode *psNext = psNode->psNext;
    1268             518 :     while( psNext != NULL )
    1269                 :     {
    1270              16 :         if( psNext->eType == CXT_Element )
    1271                 :         {
    1272              16 :             if( EQUAL(psNext->pszValue, "Edge") == TRUE ||
    1273                 :                 EQUAL(psNext->pszValue, "directedEdge") == TRUE )
    1274                 :             {
    1275              16 :                 gmlHugeFileCheckXrefs( helper, psNext );
    1276                 :             }
    1277                 :         }
    1278              16 :         psNext = psNext->psNext;
    1279                 :     }
    1280             251 : }
    1281                 : 
    1282               2 : static void gmlHugeFileCleanUp ( struct huge_helper *helper ) 
    1283                 : {
    1284                 : /* cleaning up any SQLite handle */
    1285               2 :     if( helper->hNodes != NULL )
    1286               0 :         sqlite3_finalize ( helper->hNodes );
    1287               2 :     if( helper->hEdges != NULL )
    1288               0 :         sqlite3_finalize ( helper->hEdges );
    1289               2 :     if( helper->hDB != NULL )
    1290               2 :         sqlite3_close( helper->hDB );
    1291               2 :     if( helper->nodeSrs != NULL )
    1292               0 :         delete helper->nodeSrs;
    1293               2 : }
    1294                 : 
    1295             328 : 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             328 :     if( psNode->eType == CXT_Element )
    1301                 :     {
    1302             328 :         if( EQUAL(psNode->pszValue, "directedEdge") == TRUE )
    1303                 :         {
    1304             204 :             char cOrientation = '+';
    1305             204 :             CPLXMLNode *psAttr = psNode->psChild;
    1306             680 :             while( psAttr != NULL )
    1307                 :             {
    1308             272 :                 if( psAttr->eType == CXT_Attribute &&
    1309                 :                     EQUAL( psAttr->pszValue, "orientation" ) )
    1310                 :                 {
    1311              68 :                     const CPLXMLNode *psOrientation = psAttr->psChild;
    1312              68 :                     if( psOrientation != NULL )
    1313                 :                     {
    1314              68 :                         if( psOrientation->eType == CXT_Text )
    1315              68 :                             cOrientation = *(psOrientation->pszValue);
    1316                 :                     }
    1317                 :                 }
    1318             272 :                 psAttr = psAttr->psNext;
    1319                 :             }
    1320             204 :             psAttr = psNode->psChild;
    1321             680 :             while( psAttr != NULL )
    1322                 :             {
    1323             272 :                 if( psAttr->eType == CXT_Attribute &&
    1324                 :                     EQUAL( psAttr->pszValue, "xlink:href" ) )
    1325                 :                 {
    1326             123 :                     const CPLXMLNode *pszHref = psAttr->psChild;
    1327             123 :                     if( pszHref != NULL )
    1328                 :                     {
    1329             123 :                         if( pszHref->eType == CXT_Text )
    1330                 :                         {
    1331             123 :                             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             123 :                             CPLString *gmlId = new CPLString(pszHref->pszValue+1);
    1338                 :                             gmlHugeAddPendingToHelper( helper, gmlId, psParent,
    1339             123 :                                                        psNode, TRUE, cOrientation );
    1340                 :                         }
    1341                 :                     }
    1342                 :                 }
    1343             272 :                 psAttr = psAttr->psNext;
    1344                 :             }
    1345                 :         }
    1346                 :     }
    1347                 : 
    1348                 :     /* recursively scanning each Child GML node */
    1349             328 :     const CPLXMLNode *psChild = psNode->psChild;
    1350            1212 :     while( psChild != NULL )
    1351                 :     {
    1352             556 :         if( psChild->eType == CXT_Element )
    1353                 :         {
    1354             337 :             if( EQUAL(psChild->pszValue, "directedEdge") == TRUE ||
    1355                 :                 EQUAL(psChild->pszValue, "directedFace") == TRUE ||
    1356                 :                 EQUAL(psChild->pszValue, "Face") == TRUE)
    1357                 :             {
    1358             256 :                 gmlHugeFileCheckPendingHrefs( helper, psNode, psChild );
    1359                 :             }
    1360                 :         }
    1361             556 :         psChild = psChild->psNext;
    1362                 :     }
    1363                 : 
    1364                 :     /* recursively scanning each GML of the same level */
    1365             328 :     const CPLXMLNode *psNext = psNode->psNext;
    1366            1104 :     while( psNext != NULL )
    1367                 :     {
    1368             448 :         if( psNext->eType == CXT_Element )
    1369                 :         {
    1370             448 :             if( EQUAL(psNext->pszValue, "Face") == TRUE )
    1371                 :             {
    1372               0 :                 gmlHugeFileCheckPendingHrefs( helper, psParent, psNext );
    1373                 :             }
    1374                 :         }
    1375             448 :         psNext = psNext->psNext;
    1376                 :     }
    1377             328 : }
    1378                 : 
    1379             123 : 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             123 :     struct huge_href *pItem = helper->pFirstHref;
    1385             820 :     while( pItem != NULL )
    1386                 :     {
    1387             697 :         if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) == TRUE )
    1388                 :         {
    1389             123 :             if( pItem->gmlText != NULL)
    1390               0 :                 delete pItem->gmlText;
    1391             123 :             pItem->gmlText = new CPLString( pszGmlText );
    1392             123 :             return;
    1393                 :         }
    1394             574 :         pItem = pItem->pNext;
    1395                 :     }
    1396                 : }
    1397                 : 
    1398             123 : static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
    1399                 :                                               CPLXMLNode *psParent )
    1400                 : {
    1401                 : /* inserting a GML Node (parent) to be rewritted */
    1402             123 :     struct huge_parent *pItem = helper->pFirstParent;
    1403                 : 
    1404                 :     /* checking if already exists */
    1405             318 :     while( pItem != NULL )
    1406                 :     {
    1407             169 :         if( pItem->psParent == psParent )
    1408              97 :             return pItem;
    1409              72 :         pItem = pItem->pNext;
    1410                 :     }
    1411                 : 
    1412                 :     /* creating a new Parent Node */
    1413              26 :     pItem = new struct huge_parent;
    1414              26 :     pItem->psParent = psParent;
    1415              26 :     pItem->pFirst = NULL;
    1416              26 :     pItem->pLast = NULL;
    1417              26 :     pItem->pNext = NULL;
    1418              26 :     if( helper->pFirstParent == NULL )
    1419              14 :         helper->pFirstParent = pItem;
    1420              26 :     if( helper->pLastParent != NULL )
    1421              12 :         helper->pLastParent->pNext = pItem;
    1422              26 :     helper->pLastParent = pItem;
    1423                 : 
    1424                 :     /* inserting any Child node into the Parent */
    1425              26 :     CPLXMLNode *psChild = psParent->psChild;
    1426             216 :     while( psChild != NULL )
    1427                 :     {
    1428                 :         struct huge_child *pChildItem;
    1429             164 :         pChildItem = new struct huge_child;
    1430             164 :         pChildItem->psChild = psChild;
    1431             164 :         pChildItem->pItem = NULL;
    1432             164 :         pChildItem->pNext = NULL;
    1433             164 :         if( pItem->pFirst == NULL )
    1434              26 :             pItem->pFirst = pChildItem;
    1435             164 :         if( pItem->pLast != NULL )
    1436             138 :             pItem->pLast->pNext = pChildItem;
    1437             164 :         pItem->pLast = pChildItem;
    1438             164 :         psChild = psChild->psNext;
    1439                 :     }
    1440              26 :     return pItem;
    1441                 : }
    1442                 : 
    1443             123 : static int gmlHugeSetChild( struct huge_parent *pParent,
    1444                 :                             struct huge_href *pItem )
    1445                 : {
    1446                 : /* setting a Child Node to be rewritted */
    1447             123 :     struct huge_child *pChild = pParent->pFirst;
    1448             712 :     while( pChild != NULL )
    1449                 :     {
    1450             589 :          if( pChild->psChild == pItem->psNode )
    1451                 :          {
    1452             123 :             pChild->pItem = pItem;
    1453             123 :             return TRUE;
    1454                 :          }
    1455             466 :          pChild = pChild->pNext;
    1456                 :     }
    1457               0 :     return FALSE;
    1458                 : }
    1459                 : 
    1460              14 : static int gmlHugeResolveEdges( struct huge_helper *helper,
    1461                 :                                 CPLXMLNode *psNode, sqlite3 *hDB )
    1462                 : {
    1463                 : /* resolving GML <Edge> xlink:href */
    1464              14 :     CPLString      osCommand;
    1465                 :     sqlite3_stmt   *hStmtEdges;
    1466                 :     int            rc;
    1467              14 :     int            bIsComma = FALSE;
    1468              14 :     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              14 :                 "WHERE gml_id IN (";
    1476              14 :     pItem = helper->pFirstHref;
    1477             151 :     while( pItem != NULL )
    1478                 :     {
    1479             123 :         if( bIsComma == TRUE )
    1480             109 :             osCommand += ", ";
    1481                 :         else
    1482              14 :             bIsComma = TRUE;
    1483             123 :         osCommand += "'";
    1484             123 :         osCommand += pItem->gmlId->c_str();
    1485             123 :         osCommand += "'";
    1486             123 :         pItem = pItem->pNext;
    1487                 :     }
    1488              14 :     osCommand += ")";
    1489              14 :     rc = sqlite3_prepare( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
    1490              14 :     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             123 :     while ( TRUE )
    1497                 :     {
    1498             137 :         rc = sqlite3_step( hStmtEdges );
    1499             137 :         if( rc == SQLITE_DONE )
    1500              14 :             break;
    1501             123 :         if ( rc == SQLITE_ROW )
    1502                 :         {
    1503                 :             const char *pszGmlId;
    1504             123 :             const char *pszGmlText = NULL;
    1505             123 :             pszGmlId = (const char *)sqlite3_column_text ( hStmtEdges, 0 );
    1506             123 :             if( sqlite3_column_type( hStmtEdges, 1 ) != SQLITE_NULL )
    1507             123 :                 pszGmlText = (const char *)sqlite3_column_text ( hStmtEdges, 1 );
    1508             123 :             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              14 :     sqlite3_finalize ( hStmtEdges );
    1520              14 :     if( bError == TRUE )
    1521               0 :         return FALSE;
    1522                 : 
    1523                 :     /* indentifying any GML node to be rewritten */
    1524              14 :     pItem = helper->pFirstHref;
    1525             151 :     while( pItem != NULL )
    1526                 :     {
    1527             123 :         if( pItem->gmlText == NULL || pItem->psParent == NULL ||
    1528                 :             pItem->psNode == NULL )
    1529                 :         {
    1530               0 :             bError = TRUE;
    1531               0 :             break;
    1532                 :         }
    1533             123 :         pParent = gmlHugeFindParent( helper, (CPLXMLNode *)pItem->psParent );
    1534             123 :         if( gmlHugeSetChild( pParent, pItem ) == FALSE )
    1535                 :         {
    1536               0 :             bError = TRUE;
    1537               0 :             break;
    1538                 :         }
    1539             123 :         pItem = pItem->pNext;
    1540                 :     }
    1541                 : 
    1542              14 :     if( bError == FALSE )
    1543                 :     {
    1544                 :     /* rewriting GML nodes */
    1545              14 :         pParent = helper->pFirstParent;
    1546              54 :         while( pParent != NULL )
    1547                 :         {
    1548                 :             struct huge_child *pChild;
    1549                 : 
    1550                 :             /* removing any Child node from the Parent */
    1551              26 :             pChild = pParent->pFirst;
    1552             216 :             while( pChild != NULL )
    1553                 :             {
    1554             164 :                 CPLRemoveXMLChild( pParent->psParent, pChild->psChild );
    1555                 : 
    1556                 :                 /* destroyng any Child Node to be rewritten */
    1557             164 :                 if( pChild->pItem != NULL )
    1558             123 :                     CPLDestroyXMLNode( pChild->psChild );
    1559             164 :                 pChild = pChild->pNext;
    1560                 :             }
    1561                 : 
    1562                 :             /* rewriting the Parent Node */
    1563              26 :             pChild = pParent->pFirst;
    1564             216 :             while( pChild != NULL )
    1565                 :             {
    1566             164 :                 if( pChild->pItem == NULL )
    1567                 :                 {
    1568                 :                     /* reinserting any untouched Child Node */
    1569              41 :                     CPLAddXMLChild( pParent->psParent, pChild->psChild );
    1570                 :                 }
    1571                 :                 else
    1572                 :                 {
    1573                 :                     /* rewriting a Child Node */
    1574             123 :                     CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "directedEdge");
    1575             123 :                     if( pChild->pItem->cOrientation == '-' )
    1576                 :                     {
    1577              67 :                         CPLXMLNode *psOrientationNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "orientation");
    1578              67 :                         CPLCreateXMLNode(psOrientationNode, CXT_Text, "-");
    1579                 :                     }
    1580             123 :                     CPLXMLNode *psEdge = CPLParseXMLString(pChild->pItem->gmlText->c_str());
    1581             123 :                     CPLAddXMLChild( psNewNode, psEdge );
    1582             123 :                     CPLAddXMLChild( pParent->psParent, psNewNode );
    1583                 :                 }
    1584             164 :                 pChild = pChild->pNext;
    1585                 :             }
    1586              26 :             pParent = pParent->pNext;
    1587                 :         }
    1588                 :     }
    1589                 : 
    1590                 :     /* resetting the Rewrite Helper to an empty state */
    1591              14 :     gmlHugeFileRewiterReset( helper );
    1592              14 :     if( bError == TRUE )
    1593               0 :         return FALSE;
    1594              14 :     return TRUE;
    1595                 : }
    1596                 : 
    1597               2 : 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               2 :     sqlite3        *hDB = helper->hDB;
    1608                 :     sqlite3_stmt   *hStmtNodes;
    1609               2 :     int            bError = FALSE;
    1610               2 :     int            iOutCount = 0;
    1611                 : 
    1612                 : /* -------------------------------------------------------------------- */
    1613                 : /*      Opening the resolved GML file                                   */
    1614                 : /* -------------------------------------------------------------------- */
    1615               2 :     fp = VSIFOpenL( pszOutputFilename, "w" );
    1616               2 :     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               2 :                 "FROM nodes";
    1626               2 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hStmtNodes, NULL );
    1627               2 :     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               2 :     VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); 
    1636                 :     VSIFPrintfL ( fp, "<ResolvedTopoFeatureCollection  "
    1637               2 :                       "xmlns:gml=\"http://www.opengis.net/gml\">\n" );   
    1638               2 :     VSIFPrintfL ( fp, "  <ResolvedTopoFeatureMembers>\n" );
    1639                 :     /* exporting Nodes */
    1640               2 :     GFSTemplateList *pCC = new GFSTemplateList();
    1641              66 :     while ( TRUE )
    1642                 :     {
    1643              68 :         rc = sqlite3_step( hStmtNodes );
    1644              68 :         if( rc == SQLITE_DONE )
    1645                 :             break;
    1646              66 :         if ( rc == SQLITE_ROW )
    1647                 :         {
    1648                 :             const char *pszGmlId;
    1649                 :             char* pszEscaped;
    1650                 :             double x;
    1651                 :             double y;
    1652              66 :             double z = 0.0;
    1653              66 :             int bHasZ = FALSE;
    1654              66 :             pszGmlId = (const char *)sqlite3_column_text ( hStmtNodes, 0 );
    1655              66 :             x = sqlite3_column_double ( hStmtNodes, 1 );
    1656              66 :             y = sqlite3_column_double ( hStmtNodes, 2 );
    1657              66 :             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              66 :             pCC->Update( "ResolvedNodes", TRUE );
    1665              66 :             VSIFPrintfL ( fp, "    <ResolvedNodes>\n" );
    1666              66 :             pszEscaped = CPLEscapeString( pszGmlId, -1, CPLES_XML );
    1667              66 :             VSIFPrintfL ( fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped );
    1668              66 :             CPLFree(pszEscaped);
    1669              66 :             VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1670              66 :             if ( helper->nodeSrs == NULL )
    1671                 :                 VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\">",
    1672              66 :                               ( 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              66 :             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              66 :                               x, y );
    1690              66 :             VSIFPrintfL ( fp, "      </ResolvedGeometry> \n" );
    1691              66 :             VSIFPrintfL ( fp, "    </ResolvedNodes>\n" );
    1692              66 :             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               2 :     sqlite3_finalize ( hStmtNodes );
    1704                 : 
    1705                 :     /* processing GML features */
    1706              76 :     while( (poFeature = pReader->NextFeature()) != NULL )
    1707                 :     {
    1708              72 :         GMLFeatureClass *poClass = poFeature->GetClass();
    1709              72 :         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
    1710              72 :         int iPropCount = poClass->GetPropertyCount();
    1711                 :     
    1712              72 :         int b_has_geom = FALSE;
    1713              72 :         VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() ); 
    1714                 : 
    1715             252 :         for( int iProp = 0; iProp < iPropCount; iProp++ )
    1716                 :         {
    1717             180 :             GMLPropertyDefn *poPropDefn = poClass->GetProperty( iProp );
    1718             180 :             const char *pszPropName = poPropDefn->GetName();
    1719             180 :             const GMLProperty *poProp = poFeature->GetProperty( iProp );
    1720                 : 
    1721             180 :             if( poProp != NULL )
    1722                 :             {
    1723             360 :                 for( int iSub = 0; iSub < poProp->nSubProperties; iSub++ )
    1724                 :                 {
    1725             180 :                     char *gmlText = CPLEscapeString( poProp->papszSubProperties[iSub],
    1726                 :                                                     -1,
    1727             360 :                                                     CPLES_XML );
    1728                 :                     VSIFPrintfL ( fp, "      <%s>%s</%s>\n", 
    1729             180 :                                   pszPropName, gmlText, pszPropName ); 
    1730             180 :                     CPLFree( gmlText );
    1731                 :                 }
    1732                 :             }
    1733                 :         }
    1734                 : 
    1735              72 :         if( papsGeomList != NULL )
    1736                 :         {
    1737              72 :             int i = 0;
    1738              72 :             const CPLXMLNode *psNode = papsGeomList[i];
    1739             216 :             while( psNode != NULL )
    1740                 :             {
    1741              72 :                 char *pszResolved = NULL;
    1742                 :                 int bNotToBeResolved;
    1743              72 :                 if( psNode->eType != CXT_Element )
    1744               0 :                     bNotToBeResolved = TRUE;
    1745                 :                 else
    1746                 :                 {
    1747             144 :                     if( EQUAL(psNode->pszValue, "TopoCurve") == TRUE ||
    1748                 :                         EQUAL(psNode->pszValue, "TopoSurface") == TRUE )
    1749              72 :                         bNotToBeResolved = FALSE;
    1750                 :                     else
    1751               0 :                         bNotToBeResolved = TRUE;
    1752                 :                 }
    1753              72 :                 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              72 :                     gmlHugeFileCheckPendingHrefs( helper, psNode, psNode );
    1765              72 :                     if( helper->pFirstHref == NULL )
    1766                 :                     {
    1767              58 :                         VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1768              58 :                         pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1769              58 :                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
    1770              58 :                         CPLFree( pszResolved );
    1771              58 :                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
    1772              58 :                         b_has_geom = TRUE;
    1773                 :                     }
    1774                 :                     else
    1775                 :                     {
    1776              14 :                         if( gmlHugeResolveEdges( helper, (CPLXMLNode *)psNode,
    1777                 :                                                          hDB ) == FALSE)
    1778               0 :                             bError = TRUE;
    1779              14 :                         if( gmlHugeFileHrefCheck( helper ) == FALSE )
    1780               0 :               bError = TRUE;
    1781              14 :                         VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
    1782              14 :                         pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
    1783              14 :                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
    1784              14 :                         CPLFree( pszResolved );
    1785              14 :                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
    1786              14 :                         b_has_geom = TRUE;
    1787              14 :                         gmlHugeFileHrefReset( helper );
    1788                 :                     }
    1789                 :                 }
    1790              72 :                 i++;
    1791              72 :                 psNode = papsGeomList[i];
    1792                 :             }
    1793                 :         }
    1794              72 :         pCC->Update( poClass->GetElementName(), b_has_geom );
    1795                 : 
    1796              72 :         VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() ); 
    1797                 : 
    1798              72 :         delete poFeature;
    1799              72 :         iOutCount++;
    1800                 :     }
    1801                 : 
    1802               2 :     VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" ); 
    1803               2 :     VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" ); 
    1804                 : 
    1805               2 :     VSIFCloseL( fp );
    1806                 :     
    1807               2 :     gmlUpdateFeatureClasses( pCC, pReader, m_bSequentialLayers );
    1808               2 :     if ( *m_bSequentialLayers == TRUE )
    1809               2 :         pReader->ReArrangeTemplateClasses( pCC );
    1810               2 :     delete pCC;
    1811               2 :     if( bError == TRUE || iOutCount == 0 )
    1812               0 :         return FALSE;
    1813               2 :     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               2 : int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
    1825                 :                                  const int bSqliteIsTempFile,
    1826                 :                                  const int iSqliteCacheMB )
    1827                 : 
    1828                 : {
    1829                 :     GMLFeature  *poFeature;
    1830               2 :     int iFeatureUID = 0;
    1831                 :     int rc;
    1832               2 :     sqlite3 *hDB = NULL;
    1833               2 :     CPLString osSQLiteFilename;
    1834               2 :     const char *pszSQLiteFilename = NULL;
    1835                 :     struct huge_helper helper;
    1836               2 :     char *pszErrMsg = NULL;
    1837                 : 
    1838                 :     /* initializing the helper struct */
    1839               2 :     helper.hDB = NULL;
    1840               2 :     helper.hNodes = NULL;
    1841               2 :     helper.hEdges = NULL;
    1842               2 :     helper.nodeSrs = NULL;
    1843               2 :     helper.pFirst = NULL;
    1844               2 :     helper.pLast = NULL;
    1845               2 :     helper.pFirstHref = NULL;
    1846               2 :     helper.pLastHref = NULL;
    1847               2 :     helper.pFirstParent = NULL;
    1848               2 :     helper.pLastParent = NULL;
    1849                 :   
    1850                 : /* -------------------------------------------------------------------- */
    1851                 : /*      Creating/Opening the SQLite DB file                             */
    1852                 : /* -------------------------------------------------------------------- */
    1853               2 :     osSQLiteFilename = CPLResetExtension( m_pszFilename, "sqlite" );
    1854               2 :     pszSQLiteFilename = osSQLiteFilename.c_str();
    1855                 : 
    1856                 :     VSIStatBufL statBufL;
    1857               2 :     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               2 :     rc = sqlite3_open( pszSQLiteFilename, &hDB );
    1866               2 :     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               2 :     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               2 :                        &pszErrMsg );
    1884               2 :     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               2 :                        &pszErrMsg );
    1893               2 :     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               2 :                        &pszErrMsg );
    1902               2 :     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               2 :     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               2 :     if( !SetupParser() )
    1930                 :     {
    1931               0 :         gmlHugeFileCleanUp ( &helper );
    1932               0 :         return FALSE;
    1933                 :     }
    1934                 : 
    1935                 :     /* creating SQLite tables and Insert cursors */
    1936               2 :     if( gmlHugeFileSQLiteInit( &helper ) == FALSE )
    1937                 :     {
    1938               0 :         gmlHugeFileCleanUp ( &helper );
    1939               0 :         return FALSE;
    1940                 :     }
    1941                 : 
    1942                 :     /* processing GML features */
    1943              76 :     while( (poFeature = NextFeature()) != NULL )
    1944                 :     {
    1945              72 :         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
    1946              72 :         if (papsGeomList != NULL)
    1947                 :         {
    1948              72 :             int i = 0;
    1949              72 :             const CPLXMLNode *psNode = papsGeomList[i];
    1950             216 :             while(psNode)
    1951                 :             {
    1952              72 :                 gmlHugeFileCheckXrefs( &helper, psNode );
    1953                 :                 /* inserting into the SQLite DB any appropriate row */
    1954              72 :                 gmlHugeFileSQLiteInsert ( &helper );
    1955                 :                 /* resetting an empty helper struct */
    1956              72 :                 gmlHugeFileReset ( &helper );
    1957              72 :                 i ++;
    1958              72 :                 psNode = papsGeomList[i];
    1959                 :             }
    1960                 :         }
    1961              72 :         iFeatureUID++;
    1962              72 :         delete poFeature;
    1963                 :     }
    1964                 : 
    1965                 :     /* finalizing any SQLite Insert cursor */
    1966               2 :     if( helper.hNodes != NULL )
    1967               2 :         sqlite3_finalize ( helper.hNodes );
    1968               2 :     helper.hNodes = NULL;
    1969               2 :     if( helper.hEdges != NULL )
    1970               2 :         sqlite3_finalize ( helper.hEdges );
    1971               2 :     helper.hEdges = NULL;
    1972                 : 
    1973                 :     /* confirming the still pending TRANSACTION */
    1974               2 :     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
    1975               2 :     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               2 :     if( gmlHugeFileResolveEdges( &helper ) == FALSE )
    1986                 :     {
    1987               0 :         gmlHugeFileCleanUp ( &helper );
    1988               0 :         return FALSE;
    1989                 :     }
    1990                 :   
    1991                 :     /* restarting the GML parser */
    1992               2 :     if( !SetupParser() )
    1993                 :     {
    1994               0 :         gmlHugeFileCleanUp ( &helper );
    1995               0 :         return FALSE;
    1996                 :     }
    1997                 : 
    1998                 :     /* output: writing the revolved GML file */
    1999               2 :     if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this, 
    2000                 :                                    &m_bSequentialLayers ) == FALSE)
    2001                 :     {
    2002               0 :         gmlHugeFileCleanUp ( &helper );
    2003               0 :         return FALSE;
    2004                 :     }
    2005                 : 
    2006               2 :     gmlHugeFileCleanUp ( &helper );
    2007               2 :     if ( bSqliteIsTempFile == TRUE )
    2008               2 :         VSIUnlink( pszSQLiteFilename );
    2009               2 :     return TRUE;
    2010                 : }
    2011                 : 
    2012                 : /**************************************************************/
    2013                 : /*                                                            */
    2014                 : /* an alternative <xlink:href> resolver based on SQLite       */
    2015                 : /*                                                            */
    2016                 : /**************************************************************/
    2017               2 : int GMLReader::HugeFileResolver( const char *pszFile,
    2018                 :                                  int bSqliteIsTempFile,
    2019                 :                                  int iSqliteCacheMB )
    2020                 : 
    2021                 : {
    2022                 :     // Check if the original source file is set.
    2023               2 :     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               2 :     if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == FALSE )
    2031               0 :         return FALSE;
    2032                 : 
    2033                 :     //set the source file to the resolved file
    2034               2 :     CleanupParser();
    2035               2 :     if (fpGML)
    2036               2 :         VSIFCloseL(fpGML);
    2037               2 :     fpGML = NULL;
    2038               2 :     CPLFree( m_pszFilename );
    2039               2 :     m_pszFilename = CPLStrdup( pszFile );
    2040               2 :     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