LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - hugefileresolver.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1057 804 76.1 %
Date: 2011-12-18 Functions: 24 23 95.8 %

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

Generated by: LCOV version 1.7