LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/libkml - ogrlibkmldatasource.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 514
Code covered: 30.9 % Executed lines: 159

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

Generated by: LTP GCOV extension version 1.5