CLAM-Development  1.4.0
XMLStorage.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
23 // XMLStorage.cxx
24 // Description: A storage in XML format for CLAM objects
26 
27 #include "XMLStorage.hxx"
28 
29 
30 #include "XMLable.hxx"
31 #include "Component.hxx"
32 #include "Assert.hxx"
33 #include "DomDocumentHandler.hxx"
34 #include <fstream>
35 #include <list>
36 #include <string>
37 #include <sstream>
38 
39 namespace CLAM
40 {
41  static std::string join(const std::list<std::string> & strings)
42  {
43  std::string result;
44  std::list<std::string>::const_iterator it;
45  for (it=strings.begin(); it!=strings.end(); it++)
46  {
47  result += *it + "\n";
48  }
49  return result;
50  }
51  void XmlStorage::Read(std::istream & is)
52  {
53  _documentHandler->read(is);
54  }
55 
56  void XmlStorage::Create(const std::string & name)
57  {
58  _documentHandler->create(name.c_str());
59  _lastWasContent=false;
60  }
61 
62  void XmlStorage::WriteSelection(std::ostream & os)
63  {
64  _documentHandler->writeSelection(os,_useIndentation);
65  }
66 
67  void XmlStorage::WriteDocument(std::ostream & os)
68  {
69  _documentHandler->writeDocument(os,_useIndentation);
70  }
71 
72  void XmlStorage::DumpObject(const Component & component)
73  {
74  DomDocumentHandler::WritingContext rootContext(*_documentHandler);
75  _documentHandler->SetWritingContext( & rootContext);
76  component.StoreOn(*this);
77  }
78 
80  {
81  DomDocumentHandler::ReadingContext rootContext(*_documentHandler);
82  _documentHandler->SetReadingContext(&rootContext);
83  component.LoadFrom(*this);
84  _documentHandler->GetReadingContext()->release();
85  _errors += join(_documentHandler->GetReadingContext()->errors());
86  if (_errors!="")
87  throw XmlStorageErr(_errors);
88  }
89 
90  void XmlStorage::Select(const std::string & path)
91  {
92  _documentHandler->selectPath(path.c_str());
93  }
94 
95  void XmlStorage::UseIndentation(bool useIndentation) {
96  _useIndentation=useIndentation;
97  }
98 
99 // Static sumarized interface
101  {
102  _documentHandler=new DomDocumentHandler;
103  _documentHandler->SetReadingContext(0);
104  _documentHandler->SetWritingContext(0);
105  _lastWasContent = true;
106  _useIndentation = false;
107  }
109  {
110  delete _documentHandler;
111  }
112 
113  void XmlStorage::Restore(Component & obj, const std::string & filename)
114  {
115  std::ifstream is(filename.c_str());
116  std::ostringstream os;
117  os << "Restoring from an unopened file with filename <" << filename << ">" << std::flush;
118  CLAM_WARNING(is.is_open(),os.str().c_str());
119  Restore(obj,is);
120  }
121 
122  void XmlStorage::Dump(const Component & obj, const std::string & rootName, const std::string & filename)
123  {
124  std::ofstream os(filename.c_str());
125  CLAM_WARNING(os.is_open(),"Dumping on an unopened file");
126  Dump(obj,rootName,os);
127  }
128 
129  void XmlStorage::AppendToDocument(const Component & obj, const std::string & path, const std::string & filename)
130  {
131  XmlStorage storage;
132  {
133  std::ifstream is (filename.c_str());
134  storage.Read(is);
135  }
136  storage.Select(path);
137  storage.DumpObject(obj);
138  storage.Select("/");
139  {
140  std::ofstream os(filename.c_str());
141  storage.WriteDocument(os);
142  }
143  }
144 
145 
146 // Interface for Components to load/store their subitems
147  void XmlStorage::Store(const Storable & storable)
148  {
149  const XMLable * xmlable = dynamic_cast<const XMLable *>(&storable);
150  const char * name = xmlable->XMLName();
151  if (!name)
152  {
153  StoreContentAndChildren(xmlable);
154  return;
155  }
156  if (xmlable->IsXMLAttribute())
157  {
158  _documentHandler->GetWritingContext()->addAttribute(name,xmlable->XMLContent().c_str());
159  return;
160  }
161  if (xmlable->IsXMLElement())
162  {
163  _lastWasContent=false;
164  DomDocumentHandler::WritingContext newContext(_documentHandler->GetWritingContext(), name);
165  _documentHandler->SetWritingContext(& newContext);
166  StoreContentAndChildren(xmlable);
167  _documentHandler->SetWritingContext(newContext.release());
168  _lastWasContent=false;
169  return;
170  }
171  CLAM_ASSERT(false,"A weird XMLable inserted");
172  }
173 
174  bool XmlStorage::Load(Storable & storable)
175  {
176  XMLable * xmlable = dynamic_cast<XMLable *>(&storable);
177  if (!xmlable) return false;
178 
179  if (xmlable->IsXMLText())
180  return LoadContentAndChildren(xmlable);
181 
182  if (xmlable->IsXMLElement())
183  {
184  if (!_documentHandler->GetReadingContext()->findElement(xmlable->XMLName()))
185  return false;
186  DomDocumentHandler::ReadingContext innerContext(_documentHandler->GetReadingContext(), xmlable->XMLName());
187  _documentHandler->SetReadingContext(&innerContext);
188  LoadContentAndChildren(xmlable);
189  _documentHandler->SetReadingContext(innerContext.release());
190  _errors += join(innerContext.errors());
191  return true;
192  }
193 
194  // TODO: Test Attributes
195  if (xmlable->IsXMLAttribute())
196  {
197  std::stringstream stream;
198  if (!_documentHandler->GetReadingContext()->extractAttribute(xmlable->XMLName(), stream))
199  return false;
200  return xmlable->XMLContent(stream);
201  }
202 
203  CLAM_ASSERT(false, "A weird XMLable inserted");
204  return false;
205  }
206 
207 // Private helper functions
208 
209  bool XmlStorage::LoadContentAndChildren(XMLable* xmlable)
210  {
211  bool result = xmlable->XMLContent(_documentHandler->GetReadingContext()->reachableContent());
212  Component * component = dynamic_cast<Component*>(xmlable);
213  if (component) component->LoadFrom(*this);
214  return result;
215  }
216 
217  void XmlStorage::StoreContentAndChildren(const XMLable * xmlable)
218  {
219  AddContentToElement(xmlable->XMLContent());
220  StoreChildrenIfComponent(xmlable);
221  }
222 
223  void XmlStorage::StoreChildrenIfComponent(const XMLable * xmlable)
224  {
225  const Component * component = dynamic_cast<const Component *>(xmlable);
226  if (component) component->StoreOn(*this);
227  }
228 
229  void XmlStorage::AddContentToElement(const std::string & content)
230  {
231  if (content=="") return;
232  if (_lastWasContent)
233  _documentHandler->GetWritingContext()->addContent(" ");
234  _documentHandler->GetWritingContext()->addContent(content.c_str());
235  _lastWasContent = true;
236  }
237 
238 }
239