Reader.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Riegel         <juergen.riegel@web.de>                  *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  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 Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <xercesc/sax/SAXParseException.hpp>
00028 # include <xercesc/sax/SAXException.hpp>
00029 # include <xercesc/sax2/XMLReaderFactory.hpp>
00030 # include <xercesc/sax2/SAX2XMLReader.hpp>
00031 #endif
00032 
00033 #include <locale>
00034 
00036 #include "Reader.h"
00037 #include "Exception.h"
00038 #include "Persistence.h"
00039 #include "InputSource.h"
00040 #include "Console.h"
00041 #include "Sequencer.h"
00042 
00043 #include <zipios++/zipios-config.h>
00044 #include <zipios++/zipfile.h>
00045 #include <zipios++/zipinputstream.h>
00046 #include <zipios++/zipoutputstream.h>
00047 #include <zipios++/meta-iostreams.h>
00048 
00049 #include "XMLTools.h"
00050 
00051 XERCES_CPP_NAMESPACE_USE
00052 
00053 using namespace std;
00054 
00055 
00056 
00057 // ---------------------------------------------------------------------------
00058 //  Base::XMLReader: Constructors and Destructor
00059 // ---------------------------------------------------------------------------
00060 
00061 Base::XMLReader::XMLReader(const char* FileName, std::istream& str) 
00062   : DocumentSchema(0), Level(0), _File(FileName)
00063 {
00064 #ifdef _MSC_VER
00065     str.imbue(std::locale::empty());
00066 #else
00067     //FIXME: Check whether this is correct
00068     str.imbue(std::locale::classic());
00069 #endif
00070 
00071     // create the parser
00072     parser = XMLReaderFactory::createXMLReader();
00073     //parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
00074     //parser->setFeature(XMLUni::fgXercesSchema, false);
00075     //parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
00076     //parser->setFeature(XMLUni::fgXercesIdentityConstraintChecking, false);
00077     //parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, false);
00078     //parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
00079     //parser->setFeature(XMLUni::fgXercesDynamic, true);
00080 
00081     parser->setContentHandler(this);
00082     parser->setErrorHandler(this);
00083 
00084     try {
00085         StdInputSource file(str, _File.filePath().c_str());
00086         _valid = parser->parseFirst( file,token);
00087     }
00088     catch (const XMLException& toCatch) {
00089         char* message = XMLString::transcode(toCatch.getMessage());
00090         cerr << "Exception message is: \n"
00091              << message << "\n";
00092         XMLString::release(&message);
00093     }
00094     catch (const SAXParseException& toCatch) {
00095         char* message = XMLString::transcode(toCatch.getMessage());
00096         cerr << "Exception message is: \n"
00097              << message << "\n";
00098         XMLString::release(&message);
00099     }
00100 #ifndef FC_DEBUG
00101     catch (...) {
00102         cerr << "Unexpected Exception \n";
00103     }
00104 #endif
00105 }
00106 
00107 Base::XMLReader::~XMLReader()
00108 {
00109     //  Delete the parser itself.  Must be done prior to calling Terminate, below.
00110     delete parser;
00111 }
00112 
00113 const char* Base::XMLReader::localName(void) const
00114 {
00115     return LocalName.c_str();
00116 }
00117 
00118 unsigned int Base::XMLReader::getAttributeCount(void) const
00119 {
00120     return (unsigned int)AttrMap.size();
00121 }
00122 
00123 long Base::XMLReader::getAttributeAsInteger(const char* AttrName) const
00124 {
00125     AttrMapType::const_iterator pos = AttrMap.find(AttrName);
00126 
00127     if (pos != AttrMap.end())
00128         return atol(pos->second.c_str());
00129     else
00130         // wrong name, use hasAttribute if not shure!
00131         assert(0);
00132 
00133     return 0;
00134 }
00135 
00136 unsigned long Base::XMLReader::getAttributeAsUnsigned(const char* AttrName) const
00137 {
00138     AttrMapType::const_iterator pos = AttrMap.find(AttrName);
00139 
00140     if (pos != AttrMap.end())
00141         return strtoul(pos->second.c_str(),0,10);
00142     else
00143         // wrong name, use hasAttribute if not shure!
00144         assert(0);
00145 
00146     return 0;
00147 }
00148 
00149 double Base::XMLReader::getAttributeAsFloat  (const char* AttrName) const
00150 {
00151     AttrMapType::const_iterator pos = AttrMap.find(AttrName);
00152 
00153     if (pos != AttrMap.end())
00154         return atof(pos->second.c_str());
00155     else
00156         // wrong name, use hasAttribute if not shure!
00157         assert(0);
00158 
00159     return 0.0;
00160 }
00161 
00162 const char*  Base::XMLReader::getAttribute (const char* AttrName) const
00163 {
00164     AttrMapType::const_iterator pos = AttrMap.find(AttrName);
00165 
00166     if (pos != AttrMap.end())
00167         return pos->second.c_str();
00168     else
00169         // wrong name, use hasAttribute if not shure!
00170         assert(0);
00171 
00172     return ""; 
00173 }
00174 
00175 bool Base::XMLReader::hasAttribute (const char* AttrName) const
00176 {
00177     return AttrMap.find(AttrName) != AttrMap.end();
00178 }
00179 
00180 bool Base::XMLReader::read(void)
00181 {
00182     ReadType = None;
00183 
00184     try {
00185         parser->parseNext(token);
00186     }
00187     catch (const XMLException& toCatch) {
00188 #if 0
00189         char* message = XMLString::transcode(toCatch.getMessage());
00190         cerr << "Exception message is: \n"
00191              << message << "\n";
00192         XMLString::release(&message);
00193         return false;
00194 #else
00195         char* message = XMLString::transcode(toCatch.getMessage());
00196         std::string what = message;
00197         XMLString::release(&message);
00198         throw Base::Exception(what);
00199 #endif
00200     }
00201     catch (const SAXParseException& toCatch) {
00202 #if 0
00203         char* message = XMLString::transcode(toCatch.getMessage());
00204         cerr << "Exception message is: \n"
00205              << message << "\n";
00206         XMLString::release(&message);
00207         return false;
00208 #else
00209         char* message = XMLString::transcode(toCatch.getMessage());
00210         std::string what = message;
00211         XMLString::release(&message);
00212         throw Base::XMLParseException(what);
00213 #endif
00214     }
00215     catch (...) {
00216 #if 0
00217         cerr << "Unexpected Exception \n" ;
00218         return false;
00219 #else
00220         throw Base::Exception("Unexpected XML exception");
00221 #endif
00222     }
00223 
00224     return true;
00225 }
00226 
00227 void Base::XMLReader::readElement(const char* ElementName)
00228 {
00229     bool ok;
00230     int currentLevel = Level;
00231     std::string currentName = LocalName;
00232     do {
00233         ok = read(); if (!ok) break;
00234         if (ReadType == EndElement && currentName == LocalName && currentLevel >= Level) {
00235             // we have reached the end of the element when calling this method
00236             // thus we must stop reading on.
00237             break;
00238         }
00239     } while ((ReadType != StartElement && ReadType != StartEndElement) ||
00240              (ElementName && LocalName != ElementName));
00241 }
00242 
00243 void Base::XMLReader::readEndElement(const char* ElementName)
00244 {
00245     // if we are already at the end of the current element
00246     if (ReadType == EndElement && LocalName == ElementName)
00247         return;
00248     bool ok;
00249     do {
00250         ok = read(); if (!ok) break;
00251     } while (ReadType != EndElement || (ElementName && LocalName != ElementName));
00252 }
00253 
00254 void Base::XMLReader::readCharacters(void)
00255 {
00256 }
00257 
00258 void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const
00259 {
00260     // It's possible that not all objects inside the document could be created, e.g. if a module
00261     // is missing that would know these object types. So, there may be data files inside the zip
00262     // file that cannot be read. We simply ignore these files. 
00263     // On the other hand, however, it could happen that a file should be read that is not part of
00264     // the zip file. This happens e.g. if a document is written without GUI up but is read with GUI
00265     // up. In this case the associated GUI document asks for its file which is not part of the ZIP
00266     // file, then.
00267     // In either case it's guaranteed that the order of the files is kept.
00268     zipios::ConstEntryPointer entry;
00269     try {
00270         entry = zipstream.getNextEntry();
00271     }
00272     catch (const std::exception&) {
00273         // There is no further file at all. This can happen if the
00274         // project file was created without GUI
00275         return;
00276     }
00277     std::vector<FileEntry>::const_iterator it = FileList.begin();
00278     Base::SequencerLauncher seq("Importing project files...", FileList.size());
00279     while (entry->isValid() && it != FileList.end()) {
00280         std::vector<FileEntry>::const_iterator jt = it; 
00281         // Check if the current entry is registered, otherwise check the next registered files as soon as
00282         // both file names match
00283         while (jt != FileList.end() && entry->getName() != jt->FileName)
00284             ++jt;
00285         // If this condition is true both file names match and we can read-in the data, otherwise
00286         // no file name for the current entry in the zip was registered.
00287         if (jt != FileList.end()) {
00288             try {
00289                 jt->Object->RestoreDocFile(zipstream);
00290             }
00291             catch(...) {
00292                 // For any exception we just continue with the next file.
00293                 // It doesn't matter if the last reader has read more or
00294                 // less data than the file size would allow.
00295                 // All what we need to do is to notify the user about the
00296                 // failure.
00297                 Base::Console().Error("Reading failed from embedded file: %s\n", entry->toString().c_str());
00298             }
00299             // Go to the next registered file name
00300             it = jt + 1;
00301         }
00302 
00303         seq.next();
00304 
00305         // In either case we must go to the next entry
00306         try {
00307             entry = zipstream.getNextEntry();
00308         }
00309         catch (const std::exception&) {
00310             // there is no further entry
00311             break;
00312         }
00313     }
00314 }
00315 
00316 const char *Base::XMLReader::addFile(const char* Name, Base::Persistence *Object)
00317 {
00318     FileEntry temp;
00319     temp.FileName = Name;
00320     temp.Object = Object;
00321 
00322     FileList.push_back(temp);
00323     FileNames.push_back( temp.FileName );
00324 
00325     return Name;
00326 }
00327 
00328 const std::vector<std::string>& Base::XMLReader::getFilenames() const
00329 {
00330     return FileNames;
00331 }
00332 
00333 bool Base::XMLReader::isRegistered(Base::Persistence *Object) const
00334 {
00335     if (Object) {
00336         for (std::vector<FileEntry>::const_iterator it = FileList.begin(); it != FileList.end(); ++it) {
00337             if (it->Object == Object)
00338                 return true;
00339         }
00340     }
00341 
00342     return false;
00343 }
00344 
00345 // ---------------------------------------------------------------------------
00346 //  Base::XMLReader: Implementation of the SAX DocumentHandler interface
00347 // ---------------------------------------------------------------------------
00348 void Base::XMLReader::startElement(const XMLCh* const /*uri*/, const XMLCh* const localname, const XMLCh* const /*qname*/, const XERCES_CPP_NAMESPACE_QUALIFIER Attributes& attrs)
00349 {
00350     Level++; // new scope
00351     LocalName = StrX(localname).c_str();
00352 
00353     // saving attributes of the current scope, delete all previously stored ones
00354     AttrMap.clear();
00355     for (unsigned int i = 0; i < attrs.getLength(); i++) {
00356         AttrMap[StrX(attrs.getQName(i)).c_str()] = StrXUTF8(attrs.getValue(i)).c_str();
00357     }
00358 
00359     ReadType = StartElement;
00360 }
00361 
00362 void Base::XMLReader::endElement  (const XMLCh* const /*uri*/, const XMLCh *const localname, const XMLCh *const /*qname*/)
00363 {
00364     Level--; // end of scope
00365     LocalName = StrX(localname).c_str();
00366 
00367     if (ReadType == StartElement)
00368         ReadType = StartEndElement;
00369     else
00370         ReadType = EndElement;
00371 }
00372 
00373 
00374 void Base::XMLReader::characters(const   XMLCh* const chars, const unsigned int length)
00375 {
00376     Characters = StrX(chars).c_str();
00377     ReadType = Chars;
00378     CharacterCount += length;
00379 }
00380 
00381 void Base::XMLReader::ignorableWhitespace( const   XMLCh* const /*chars*/, const unsigned int /*length*/)
00382 {
00383     //fSpaceCount += length;
00384 }
00385 
00386 void Base::XMLReader::resetDocument()
00387 {
00388     //fAttrCount = 0;
00389     //fCharacterCount = 0;
00390     //fElementCount = 0;
00391     //fSpaceCount = 0;
00392 }
00393 
00394 
00395 // ---------------------------------------------------------------------------
00396 //  Base::XMLReader: Overrides of the SAX ErrorHandler interface
00397 // ---------------------------------------------------------------------------
00398 void Base::XMLReader::error(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& e)
00399 {
00400     // print some details to error output and throw an
00401     // exception to abort the parsing
00402     cerr << "Error at file " << StrX(e.getSystemId())
00403          << ", line " << e.getLineNumber()
00404          << ", char " << e.getColumnNumber() << endl;
00405     throw e;
00406 }
00407 
00408 void Base::XMLReader::fatalError(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& e)
00409 {
00410     // print some details to error output and throw an
00411     // exception to abort the parsing
00412     cerr << "Fatal Error at file " << StrX(e.getSystemId())
00413          << ", line " << e.getLineNumber()
00414          << ", char " << e.getColumnNumber() << endl;
00415     throw e;
00416 }
00417 
00418 void Base::XMLReader::warning(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& e)
00419 {
00420     // print some details to error output and throw an
00421     // exception to abort the parsing
00422    cerr << "Warning at file " << StrX(e.getSystemId())
00423         << ", line " << e.getLineNumber()
00424         << ", char " << e.getColumnNumber() << endl;
00425    throw e;
00426 }
00427 
00428 void Base::XMLReader::resetErrors()
00429 {
00430 }

Generated on Wed Nov 23 19:00:35 2011 for FreeCAD by  doxygen 1.6.1