LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/libkml - ogrlibkmldatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 622 413 66.4 %
Date: 2012-12-26 Functions: 40 27 67.5 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  KML Translator
       4                 :  * Purpose:  Implements OGRLIBKMLDriver
       5                 :  * Author:   Brian Case, rush at winkey dot org
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2010, Brian Case
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  *****************************************************************************/
      28                 : 
      29                 : //#include "cpl_conv.h"
      30                 : //#include "cpl_string.h"
      31                 : //#include "cpl_error.h"
      32                 : #include <iostream>
      33                 : //#include <sstream>
      34                 : #include <kml/dom.h>
      35                 : #include <kml/base/file.h>
      36                 : 
      37                 : using kmldom::KmlFactory;
      38                 : using kmldom::DocumentPtr;
      39                 : using kmldom::FolderPtr;
      40                 : using kmldom::FeaturePtr;
      41                 : using kmldom::NetworkLinkPtr;
      42                 : using kmldom::StyleSelectorPtr;
      43                 : using kmldom::LinkPtr;
      44                 : using kmldom::SchemaPtr;
      45                 : using kmlbase::File;
      46                 : using kmldom::KmlPtr;
      47                 : 
      48                 : #include "ogr_libkml.h"
      49                 : #include "ogrlibkmlstyle.h"
      50                 : 
      51                 : /***** this was shamelessly swiped from the kml driver *****/
      52                 : 
      53                 : #define OGRLIBKMLSRSWKT "GEOGCS[\"WGS 84\", "\
      54                 :                         "   DATUM[\"WGS_1984\","\
      55                 :                         "     SPHEROID[\"WGS 84\",6378137,298.257223563,"\
      56                 :                         "           AUTHORITY[\"EPSG\",\"7030\"]],"\
      57                 :                         "           AUTHORITY[\"EPSG\",\"6326\"]],"\
      58                 :                         "       PRIMEM[\"Greenwich\",0,"\
      59                 :                         "           AUTHORITY[\"EPSG\",\"8901\"]],"\
      60                 :                         "       UNIT[\"degree\",0.01745329251994328,"\
      61                 :                         "           AUTHORITY[\"EPSG\",\"9122\"]],"\
      62                 :                         "           AUTHORITY[\"EPSG\",\"4326\"]]"
      63                 : 
      64                 : /******************************************************************************
      65                 :  OGRLIBKMLDataSource Constructor
      66                 : 
      67                 :  Args:          none
      68                 :  
      69                 :  Returns:       nothing
      70                 :                 
      71                 : ******************************************************************************/
      72                 : 
      73             312 : OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
      74                 : {
      75             312 :     pszName = NULL;
      76             312 :     papoLayers = NULL;
      77             312 :     nLayers = 0;
      78             312 :     nAlloced = 0;
      79                 : 
      80             312 :     bUpdated = FALSE;
      81                 : 
      82             312 :     m_isKml = FALSE;
      83             312 :     m_poKmlDSKml = NULL;
      84             312 :     m_poKmlDSContainer = NULL;
      85                 : 
      86             312 :     m_isKmz = FALSE;
      87             312 :     m_poKmlDocKml = NULL;
      88             312 :     pszStylePath = (char *) "";
      89                 : 
      90             312 :     m_isDir = FALSE;
      91                 :     
      92             312 :     m_poKmlFactory = poKmlFactory;
      93                 : 
      94                 :     //m_poStyleTable = NULL;
      95                 : 
      96             312 : }
      97                 : 
      98                 : /******************************************************************************
      99                 :  method to write a single file ds .kml at ds destroy
     100                 : 
     101                 :  Args:          none
     102                 :  
     103                 :  Returns:       nothing
     104                 :                 
     105                 : ******************************************************************************/
     106                 : 
     107               1 : void OGRLIBKMLDataSource::WriteKml (
     108                 :      )
     109                 : {
     110               1 :     std::string oKmlFilename = pszName;
     111                 : 
     112               3 :     if ( m_poKmlDSContainer
     113               1 :          && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) ) {
     114               1 :         DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
     115                 :         int iLayer;
     116                 : 
     117               3 :         for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     118               2 :             SchemaPtr poKmlSchema;
     119               2 :             SchemaPtr poKmlSchema2;
     120                 : 
     121               2 :             if ( ( poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  ) ) ) {
     122               2 :                 size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
     123                 :                 size_t iKmlSchema;
     124                 : 
     125               3 :                 for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
     126                 :                     poKmlSchema2 =
     127               1 :                         poKmlDocument->get_schema_array_at ( iKmlSchema );
     128               1 :                     if ( poKmlSchema2 == poKmlSchema )
     129               0 :                         break;
     130                 :                 }
     131                 : 
     132               2 :                 if ( poKmlSchema2 != poKmlSchema )
     133               2 :                     poKmlDocument->add_schema ( poKmlSchema );
     134                 :             }
     135               1 :         }
     136                 :     }
     137                 : 
     138               1 :     std::string oKmlOut;
     139               1 :     if ( m_poKmlDSKml ) {
     140               1 :         oKmlOut = kmldom::SerializePretty ( m_poKmlDSKml );
     141                 :     }
     142               0 :     else if ( m_poKmlDSContainer ) {
     143               0 :         oKmlOut = kmldom::SerializePretty ( m_poKmlDSContainer );
     144                 :     }
     145                 : 
     146               1 :     if (oKmlOut.size() != 0)
     147                 :     {
     148               1 :         VSILFILE* fp = VSIFOpenL( oKmlFilename.c_str(), "wb" );
     149               1 :         if (fp == NULL)
     150                 :         {
     151                 :             CPLError ( CE_Failure, CPLE_FileIO,
     152               0 :                        "ERROR writing %s", oKmlFilename.c_str (  ) );
     153                 :             return;
     154                 :         }
     155                 : 
     156               1 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     157               1 :         VSIFCloseL(fp);
     158                 :     }
     159                 : 
     160               0 :     return;
     161                 : }
     162                 : 
     163                 : /******************************************************************************
     164                 :  method to write a ds .kmz at ds destroy
     165                 : 
     166                 :  Args:          none
     167                 :  
     168                 :  Returns:       nothing
     169                 :                 
     170                 : ******************************************************************************/
     171                 : 
     172               1 : void OGRLIBKMLDataSource::WriteKmz (
     173                 :      )
     174                 : {
     175                 : 
     176               1 :     void* hZIP = CPLCreateZip( pszName, NULL );
     177                 : 
     178               1 :     if ( !hZIP ) {
     179                 :         CPLError ( CE_Failure, CPLE_NoWriteAccess, "ERROR creating %s",
     180               0 :                    pszName );
     181               0 :         return;
     182                 :     }
     183                 : 
     184                 :     /***** write out the doc.kml ****/
     185                 : 
     186                 :     const char *pszUseDocKml =
     187               1 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
     188                 : 
     189               1 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
     190                 : 
     191                 :         /***** if we dont have the doc.kml root *****/
     192                 :         /***** make it and add the container    *****/
     193                 :         
     194               1 :         if ( !m_poKmlDocKmlRoot ) {
     195               1 :             m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
     196                 : 
     197               1 :             AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
     198                 :         }
     199                 :         
     200               1 :         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
     201                 : 
     202                 : 
     203               1 :         if ( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
     204                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     205                 :             CPLError ( CE_Failure, CPLE_FileIO,
     206               0 :                        "ERROR adding %s to %s", "doc.kml", pszName );
     207               1 :         CPLCloseFileInZip(hZIP);
     208                 : 
     209                 :     }
     210                 : 
     211                 :     /***** loop though the layers and write them *****/
     212                 : 
     213                 :     int iLayer;
     214                 : 
     215               3 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     216               2 :         ContainerPtr poKlmContainer = papoLayers[iLayer]->GetKmlLayer (  );
     217                 : 
     218               2 :         if ( poKlmContainer->IsA ( kmldom::Type_Document ) ) {
     219                 : 
     220               2 :             DocumentPtr poKmlDocument = AsDocument ( poKlmContainer );
     221               2 :             SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
     222                 : 
     223               2 :             if ( !poKmlDocument->get_schema_array_size (  ) &&
     224                 :                  poKmlSchema &&
     225                 :                  poKmlSchema->get_simplefield_array_size (  ) ) {
     226               1 :                 poKmlDocument->add_schema ( poKmlSchema );
     227               2 :             }
     228                 :         }
     229                 : 
     230                 :         /***** if we dont have the layers root *****/
     231                 :         /***** make it and add the container    *****/
     232                 : 
     233               2 :         KmlPtr poKmlKml = NULL;
     234                 : 
     235               2 :         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
     236                 : 
     237               2 :             poKmlKml = m_poKmlFactory->CreateKml (  );
     238                 : 
     239               2 :             poKmlKml->set_feature ( poKlmContainer );
     240                 :         }
     241                 : 
     242               2 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     243                 : 
     244               2 :         if ( CPLCreateFileInZip( hZIP, papoLayers[iLayer]->GetFileName (  ), NULL ) != CE_None ||
     245                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     246                 :             CPLError ( CE_Failure, CPLE_FileIO,
     247               0 :                        "ERROR adding %s to %s", papoLayers[iLayer]->GetFileName (  ), pszName );
     248               2 :         CPLCloseFileInZip(hZIP);
     249                 : 
     250                 :     }
     251                 : 
     252                 :    /***** write the style table *****/
     253                 : 
     254               1 :     if ( m_poKmlStyleKml ) {
     255                 : 
     256               0 :         KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
     257                 : 
     258               0 :         poKmlKml->set_feature ( m_poKmlStyleKml );
     259               0 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     260                 : 
     261               0 :         if ( CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
     262                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     263                 :             CPLError ( CE_Failure, CPLE_FileIO,
     264               0 :                        "ERROR adding %s to %s", "style/style.kml", pszName );
     265               0 :         CPLCloseFileInZip(hZIP);
     266                 :     }
     267                 : 
     268               1 :     CPLCloseZip(hZIP);
     269                 : 
     270               1 :     return;
     271                 : }
     272                 : 
     273                 : /******************************************************************************
     274                 :  method to write a dir ds at ds destroy
     275                 : 
     276                 :  Args:          none
     277                 :  
     278                 :  Returns:       nothing
     279                 :                 
     280                 : ******************************************************************************/
     281                 : 
     282               1 : void OGRLIBKMLDataSource::WriteDir (
     283                 :      )
     284                 : {
     285                 : 
     286                 :     /***** write out the doc.kml ****/
     287                 : 
     288                 :     const char *pszUseDocKml =
     289               1 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
     290                 : 
     291               1 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
     292                 : 
     293                 :         /***** if we dont have the doc.kml root *****/
     294                 :         /***** make it and add the container    *****/
     295                 :         
     296               1 :         if ( !m_poKmlDocKmlRoot ) {
     297               1 :             m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
     298                 : 
     299               1 :             AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
     300                 :         }
     301                 :         
     302               1 :         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
     303                 : 
     304               1 :         const char *pszOutfile = CPLFormFilename ( pszName, "doc.kml", NULL );
     305                 : 
     306               1 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     307               1 :         if (fp == NULL)
     308                 :         {
     309                 :             CPLError ( CE_Failure, CPLE_FileIO,
     310               0 :                        "ERROR Writing %s to %s", "doc.kml", pszName );
     311                 :             return;
     312                 :         }
     313                 : 
     314               1 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     315               1 :         VSIFCloseL(fp);
     316                 :     }
     317                 : 
     318                 :     /***** loop though the layers and write them *****/
     319                 : 
     320                 :     int iLayer;
     321                 : 
     322               1 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     323               2 :         ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
     324                 : 
     325               2 :         if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
     326                 : 
     327               2 :             DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
     328               2 :             SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
     329                 : 
     330               2 :             if ( !poKmlDocument->get_schema_array_size (  ) &&
     331                 :                  poKmlSchema &&
     332                 :                  poKmlSchema->get_simplefield_array_size (  ) ) {
     333               1 :                 poKmlDocument->add_schema ( poKmlSchema );
     334               2 :             };
     335                 :         }
     336                 : 
     337                 :         /***** if we dont have the layers root *****/
     338                 :         /***** make it and add the container    *****/
     339                 : 
     340               2 :         KmlPtr poKmlKml = NULL;
     341                 : 
     342               2 :         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
     343                 : 
     344               2 :             poKmlKml = m_poKmlFactory->CreateKml (  );
     345                 : 
     346               2 :             poKmlKml->set_feature ( poKmlContainer );
     347                 :         }
     348                 : 
     349               2 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     350                 : 
     351                 :         const char *pszOutfile = CPLFormFilename ( pszName,
     352               2 :                                                    papoLayers[iLayer]->
     353                 :                                                    GetFileName (  ),
     354               4 :                                                    NULL );
     355                 : 
     356               2 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     357               2 :         if (fp == NULL)
     358                 :         {
     359                 :             CPLError ( CE_Failure, CPLE_FileIO,
     360                 :                        "ERROR Writing %s to %s",
     361               0 :                        papoLayers[iLayer]->GetFileName (  ), pszName );
     362                 :             return;
     363                 :         }
     364                 : 
     365               2 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     366               2 :         VSIFCloseL(fp);
     367                 :     }
     368                 : 
     369                 :    /***** write the style table *****/
     370                 : 
     371               1 :     if ( m_poKmlStyleKml ) {
     372                 : 
     373               0 :         KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
     374                 : 
     375               0 :         poKmlKml->set_feature ( m_poKmlStyleKml );
     376               0 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     377                 : 
     378                 :         const char *pszOutfile = CPLFormFilename ( pszName,
     379                 :                                                    "style.kml",
     380               0 :                                                    NULL );
     381                 : 
     382               0 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     383               0 :         if (fp == NULL)
     384                 :         {
     385                 :             CPLError ( CE_Failure, CPLE_FileIO,
     386               0 :                        "ERROR Writing %s to %s", "style.kml", pszName );
     387                 :             return;
     388                 :         }
     389                 : 
     390               0 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     391               0 :         VSIFCloseL(fp);
     392                 :     }
     393                 : 
     394               1 :     return;
     395                 : }
     396                 : 
     397                 : /******************************************************************************
     398                 :  method to write the datasource to disk
     399                 : 
     400                 :  Args:      none
     401                 : 
     402                 :  Returns    nothing
     403                 : 
     404                 : ******************************************************************************/
     405                 : 
     406             312 : OGRErr OGRLIBKMLDataSource::SyncToDisk (
     407                 :      )
     408                 : {
     409                 : 
     410             312 :     if ( bUpdated ) {
     411                 : 
     412                 :         /***** kml *****/
     413                 : 
     414               3 :         if ( bUpdate && IsKml (  ) )
     415               1 :             WriteKml (  );
     416                 : 
     417                 :         /***** kmz *****/
     418                 : 
     419               2 :         else if ( bUpdate && IsKmz (  ) ) {
     420               1 :             WriteKmz (  );
     421                 :         }
     422                 : 
     423               1 :         else if ( bUpdate && IsDir (  ) ) {
     424               1 :             WriteDir (  );
     425                 :         }
     426                 : 
     427               3 :         bUpdated = FALSE;
     428                 :     }
     429                 : 
     430             312 :     return OGRERR_NONE;
     431                 : }
     432                 : 
     433                 : /******************************************************************************
     434                 :  OGRLIBKMLDataSource Destructor
     435                 :  
     436                 :  Args:          none
     437                 :  
     438                 :  Returns:       nothing
     439                 :                 
     440                 : ******************************************************************************/
     441                 : 
     442             312 : OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
     443                 : {
     444                 : 
     445                 : 
     446                 :     /***** sync the DS to disk *****/
     447                 : 
     448             312 :     SyncToDisk (  );
     449                 : 
     450             312 :     CPLFree ( pszName );
     451                 : 
     452             312 :     if (! EQUAL(pszStylePath, ""))
     453               2 :         CPLFree ( pszStylePath );
     454                 :     
     455             364 :     for ( int i = 0; i < nLayers; i++ )
     456              52 :         delete papoLayers[i];
     457                 : 
     458             312 :     CPLFree ( papoLayers );
     459                 : 
     460                 :     //delete m_poStyleTable;
     461                 : 
     462             312 : }
     463                 : 
     464                 : 
     465                 : /******************************************************************************
     466                 :  method to parse a schemas out of a document
     467                 : 
     468                 :  Args:          poKmlDocument   pointer to the document to parse
     469                 :  
     470                 :  Returns:       nothing
     471                 :                 
     472                 : ******************************************************************************/
     473                 : 
     474               5 : SchemaPtr OGRLIBKMLDataSource::FindSchema (
     475                 :     const char *pszSchemaUrl )
     476                 : {
     477               5 :     char *pszID = NULL;
     478               5 :     char *pszFile = NULL;
     479               5 :     char *pszSchemaName = NULL;
     480                 :     char *pszPound;
     481               5 :     DocumentPtr poKmlDocument = NULL;
     482               5 :     SchemaPtr poKmlSchemaResult = NULL;
     483                 : 
     484               5 :     if ( !pszSchemaUrl || !*pszSchemaUrl )
     485               0 :         return NULL;
     486                 : 
     487               5 :     if ( *pszSchemaUrl == '#' ) {
     488               3 :         pszID = CPLStrdup ( pszSchemaUrl + 1 );
     489                 : 
     490                 :         /***** kml *****/
     491                 : 
     492               3 :         if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
     493               3 :             poKmlDocument = AsDocument ( m_poKmlDSContainer );
     494                 : 
     495                 :         /***** kmz *****/
     496                 : 
     497               0 :         else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
     498               0 :                   && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
     499               0 :             poKmlDocument = AsDocument ( m_poKmlDocKml );
     500                 : 
     501                 :     }
     502                 : 
     503                 : 
     504               2 :     else if ( ( pszPound = strchr ( (char *)pszSchemaUrl, '#' ) ) ) {
     505               0 :         pszFile = CPLStrdup ( pszSchemaUrl );
     506               0 :         pszID = CPLStrdup ( pszPound + 1 );
     507               0 :         pszPound = strchr ( pszFile, '#' );
     508               0 :         *pszPound = '\0';
     509                 :     }
     510                 : 
     511                 :     else {
     512               2 :         pszSchemaName = CPLStrdup ( pszSchemaUrl );
     513                 : 
     514                 :         /***** kml *****/
     515                 : 
     516               2 :         if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
     517               2 :             poKmlDocument = AsDocument ( m_poKmlDSContainer );
     518                 : 
     519                 :         /***** kmz *****/
     520                 : 
     521               0 :         else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
     522               0 :                   && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
     523               0 :             poKmlDocument = AsDocument ( m_poKmlDocKml );
     524                 : 
     525                 :     }
     526                 :     
     527                 : 
     528               5 :     if ( poKmlDocument) {
     529                 : 
     530               5 :         size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
     531                 :         size_t iKmlSchema;
     532                 : 
     533               5 :         for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
     534                 :             SchemaPtr poKmlSchema =
     535               6 :                 poKmlDocument->get_schema_array_at ( iKmlSchema );
     536               6 :             if ( poKmlSchema->has_id (  ) && pszID) {
     537               4 :                 if ( EQUAL ( pszID, poKmlSchema->get_id (  ).c_str (  ) ) ) {
     538               2 :                     poKmlSchemaResult = poKmlSchema;
     539                 :                     break;
     540                 :                 }
     541                 :             }
     542                 : 
     543               2 :             else if ( poKmlSchema->has_name (  ) && pszSchemaName) {
     544               2 :                 if ( EQUAL ( pszSchemaName, poKmlSchema->get_name (  ).c_str (  ) ) ) {
     545               1 :                     poKmlSchemaResult = poKmlSchema;
     546                 :                     break;
     547                 :                 }
     548                 :             }
     549                 : 
     550                 :         }
     551                 :     }
     552                 : 
     553               5 :     if ( pszFile )
     554               0 :         CPLFree ( pszFile );
     555               5 :     if ( pszID )
     556               3 :         CPLFree ( pszID );
     557               5 :     if ( pszSchemaName )
     558               2 :         CPLFree ( pszSchemaName );
     559                 : 
     560               5 :     return poKmlSchemaResult;
     561                 : 
     562                 : }
     563                 : 
     564                 : /******************************************************************************
     565                 : Method to allocate memory for the layer array, create the layer,
     566                 :  and add it to the layer array
     567                 : 
     568                 :  Args:          pszLayerName    the name of the layer
     569                 :                 poSpatialRef    the spacial Refrance for the layer
     570                 :                 eGType          the layers geometry type
     571                 :                 poOgrDS         pointer to the datasource the layer is in
     572                 :                 poKmlRoot       pointer to the root kml element of the layer
     573                 :                 pszFileName     the filename of the layer
     574                 :                 bNew            true if its a new layer
     575                 :                 bUpdate         true if the layer is writeable
     576                 :                 nGuess          a guess at the number of additional layers
     577                 :                                 we are going to need
     578                 :  
     579                 :  Returns:       Pointer to the new layer
     580                 : ******************************************************************************/
     581                 : 
     582              52 : OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
     583                 :     const char *pszLayerName,
     584                 :     OGRSpatialReference * poSpatialRef,
     585                 :     OGRwkbGeometryType eGType,
     586                 :     OGRLIBKMLDataSource * poOgrDS,
     587                 :     ElementPtr poKmlRoot,
     588                 :     ContainerPtr poKmlContainer,
     589                 :     const char *pszFileName,
     590                 :     int bNew,
     591                 :     int bUpdate,
     592                 :     int nGuess )
     593                 : {
     594                 : 
     595                 :     /***** check to see if we have enough space to store the layer *****/
     596                 : 
     597              52 :     if ( nLayers == nAlloced ) {
     598              20 :         nAlloced += nGuess;
     599                 :         void *tmp = CPLRealloc ( papoLayers,
     600              20 :                                  sizeof ( OGRLIBKMLLayer * ) * nAlloced );
     601                 : 
     602              20 :         papoLayers = ( OGRLIBKMLLayer ** ) tmp;
     603                 :     }
     604                 : 
     605                 :     /***** create the layer *****/
     606                 : 
     607              52 :     int iLayer = nLayers++;
     608                 : 
     609                 :     OGRLIBKMLLayer *poOgrLayer = new OGRLIBKMLLayer ( pszLayerName,
     610                 :                                                       poSpatialRef,
     611                 :                                                       eGType,
     612                 :                                                       poOgrDS,
     613                 :                                                       poKmlRoot,
     614                 :                                                       poKmlContainer,
     615                 :                                                       pszFileName,
     616                 :                                                       bNew,
     617              52 :                                                       bUpdate );
     618                 : 
     619                 :     /***** add the layer to the array *****/
     620                 : 
     621              52 :     papoLayers[iLayer] = poOgrLayer;
     622                 : 
     623              52 :     return poOgrLayer;
     624                 : }
     625                 : 
     626                 : /******************************************************************************
     627                 :  method to parse multiple layers out of a container
     628                 : 
     629                 :  Args:          poKmlContainer  pointer to the container to parse
     630                 :                 poOgrSRS        SRS to use when creating the layer
     631                 :  
     632                 :  Returns:       number of features in the container that are not another
     633                 :                 container
     634                 :                 
     635                 : ******************************************************************************/
     636                 : 
     637              56 : int OGRLIBKMLDataSource::ParseLayers (
     638                 :     ContainerPtr poKmlContainer,
     639                 :     OGRSpatialReference * poOgrSRS )
     640                 : {
     641              56 :     int nResult = 0;
     642                 : 
     643                 :     /***** if container is null just bail now *****/
     644                 : 
     645              56 :     if ( !poKmlContainer )
     646               0 :         return nResult;
     647                 : 
     648              56 :     size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
     649                 : 
     650                 :     /***** loop over the container to seperate the style, layers, etc *****/
     651                 : 
     652                 :     size_t iKmlFeature;
     653                 : 
     654             242 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
     655                 :         FeaturePtr poKmlFeat =
     656             186 :             poKmlContainer->get_feature_array_at ( iKmlFeature );
     657                 : 
     658                 :         /***** container *****/
     659                 : 
     660             186 :         if ( poKmlFeat->IsA ( kmldom::Type_Container ) ) {
     661                 : 
     662                 :             /***** see if the container has a name *****/
     663                 : 
     664              39 :             std::string oKmlFeatName;
     665              39 :             if ( poKmlFeat->has_name (  ) ) {
     666                 :                 /* Strip leading and trailing spaces */
     667              39 :                 const char* pszName = poKmlFeat->get_name (  ).c_str();
     668              78 :                 while(*pszName == ' ' || *pszName == '\n' || *pszName == '\r' || *pszName == '\t' )
     669               0 :                     pszName ++;
     670              39 :                 oKmlFeatName = pszName;
     671              39 :                 int nSize = (int)oKmlFeatName.size();
     672              78 :                 while (nSize > 0 &&
     673                 :                        (oKmlFeatName[nSize-1] == ' ' || oKmlFeatName[nSize-1] == '\n' ||
     674                 :                         oKmlFeatName[nSize-1] == '\r' || oKmlFeatName[nSize-1] == '\t'))
     675                 :                 {
     676               0 :                     nSize --;
     677               0 :                     oKmlFeatName.resize(nSize);
     678                 :                 }
     679                 :             }
     680                 : 
     681                 :             /***** use the feature index number as the name *****/
     682                 :             /***** not sure i like this c++ ich *****/
     683                 : 
     684                 :             else {
     685               0 :                 std::stringstream oOut;
     686               0 :                 oOut << iKmlFeature;
     687               0 :                 oKmlFeatName = "Layer";
     688               0 :                 oKmlFeatName.append(oOut.str (  ));
     689                 :             }
     690                 : 
     691                 :             /***** create the layer *****/
     692                 : 
     693                 :             AddLayer ( oKmlFeatName.c_str (  ),
     694                 :                        poOgrSRS, wkbUnknown, this,
     695              39 :                        NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate, nKmlFeatures );
     696                 : 
     697                 :         }
     698                 : 
     699                 :         else
     700             147 :             nResult++;
     701                 :     }
     702                 : 
     703              56 :     return nResult;
     704                 : }
     705                 : 
     706                 : /******************************************************************************
     707                 :  function to get the container from the kmlroot
     708                 :  
     709                 :  Args:          poKmlRoot   the root element
     710                 :  
     711                 :  Returns:       root if its a container, if its a kml the container it
     712                 :                 contains, or NULL
     713                 : 
     714                 : ******************************************************************************/
     715                 : 
     716              16 : static ContainerPtr GetContainerFromRoot (
     717                 :     KmlFactory *m_poKmlFactory, ElementPtr poKmlRoot )
     718                 : {
     719              16 :     ContainerPtr poKmlContainer = NULL;
     720                 : 
     721              16 :     int bReadGroundOverlay = CSLTestBoolean(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
     722                 : 
     723              16 :     if ( poKmlRoot ) {
     724                 : 
     725                 :         /***** skip over the <kml> we want the container *****/
     726                 : 
     727              16 :         if ( poKmlRoot->IsA ( kmldom::Type_kml ) ) {
     728                 : 
     729              16 :             KmlPtr poKmlKml = AsKml ( poKmlRoot );
     730                 : 
     731              16 :             if ( poKmlKml->has_feature (  ) ) {
     732              16 :                 FeaturePtr poKmlFeat = poKmlKml->get_feature (  );
     733                 : 
     734              16 :                 if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
     735              14 :                     poKmlContainer = AsContainer ( poKmlFeat );
     736               2 :                 else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) ||
     737               0 :                           (bReadGroundOverlay && poKmlFeat->IsA ( kmldom::Type_GroundOverlay )) ) 
     738                 :                 {
     739               2 :                     poKmlContainer = m_poKmlFactory->CreateDocument (  );
     740               2 :                     poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
     741              16 :                 }
     742              16 :             }
     743                 : 
     744                 :         }
     745                 : 
     746               0 :         else if ( poKmlRoot->IsA ( kmldom::Type_Container ) )
     747               0 :             poKmlContainer = AsContainer ( poKmlRoot );
     748                 :     }
     749                 : 
     750               0 :     return poKmlContainer;
     751                 : }
     752                 : 
     753                 : /******************************************************************************
     754                 :  method to parse a kml string into the style table
     755                 : ******************************************************************************/
     756                 : 
     757               0 : int OGRLIBKMLDataSource::ParseIntoStyleTable (
     758                 :     std::string *poKmlStyleKml,
     759                 :     const char *pszMyStylePath)
     760                 : {
     761                 :     
     762                 :     /***** parse the kml into the dom *****/
     763                 : 
     764               0 :     std::string oKmlErrors;
     765               0 :     ElementPtr poKmlRoot = kmldom::Parse ( *poKmlStyleKml, &oKmlErrors );
     766                 : 
     767               0 :     if ( !poKmlRoot ) {
     768                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     769                 :                    "ERROR Parseing style kml %s :%s",
     770               0 :                    pszStylePath, oKmlErrors.c_str (  ) );
     771               0 :         return false;
     772                 :     }
     773                 :     
     774               0 :     ContainerPtr poKmlContainer;
     775                 : 
     776               0 :     if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
     777               0 :         return false;
     778                 :     }
     779                 :     
     780               0 :     ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
     781               0 :     pszStylePath = CPLStrdup(pszMyStylePath);
     782                 :     
     783                 :         
     784               0 :     return true;
     785                 : }
     786                 : 
     787                 : /******************************************************************************
     788                 :  method to open a kml file
     789                 :  
     790                 :  Args:          pszFilename file to open
     791                 :                 bUpdate     update mode
     792                 :  
     793                 :  Returns:       True on success, false on failure
     794                 : 
     795                 : ******************************************************************************/
     796                 : 
     797              10 : int OGRLIBKMLDataSource::OpenKml (
     798                 :     const char *pszFilename,
     799                 :     int bUpdate )
     800                 : {
     801              10 :     std::string oKmlKml;
     802                 :     char szBuffer[1024+1];
     803                 : 
     804              10 :     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     805              10 :     if (fp == NULL)
     806                 :     {
     807                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     808               0 :                    "Cannot open %s", pszFilename );
     809               0 :         return FALSE;
     810                 :     }
     811                 :     int nRead;
     812             142 :     while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
     813                 :     {
     814                 :         try
     815                 :         {
     816             122 :             oKmlKml.append(szBuffer, nRead);
     817                 :         }
     818               0 :         catch(std::bad_alloc& e)
     819                 :         {
     820               0 :             VSIFCloseL(fp);
     821               0 :             return FALSE;
     822                 :         }
     823                 :     }
     824              10 :     VSIFCloseL(fp);
     825                 : 
     826              10 :     CPLLocaleC  oLocaleForcer;
     827                 : 
     828                 :     /***** create a SRS *****/
     829                 : 
     830                 :     OGRSpatialReference *poOgrSRS =
     831              10 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
     832                 : 
     833                 :     /***** parse the kml into the DOM *****/
     834                 : 
     835              10 :     std::string oKmlErrors;
     836                 : 
     837              10 :     ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
     838                 : 
     839              10 :     if ( !poKmlRoot ) {
     840                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     841                 :                    "ERROR Parseing kml %s :%s",
     842               0 :                    pszFilename, oKmlErrors.c_str (  ) );
     843               0 :         delete poOgrSRS;
     844                 : 
     845               0 :         return FALSE;
     846                 :     }
     847                 : 
     848                 :     /***** get the container from root  *****/
     849                 : 
     850              10 :     if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
     851                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     852                 :                    "ERROR Parseing kml %s :%s %s",
     853                 :                    pszFilename, "This file does not fit the OGR model,",
     854               0 :                    "there is no container element at the root." );
     855               0 :         delete poOgrSRS;
     856                 : 
     857               0 :         return FALSE;
     858                 :     }
     859                 : 
     860              10 :     m_isKml = TRUE;
     861                 : 
     862                 :     /***** get the styles *****/
     863                 : 
     864              10 :     ParseStyles ( AsDocument ( m_poKmlDSContainer ), &m_poStyleTable );
     865                 : 
     866                 :     /***** parse for layers *****/
     867                 : 
     868              10 :     int nPlacemarks = ParseLayers ( m_poKmlDSContainer, poOgrSRS );
     869                 : 
     870                 :     /***** if there is placemarks in the root its a layer *****/
     871                 : 
     872              10 :     if ( nPlacemarks && !nLayers ) {
     873                 :         AddLayer ( CPLGetBasename ( pszFilename ),
     874                 :                    poOgrSRS, wkbUnknown,
     875               2 :                    this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE, bUpdate, 1 );
     876                 :     }
     877                 : 
     878              10 :     delete poOgrSRS;
     879                 : 
     880              10 :     return TRUE;
     881                 : }
     882                 : 
     883                 : /******************************************************************************
     884                 :  method to open a kmz file
     885                 :  
     886                 :  Args:          pszFilename file to open
     887                 :                 bUpdate     update mode
     888                 :  
     889                 :  Returns:       True on success, false on failure
     890                 : 
     891                 : ******************************************************************************/
     892                 : 
     893                 : 
     894               1 : int OGRLIBKMLDataSource::OpenKmz (
     895                 :     const char *pszFilename,
     896                 :     int bUpdate )
     897                 : {
     898               1 :     std::string oKmlKmz;
     899                 :     char szBuffer[1024+1];
     900                 : 
     901               1 :     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     902               1 :     if (fp == NULL)
     903                 :     {
     904                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     905               0 :                    "Cannot open %s", pszFilename );
     906               0 :         return FALSE;
     907                 :     }
     908                 :     int nRead;
     909               3 :     while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
     910                 :     {
     911                 :         try
     912                 :         {
     913               1 :             oKmlKmz.append(szBuffer, nRead);
     914                 :         }
     915               0 :         catch(std::bad_alloc& e)
     916                 :         {
     917               0 :             VSIFCloseL(fp);
     918               0 :             return FALSE;
     919                 :         }
     920                 :     }
     921               1 :     VSIFCloseL(fp);
     922                 : 
     923               1 :     KmzFile *poKmlKmzfile = KmzFile::OpenFromString ( oKmlKmz );
     924                 : 
     925               1 :     if ( !poKmlKmzfile ) {
     926                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     927               0 :                    "%s is not a valid kmz file", pszFilename );
     928               0 :         return FALSE;
     929                 :     }
     930                 : 
     931               1 :     CPLLocaleC  oLocaleForcer;
     932                 : 
     933                 :     /***** read the doc.kml *****/
     934                 : 
     935               1 :     std::string oKmlKml;
     936               1 :     std::string oKmlKmlPath;
     937               1 :     if ( !poKmlKmzfile->ReadKmlAndGetPath ( &oKmlKml, &oKmlKmlPath ) ) {
     938                 : 
     939               0 :         return FALSE;
     940                 :     }
     941                 : 
     942                 :     /***** create a SRS *****/
     943                 : 
     944                 :     OGRSpatialReference *poOgrSRS =
     945               1 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
     946                 : 
     947                 :     /***** parse the kml into the DOM *****/
     948                 : 
     949               1 :     std::string oKmlErrors;
     950               1 :     ElementPtr poKmlDocKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
     951                 : 
     952               1 :     if ( !poKmlDocKmlRoot ) {
     953                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     954                 :                    "ERROR Parseing kml layer %s from %s :%s",
     955                 :                    oKmlKmlPath.c_str (  ),
     956               0 :                    pszFilename, oKmlErrors.c_str (  ) );
     957               0 :         delete poOgrSRS;
     958                 : 
     959               0 :         return FALSE;
     960                 :     }
     961                 : 
     962                 :     /***** get the child contianer from root *****/
     963                 : 
     964               1 :     ContainerPtr poKmlContainer;
     965                 : 
     966               1 :     if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlDocKmlRoot ))) {
     967                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     968                 :                    "ERROR Parseing %s from %s :%s",
     969                 :                    oKmlKmlPath.c_str (  ),
     970               0 :                    pszFilename, "kml contains no Containers" );
     971               0 :         delete poOgrSRS;
     972                 : 
     973               0 :         return FALSE;
     974                 :     }
     975                 : 
     976                 :     /***** loop over the container looking for network links *****/
     977                 : 
     978               1 :     size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
     979                 :     size_t iKmlFeature;
     980               1 :     int nLinks = 0;
     981                 : 
     982               1 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
     983                 :         FeaturePtr poKmlFeat =
     984               2 :             poKmlContainer->get_feature_array_at ( iKmlFeature );
     985                 : 
     986                 :         /***** is it a network link? *****/
     987                 : 
     988               2 :         if ( !poKmlFeat->IsA ( kmldom::Type_NetworkLink ) )
     989               0 :             continue;
     990                 : 
     991               2 :         NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
     992                 : 
     993                 :         /***** does it have a link? *****/
     994                 : 
     995               2 :         if ( !poKmlNetworkLink->has_link (  ) )
     996               0 :             continue;
     997                 : 
     998               2 :         LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
     999                 : 
    1000                 :         /***** does the link have a href? *****/
    1001                 : 
    1002               2 :         if ( !poKmlLink->has_href (  ) )
    1003               0 :             continue;
    1004                 : 
    1005                 :         kmlengine::Href * poKmlHref =
    1006               2 :             new kmlengine::Href ( poKmlLink->get_href (  ) );
    1007                 : 
    1008                 :         /***** is the link relative? *****/
    1009                 : 
    1010               4 :         if ( poKmlHref->IsRelativePath (  ) ) {
    1011                 : 
    1012               2 :             nLinks++;
    1013                 : 
    1014               2 :             std::string oKml;
    1015               2 :             if ( poKmlKmzfile->
    1016                 :                  ReadFile ( poKmlHref->get_path (  ).c_str (  ), &oKml ) ) {
    1017                 : 
    1018                 :                 /***** parse the kml into the DOM *****/
    1019                 : 
    1020               2 :                 std::string oKmlErrors;
    1021               2 :                 ElementPtr poKmlLyrRoot = kmldom::Parse ( oKml, &oKmlErrors );
    1022                 : 
    1023               2 :                 if ( !poKmlLyrRoot ) {
    1024                 :                     CPLError ( CE_Failure, CPLE_OpenFailed,
    1025                 :                                "ERROR Parseing kml layer %s from %s :%s",
    1026                 :                                poKmlHref->get_path (  ).c_str (  ),
    1027               0 :                                pszFilename, oKmlErrors.c_str (  ) );
    1028               0 :                     delete poKmlHref;
    1029                 : 
    1030               0 :                     continue;
    1031                 :                 }
    1032                 : 
    1033                 :                 /***** get the container from root  *****/
    1034                 : 
    1035                 :                 ContainerPtr poKmlLyrContainer =
    1036               2 :                     GetContainerFromRoot ( m_poKmlFactory, poKmlLyrRoot );
    1037                 : 
    1038               2 :                 if ( !poKmlLyrContainer )
    1039                 :                 {
    1040                 :                     CPLError ( CE_Failure, CPLE_OpenFailed,
    1041                 :                                "ERROR Parseing kml layer %s from %s :%s",
    1042                 :                                poKmlHref->get_path (  ).c_str (  ),
    1043               0 :                                pszFilename, oKmlErrors.c_str (  ) );
    1044               0 :                     delete poKmlHref;
    1045                 : 
    1046               0 :                     continue;
    1047                 :                 }
    1048                 : 
    1049                 :                 /***** create the layer *****/
    1050                 : 
    1051                 :                 AddLayer ( CPLGetBasename
    1052                 :                            ( poKmlHref->get_path (  ).c_str (  ) ), poOgrSRS,
    1053                 :                            wkbUnknown, this, poKmlLyrRoot, poKmlLyrContainer,
    1054                 :                            poKmlHref->get_path (  ).c_str (  ), FALSE, bUpdate,
    1055               2 :                            nKmlFeatures );
    1056                 : 
    1057               0 :             }
    1058                 :         }
    1059                 : 
    1060                 :         /***** cleanup *****/
    1061                 : 
    1062               2 :         delete poKmlHref;
    1063                 :     }
    1064                 : 
    1065                 :     /***** if the doc.kml has links store it so if were in update mode we can write it *****/
    1066                 :     
    1067               1 :     if ( nLinks ) {
    1068               1 :         m_poKmlDocKml = poKmlContainer;
    1069               1 :         m_poKmlDocKmlRoot = poKmlDocKmlRoot;
    1070                 :     }
    1071                 :         
    1072                 :     /***** if the doc.kml has no links treat it as a normal kml file *****/
    1073                 : 
    1074                 :     else {
    1075                 : 
    1076                 :         /* todo there could still be a seperate styles file in the kmz
    1077                 :            if there is this would be a layer style table IF its only a single
    1078                 :            layer
    1079                 :          */
    1080                 : 
    1081                 :         /***** get the styles *****/
    1082                 : 
    1083               0 :         ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
    1084                 : 
    1085                 :         /***** parse for layers *****/
    1086                 : 
    1087               0 :         int nPlacemarks = ParseLayers ( poKmlContainer, poOgrSRS );
    1088                 : 
    1089                 :         /***** if there is placemarks in the root its a layer *****/
    1090                 : 
    1091               0 :         if ( nPlacemarks && !nLayers ) {
    1092                 :             AddLayer ( CPLGetBasename ( pszFilename ),
    1093                 :                        poOgrSRS, wkbUnknown,
    1094               0 :                        this, poKmlDocKmlRoot, poKmlContainer, pszFilename, FALSE, bUpdate, 1 );
    1095                 :         }
    1096                 :     }
    1097                 : 
    1098                 :     /***** read the style table if it has one *****/
    1099                 : 
    1100               1 :     std::string oKmlStyleKml;
    1101               1 :     if ( poKmlKmzfile->ReadFile ( "style/style.kml", &oKmlStyleKml ) )
    1102               0 :         ParseIntoStyleTable ( &oKmlStyleKml, "style/style.kml");
    1103                 : 
    1104                 :     /***** cleanup *****/
    1105                 : 
    1106               1 :     delete poOgrSRS;
    1107                 : 
    1108               1 :     delete poKmlKmzfile;
    1109               1 :     m_isKmz = TRUE;
    1110                 :     
    1111               1 :     return TRUE;
    1112                 : }
    1113                 : 
    1114                 : /******************************************************************************
    1115                 :  method to open a dir
    1116                 :  
    1117                 :  Args:          pszFilename Dir to open
    1118                 :                 bUpdate     update mode
    1119                 :  
    1120                 :  Returns:       True on success, false on failure
    1121                 : 
    1122                 : ******************************************************************************/
    1123                 : 
    1124               7 : int OGRLIBKMLDataSource::OpenDir (
    1125                 :     const char *pszFilename,
    1126                 :     int bUpdate )
    1127                 : {
    1128                 : 
    1129               7 :     char **papszDirList = NULL;
    1130                 : 
    1131               7 :     if ( !( papszDirList = VSIReadDir ( pszFilename ) ) )
    1132               0 :         return FALSE;
    1133                 : 
    1134                 :     /***** create a SRS *****/
    1135                 : 
    1136                 :     OGRSpatialReference *poOgrSRS =
    1137               7 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
    1138                 : 
    1139               7 :     int nFiles = CSLCount ( papszDirList );
    1140                 :     int iFile;
    1141                 : 
    1142               7 :     for ( iFile = 0; iFile < nFiles; iFile++ ) {
    1143                 : 
    1144                 :         /***** make sure its a .kml file *****/
    1145                 : 
    1146             510 :         if ( !EQUAL ( CPLGetExtension ( papszDirList[iFile] ), "kml" ) )
    1147             507 :             continue;
    1148                 : 
    1149                 :         /***** read the file *****/
    1150               3 :         std::string oKmlKml;
    1151                 :         char szBuffer[1024+1];
    1152                 : 
    1153                 :         CPLString osFilePath =
    1154               3 :             CPLFormFilename ( pszFilename, papszDirList[iFile], NULL );
    1155                 : 
    1156               3 :         VSILFILE* fp = VSIFOpenL(osFilePath, "rb");
    1157               3 :         if (fp == NULL)
    1158                 :         {
    1159                 :              CPLError ( CE_Failure, CPLE_OpenFailed,
    1160               0 :                        "Cannot open %s", osFilePath.c_str() );
    1161               0 :              continue;
    1162                 :         }
    1163                 : 
    1164                 :         int nRead;
    1165              12 :         while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
    1166                 :         {
    1167                 :             try
    1168                 :             {
    1169               6 :                 oKmlKml.append(szBuffer, nRead);
    1170                 :             }
    1171               0 :             catch(std::bad_alloc& e)
    1172                 :             {
    1173               0 :                 VSIFCloseL(fp);
    1174               0 :                 CSLDestroy ( papszDirList );
    1175               0 :                 return FALSE;
    1176                 :             }
    1177                 :         }
    1178               3 :         VSIFCloseL(fp);
    1179                 : 
    1180               3 :         CPLLocaleC  oLocaleForcer;
    1181                 : 
    1182                 :         /***** parse the kml into the DOM *****/
    1183                 : 
    1184               3 :         std::string oKmlErrors;
    1185               3 :         ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
    1186                 : 
    1187               3 :         if ( !poKmlRoot ) {
    1188                 :             CPLError ( CE_Failure, CPLE_OpenFailed,
    1189                 :                        "ERROR Parseing kml layer %s from %s :%s",
    1190               0 :                        osFilePath.c_str(), pszFilename, oKmlErrors.c_str (  ) );
    1191                 : 
    1192               0 :             continue;
    1193                 :         }
    1194                 : 
    1195                 :         /***** get the cintainer from the root *****/
    1196                 : 
    1197               3 :         ContainerPtr poKmlContainer;
    1198                 : 
    1199               3 :         if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
    1200                 :             CPLError ( CE_Failure, CPLE_OpenFailed,
    1201                 :                        "ERROR Parseing kml %s :%s %s",
    1202                 :                        pszFilename,
    1203                 :                        "This file does not fit the OGR model,",
    1204               0 :                        "there is no container element at the root." );
    1205               0 :             continue;
    1206                 :         }
    1207                 : 
    1208                 :         /***** is it a style table? *****/
    1209                 : 
    1210               3 :         if ( EQUAL ( papszDirList[iFile], "style.kml" ) ) {
    1211               0 :             ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
    1212               0 :             pszStylePath = CPLStrdup((char *) "style.kml");
    1213               0 :             continue;
    1214                 :         }
    1215                 : 
    1216                 : 
    1217                 :         /***** create the layer *****/
    1218                 : 
    1219                 :         AddLayer ( CPLGetBasename ( osFilePath.c_str() ),
    1220                 :                    poOgrSRS, wkbUnknown,
    1221               3 :                    this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE, bUpdate, nFiles );
    1222                 : 
    1223                 :     }
    1224                 : 
    1225               7 :     delete poOgrSRS;
    1226                 : 
    1227               7 :     CSLDestroy ( papszDirList );
    1228                 : 
    1229               7 :     if ( nLayers > 0 ) {
    1230               1 :         m_isDir = TRUE;
    1231               1 :         return TRUE;
    1232                 :     }
    1233                 : 
    1234               6 :     return FALSE;
    1235                 : }
    1236                 : 
    1237                 : /******************************************************************************
    1238                 :  Method to open a datasource
    1239                 :  
    1240                 :  Args:          pszFilename Darasource to open
    1241                 :                 bUpdate     update mode
    1242                 :  
    1243                 :  Returns:       True on success, false on failure
    1244                 : 
    1245                 : ******************************************************************************/
    1246                 : 
    1247             519 : static int CheckIsKMZ(const char *pszFilename)
    1248                 : {
    1249             519 :     char** papszFiles = VSIReadDir(pszFilename);
    1250             519 :     char** papszIter = papszFiles;
    1251             519 :     int bFoundKML = FALSE;
    1252            1533 :     while(papszIter && *papszIter)
    1253                 :     {
    1254             495 :         if (EQUAL(CPLGetExtension(*papszIter), "kml"))
    1255                 :         {
    1256               0 :             bFoundKML = TRUE;
    1257               0 :             break;
    1258                 :         }
    1259                 :         else
    1260                 :         {
    1261             495 :             CPLString osFilename(pszFilename);
    1262             495 :             osFilename += "/";
    1263             495 :             osFilename += *papszIter;
    1264             495 :             if (CheckIsKMZ(osFilename))
    1265                 :             {
    1266               0 :                 bFoundKML = TRUE;
    1267                 :                 break;
    1268               0 :             }
    1269                 :         }
    1270             495 :         papszIter ++;
    1271                 :     }
    1272             519 :     CSLDestroy(papszFiles);
    1273             519 :     return bFoundKML;
    1274                 : }
    1275                 : 
    1276             309 : int OGRLIBKMLDataSource::Open (
    1277                 :     const char *pszFilename,
    1278                 :     int bUpdate )
    1279                 : {
    1280                 : 
    1281             309 :     this->bUpdate = bUpdate;
    1282             309 :     pszName = CPLStrdup ( pszFilename );
    1283                 : 
    1284                 :     /***** dir *****/
    1285                 : 
    1286             309 :     VSIStatBufL sStatBuf = { };
    1287             309 :     if ( !VSIStatExL ( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) &&
    1288                 :          VSI_ISDIR ( sStatBuf.st_mode ) )
    1289               7 :         return OpenDir ( pszFilename, bUpdate );
    1290                 : 
    1291                 :    /***** kml *****/
    1292                 : 
    1293             302 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
    1294              10 :         return OpenKml ( pszFilename, bUpdate );
    1295                 : 
    1296                 :     /***** kmz *****/
    1297                 : 
    1298             292 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
    1299               1 :         return OpenKmz ( pszFilename, bUpdate );
    1300                 : 
    1301                 :     else
    1302                 :     {
    1303                 :         char szBuffer[1024+1];
    1304             291 :         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
    1305             291 :         if (fp == NULL)
    1306             173 :             return FALSE;
    1307                 : 
    1308             118 :         int nRead = VSIFReadL(szBuffer, 1, 1024, fp);
    1309             118 :         szBuffer[nRead] = 0;
    1310                 : 
    1311             118 :         VSIFCloseL(fp);
    1312                 : 
    1313                 :         /* Does it look like a zip file ? */
    1314             288 :         if (nRead == 1024 &&
    1315             122 :             szBuffer[0] == 0x50 && szBuffer[1] == 0x4B &&
    1316              48 :             szBuffer[2] == 0x03  && szBuffer[3] == 0x04)
    1317                 :         {
    1318              24 :             CPLString osFilename("/vsizip/");
    1319              24 :             osFilename += pszFilename;
    1320              24 :             if (!CheckIsKMZ(osFilename))
    1321              24 :                 return FALSE;
    1322                 : 
    1323               0 :             return OpenKmz ( pszFilename, bUpdate );
    1324                 :         }
    1325                 : 
    1326              94 :         if (strstr(szBuffer, "<kml>") || strstr(szBuffer, "<kml xmlns="))
    1327               0 :             return OpenKml ( pszFilename, bUpdate );
    1328                 :         
    1329              94 :         return FALSE;
    1330                 :     }
    1331                 : }
    1332                 : 
    1333                 : /******************************************************************************
    1334                 :  method to create a single file .kml ds
    1335                 :  
    1336                 :  Args:          pszFilename     the datasource to create
    1337                 :                 papszOptions    datasource creation options
    1338                 :  
    1339                 :  Returns:       True on success, false on failure
    1340                 : 
    1341                 : ******************************************************************************/
    1342                 : 
    1343               1 : int OGRLIBKMLDataSource::CreateKml (
    1344                 :     const char *pszFilename,
    1345                 :     char **papszOptions )
    1346                 : {
    1347                 : 
    1348               1 :     m_poKmlDSKml = m_poKmlFactory->CreateKml (  );
    1349               1 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1350                 : 
    1351               1 :     m_poKmlDSKml->set_feature ( poKmlDocument );
    1352               1 :     m_poKmlDSContainer = poKmlDocument;
    1353               1 :     m_isKml = TRUE;
    1354               1 :     bUpdated = TRUE;
    1355                 : 
    1356               1 :     return true;
    1357                 : }
    1358                 : 
    1359                 : /******************************************************************************
    1360                 :  method to create a .kmz ds
    1361                 :  
    1362                 :  Args:          pszFilename     the datasource to create
    1363                 :                 papszOptions    datasource creation options
    1364                 :  
    1365                 :  Returns:       True on success, false on failure
    1366                 : 
    1367                 : ******************************************************************************/
    1368                 : 
    1369               1 : int OGRLIBKMLDataSource::CreateKmz (
    1370                 :     const char *pszFilename,
    1371                 :     char **papszOptions )
    1372                 : {
    1373                 : 
    1374                 : 
    1375                 :     /***** create the doc.kml  *****/
    1376                 : 
    1377               1 :     const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1378                 : 
    1379               1 :     if ( !strcmp ( namefield, "yes" ) ) {
    1380               1 :         m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
    1381                 :     }
    1382                 : 
    1383               1 :     pszStylePath = CPLStrdup((char *) "style/style.kml");
    1384                 : 
    1385               1 :     m_isKmz = TRUE;
    1386               1 :     bUpdated = TRUE;
    1387                 : 
    1388               1 :     return TRUE;
    1389                 : }
    1390                 : 
    1391                 : /******************************************************************************
    1392                 :  Method to create a dir datasource
    1393                 :  
    1394                 :  Args:          pszFilename     the datasource to create
    1395                 :                 papszOptions    datasource creation options
    1396                 :  
    1397                 :  Returns:       True on success, false on failure
    1398                 : 
    1399                 : ******************************************************************************/
    1400                 : 
    1401               1 : int OGRLIBKMLDataSource::CreateDir (
    1402                 :     const char *pszFilename,
    1403                 :     char **papszOptions )
    1404                 : {
    1405                 : 
    1406               1 :     if ( VSIMkdir ( pszFilename, 0755 ) ) {
    1407                 :         CPLError ( CE_Failure, CPLE_AppDefined,
    1408               0 :                    "ERROR Creating dir: %s for KML datasource", pszFilename );
    1409               0 :         return FALSE;
    1410                 :     }
    1411                 : 
    1412               1 :     m_isDir = TRUE;
    1413               1 :     bUpdated = TRUE;
    1414                 : 
    1415                 : 
    1416               1 :     const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1417                 : 
    1418               1 :     if ( !strcmp ( namefield, "yes" ) ) {
    1419               1 :         m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
    1420                 :     }
    1421                 : 
    1422               1 :     pszStylePath = CPLStrdup((char *) "style.kml");
    1423                 : 
    1424               1 :     return TRUE;
    1425                 : }
    1426                 : 
    1427                 : 
    1428                 : /******************************************************************************
    1429                 :  method to create a datasource
    1430                 :  
    1431                 :  Args:          pszFilename     the datasource to create
    1432                 :                 papszOptions    datasource creation options
    1433                 :  
    1434                 :  Returns:       True on success, false on failure
    1435                 :  
    1436                 :  env vars:
    1437                 :   LIBKML_USE_DOC.KML         default: yes
    1438                 :  
    1439                 : ******************************************************************************/
    1440                 : 
    1441               3 : int OGRLIBKMLDataSource::Create (
    1442                 :     const char *pszFilename,
    1443                 :     char **papszOptions )
    1444                 : {
    1445                 : 
    1446               3 :     int bResult = FALSE;
    1447                 : 
    1448               3 :     if (strcmp(pszFilename, "/dev/stdout") == 0)
    1449               0 :         pszFilename = "/vsistdout/";
    1450                 : 
    1451               3 :     pszName = CPLStrdup ( pszFilename );
    1452               3 :     bUpdate = TRUE;
    1453                 : 
    1454                 :     /***** kml *****/
    1455                 : 
    1456               3 :     if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
    1457                 :          strncmp(pszFilename, "/vsigzip/", 9) == 0 ||
    1458                 :          EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
    1459               1 :         bResult = CreateKml ( pszFilename, papszOptions );
    1460                 : 
    1461                 :     /***** kmz *****/
    1462                 : 
    1463               2 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
    1464               1 :         bResult = CreateKmz ( pszFilename, papszOptions );
    1465                 : 
    1466                 :     /***** dir *****/
    1467                 : 
    1468                 :     else
    1469               1 :         bResult = CreateDir ( pszFilename, papszOptions );
    1470                 : 
    1471               3 :     return bResult;
    1472                 : }
    1473                 : 
    1474                 : /******************************************************************************
    1475                 :  method to get a layer by index
    1476                 :  
    1477                 :  Args:          iLayer      the index of the layer to get
    1478                 :  
    1479                 :  Returns:       pointer to the layer, or NULL if the layer does not exist
    1480                 : 
    1481                 : ******************************************************************************/
    1482                 : 
    1483              23 : OGRLayer *OGRLIBKMLDataSource::GetLayer (
    1484                 :     int iLayer )
    1485                 : {
    1486              23 :     if ( iLayer < 0 || iLayer >= nLayers )
    1487               2 :         return NULL;
    1488                 :     else
    1489              21 :         return papoLayers[iLayer];
    1490                 : 
    1491                 : }
    1492                 : 
    1493                 : /******************************************************************************
    1494                 :  method to get a layer by name
    1495                 :  
    1496                 :  Args:          pszname     name of the layer to get
    1497                 :  
    1498                 :  Returns:       pointer to the layer, or NULL if the layer does not exist
    1499                 : 
    1500                 : ******************************************************************************/
    1501                 : 
    1502              71 : OGRLayer *OGRLIBKMLDataSource::GetLayerByName (
    1503                 :     const char *pszname )
    1504                 : {
    1505              71 :     int iLayer = 0;
    1506                 : 
    1507             381 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
    1508             380 :         if ( EQUAL ( pszname, papoLayers[iLayer]->GetName (  ) ) )
    1509              70 :             return papoLayers[iLayer];
    1510                 :     }
    1511                 : 
    1512               1 :     return NULL;
    1513                 : }
    1514                 : 
    1515                 : 
    1516                 : /******************************************************************************
    1517                 :  method to DeleteLayers in a .kml datasource
    1518                 :  
    1519                 :  Args:          iLayer  index of the layer to delete
    1520                 :  
    1521                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1522                 : 
    1523                 : ******************************************************************************/
    1524                 : 
    1525               0 : OGRErr OGRLIBKMLDataSource::DeleteLayerKml (
    1526                 :     int iLayer )
    1527                 : {
    1528               0 :     OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
    1529                 : 
    1530                 :     /***** loop over the features *****/
    1531                 : 
    1532               0 :     size_t nKmlFeatures = m_poKmlDSContainer->get_feature_array_size (  );
    1533                 :     size_t iKmlFeature;
    1534                 : 
    1535               0 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
    1536                 :         FeaturePtr poKmlFeat =
    1537               0 :             m_poKmlDSContainer->get_feature_array_at ( iKmlFeature );
    1538                 : 
    1539               0 :         if ( poKmlFeat == poOgrLayer->GetKmlLayer (  ) ) {
    1540               0 :             m_poKmlDSContainer->DeleteFeatureAt ( iKmlFeature );
    1541                 :             break;
    1542                 :         }
    1543                 : 
    1544                 :     }
    1545                 : 
    1546                 : 
    1547               0 :     return OGRERR_NONE;
    1548                 : }
    1549                 : 
    1550                 : /******************************************************************************
    1551                 :  method to DeleteLayers in a .kmz datasource
    1552                 :  
    1553                 :  Args:          iLayer  index of the layer to delete
    1554                 :  
    1555                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1556                 : 
    1557                 : ******************************************************************************/
    1558                 : 
    1559               0 : OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
    1560                 :     int iLayer )
    1561                 : {
    1562               0 :     OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
    1563                 : 
    1564                 :     const char *pszUseDocKml =
    1565               0 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1566                 : 
    1567               0 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
    1568                 : 
    1569                 :         /***** loop over the features *****/
    1570                 : 
    1571               0 :         size_t nKmlFeatures = m_poKmlDocKml->get_feature_array_size (  );
    1572                 :         size_t iKmlFeature;
    1573                 : 
    1574               0 :         for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
    1575                 :             FeaturePtr poKmlFeat =
    1576               0 :                 m_poKmlDocKml->get_feature_array_at ( iKmlFeature );
    1577                 : 
    1578               0 :             if ( poKmlFeat->IsA ( kmldom::Type_NetworkLink ) ) {
    1579               0 :                 NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
    1580                 : 
    1581                 :                 /***** does it have a link? *****/
    1582                 : 
    1583               0 :                 if ( poKmlNetworkLink->has_link (  ) ) {
    1584               0 :                     LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
    1585                 : 
    1586                 :                     /***** does the link have a href? *****/
    1587                 : 
    1588               0 :                     if ( poKmlLink->has_href (  ) ) {
    1589                 :                         kmlengine::Href * poKmlHref =
    1590               0 :                             new kmlengine::Href ( poKmlLink->get_href (  ) );
    1591                 : 
    1592                 :                         /***** is the link relative? *****/
    1593                 : 
    1594               0 :                         if ( poKmlHref->IsRelativePath (  ) ) {
    1595                 : 
    1596                 :                             const char *pszLink =
    1597               0 :                                 poKmlHref->get_path (  ).c_str (  );
    1598                 : 
    1599               0 :                             if ( EQUAL
    1600                 :                                  ( pszLink, poOgrLayer->GetFileName (  ) ) ) {
    1601               0 :                                 m_poKmlDocKml->DeleteFeatureAt ( iKmlFeature );
    1602                 :                                 break;
    1603                 :                             }
    1604                 : 
    1605                 : 
    1606                 :                         }
    1607               0 :                     }
    1608               0 :                 }
    1609                 :             }
    1610                 :         }
    1611                 : 
    1612                 :     }
    1613                 : 
    1614               0 :     return OGRERR_NONE;
    1615                 : }
    1616                 : 
    1617                 : /******************************************************************************
    1618                 :  method to delete a layer in a datasource
    1619                 :  
    1620                 :  Args:          iLayer  index of the layer to delete
    1621                 :  
    1622                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1623                 : 
    1624                 : ******************************************************************************/
    1625                 : 
    1626               0 : OGRErr OGRLIBKMLDataSource::DeleteLayer (
    1627                 :     int iLayer )
    1628                 : {
    1629                 : 
    1630               0 :     if ( !bUpdate )
    1631               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1632                 : 
    1633               0 :     if ( iLayer >= nLayers )
    1634               0 :         return OGRERR_FAILURE;
    1635                 : 
    1636               0 :     if ( IsKml (  ) )
    1637               0 :         DeleteLayerKml ( iLayer );
    1638                 : 
    1639               0 :     else if ( IsKmz (  ) )
    1640               0 :         DeleteLayerKmz ( iLayer );
    1641                 : 
    1642               0 :     else if ( IsDir (  ) ) {
    1643               0 :         DeleteLayerKmz ( iLayer );
    1644                 : 
    1645                 :         /***** delete the file the layer corisponds to *****/
    1646                 : 
    1647                 :         const char *pszFilePath =
    1648               0 :             CPLFormFilename ( pszName, papoLayers[iLayer]->GetFileName (  ),
    1649               0 :                               NULL );
    1650               0 :         VSIStatBufL oStatBufL = { };
    1651               0 :         if ( !VSIStatL ( pszFilePath, &oStatBufL ) ) {
    1652               0 :             if ( VSIUnlink ( pszFilePath ) ) {
    1653                 :                 CPLError ( CE_Failure, CPLE_AppDefined,
    1654                 :                            "ERROR Deleteing Layer %s from filesystem as %s",
    1655               0 :                            papoLayers[iLayer]->GetName (  ), pszFilePath );
    1656                 :             }
    1657                 :         }
    1658                 :     }
    1659                 : 
    1660                 : 
    1661               0 :     delete papoLayers[iLayer];
    1662                 :     memmove ( papoLayers + iLayer, papoLayers + iLayer + 1,
    1663               0 :               sizeof ( void * ) * ( nLayers - iLayer - 1 ) );
    1664               0 :     nLayers--;
    1665               0 :     bUpdated = TRUE;
    1666                 : 
    1667               0 :     return OGRERR_NONE;
    1668                 : }
    1669                 : 
    1670                 : /******************************************************************************
    1671                 :  method to create a layer in a single file .kml
    1672                 :  
    1673                 :  Args:          pszLayerName    name of the layer to create
    1674                 :                 poOgrSRS        the SRS of the layer
    1675                 :                 eGType          the layers geometry type
    1676                 :                 papszOptions    layer creation options
    1677                 :  
    1678                 :  Returns:       return a pointer to the new layer or NULL on failure
    1679                 : 
    1680                 : ******************************************************************************/
    1681                 : 
    1682               2 : OGRLayer *OGRLIBKMLDataSource::CreateLayerKml (
    1683                 :     const char *pszLayerName,
    1684                 :     OGRSpatialReference * poOgrSRS,
    1685                 :     OGRwkbGeometryType eGType,
    1686                 :     char **papszOptions )
    1687                 : {
    1688                 : 
    1689               2 :     OGRLIBKMLLayer *poOgrLayer = NULL;
    1690                 : 
    1691               2 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1692                 : 
    1693               2 :     m_poKmlDSContainer->add_feature ( poKmlDocument );
    1694                 : 
    1695                 :     /***** create the layer *****/
    1696                 : 
    1697                 :     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
    1698               2 :                             NULL, poKmlDocument, "", TRUE, bUpdate, 1 );
    1699                 : 
    1700                 :     /***** add the layer name as a <Name> *****/
    1701                 : 
    1702               2 :     poKmlDocument->set_name ( pszLayerName );
    1703                 : 
    1704               2 :     return ( OGRLayer * ) poOgrLayer;
    1705                 : }
    1706                 : 
    1707                 : /******************************************************************************
    1708                 :  method to create a layer in a .kmz or dir
    1709                 :  
    1710                 :  Args:          pszLayerName    name of the layer to create
    1711                 :                 poOgrSRS        the SRS of the layer
    1712                 :                 eGType          the layers geometry type
    1713                 :                 papszOptions    layer creation options
    1714                 :  
    1715                 :  Returns:       return a pointer to the new layer or NULL on failure
    1716                 : 
    1717                 : ******************************************************************************/
    1718                 : 
    1719               4 : OGRLayer *OGRLIBKMLDataSource::CreateLayerKmz (
    1720                 :     const char *pszLayerName,
    1721                 :     OGRSpatialReference * poOgrSRS,
    1722                 :     OGRwkbGeometryType eGType,
    1723                 :     char **papszOptions )
    1724                 : {
    1725                 : 
    1726                 :     /***** add a network link to doc.kml *****/
    1727                 : 
    1728                 :     const char *pszUseDocKml =
    1729               4 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1730                 : 
    1731               4 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
    1732                 : 
    1733               4 :         DocumentPtr poKmlDocument = AsDocument ( m_poKmlDocKml );
    1734                 : 
    1735               4 :         NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
    1736               4 :         LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
    1737                 : 
    1738               4 :         std::string oHref;
    1739               4 :         oHref.append ( pszLayerName );
    1740               4 :         oHref.append ( ".kml" );
    1741               4 :         poKmlLink->set_href ( oHref );
    1742                 : 
    1743               4 :         poKmlNetLink->set_link ( poKmlLink );
    1744               4 :         poKmlDocument->add_feature ( poKmlNetLink );
    1745                 : 
    1746                 :     }
    1747                 : 
    1748                 :     /***** create the layer *****/
    1749                 : 
    1750               4 :     OGRLIBKMLLayer *poOgrLayer = NULL;
    1751                 : 
    1752               4 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1753                 : 
    1754                 :     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
    1755                 :                             NULL, poKmlDocument,
    1756                 :                             CPLFormFilename ( NULL, pszLayerName, ".kml" ),
    1757               4 :                             TRUE, bUpdate, 1 );
    1758                 : 
    1759                 :     /***** add the layer name as a <Name> *****/
    1760                 : 
    1761               4 :     poKmlDocument->set_name ( pszLayerName );
    1762                 : 
    1763               4 :     return ( OGRLayer * ) poOgrLayer;
    1764                 : }
    1765                 : 
    1766                 : /******************************************************************************
    1767                 :  CreateLayer()
    1768                 :  
    1769                 :  Args:          pszLayerName    name of the layer to create
    1770                 :                 poOgrSRS        the SRS of the layer
    1771                 :                 eGType          the layers geometry type
    1772                 :                 papszOptions    layer creation options
    1773                 :  
    1774                 :  Returns:       return a pointer to the new layer or NULL on failure
    1775                 : 
    1776                 : ******************************************************************************/
    1777                 : 
    1778               6 : OGRLayer *OGRLIBKMLDataSource::CreateLayer (
    1779                 :     const char *pszLayerName,
    1780                 :     OGRSpatialReference * poOgrSRS,
    1781                 :     OGRwkbGeometryType eGType,
    1782                 :     char **papszOptions )
    1783                 : {
    1784                 : 
    1785               6 :     if ( !bUpdate )
    1786               0 :         return NULL;
    1787                 : 
    1788               6 :     OGRLayer *poOgrLayer = NULL;
    1789                 : 
    1790                 :     /***** kml DS *****/
    1791                 : 
    1792               6 :     if ( IsKml (  ) ) {
    1793                 :         poOgrLayer = CreateLayerKml ( pszLayerName, poOgrSRS,
    1794               2 :                                       eGType, papszOptions );
    1795                 : 
    1796                 :     }
    1797                 : 
    1798               4 :     else if ( IsKmz (  ) || IsDir (  ) ) {
    1799                 :         poOgrLayer = CreateLayerKmz ( pszLayerName, poOgrSRS,
    1800               4 :                                       eGType, papszOptions );
    1801                 : 
    1802                 :     }
    1803                 : 
    1804                 : 
    1805                 : 
    1806                 : 
    1807                 :     /***** mark the dataset as updated *****/
    1808                 : 
    1809               6 :     if ( poOgrLayer )
    1810               6 :         bUpdated = TRUE;
    1811                 : 
    1812               6 :     return poOgrLayer;
    1813                 : }
    1814                 : 
    1815                 : /******************************************************************************
    1816                 :  method to get a datasources style table
    1817                 :  
    1818                 :  Args:          none
    1819                 :  
    1820                 :  Returns:       pointer to the datasources style table, or NULL if it does
    1821                 :                 not have one
    1822                 : 
    1823                 : ******************************************************************************/
    1824                 : 
    1825               0 : OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
    1826                 :      )
    1827                 : {
    1828                 : 
    1829               0 :     return m_poStyleTable;
    1830                 : }
    1831                 : 
    1832                 : /******************************************************************************
    1833                 :   method to write a style table to a single file .kml ds
    1834                 :  
    1835                 :  Args:          poStyleTable    pointer to the style table to add
    1836                 :  
    1837                 :  Returns:       nothing
    1838                 : 
    1839                 : ******************************************************************************/
    1840                 : 
    1841               0 : void OGRLIBKMLDataSource::SetStyleTable2Kml (
    1842                 :     OGRStyleTable * poStyleTable )
    1843                 : {
    1844                 : 
    1845                 :     /***** delete all the styles *****/
    1846                 : 
    1847               0 :     DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
    1848               0 :     size_t nKmlStyles = poKmlDocument->get_styleselector_array_size (  );
    1849                 :     int iKmlStyle;
    1850                 : 
    1851               0 :     for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
    1852               0 :         poKmlDocument->DeleteStyleSelectorAt ( iKmlStyle );
    1853                 :     }
    1854                 : 
    1855                 :     /***** add the new style table to the document *****/
    1856                 : 
    1857                 :     styletable2kml ( poStyleTable, m_poKmlFactory,
    1858               0 :                      AsContainer ( poKmlDocument ) );
    1859                 : 
    1860               0 :     return;
    1861                 : }
    1862                 : 
    1863                 : /******************************************************************************
    1864                 :  method to write a style table to a kmz ds
    1865                 :  
    1866                 :  Args:          poStyleTable    pointer to the style table to add
    1867                 :  
    1868                 :  Returns:       nothing
    1869                 : 
    1870                 : ******************************************************************************/
    1871                 : 
    1872               0 : void OGRLIBKMLDataSource::SetStyleTable2Kmz (
    1873                 :     OGRStyleTable * poStyleTable )
    1874                 : {
    1875                 : 
    1876                 :     /***** replace the style document with a new one *****/
    1877                 : 
    1878               0 :     m_poKmlStyleKml = m_poKmlFactory->CreateDocument (  );
    1879                 : 
    1880               0 :     styletable2kml ( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
    1881                 : 
    1882                 :     return;
    1883                 : }
    1884                 : 
    1885                 : /******************************************************************************
    1886                 :  method to write a style table to a datasource
    1887                 :  
    1888                 :  Args:          poStyleTable    pointer to the style table to add
    1889                 :  
    1890                 :  Returns:       nothing
    1891                 : 
    1892                 :  note: this method assumes ownership of the style table
    1893                 :  
    1894                 : ******************************************************************************/
    1895                 : 
    1896               0 : void OGRLIBKMLDataSource::SetStyleTableDirectly (
    1897                 :     OGRStyleTable * poStyleTable )
    1898                 : {
    1899                 : 
    1900               0 :     if ( !bUpdate )
    1901               0 :         return;
    1902                 : 
    1903               0 :     if ( m_poStyleTable )
    1904               0 :         delete m_poStyleTable;
    1905                 : 
    1906               0 :     m_poStyleTable = poStyleTable;
    1907                 : 
    1908                 :     /***** a kml datasource? *****/
    1909                 : 
    1910               0 :     if ( IsKml (  ) )
    1911               0 :         SetStyleTable2Kml ( m_poStyleTable );
    1912                 : 
    1913               0 :     else if ( IsKmz (  ) || IsDir (  ) )
    1914               0 :         SetStyleTable2Kmz ( m_poStyleTable );
    1915                 : 
    1916               0 :     bUpdated = TRUE;
    1917                 : 
    1918                 : 
    1919                 : 
    1920                 : 
    1921               0 :     return;
    1922                 : }
    1923                 : 
    1924                 : /******************************************************************************
    1925                 :  method to write a style table to a datasource
    1926                 :  
    1927                 :  Args:          poStyleTable    pointer to the style table to add
    1928                 :  
    1929                 :  Returns:       nothing
    1930                 : 
    1931                 :  note:  this method copys the style table, and the user will still be
    1932                 :         responsible for its destruction
    1933                 : 
    1934                 : ******************************************************************************/
    1935                 : 
    1936               0 : void OGRLIBKMLDataSource::SetStyleTable (
    1937                 :     OGRStyleTable * poStyleTable )
    1938                 : {
    1939                 : 
    1940               0 :     if ( !bUpdate )
    1941               0 :         return;
    1942                 : 
    1943               0 :     if ( poStyleTable )
    1944               0 :         SetStyleTableDirectly ( poStyleTable->Clone (  ) );
    1945                 :     else
    1946               0 :         SetStyleTableDirectly ( NULL );
    1947               0 :     return;
    1948                 : }
    1949                 : 
    1950                 : 
    1951                 : /******************************************************************************
    1952                 :  Test if capability is available.
    1953                 : 
    1954                 :  Args:          pszCap  datasource capability name to test
    1955                 :  
    1956                 :  Returns:       nothing
    1957                 : 
    1958                 :  ODsCCreateLayer: True if this datasource can create new layers.
    1959                 :  ODsCDeleteLayer: True if this datasource can delete existing layers.
    1960                 :  
    1961                 : ******************************************************************************/
    1962                 : 
    1963               1 : int OGRLIBKMLDataSource::TestCapability (
    1964                 :     const char *pszCap )
    1965                 : {
    1966                 : 
    1967               1 :     if ( EQUAL ( pszCap, ODsCCreateLayer ) )
    1968               0 :         return bUpdate;
    1969               1 :     else if ( EQUAL ( pszCap, ODsCDeleteLayer ) )
    1970               0 :         return bUpdate;
    1971                 :     else
    1972               1 :         return FALSE;
    1973                 : 
    1974            2139 : }

Generated by: LCOV version 1.7