Field3D
Field3DFile.cpp
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00043 //----------------------------------------------------------------------------//
00044 
00045 #include <sys/stat.h>
00046 #include <unistd.h>
00047 
00048 #include <hdf5.h>
00049 #include <H5Epublic.h>
00050 
00051 #include <boost/tokenizer.hpp>
00052 #include <boost/utility.hpp>
00053 
00054 #include "Field3DFile.h"
00055 #include "Field.h"
00056 #include "ClassFactory.h"
00057 
00058 
00059 //----------------------------------------------------------------------------//
00060 
00061 using namespace std;
00062 
00063 //----------------------------------------------------------------------------//
00064 
00065 FIELD3D_NAMESPACE_OPEN
00066 
00067 //----------------------------------------------------------------------------//
00068 // Field3D namespaces
00069 //----------------------------------------------------------------------------//
00070 
00071 using namespace Exc;
00072 using namespace Hdf5Util;
00073 using namespace File;
00074 
00075 //----------------------------------------------------------------------------//
00076 // Local namespace
00077 //----------------------------------------------------------------------------//
00078 
00079 namespace {
00080   
00081   // Strings used only in this file --------------------------------------------
00082 
00083   const std::string k_mappingStr("mapping");
00084   const std::string k_versionAttrName("version_number");
00085   const std::string k_classNameAttrName("class_name");
00086   const std::string k_mappingTypeAttrName("mapping_type");
00087 
00090 
00091   int k_currentFileVersion[3] =
00092     { FIELD3D_MAJOR_VER, FIELD3D_MINOR_VER, FIELD3D_MICRO_VER };
00093   int k_minFileVersion[2] = { 0, 0 };
00094 
00095   // Function objects used only in this file -----------------------------------
00096 
00097   std::vector<std::string> makeUnique(std::vector<std::string> vec)
00098   {
00099     std::vector<string> ret;
00100     std::sort(vec.begin(), vec.end());
00101     std::vector<std::string>::iterator newEnd = 
00102       std::unique(vec.begin(), vec.end());
00103     ret.resize(std::distance(vec.begin(), newEnd));
00104     std::copy(vec.begin(), newEnd, ret.begin()); 
00105     return ret;
00106   }
00107 
00108 //----------------------------------------------------------------------------//
00109 
00111   template <class T>
00112   class print : std::unary_function<T, void>
00113   {
00114   public:
00115     print(int indentAmt)
00116       : indent(indentAmt)
00117     { }
00118     void operator()(const T& x) const
00119     {
00120       for (int i = 0; i < indent; i++)
00121         std::cout << " ";
00122       std::cout << x << std::endl;
00123     }
00124     int indent;
00125   };
00126 
00127 //----------------------------------------------------------------------------//
00128 
00134   bool fileExists(const std::string &filename)
00135   {
00136     struct stat statbuf;
00137     return (stat(filename.c_str(), &statbuf) != -1);
00138   }
00139 
00145   void checkFile(const std::string &filename)
00146   {
00147     if (!fileExists(filename))
00148     {
00149       throw NoSuchFileException(filename);
00150     }
00151   }
00152 
00153 //----------------------------------------------------------------------------//
00154 
00155   bool isSupportedFileVersion(const int fileVersion[3],
00156                               const int minVersion[2])
00157   {
00158     stringstream currentVersionStr;
00159     currentVersionStr << k_currentFileVersion[0] << "."
00160                       << k_currentFileVersion[1] << "."
00161                       << k_currentFileVersion[2];
00162     stringstream fileVersionStr;
00163     fileVersionStr << fileVersion[0] << "."
00164                    << fileVersion[1] << "."
00165                    << fileVersion[2];
00166     stringstream minVersionStr;
00167     minVersionStr << minVersion[0] << "."
00168                   << minVersion[1];
00169 
00170     if (fileVersion[0] > k_currentFileVersion[0] ||
00171         (fileVersion[0] == k_currentFileVersion[0] && 
00172          fileVersion[1] > k_currentFileVersion[1])) {
00173       Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
00174                  " is higher than the current version " +
00175                  currentVersionStr.str());
00176       return true;
00177     }
00178 
00179     if (fileVersion[0] < minVersion[0] ||
00180         (fileVersion[0] == minVersion[0] &&
00181          fileVersion[1] < minVersion[1])) {
00182       Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
00183                  " is lower than the minimum supported version " +
00184                  minVersionStr.str());
00185       return false;
00186     }
00187     return true;
00188   }
00189 
00190 //----------------------------------------------------------------------------//
00191 
00192   static herr_t localPrintError( hid_t estack_id, void *stream )
00193   {
00194     printf("H5E message -----------------------\n");
00195     return H5Eprint2(estack_id, static_cast<FILE*>(stream));
00196   }
00197   
00198 //----------------------------------------------------------------------------//
00199 
00200 } // end of local namespace
00201 
00202 //----------------------------------------------------------------------------//
00203 // Partition implementations
00204 //----------------------------------------------------------------------------//
00205 
00206 void 
00207 Partition::addScalarLayer(const Layer &layer)
00208 {
00209   m_scalarLayers.push_back(layer);
00210 }
00211 
00212 //----------------------------------------------------------------------------//
00213 
00214 void 
00215 Partition::addVectorLayer(const Layer &layer)
00216 {
00217   m_vectorLayers.push_back(layer);
00218 }
00219 
00220 //----------------------------------------------------------------------------//
00221 
00222 const Layer* 
00223 Partition::scalarLayer(const std::string &name) const
00224 {
00225   for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
00226        i != m_scalarLayers.end(); ++i) {
00227     if (i->name == name)
00228       return &(*i);
00229   }
00230   return NULL;
00231 }
00232 
00233 //----------------------------------------------------------------------------//
00234 
00235 const Layer* 
00236 Partition::vectorLayer(const std::string &name) const
00237 {
00238   for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
00239        i != m_vectorLayers.end(); ++i) {
00240     if (i->name == name)
00241       return &(*i);
00242   }
00243   return NULL;
00244 }
00245 
00246 //----------------------------------------------------------------------------//
00247 
00248 void 
00249 Partition::getScalarLayerNames(std::vector<std::string> &names) const 
00250 {
00251   // We don't want to do names.clear() here, since this gets called
00252   // inside some loops that want to accumulate names.
00253   for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
00254        i != m_scalarLayers.end(); ++i) {
00255     names.push_back(i->name);
00256   }
00257 }
00258 
00259 //----------------------------------------------------------------------------//
00260 
00261 void 
00262 Partition::getVectorLayerNames(std::vector<std::string> &names) const
00263 {
00264   // We don't want to do names.clear() here, since this gets called
00265   // inside some loops that want to accumulate names.
00266   for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
00267        i != m_vectorLayers.end(); ++i) {
00268     names.push_back(i->name);
00269   }
00270 }
00271 
00272 //----------------------------------------------------------------------------//
00273 // Field3DFileBase implementations
00274 //----------------------------------------------------------------------------//
00275 
00276 Field3DFileBase::Field3DFileBase()
00277   : m_file(-1), m_metadata(this)
00278 {
00279   // Suppressing HDF error messages
00280   // Explanation about the function for the error stack is here:
00281   // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5E.html#Error-SetAuto2
00282   if (getenv("DEBUG_HDF")) {
00283     cerr << "Field3DFile -- HDF5 messages are on" << endl;
00284     H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
00285   } else {
00286     H5Eset_auto(H5E_DEFAULT, NULL, NULL);
00287   }
00288 }
00289 
00290 //----------------------------------------------------------------------------//
00291 
00292 Field3DFileBase::~Field3DFileBase()
00293 {
00294   close();
00295 }
00296 
00297 //----------------------------------------------------------------------------//
00298 
00299 std::string 
00300 Field3DFileBase::intPartitionName(const std::string &partitionName,
00301                                   const std::string &layerName,
00302                                   FieldRes::Ptr field)
00303 {
00304   // Loop over existing partitions and see if there's a matching mapping
00305   for (PartitionList::const_iterator i = m_partitions.begin();
00306        i != m_partitions.end(); ++i) {
00307     if (removeUniqueId((**i).name) == partitionName) {
00308       if ((**i).mapping->isIdentical(field->mapping())) {
00309         return (**i).name;
00310       }
00311     }
00312   }
00313 
00314   // If there was no previously matching name, then make a new one
00315 
00316   int nextIdx = -1;
00317   if (m_partitionCount.find(partitionName) != m_partitionCount.end()) {
00318     nextIdx = ++m_partitionCount[partitionName];
00319   } else {
00320     nextIdx = 0;
00321     m_partitionCount[partitionName] = 0;
00322   }
00323 
00324   return makeIntPartitionName(partitionName, nextIdx);
00325 }
00326 
00327 //----------------------------------------------------------------------------//
00328 
00329 Partition::Ptr Field3DFileBase::partition(const string &partitionName) 
00330 {
00331   for (PartitionList::iterator i = m_partitions.begin();
00332        i != m_partitions.end(); ++i) {
00333     if ((**i).name == partitionName)
00334       return *i;
00335   }
00336 
00337   return Partition::Ptr();
00338 }
00339 
00340 //----------------------------------------------------------------------------//
00341 
00342 Partition::Ptr
00343 Field3DFileBase::partition(const string &partitionName) const
00344 {
00345   for (PartitionList::const_iterator i = m_partitions.begin();
00346        i != m_partitions.end(); ++i) {
00347     if ((**i).name == partitionName)
00348       return *i;
00349   }
00350 
00351   return Partition::Ptr();
00352 }
00353 
00354 //----------------------------------------------------------------------------//
00355 
00356 std::string 
00357 Field3DFileBase::removeUniqueId(const std::string &partitionName) const
00358 {
00359   size_t pos = partitionName.rfind(".");
00360   if (pos == partitionName.npos) {
00361     return partitionName;
00362   } else {
00363     return partitionName.substr(0, pos);
00364   }  
00365 }
00366 
00367 //----------------------------------------------------------------------------//
00368 
00369 void 
00370 Field3DFileBase::getPartitionNames(vector<string> &names) const
00371 {
00372   names.clear();
00373 
00374   vector<string> tempNames;
00375 
00376   for (PartitionList::const_iterator i = m_partitions.begin();
00377        i != m_partitions.end(); ++i) {
00378     tempNames.push_back(removeUniqueId((**i).name));
00379   }
00380 
00381   names = makeUnique(tempNames);
00382 }
00383 
00384 //----------------------------------------------------------------------------//
00385 
00386 void 
00387 Field3DFileBase::getScalarLayerNames(vector<string> &names, 
00388                                      const string &partitionName) const
00389 {
00390   names.clear();
00391 
00392   for (int i = 0; i < numIntPartitions(partitionName); i++) {
00393     string internalName = makeIntPartitionName(partitionName, i);
00394     Partition::Ptr part = partition(internalName);
00395     if (part)
00396       part->getScalarLayerNames(names);
00397   }
00398 
00399   names = makeUnique(names);
00400 }
00401 
00402 //----------------------------------------------------------------------------//
00403 
00404 void 
00405 Field3DFileBase::getVectorLayerNames(vector<string> &names, 
00406                                      const string &partitionName) const
00407 {
00408   names.clear();
00409 
00410   for (int i = 0; i < numIntPartitions(partitionName); i++) {
00411     string internalName = makeIntPartitionName(partitionName, i);
00412     Partition::Ptr part = partition(internalName);
00413     if (part)
00414       part->getVectorLayerNames(names);
00415   }
00416 
00417   names = makeUnique(names);
00418 }
00419 
00420 //----------------------------------------------------------------------------//
00421 
00422 void 
00423 Field3DFileBase::getIntPartitionNames(vector<string> &names) const
00424 {
00425   names.clear();
00426 
00427   for (PartitionList::const_iterator i = m_partitions.begin();
00428        i != m_partitions.end(); ++i) {
00429     names.push_back((**i).name);
00430   }
00431 }
00432 
00433 //----------------------------------------------------------------------------//
00434 
00435 void 
00436 Field3DFileBase::getIntScalarLayerNames(vector<string> &names, 
00437                                         const string &intPartitionName) const
00438 {
00439   names.clear();
00440 
00441   Partition::Ptr part = partition(intPartitionName);
00442 
00443   if (!part) {
00444     Msg::print("getIntScalarLayerNames no partition: " + intPartitionName);
00445     return;
00446   }
00447 
00448   part->getScalarLayerNames(names);
00449 }
00450 
00451 //----------------------------------------------------------------------------//
00452 
00453 void 
00454 Field3DFileBase::getIntVectorLayerNames(vector<string> &names, 
00455                                         const string &intPartitionName) const
00456 {
00457   names.clear();
00458 
00459   Partition::Ptr part = partition(intPartitionName);
00460 
00461   if (!part) {
00462     Msg::print("getIntVectorLayerNames no partition: " + intPartitionName);    
00463     return;
00464   }
00465 
00466   part->getVectorLayerNames(names);
00467 }
00468 
00469 //----------------------------------------------------------------------------//
00470 
00471 void Field3DFileBase::clear()
00472 {
00473   closeInternal();
00474   m_partitions.clear();
00475   m_groupMembership.clear();
00476 }
00477 
00478 //----------------------------------------------------------------------------//
00479 
00480 bool Field3DFileBase::close()
00481 {
00482   closeInternal();
00483 
00484   return true;
00485 }
00486 
00487 //----------------------------------------------------------------------------//
00488 
00489 void Field3DFileBase::closeInternal()
00490 {
00491   if (m_file != -1) {
00492     if (H5Fclose(m_file) < 0) {
00493       Msg::print(Msg::SevWarning, "Failed to close hdf5 file handle");
00494       return;
00495     }    
00496     m_file = -1;
00497   }
00498 }
00499 
00500 //----------------------------------------------------------------------------//
00501 
00502 int 
00503 Field3DFileBase::numIntPartitions(const std::string &partitionName) const
00504 {
00505   int count = 0;
00506 
00507   for (PartitionList::const_iterator i = m_partitions.begin();
00508        i != m_partitions.end(); ++i) {
00509     string name = (**i).name;
00510     size_t pos = name.rfind(".");
00511     if (pos != name.npos) {
00512       if (name.substr(0, pos) == partitionName) {
00513         count++;
00514       }
00515     }
00516   }
00517 
00518   return count;
00519 }
00520 
00521 //----------------------------------------------------------------------------//
00522 
00523 string 
00524 Field3DFileBase::makeIntPartitionName(const std::string &partitionName,
00525                                       int i) const
00526 {
00527   return partitionName + "." + boost::lexical_cast<std::string>(i);
00528 }
00529 
00530 //----------------------------------------------------------------------------//
00531 
00532 void 
00533 Field3DFileBase::addGroupMembership(const GroupMembershipMap& groupMembers)
00534 {
00535   GroupMembershipMap::const_iterator i= groupMembers.begin();
00536   GroupMembershipMap::const_iterator end= groupMembers.end();
00537 
00538   for (; i != end; ++i) {
00539     GroupMembershipMap::iterator foundGroupIter = 
00540       m_groupMembership.find(i->first);
00541     if (foundGroupIter != m_groupMembership.end()){
00542       std::string value = m_groupMembership[i->first] + i->second;
00543       m_groupMembership[i->first] = value;
00544     } else { 
00545       m_groupMembership[i->first] = i->second;
00546     }
00547   }
00548 }
00549 
00550 //----------------------------------------------------------------------------//
00551 // Field3DInputFile implementations
00552 //----------------------------------------------------------------------------//
00553 
00554 Field3DInputFile::Field3DInputFile() 
00555 { 
00556   // Empty
00557 }
00558 
00559 //----------------------------------------------------------------------------//
00560 
00561 Field3DInputFile::~Field3DInputFile() 
00562 { 
00563   clear(); 
00564 }
00565 
00566 //----------------------------------------------------------------------------//
00567 
00568 bool Field3DInputFile::open(const string &filename)
00569 {
00570   clear();
00571 
00572   bool success = true;
00573 
00574   m_filename = filename;
00575 
00576   try {
00577 
00578     string version;
00579 
00580     // Throws exceptions if the file doesn't exist.
00581     // This was added because H5Fopen prints out a lot of junk
00582     // to the terminal.
00583     checkFile(filename);
00584 
00585     m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
00586 
00587     if (m_file < 0)
00588       throw NoSuchFileException(filename);
00589 
00590     int fileVersion[3];
00591     try { 
00592       if (!readAttribute(m_file, k_versionAttrName, 3, fileVersion[0])) {
00593         //Msg::print(Msg::SevWarning, "Missing version_number attribute");
00594       } else {
00595         if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
00596           stringstream versionStr;
00597           versionStr << fileVersion[0] << "."
00598                      << fileVersion[1] << "."
00599                      << fileVersion[2];
00600           throw UnsupportedVersionException(versionStr.str());
00601         }
00602       }
00603     }
00604     catch (MissingAttributeException &e) {
00605       //Msg::print(Msg::SevWarning, "Missing version_number attribute");
00606     }
00607 
00608     try { 
00609       if (H5Lexists(m_file, "field3d_global_metadata", H5P_DEFAULT)) {      
00610         // read the metadata 
00611         H5ScopedGopen metadataGroup(m_file, "field3d_global_metadata");
00612         if (metadataGroup.id() > 0) {    
00613           readMetadata(metadataGroup.id());
00614         }
00615       }
00616     }
00617     catch (...) {
00618       Msg::print(Msg::SevWarning, 
00619                  "Unknown error when reading file metadata ");
00620       //throw BadFileHierarchyException(filename);
00621     }
00622 
00623     try {
00624       if (!readPartitionAndLayerInfo()) {
00625         success = false;
00626       }
00627     } 
00628     catch (MissingGroupException &e) {
00629       Msg::print(Msg::SevWarning, "Missing group: " + string(e.what()));
00630       throw BadFileHierarchyException(filename);
00631     }
00632     catch (ReadMappingException &e) {
00633       Msg::print(Msg::SevWarning, "Couldn't read mapping for partition: " 
00634                 + string(e.what()));
00635       throw BadFileHierarchyException(filename);
00636     }
00637     catch (Exception &e) {
00638       Msg::print(Msg::SevWarning, "Unknown error when reading file hierarchy: "
00639                 + string(e.what()));
00640       throw BadFileHierarchyException(filename);
00641     }
00642     catch (...) {
00643       Msg::print(Msg::SevWarning, 
00644                  "Unknown error when reading file hierarchy. ");
00645       throw BadFileHierarchyException(filename);
00646     }
00647 
00648   }
00649   catch (NoSuchFileException &e) {
00650     Msg::print(Msg::SevWarning, "Couldn't open file: " 
00651               + string(e.what()) );
00652     success = false;    
00653   }
00654   catch (MissingAttributeException &e) {
00655     Msg::print(Msg::SevWarning, 
00656                "In file: " + filename + " - "
00657               + string(e.what()) );
00658     success = false;
00659   }
00660   catch (UnsupportedVersionException &e) {    
00661     Msg::print(Msg::SevWarning, 
00662                "In file: " + filename + " - File version can not be read: " 
00663               + string(e.what()));
00664     success = false;    
00665   }
00666   catch (BadFileHierarchyException &e) {
00667     Msg::print(Msg::SevWarning, 
00668                "In file: " + filename + " - Bad file hierarchy. ");
00669     success = false;    
00670   }
00671   catch (...) {
00672     Msg::print(Msg::SevWarning, 
00673                "In file: " + filename + " Unknown exception ");
00674     success = false;
00675   }
00676 
00677   if (!success)
00678     close();
00679   
00680   return success;
00681 }
00682 
00683 //----------------------------------------------------------------------------//
00684 
00685 bool Field3DInputFile::readPartitionAndLayerInfo()
00686 {
00687   using namespace InputFile;
00688 
00689   // First, find the partitions ---
00690 
00691   herr_t status;
00692   status = H5Literate(m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, 
00693                       &parsePartitions, this);
00694 
00695   // Get the partition names to store 
00696   m_partitions.clear();
00697 
00698   for (size_t i=0; i < m_partitionNames.size(); i++) {
00699     Partition::Ptr part(new Partition);
00700     part->name = m_partitionNames[i];    
00701     m_partitions.push_back(part);
00702   }
00703   
00704   // For each partition, find its mapping ---
00705 
00706   for (PartitionList::iterator i = m_partitions.begin();
00707        i != m_partitions.end(); ++i) {
00708 
00709     // Open the partition
00710     H5ScopedGopen partitionGroup(m_file, (**i).name);
00711 
00712     string mappingPath = "/" + (**i).name + "/" + k_mappingStr;
00713 
00714     // Open up the mapping group
00715     H5ScopedGopen mappingGroup(m_file, mappingPath);
00716     if (mappingGroup.id() < 0)
00717       throw MissingGroupException((**i).name + "/" + k_mappingStr);
00718 
00719     // Try to build a mapping from it
00720     FieldMapping::Ptr mapping;
00721 
00722     mapping = readFieldMapping(mappingGroup.id());
00723     if (!mapping) {
00724       Msg::print(Msg::SevWarning, "Got a null pointer when reading mapping");
00725       throw ReadMappingException((**i).name);
00726     }
00727     
00728     // Attach the mapping to the partition
00729     (**i).mapping = mapping;
00730 
00731   }
00732 
00733   // ... And then find its layers ---
00734 
00735   for (PartitionList::const_iterator i = m_partitions.begin();
00736        i != m_partitions.end(); ++i) {
00737 
00738     // Open the partition
00739     H5ScopedGopen partitionGroup(m_file, (**i).name);
00740     
00741     // Set up the info struct for the callback
00742     ParseLayersInfo info;
00743     info.file = this;
00744     info.partitionName = (**i).name;
00745 
00746     m_layerInfo.clear();
00747 
00748     status = H5Literate(partitionGroup.id(), H5_INDEX_NAME, H5_ITER_NATIVE, 
00749                         NULL, &parseLayers, &info);
00750 
00751     //set the layer information on the partitions here
00752 
00753     for (std::vector<LayerInfo>::iterator i = m_layerInfo.begin();
00754          i != m_layerInfo.end(); i++) {
00755 
00756       std::string parent = i->parentName;      
00757 
00758       Partition::Ptr part = partition(parent);
00759 
00760       Layer layer;
00761       layer.name = i->name;
00762       layer.parent = i->parentName;
00763       if (i->components == 1) {
00764         part->addScalarLayer(layer);
00765       } else if (i->components == 3) {
00766         part->addVectorLayer(layer);
00767       }
00768     }
00769 
00770   }
00771 
00772   return true;
00773 }
00774 
00775 //----------------------------------------------------------------------------//
00776 
00777 herr_t Field3DInputFile::parsePartition(hid_t loc_id, 
00778                                         const std::string itemName)
00779 {
00780   // Add the partition ---
00781   
00782   m_partitionNames.push_back(string(itemName));
00783   return 0;
00784 }
00785 
00786 //----------------------------------------------------------------------------//
00787 
00791 herr_t Field3DInputFile::parseLayer(hid_t layerGroup, 
00792                                const std::string &partitionName,
00793                                const std::string &layerName)
00794 {
00795   int components;
00796   if (!readAttribute(layerGroup, string("components"), 1, components)) {
00797     Msg::print(Msg::SevWarning, "Couldn't read components attribute for layer " 
00798               + partitionName + "/" + layerName);
00799     return 0;
00800   }
00801 
00802   LayerInfo linfo(partitionName,layerName,components);
00803 
00804   m_layerInfo.push_back(linfo);
00805 
00806   return 0;
00807 }
00808 
00809 //----------------------------------------------------------------------------//
00810 
00812 bool  
00813 Field3DInputFile::
00814 readMetadata(hid_t metadata_id, FieldBase::Ptr field) const
00815 {
00816 
00817   hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
00818 
00819   if (num_attrs > 0) { 
00820     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
00821       H5ScopedAopenIdx attrIdx(metadata_id, idx);
00822       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
00823       if (len > 0) {
00824         char *name = new char[len+1];
00825         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
00826           H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
00827           H5ScopedAget_space attrSpace(attr);
00828           H5ScopedAget_type attrType(attr);           
00829           H5T_class_t typeClass = H5Tget_class(attrType);
00830 
00831           if (typeClass == H5T_STRING) { 
00832             string value;
00833             if (!readAttribute(metadata_id, name, value)) {
00834               Msg::print(Msg::SevWarning, 
00835                          "Failed to read metadata " + string(name));
00836               if (name) {
00837                 delete[] name;
00838               }
00839               continue;
00840             }
00841             field->metadata().setStrMetadata(name, value);
00842              
00843           }
00844           else {
00845 
00846             if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
00847               Msg::print(Msg::SevWarning, "Bad attribute rank for attribute " 
00848                         + string(name));
00849               if (name) {
00850                 delete[] name;
00851               }
00852               continue;
00853             }            
00854 
00855             hsize_t dims[1];
00856             H5Sget_simple_extent_dims(attrSpace, dims, NULL);
00857  
00858             if (typeClass == H5T_INTEGER) { 
00859               if (dims[0] == 1){
00860                 int value;
00861                 if (!readAttribute(metadata_id, name, dims[0], value))
00862                   Msg::print(Msg::SevWarning, "Failed to read metadata " 
00863                             + string(name));
00864                 field->metadata().setIntMetadata(name, value);
00865               }
00866               else if (dims[0] == 3){
00867                 V3i value;
00868                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00869                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00870                             string(name) );
00871                 field->metadata().setVecIntMetadata(name, value);
00872               }
00873               else {
00874                 Msg::print(Msg::SevWarning, 
00875                            "Attribute of size " + 
00876                            boost::lexical_cast<std::string>(dims[0]) 
00877                            + " is not valid for metadata");
00878               }
00879             }
00880             else if (typeClass == H5T_FLOAT) { 
00881               if (dims[0] == 1){
00882                 float value;
00883                 if (!readAttribute(metadata_id, name, dims[0], value))
00884                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00885                             string(name) );
00886                 
00887                 field->metadata().setFloatMetadata(name, value);
00888               }
00889               else if (dims[0] == 3){
00890                 V3f value;
00891                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00892                   Msg::print(Msg::SevWarning, "Failed to read metadata "+ 
00893                             string(name) );
00894                 field->metadata().setVecFloatMetadata(name, value);
00895               }
00896               else {
00897                 Msg::print(Msg::SevWarning, "Attribute of size " +
00898                            boost::lexical_cast<std::string>(dims[0]) +
00899                            " is not valid for metadata");
00900               }
00901             }
00902             else {               
00903               Msg::print(Msg::SevWarning, "Attribute '" + string(name) + 
00904                         + "' has unsupported data type for metadata");
00905               
00906             }
00907           }
00908         }
00909         if (name) {
00910           delete[] name;
00911         }
00912       }
00913     }
00914   }
00915 
00916   return true;
00917 }
00918 
00919 //----------------------------------------------------------------------------//
00920 
00922 bool  
00923 Field3DInputFile::readMetadata(hid_t metadata_id)
00924 {
00925 
00926   hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
00927 
00928   if (num_attrs > 0) { 
00929     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
00930       H5ScopedAopenIdx attrIdx(metadata_id, idx);
00931       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
00932       if (len > 0) {
00933         char *name = new char[len+1];
00934         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
00935           H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
00936           H5ScopedAget_space attrSpace(attr);
00937           H5ScopedAget_type attrType(attr);           
00938           H5T_class_t typeClass = H5Tget_class(attrType);
00939 
00940           if (typeClass == H5T_STRING) { 
00941             string value;
00942             if (!readAttribute(metadata_id, name, value)) {
00943               Msg::print(Msg::SevWarning, 
00944                          "Failed to read metadata " + string(name));
00945               if (name) {
00946                 delete[] name;
00947               }
00948               continue;
00949             }
00950             metadata().setStrMetadata(name, value);
00951              
00952           }
00953           else {
00954 
00955             if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
00956               Msg::print(Msg::SevWarning, "Bad attribute rank for attribute " 
00957                         + string(name));
00958               if (name) {
00959                 delete[] name;
00960               }
00961               continue;
00962             }            
00963 
00964             hsize_t dims[1];
00965             H5Sget_simple_extent_dims(attrSpace, dims, NULL);
00966  
00967             if (typeClass == H5T_INTEGER) { 
00968               if (dims[0] == 1){
00969                 int value;
00970                 if (!readAttribute(metadata_id, name, dims[0], value))
00971                   Msg::print(Msg::SevWarning, "Failed to read metadata " 
00972                             + string(name));
00973                 metadata().setIntMetadata(name, value);
00974               }
00975               else if (dims[0] == 3){
00976                 V3i value;
00977                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00978                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00979                             string(name) );
00980                 metadata().setVecIntMetadata(name, value);
00981               }
00982               else {
00983                 Msg::print(Msg::SevWarning, 
00984                            "Attribute of size " + 
00985                            boost::lexical_cast<std::string>(dims[0]) 
00986                            + " is not valid for metadata");
00987               }
00988             }
00989             else if (typeClass == H5T_FLOAT) { 
00990               if (dims[0] == 1){
00991                 float value;
00992                 if (!readAttribute(metadata_id, name, dims[0], value))
00993                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00994                             string(name) );
00995                 
00996                 metadata().setFloatMetadata(name, value);
00997               }
00998               else if (dims[0] == 3){
00999                 V3f value;
01000                 if (!readAttribute(metadata_id, name, dims[0], value.x))
01001                   Msg::print(Msg::SevWarning, "Failed to read metadata "+ 
01002                             string(name) );
01003                 metadata().setVecFloatMetadata(name, value);
01004               }
01005               else {
01006                 Msg::print(Msg::SevWarning, "Attribute of size " +
01007                            boost::lexical_cast<std::string>(dims[0]) +
01008                            " is not valid for metadata");
01009               }
01010             }
01011             else {               
01012               Msg::print(Msg::SevWarning, "Attribute '" + string(name) + 
01013                         + "' has unsupported data type for metadata");
01014               
01015             }
01016           }
01017         }
01018         if (name) {
01019           delete[] name;
01020         }
01021       }
01022     }
01023   }
01024 
01025   return true;
01026 }
01027 
01028 //----------------------------------------------------------------------------//
01029 
01030 bool
01031 Field3DInputFile::
01032 readGroupMembership(GroupMembershipMap &gpMembershipMap)
01033 {
01034   if (!H5Lexists(m_file, "field3d_group_membership", H5P_DEFAULT)) {
01035     return false;
01036   }
01037 
01038   H5ScopedGopen memberGroup(m_file, "field3d_group_membership");
01039   if (memberGroup < 0) {
01040     return false;
01041   }
01042   
01043   typedef boost::tokenizer<boost::char_separator<char> > Tok;
01044 
01045   hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
01046   if (num_attrs > 0) { 
01047     
01048     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
01049       H5ScopedAopenIdx attrIdx(memberGroup, idx);        
01050       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
01051       if (len>0) {
01052         char *name = new char[len+1];
01053         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
01054 
01055           if (string(name) == "is_field3d_group_membership")
01056             continue;
01057 
01058           H5ScopedAopen attr(memberGroup, name, H5P_DEFAULT);
01059           H5ScopedAget_space attrSpace(attr);
01060           H5ScopedAget_type attrType(attr);           
01061           H5T_class_t typeClass = H5Tget_class(attrType);
01062 
01063           if (typeClass == H5T_STRING) { 
01064             string value;
01065             if (!readAttribute(memberGroup, name, value)) {
01066               Msg::print(Msg::SevWarning, 
01067                          "Failed to read group membership data  " 
01068                         + string(name));
01069               continue;
01070             }
01071 
01072             {
01073               boost::char_separator<char> sep(" :");
01074               Tok tok(value, sep);
01075               string new_value;
01076               for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
01077 
01078                 string fieldgroup = *beg; ++beg;
01079                 fieldgroup = removeUniqueId(fieldgroup) + ":" + *beg; ++beg;
01080                 new_value += fieldgroup + " "; 
01081               }
01082 
01083               m_groupMembership[name] = value;
01084               gpMembershipMap[name] = new_value;
01085             }
01086           }
01087         }
01088       }
01089     }
01090   }
01091 
01092   return true;
01093 }
01094 
01095 
01096 //----------------------------------------------------------------------------//
01097 // Field3DFile-related callback functions
01098 //----------------------------------------------------------------------------//
01099 
01100 namespace InputFile {
01101 
01102 //----------------------------------------------------------------------------//
01103 
01104 herr_t parsePartitions(hid_t loc_id, const char *itemName, 
01105                        const H5L_info_t *linfo, void *opdata)
01106 {
01107   herr_t          status;
01108   H5O_info_t      infobuf;
01109 
01110   status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
01111 
01112   if (status < 0) {
01113     return -1;
01114   }
01115   
01116   if (infobuf.type == H5O_TYPE_GROUP) {
01117 
01118     // Check that we have a name 
01119     if (!itemName) {
01120       return -1;
01121     }
01122 
01123     // check that this group is not "groupMembership"
01124     if (string(itemName) != "field3d_group_membership" &&
01125         string(itemName) != "field3d_global_metadata")
01126     { 
01127 
01128       // Get a pointer to the file data structure
01129       Field3DInputFile* fileObject = static_cast<Field3DInputFile*>(opdata);
01130       if (!fileObject) {
01131         return -1;
01132       }
01133       
01134       return fileObject->parsePartition(loc_id, itemName);
01135     }
01136   }
01137   return 0;
01138 }
01139 
01140 //----------------------------------------------------------------------------//
01141 
01142 herr_t parseLayers(hid_t loc_id, const char *itemName, 
01143                    const H5L_info_t *linfo, void *opdata)
01144 {
01145   herr_t          status;
01146   H5O_info_t      infobuf;
01147   
01148   status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
01149 
01150   if (infobuf.type == H5O_TYPE_GROUP) {
01151 
01152     // Check that we have a name 
01153     if (!itemName)
01154       return -1;
01155 
01156     // Get a pointer to the file data structure
01157     ParseLayersInfo* info = static_cast<ParseLayersInfo*>(opdata);
01158     if (!info) 
01159       return -1;
01160 
01161     // Open up the layer group
01162     H5ScopedGopen layerGroup(loc_id, itemName);
01163 
01164     // Check if it's a layer
01165     string classType;
01166     try {
01167       if (!readAttribute(layerGroup.id(), "class_type", classType)) {
01168         return 0;
01169       }
01170       if (classType == string("field3d_layer")) 
01171         return info->file->parseLayer(layerGroup.id(), info->partitionName,
01172                                       itemName);
01173                                    
01174     }
01175     catch (MissingAttributeException &e) {
01176       
01177     }
01178     return 0;
01179 
01180   }
01181 
01182   return 0;
01183 }
01184 
01185 //----------------------------------------------------------------------------//
01186 
01187 } // namespace InputFile
01188 
01189 //----------------------------------------------------------------------------//
01190 // Field3DOutputFile implementations
01191 //----------------------------------------------------------------------------//
01192 
01193 Field3DOutputFile::Field3DOutputFile() 
01194 { 
01195   // Empty
01196 }
01197 
01198 //----------------------------------------------------------------------------//
01199 
01200 Field3DOutputFile::~Field3DOutputFile() 
01201 { 
01202 
01203 }
01204 
01205 //----------------------------------------------------------------------------//
01206 
01209 bool Field3DOutputFile::create(const string &filename, CreateMode cm)
01210 {
01211   closeInternal();
01212 
01213   bool success = true;
01214 
01215   try {
01216 
01217     hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
01218     H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
01219 
01220     // Create new file
01221     switch (cm) {
01222     case OverwriteMode:
01223       m_file = H5Fcreate(filename.c_str(), 
01224                          H5F_ACC_TRUNC, H5P_DEFAULT, faid);
01225       break;
01226     case FailOnExisting:
01227       m_file = H5Fcreate(filename.c_str(), 
01228                          H5F_ACC_EXCL, H5P_DEFAULT, faid);
01229       break;
01230     }
01231     
01232     // Check that file was created
01233     if (m_file < 0)
01234       throw ErrorCreatingFileException(filename);
01235     
01236     // Create a version attribute on the root node
01237     if (!writeAttribute(m_file, k_versionAttrName, 3,
01238                         k_currentFileVersion[0])) {
01239       Msg::print(Msg::SevWarning, "Adding version number.");
01240       closeInternal();
01241       return false;
01242     }
01243 
01244   }
01245   catch (ErrorCreatingFileException &e) {
01246     Msg::print(Msg::SevWarning, "Couldn't create file: " + string(e.what()) );
01247     success = false;
01248   } 
01249   catch (WriteAttributeException &e) {
01250     Msg::print(Msg::SevWarning, "In file : " + filename +
01251               " - Couldn't add attribute " + string(e.what()) );
01252     success = false;
01253   }
01254   catch (...) {
01255     Msg::print(Msg::SevWarning, 
01256                "Unknown error when creating file: " + filename );
01257     success = false;
01258   }
01259 
01260   return success;
01261 }
01262 
01263 //----------------------------------------------------------------------------//
01264 
01265 bool Field3DOutputFile::writeMapping(hid_t partitionGroup, 
01266                                      FieldMapping::Ptr mapping)
01267 {
01268   try {
01269     // Make a group under the partition to store the mapping data
01270     H5ScopedGcreate mappingGroup(partitionGroup, k_mappingStr);
01271     if (mappingGroup.id() < 0)
01272       throw CreateGroupException(k_mappingStr);
01273     // Let FieldMappingIO handle the rest
01274     if (!writeFieldMapping(mappingGroup.id(), mapping))
01275       throw WriteMappingException(k_mappingStr);       
01276   }
01277   catch (CreateGroupException &e) {
01278     Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
01279     throw WriteMappingException(k_mappingStr);
01280   }
01281   return true;
01282 }
01283 
01284 //----------------------------------------------------------------------------//
01285 
01286 bool Field3DOutputFile::writeMetadata(hid_t metadataGroup, FieldBase::Ptr field)
01287 {
01288   using namespace Hdf5Util;
01289 
01290   {
01291     FieldMetadata<FieldBase>::StrMetadata::const_iterator i = 
01292       field->metadata().strMetadata().begin();
01293     FieldMetadata<FieldBase>::StrMetadata::const_iterator end = 
01294       field->metadata().strMetadata().end();
01295     for (; i != end; ++i) {
01296       if (!writeAttribute(metadataGroup, i->first, i->second))
01297       {
01298         Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
01299         return false;
01300       }
01301     }
01302   }
01303 
01304   {
01305     FieldMetadata<FieldBase>::IntMetadata::const_iterator i = 
01306       field->metadata().intMetadata().begin();
01307     FieldMetadata<FieldBase>::IntMetadata::const_iterator end = 
01308       field->metadata().intMetadata().end();
01309     for (; i != end; ++i) {
01310       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01311       {
01312         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01313         return false;
01314       }
01315     }
01316   }
01317 
01318   {
01319     FieldMetadata<FieldBase>::FloatMetadata::const_iterator i = 
01320       field->metadata().floatMetadata().begin();
01321     FieldMetadata<FieldBase>::FloatMetadata::const_iterator end = 
01322       field->metadata().floatMetadata().end();
01323     for (; i != end; ++i) {
01324       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01325       {
01326         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01327         return false;
01328       }
01329     }
01330   }
01331 
01332   {
01333     FieldMetadata<FieldBase>::VecIntMetadata::const_iterator i = 
01334       field->metadata().vecIntMetadata().begin();
01335     FieldMetadata<FieldBase>::VecIntMetadata::const_iterator end = 
01336       field->metadata().vecIntMetadata().end();
01337     for (; i != end; ++i) {
01338       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01339       {
01340         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01341         return false;
01342       }
01343     }
01344   }
01345 
01346   {
01347     FieldMetadata<FieldBase>::VecFloatMetadata::const_iterator i = 
01348       field->metadata().vecFloatMetadata().begin();
01349     FieldMetadata<FieldBase>::VecFloatMetadata::const_iterator end = 
01350       field->metadata().vecFloatMetadata().end();
01351     for (; i != end; ++i) {
01352       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01353       {
01354         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01355         return false;
01356       }
01357     }
01358 
01359   }
01360 
01361   return true;
01362 
01363 }
01364 
01365 //----------------------------------------------------------------------------//
01366 
01367 bool Field3DOutputFile::writeMetadata(hid_t metadataGroup)
01368 {
01369   using namespace Hdf5Util;
01370 
01371   {
01372     FieldMetadata<Field3DFileBase>::StrMetadata::const_iterator i = 
01373       metadata().strMetadata().begin();
01374     FieldMetadata<Field3DFileBase>::StrMetadata::const_iterator end = 
01375       metadata().strMetadata().end();
01376     for (; i != end; ++i) {
01377       if (!writeAttribute(metadataGroup, i->first, i->second))
01378       {
01379         Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
01380         return false;
01381       }
01382     }
01383   }
01384 
01385   {
01386     FieldMetadata<Field3DFileBase>::IntMetadata::const_iterator i = 
01387       metadata().intMetadata().begin();
01388     FieldMetadata<Field3DFileBase>::IntMetadata::const_iterator end = 
01389       metadata().intMetadata().end();
01390     for (; i != end; ++i) {
01391       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01392       {
01393         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01394         return false;
01395       }
01396     }
01397   }
01398 
01399   {
01400     FieldMetadata<Field3DFileBase>::FloatMetadata::const_iterator i = 
01401       metadata().floatMetadata().begin();
01402     FieldMetadata<Field3DFileBase>::FloatMetadata::const_iterator end = 
01403       metadata().floatMetadata().end();
01404     for (; i != end; ++i) {
01405       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01406       {
01407         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01408         return false;
01409       }
01410     }
01411   }
01412 
01413   {
01414     FieldMetadata<Field3DFileBase>::VecIntMetadata::const_iterator i = 
01415       metadata().vecIntMetadata().begin();
01416     FieldMetadata<Field3DFileBase>::VecIntMetadata::const_iterator end = 
01417       metadata().vecIntMetadata().end();
01418     for (; i != end; ++i) {
01419       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01420       {
01421         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01422         return false;
01423       }
01424     }
01425   }
01426 
01427   {
01428     FieldMetadata<Field3DFileBase>::VecFloatMetadata::const_iterator i = 
01429       metadata().vecFloatMetadata().begin();
01430     FieldMetadata<Field3DFileBase>::VecFloatMetadata::const_iterator end = 
01431       metadata().vecFloatMetadata().end();
01432     for (; i != end; ++i) {
01433       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01434       {
01435         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01436         return false;
01437       }
01438     }
01439 
01440   }
01441 
01442   return true;
01443 
01444 }
01445 
01446 //----------------------------------------------------------------------------//
01447 
01448 bool 
01449 Field3DOutputFile::writeGlobalMetadata()
01450 {
01451 
01452   // Add metadata group and write it out  
01453   H5ScopedGcreate metadataGroup(m_file, "field3d_global_metadata");
01454   if (metadataGroup.id() < 0) {
01455     Msg::print(Msg::SevWarning, "Error creating group: file metadata");
01456     return false;
01457   }  
01458   if (!writeMetadata(metadataGroup.id())) {
01459     Msg::print(Msg::SevWarning, "Error writing file metadata.");
01460     return false;
01461   }    
01462  
01463   return true;
01464 }
01465 
01466 //----------------------------------------------------------------------------//
01467 
01468 bool 
01469 Field3DOutputFile::writeGroupMembership()
01470 {
01471   using namespace std;
01472   using namespace Hdf5Util;
01473 
01474   if (!m_groupMembership.size())
01475     return true;
01476 
01477   H5ScopedGcreate group(m_file, "field3d_group_membership");
01478   if (group < 0) {
01479     Msg::print(Msg::SevWarning, 
01480                "Error creating field3d_group_membership group.");      
01481     return false;
01482   } 
01483 
01484   if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
01485     Msg::print(Msg::SevWarning, 
01486                "Failed to write field3d_group_membership attribute.");
01487     return false;
01488   }    
01489 
01490   std::map<std::string, std::string>::const_iterator iter = 
01491     m_groupMembership.begin();
01492   std::map<std::string, std::string>::const_iterator iEnd = 
01493     m_groupMembership.end();
01494   
01495   for (; iter != iEnd; ++iter) {
01496     if (!writeAttribute(group, iter->first, iter->second)) {
01497       Msg::print(Msg::SevWarning, 
01498                  "Failed to write groupMembership string: "+ iter->first);
01499       return false;
01500     }        
01501   }
01502   
01503   return true;
01504 }
01505 
01506 //----------------------------------------------------------------------------//
01507 // Debug
01508 //----------------------------------------------------------------------------//
01509 
01510 void Field3DFileBase::printHierarchy() const
01511 {
01512   // For each partition
01513   for (PartitionList::const_iterator i = m_partitions.begin();
01514        i != m_partitions.end(); ++i) {
01515     cout << "Name: " << (**i).name << endl;
01516     if ((**i).mapping)
01517       cout << "  Mapping: " << (**i).mapping->className() << endl;
01518     else 
01519       cout << "  Mapping: NULL" << endl;
01520     cout << "  Scalar layers: " << endl;
01521     vector<string> sNames;
01522     (**i).getScalarLayerNames(sNames);
01523     for_each(sNames.begin(), sNames.end(), print<string>(4));
01524     cout << "  Vector layers: " << endl;
01525     vector<string> vNames;
01526     (**i).getVectorLayerNames(vNames);
01527     for_each(vNames.begin(), vNames.end(), print<string>(4));
01528   }
01529 }
01530 
01531 //----------------------------------------------------------------------------//
01532 // Function Implementations
01533 //----------------------------------------------------------------------------//
01534 
01535 bool writeField(hid_t layerGroup, FieldBase::Ptr field)
01536 {
01537   ClassFactory &factory = ClassFactory::singleton();
01538     
01539   FieldIO::Ptr io = factory.createFieldIO(field->className());
01540   assert(io != 0);
01541   if (!io) {
01542     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01543                field->className());
01544     return false;
01545   }
01546 
01547   // Add class name attribute
01548   if (!writeAttribute(layerGroup, k_classNameAttrName, 
01549                       field->className())) {
01550     Msg::print(Msg::SevWarning, "Error adding class name attribute.");
01551     return false;
01552   }
01553 
01554   return io->write(layerGroup, field);
01555 }
01556 
01557 //----------------------------------------------------------------------------//
01558 
01559 FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
01560 {
01561   ClassFactory &factory = ClassFactory::singleton();
01562 
01563   std::string className;
01564 
01565   if (!readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
01566     Msg::print(Msg::SevWarning, "Couldn't find " + k_mappingTypeAttrName + 
01567               " attribute");
01568     return FieldMapping::Ptr();    
01569   }
01570 
01571   FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
01572   assert(io != 0);
01573   if (!io) {
01574     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01575                className);
01576     return FieldMapping::Ptr();
01577   }
01578 
01579 
01580   FieldMapping::Ptr mapping = io->read(mappingGroup);
01581   if (!mapping) {
01582     Msg::print(Msg::SevWarning, "Couldn't read mapping");
01583     return FieldMapping::Ptr();
01584   }
01585   
01586   return mapping;
01587 }
01588 
01589 //----------------------------------------------------------------------------//
01590 
01591 bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
01592 {
01593   ClassFactory &factory = ClassFactory::singleton();
01594 
01595   std::string className = mapping->className();
01596 
01597   if (!writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
01598     Msg::print(Msg::SevWarning, "Couldn't add " + className + " attribute");
01599     return false;
01600   }
01601 
01602   FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
01603   assert(io != 0);
01604   if (!io) {
01605     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01606                className);
01607     return false;
01608   }
01609 
01610   return io->write(mappingGroup, mapping);
01611 }
01612 
01613 //----------------------------------------------------------------------------//
01614 
01615 FIELD3D_NAMESPACE_SOURCE_CLOSE
01616 
01617 //----------------------------------------------------------------------------//