1 /******************************************************************************
2  *
3  * Project:  GDAL Core
4  * Purpose:  Read metadata from Resurs-DK1 imagery.
5  * Author:   Alexander Lisovenko
6  * Author:   Dmitry Baryshnikov, polimax@mail.ru
7  *
8  ******************************************************************************
9  * Copyright (c) 2014-2015 NextGIS <info@nextgis.ru>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #include "cpl_port.h"
31 #include "reader_rdk1.h"
32 
33 #include <cstdio>
34 
35 #include "cpl_error.h"
36 #include "cpl_minixml.h"
37 #include "cpl_string.h"
38 #include "gdal_priv.h"
39 
40 CPL_CVSID("$Id: reader_rdk1.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
41 
42 /**
43  * GDALMDReaderResursDK1()
44  */
GDALMDReaderResursDK1(const char * pszPath,char ** papszSiblingFiles)45 GDALMDReaderResursDK1::GDALMDReaderResursDK1(const char *pszPath,
46                                              char **papszSiblingFiles) :
47     GDALMDReaderBase(pszPath, papszSiblingFiles),
48     m_osXMLSourceFilename( GDALFindAssociatedFile( pszPath, "XML",
49                                                     papszSiblingFiles, 0 ) )
50 {
51     if( !m_osXMLSourceFilename.empty() )
52         CPLDebug( "MDReaderResursDK1", "XML Filename: %s",
53                   m_osXMLSourceFilename.c_str() );
54 }
55 
56 /**
57  * ~GDALMDReaderResursDK1()
58  */
~GDALMDReaderResursDK1()59 GDALMDReaderResursDK1::~GDALMDReaderResursDK1()
60 {
61 }
62 
63 /**
64  * HasRequiredFiles()
65  */
HasRequiredFiles() const66 bool GDALMDReaderResursDK1::HasRequiredFiles() const
67 {
68     // check <MSP_ROOT>
69     if (!m_osXMLSourceFilename.empty() &&
70             GDALCheckFileHeader(m_osXMLSourceFilename, "<MSP_ROOT>"))
71         return true;
72 
73     return false;
74 }
75 
76 /**
77  * GetMetadataFiles()
78  */
GetMetadataFiles() const79 char** GDALMDReaderResursDK1::GetMetadataFiles() const
80 {
81     char **papszFileList = nullptr;
82     if(!m_osXMLSourceFilename.empty())
83         papszFileList= CSLAddString( papszFileList, m_osXMLSourceFilename );
84 
85     return papszFileList;
86 }
87 
88 /**
89  * LoadMetadata()
90  */
LoadMetadata()91 void GDALMDReaderResursDK1::LoadMetadata()
92 {
93     if(m_bIsMetadataLoad)
94         return;
95 
96     if (!m_osXMLSourceFilename.empty())
97     {
98         CPLXMLNode* psNode = CPLParseXMLFile(m_osXMLSourceFilename);
99 
100         if(psNode != nullptr)
101         {
102             CPLXMLNode* pMSPRootNode = CPLSearchXMLNode(psNode, "=MSP_ROOT");
103 
104             if(pMSPRootNode != nullptr)
105             {
106                 m_papszIMDMD = ReadXMLToList(pMSPRootNode, m_papszIMDMD, "MSP_ROOT");
107             }
108             CPLDestroyXMLNode(psNode);
109         }
110     }
111 
112     m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "MSP");
113 
114     m_bIsMetadataLoad = true;
115 
116     if(nullptr == m_papszIMDMD)
117     {
118         return;
119     }
120 
121     //extract imagery metadata
122     const char* pszSatId = CSLFetchNameValue(m_papszIMDMD, "MSP_ROOT.cCodeKA");
123     if(nullptr != pszSatId)
124     {
125         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
126                                            CPLStripQuotes(pszSatId));
127     }
128 
129     const char* pszDate = CSLFetchNameValue(m_papszIMDMD,
130                                             "MSP_ROOT.Normal.dSceneDate");
131 
132     if(nullptr != pszDate)
133     {
134         const char* pszTime = CSLFetchNameValue(m_papszIMDMD,
135                                          "MSP_ROOT.Normal.tSceneTime");
136         if(nullptr == pszTime)
137             pszTime = "00:00:00.000000";
138 
139         char buffer[80];
140         time_t timeMid = GetAcquisitionTimeFromString(CPLSPrintf( "%s %s",
141                                                      pszDate, pszTime));
142         strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
143         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
144                                            MD_NAME_ACQDATETIME, buffer);
145     }
146 
147     m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
148                                        MD_CLOUDCOVER_NA);
149 }
150 
151 /**
152  * GetAcqisitionTimeFromString()
153  */
GetAcquisitionTimeFromString(const char * pszDateTime)154 time_t GDALMDReaderResursDK1::GetAcquisitionTimeFromString(
155         const char* pszDateTime)
156 {
157     if(nullptr == pszDateTime)
158         return 0;
159 
160     int iYear;
161     int iMonth;
162     int iDay;
163     int iHours;
164     int iMin;
165     int iSec;
166 
167 // string example <Normal>
168 //                  tSceneTime = 10:21:36.000000
169 //                  dSceneDate = 16/9/2008
170 //                </Normal>
171 
172     int r = sscanf ( pszDateTime, "%d/%d/%d %d:%d:%d.%*s",
173                      &iDay, &iMonth, &iYear, &iHours, &iMin, &iSec);
174 
175     if (r != 6)
176         return 0;
177 
178     struct tm tmDateTime;
179     tmDateTime.tm_sec = iSec;
180     tmDateTime.tm_min = iMin;
181     tmDateTime.tm_hour = iHours;
182     tmDateTime.tm_mday = iDay;
183     tmDateTime.tm_mon = iMonth - 1;
184     tmDateTime.tm_year = iYear - 1900;
185     tmDateTime.tm_isdst = -1;
186 
187     return mktime(&tmDateTime) - 10800; // int UTC+3 MSK
188 }
189 
AddXMLNameValueToList(char ** papszList,const char * pszName,const char * pszValue)190 char** GDALMDReaderResursDK1::AddXMLNameValueToList(char** papszList,
191                                                const char *pszName,
192                                                const char *pszValue)
193 {
194     char** papszTokens = CSLTokenizeString2( pszValue, "\n",
195         CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
196 
197     for(int i = 0; papszTokens[i] != nullptr; i++ )
198     {
199 
200         char** papszSubTokens = CSLTokenizeString2( papszTokens[i], "=",
201             CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
202         if(CSLCount(papszSubTokens) < 2)
203         {
204             CSLDestroy( papszSubTokens );
205             continue;
206         }
207 
208         papszList = CSLAddNameValue(papszList, CPLSPrintf("%s.%s", pszName,
209                                               papszSubTokens[0]),
210                                               papszSubTokens[1]);
211         CSLDestroy( papszSubTokens );
212     }
213 
214     CSLDestroy( papszTokens );
215 
216     return papszList;
217 }
218