XMLStorage.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00024
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
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
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
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
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