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 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
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 += concat(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