Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

xmlsource.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/ 
00020 #include "xmlsource.h"
00021 #include "../xmlencodeattr.h"
00022 
00023 /* OPIE */
00024 #include <opie2/odebug.h>
00025 using namespace Opie::Core;
00026 
00027 /* QT */
00028 #include <qdict.h>
00029 #include <qtextstream.h>
00030 
00031 /* STD */
00032 #include <stdlib.h>
00033 
00034 DBXml::DBXml(DBStore *d) 
00035 {
00036     dstore = d;
00037 } 
00038 
00039 QString DBXml::type()
00040 {
00041     return "xml";
00042 }
00043 
00044 bool DBXml::openSource(QIODevice *inDev)
00045 {
00046     bool ok;
00047 
00048     DBXmlHandler h(dstore); 
00049 
00050     QTextStream tsIn(inDev);
00051     QXmlInputSource source(tsIn); 
00052     QXmlSimpleReader reader; 
00053     reader.setContentHandler(&h); 
00054     reader.setErrorHandler(&h); 
00055     ok = reader.parse(source); 
00056 
00057     return ok;
00058 } 
00059 
00060 bool DBXml::saveSource(QIODevice *outDev)
00061 {
00062     int i;
00063     DataElem *elem;
00064     KeyList *k;
00065 
00066     QTextStream outstream(outDev);
00067 
00068     outstream << "<database name=\"" << dstore->getName() << "\">" << endl;
00069     outstream << "<header>" << endl;
00070     
00071     k = dstore->getKeys();
00072     KeyListIterator it(*k);
00073     while(it.current()) {
00074         if (!it.current()->delFlag()) {
00075             outstream << "<key name=\"KEYID" << it.currentKey() << "\" ";
00076             outstream << "type=\"" 
00077                       << TVVariant::typeToName(it.current()->type()) 
00078                       << "\">";
00079             outstream << encodeAttr(it.current()->name()) << "</key>" << endl;
00080         }
00081         ++it;
00082     }
00083 
00084     outstream << "</header>" << endl;
00085 
00086     dstore->first();
00087 
00088     do {
00089         elem = dstore->getCurrentData();
00090         if (!elem)
00091             break;
00092         outstream << "<record>" << endl;
00093         it.toFirst();
00094         while (it.current()) {
00095             i = it.currentKey();
00096             if (elem->hasValidValue(i)) {
00097                 outstream << "<KEYID" << i << ">";
00098                 if (dstore->getKeyType(i) == TVVariant::Date) {
00099                     // dates in files are different from displayed dates
00100                     QDate date = elem->getField(i).toDate();
00101                     outstream << date.day() << "/" 
00102                               << date.month() << "/"
00103                               << date.year();
00104                 } else {
00105                     outstream << encodeAttr(elem->toQString(i));
00106                 }
00107                 outstream << "</KEYID" << i << ">" << endl;
00108             }
00109             ++it;
00110         }
00111         outstream << "</record>" << endl;
00112     } while(dstore->next());
00113     
00114     outstream << "</database>" << endl;
00115     return TRUE;
00116 }
00117 
00118 DBXml::~DBXml() {}
00119 
00134 DBXmlHandler::DBXmlHandler(DBStore *ds)
00135 {
00136         data_store = ds;
00137     current_keyrep = 0;
00138 }
00139 
00143 DBXmlHandler::~DBXmlHandler()
00144 {
00145 }
00146 
00147 QString DBXmlHandler::errorProtocol()
00148 {
00149     owarn << "Error reading file" << oendl; 
00150         return errorProt;
00151 }
00152 
00153 bool DBXmlHandler::startDocument()
00154 {
00155         errorProt = "";
00156         state = StateInit;
00157         return TRUE;
00158 }
00159 
00160 bool DBXmlHandler::startElement(const QString&, const QString&, 
00161                                                 const QString& qName, const QXmlAttributes& atts)
00162 {
00163         if (state == StateInit && qName == "database") {
00164                 // First thing it expects is a <document name="..."> tag
00165                 state = StateDocument;
00166                 data_store->setName(atts.value("name"));
00167                 return TRUE;
00168         }
00169     if (state == StateDocument && qName == "header") {
00170         state = StateHeader;
00171         if (current_keyrep) delete current_keyrep;
00172         current_keyrep = new KeyList();
00173         return TRUE;
00174     }
00175     if (state == StateHeader && qName == "key") {
00176         /* Ok, adding a new key to our KeyList TODO */
00177         state = StateKey;
00178         last_key_type = TVVariant::String;
00179         key = atts.value("name");
00180         if (key.isEmpty()) {
00181             owarn << "empty key name" << oendl; 
00182             return FALSE;
00183         }
00184         if(!atts.value("type").isEmpty())
00185             last_key_type = TVVariant::nameToType(atts.value("type"));
00186         return TRUE;
00187     }
00188         if (state == StateDocument && qName == "record") {
00189                 state = StateRecord;
00190         current_data = new DataElem(data_store);
00191                 // Now expecting a <record> tag
00192                 return TRUE;
00193         }
00194         if (state == StateRecord) {
00195         state = StateField;
00196         /* the qName is the name of a key */
00197         if (!keyIndexList[qName]) {
00198             /* invalid key, we failed */
00199             owarn << "Invalid key in record" << oendl; 
00200             return FALSE;
00201         }
00202         keyIndex = *keyIndexList[qName];
00203                 return TRUE;
00204         }
00205     owarn << "Unable to determine tag type" << oendl; 
00206         return FALSE;
00207 }
00208 
00209 bool DBXmlHandler::endElement(const QString&, const QString&, 
00210                                                                 const QString& qName)
00211 {
00212         switch(state) {
00213         case StateField:
00214                 // TODO checks 'could' be done of the popped value
00215         state = StateRecord;
00216                 break;
00217         case StateKey:
00218                 // TODO checks 'could' be done of the popped value
00219         state = StateHeader;
00220                 break;
00221     case StateHeader:
00222         data_store->setKeys(current_keyrep);
00223         state = StateDocument;
00224         break;
00225         case StateRecord:
00226         data_store->addItem(current_data);
00227                 state = StateDocument;
00228                 break;
00229         case StateDocument:
00230                 // we are done... 
00231                 break;
00232         default:
00233                 // should only get a 'endElement' from one of the above states.
00234         owarn << "Invalid end tag" << oendl; 
00235                 return FALSE;
00236                 break;
00237         }
00238         return TRUE;
00239 }
00240 
00241 bool DBXmlHandler::characters(const QString& ch)
00242 {
00243         // this is where the 'between tag' stuff happens.
00244         // e.g. the stuff between tags.
00245         QString ch_simplified = ch.simplifyWhiteSpace();
00246 
00247         if (ch_simplified.isEmpty())
00248                 return TRUE;
00249 
00250         if (state == StateKey) {
00251         int *tmp_val = new int;
00252         /* We just grabbed the display name of a key */
00253         *tmp_val = current_keyrep->addKey(ch_simplified, last_key_type);
00254         keyIndexList.insert(key, tmp_val);
00255                 return TRUE;
00256         }
00257         if (state == StateField) {
00258         /* Ok, need to add data here */
00259         current_data->setField(keyIndex, ch_simplified);
00260                 return TRUE;
00261         }
00262         
00263     owarn << "Junk characters found... ignored" << oendl; 
00264     return TRUE;
00265 }
00266 
00267 QString DBXmlHandler::errorString()
00268 {
00269         return "the document is not in the expected file format";
00270 }
00271 
00272 bool DBXmlHandler::warning(const QXmlParseException& exception)
00273 {
00274     errorProt += QString("warning parsing error: %1 in line %2, column %3\n" )
00275         .arg(exception.message())
00276         .arg(exception.lineNumber())
00277         .arg(exception.columnNumber());
00278 
00279     owarn << errorProt << oendl; 
00280     return QXmlDefaultHandler::fatalError(exception);
00281 }
00282 
00283 bool DBXmlHandler::error(const QXmlParseException& exception)
00284 {
00285     errorProt += QString("error parsing error: %1 in line %2, column %3\n" )
00286         .arg(exception.message())
00287         .arg(exception.lineNumber())
00288         .arg(exception.columnNumber());
00289 
00290     owarn << errorProt << oendl; 
00291     return QXmlDefaultHandler::fatalError(exception);
00292 }
00293 
00294 bool DBXmlHandler::fatalError(const QXmlParseException& exception)
00295 {
00296     errorProt += QString("fatal parsing error: %1 in line %2, column %3\n" )
00297         .arg(exception.message())
00298         .arg(exception.lineNumber())
00299         .arg(exception.columnNumber());
00300 
00301     owarn << errorProt << oendl; 
00302     return QXmlDefaultHandler::fatalError(exception);
00303 }

Generated on Sat Nov 5 16:17:08 2005 for OPIE by  doxygen 1.4.2