openModeller  Version 1.4.0
om_layer_utils.cpp
Go to the documentation of this file.
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 }