XMLStorage.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00023 // XMLStorage.cxx
00024 // Description: A storage in XML format for CLAM objects
00026 
00027 #include "XMLStorage.hxx"
00028 
00029 
00030 #include "XMLable.hxx"
00031 #include "Component.hxx"
00032 #include "Assert.hxx"
00033 #include "DomDocumentHandler.hxx"
00034 #include <fstream>
00035 #include <list>
00036 #include <string>
00037 #include <sstream>
00038 
00039 namespace CLAM
00040 {
00041         static std::string join(const std::list<std::string> & strings)
00042         {
00043                 std::string result;
00044                 std::list<std::string>::const_iterator it;
00045                 for (it=strings.begin(); it!=strings.end(); it++)
00046                 {
00047                         result += *it + "\n";
00048                 }
00049                 return result;
00050         }
00051         void XmlStorage::Read(std::istream & is)
00052         {
00053                 _documentHandler->read(is);
00054         }
00055 
00056         void XmlStorage::Create(const std::string & name)
00057         {
00058                 _documentHandler->create(name.c_str());
00059                 _lastWasContent=false;
00060         }
00061 
00062         void XmlStorage::WriteSelection(std::ostream & os)
00063         {
00064                 _documentHandler->writeSelection(os,_useIndentation);
00065         }
00066 
00067         void XmlStorage::WriteDocument(std::ostream & os)
00068         {
00069                 _documentHandler->writeDocument(os,_useIndentation);
00070         }
00071 
00072         void XmlStorage::DumpObject(const Component & component)
00073         {
00074                 DomDocumentHandler::WritingContext rootContext(*_documentHandler);
00075                 _documentHandler->SetWritingContext( & rootContext);
00076                 component.StoreOn(*this);
00077         }
00078 
00079         void XmlStorage::RestoreObject(Component & component)
00080         {
00081                 DomDocumentHandler::ReadingContext rootContext(*_documentHandler);
00082                 _documentHandler->SetReadingContext(&rootContext);
00083                 component.LoadFrom(*this);
00084                 _documentHandler->GetReadingContext()->release();
00085                 _errors += join(_documentHandler->GetReadingContext()->errors());
00086                 if (_errors!="")
00087                         throw XmlStorageErr(_errors);
00088         }
00089 
00090         void XmlStorage::Select(const std::string & path)
00091         {
00092                 _documentHandler->selectPath(path.c_str());
00093         }
00094 
00095         void XmlStorage::UseIndentation(bool useIndentation) {
00096                 _useIndentation=useIndentation;
00097         }
00098 
00099 // Static sumarized interface
00100         XmlStorage::XmlStorage()
00101         {
00102                 _documentHandler=new DomDocumentHandler;
00103                 _documentHandler->SetReadingContext(0);
00104                 _documentHandler->SetWritingContext(0);
00105                 _lastWasContent = true;
00106                 _useIndentation = false;
00107         }
00108         XmlStorage::~XmlStorage()
00109         {
00110                 delete _documentHandler;
00111         }
00112 
00113         void XmlStorage::Restore(Component & obj, const std::string & filename)
00114         {
00115                 std::ifstream is(filename.c_str());
00116                 std::ostringstream os;
00117                 os << "Restoring from an unopened file with filename <" << filename << ">" << std::flush;
00118                 CLAM_WARNING(is.is_open(),os.str().c_str());
00119                 Restore(obj,is);
00120         }
00121 
00122         void XmlStorage::Dump(const Component & obj, const std::string & rootName, const std::string & filename)
00123         {
00124                 std::ofstream os(filename.c_str());
00125                 CLAM_WARNING(os.is_open(),"Dumping on an unopened file");
00126                 Dump(obj,rootName,os);
00127         }
00128 
00129         void XmlStorage::AppendToDocument(const Component & obj, const std::string & path, const std::string & filename)
00130         {
00131                 XmlStorage storage;
00132                 {
00133                         std::ifstream is (filename.c_str());
00134                         storage.Read(is);
00135                 }
00136                 storage.Select(path);
00137                 storage.DumpObject(obj);
00138                 storage.Select("/");
00139                 {
00140                         std::ofstream os(filename.c_str());
00141                         storage.WriteDocument(os);
00142                 }
00143         }
00144 
00145 
00146 // Interface for Components to load/store their subitems
00147         void XmlStorage::Store(const Storable & storable)
00148         {
00149                 const XMLable * xmlable = dynamic_cast<const XMLable *>(&storable);
00150                 const char * name = xmlable->XMLName();
00151                 if (!name)
00152                 {
00153                         StoreContentAndChildren(xmlable);
00154                         return;
00155                 }
00156                 if (xmlable->IsXMLAttribute())
00157                 {
00158                         _documentHandler->GetWritingContext()->addAttribute(name,xmlable->XMLContent().c_str());
00159                         return;
00160                 }
00161                 if (xmlable->IsXMLElement())
00162                 {
00163                         _lastWasContent=false;
00164                         DomDocumentHandler::WritingContext newContext(_documentHandler->GetWritingContext(), name);
00165                         _documentHandler->SetWritingContext(& newContext);
00166                         StoreContentAndChildren(xmlable);
00167                         _documentHandler->SetWritingContext(newContext.release());
00168                         _lastWasContent=false;
00169                         return;
00170                 }
00171                 CLAM_ASSERT(false,"A weird XMLable inserted");
00172         }
00173 
00174         bool XmlStorage::Load(Storable & storable)
00175         {
00176                 XMLable * xmlable = dynamic_cast<XMLable *>(&storable);
00177                 if (!xmlable) return false;
00178 
00179                 if (xmlable->IsXMLText())
00180                         return LoadContentAndChildren(xmlable);
00181 
00182                 if (xmlable->IsXMLElement())
00183                 {
00184                         if (!_documentHandler->GetReadingContext()->findElement(xmlable->XMLName()))
00185                                 return false;
00186                         DomDocumentHandler::ReadingContext innerContext(_documentHandler->GetReadingContext(), xmlable->XMLName());
00187                         _documentHandler->SetReadingContext(&innerContext);
00188                         LoadContentAndChildren(xmlable);
00189                         _documentHandler->SetReadingContext(innerContext.release());
00190                         _errors += join(innerContext.errors());
00191                         return true;
00192                 }
00193 
00194                 // TODO: Test Attributes
00195                 if (xmlable->IsXMLAttribute())
00196                 {
00197                         std::stringstream stream;
00198                         if (!_documentHandler->GetReadingContext()->extractAttribute(xmlable->XMLName(), stream))
00199                                 return false;
00200                         return xmlable->XMLContent(stream);
00201                 }
00202 
00203                 CLAM_ASSERT(false, "A weird XMLable inserted");
00204                 return false;
00205         }
00206 
00207 // Private helper functions
00208 
00209         bool XmlStorage::LoadContentAndChildren(XMLable* xmlable)
00210         {
00211                 bool result = xmlable->XMLContent(_documentHandler->GetReadingContext()->reachableContent());
00212                 Component * component = dynamic_cast<Component*>(xmlable);
00213                 if (component) component->LoadFrom(*this);
00214                 return result;
00215         }
00216 
00217         void XmlStorage::StoreContentAndChildren(const XMLable * xmlable)
00218         {
00219                 AddContentToElement(xmlable->XMLContent());
00220                 StoreChildrenIfComponent(xmlable);
00221         }
00222 
00223         void XmlStorage::StoreChildrenIfComponent(const XMLable * xmlable)
00224         {
00225                 const Component * component = dynamic_cast<const Component *>(xmlable);
00226                 if (component) component->StoreOn(*this);
00227         }
00228 
00229         void XmlStorage::AddContentToElement(const std::string & content)
00230         {
00231                 if (content=="") return;
00232                 if (_lastWasContent)
00233                         _documentHandler->GetWritingContext()->addContent(" ");
00234                 _documentHandler->GetWritingContext()->addContent(content.c_str());
00235                 _lastWasContent = true;
00236         }
00237 
00238 }
00239 
Generated by  doxygen 1.6.3