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-12-26 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         1122976 : GDALMultiDomainMetadata::GDALMultiDomainMetadata()
      42                 : 
      43                 : {
      44         1122976 :     papszDomainList = NULL;
      45         1122976 :     papoMetadataLists = NULL;
      46         1122976 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                      ~GDALMultiDomainMetadata()                      */
      50                 : /************************************************************************/
      51                 : 
      52         1120525 : GDALMultiDomainMetadata::~GDALMultiDomainMetadata()
      53                 : 
      54                 : {
      55         1120525 :     Clear();
      56         1120525 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                               Clear()                                */
      60                 : /************************************************************************/
      61                 : 
      62         1120525 : void GDALMultiDomainMetadata::Clear()
      63                 : 
      64                 : {
      65                 :     int i, nDomainCount;
      66                 : 
      67         1120525 :     nDomainCount = CSLCount( papszDomainList );
      68         1120525 :     CSLDestroy( papszDomainList );
      69         1120525 :     papszDomainList = NULL;
      70                 : 
      71         1202875 :     for( i = 0; i < nDomainCount; i++ )
      72                 :     {
      73           82350 :         delete papoMetadataLists[i];
      74                 :     }
      75         1120525 :     CPLFree( papoMetadataLists );
      76         1120525 :     papoMetadataLists = NULL;
      77         1120525 : }
      78                 : 
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                            GetMetadata()                             */
      82                 : /************************************************************************/
      83                 : 
      84           16772 : char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
      85                 : 
      86                 : {
      87           16772 :     if( pszDomain == NULL )
      88             856 :         pszDomain = "";
      89                 : 
      90           16772 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
      91                 : 
      92           16772 :     if( iDomain == -1 )
      93            9004 :         return NULL;
      94                 :     else
      95            7768 :         return papoMetadataLists[iDomain]->List();
      96                 : }
      97                 : 
      98                 : /************************************************************************/
      99                 : /*                            SetMetadata()                             */
     100                 : /************************************************************************/
     101                 : 
     102           85079 : CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata, 
     103                 :                                              const char *pszDomain )
     104                 : 
     105                 : {
     106           85079 :     if( pszDomain == NULL )
     107             279 :         pszDomain = "";
     108                 : 
     109           85079 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     110                 : 
     111           85079 :     if( iDomain == -1 )
     112                 :     {
     113                 :         int nDomainCount;
     114                 : 
     115           84782 :         papszDomainList = CSLAddString( papszDomainList, pszDomain );
     116           84782 :         nDomainCount = CSLCount( papszDomainList );
     117                 : 
     118                 :         papoMetadataLists = (CPLStringList **) 
     119           84782 :             CPLRealloc( papoMetadataLists, sizeof(void*)*(nDomainCount+1) );
     120           84782 :         papoMetadataLists[nDomainCount] = NULL;
     121           84782 :         papoMetadataLists[nDomainCount-1] = new CPLStringList();
     122           84782 :         iDomain = nDomainCount-1;
     123                 :     }
     124                 : 
     125           85079 :     papoMetadataLists[iDomain]->Assign( CSLDuplicate( papszMetadata ) );
     126                 : 
     127                 :     // we want to mark name/value pair domains as being sorted for fast
     128                 :     // access.
     129           85079 :     if( !EQUALN(pszDomain,"xml:",4) && !EQUAL(pszDomain, "SUBDATASETS") )
     130           84981 :         papoMetadataLists[iDomain]->Sort();
     131                 : 
     132           85079 :     return CE_None;
     133                 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                          GetMetadataItem()                           */
     137                 : /************************************************************************/
     138                 : 
     139           65001 : const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName, 
     140                 :                                                       const char *pszDomain )
     141                 : 
     142                 : {
     143           65001 :     if( pszDomain == NULL )
     144            1184 :         pszDomain = "";
     145                 : 
     146           65001 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     147                 : 
     148           65001 :     if( iDomain == -1 )
     149           42999 :         return NULL;
     150                 :     else
     151           22002 :         return papoMetadataLists[iDomain]->FetchNameValue( pszName );
     152                 : }
     153                 : 
     154                 : /************************************************************************/
     155                 : /*                          SetMetadataItem()                           */
     156                 : /************************************************************************/
     157                 : 
     158          355169 : CPLErr GDALMultiDomainMetadata::SetMetadataItem( const char *pszName,
     159                 :                                                  const char *pszValue,
     160                 :                                                  const char *pszDomain )
     161                 : 
     162                 : {
     163          355169 :     if( pszDomain == NULL )
     164             157 :         pszDomain = "";
     165                 : 
     166                 : /* -------------------------------------------------------------------- */
     167                 : /*      Create the domain if it does not already exist.                 */
     168                 : /* -------------------------------------------------------------------- */
     169          355169 :     int iDomain = CSLFindString( papszDomainList, pszDomain );
     170                 : 
     171          355169 :     if( iDomain == -1 )
     172                 :     {
     173           80870 :         SetMetadata( NULL, pszDomain );
     174           80870 :         iDomain = CSLFindString( papszDomainList, pszDomain );
     175                 :     }
     176                 : 
     177                 : /* -------------------------------------------------------------------- */
     178                 : /*      Set the value in the domain list.                               */
     179                 : /* -------------------------------------------------------------------- */
     180          355169 :     papoMetadataLists[iDomain]->SetNameValue( pszName, pszValue );
     181                 : 
     182          355169 :     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            1884 : 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            8405 :     for( psMetadata = psTree->psChild; 
     201                 :          psMetadata != NULL; psMetadata = psMetadata->psNext )
     202                 :     {
     203                 :         CPLXMLNode *psMDI;
     204                 :         const char *pszDomain, *pszFormat;
     205                 : 
     206            6521 :         if( psMetadata->eType != CXT_Element
     207                 :             || !EQUAL(psMetadata->pszValue,"Metadata") )
     208            5674 :             continue;
     209                 : 
     210             847 :         pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
     211             847 :         pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
     212                 : 
     213                 :         // Make sure we have a CPLStringList for this domain, 
     214                 :         // without wiping out an existing one.
     215             847 :         if( GetMetadata( pszDomain ) == NULL )  
     216             518 :             SetMetadata( NULL, pszDomain );
     217                 : 
     218             847 :         int iDomain = CSLFindString( papszDomainList, pszDomain );
     219             847 :         CPLAssert( iDomain != -1 );
     220                 :         
     221             847 :         CPLStringList *poMDList = papoMetadataLists[iDomain];
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      XML format subdocuments.                                        */
     225                 : /* -------------------------------------------------------------------- */
     226             847 :         if( EQUAL(pszFormat,"xml") )
     227                 :         {
     228                 :             CPLXMLNode *psSubDoc;
     229                 : 
     230                 :             /* find first non-attribute child of current element */
     231               9 :             psSubDoc = psMetadata->psChild;
     232              36 :             while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute )
     233              18 :                 psSubDoc = psSubDoc->psNext;
     234                 :             
     235               9 :             char *pszDoc = CPLSerializeXMLTree( psSubDoc );
     236                 : 
     237               9 :             poMDList->AddStringDirectly( pszDoc );
     238                 :         }
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Name value format.                                              */
     242                 : /*      <MDI key="...">value_Text</MDI>                                 */
     243                 : /* -------------------------------------------------------------------- */
     244                 :         else
     245                 :         {
     246            4732 :             for( psMDI = psMetadata->psChild; psMDI != NULL;
     247                 :                  psMDI = psMDI->psNext )
     248                 :             {
     249            3894 :                 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            1275 :                     continue;
     256                 : 
     257            2619 :                 char* pszName = psMDI->psChild->psChild->pszValue;
     258            2619 :                 char* pszValue = psMDI->psChild->psNext->pszValue;
     259            2619 :                 if( pszName != NULL && pszValue != NULL )
     260            2619 :                     poMDList->SetNameValue( pszName, pszValue );
     261                 :             }
     262                 :         }
     263                 :     }
     264                 : 
     265            1884 :     return CSLCount(papszDomainList) != 0;
     266                 : }
     267                 : 
     268                 : /************************************************************************/
     269                 : /*                             Serialize()                              */
     270                 : /************************************************************************/
     271                 : 
     272            2331 : CPLXMLNode *GDALMultiDomainMetadata::Serialize()
     273                 : 
     274                 : {
     275            2331 :     CPLXMLNode *psFirst = NULL;
     276                 : 
     277            5883 :     for( int iDomain = 0; 
     278            2335 :          papszDomainList != NULL && papszDomainList[iDomain] != NULL; 
     279                 :          iDomain++)
     280                 :     {
     281            1217 :         char **papszMD = papoMetadataLists[iDomain]->List();
     282                 :         CPLXMLNode *psMD;
     283            1217 :         int bFormatXML = FALSE;
     284                 :         
     285            1217 :         psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
     286                 : 
     287            1217 :         if( strlen( papszDomainList[iDomain] ) > 0 )
     288                 :             CPLCreateXMLNode( 
     289                 :                 CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ), 
     290             214 :                 CXT_Text, papszDomainList[iDomain] );
     291                 : 
     292            1217 :         if( EQUALN(papszDomainList[iDomain],"xml:",4) 
     293                 :             && CSLCount(papszMD) == 1 )
     294                 :         {
     295               6 :             CPLXMLNode *psValueAsXML = CPLParseXMLString( papszMD[0] );
     296               6 :             if( psValueAsXML != NULL )
     297                 :             {
     298               6 :                 bFormatXML = TRUE;
     299                 : 
     300                 :                 CPLCreateXMLNode( 
     301                 :                     CPLCreateXMLNode( psMD, CXT_Attribute, "format" ), 
     302               6 :                     CXT_Text, "xml" );
     303                 :                 
     304               6 :                 CPLAddXMLChild( psMD, psValueAsXML );
     305                 :             }
     306                 :         }
     307                 : 
     308            1217 :         if( !bFormatXML )
     309                 :         {
     310            1211 :             CPLXMLNode* psLastChild = NULL;
     311            1211 :             if( psMD->psChild != NULL )
     312                 :             {
     313             208 :                 psLastChild = psMD->psChild;
     314             416 :                 while( psLastChild->psNext != NULL )
     315               0 :                     psLastChild = psLastChild->psNext; 
     316                 :             }
     317            5191 :             for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     318                 :             {
     319                 :                 const char *pszRawValue;
     320            3980 :                 char *pszKey = NULL;
     321                 :                 CPLXMLNode *psMDI;
     322                 :                 
     323            3980 :                 pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
     324                 :                 
     325            3980 :                 psMDI = CPLCreateXMLNode( NULL, CXT_Element, "MDI" );
     326            3980 :                 if( psLastChild == NULL )
     327             776 :                     psMD->psChild = psMDI;
     328                 :                 else
     329            3204 :                     psLastChild->psNext = psMDI;
     330            3980 :                 psLastChild = psMDI;
     331                 : 
     332            3980 :                 CPLSetXMLValue( psMDI, "#key", pszKey );
     333            3980 :                 CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
     334                 :                 
     335            3980 :                 CPLFree( pszKey );
     336                 :             }
     337                 :         }
     338                 :             
     339            1217 :         if( psFirst == NULL )
     340            1118 :             psFirst = psMD;
     341                 :         else
     342              99 :             CPLAddXMLSibling( psFirst, psMD );
     343                 :     }
     344                 : 
     345            2331 :     return psFirst;
     346                 : }
     347                 : 

Generated by: LCOV version 1.7