LCOV - code coverage report
Current view: directory - gcore - gdalmultidomainmetadata.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 115 114 99.1 %
Date: 2012-04-28 Functions: 11 9 81.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Implementation of GDALMultiDomainMetadata class.  This class
       6                 :  *           manages metadata items for a variable list of domains. 
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal_pam.h"
      32                 : #include "cpl_string.h"
      33                 : #include <map>
      34                 : 
      35                 : CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                      GDALMultiDomainMetadata()                       */
      39                 : /************************************************************************/
      40                 : 
      41         2231009 : GDALMultiDomainMetadata::GDALMultiDomainMetadata()
      42                 : 
      43                 : {
      44         2231009 :     papszDomainList = NULL;
      45         2231009 :     papoMetadataLists = NULL;
      46         2231009 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                      ~GDALMultiDomainMetadata()                      */
      50                 : /************************************************************************/
      51                 : 
      52         2226437 : GDALMultiDomainMetadata::~GDALMultiDomainMetadata()
      53                 : 
      54                 : {
      55         2226437 :     Clear();
      56         2226437 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                               Clear()                                */
      60                 : /************************************************************************/
      61                 : 
      62         2226437 : void GDALMultiDomainMetadata::Clear()
      63                 : 
      64                 : {
      65                 :     int i, nDomainCount;
      66                 : 
      67         2226437 :     nDomainCount = CSLCount( papszDomainList );
      68         2226437 :     CSLDestroy( papszDomainList );
      69         2226437 :     papszDomainList = NULL;
      70                 : 
      71         2384151 :     for( i = 0; i < nDomainCount; i++ )
      72                 :     {
      73          157714 :         delete papoMetadataLists[i];
      74                 :     }
      75         2226437 :     CPLFree( papoMetadataLists );
      76         2226437 :     papoMetadataLists = NULL;
      77         2226437 : }
      78                 : 
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                            GetMetadata()                             */
      82                 : /************************************************************************/
      83                 : 
      84           31253 : char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
      85                 : 
      86                 : {
      87           31253 :     if( pszDomain == NULL )
      88            1622 :         pszDomain = "";
      89                 : 
      90           31253 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
      91                 : 
      92           31253 :     if( iDomain == -1 )
      93           16866 :         return NULL;
      94                 :     else
      95           14387 :         return papoMetadataLists[iDomain]->List();
      96                 : }
      97                 : 
      98                 : /************************************************************************/
      99                 : /*                            SetMetadata()                             */
     100                 : /************************************************************************/
     101                 : 
     102          162792 : CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata, 
     103                 :                                              const char *pszDomain )
     104                 : 
     105                 : {
     106          162792 :     if( pszDomain == NULL )
     107             548 :         pszDomain = "";
     108                 : 
     109          162792 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     110                 : 
     111          162792 :     if( iDomain == -1 )
     112                 :     {
     113                 :         int nDomainCount;
     114                 : 
     115          162250 :         papszDomainList = CSLAddString( papszDomainList, pszDomain );
     116          162250 :         nDomainCount = CSLCount( papszDomainList );
     117                 : 
     118                 :         papoMetadataLists = (CPLStringList **) 
     119          162250 :             CPLRealloc( papoMetadataLists, sizeof(void*)*(nDomainCount+1) );
     120          162250 :         papoMetadataLists[nDomainCount] = NULL;
     121          162250 :         papoMetadataLists[nDomainCount-1] = new CPLStringList();
     122          162250 :         iDomain = nDomainCount-1;
     123                 :     }
     124                 : 
     125          162792 :     papoMetadataLists[iDomain]->Assign( CSLDuplicate( papszMetadata ) );
     126                 : 
     127                 :     // we want to mark name/value pair domains as being sorted for fast
     128                 :     // access.
     129          162792 :     if( !EQUALN(pszDomain,"xml:",4) && !EQUAL(pszDomain, "SUBDATASETS") )
     130          162610 :         papoMetadataLists[iDomain]->Sort();
     131                 : 
     132          162792 :     return CE_None;
     133                 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                          GetMetadataItem()                           */
     137                 : /************************************************************************/
     138                 : 
     139          108052 : const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName, 
     140                 :                                                       const char *pszDomain )
     141                 : 
     142                 : {
     143          108052 :     if( pszDomain == NULL )
     144            2330 :         pszDomain = "";
     145                 : 
     146          108052 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     147                 : 
     148          108052 :     if( iDomain == -1 )
     149           66850 :         return NULL;
     150                 :     else
     151           41202 :         return papoMetadataLists[iDomain]->FetchNameValue( pszName );
     152                 : }
     153                 : 
     154                 : /************************************************************************/
     155                 : /*                          SetMetadataItem()                           */
     156                 : /************************************************************************/
     157                 : 
     158          678080 : CPLErr GDALMultiDomainMetadata::SetMetadataItem( const char *pszName,
     159                 :                                                  const char *pszValue,
     160                 :                                                  const char *pszDomain )
     161                 : 
     162                 : {
     163          678080 :     if( pszDomain == NULL )
     164             262 :         pszDomain = "";
     165                 : 
     166                 : /* -------------------------------------------------------------------- */
     167                 : /*      Create the domain if it does not already exist.                 */
     168                 : /* -------------------------------------------------------------------- */
     169          678080 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     170                 : 
     171          678080 :     if( iDomain == -1 )
     172                 :     {
     173          154818 :         SetMetadata( NULL, pszDomain );
     174          154818 :         iDomain = CSLFindString( papszDomainList, pszDomain );
     175                 :     }
     176                 : 
     177                 : /* -------------------------------------------------------------------- */
     178                 : /*      Set the value in the domain list.                               */
     179                 : /* -------------------------------------------------------------------- */
     180          678080 :     papoMetadataLists[iDomain]->SetNameValue( pszName, pszValue );
     181                 : 
     182          678080 :     return CE_None;
     183                 : }
     184                 : 
     185                 : /************************************************************************/
     186                 : /*                              XMLInit()                               */
     187                 : /*                                                                      */
     188                 : /*      This method should be invoked on the parent of the              */
     189                 : /*      <Metadata> elements.                                            */
     190                 : /************************************************************************/
     191                 : 
     192            3272 : int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
     193                 : 
     194                 : {
     195                 :     CPLXMLNode *psMetadata;
     196                 : 
     197                 : /* ==================================================================== */
     198                 : /*      Process all <Metadata> elements, each for one domain.           */
     199                 : /* ==================================================================== */
     200           14731 :     for( psMetadata = psTree->psChild; 
     201                 :          psMetadata != NULL; psMetadata = psMetadata->psNext )
     202                 :     {
     203                 :         CPLXMLNode *psMDI;
     204                 :         const char *pszDomain, *pszFormat;
     205                 : 
     206           11459 :         if( psMetadata->eType != CXT_Element
     207                 :             || !EQUAL(psMetadata->pszValue,"Metadata") )
     208            9802 :             continue;
     209                 : 
     210            1657 :         pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
     211            1657 :         pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
     212                 : 
     213                 :         // Make sure we have a CPLStringList for this domain, 
     214                 :         // without wiping out an existing one.
     215            1657 :         if( GetMetadata( pszDomain ) == NULL )  
     216            1028 :             SetMetadata( NULL, pszDomain );
     217                 : 
     218            1657 :         int iDomain = CSLFindString( papszDomainList, pszDomain );
     219            1657 :         CPLAssert( iDomain != -1 );
     220                 :         
     221            1657 :         CPLStringList *poMDList = papoMetadataLists[iDomain];
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      XML format subdocuments.                                        */
     225                 : /* -------------------------------------------------------------------- */
     226            1657 :         if( EQUAL(pszFormat,"xml") )
     227                 :         {
     228                 :             CPLXMLNode *psSubDoc;
     229                 : 
     230                 :             /* find first non-attribute child of current element */
     231              18 :             psSubDoc = psMetadata->psChild;
     232              72 :             while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute )
     233              36 :                 psSubDoc = psSubDoc->psNext;
     234                 :             
     235              18 :             char *pszDoc = CPLSerializeXMLTree( psSubDoc );
     236                 : 
     237              18 :             poMDList->AddStringDirectly( pszDoc );
     238                 :         }
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Name value format.                                              */
     242                 : /*      <MDI key="...">value_Text</MDI>                                 */
     243                 : /* -------------------------------------------------------------------- */
     244                 :         else
     245                 :         {
     246            9298 :             for( psMDI = psMetadata->psChild; psMDI != NULL;
     247                 :                  psMDI = psMDI->psNext )
     248                 :             {
     249            7659 :                 if( !EQUAL(psMDI->pszValue,"MDI")
     250                 :                     || psMDI->eType != CXT_Element
     251                 :                     || psMDI->psChild == NULL
     252                 :                     || psMDI->psChild->psNext == NULL
     253                 :                     || psMDI->psChild->eType != CXT_Attribute
     254                 :                     || psMDI->psChild->psChild == NULL )
     255            2516 :                     continue;
     256                 : 
     257            5143 :                 char* pszName = psMDI->psChild->psChild->pszValue;
     258            5143 :                 char* pszValue = psMDI->psChild->psNext->pszValue;
     259            5143 :                 if( pszName != NULL && pszValue != NULL )
     260            5143 :                     poMDList->SetNameValue( pszName, pszValue );
     261                 :             }
     262                 :         }
     263                 :     }
     264                 : 
     265            3272 :     return CSLCount(papszDomainList) != 0;
     266                 : }
     267                 : 
     268                 : /************************************************************************/
     269                 : /*                             Serialize()                              */
     270                 : /************************************************************************/
     271                 : 
     272            4606 : CPLXMLNode *GDALMultiDomainMetadata::Serialize()
     273                 : 
     274                 : {
     275            4606 :     CPLXMLNode *psFirst = NULL;
     276                 : 
     277           11428 :     for( int iDomain = 0; 
     278            4494 :          papszDomainList != NULL && papszDomainList[iDomain] != NULL; 
     279                 :          iDomain++)
     280                 :     {
     281            2328 :         char **papszMD = papoMetadataLists[iDomain]->List();
     282                 :         CPLXMLNode *psMD;
     283            2328 :         int bFormatXML = FALSE;
     284                 :         
     285            2328 :         psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
     286                 : 
     287            2328 :         if( strlen( papszDomainList[iDomain] ) > 0 )
     288                 :             CPLCreateXMLNode( 
     289                 :                 CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ), 
     290             368 :                 CXT_Text, papszDomainList[iDomain] );
     291                 : 
     292            2328 :         if( EQUALN(papszDomainList[iDomain],"xml:",4) 
     293                 :             && CSLCount(papszMD) == 1 )
     294                 :         {
     295              12 :             CPLXMLNode *psValueAsXML = CPLParseXMLString( papszMD[0] );
     296              12 :             if( psValueAsXML != NULL )
     297                 :             {
     298              12 :                 bFormatXML = TRUE;
     299                 : 
     300                 :                 CPLCreateXMLNode( 
     301                 :                     CPLCreateXMLNode( psMD, CXT_Attribute, "format" ), 
     302              12 :                     CXT_Text, "xml" );
     303                 :                 
     304              12 :                 CPLAddXMLChild( psMD, psValueAsXML );
     305                 :             }
     306                 :         }
     307                 : 
     308            2328 :         if( !bFormatXML )
     309                 :         {
     310            2316 :             CPLXMLNode* psLastChild = NULL;
     311            2316 :             if( psMD->psChild != NULL )
     312                 :             {
     313             356 :                 psLastChild = psMD->psChild;
     314             712 :                 while( psLastChild->psNext != NULL )
     315               0 :                     psLastChild = psLastChild->psNext; 
     316                 :             }
     317            9878 :             for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     318                 :             {
     319                 :                 const char *pszRawValue;
     320            7562 :                 char *pszKey = NULL;
     321                 :                 CPLXMLNode *psMDI;
     322                 :                 
     323            7562 :                 pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
     324                 :                 
     325            7562 :                 psMDI = CPLCreateXMLNode( NULL, CXT_Element, "MDI" );
     326            7562 :                 if( psLastChild == NULL )
     327            1516 :                     psMD->psChild = psMDI;
     328                 :                 else
     329            6046 :                     psLastChild->psNext = psMDI;
     330            7562 :                 psLastChild = psMDI;
     331                 : 
     332            7562 :                 CPLSetXMLValue( psMDI, "#key", pszKey );
     333            7562 :                 CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
     334                 :                 
     335            7562 :                 CPLFree( pszKey );
     336                 :             }
     337                 :         }
     338                 :             
     339            2328 :         if( psFirst == NULL )
     340            2166 :             psFirst = psMD;
     341                 :         else
     342             162 :             CPLAddXMLSibling( psFirst, psMD );
     343                 :     }
     344                 : 
     345            4606 :     return psFirst;
     346                 : }
     347                 : 

Generated by: LCOV version 1.7