openModeller
Version 1.4.0
|
00001 00027 #include <om_layer_utils.hh> 00028 00029 #include <string> 00030 00031 #include <dirent.h> 00032 00033 #include "gdal_priv.h" 00034 00035 #include <openmodeller/Log.hh> 00036 #include <openmodeller/FileParser.hh> 00037 00038 /***********************/ 00039 /**** readDirectory ****/ 00040 bool 00041 readDirectory( const char* dir, const char* label, ostream &xml, int depth, int* seq ) 00042 { 00043 bool r = true; 00044 00045 if ( depth == 0 ) { 00046 00047 GDALAllRegister(); 00048 00049 CPLSetErrorHandler( CPLQuietErrorHandler ); 00050 } 00051 00052 ++depth; 00053 00054 // Maximum depth level to recurse on directories 00055 if ( depth > 20 ) 00056 { 00057 return false; 00058 } 00059 00060 // Create copy of dir and add slash to the end if necessary 00061 string myDir( dir ); 00062 00063 //skip hidden dirs 00064 if ( myDir.find( "." ) == 1 ) { 00065 return false; 00066 } 00067 if ( myDir.find_first_of( ".",0 ) == 1 ) { 00068 return false; 00069 } 00070 00071 if ( myDir.find_last_of( "/" ) != myDir.size() - 1 ) { 00072 00073 myDir.append( "/" ); 00074 } 00075 00076 // Open directory 00077 struct dirent **nameList; 00078 int n; 00079 struct stat buf; 00080 00081 n = scandir( myDir.c_str(), &nameList, 0, alphasort ); 00082 00083 if ( n < 0 ) { 00084 00085 // Problems opening directory 00086 return false; 00087 } 00088 else if ( n == 0 ) { 00089 00090 // Empty directories are useless 00091 return true; 00092 } 00093 00094 xml << "<LayersGroup Id=\"" << *seq << "\">"; 00095 00096 ++*seq; 00097 00098 xml << "<Label>" << label << "</Label>"; 00099 00100 string xmlFiles; 00101 00102 for ( int i = 0; i < n; i++ ) { 00103 00104 // Skip "." and ".." directories 00105 if ( strcmp( nameList[i]->d_name, "." ) == 0 || strcmp( nameList[i]->d_name, ".." ) == 0 ) { 00106 00107 continue; 00108 } 00109 00110 // Skip ".aux" files 00111 if ( strstr( nameList[i]->d_name, ".aux" ) != 0 ) { 00112 00113 continue; 00114 } 00115 00116 // Need the full name to "stat" 00117 string fullName( myDir ); 00118 fullName.append( nameList[i]->d_name ); 00119 00120 // Get file attributes (skip on failure) 00121 if ( stat( fullName.c_str(), &buf ) == -1 ) { 00122 00123 continue; 00124 } 00125 00126 // Directory 00127 if ( S_ISDIR( buf.st_mode ) ) { 00128 00129 Log::instance()->debug( "Checking directory: %s\n", fullName.c_str() ); 00130 00131 if ( isValidGdalFile( fullName.c_str() ) ) { 00132 00133 string hasProj = ( hasValidGdalProjection( fullName.c_str() ) ) ? "1" : "0"; 00134 00135 string label = getLayerLabel( myDir, nameList[i]->d_name, true ); 00136 00137 xmlFiles.append( "<Layer Id=\"" ); 00138 xmlFiles.append( fullName ); 00139 xmlFiles.append( "\" HasProjection=\""); 00140 xmlFiles.append( hasProj ); 00141 xmlFiles.append( "\">" ); 00142 xmlFiles.append( "<Label>" ); 00143 xmlFiles.append( label ); 00144 xmlFiles.append( "</Label>" ); 00145 xmlFiles.append( "</Layer>" ); 00146 } 00147 else { 00148 00149 r = readDirectory( fullName.c_str(), nameList[i]->d_name, xml, depth, seq ); 00150 } 00151 } 00152 // Regular file 00153 else if ( S_ISREG( buf.st_mode ) ) { 00154 00155 Log::instance()->debug( "Checking file: %s\n", fullName.c_str() ); 00156 00157 if ( isValidGdalFile( fullName.c_str() ) ) { 00158 00159 string hasProj = ( hasValidGdalProjection( fullName.c_str() ) ) ? "1" : "0"; 00160 00161 string label = getLayerLabel( myDir, nameList[i]->d_name, false ); 00162 00163 xmlFiles.append( "<Layer Id=\"" ); 00164 xmlFiles.append( fullName ); 00165 xmlFiles.append( "\" HasProjection=\""); 00166 xmlFiles.append( hasProj ); 00167 xmlFiles.append( "\">" ); 00168 xmlFiles.append( "<Label>" ); 00169 xmlFiles.append( label ); 00170 xmlFiles.append( "</Label>" ); 00171 xmlFiles.append( "</Layer>" ); 00172 } 00173 } 00174 // Symbolic link 00175 //else if ( S_ISLNK( buf.st_mode ) ) { 00176 00177 // What should we do with symlinks? 00178 //readDirectory( fullName.c_str(), nameList[i]->d_name, xml, depth, seq ); 00179 //} 00180 } 00181 00182 // openModeller.xsd mandates that files should always come after directories 00183 xml << xmlFiles; 00184 00185 xml << "</LayersGroup>"; 00186 00187 return r; 00188 } 00189 00190 /***********************/ 00191 /**** getLayerLabel ****/ 00192 string 00193 getLayerLabel( const string path, const string name, bool isDir ) 00194 { 00195 string metaFile = path; 00196 00197 // It is a directory 00198 if ( isDir ) { 00199 00200 // append last dir name and ".meta" 00201 metaFile = metaFile.append(name).append(".meta"); 00202 } 00203 // It is a file 00204 else { 00205 00206 size_t pos = name.find_last_of( "." ); 00207 00208 if ( pos != string::npos ) { 00209 00210 // replace extension with ".meta" 00211 string metaName = name.substr( 0, pos ).append(".meta"); 00212 metaFile = metaFile.append( metaName ); 00213 } 00214 else { 00215 00216 // try just appending name and ".meta" 00217 metaFile = metaFile.append(name).append(".meta"); 00218 } 00219 } 00220 00221 FILE * file = fopen( metaFile.c_str(), "r" ); 00222 00223 if ( file != NULL ) { 00224 00225 fclose( file ); 00226 00227 FileParser fParser( metaFile.c_str() ); 00228 00229 return fParser.get( "LABEL" ); 00230 } 00231 00232 return name; 00233 } 00234 00235 /*************************/ 00236 /**** isValidGdalFile ****/ 00237 bool 00238 isValidGdalFile( const char* fileName ) 00239 { 00240 // test whether the file is GDAL compatible 00241 GDALDataset * testFile = (GDALDataset *)GDALOpen( fileName, GA_ReadOnly ); 00242 00243 if ( testFile == NULL ) { 00244 00245 // not GDAL compatible 00246 return false; 00247 } 00248 else { 00249 00250 // is GDAL compatible 00251 GDALClose( testFile ); 00252 return true; 00253 } 00254 } 00255 00256 /********************************/ 00257 /**** hasValidGdalProjection ****/ 00258 bool 00259 hasValidGdalProjection( const char* fileName ) 00260 { 00261 // test whether the file has GDAL projection info 00262 GDALDataset * testFile = (GDALDataset *)GDALOpen( fileName, GA_ReadOnly ); 00263 00264 const char *projectionString = testFile->GetProjectionRef(); 00265 00266 GDALClose( testFile ); 00267 00268 if ( projectionString ) { 00269 00270 // has projection info 00271 return true; 00272 } 00273 00274 // does not have projection info 00275 return false; 00276 }