CLAM-Development
1.1
|
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 concat(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 += concat(_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 += concat(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