Main Page   Namespace List   Alphabetical List   Compound List   File List   Compound Members   File Members  

SubTree.cpp

Go to the documentation of this file.
00001 #include "SubTree.h"
00002 #include "PathParser.h"
00003 #include "MountInfo.h"
00004 
00005 #include "AIDA_Dev/IDevTree.h"
00006 #include "AIDA_Dev/IStore.h"
00007 
00008 Anaphe::AIDA_Tree_native::SubTree::SubTree( const std::string& name,
00009                                             AIDA::Dev::IDevTree* masterTree ):
00010   m_name( name ),
00011   m_masterTree( masterTree ),
00012   m_mountInfo( 0 ),
00013   m_subTrees(),
00014   m_objects(),
00015   m_links()
00016 {}
00017 
00018 
00019 Anaphe::AIDA_Tree_native::SubTree::~SubTree()
00020 {
00021   if ( m_mountInfo ) delete m_mountInfo;
00022   for ( std::map< std::string, AIDA::IManagedObject* >::iterator iObj = m_objects.begin();
00023         iObj != m_objects.end(); ++iObj ) {
00024     delete iObj->second;
00025   }
00026   for ( std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.begin();
00027         iDir != m_subTrees.end(); ++iDir ) {
00028     delete iDir->second;
00029   }
00030 }
00031 
00032 
00033 bool
00034 Anaphe::AIDA_Tree_native::SubTree::add( AIDA::IManagedObject * object,
00035                                         std::list< std::string >& path,
00036                                         bool overWrite,
00037                                         std::map< const AIDA::IManagedObject*, std::string >& objectMap,
00038                                         bool copy,
00039                                         bool addInStore )
00040 {
00041   if ( m_mountInfo ) {
00042     if ( ! object ) return false;
00043     std::list< std::string > targetNames = anaphe_path_parser.formNames( m_mountInfo->targetPath() );
00044     for ( std::list< std::string >::const_iterator iName = path.begin(); iName != path.end(); ++iName ) {
00045       targetNames.push_back( *iName );
00046     }
00047     if ( copy ) {
00048       return m_mountInfo->targetTree()->copyAndAdd( object, "/" + anaphe_path_parser.formPath( targetNames ) );
00049     }
00050     else {
00051       targetNames.pop_back(); // remove the "filename" from the directory part
00052       return m_mountInfo->targetTree()->add( object, "/" + anaphe_path_parser.formPath( targetNames ) );
00053     }
00054   }
00055 
00056   const std::string& name = path.front();
00057   // First of all check whether it still has to propagate the call even further.
00058   if ( path.size() > 1 ) {
00059     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iSubDir = m_subTrees.find( name );
00060     if ( iSubDir == m_subTrees.end() ) {
00061       return false;
00062     }
00063     else { // propagate call to the underlying sub-tree
00064       path.pop_front();
00065       return iSubDir->second->add( object, path, overWrite, objectMap, copy, addInStore );
00066     }
00067   }
00068 
00069   // We are in the target directory
00070   // make sure that there is no directory or link named after the same name
00071   std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iSubDir = m_subTrees.find( name );
00072   if ( iSubDir != m_subTrees.end() ) {
00073     if ( copy &&
00074          iSubDir->second->m_mountInfo == 0 &&
00075          iSubDir->second->m_subTrees.find( name ) != iSubDir->second->m_subTrees.end() ) {
00076       return iSubDir->second->add( object, path, overWrite, objectMap, copy, addInStore );
00077     }
00078     else return false;
00079   }
00080 
00081   // Check if an object with this name already exists
00082   if ( m_objects.find( name ) != m_objects.end() ) {
00083     if ( overWrite ) {
00084       // Remove first the old one
00085       m_masterTree->rm( m_name + name );
00086       m_objects.insert( std::make_pair( name, object ) );
00087       if ( object ) {
00088         if ( copy ) {
00089           AIDA::IManagedObject* newObject = m_masterTree->nativeStore()->copyAndWrite( *object, m_name + name );
00090           m_objects[ name ] = newObject;
00091           objectMap[ newObject ] = m_name + name;
00092         }
00093         else {
00094           if (addInStore) m_masterTree->nativeStore()->writeObject( *object, m_name + name );
00095           objectMap[ object ] = m_name + name;
00096         }
00097       }
00098       return true;
00099     }
00100     else return false;
00101   }
00102   else {
00103     // Check if a symbolic link exists with the same name.
00104     // Note : if in a copy method it is the directory that it is specified and the last node is a link,
00105     // then the link is overwritten and not followed. (We cannot look at it since it may point to another tree).
00106     if ( m_links.find( name ) != m_links.end() ){
00107       if ( overWrite ) {
00108         m_links.erase( name );
00109       }
00110       else {
00111         return false;
00112       }
00113     }
00114     m_objects.insert( std::make_pair( name, object ) );
00115     if ( object ) {
00116       if ( copy ) {
00117         AIDA::IManagedObject* newObject = m_masterTree->nativeStore()->copyAndWrite( *object, m_name + name );
00118         m_objects[ name ] = newObject;
00119         objectMap[ newObject ] = m_name + name;
00120       }
00121       else {
00122         if (addInStore) m_masterTree->nativeStore()->writeObject( *object, m_name + name );
00123         objectMap[ object ] = m_name + name;
00124       }
00125     }
00126     return true;
00127   }
00128 }
00129 
00130 
00131 AIDA::Dev::IStore*
00132 Anaphe::AIDA_Tree_native::SubTree::store( std::list< std::string >& path )
00133 {
00134   if ( m_mountInfo ) {
00135     return m_mountInfo->targetTree()->store( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00136   }
00137   const std::string& dirName = path.front();
00138   if ( path.size() > 1 ) {   // Check if the directory already exists
00139     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00140     if ( iDir == m_subTrees.end() ) {
00141       return 0;
00142     }
00143     path.pop_front();
00144     return iDir->second->store( path );
00145   }
00146 
00147   // This is the mother directory. Check if the target exists
00148   std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00149   if ( iDir != m_subTrees.end() ) {
00150     if ( iDir->second->m_mountInfo ) {
00151       return iDir->second->m_mountInfo->targetTree()->store( iDir->second->m_mountInfo->targetPath() );
00152     }
00153     else return m_masterTree->nativeStore();
00154   }
00155   if ( m_objects.find( dirName ) != m_objects.end() ) return m_masterTree->nativeStore();
00156   std::map< std::string, std::string >::const_iterator iLink = m_links.find( dirName );
00157   if ( iLink == m_links.end() ) return 0; // apparently, bad directory path was given
00158   else return m_masterTree->store( iLink->second );
00159 }
00160 
00161 
00162 bool
00163 Anaphe::AIDA_Tree_native::SubTree::existsDirectory( std::list< std::string >& path )
00164 {
00165   if ( m_mountInfo ) {
00166     return m_mountInfo->targetTree()->existsDirectory( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00167   }
00168   const std::string& dirName = path.front();
00169   if ( path.size() > 1 ) {   // Check if the directory already exists
00170     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00171     if ( iDir == m_subTrees.end() ) {
00172       return false;
00173     }
00174     path.pop_front();
00175     return iDir->second->existsDirectory( path );
00176   }
00177 
00178   // This is the mother directory. Check if the directory exists
00179   if ( m_subTrees.find( dirName ) != m_subTrees.end() ) return true;
00180   else return false;
00181 }
00182 
00183 
00184 bool
00185 Anaphe::AIDA_Tree_native::SubTree::mkdir( std::list< std::string >& path )
00186 {
00187   if ( m_mountInfo ) {
00188     return m_mountInfo->targetTree()->mkdir( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00189   }
00190   const std::string& dirName = path.front();
00191   if ( path.size() > 1 ) {   // Check if the directory already exists
00192     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00193     if ( iDir == m_subTrees.end() ) {
00194       return false;
00195     }
00196     path.pop_front();
00197     return iDir->second->mkdir( path );
00198   }
00199 
00200   // This is the mother directory. Check the validity of the name and add in the list of directories
00201   if ( m_objects.find( dirName ) != m_objects.end() ) return false;
00202   if ( m_links.find( dirName ) != m_links.end() ) return false;
00203   if ( m_subTrees.find( dirName ) != m_subTrees.end() ) return false;
00204   if ( dirName == "" || dirName == "." || dirName == ".." ) return false; // Check for invalid names ("", ".", "..")
00205 
00206   m_subTrees.insert( std::make_pair( dirName, new Anaphe::AIDA_Tree_native::SubTree( m_name + dirName + "/", m_masterTree ) ) );
00207   return true;
00208 }
00209 
00210 
00211 bool
00212 Anaphe::AIDA_Tree_native::SubTree::mkdirs( std::list< std::string >& path )
00213 {
00214   if ( m_mountInfo ) {
00215     return m_mountInfo->targetTree()->mkdirs( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00216   }
00217   if ( path.size() == 1 ) return mkdir( path );
00218 
00219   // Propagate the call to the next directory
00220   std::string dirName = path.front();
00221   path.pop_front();
00222   // Check if the directory already exists
00223   std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::const_iterator iDir = m_subTrees.find( dirName );
00224   if ( iDir == m_subTrees.end() ) {
00225     if ( m_objects.find( dirName ) != m_objects.end() ) return false;
00226     else if ( m_links.find( dirName ) != m_links.end() ) return false;
00227     else { // Not in the links, therefore create the intermediate directory
00228       m_subTrees[ dirName ] = new Anaphe::AIDA_Tree_native::SubTree( m_name + dirName + "/", m_masterTree );
00229       return m_subTrees[ dirName ]->mkdirs( path );
00230     }
00231   }
00232   else {
00233     return iDir->second->mkdirs( path );
00234   }
00235 }
00236 
00237 
00238 bool
00239 Anaphe::AIDA_Tree_native::SubTree::rmdir( std::list< std::string >& path )
00240 {
00241   if ( m_mountInfo ) {
00242     return m_mountInfo->targetTree()->rmdir( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00243   }
00244 
00245   const std::string& dirName = path.front();
00246   if ( path.size() > 1 ) {   // Check if the directory already exists
00247     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00248     if ( iDir == m_subTrees.end() ) {
00249       return false;
00250     }
00251     path.pop_front();
00252     return iDir->second->rmdir( path );
00253   }
00254 
00255   // This is the parent directory.
00256   if ( m_objects.find( dirName ) != m_objects.end() ) return false;
00257 
00258   // Check if the target directory is empty.
00259   Anaphe::AIDA_Tree_native::SubTree& subTree =  * ( m_subTrees[ dirName ] );
00260   if ( subTree.m_objects.size() > 0 ) return false;
00261   if ( subTree.m_subTrees.size() > 0 ) return false;
00262   // Destroy the directory.
00263   delete m_subTrees[ dirName ];
00264   m_subTrees.erase( dirName );
00265   return true;
00266 }
00267 
00268 
00269 bool
00270 Anaphe::AIDA_Tree_native::SubTree::symlink( const std::string& path,
00271                                             std::list< std::string >& alias )
00272 {
00273   if ( m_mountInfo ) {
00274     return m_mountInfo->targetTree()->symlink( m_mountInfo->targetPath() + anaphe_path_parser.formPath( alias ), path );
00275   }
00276 
00277   const std::string& dirName = alias.front();
00278   if ( alias.size() > 1 ) {
00279     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00280     if ( iDir == m_subTrees.end() ) {
00281       return false;
00282     }
00283     alias.pop_front();
00284     return iDir->second->symlink( path, alias );
00285   }
00286 
00287   // This is the mother directory. Check if there is a directory or an object with the same name
00288   if ( m_subTrees.find( dirName ) != m_subTrees.end() ) return false;
00289   if ( m_objects.find( dirName ) != m_objects.end() ) return false;
00290 
00291   // Check if there is a link with the same name
00292   return m_links.insert( std::make_pair( dirName, path ) ).second;
00293 }
00294 
00295 
00296 
00297 bool
00298 Anaphe::AIDA_Tree_native::SubTree::mount( const std::string & path,
00299                                           AIDA::Dev::IDevTree* tree,
00300                                           std::list< std::string >& treePath,
00301                                           std::map< AIDA::Dev::IDevTree*, Anaphe::AIDA_Tree_native::MountInfo* >& mountPoints )
00302 {
00303   if ( m_mountInfo ) {
00304     return false; // Directory is already a mount point for a tree
00305   }
00306 
00307   if ( treePath.size() > 0 ) {
00308     const std::string& dirName = treePath.front();
00309     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00310     if ( iDir == m_subTrees.end() ) {
00311       return false;
00312     }
00313     treePath.pop_front();
00314     return iDir->second->mount( path, tree, treePath, mountPoints );
00315   }
00316 
00317   // This is the mount directory. Make sure that we are not mounting the same tree !!!
00318   if ( tree == m_masterTree ) return false;
00319 
00320   m_mountInfo = new MountInfo( tree, path, m_name );
00321   tree->setParentTree( m_masterTree );
00322   return mountPoints.insert( std::make_pair( tree, m_mountInfo ) ).second;
00323 }
00324 
00325 
00326 bool
00327 Anaphe::AIDA_Tree_native::SubTree::unmount( std::list< std::string >& path,
00328                                             std::map< AIDA::Dev::IDevTree*, Anaphe::AIDA_Tree_native::MountInfo* >& mountPoints )
00329 {
00330   AIDA::Dev::IDevTree* p = 0;
00331   if ( m_mountInfo ) {
00332     if ( path.size() == 0 ) {
00333       p = m_mountInfo->targetTree();
00334       delete m_mountInfo;
00335       m_mountInfo = 0;
00336     }
00337   }
00338   else if ( path.size() > 0 ) {
00339     const std::string& dirName = path.front();
00340     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00341     if ( iDir == m_subTrees.end() ) {
00342       return false;
00343     }
00344     path.pop_front();
00345     return iDir->second->unmount( path, mountPoints );
00346   }
00347 
00348   if ( p ) {
00349     p->setParentTree( 0 );
00350     mountPoints.erase( p );
00351     return true;
00352   }
00353   else return false;
00354 }
00355 
00356 
00357 bool
00358 Anaphe::AIDA_Tree_native::SubTree::rm( std::list< std::string >& path,
00359                                        std::map< const AIDA::IManagedObject*, std::string >& objectMap )
00360 {
00361   if ( m_mountInfo ) {
00362     return m_mountInfo->targetTree()->rm( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00363   }
00364 
00365   const std::string& dirName = path.front();
00366   if ( path.size() > 1 ) {   // Check if the directory already exists
00367     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00368     if ( iDir == m_subTrees.end() ) {
00369       return false;
00370     }
00371     path.pop_front();
00372     return iDir->second->rm( path, objectMap );
00373   }
00374 
00375   // This is the mother directory.
00376   // Check if the name is one of the links
00377   if ( m_links.find( dirName ) != m_links.end() ) {
00378     m_links.erase( dirName );
00379     return true;
00380   }
00381   else { // Check in the registered objects
00382     std::map< std::string, AIDA::IManagedObject* >::iterator iObj = m_objects.find( dirName );
00383     if ( iObj == m_objects.end() ) return false; // Invalid path
00384     AIDA::IManagedObject* objectPointer = iObj->second;
00385     if ( objectPointer ) delete objectPointer;
00386     m_objects.erase( iObj );
00387     m_masterTree->nativeStore()->removeObject( m_name + dirName ); // remove object from the store.
00388     objectMap.erase( objectPointer );
00389     return true;
00390   }
00391 }
00392 
00393 
00394 AIDA::IManagedObject*
00395 Anaphe::AIDA_Tree_native::SubTree::find( std::list< std::string >& path,
00396                                          std::map< const AIDA::IManagedObject*, std::string >& objectMap )
00397 {
00398   if ( m_mountInfo ) {
00399     return m_mountInfo->targetTree()->find( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ) );
00400   }
00401 
00402   const std::string& dirName = path.front();
00403   if ( path.size() > 1 ) {   // Check if the directory already exists
00404     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00405     if ( iDir == m_subTrees.end() ) {
00406       return 0;
00407     }
00408     path.pop_front();
00409     return iDir->second->find( path, objectMap );
00410   }
00411 
00412   // This is the mother directory.
00413   // Check if the name is one of the links
00414   std::map< std::string, std::string >::const_iterator iLink = m_links.find( dirName );
00415   if ( iLink != m_links.end() ) {
00416     return m_masterTree->find( iLink->second );
00417   }
00418   else { // Check in the registered objects
00419     std::map< std::string, AIDA::IManagedObject* >::iterator iObj = m_objects.find( dirName );
00420     if ( iObj == m_objects.end() ) return 0; // Invalid path
00421     else {
00422       // Check if the object has been fetched from the store.
00423       AIDA::IManagedObject* objectPointer = iObj->second;
00424       if ( objectPointer == 0 ) {
00425         objectPointer = m_masterTree->nativeStore()->retrieveObject( m_name + dirName );
00426         if ( objectPointer ) objectMap[ objectPointer ] = m_name + dirName;
00427       }
00428       return objectPointer;
00429     }
00430   }
00431 }
00432 
00433 
00434 AIDA::IManagedObject*
00435 Anaphe::AIDA_Tree_native::SubTree::findAndErase( std::list< std::string >& path )
00436 {
00437   if ( m_mountInfo ) return 0;
00438 
00439   const std::string& dirName = path.front();
00440   if ( path.size() > 1 ) {   // Check if the directory already exists
00441     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::iterator iDir = m_subTrees.find( dirName );
00442     if ( iDir == m_subTrees.end() ) {
00443       return 0;
00444     }
00445     path.pop_front();
00446     return iDir->second->findAndErase( path );
00447   }
00448 
00449   // This is the mother directory.
00450   // Check if the name is one of the links
00451   if ( m_links.find( dirName ) != m_links.end() ) return 0;
00452   else { // Check in the registered objects
00453     std::map< std::string, AIDA::IManagedObject* >::const_iterator iObj = m_objects.find( dirName );
00454     if ( iObj == m_objects.end() ) return 0; // Invalid path
00455     else {
00456       AIDA::IManagedObject* p = iObj->second;
00457       m_objects.erase( iObj->first );
00458       return p;
00459     }
00460   }
00461 }
00462 
00463 
00464 std::vector< std::string >
00465 Anaphe::AIDA_Tree_native::SubTree::listObjectNames( std::list< std::string >& path,
00466                                                     bool recursive ) const
00467 {
00468   if ( m_mountInfo ) {
00469     return m_mountInfo->targetTree()->listObjectNames( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ), recursive );
00470   }
00471 
00472   const std::string& dirName = path.front();
00473   if ( path.size() > 0 ) {   // Check if the directory already exists
00474     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::const_iterator iDir = m_subTrees.find( dirName );
00475     if ( iDir == m_subTrees.end() ) {
00476       return std::vector< std::string >();
00477     }
00478     path.pop_front();
00479     return iDir->second->listObjectNames( path, recursive );
00480   }
00481 
00482   // This is the mother directory.
00483   std::vector< std::string > output;
00484   // List first the links:
00485   for ( std::map< std::string, std::string >::const_iterator iLink = m_links.begin();
00486         iLink != m_links.end(); ++iLink ) {
00487     output.push_back( iLink->first );
00488   }
00489 
00490   // Actual objects then. Ask the store to provide them.
00491   std::vector< std::string > objectNamesFromStore = m_masterTree->nativeStore()->listObjectPaths( m_name, false );
00492   std::vector< std::string > objectTypesFromStore = m_masterTree->nativeStore()->listObjectTypes( m_name, false );
00493   for ( unsigned int i = 0; i < objectNamesFromStore.size(); ++i ) {
00494     if ( objectTypesFromStore[i] != "dir" ) {
00495       output.push_back( objectNamesFromStore[i].substr( m_name.size() ) );
00496     }
00497   }
00498 
00499   // Finally list the directories:
00500   for ( std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::const_iterator iDir = m_subTrees.begin();
00501         iDir != m_subTrees.end(); ++iDir ) {
00502     output.push_back( iDir->first );
00503     if ( recursive ) {
00504       std::list< std::string > emptyList;
00505       std::vector< std::string > dirOutput = iDir->second->listObjectNames( emptyList, recursive );
00506       for ( unsigned int i = 0; i < dirOutput.size(); ++i ) output.push_back( iDir->first + "/" + dirOutput[i] );
00507     }
00508   }
00509   return output;
00510 }
00511 
00512 
00513 std::vector< std::string >
00514 Anaphe::AIDA_Tree_native::SubTree::listObjectTypes( std::list< std::string >& path,
00515                                                     bool recursive ) const
00516 {
00517   if ( m_mountInfo ) {
00518     return m_mountInfo->targetTree()->listObjectTypes( m_mountInfo->targetPath() + anaphe_path_parser.formPath( path ), recursive );
00519   }
00520 
00521   const std::string& dirName = path.front();
00522   if ( path.size() > 0 ) {   // Check if the directory already exists
00523     std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::const_iterator iDir = m_subTrees.find( dirName );
00524     if ( iDir == m_subTrees.end() ) {
00525       return std::vector< std::string >();
00526     }
00527     path.pop_front();
00528     return iDir->second->listObjectTypes( path, recursive );
00529   }
00530 
00531   // This is the mother directory.
00532   std::vector< std::string > output;
00533   // List first the links:
00534   for ( std::map< std::string, std::string >::const_iterator iLink = m_links.begin();
00535         iLink != m_links.end(); ++iLink ) {
00536     output.push_back( "-> " + iLink->second );
00537   }
00538 
00539   // Actual objects then. Ask the store to provide them.
00540   std::vector< std::string > objectTypesFromStore = m_masterTree->nativeStore()->listObjectTypes( m_name, false );
00541   for ( unsigned int i = 0; i < objectTypesFromStore.size(); ++i ) {
00542     if ( objectTypesFromStore[i] != "dir" ) output.push_back( objectTypesFromStore[i] );
00543   }
00544 
00545   // Finally list the directories:
00546   for ( std::map< std::string, Anaphe::AIDA_Tree_native::SubTree* >::const_iterator iDir = m_subTrees.begin();
00547         iDir != m_subTrees.end(); ++iDir ) {
00548     output.push_back( "dir" );
00549     if ( recursive ) {
00550       std::list< std::string > emptyList;
00551       std::vector< std::string > dirOutput = iDir->second->listObjectTypes( emptyList, recursive );
00552       for ( unsigned int i = 0; i < dirOutput.size(); ++i ) output.push_back( dirOutput[i] );
00553     }
00554   }
00555   return output;
00556 }

Generated on Tue Feb 18 17:51:15 2003 for AIDA_Tree_native by doxygen1.2.16