utils.h
Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.9.1/include/frepple/utils.h $
00003   version : $LastChangedRevision: 1669 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2012-04-04 14:34:56 +0200 (Wed, 04 Apr 2012) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba                 *
00010  *                                                                         *
00011  * This library is free software; you can redistribute it and/or modify it *
00012  * under the terms of the GNU Lesser General Public License as Objecthed   *
00013  * by the Free Software Foundation; either version 2.1 of the License, or  *
00014  * (at your option) any later version.                                     *
00015  *                                                                         *
00016  * This library is distributed in the hope that it will be useful,         *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
00019  * General Public License for more details.                                *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Lesser General Public        *
00022  * License along with this library; if not, write to the Free Software     *
00023  * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 *
00024  * USA                                                                     *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 /** @file utils.h
00029   * @brief Header file for auxilary classes.
00030   *
00031   * @namespace frepple::utils
00032   * @brief Utilities for the frePPle core
00033   */
00034 
00035 #ifndef FREPPLE_UTILS_H
00036 #define FREPPLE_UTILS_H
00037 
00038 /* Python.h has to be included first.
00039    For a debugging build on windows we avoid using the debug version of Python
00040    since that also requires Python and all its modules to be compiled in debug
00041    mode.
00042    Visual Studio will complain if system headers are #included both with
00043    and without _DEBUG defined, so we have to #include all the system headers
00044    used by pyconfig.h right here.
00045 */
00046 #if defined(_DEBUG) && defined(_MSC_VER)
00047 #include <stddef.h>
00048 #include <stdarg.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <assert.h>
00052 #include <errno.h>
00053 #include <ctype.h>
00054 #include <wchar.h>
00055 #include <basetsd.h>
00056 #include <io.h>
00057 #include <limits.h>
00058 #include <float.h>
00059 #include <string.h>
00060 #include <math.h>
00061 #include <time.h>
00062 #undef _DEBUG
00063 #include "Python.h"
00064 #define _DEBUG
00065 #else
00066 #include "Python.h"
00067 #endif
00068 #include "datetime.h"
00069 
00070 // For compatibility with earlier Python releases
00071 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
00072 typedef int Py_ssize_t;
00073 #define PY_SSIZE_T_MAX INT_MAX
00074 #define PY_SSIZE_T_MIN INT_MIN
00075 #endif
00076 
00077 #ifndef DOXYGEN
00078 #include <iostream>
00079 #include <fstream>
00080 #include <sstream>
00081 #include <stdexcept>
00082 #include <ctime>
00083 #include <assert.h>
00084 #include <typeinfo>
00085 #include <float.h>
00086 #endif
00087 
00088 // We want to use singly linked lists, but these are not part of the C++
00089 // standard though. Sigh...
00090 #ifndef DOXYGEN
00091 #ifdef HAVE_EXT_SLIST
00092 // Singly linked lists as extension: gcc 3.x
00093 #include <ext/slist>
00094 using namespace gnu_cxx;
00095 #else
00096 #ifdef HAVE_SLIST
00097 // Singly linked lists available in std stl: gcc 2.95
00098 #include <slist>
00099 #else
00100 // Not available: use a double linked list instead
00101 #define slist list
00102 #endif
00103 #endif
00104 #endif
00105 
00106 // STL include files
00107 #ifndef DOXYGEN
00108 #include <list>
00109 #include <map>
00110 #include <set>
00111 #include <string>
00112 #include <stack>
00113 #include <vector>
00114 #include <algorithm>
00115 #endif
00116 using namespace std;
00117 
00118 /** @def PACKAGE_VERSION
00119   * Defines the version of frePPLe.
00120   */
00121 #ifdef HAVE_CONFIG_H
00122 #undef PACKAGE_BUGREPORT
00123 #undef PACKAGE_NAME
00124 #undef PACKAGE_STRING
00125 #undef PACKAGE_TARNAME
00126 #undef PACKAGE_VERSION
00127 #include <config.h>
00128 #else
00129 // Define the version for (windows) compilers that don't use autoconf
00130 #define PACKAGE_VERSION "0.9.1"
00131 #endif
00132 
00133 // Header for multithreading
00134 #if defined(MT)
00135 #if defined(HAVE_PTHREAD_H)
00136 #include <pthread.h>
00137 #elif defined(WIN32)
00138 #define WIN32_LEAN_AND_MEAN
00139 #include <windows.h>
00140 #include <process.h>
00141 #else
00142 #error Multithreading not supported on your platform
00143 #endif
00144 #endif
00145 
00146 // For the disabled and ansi-challenged people...
00147 #ifndef DOXYGEN
00148 #ifndef HAVE_STRNCASECMP
00149 # ifdef _MSC_VER
00150 #   define strncasecmp _strnicmp
00151 # else
00152 #   ifdef HAVE_STRNICMP
00153 #     define strncasecmp(s1,s2,n) strnicmp(s1,s2,n)
00154 #   else
00155       // Last resort. Force it through...
00156 #     define strncasecmp(s1,s2,n) strnuppercmp(s1,s2,n)
00157 #   endif
00158 # endif
00159 #endif
00160 #endif
00161 
00162 /** @def ROUNDING_ERROR
00163   * This constant defines the magnitude of what can still be considered
00164   * as a rounding error.
00165   */
00166 #define ROUNDING_ERROR   0.000001
00167 
00168 // Header files for the Xerces-c XML parser.
00169 #ifndef DOXYGEN
00170 #define XERCES_STATIC_LIBRARY
00171 #include <xercesc/util/PlatformUtils.hpp>
00172 #include <xercesc/sax2/SAX2XMLReader.hpp>
00173 #include <xercesc/sax2/Attributes.hpp>
00174 #include <xercesc/sax2/DefaultHandler.hpp>
00175 #include <xercesc/framework/MemBufInputSource.hpp>
00176 #include <xercesc/sax2/XMLReaderFactory.hpp>
00177 #include <xercesc/util/XMLUni.hpp>
00178 #include <xercesc/framework/MemBufInputSource.hpp>
00179 #include <xercesc/framework/LocalFileInputSource.hpp>
00180 #include <xercesc/framework/StdInInputSource.hpp>
00181 #include <xercesc/framework/URLInputSource.hpp>
00182 #include <xercesc/util/XMLException.hpp>
00183 #endif
00184 
00185 /** @def DECLARE_EXPORT
00186   * Used to define which symbols to export from a Windows DLL.
00187   * @def MODULE_EXPORT
00188   * Signature used for a module initialization routine. It assures the
00189   * function is exported appropriately when running on Windows.<br>
00190   * A module will need to define a function with the following prototype:
00191   * @code
00192   * MODULE_EXPORT string initialize(const CommandLoadLibrary::ParameterList&);
00193   * @endcode
00194   */
00195 #undef DECLARE_EXPORT
00196 #undef MODULE_EXPORT
00197 #if defined(WIN32) && !defined(DOXYGEN)
00198   #ifdef FREPPLE_CORE
00199     #define DECLARE_EXPORT __declspec (dllexport)
00200   #else
00201     #define DECLARE_EXPORT __declspec (dllimport)
00202   #endif
00203   #define MODULE_EXPORT  extern "C" __declspec (dllexport)
00204 #else
00205   #define DECLARE_EXPORT
00206   #define MODULE_EXPORT extern "C"
00207 #endif
00208 
00209 
00210 namespace frepple
00211 {
00212 
00213 // Forward declarations
00214 class CommandMoveOperationPlan;
00215 
00216 namespace utils
00217 {
00218 
00219 // Forward declarations
00220 class Object;
00221 class Keyword;
00222 class XMLInput;
00223 class AttributeList;
00224 
00225 // Include the list of predefined tags
00226 #include "frepple/tags.h"
00227 
00228 
00229 /** This type defines what operation we want to do with the entity. */
00230 enum Action
00231 {
00232   /** or A.<br>
00233     * Add an new entity, and report an error if the entity already exists. */
00234   ADD = 0,
00235   /** or C.<br>
00236     * Change an existing entity, and report an error if the entity doesn't
00237     * exist yet. */
00238   CHANGE = 1,
00239   /** or D.<br>
00240     * Delete an entity, and report an error if the entity doesn't exist. */
00241   REMOVE = 2,
00242   /** or AC.<br>
00243     * Change an entity or create a new one if it doesn't exist yet.<br>
00244     * This is the default action.
00245     */
00246   ADD_CHANGE = 3
00247 };
00248 
00249 
00250 /** Writes an action description to an output stream. */
00251 inline ostream & operator << (ostream & os, const Action & d)
00252 {
00253   switch (d)
00254   {
00255     case ADD: os << "ADD"; return os;
00256     case CHANGE: os << "CHANGE"; return os;
00257     case REMOVE: os << "REMOVE"; return os;
00258     case ADD_CHANGE: os << "ADD_CHANGE"; return os;
00259     default: assert(false); return os;
00260   }
00261 }
00262 
00263 
00264 /** This type defines the types of callback events possible. */
00265 enum Signal
00266 {
00267   /** Adding a new entity. */
00268   SIG_ADD = 0,
00269   /** Deleting an entity. */
00270   SIG_REMOVE = 1
00271 };
00272 
00273 
00274 /** Writes a signal description to an output stream. */
00275 inline ostream & operator << (ostream & os, const Signal & d)
00276 {
00277   switch (d)
00278   {
00279     case SIG_ADD: os << "ADD"; return os;
00280     case SIG_REMOVE: os << "REMOVE"; return os;
00281     default: assert(false); return os;
00282   }
00283 }
00284 
00285 
00286 /** This is the datatype used for hashing an XML-element to a numeric value. */
00287 typedef unsigned int hashtype;
00288 
00289 /** This stream is the general output for all logging and debugging messages. */
00290 extern DECLARE_EXPORT ostream logger;
00291 
00292 /** Auxilary structure for easy indenting in the log stream. */
00293 struct indent
00294 {
00295   short level;
00296   indent(short l) : level(l) {}
00297   indent operator() (short l) {return indent(l);}
00298 };
00299 
00300 /** Print a number of spaces to the output stream. */
00301 inline ostream& operator <<(ostream &os, const indent& i)
00302 {
00303   for (short c = i.level; c>0; --c) os << ' ';
00304   return os;
00305 }
00306 
00307 
00308 
00309 //
00310 // CUSTOM EXCEPTION CLASSES
00311 //
00312 
00313 
00314 /** @brief An exception of this type is thrown when data errors are found.
00315   *
00316   * The normal handling of this error is to catch the exception and
00317   * continue execution of the rest of the program.<br>
00318   * When a DataException is thrown the object is expected to remain in
00319   * valid and consistent state.
00320   */
00321 class DataException : public logic_error
00322 {
00323   public:
00324     DataException(const char * c) : logic_error(c) {}
00325     DataException(const string s) : logic_error(s) {}
00326 };
00327 
00328 
00329 /** @brief An exception of this type is thrown when the library gets in an
00330   * inconsistent state from which the normal course of action can't continue.
00331   *
00332   * The normal handling of this error is to exit the program, and report the
00333   * problem. This exception indicates a bug in the program code.
00334   */
00335 class LogicException: public logic_error
00336 {
00337   public:
00338     LogicException(const char * c) : logic_error(c) {}
00339     LogicException(const string s) : logic_error(s) {}
00340 };
00341 
00342 
00343 /** @brief An exception of this type is thrown when the library runs into
00344   * problems that are specific at runtime. <br>
00345   * These could either be memory problems, threading problems, file system
00346   * problems, etc...
00347   *
00348   * Errors of this type can be caught by the client applications and the
00349   * application can continue in most cases.<br>
00350   * This exception shouldn't be used for issueing warnings. Warnings should
00351   * simply be logged in the logfile and actions continue in some default way.
00352   */
00353 class RuntimeException: public runtime_error
00354 {
00355   public:
00356     RuntimeException(const char * c) : runtime_error(c) {}
00357     RuntimeException(const string s) : runtime_error(s) {}
00358 };
00359 
00360 
00361 /** @brief Python exception class matching with frepple::LogicException. */
00362 extern DECLARE_EXPORT PyObject* PythonLogicException;
00363 
00364 /** @brief Python exception class matching with frepple::DataException. */
00365 extern DECLARE_EXPORT PyObject* PythonDataException;
00366 
00367 /** @brief Python exception class matching with frepple::RuntimeException. */
00368 extern DECLARE_EXPORT PyObject* PythonRuntimeException;
00369 
00370 
00371 //
00372 // UTILITY CLASS "NON-COPYABLE"
00373 //
00374 
00375 /** @brief Class NonCopyable is a base class.<br>Derive your own class from
00376   * it when you want to prohibit copy construction and copy assignment.
00377   *
00378   * Some objects, particularly those which hold complex resources like files
00379   * or network connections, have no sensible copy semantics.  Sometimes there
00380   * are possible copy semantics, but these would be of very limited usefulness
00381   * and be very difficult to implement correctly. Sometimes you're implementing
00382   * a class that doesn't need to be copied just yet and you don't want to
00383   * take the time to write the appropriate functions.  Deriving from
00384   * noncopyable will prevent the otherwise implicitly-generated functions
00385   * (which don't have the proper semantics) from becoming a trap for other
00386   * programmers.<br>
00387   * The traditional way to deal with these is to declare a private copy
00388   * constructor and copy assignment, and then document why this is done. But
00389   * deriving from NonCopyable is simpler and clearer, and doesn't require
00390   * additional documentation.
00391   */
00392 class NonCopyable
00393 {
00394   protected:
00395     NonCopyable() {}
00396     ~NonCopyable() {}
00397 
00398   private:
00399     /** This copy constructor isn't implemented.<br>
00400       * It's here just so we can declare them as private so that this, and
00401       * any derived class, do not have copy constructors.
00402       */
00403     NonCopyable(const NonCopyable&);
00404 
00405     /** This assignment operator isn't implemented.<br>
00406       * It's here just so we can declare them as private so that this, and
00407       * any derived class, do not have copy constructors.
00408       */
00409     NonCopyable& operator=(const NonCopyable&);
00410 };
00411 
00412 
00413 /** @brief This class is used to maintain the Python interpreter.
00414   *
00415   * A single interpreter is used throughout the lifetime of the
00416   * application.<br>
00417   * The implementation is implemented in a thread-safe way (within the
00418   * limitations of the Python threading model, of course).
00419   *
00420   * During the initialization the code checks for a file 'init.py' in its
00421   * search path and, if it does exist, the statements in the file will be
00422   * executed. In this way a library of globally available functions
00423   * can easily be initialized.
00424   *
00425   * The stderr and stdout streams of Python are redirected by default to
00426   * the frePPLe log stream.
00427   *
00428   * The following frePPLe functions are available from within Python.<br>
00429   * All of these are in the module called frePPLe.
00430   *   - The following <b>classes</b> and their attributes are accessible for
00431   *     reading and writing.<br>
00432   *     Each object has a toXML() method that returns its XML representation
00433   *     as a string, or writes it to a file is a file is passed as argument.
00434   *       - buffer
00435   *       - buffer_default
00436   *       - buffer_infinite
00437   *       - buffer_procure
00438   *       - calendar
00439   *       - calendarBucket
00440   *       - calendar_boolean
00441   *       - calendar_double
00442   *       - calendar_void
00443   *       - customer
00444   *       - customer_default
00445   *       - demand
00446   *       - demand_default
00447   *       - flow
00448   *       - flowplan
00449   *       - item
00450   *       - item_default
00451   *       - load
00452   *       - loadplan
00453   *       - location
00454   *       - location_default
00455   *       - operation
00456   *       - operation_alternate
00457   *           - addAlternate(operation=x, priority=y, effective_start=z1, effective_end=z2)
00458   *       - operation_fixed_time
00459   *       - operation_routing
00460   *           - addStep(tuple of operations)
00461   *       - operation_time_per
00462   *       - operationplan
00463   *       - parameters
00464   *       - problem  (read-only)
00465   *       - resource
00466   *       - resource_default
00467   *       - resource_infinite
00468   *       - setup_matrix
00469   *       - setup_matrix_default
00470   *       - solver
00471   *           - solve()
00472   *       - solver_mrp
00473   *   - The following functions or attributes return <b>iterators</b> over the
00474   *     frePPLe objects:<br>
00475   *       - buffers()
00476   *       - buffer.flows
00477   *       - buffer.flowplans
00478   *       - calendar.buckets
00479   *       - calendars()
00480   *       - customers()
00481   *       - demands()
00482   *       - demand.operationplans
00483   *       - demand.pegging
00484   *       - operation.flows
00485   *       - operation.loads
00486   *       - items()
00487   *       - locations()
00488   *       - operations()
00489   *       - operation.operationplans
00490   *       - problems()
00491   *       - resources()
00492   *       - resource.loads
00493   *       - resource.loadplans
00494   *       - setup_matrices()
00495   *       - solvers()
00496   *   - <b>printsize()</b>:<br>
00497   *     Prints information about the memory consumption.
00498   *   - <b>loadmodule(string [,parameter=value, ...])</b>:<br>
00499   *     Dynamically load a module in memory.
00500   *   - <b>readXMLdata(string [,bool] [,bool])</b>:<br>
00501   *     Processes an XML string passed as argument.
00502   *   - <b>log(string)</b>:<br>
00503   *     Prints a string to the frePPLe log file.<br>
00504   *     This is used for redirecting the stdout and stderr of Python.
00505   *   - <b>readXMLfile(string [,bool] [,bool])</b>:<br>
00506   *     Read an XML-file.
00507   *   - <b>saveXMLfile(string)</b>:<br>
00508   *     Save the model to an XML-file.
00509   *   - <b>saveplan(string)</b>:<br>
00510   *     Save the main plan information to a file.
00511   *   - <b>erase(boolean)</b>:<br>
00512   *     Erase the model (arg true) or only the plan (arg false, default).
00513   *   - <b>version</b>:<br>
00514   *     A string variable with the version number.
00515   *
00516   * The technical implementation is inspired by and inherited from the following
00517   * article: "Embedding Python in Multi-Threaded C/C++ Applications", see
00518   * http://www.linuxjournal.com/article/3641
00519   */
00520 class PythonInterpreter
00521 {
00522   public:
00523     /** Initializes the interpreter. */
00524     static DECLARE_EXPORT void initialize(int argc, char** argv);
00525 
00526     /** Finalizes the interpreter. */
00527     static DECLARE_EXPORT void finalize();
00528 
00529     /** Execute some python code. */
00530     static DECLARE_EXPORT void execute(const char*);
00531 
00532     /** Execute a file with Python code. */
00533     static DECLARE_EXPORT void executeFile(string);
00534 
00535     /** Register a new method to Python.<br>
00536       * Arguments:
00537       * - The name of the built-in function/method
00538       * - The function that implements it.
00539       * - Combination of METH_* flags, which mostly describe the args
00540       *   expected by the C func.
00541       * - The __doc__ attribute, or NULL.
00542       */
00543     static DECLARE_EXPORT void registerGlobalMethod(
00544       const char*, PyCFunction, int, const char*, bool = true
00545     );
00546 
00547     /** Register a new method to Python. */
00548     static DECLARE_EXPORT void registerGlobalMethod
00549     (const char*, PyCFunctionWithKeywords, int, const char*, bool = true);
00550 
00551     /** Return a pointer to the main extension module. */
00552     static PyObject* getModule() {return module;}
00553 
00554     /** Return the preferred encoding of the Python interpreter. */
00555     static const char* getPythonEncoding() {return encoding.c_str();}
00556 
00557     /** Create a new Python thread state.<br>
00558       * Each OS-level thread needs to initialize a Python thread state as well.
00559       * When a new thread is created in the OS, this method should be called
00560       * to create a Python thread state as well.<br>
00561       * See the Python PyGILState_Ensure API.
00562       */
00563     static DECLARE_EXPORT void addThread();
00564 
00565     /** Delete a Python thread state.<br>
00566       * Each OS-level thread has a Python thread state.
00567       * When an OS thread is deleted, this method should be called
00568       * to delete the Python thread state as well.<br>
00569       * See the Python PyGILState_Release API.
00570       */
00571     static DECLARE_EXPORT void deleteThread();
00572 
00573   private:
00574     /** A pointer to the frePPLe extension module. */
00575     static DECLARE_EXPORT PyObject *module;
00576 
00577     /** Python API: Used for redirecting the Python output to the same file
00578       * as the application.
00579       */
00580     static DECLARE_EXPORT PyObject *python_log(PyObject*, PyObject*);
00581 
00582     /** Python unicode strings are encoded to this locale when bringing them into
00583       * frePPLe.<br>
00584       */
00585     static DECLARE_EXPORT string encoding;
00586 
00587     /** Main thread info. */
00588     static DECLARE_EXPORT PyThreadState* mainThreadState;
00589 };
00590 
00591 
00592 /** A utility function to do wildcard matching in strings.<br>
00593   * The function recognizes two wildcard characaters:
00594   *   - ?: matches any single character
00595   *   - *: matches any sequence of characters
00596   *
00597   * The code is written by Jack Handy (jakkhandy@hotmail.com) and published
00598   * on http://www.codeproject.com/KB/string/wildcmp.aspx. No specific license
00599   * constraints apply on using the code.
00600   */
00601 DECLARE_EXPORT bool matchWildcard(const char*, const char*);
00602 
00603 
00604 //
00605 // METADATA AND OBJECT FACTORY
00606 //
00607 
00608 /** @brief This class defines a keyword for the frePPLe data model.
00609   *
00610   * The keywords are used to define the attribute names for the objects.<br>
00611   * They are used as:
00612   *  - Element and attribute names in XML documents
00613   *  - Attribute names in the Python extension.
00614   *
00615   * Special for this class is the requirement to have a "perfect" hash
00616   * function, i.e. a function that returns a distinct number for each
00617   * defined tag. The class prints a warning message when the hash
00618   * function doesn't satisfy this criterion.
00619   */
00620 class Keyword : public NonCopyable
00621 {
00622   private:
00623     /** Stores the hash value of this tag. */
00624     hashtype dw;
00625 
00626     /** Store different preprocessed variations of the name of the tag.
00627       * These are all stored in memory for improved performance. */
00628     string strName, strStartElement, strEndElement, strElement, strAttribute;
00629 
00630     /** Name of the string transcoded to its Xerces-internal representation. */
00631     XMLCh* xmlname;
00632 
00633     /** A function to verify the uniquess of our hashes. */
00634     void check();
00635 
00636   public:
00637     /** Container for maintaining a list of all tags. */
00638     typedef map<hashtype,Keyword*> tagtable;
00639 
00640     /** This is the constructor.<br>
00641       * The tag doesn't belong to an XML namespace. */
00642     DECLARE_EXPORT Keyword(const string&);
00643 
00644     /** This is the constructor. The tag belongs to the XML namespace passed
00645       * as second argument.<br>
00646       * Note that we still require the first argument to be unique, since it
00647       * is used as a keyword for the Python extensions.
00648       */
00649     DECLARE_EXPORT Keyword(const string&, const string&);
00650 
00651     /** Destructor. */
00652     DECLARE_EXPORT ~Keyword();
00653 
00654     /** Returns the hash value of the tag. */
00655     hashtype getHash() const {return dw;}
00656 
00657     /** Returns the name of the tag. */
00658     const string& getName() const {return strName;}
00659 
00660     /** Returns a pointer to an array of XML characters. This format is used
00661       * by Xerces for the internal representation of character strings. */
00662     const XMLCh* getXMLCharacters() const {return xmlname;}
00663 
00664     /** Returns a string to start an XML element with this tag: <TAG */
00665     const string& stringStartElement() const {return strStartElement;}
00666 
00667     /** Returns a string to end an XML element with this tag: </TAG> */
00668     const string& stringEndElement() const {return strEndElement;}
00669 
00670     /** Returns a string to start an XML element with this tag: <TAG> */
00671     const string& stringElement() const {return strElement;}
00672 
00673     /** Returns a string to start an XML attribute with this tag: TAG=" */
00674     const string& stringAttribute() const {return strAttribute;}
00675 
00676     /** This is the hash function. See the note on the perfectness of
00677       * this function at the start. This function should be as simple
00678       * as possible while still garantueeing the perfectness.<br>
00679       * The hash function is based on the Xerces-C implementation,
00680       * with the difference that the hash calculated by our function is
00681       * portable between platforms.<br>
00682       * The hash modulus is 954991 (which is the biggest prime number
00683       * lower than 1000000).
00684       */
00685     static DECLARE_EXPORT hashtype hash(const char*);
00686 
00687     /** This is the hash function.
00688       * @see hash(const char*)
00689       */
00690     static hashtype hash(const string& c) {return hash(c.c_str());}
00691 
00692     /** This is the hash function taken an XML character string as input.<br>
00693       * The function is expected to return exactly the same result as when a
00694       * character pointer is passed as argument.
00695       * @see hash(const char*)
00696       */
00697     static DECLARE_EXPORT hashtype hash(const XMLCh*);
00698 
00699     /** Finds a tag when passed a certain string. If no tag exists yet, it
00700       * will be created. */
00701     static DECLARE_EXPORT const Keyword& find(const char*);
00702 
00703     /** Return a reference to a table with all defined tags. */
00704     static DECLARE_EXPORT tagtable& getTags();
00705 
00706     /** Prints a list of all tags that have been defined. This can be useful
00707       * for debugging and also for creating a good hashing function.<br>
00708       * GNU gperf is a program that can generate a perfect hash function for
00709       * a given set of symbols.
00710       */
00711     static DECLARE_EXPORT void printTags();
00712 };
00713 
00714 
00715 /** @brief This abstract class is the base class used for callbacks.
00716   * @see MetaClass::callback
00717   * @see FunctorStatic
00718   * @see FunctorInstance
00719   */
00720 class Functor : public NonCopyable
00721 {
00722   public:
00723     /** This is the callback method.<br>
00724       * The return value should be true in case the action is allowed to
00725       * happen. In case a subscriber disapproves the action false is
00726       * returned.<br>
00727       * It is important that the callback methods are implemented in a
00728       * thread-safe and re-entrant way!!!
00729       */
00730     virtual bool callback(Object* v, const Signal a) const = 0;
00731 
00732     /** Destructor. */
00733     virtual ~Functor() {}
00734 };
00735 
00736 
00737 // The following handler functions redirect the call from Python onto a
00738 // matching virtual function in a PythonExtensionBase subclass.
00739 extern "C"
00740 {
00741   /** Handler function called from Python. Internal use only. */
00742   DECLARE_EXPORT PyObject* getattro_handler (PyObject*, PyObject*);
00743   /** Handler function called from Python. Internal use only. */
00744   DECLARE_EXPORT int setattro_handler (PyObject*, PyObject*, PyObject*);
00745   /** Handler function called from Python. Internal use only. */
00746   DECLARE_EXPORT int compare_handler (PyObject*, PyObject*);
00747   /** Handler function called from Python. Internal use only. */
00748   DECLARE_EXPORT PyObject* iternext_handler (PyObject*);
00749   /** Handler function called from Python. Internal use only. */
00750   DECLARE_EXPORT PyObject* call_handler(PyObject*, PyObject*, PyObject*);
00751   /** Handler function called from Python. Internal use only. */
00752   DECLARE_EXPORT PyObject* str_handler(PyObject*);
00753 }
00754 
00755 
00756 /** @brief This class is a thin wrapper around the type information in Python.
00757   *
00758   * This class defines a number of convenience functions to interact with the
00759   * PyTypeObject struct of the Python C API.
00760   */
00761 class PythonType : public NonCopyable
00762 {
00763   private:
00764     /** This static variable is a template for cloning type definitions.<br>
00765       * It is copied for each type object we create.
00766       */
00767     static const PyTypeObject PyTypeObjectTemplate;
00768 
00769     /** Incremental size of the method table.<br>
00770       * We allocate memory for the method definitions per block, not
00771       * one-by-one.
00772       */
00773     static const unsigned short methodArraySize = 5;
00774 
00775     /** The Python type object which this class is wrapping. */
00776     PyTypeObject* table;
00777 
00778   public:
00779     /** A static function that evaluates an exception and sets the Python
00780        * error string properly.<br>
00781        * This function should only be called from within a catch-block, since
00782        * internally it rethrows the exception!
00783        */
00784     static DECLARE_EXPORT void evalException();
00785 
00786     /** Constructor, sets the tp_base_size member. */
00787     DECLARE_EXPORT PythonType(size_t, const type_info*);
00788 
00789     /** Return a pointer to the actual Python PyTypeObject. */
00790     PyTypeObject* type_object() const {return table;}
00791 
00792     /** Add a new method. */
00793     DECLARE_EXPORT void addMethod(const char*, PyCFunction, int, const char*);
00794 
00795     /** Add a new method. */
00796     DECLARE_EXPORT void addMethod(const char*, PyCFunctionWithKeywords, int, const char*);
00797 
00798     /** Updates tp_name. */
00799     void setName (const string n)
00800     {
00801       string *name = new string("frepple." + n);
00802       table->tp_name = const_cast<char*>(name->c_str());
00803     }
00804 
00805     /** Updates tp_doc. */
00806     void setDoc (const string n)
00807     {
00808       string *doc = new string(n);
00809       table->tp_doc = const_cast<char*>(doc->c_str());
00810     }
00811 
00812     /** Updates tp_base. */
00813     void setBase(PyTypeObject* b)
00814     {
00815       table->tp_base = b;
00816     }
00817 
00818     /** Updates the deallocator. */
00819     void supportdealloc(void (*f)(PyObject*))
00820     {
00821       table->tp_dealloc = f;
00822     }
00823 
00824     /** Updates tp_getattro.<br>
00825       * The extension class will need to define a member function with this
00826       * prototype:<br>
00827       *   PythonObject getattro(const XMLElement& name)
00828       */
00829     void supportgetattro()
00830     {table->tp_getattro = getattro_handler;}
00831 
00832     /** Updates tp_setattro.<br>
00833       * The extension class will need to define a member function with this
00834       * prototype:<br>
00835       *   int setattro(const Attribute& attr, const PythonObject& field)
00836       */
00837     void supportsetattro()
00838     {table->tp_setattro = setattro_handler;}
00839 
00840     /** Updates tp_compare.<br>
00841       * The extension class will need to define a member function with this
00842       * prototype:<br>
00843       *   int compare(const PyObject* other) const
00844       */
00845     void supportcompare()
00846     {table->tp_compare = compare_handler;}
00847 
00848     /** Updates tp_iter and tp_iternext.<br>
00849       * The extension class will need to define a member function with this
00850       * prototype:<br>
00851       *   PyObject* iternext()
00852       */
00853     void supportiter()
00854     {
00855       table->tp_iter = PyObject_SelfIter;
00856       table->tp_iternext = iternext_handler;
00857     }
00858 
00859     /** Updates tp_call.<br>
00860       * The extension class will need to define a member function with this
00861       * prototype:<br>
00862       *   PyObject* call(const PythonObject& args, const PythonObject& kwds)
00863       */
00864     void supportcall()
00865     {table->tp_call = call_handler;}
00866 
00867     /** Updates tp_str.<br>
00868       * The extension class will need to define a member function with this
00869       * prototype:<br>
00870       *   PyObject* str()
00871       */
00872     void supportstr()
00873     {table->tp_str = str_handler;}
00874 
00875     /** Type definition for create functions. */
00876     typedef PyObject* (*createfunc)(PyTypeObject*, PyObject*, PyObject*);
00877 
00878     /** Updates tp_new with the function passed as argument. */
00879     void supportcreate(createfunc c) {table->tp_new = c;}
00880 
00881     /** This method needs to be called after the type information has all
00882       * been updated. It adds the type to the frepple module. */
00883     DECLARE_EXPORT int typeReady();
00884 
00885     /** Comparison operator. */
00886     bool operator == (const PythonType& i) const
00887     {
00888       return *cppClass == *(i.cppClass);
00889     }
00890 
00891     /** Comparison operator. */
00892     bool operator == (const type_info& i) const
00893     {
00894       return *cppClass == i;
00895     }
00896 
00897     /** Type info of the registering class. */
00898     const type_info* cppClass;
00899 };
00900 
00901 
00902 class MetaCategory;
00903 /** @brief This class stores metadata about the classes in the library.
00904   * The stored information goes well beyond the standard 'type_info'.
00905   *
00906   * A MetaClass instance represents metadata for a specific instance type.
00907   * A MetaCategory instance represents metadata for a category of object.
00908   * For instance, 'Resource' is a category while 'ResourceDefault' and
00909   * 'ResourceInfinite' are specific classes.<br>
00910   * The metadata class also maintains subscriptions to certain events.
00911   * Registered classes and objects will receive callbacks when objects are
00912   * being created, changed or deleted.<br>
00913   * The proper usage is to include the following code snippet in every
00914   * class:<br>
00915   * @code
00916   *  In the header file:
00917   *    class X : public Object
00918   *    {
00919   *      public:
00920   *        virtual const MetaClass& getType() {return *metadata;}
00921   *        static const MetaClass *metadata;
00922   *    }
00923   *  In the implementation file:
00924   *    const MetaClass *X::metadata;
00925   * @endcode
00926   * Creating a MetaClass object isn't sufficient. It needs to be registered,
00927   * typically in an initialization method:
00928   * @code
00929   *    void initialize()
00930   *    {
00931   *      ...
00932   *      Y::metadata = new MetaCategory("Y","Ys", reader_method, writer_method);
00933   *      X::metadata = new MetaClass("Y","X", factory_method);
00934   *      ...
00935   *    }
00936   * @endcode
00937   * @see MetaCategory
00938   */
00939 class MetaClass : public NonCopyable
00940 {
00941     friend class MetaCategory;
00942     template <class T, class U> friend class FunctorStatic;
00943     template <class T, class U> friend class FunctorInstance;
00944 
00945   public:
00946     /** Type definition for a factory method calling the default
00947      * constructor.. */
00948     typedef Object* (*creatorDefault)();
00949 
00950     /** Type definition for a factory method calling the constructor that
00951       * takes a string as argument. */
00952     typedef Object* (*creatorString)(const string&);
00953 
00954     /** A string specifying the object type, i.e. the subclass within the
00955       * category. */
00956     string type;
00957 
00958     /** A reference to an Keyword of the base string. */
00959     const Keyword* typetag;
00960 
00961     /** The category of this class. */
00962     const MetaCategory* category;
00963 
00964     /** A pointer to the Python type. */
00965     PyTypeObject* pythonClass;
00966 
00967     /** A factory method for the registered class. */
00968     union
00969     {
00970       creatorDefault factoryMethodDefault;
00971       creatorString factoryMethodString;
00972     };
00973 
00974     /** Destructor. */
00975     virtual ~MetaClass() {}
00976 
00977     /** Initialize the data structure and register the class. */
00978     DECLARE_EXPORT void registerClass(const string&, const string&,
00979         bool = false, creatorDefault = NULL);
00980 
00981     /** This constructor registers the metadata of a class. */
00982     MetaClass (const string& cat, const string& cls, bool def = false)
00983       : pythonClass(NULL)
00984     {
00985       registerClass(cat,cls,def);
00986     }
00987 
00988     /** This constructor registers the metadata of a class, with a factory
00989       * method that uses the default constructor of the class. */
00990     MetaClass (const string& cat, const string& cls, creatorDefault f,
00991         bool def = false) : pythonClass(NULL)
00992     {
00993       registerClass(cat,cls,def);
00994       factoryMethodDefault = f;
00995     }
00996 
00997     /** This constructor registers the metadata of a class, with a factory
00998       * method that uses a constructor with a string argument. */
00999     MetaClass (const string& cat, const string& cls, creatorString f,
01000         bool def = false) : pythonClass(NULL)
01001     {
01002       registerClass(cat,cls,def);
01003       factoryMethodString = f;
01004     }
01005 
01006     /** This function will analyze the string being passed, and return the
01007       * appropriate action.
01008       * The string is expected to be one of the following:
01009       *  - 'A' for action ADD
01010       *  - 'C' for action CHANGE
01011       *  - 'AC' for action ADD_CHANGE
01012       *  - 'R' for action REMOVE
01013       *  - Any other value will result in a data exception
01014       */
01015     static DECLARE_EXPORT Action decodeAction(const char*);
01016 
01017     /** This method picks up the attribute named "ACTION" from the list and
01018       * calls the method decodeAction(const XML_Char*) to analyze it.
01019       * @see decodeAction(const XML_Char*)
01020       */
01021     static DECLARE_EXPORT Action decodeAction(const AttributeList&);
01022 
01023     /** Sort two metaclass objects. This is used to sort entities on their
01024       * type information in a stable and platform independent way.
01025       * @see operator !=
01026       * @see operator ==
01027       */
01028     bool operator < (const MetaClass& b) const
01029     {
01030       return typetag->getHash() < b.typetag->getHash();
01031     }
01032 
01033     /** Compare two metaclass objects. We are not always sure that only a
01034       * single instance of a metadata object exists in the system, and a
01035       * pointer comparison is therefore not appropriate.
01036       * @see operator !=
01037       * @see operator <
01038       */
01039     bool operator == (const MetaClass& b) const
01040     {
01041       return typetag->getHash() == b.typetag->getHash();
01042     }
01043 
01044     /** Compare two metaclass objects. We are not always sure that only a
01045       * single instance of a metadata object exists in the system, and a
01046       * pointer comparison is therefore not appropriate.
01047       * @see operator ==
01048       * @see operator <
01049       */
01050     bool operator != (const MetaClass& b) const
01051     {
01052       return typetag->getHash() != b.typetag->getHash();
01053     }
01054 
01055     /** This method should be called whenever objects of this class are being
01056       * created, updated or deleted. It will run the callback method of all
01057       * subscribers.<br>
01058       * If the function returns true, all callback methods approved of the
01059       * event. If false is returned, one of the callbacks disapproved it and
01060       * the event action should be allowed to execute.
01061       */
01062     DECLARE_EXPORT bool raiseEvent(Object* v, Signal a) const;
01063 
01064     /** Connect a new subscriber to the class. */
01065     void connect(Functor *c, Signal a) const
01066     {const_cast<MetaClass*>(this)->subscribers[a].push_front(c);}
01067 
01068     /** Disconnect a subscriber from the class. */
01069     void disconnect(Functor *c, Signal a) const
01070     {const_cast<MetaClass*>(this)->subscribers[a].remove(c);}
01071 
01072     /** Print all registered factory methods to the standard output for
01073       * debugging purposes. */
01074     static DECLARE_EXPORT void printClasses();
01075 
01076     /** Find a particular class by its name. If it can't be located the return
01077       * value is NULL. */
01078     static DECLARE_EXPORT const MetaClass* findClass(const char*);
01079 
01080   protected:
01081     /** Default constructor. */
01082     MetaClass() : type("unspecified"), typetag(&Keyword::find("unspecified")),
01083       category(NULL), pythonClass(NULL), factoryMethodDefault(NULL) {}
01084 
01085   private:
01086     /** This is a list of objects that will receive a callback when the call
01087       * method is being used.<br>
01088       * There is limited error checking in maintaining this list, and it is the
01089       * user's responsability of calling the connect() and disconnect() methods
01090       * correctly.<br>
01091       * This design garantuees maximum performance, but assumes a properly
01092       * educated user.
01093       */
01094     list<Functor*> subscribers[4];
01095 };
01096 
01097 
01098 class XMLOutput;
01099 /** @brief A MetaCategory instance represents metadata for a category of
01100   * object.
01101   *
01102   * A MetaClass instance represents metadata for a specific instance type.
01103   * For instance, 'Resource' is a category while 'ResourceDefault' and
01104   * 'ResourceInfinite' are specific classes.<br>
01105   * A category has the following specific pieces of data:
01106   *  - A reader function for creating objects.<br>
01107   *    The reader function creates objects for all classes registered with it.
01108   *  - A writer function for persisting objects.<br>
01109   *    The writer function will typically iterate over all objects of the
01110   *    category and call the writeElement method on them.
01111   *  - A group tag used for the grouping objects of the category in the XML
01112   *    output stream.
01113   * @see MetaClass
01114   */
01115 class MetaCategory : public MetaClass
01116 {
01117     friend class MetaClass;
01118     template<class T> friend class HasName;
01119   public:
01120     /** The name used to name a collection of objects of this category. */
01121     string group;
01122 
01123     /** A XML tag grouping objects of the category. */
01124     const Keyword* grouptag;
01125 
01126     /** Type definition for the read control function. */
01127     typedef Object* (*readController)(const MetaClass*, const AttributeList&);
01128 
01129     /** Type definition for the write control function. */
01130     typedef void (*writeController)(const MetaCategory*, XMLOutput *o);
01131 
01132     /** This template method is available as a object creation factory for
01133       * classes without key fields and which rely on a default constructor.
01134       */
01135     static Object* ControllerDefault (const MetaClass*, const AttributeList&);
01136 
01137     /** Destructor. */
01138     virtual ~MetaCategory() {}
01139 
01140     /** Constructor. */
01141     DECLARE_EXPORT MetaCategory (const string& t, const string& g,
01142         readController = NULL, writeController = NULL);
01143 
01144     /** Type definition for the map of all registered classes. */
01145     typedef map < hashtype, const MetaClass*, less<hashtype> > ClassMap;
01146 
01147     /** Type definition for the map of all categories. */
01148     typedef map < hashtype, const MetaCategory*, less<hashtype> > CategoryMap;
01149 
01150     /** Looks up a category name in the registry. If the catgory can't be
01151       * located the return value is NULL. */
01152     static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const char*);
01153 
01154     /** Looks up a category name in the registry. If the catgory can't be
01155       * located the return value is NULL. */
01156     static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const hashtype);
01157 
01158     /** Looks up a category name in the registry. If the catgory can't be
01159       * located the return value is NULL. */
01160     static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const char*);
01161 
01162     /** Looks up a category name in the registry. If the category can't be
01163       * located the return value is NULL. */
01164     static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const hashtype);
01165 
01166     /** Find a class in this category with a specified name.<br>
01167       * If the catrgory can't be found the return value is NULL.
01168       */
01169     DECLARE_EXPORT const MetaClass* findClass(const char*) const;
01170 
01171     /** Find a class in this category with a specified name.<br>
01172       * If the catrgory can't be found the return value is NULL.
01173       */
01174     DECLARE_EXPORT const MetaClass* findClass(const hashtype) const;
01175 
01176     /** This method takes care of the persistence of all categories. It loops
01177       * through all registered categories (in the order of their registration)
01178       * and calls the persistance handler.
01179       */
01180     static DECLARE_EXPORT void persist(XMLOutput *);
01181 
01182     /** A control function for reading objects of a category.
01183       * The controller function manages the creation and destruction of
01184       * objects in this category.
01185       */
01186     readController readFunction;
01187 
01188   private:
01189     /** A map of all classes registered for this category. */
01190     ClassMap classes;
01191 
01192     /** Compute the hash for "default" once and store it in this variable for
01193       * efficiency. */
01194     static DECLARE_EXPORT const hashtype defaultHash;
01195 
01196     /** This is the root for a linked list of all categories.
01197       * Categories are chained to the list in the order of their registration.
01198       */
01199     static DECLARE_EXPORT const MetaCategory* firstCategory;
01200 
01201     /** A pointer to the next category in the singly linked list. */
01202     const MetaCategory* nextCategory;
01203 
01204     /** A control function for writing the category.
01205       * The controller function will loop over the objects in the category and
01206       * call write them one by one.
01207       */
01208     writeController writeFunction;
01209 
01210     /** A map of all categories by their name. */
01211     static DECLARE_EXPORT CategoryMap categoriesByTag;
01212 
01213     /** A map of all categories by their group name. */
01214     static DECLARE_EXPORT CategoryMap categoriesByGroupTag;
01215 };
01216 
01217 
01218 /** @brief This class represents a static subscription to a signal.
01219   *
01220   * When the signal callback is triggered the static method callback() on the
01221   * parameter class will be called.
01222   */
01223 template <class T, class U> class FunctorStatic : public Functor
01224 {
01225     friend class MetaClass;
01226   public:
01227     /** Add a signal subscriber. */
01228     static void connect(const Signal a)
01229     {T::metadata->connect(new FunctorStatic<T,U>(), a);}
01230 
01231     /** Remove a signal subscriber. */
01232     static void disconnect(const Signal a)
01233     {
01234       MetaClass &t =
01235         const_cast<MetaClass&>(static_cast<const MetaClass&>(*T::metadata));
01236       // Loop through all subscriptions
01237       for (list<Functor*>::iterator i = t.subscribers[a].begin();
01238           i != t.subscribers[a].end(); ++i)
01239       {
01240         // Try casting the functor to the right type
01241         FunctorStatic<T,U> *f = dynamic_cast< FunctorStatic<T,U>* >(*i);
01242         if (f)
01243         {
01244           // Casting was successfull. Delete the functor.
01245           delete *i;
01246           t.subscribers[a].erase(i);
01247           return;
01248         }
01249       }
01250       // Not found in the list of subscriptions
01251       throw LogicException("Subscription doesn't exist");
01252     }
01253 
01254   private:
01255     /** This is the callback method. The functor will call the static callback
01256       * method of the subscribing class.
01257       */
01258     virtual bool callback(Object* v, const Signal a) const
01259     {return U::callback(static_cast<T*>(v),a);}
01260 };
01261 
01262 
01263 /** @brief This class represents an object subscribing to a signal.
01264   *
01265   * When the signal callback is triggered the method callback() on the
01266   * instance object will be called.
01267   */
01268 template <class T, class U> class FunctorInstance : public Functor
01269 {
01270   public:
01271     /** Connect a new subscriber to a signal.<br>
01272       * It is the users' responsibility to call the disconnect method
01273       * when the subscriber is being deleted. Otherwise the application
01274       * will crash.
01275       */
01276     static void connect(U* u, const Signal a)
01277     {if (u) T::metadata.connect(new FunctorInstance(u), a);}
01278 
01279     /** Disconnect from a signal. */
01280     static void disconnect(U *u, const Signal a)
01281     {
01282       MetaClass &t =
01283         const_cast<MetaClass&>(static_cast<const MetaClass&>(T::metadata));
01284       // Loop through all subscriptions
01285       for (list<Functor*>::iterator i = t.subscribers[a].begin();
01286           i != t.subscribers[a].end(); ++i)
01287       {
01288         // Try casting the functor to the right type
01289         FunctorInstance<T,U> *f = dynamic_cast< FunctorInstance<T,U>* >(*i);
01290         if (f && f->instance == u)
01291         {
01292           // Casting was successfull. Delete the functor.
01293           delete *i;
01294           t.subscribers[a].erase(i);
01295           return;
01296         }
01297       }
01298       // Not found in the list of subscriptions
01299       throw LogicException("Subscription doesn't exist");
01300     }
01301 
01302     /** Constructor. */
01303     FunctorInstance(U* u) : instance(u) {}
01304 
01305   private:
01306     /** This is the callback method. */
01307     virtual bool callback(Object* v, const Signal a) const
01308     {return instance ? instance->callback(static_cast<T*>(v),a) : true;}
01309 
01310     /** The object whose callback method will be called. */
01311     U* instance;
01312 };
01313 
01314 
01315 //
01316 // UTILITY CLASS "TIMER".
01317 //
01318 
01319 /** @brief This class is used to measure the processor time used by the
01320   * program.
01321   *
01322   * The accuracy of the timer is dependent on the implementation of the
01323   * ANSI C-function clock() by your compiler and your platform.
01324   * You may count on milli-second accuracy. Different platforms provide
01325   * more accurate timer functions, which can be used if the accuracy is a
01326   * prime objective.<br>
01327   * When compiled with Visual C++, the timer is returning the elapsed
01328   * time - which is not the expected ANSI behavior!<br>
01329   * Other compilers and platforms return the consumed cpu time, as expected.
01330   * When the load on a machine is low, the consumed cpu-time and the elapsed
01331   * time are close to each other. On a system with a higher load, the
01332   * elapsed time deviates a lot from the consumed cpu-time.
01333   */
01334 class Timer
01335 {
01336   public:
01337     /** Default constructor. Creating the timer object sets the start point
01338       * for the time measurement. */
01339     explicit Timer() : start_time(clock()) {}
01340 
01341     /** Reset the time counter to 0. */
01342     void restart() {start_time = clock();}
01343 
01344     /** Return the cpu-time in seconds consumed since the creation or the last
01345       * reset of the timer. */
01346     double elapsed() const {return double(clock()-start_time)/CLOCKS_PER_SEC;}
01347 
01348   private:
01349     /** Stores the time when the timer is started. */
01350     clock_t start_time;
01351 };
01352 
01353 
01354 /** Prints a timer to the outputstream. The output is formatted as a double. */
01355 inline ostream & operator << (ostream& os, const Timer& t)
01356 {
01357   return os << t.elapsed();
01358 }
01359 
01360 
01361 //
01362 // UTILITY CLASSES "DATE", "DATE_RANGE" AND "TIME".
01363 //
01364 
01365 
01366 /** @brief This class represents a time duration with an accuracy of
01367   * one second.
01368   *
01369   * The duration can be both positive and negative.
01370   */
01371 class TimePeriod
01372 {
01373     friend ostream& operator << (ostream &, const TimePeriod &);
01374   public:
01375     /** Default constructor and constructor with timeperiod passed. */
01376     TimePeriod(const long l = 0) : lval(l) {}
01377 
01378     /** Constructor from a character string.<br>
01379       * See the parse() method for details on the format of the argument.
01380       */
01381     TimePeriod(const char* s) {parse(s);}
01382 
01383     /** Comparison between periods of time. */
01384     bool operator < (const long& b) const {return lval < b;}
01385 
01386     /** Comparison between periods of time. */
01387     bool operator > (const long& b) const {return lval > b;}
01388 
01389     /** Comparison between periods of time. */
01390     bool operator <= (const long& b) const {return lval <= b;}
01391 
01392     /** Comparison between periods of time. */
01393     bool operator >= (const long& b) const {return lval >= b;}
01394 
01395     /** Comparison between periods of time. */
01396     bool operator < (const TimePeriod& b) const {return lval < b.lval;}
01397 
01398     /** Comparison between periods of time. */
01399     bool operator > (const TimePeriod& b) const {return lval > b.lval;}
01400 
01401     /** Comparison between periods of time. */
01402     bool operator <= (const TimePeriod& b) const {return lval <= b.lval;}
01403 
01404     /** Comparison between periods of time. */
01405     bool operator >= (const TimePeriod& b) const {return lval >= b.lval;}
01406 
01407     /** Equality operator. */
01408     bool operator == (const TimePeriod& b) const {return lval == b.lval;}
01409 
01410     /** Inequality operator. */
01411     bool operator != (const TimePeriod& b) const {return lval != b.lval;}
01412 
01413     /** Increase the timeperiod. */
01414     void operator += (const TimePeriod& l) {lval += l.lval;}
01415 
01416     /** Decrease the timeperiod. */
01417     void operator -= (const TimePeriod& l) {lval -= l.lval;}
01418 
01419     /** Returns true of the duration is equal to 0. */
01420     bool operator ! () const {return lval == 0L;}
01421 
01422     /** This conversion operator creates a long value from a timeperiod. */
01423     operator long() const {return lval;}
01424 
01425     /** Converts the date to a string, formatted according to ISO 8601. */
01426     operator string() const
01427     {
01428       char str[20];
01429       toCharBuffer(str);
01430       return string(str);
01431     }
01432 
01433     /** Function that parses a input string to a time value.<br>
01434       * The string format is following the ISO 8601 specification for
01435       * durations: [-]P[nY][nM][nW][nD][T[nH][nM][nS]]<br>
01436       * Some examples to illustrate how the string is converted to a
01437       * timeperiod, expressed in seconds:<br>
01438       *    P1Y = 1 year = 365 days = 31536000 seconds
01439       *    P1M = 365/12 days = 2628000 seconds
01440       *    P1W = 1 week = 7 days = 604800 seconds
01441       *    -P1D = -1 day = -86400 seconds
01442       *    PT1H = 1 hour = 3600 seconds
01443       *    -PT1000000S = 1000000 seconds
01444       *    P1M1WT1H = 1 month + 1 week + 1 hour = 3236400 seconds
01445       * It pretty strictly checks the spec, with a few exceptions:
01446       *  - A week field ('W') may coexist with other units.
01447       *  - Decimal values are not supported.
01448       *  - The alternate format as a date and time is not supported.
01449       */
01450     DECLARE_EXPORT void parse(const char*);
01451 
01452     /** The maximum value for a timeperiod. */
01453     DECLARE_EXPORT static const TimePeriod MAX;
01454 
01455     /** The minimum value for a timeperiod. */
01456     DECLARE_EXPORT static const TimePeriod MIN;
01457 
01458   private:
01459     /** The time is stored as a number of seconds. */
01460     long lval;
01461 
01462     /** This function fills a character buffer with a text representation of
01463       * the TimePeriod.<br>
01464       * The character buffer passed MUST have room for at least 20 characters.
01465       * 20 characters is sufficient for even the most longest possible time
01466       * duration.<br>
01467       * The output format is described with the string() method.
01468       * @see string()
01469       */
01470     DECLARE_EXPORT void toCharBuffer(char*) const;
01471 };
01472 
01473 
01474 /** Prints a Timeperiod to the outputstream.
01475   * @see TimePeriod::string()
01476   */
01477 inline ostream & operator << (ostream & os, const TimePeriod & t)
01478 {
01479   char str[20];
01480   t.toCharBuffer(str);
01481   return os << str;
01482 }
01483 
01484 
01485 /** @brief This class represents a date and time with an accuracy of
01486   * one second. */
01487 class Date
01488 {
01489     friend ostream& operator << (ostream &, const Date &);
01490   private:
01491     /** This string is a format string to be used to convert a date to and
01492       * from a string format. The formats codes that are allowed are the
01493       * ones recognized by the standard C function strftime:
01494       *  - %a short name of day
01495       *  - %A full name of day
01496       *  - %b short name of month
01497       *  - %B full name of month
01498       *  - %c standard string for Date and time
01499       *  - %d day of month (between 1 and 31)
01500       *  - %H hour (between 0 and 23)
01501       *  - %I hour (between 1 and 12)
01502       *  - %j day of the year (between 1 and 366)
01503       *  - %m month as number (between 1 and 12)
01504       *  - %M minutes (between 0 and 59)
01505       *  - %p AM/PM
01506       *  - %S seconds (between o and 59)
01507       *  - %U week of the year (between 0 and 52, sunday as start of week)
01508       *  - %w day of the week (between 0 and 6, sunday as start of week)
01509       *  - %W week of the year (monday as first day of week)
01510       *  - %x standard string for Date
01511       *  - %X standard string for time
01512       *  - %y year (between 0 and 99, without century)
01513       *  - %Y year (complete)
01514       *  - %Z time zone
01515       *  - %% percentage sign
01516       * The default date format is %Y-%m-%dT%H:%M:%S, which is the standard
01517       * format defined in the XML Schema standard.
01518       */
01519     static DECLARE_EXPORT string format;
01520 
01521     /** The internal representation of a date is a single long value. */
01522     time_t lval;
01523 
01524     /** Checks whether we stay within the boundaries of finite Dates. */
01525     DECLARE_EXPORT void checkFinite(long long);
01526 
01527     /** A private constructor used to create the infinitePast and
01528       * infiniteFuture constants. */
01529     Date(const char* s, bool dummy) {parse(s);}
01530 
01531     /** Constructor initialized with a long value. */
01532     Date(const time_t l) : lval(l) {checkFinite(lval);}
01533 
01534   public:
01535     /** Default constructor. */
01536     // This constructor can skip the check for finite dates, and
01537     // thus gives the best performance.
01538     Date() : lval(infinitePast.lval) {}
01539 
01540     /* Note: the automatic copy constructor works fine and is faster than
01541        writing our own. */
01542 
01543     /** Constructor initialized with a string. The string needs to be in
01544       * the format specified by the "format". */
01545     Date(const char* s) {parse(s); checkFinite(lval);}
01546 
01547     /** Constructor with year, month and day as arguments. Hours, minutes
01548       * and seconds can optionally be passed too.
01549       */
01550     DECLARE_EXPORT Date(int year, int month, int day,
01551         int hr=0, int min=0, int sec=0
01552                        );
01553 
01554     /** Comparison between dates. */
01555     bool operator < (const Date& b) const {return lval < b.lval;}
01556 
01557     /** Comparison between dates. */
01558     bool operator > (const Date& b) const {return lval > b.lval;}
01559 
01560     /** Equality of dates. */
01561     bool operator == (const Date& b) const {return lval == b.lval;}
01562 
01563     /** Inequality of dates. */
01564     bool operator != (const Date& b) const {return lval != b.lval;}
01565 
01566     /** Comparison between dates. */
01567     bool operator >= (const Date& b) const {return lval >= b.lval;}
01568 
01569     /** Comparison between dates. */
01570     bool operator <= (const Date& b) const {return lval <= b.lval;}
01571 
01572     /** Assignment operator. */
01573     void operator = (const Date& b) {lval = b.lval;}
01574 
01575     /** Adds some time to this date. */
01576     void operator += (const TimePeriod& l)
01577     {checkFinite(static_cast<long long>(l) + lval);}
01578 
01579     /** Subtracts some time to this date. */
01580     void operator -= (const TimePeriod& l)
01581     {checkFinite(- static_cast<long long>(l) + lval);}
01582 
01583     /** Adding a time to a date returns a new date. */
01584     Date operator + (const TimePeriod& l) const
01585     {
01586       Date d;
01587       d.checkFinite(static_cast<long long>(l) + lval);
01588       return d;
01589     }
01590 
01591     /** Subtracting a time from a date returns a new date. */
01592     Date operator - (const TimePeriod& l) const
01593     {
01594       Date d;
01595       d.checkFinite(- static_cast<long>(l) + lval);
01596       return d;
01597     }
01598 
01599     /** Subtracting two date values returns the time difference in a
01600       * TimePeriod object. */
01601     TimePeriod operator - (const Date& l) const
01602     {return static_cast<long>(lval - l.lval);}
01603 
01604     /** Check whether the date has been initialized. */
01605     bool operator ! () const {return lval == infinitePast.lval;}
01606 
01607     /** Check whether the date has been initialized. */
01608     operator bool() const {return lval != infinitePast.lval;}
01609 
01610     /** Static function returns a date object initialized with the current
01611       * Date and time. */
01612     static Date now() {return Date(time(0));}
01613 
01614     /** Converts the date to a string. The format can be controlled by the
01615       * setFormat() function. */
01616     operator string() const
01617     {
01618       char str[30];
01619       toCharBuffer(str);
01620       return string(str);
01621     }
01622 
01623     /** This function fills a character buffer with a text representation of
01624       * the date.<br>
01625       * The character buffer passed is expected to have room for
01626       * at least 30 characters. 30 characters should be sufficient for even
01627       * the most funky date format.
01628       */
01629     DECLARE_EXPORT size_t toCharBuffer(char*) const;
01630 
01631     /** Return the seconds since the epoch, which is also the internal
01632       * representation of a date. */
01633     time_t getTicks() const {return lval;}
01634 
01635     /** Function that parses a string according to the format string. */
01636     DECLARE_EXPORT void parse(const char*, const string& = format);
01637 
01638     /** Updates the default date format. */
01639     static void setFormat(const string& n) {format = n;}
01640 
01641     /** Retrieves the default date format. */
01642     static string getFormat() {return format;}
01643 
01644     /** A constant representing the infinite past, i.e. the earliest time which
01645       * we can represent.<br>
01646       * This value is normally 1971-01-01T00:00:00.
01647       */
01648     static DECLARE_EXPORT const Date infinitePast;
01649 
01650     /** A constant representing the infinite future, i.e. the latest time which
01651       * we can represent.<br>
01652       * This value is currently set to 2030-12-31T00:00:00.
01653       */
01654     static DECLARE_EXPORT const Date infiniteFuture;
01655 
01656 #ifndef HAVE_STRPTIME
01657   private:
01658     DECLARE_EXPORT char* strptime(const char *, const char *, struct tm *);
01659 #endif
01660 };
01661 
01662 
01663 /** Prints a date to the outputstream. */
01664 inline ostream & operator << (ostream & os, const Date & d)
01665 {
01666   char str[30];
01667   d.toCharBuffer(str);
01668   return os << str;
01669 }
01670 
01671 
01672 /** @brief This class defines a date-range, i.e. a start-date and end-date pair.
01673   *
01674   * The behavior is such that the start date is considered as included in
01675   * it, but the end date is excluded from it.
01676   * In other words, a daterange is a halfopen date interval: [start,end[<br>
01677   * The start and end dates are always such that the start date is less than
01678   * or equal to the end date.
01679   */
01680 class DateRange
01681 {
01682   public:
01683     /** Constructor with specified start and end dates.<br>
01684       * If the start date is later than the end date parameter, the
01685       * parameters will be swapped. */
01686     DateRange(const Date& st, const Date& nd) : start(st), end(nd)
01687     {if(st>nd) {start=nd; end=st;}}
01688 
01689     /** Default constructor.<br>
01690       * This will create a daterange covering the complete horizon.
01691       */
01692     DateRange() : start(Date::infinitePast), end(Date::infiniteFuture) {}
01693 
01694     /** Copy constructor. */
01695     DateRange(const DateRange& n) : start(n.start), end(n.end) {}
01696 
01697     /** Returns the start date. */
01698     const Date& getStart() const {return start;}
01699 
01700     /** Updates the start date.<br>
01701       * If the new start date is later than the end date, the end date will
01702       * be set equal to the new start date.
01703       */
01704     void setStart(const Date& d) {start=d; if(start>end) end=start;}
01705 
01706     /** Returns the end date. */
01707     const Date & getEnd() const {return end;}
01708 
01709     /** Updates the end date.<br>
01710       * If the new end date is earlier than the start date, the start date will
01711       * be set equal to the new end date.
01712       */
01713     void setEnd(const Date& d) {end=d; if(start>end) start=end;}
01714 
01715     /** Updates the start and end dates simultaneously. */
01716     void setStartAndEnd(const Date& st, const Date& nd)
01717     {if (st<nd) {start=st; end=nd;} else {start=nd; end=st;}}
01718 
01719     /** Returns the duration of the interval. Note that this number will always
01720       * be greater than or equal to 0, since the end date is always later than
01721       * the start date.
01722       */
01723     TimePeriod getDuration() const {return end - start;}
01724 
01725     /** Equality of date ranges. */
01726     bool operator == (const DateRange& b) const
01727     {return start==b.start && end==b.end;}
01728 
01729     /** Inequality of date ranges. */
01730     bool operator != (const DateRange& b) const
01731     {return start!=b.start || end!=b.end;}
01732 
01733     /** Move the daterange later in time. */
01734     void operator += (const TimePeriod& l) {start += l; end += l;}
01735 
01736     /** Move the daterange earlier in time. */
01737     void operator -= (const TimePeriod& l) {start -= l; end -= l;}
01738 
01739     /** Assignment operator. */
01740     void operator = (const DateRange& dr) {start = dr.start; end = dr.end;}
01741 
01742     /** Return true if two date ranges are overlapping.<br>
01743       * The start point of the first interval is included in the comparison,
01744       * whereas the end point isn't. As a result this method is not
01745       * symmetrical, ie when a.intersect(b) returns true b.intersect(a) is
01746       * not nessarily true.
01747       */
01748     bool intersect(const DateRange& dr) const
01749     {return dr.start<=end && dr.end>start;}
01750 
01751     /** Returns the number of seconds the two dateranges overlap. */
01752     TimePeriod overlap(const DateRange& dr) const
01753     {
01754       long x = (dr.end<end ? dr.end : end)
01755           - (dr.start>start ? dr.start : start);
01756       return x>0 ? x : 0;
01757     }
01758 
01759     /** Returns true if the date passed as argument does fall within the
01760       * daterange. */
01761     bool within(const Date& d) const {return d>=start && d<end;}
01762 
01763     /** Convert the daterange to a string. */
01764     DECLARE_EXPORT operator string() const;
01765 
01766     /** Updates the default seperator. */
01767     static void setSeparator(const string& n)
01768     {
01769       separator = n;
01770       separatorlength = n.size();
01771     }
01772 
01773     /** Retrieves the default seperator. */
01774     static const string& getSeparator() {return separator;}
01775 
01776   private:
01777     /** Start date of the interval. */
01778     Date start;
01779 
01780     /** End dat of the interval. */
01781     Date end;
01782 
01783     /** Separator to be used when printing this string. */
01784     static DECLARE_EXPORT string separator;
01785 
01786     /** Separator to be used when printing this string. */
01787     static DECLARE_EXPORT size_t separatorlength;
01788 };
01789 
01790 
01791 /** Prints a date range to the outputstream.
01792   * @see DateRange::string() */
01793 inline ostream & operator << (ostream & os, const DateRange & dr)
01794 {
01795   return os << dr.getStart() << DateRange::getSeparator() << dr.getEnd();
01796 }
01797 
01798 
01799 //
01800 // UTILITY CLASSES FOR INPUT AND OUTPUT
01801 //
01802 
01803 
01804 /** This type is used to define different ways of persisting an object. */
01805 enum mode
01806 {
01807   /** Write the full object or a reference. If the object is nested more
01808     * than one level deep a reference is written, otherwise the complete
01809     * object is written.<br>
01810     * This mode is the one to be used when dumping all objects to be restored
01811     * later. The other modes can dump too little or too much data.
01812     * Eg: <MODEL NAME="POL" TYPE="a"><FIELD>value</FIELD></MODEL>
01813     */
01814   DEFAULT = 0,
01815   /** Write only the key fields of the object.<br>
01816     * Eg: <MODEL NAME="POL" TYPE="a"/>
01817     */
01818   REFERENCE = 1,
01819   /** Write the full object, but without a header line. This method is
01820     * typically used when a subclass calls the write method of its parent
01821     * class.<br>
01822     * Eg: <FIELD>value</FIELD></MODEL>
01823     */
01824   NOHEADER = 2,
01825   /** Write the full object, with all its fields and a header line.<br>
01826     * Eg: <MODEL NAME="POL" TYPE="a"><FIELD>value</FIELD></MODEL>
01827     */
01828   FULL = 3
01829 };
01830 
01831 
01832 /** @ brief This utility class escapes special characters from a string.
01833   *
01834   *  The following characters are replaced:
01835   *    - &: replaced with &amp;
01836   *    - <: replaced with &lt;
01837   *    - >: replaced with &gt;
01838   *    - ": replaced with &quot;
01839   *    - ': replaced with &apos;
01840   *    - all other characters are left unchanged
01841   * The reverse process of un-escaping the special character sequences is
01842   * taken care of by the Xerces library.
01843   *
01844   * This class works fine with UTF-8 and single-byte encodings, but will
01845   * NOT work with other multibyte encodings (such as UTF-116 or UTF-32).
01846   */
01847 class XMLEscape
01848 {
01849     friend DECLARE_EXPORT ostream& operator << (ostream&, const XMLEscape&);
01850   private:
01851     const char* data;
01852   public:
01853     XMLEscape(const char* p) {data = p;}
01854     XMLEscape(const string& p) {data = p.c_str();}
01855 };
01856 
01857 
01858 /** Prints the escaped value of the string to the outputstream. */
01859 DECLARE_EXPORT ostream & operator << (ostream&, const XMLEscape&);
01860 
01861 
01862 /** @brief Base class for writing XML formatted data to an output stream.
01863   *
01864   * Subclasses implement writing to specific stream types, such as files
01865   * and strings.
01866   */
01867 class XMLOutput
01868 {
01869   protected:
01870     /** Updating the output stream. */
01871     void setOutput(ostream& o) {m_fp = &o;}
01872 
01873   public:
01874     /** This type is used to define different types of output.
01875       * @see STANDARD
01876       * @see PLAN
01877       * @see PLANDETAIL
01878       */
01879     typedef unsigned short content_type;
01880 
01881     /** Constant used to mark standard export for the export.
01882       * The standard export saves just enough information to persist the full
01883       * state of the model as brief as possible.
01884       * @see PLAN
01885       * @see PLANDETAIL
01886       */
01887     static DECLARE_EXPORT const content_type STANDARD;
01888 
01889     /** Constant to mark an export of the standard information plus the plan
01890       * information. In this format, every entity is saved with the details
01891       * on how it is used in the plan.<br>
01892       * E.g. a resource will be saved with a reference to all its loadplans.
01893       * E.g. an operation will be saved with all its operationplans.
01894       * @see STANDARD
01895       * @see PLANDETAIL
01896       */
01897     static DECLARE_EXPORT const content_type PLAN;
01898 
01899     /** Constant to mark an export of the lowest level of plan information.
01900       * In addition to the plan information pegging information is now saved.
01901       * @see STANDARD
01902       * @see PLAN
01903       */
01904     static DECLARE_EXPORT const content_type PLANDETAIL;
01905 
01906     /** Returns which type of export is requested.
01907       * Constants have been defined for each type.
01908       * @see STANDARD
01909       * @see PLAN
01910       * @see PLANDETAIL
01911       */
01912     content_type getContentType() const {return content;}
01913 
01914     /** Specify the type of export.
01915       * @see STANDARD
01916       * @see PLAN
01917       * @see PLANDETAIL
01918       */
01919     void setContentType(content_type c) {content = c;}
01920 
01921     /** Updates the string that is printed as the first line of each XML
01922       * document.<br>
01923       * The default value is:
01924       *   <?xml version="1.0" encoding="UTF-8"?>
01925       */
01926     void setHeaderStart(const string& s) {headerStart = s;}
01927 
01928     /** Returns the string that is printed as the first line of each XML
01929       * document. */
01930     string getHeaderStart() const {return headerStart;}
01931 
01932     /** Updates the attributes that are written for the root element of each
01933       * XML document.<br>
01934       * The default value is an empty string.
01935       */
01936     void setHeaderAtts(const string& s) {headerAtts = s;}
01937 
01938     /** Returns the attributes that are written for the root element of each
01939       * XML document. */
01940     string getHeaderAtts() const {return headerAtts;}
01941 
01942     /** Constructor with a given stream. */
01943     XMLOutput(ostream& os) : m_nIndent(0), numObjects(0),
01944       numParents(0), currentObject(NULL), parentObject(NULL), content(STANDARD),
01945       headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
01946       headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
01947     {m_fp = &os; indentstring[0] = '\0';}
01948 
01949     /** Default constructor. */
01950     XMLOutput() : m_nIndent(0), numObjects(0), numParents(0),
01951       currentObject(NULL), parentObject(NULL), content(STANDARD),
01952       headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
01953       headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
01954     {m_fp = &logger; indentstring[0] = '\0';}
01955 
01956     /** Start writing a new object. This method will open a new XML-tag.<br>
01957       * Output: <TAG_T> */
01958     void BeginObject(const Keyword& t)
01959     {
01960       *m_fp << indentstring << t.stringElement() << "\n";
01961       incIndent();
01962     }
01963 
01964     /** Start writing a new object. This method will open a new XML-tag.<br>
01965       * Output: <TAG_T TAG_U="val1"> */
01966     void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1)
01967     {
01968       *m_fp << indentstring << t.stringStartElement()
01969           << attr1.stringAttribute() << XMLEscape(val1) << "\">\n";
01970       incIndent();
01971     }
01972 
01973     /** Start writing a new object. This method will open a new XML-tag.<br>
01974       * Output: <TAG_T TAG_T1="val1" TAG_T2="val2"> */
01975     void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1,
01976         const Keyword& attr2, const string& val2)
01977     {
01978       *m_fp << indentstring << t.stringStartElement()
01979           << attr1.stringAttribute() << XMLEscape(val1) << "\""
01980           << attr2.stringAttribute() << XMLEscape(val2) << "\">\n";
01981       incIndent();
01982     }
01983 
01984     /** Start writing a new object. This method will open a new XML-tag.<br>
01985       * Output: <TAG_T TAG_U="val1" TAG_V="val2" TAG_W="val3"> */
01986     void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1,
01987         const Keyword& attr2, const string& val2,
01988         const Keyword& attr3, const string& val3)
01989     {
01990       *m_fp << indentstring << t.stringStartElement()
01991           << attr1.stringAttribute() << XMLEscape(val1) << "\""
01992           << attr2.stringAttribute() << XMLEscape(val2) << "\""
01993           << attr3.stringAttribute() << XMLEscape(val3) << "\">\n";
01994       incIndent();
01995     }
01996 
01997     /** Start writing a new object. This method will open a new XML-tag. */
01998     void BeginObject(const Keyword& t, const string& atts)
01999     {
02000       *m_fp << indentstring << t.stringStartElement() << " " << atts << ">\n";
02001       incIndent();
02002     }
02003 
02004     /** Start writing a new object. This method will open a new XML-tag.<br>
02005       * Output: <TAG_T TAG_U="long"> */
02006     void BeginObject(const Keyword& t, const Keyword& attr1, const long val1)
02007     {
02008       *m_fp << indentstring << t.stringStartElement()
02009           << attr1.stringAttribute() << val1 << "\">\n";
02010       incIndent();
02011     }
02012 
02013     /** Start writing a new object. This method will open a new XML-tag.<br>
02014       * Output: <TAG_T TAG_T1="val1" TAG_T2="val2"> */
02015     void BeginObject(const Keyword& t, const Keyword& attr1, unsigned long val1,
02016         const Keyword& attr2, const string& val2)
02017     {
02018       *m_fp << indentstring << t.stringStartElement()
02019           << attr1.stringAttribute() << val1 << "\""
02020           << attr2.stringAttribute() << XMLEscape(val2) << "\">\n";
02021       incIndent();
02022     }
02023 
02024     /** Write the closing tag of this object and decrease the indentation
02025       * level.<br>
02026       * Output: </TAG_T>
02027       */
02028     void EndObject(const Keyword& t)
02029     {
02030       decIndent();
02031       *m_fp << indentstring << t.stringEndElement();
02032     }
02033 
02034     /** Write the string to the output. No XML-tags are added, so this method
02035       * is used for passing text straight into the output file. */
02036     void writeString(const string& c)
02037     {
02038       *m_fp << indentstring << c << "\n";
02039     }
02040 
02041     /** Write an unsigned long value enclosed opening and closing tags.<br>
02042       * Output: <TAG_T>uint</TAG_T> */
02043     void writeElement(const Keyword& t, const long unsigned int val)
02044     {
02045       *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
02046     }
02047 
02048     /** Write an integer value enclosed opening and closing tags.<br>
02049       * Output: <TAG_T>integer</TAG_T> */
02050     void writeElement(const Keyword& t, const int val)
02051     {
02052       *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
02053     }
02054 
02055     /** Write a double value enclosed opening and closing tags.<br>
02056       * Output: <TAG_T>double</TAG_T> */
02057     void writeElement(const Keyword& t, const double val)
02058     {
02059       *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
02060     }
02061 
02062     /** Write a boolean value enclosed opening and closing tags. The boolean
02063       * is written out as the string 'true' or 'false'.<br>
02064       * Output: <TAG_T>true</TAG_T>
02065       */
02066     void writeElement(const Keyword& t, const bool val)
02067     {
02068       *m_fp << indentstring << t.stringElement()
02069           << (val ? "true" : "false") << t.stringEndElement();
02070     }
02071 
02072     /** Write a string value enclosed opening and closing tags. Special
02073       * characters (i.e. & < > " ' ) are appropriately escaped.<br>
02074       * Output: <TAG_T>val</TAG_T> */
02075     void writeElement(const Keyword& t, const string& val)
02076     {
02077       if (!val.empty())
02078         *m_fp << indentstring << t.stringElement()
02079             << XMLEscape(val) << t.stringEndElement();
02080     }
02081 
02082     /** Writes an element with a string attribute.<br>
02083       * Output: <TAG_U TAG_T="string"/> */
02084     void writeElement(const Keyword& u, const Keyword& t, const string& val)
02085     {
02086       if (val.empty())
02087         *m_fp << indentstring << u.stringStartElement() << "/>\n";
02088       else
02089         *m_fp << indentstring << u.stringStartElement()
02090             << t.stringAttribute() << XMLEscape(val)
02091             << "\"/>\n";
02092     }
02093 
02094     /** Writes an element with a long attribute.<br>
02095       * Output: <TAG_U TAG_T="val"/> */
02096     void writeElement(const Keyword& u, const Keyword& t, const long val)
02097     {
02098       *m_fp << indentstring << u.stringStartElement()
02099           << t.stringAttribute() << val << "\"/>\n";
02100     }
02101 
02102     /** Writes an element with a date attribute.<br>
02103       * Output: <TAG_U TAG_T="val"/> */
02104     void writeElement(const Keyword& u, const Keyword& t, const Date& val)
02105     {
02106       *m_fp << indentstring << u.stringStartElement()
02107           << t.stringAttribute() << string(val) << "\"/>\n";
02108     }
02109 
02110     /** Writes an element with 2 string attributes.<br>
02111       * Output: <TAG_U TAG_T1="val1" TAG_T2="val2"/> */
02112     void writeElement(const Keyword& u, const Keyword& t1, const string& val1,
02113         const Keyword& t2, const string& val2)
02114     {
02115       if(val1.empty())
02116         *m_fp << indentstring << u.stringStartElement() << "/>\n";
02117       else
02118         *m_fp << indentstring << u.stringStartElement()
02119             << t1.stringAttribute() << XMLEscape(val1.c_str()) << "\""
02120             << t2.stringAttribute() << XMLEscape(val2.c_str())
02121             << "\"/>\n";
02122     }
02123 
02124     /** Writes an element with a string and a long attribute.<br>
02125       * Output: <TAG_U TAG_T1="val1" TAG_T2="val2"/> */
02126     void writeElement(const Keyword& u, const Keyword& t1, unsigned long val1,
02127         const Keyword& t2, const string& val2)
02128     {
02129       *m_fp << indentstring << u.stringStartElement()
02130           << t1.stringAttribute() << val1 << "\""
02131           << t2.stringAttribute() << XMLEscape(val2.c_str())
02132           << "\"/>\n";
02133     }
02134 
02135     /** Writes a C-type character string.<br>
02136       * Output: <TAG_T>val</TAG_T> */
02137     void writeElement(const Keyword& t, const char* val)
02138     {
02139       if (val)
02140         *m_fp << indentstring << t.stringElement()
02141             << XMLEscape(val) << t.stringEndElement();
02142     }
02143 
02144     /** Writes an timeperiod element.<br>
02145       * Output: <TAG_T>d</TAG_T> /> */
02146     void writeElement(const Keyword& t, const TimePeriod d)
02147     {
02148       *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02149     }
02150 
02151     /** Writes an date element.<br>
02152       * Output: <TAG_T>d</TAG_T> /> */
02153     void writeElement(const Keyword& t, const Date d)
02154     {
02155       *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02156     }
02157 
02158     /** Writes an daterange element.<br>
02159       * Output: <TAG_T>d</TAG_T> */
02160     void writeElement(const Keyword& t, const DateRange& d)
02161     {
02162       *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02163     }
02164 
02165     /** This method writes a serializable object. It maintains a STL-map of
02166       * all objects that have been saved already. For objects that have
02167       * already been saved earlier, the method will instruct the serializable
02168       * object to write only a reference, rather than the complete object.
02169       * You should call this method for all objects in your xml document,
02170       * except for the root object.
02171       * @see writeElementWithHeader(const Keyword&, Object*)
02172       */
02173     DECLARE_EXPORT void writeElement(const Keyword&, const Object*, mode = DEFAULT);
02174 
02175     /** @see writeElement(const Keyword&, const Object*, mode) */
02176     void writeElement(const Keyword& t, const Object& o, mode m = DEFAULT)
02177     {writeElement(t,&o,m);}
02178 
02179     /** This method writes a serializable object with a complete XML compliant
02180       * header.<br>
02181       * You should call this method for the root object of your xml document,
02182       * and writeElement for all objects nested in it.
02183       * @see writeElement(const Keyword&, Object*)
02184       * @see writeHeader
02185       * @exception RuntimeException Generated when multiple root elements
02186       *    are available for the output document.
02187       */
02188     DECLARE_EXPORT void writeElementWithHeader(const Keyword& tag, const Object* object);
02189 
02190     /** This method writes the opening tag for an XML output.<br>
02191       * You should call this method or writeElementWithHeader() when writing
02192       * the first element of an xml document.
02193       * @see writeElementWithHeader
02194       * @exception RuntimeException Generated when multiple root elements
02195       *    are available for the output document.
02196       */
02197     DECLARE_EXPORT void writeHeader(const Keyword& tag);
02198 
02199     /** Returns a pointer to the object that is currently being saved. */
02200     Object* getCurrentObject() const
02201     {return const_cast<Object*>(currentObject);}
02202 
02203     /** Returns a pointer to the parent of the object that is being saved. */
02204     Object* getPreviousObject() const
02205     {return const_cast<Object*>(parentObject);}
02206 
02207     /** Returns the number of objects that have been serialized. */
02208     unsigned long countObjects() const {return numObjects;}
02209 
02210   private:
02211     /** Output stream. */
02212     ostream* m_fp;
02213 
02214     /** This variable keeps track of the indentation level.
02215       * @see incIndent, decIndent
02216       */
02217     short int m_nIndent;
02218 
02219     /** This string is a null terminated string containing as many spaces as
02220       * indicated by the m_indent.
02221       * @see incIndent, decIndent
02222       */
02223     char indentstring[41];
02224 
02225     /** Keep track of the number of objects being stored. */
02226     unsigned long numObjects;
02227 
02228     /** Keep track of the number of objects currently in the save stack. */
02229     unsigned int numParents;
02230 
02231     /** This stores a pointer to the object that is currently being saved. */
02232     const Object *currentObject;
02233 
02234     /** This stores a pointer to the object that has previously been saved. */
02235     const Object *parentObject;
02236 
02237     /** Increase the indentation level. The indentation level is between
02238       * 0 and 40. */
02239     DECLARE_EXPORT void incIndent();
02240 
02241     /** Decrease the indentation level. */
02242     DECLARE_EXPORT void decIndent();
02243 
02244     /** Stores the type of data to be exported. */
02245     content_type content;
02246 
02247     /** This string defines what will be printed at the start of each XML
02248       * document. The default value is:
02249       *   <?xml version="1.0" encoding="UTF-8"?>
02250       */
02251     string headerStart;
02252 
02253     /** This string defines what will be attributes are printed for the root
02254       * element of each XML document.
02255       * The default value is:
02256       *    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
02257       */
02258     string headerAtts;
02259 };
02260 
02261 
02262 /** @brief This class writes XML data to a flat file.
02263   *
02264   * Note that an object of this class can write only to a single file. If
02265   * multiple files are required multiple XMLOutputFile objects will be
02266   * required too.
02267   * @see XMLOutput
02268   */
02269 class XMLOutputFile : public XMLOutput
02270 {
02271   public:
02272     /** Constructor with a filename as argument. An exception will be
02273       * thrown if the output file can't be properly initialized. */
02274     XMLOutputFile(const string& chFilename)
02275     {
02276       of.open(chFilename.c_str(), ios::out);
02277       if(!of) throw RuntimeException("Could not open output file");
02278       setOutput(of);
02279     }
02280 
02281     /** Destructor. */
02282     ~XMLOutputFile() {of.close();}
02283 
02284   private:
02285     ofstream of;
02286 };
02287 
02288 
02289 /** @brief This class writes XML data to a string.
02290   *
02291   * The generated output is stored internally in the class, and can be
02292   * accessed by converting the XMLOutputString object to a string object.
02293   * This class can consume a lot of memory if large sets of objects are
02294   * being saved in this way.
02295   * @see XMLOutput
02296   */
02297 class XMLOutputString : public XMLOutput
02298 {
02299   public:
02300     /** Constructor with a starting string as argument. */
02301     XMLOutputString(const string& str) : os(str) {setOutput(os);}
02302 
02303     /** Default constructor. */
02304     XMLOutputString() {setOutput(os);}
02305 
02306     /** Return the output string. */
02307     const string getData() const {return os.str();}
02308 
02309   private:
02310     ostringstream os;
02311 };
02312 
02313 
02314 /** @brief A class to model keyword instances.
02315   *
02316   * The class uses hashes to do a fast comparison with the set of keywords.
02317   */
02318 class Attribute
02319 {
02320   private:
02321     /** This string stores the hash value of the element. */
02322     hashtype hash;
02323 
02324     /** A pointer to the string representation of the keyword.<br>
02325       * The string buffer is to be managed by the code creating this
02326       * instance.
02327       */
02328     const char* ch;
02329 
02330   public:
02331     /** Default constructor. */
02332     explicit Attribute() : hash(0), ch(NULL) {}
02333 
02334     /** Constructor. */
02335     explicit Attribute(const string& n)
02336       : hash(Keyword::hash(n)), ch(n.c_str()) {}
02337 
02338     /** Constructor. */
02339     explicit Attribute(const char* c) : hash(Keyword::hash(c)), ch(c) {}
02340 
02341     /** Copy constructor. */
02342     Attribute(const Attribute& o) : hash(o.hash), ch(o.ch) {}
02343 
02344     /** Returns the hash value of this tag. */
02345     hashtype getHash() const {return hash;}
02346 
02347     /** Returns this tag. */
02348     void reset(const char *const c)
02349     {
02350       hash = Keyword::hash(c);
02351       ch = c;
02352     }
02353 
02354     /** Returns this tag. */
02355     void reset(const XMLCh *const c)
02356     {
02357       hash = Keyword::hash(c);
02358       // An XMLCh is normally a wchar, and would need to be transcoded
02359       // to a char. We won't bother...
02360       ch = NULL;
02361     }
02362 
02363     /** Return the element name. Since this method involves a lookup in a
02364       * table with Keywords, it has some performance impact and should be
02365       * avoided where possible. Only the hash of an element can efficiently
02366       * be retrieved.
02367       */
02368     DECLARE_EXPORT const char* getName() const;
02369 
02370     /** Returns true when this element is an instance of this tag. This method
02371       * doesn't involve a string comparison and is extremely efficient. */
02372     bool isA(const Keyword& t) const {return t.getHash() == hash;}
02373 
02374     /** Returns true when this element is an instance of this tag. This method
02375       * doesn't involve a string comparison and is extremely efficient. */
02376     bool isA(const Keyword* t) const {return t->getHash() == hash;}
02377 
02378     /** Comparison operator. */
02379     bool operator < (const Attribute& o) const {return hash < o.hash;}
02380 
02381     /** String comparison. */
02382     bool operator == (const string o) const {return o == ch;}
02383 };
02384 
02385 
02386 /** @brief This abstract class represents a attribute and value pair for
02387   * updating objects in frePPLe.
02388   *
02389   * It is instantiated in the XMLElement and PythonObject classes.
02390   * @todo only takes care of transformation from external format to C++. Not the C++ to external format yet.
02391   */
02392 class DataElement
02393 {
02394   public:
02395     virtual operator bool() const
02396     {throw LogicException("DataElement is an abstract class");}
02397 
02398     /** Destructor. */
02399     virtual ~DataElement() {}
02400 
02401     void operator >> (unsigned long int& val) const {val = getUnsignedLong();}
02402 
02403     void operator >> (long& val) const {val = getLong();}
02404 
02405     void operator >> (TimePeriod& val) const {val = getTimeperiod();}
02406 
02407     void operator >> (bool& v) const {v=getBool();}
02408 
02409     void operator >> (int& val) const {val = getInt();}
02410 
02411     void operator >> (double& val) const {val = getDouble();}
02412 
02413     void operator >> (Date& val) const {val = getDate();}
02414 
02415     void operator >> (string& val) const {val = getString();}
02416 
02417     virtual long getLong() const
02418     {throw LogicException("DataElement is an abstract class");}
02419 
02420     virtual unsigned long getUnsignedLong() const
02421     {throw LogicException("DataElement is an abstract class");}
02422 
02423     virtual TimePeriod getTimeperiod() const
02424     {throw LogicException("DataElement is an abstract class");}
02425 
02426     virtual int getInt() const
02427     {throw LogicException("DataElement is an abstract class");}
02428 
02429     virtual double getDouble() const
02430     {throw LogicException("DataElement is an abstract class");}
02431 
02432     virtual Date getDate() const
02433     {throw LogicException("DataElement is an abstract class");}
02434 
02435     virtual string getString() const
02436     {throw LogicException("DataElement is an abstract class");}
02437 
02438     virtual bool getBool() const
02439     {throw LogicException("DataElement is an abstract class");}
02440 };
02441 
02442 
02443 /** @brief This class represents an XML element being read in from the
02444   * input file. */
02445 class XMLElement : public DataElement
02446 {
02447   private:
02448     /** This string stores the XML input data. */
02449     string m_strData;
02450 
02451   public:
02452     virtual operator bool() const {return !m_strData.empty();}
02453 
02454     /** Default constructor. */
02455     XMLElement() {}
02456 
02457     /** Constructor. */
02458     XMLElement(const string& v) : m_strData(v) {}
02459 
02460     /** Destructor. */
02461     virtual ~XMLElement() {}
02462 
02463     /** Re-initializes an existing element. Using this method we can avoid
02464       * destroying and recreating XMLelement objects too frequently. Instead
02465       * we can manage them in a array.
02466       */
02467     void reset() {m_strData.clear();}
02468 
02469     /** Add some characters to this data field of this element.<br>
02470       * The second argument is the number of bytes, not the number of
02471       * characters.
02472       */
02473     void addData(const char *pData, size_t len) {m_strData.append(pData,len);}
02474 
02475     /** Set the data value of this element. */
02476     void setData(const char *pData) {m_strData.assign(pData);}
02477 
02478     /** Return the data field. */
02479     const char *getData() const {return m_strData.c_str();}
02480 
02481     virtual long getLong() const {return atol(getData());}
02482 
02483     virtual unsigned long getUnsignedLong() const {return atol(getData());}
02484 
02485     virtual TimePeriod getTimeperiod() const {return TimePeriod(getData());}
02486 
02487     virtual int getInt() const {return atoi(getData());}
02488 
02489     virtual double getDouble() const {return atof(getData());}
02490 
02491     virtual Date getDate() const {return Date(getData());}
02492 
02493     /** Returns the string value of the XML data. The xerces library takes care
02494       * of appropriately unescaping special character sequences. */
02495     virtual string getString() const {return m_strData;}
02496 
02497     /** Interprets the element as a boolean value.<br>
02498       * <p>Our implementation is a bit more generous and forgiving than the
02499       * boolean datatype that is part of the XML schema v2 standard.
02500       * The standard expects the following literals:<br>
02501       *   {true, false, 1, 0}</p>
02502       * <p>Our implementation uses only the first charater of the text, and is
02503       * case insensitive. It thus matches a wider range of values:<br>
02504       *   {t.*, T.*, f.*, F.*, 1.*, 0.*}</p>
02505       */
02506     DECLARE_EXPORT bool getBool() const;
02507 };
02508 
02509 
02510 /** @brief This class groups some functions used to interact with the operating
02511   * system environment.
02512   *
02513   * It handles:
02514   *   - The location of the configuration files.
02515   *   - The maximum number of processors / threads to be used by frePPLe.
02516   *   - An output stream for logging all output.
02517   *   - Dynamic loading of a shared library.
02518   */
02519 class Environment
02520 {
02521   private:
02522     /** Caches the number of processor cores. */
02523     static DECLARE_EXPORT int processorcores;
02524 
02525     /** A file where output is directed to. */
02526     static DECLARE_EXPORT ofstream logfile;
02527 
02528     /** The name of the log file. */
02529     static DECLARE_EXPORT string logfilename;
02530 
02531     /** A list of all loaded modules. */
02532     static DECLARE_EXPORT set<string> moduleRegistry;
02533 
02534   public:
02535     /** Search for a file with a given name.<br>
02536       * The following directories are searched in sequence to find a match:
02537       *   - The current directory.
02538       *   - The directory reffered to by the variable FREPPLE_HOME, if it
02539       *     is defined.
02540       *   - The data directory as configured during the compilation.
02541       *     This applies only to linux / unix.
02542       *   - The library directory as configured during the compilation.
02543       *     This applies only to linux / unix.
02544       */
02545     static DECLARE_EXPORT string searchFile(const string);
02546 
02547     /** Returns the number of processor cores on your machine. */
02548     static DECLARE_EXPORT int getProcessorCores();
02549 
02550     /** Returns the name of the logfile. */
02551     static const string& getLogFile() {return logfilename;}
02552 
02553     /** Updates the filename for logging error messages and warnings.
02554       * The file is also opened for writing and the standard output and
02555       * standard error output streams are redirected to it.<br>
02556       * If the filename starts with '+' the log file is appended to
02557       * instead of being overwritten.
02558       */
02559     static DECLARE_EXPORT void setLogFile(const string& x);
02560 
02561     /** Type for storing parameters passed to a module that is loaded. */
02562     typedef map<string,XMLElement> ParameterList;
02563 
02564     /** @brief Function to dynamically load a shared library in frePPLe.
02565       *
02566       * After loading the library, the function "initialize" of the module
02567       * is executed.
02568       *
02569       * The current implementation supports the following platforms:
02570       *  - Windows
02571       *  - Linux
02572       *  - Unix systems supporting the dlopen function in the standard way.
02573       *    Some unix systems have other or deviating APIs. A pretty messy story :-<
02574       */
02575     static DECLARE_EXPORT void loadModule(string lib, ParameterList& parameters); //@todo replace argument with a AttributeList instead
02576 
02577     /** Print all modules that have been loaded. */
02578     static DECLARE_EXPORT void printModules();
02579 };
02580 
02581 
02582 /** @brief This class handles two-way translation between the data types
02583   * in C++ and Python.
02584   *
02585   * This class is basically a wrapper around a PyObject pointer.
02586   *
02587   * When creating a PythonObject from a C++ object, make sure to increment
02588   * the reference count of the object.<br>
02589   * When constructing a PythonObject from an existing Python object, the
02590   * code that provided us the PyObject pointer should have incremented the
02591   * reference count already.
02592   *
02593   * @todo endelement function should be shared with setattro function.
02594   * Unifies the python and xml worlds: shared code base to update objects!
02595   * (Code for extracting info is still python specific, and writeElement
02596   * is also xml-specific)
02597   * xml->prevObject = python->cast value to a different type
02598   *
02599   * @todo object creator should be common with the XML reader, which uses
02600   * the registered factory method.
02601   * Also supports add/add_change/remove.
02602   * Tricky: flow/load which use an additional validate() method
02603   */
02604 class PythonObject : public DataElement
02605 {
02606   private:
02607     PyObject* obj;
02608 
02609   public:
02610     /** Default constructor. The default value is equal to Py_None. */
02611     explicit PythonObject() : obj(Py_None) {Py_INCREF(obj);}
02612 
02613     /** Constructor from an existing Python object.<br>
02614       * The reference count isn't increased.
02615       */
02616     PythonObject(const PyObject* o)
02617       : obj(o ? const_cast<PyObject*>(o) : Py_None) {Py_INCREF(obj);}
02618 
02619     /** This conversion operator casts the object back to a PyObject pointer. */
02620     operator PyObject*() const {return obj;}
02621 
02622     /** Check for null value. */
02623     operator bool() const {return obj != NULL && obj != Py_None;}
02624 
02625     /** Assignment operator. */
02626     PythonObject& operator = (const PythonObject& o)
02627     {
02628       if (obj) {Py_DECREF(obj);}
02629       obj = o.obj;
02630       if (obj) {Py_INCREF(obj);}
02631       return *this;
02632     }
02633 
02634     /** Check whether the Python object is of a certain type.<br>
02635       * Subclasses of the argument type will also give a true return value.
02636       */
02637     bool check(const MetaClass* c) const
02638     {
02639       return obj ?
02640           PyObject_TypeCheck(obj, c->pythonClass) :
02641           false;
02642     }
02643 
02644     /** Check whether the Python object is of a certain type.<br>
02645       * Subclasses of the argument type will also give a true return value.
02646       */
02647     bool check(const PythonType& c) const
02648     {
02649       return obj ?
02650           PyObject_TypeCheck(obj, c.type_object()) :
02651           false;
02652     }
02653 
02654     /** Convert a Python string into a C++ string. */
02655     inline string getString() const
02656     {
02657       if (obj == Py_None)
02658         return string();
02659       else if (PyUnicode_Check(obj))
02660       {
02661         // It's a Python unicode string
02662         PyObject* x = PyUnicode_AsEncodedString(obj,
02663             PythonInterpreter::getPythonEncoding(), "ignore");
02664         string result = PyString_AsString(x);
02665         Py_DECREF(x);
02666         return result;
02667       }
02668       else if (PyString_Check(obj))
02669         // It's a Python string
02670         return PyString_AsString(obj);
02671       else
02672       {
02673         // It's not a Python string object, call the str() function on the object
02674         PyObject* x = PyObject_Str(obj);
02675         string result = PyString_AsString(x);
02676         Py_DECREF(x);
02677         return result;
02678       }
02679     }
02680 
02681     /** Extract an unsigned long from the Python object. */
02682     unsigned long getUnsignedLong() const
02683     {
02684       if (obj == Py_None) return 0;
02685       if (PyString_Check(obj))
02686       {
02687         PyObject* t = PyFloat_FromString(obj, NULL);
02688         if (!t) throw DataException("Invalid number");
02689         double x = PyFloat_AS_DOUBLE(t);
02690         Py_DECREF(t);
02691         if (x < 0 || x > ULONG_MAX)
02692           throw DataException("Invalid number");
02693         return static_cast<unsigned long>(x);
02694       }
02695       return PyLong_AsUnsignedLong(obj);
02696     }
02697 
02698     /** Convert a Python datetime.date or datetime.datetime object into a
02699       * frePPLe date. */
02700     DECLARE_EXPORT Date getDate() const;
02701 
02702     /** Convert a Python number or string into a C++ double. */
02703     inline double getDouble() const
02704     {
02705       if (obj == Py_None) return 0;
02706       if (PyString_Check(obj))
02707       {
02708         PyObject* t = PyFloat_FromString(obj, NULL);
02709         if (!t) throw DataException("Invalid number");
02710         double x = PyFloat_AS_DOUBLE(t);
02711         Py_DECREF(t);
02712         return x;
02713       }
02714       return PyFloat_AsDouble(obj);
02715     }
02716 
02717     /** Convert a Python number or string into a C++ integer. */
02718     inline int getInt() const
02719     {
02720       if (PyString_Check(obj))
02721       {
02722         PyObject* t = PyFloat_FromString(obj, NULL);
02723         if (!t) throw DataException("Invalid number");
02724         double x = PyFloat_AS_DOUBLE(t);
02725         Py_DECREF(t);
02726         if (x < INT_MIN || x > INT_MAX)
02727           throw DataException("Invalid number");
02728         return static_cast<int>(x);
02729       }
02730       int result = PyInt_AsLong(obj);
02731       if (result == -1 && PyErr_Occurred())
02732         throw DataException("Invalid number");
02733       return result;
02734     }
02735 
02736     /** Convert a Python number into a C++ long. */
02737     inline long getLong() const
02738     {
02739       if (PyString_Check(obj))
02740       {
02741         PyObject* t = PyFloat_FromString(obj, NULL);
02742         if (!t) throw DataException("Invalid number");
02743         double x = PyFloat_AS_DOUBLE(t);
02744         Py_DECREF(t);
02745         if (x < LONG_MIN || x > LONG_MIN)
02746           throw DataException("Invalid number");
02747         return static_cast<long>(x);
02748       }
02749       int result = PyInt_AsLong(obj);
02750       if (result == -1 && PyErr_Occurred())
02751         throw DataException("Invalid number");
02752       return result;
02753     }
02754 
02755     /** Convert a Python number into a C++ bool. */
02756     inline bool getBool() const
02757     {
02758       return PyObject_IsTrue(obj) ? true : false;
02759     }
02760 
02761     /** Convert a Python number as a number of seconds into a frePPLe
02762       * TimePeriod.<br>
02763       * A TimePeriod is represented as a number of seconds in Python.
02764       */
02765     TimePeriod getTimeperiod() const
02766     {
02767       if (PyString_Check(obj))
02768       {
02769         if (PyUnicode_Check(obj))
02770         {
02771           // Replace the unicode object with a string encoded in the correct locale
02772           const_cast<PyObject*&>(obj) =
02773             PyUnicode_AsEncodedString(obj, PythonInterpreter::getPythonEncoding(), "ignore");
02774         }
02775         return TimePeriod(PyString_AsString(PyObject_Str(obj)));
02776       }
02777       int result = PyInt_AsLong(obj);
02778       if (result == -1 && PyErr_Occurred())
02779         throw DataException("Invalid number");
02780       return result;
02781     }
02782 
02783     /** Constructor from a pointer to an Object.<br>
02784       * The metadata of the Object instances allow us to create a Python
02785       * object that works as a proxy for the C++ object.
02786       */
02787     DECLARE_EXPORT PythonObject(Object* p);
02788 
02789     /** Convert a C++ string into a (raw) Python string. */
02790     inline PythonObject(const string& val)
02791     {
02792       if (val.empty())
02793       {
02794         obj = Py_None;
02795         Py_INCREF(obj);
02796       }
02797       else
02798         obj = PyString_FromString(val.c_str());
02799     }
02800 
02801     /** Convert a C++ double into a Python number. */
02802     inline PythonObject(const double val)
02803     {
02804       obj = PyFloat_FromDouble(val);
02805     }
02806 
02807     /** Convert a C++ integer into a Python integer. */
02808     inline PythonObject(const int val)
02809     {
02810       obj = PyInt_FromLong(val);
02811     }
02812 
02813     /** Convert a C++ long into a Python long. */
02814     inline PythonObject(const long val)
02815     {
02816       obj = PyLong_FromLong(val);
02817     }
02818 
02819     /** Convert a C++ unsigned long into a Python long. */
02820     inline PythonObject(const unsigned long val)
02821     {
02822       obj = PyLong_FromUnsignedLong(val);
02823     }
02824 
02825     /** Convert a C++ boolean into a Python boolean. */
02826     inline PythonObject(const bool val)
02827     {
02828       obj = val ? Py_True : Py_False;
02829       Py_INCREF(obj);
02830     }
02831 
02832     /** Convert a frePPLe TimePeriod into a Python number representing
02833       * the number of seconds. */
02834     inline PythonObject(const TimePeriod val)
02835     {
02836       // A TimePeriod is represented as a number of seconds in Python
02837       obj = PyLong_FromLong(val);
02838     }
02839 
02840     /** Convert a frePPLe date into a Python datetime.datetime object. */
02841     DECLARE_EXPORT PythonObject(const Date& val);
02842 };
02843 
02844 
02845 /** @brief This call is a wrapper around a Python function that can be
02846   * called from the C++ code.
02847   */
02848 class PythonFunction : public PythonObject
02849 {
02850   public:
02851     /** Default constructor. */
02852     PythonFunction() : func(NULL) {}
02853 
02854     /** Constructor. */
02855     DECLARE_EXPORT PythonFunction(const string&);
02856 
02857     /** Constructor. */
02858     DECLARE_EXPORT PythonFunction(PyObject*);
02859 
02860     /** Copy constructor. */
02861     PythonFunction(const PythonFunction& o) : func(o.func)
02862     {
02863       if (func) {Py_INCREF(func);}
02864     }
02865 
02866     /** Assignment operator. */
02867     PythonFunction& operator= (const PythonFunction& o)
02868     {
02869       if (func) {Py_DECREF(func);}
02870       func = o.func;
02871       if (func) {Py_INCREF(func);}
02872       return *this;
02873     }
02874 
02875     /** Destructor. */
02876     ~PythonFunction() {if (func) {Py_DECREF(func);}}
02877 
02878     /** Conversion operator to a Python pointer. */
02879     operator const PyObject*() const {return func;}
02880 
02881     /** Conversion operator to a string. */
02882     operator string() const {return func ? PyEval_GetFuncName(func) : "NULL";}
02883 
02884     /** Conversion operator to bool. */
02885     operator bool() const {return func != NULL;}
02886 
02887     /** Call the Python function without arguments. */
02888     DECLARE_EXPORT PythonObject call() const;
02889 
02890     /** Call the Python function with one argument. */
02891     DECLARE_EXPORT PythonObject call(const PyObject*) const;
02892 
02893     /** Call the Python function with two arguments. */
02894     DECLARE_EXPORT PythonObject call(const PyObject*, const PyObject*) const;
02895 
02896   private:
02897     /** A pointer to the Python object. */
02898     PyObject* func;
02899 };
02900 
02901 
02902 /** @brief This class represents a dictionary of keyword + value pairs.
02903   *
02904   * This abstract class can be instantiated as XML attributes, or as a
02905   * Python keyword dictionary.
02906   *  - XML:<br>
02907   *    &lt;buffer name="a" onhand="10" category="A" /&gt;
02908   *  - Python:<br>
02909   *    buffer(name="a", onhand="10", category="A")
02910   */
02911 class AttributeList
02912 {
02913   public:
02914     virtual const DataElement* get(const Keyword&) const = 0;
02915     // @todo Iterator???
02916 
02917     /** Destructor. */
02918     virtual ~AttributeList() {}
02919 };
02920 
02921 
02922 /** @brief This class represents a list of XML attributes. */
02923 class XMLAttributeList : public AttributeList
02924 {
02925   private:
02926     const xercesc::Attributes* atts;
02927     XMLElement result;
02928   public:
02929     XMLAttributeList(const xercesc::Attributes* a) : atts(a) {}
02930 
02931     const XMLElement* get(const Keyword& key) const
02932     {
02933       char* s = xercesc::XMLString::transcode(atts->getValue(key.getXMLCharacters()));
02934       const_cast<XMLAttributeList*>(this)->result.setData(s ? s : "");
02935       xercesc::XMLString::release(&s);
02936       return &result;
02937     }
02938 };
02939 
02940 
02941 /** @brief This class is a wrapper around a Python dictionary. */
02942 class PythonAttributeList : public AttributeList
02943 {
02944   private:
02945     PyObject* kwds;
02946     PythonObject result;
02947 
02948   public:
02949     PythonAttributeList(PyObject* a) : kwds(a) {}
02950 
02951     virtual const DataElement* get(const Keyword& k) const
02952     {
02953       if (!kwds)
02954       {
02955         const_cast<PythonAttributeList*>(this)->result = PythonObject();
02956         return &result;
02957       }
02958       PyObject* val = PyDict_GetItemString(kwds,k.getName().c_str());
02959       const_cast<PythonAttributeList*>(this)->result = PythonObject(val);
02960       return &result;
02961     }
02962 };
02963 
02964 
02965 /** @brief This is a base class for all Python extension types.
02966   *
02967   * When creating you own extensions, inherit from the PythonExtension
02968   * template class instead of this one.
02969   *
02970   * It inherits from the PyObject C struct, defined in the Python C API.<br>
02971   * These functions aren't called directly from Python. Python first calls a
02972   * handler C-function and the handler function will use a virtual call to
02973   * run the correct C++-method.
02974   *
02975   * Our extensions don't use the usual Python heap allocator. They are
02976   * created and initialized with the regular C++ new and delete. A special
02977   * deallocator is called from Python to delete objects when their reference
02978   * count reaches zero.
02979   */
02980 class PythonExtensionBase : public PyObject
02981 {
02982   public:
02983     /** Default constructor */
02984     PythonExtensionBase() {}
02985 
02986     /** Destructor. */
02987     virtual ~PythonExtensionBase()
02988     {
02989       if (PyObject::ob_refcnt > 1)
02990         logger << "Warning: Deleting " << PyObject::ob_type->tp_name
02991             << " object that is still referenced "
02992             << (PyObject::ob_refcnt-1) << " times" << endl;
02993     }
02994 
02995     /** A function to force an object to be destroyed by the Python garbage
02996       * collection.<br>
02997       * Be very careful to use this!
02998       */
02999     void resetReferenceCount() {PyObject::ob_refcnt = 0;}
03000 
03001     /** Initialize the object to a certain Python type. */
03002     inline void initType(const MetaClass *t)
03003     {
03004       PyObject_INIT(this,t->pythonClass);
03005     }
03006 
03007     /** Initialize the object to a certain Python type. */
03008     inline void initType(PyTypeObject *t)
03009     {
03010       PyObject_INIT(this,t);
03011     }
03012 
03013     /** Default getattro method. <br>
03014       * Subclasses are expected to implement an override if the type supports
03015       * gettattro.
03016       */
03017     virtual PyObject* getattro(const Attribute& attr)
03018     {
03019       PyErr_SetString(PythonLogicException, "Missing method 'getattro'");
03020       return NULL;
03021     }
03022 
03023     /** Default setattro method. <br>
03024       * Subclasses are expected to implement an override if the type supports
03025       * settattro.
03026       */
03027     virtual int setattro(const Attribute& attr, const PythonObject& field)
03028     {
03029       PyErr_SetString(PythonLogicException, "Missing method 'setattro'");
03030       return -1;
03031     }
03032 
03033     /** Default compare method. <br>
03034       * Subclasses are expected to implement an override if the type supports
03035       * compare.
03036       */
03037     virtual int compare(const PyObject* other) const
03038     {
03039       PyErr_SetString(PythonLogicException, "Missing method 'compare'");
03040       return -1;
03041     }
03042 
03043     /** Default iternext method. <br>
03044       * Subclasses are expected to implement an override if the type supports
03045       * iteration.
03046       */
03047     virtual PyObject* iternext()
03048     {
03049       PyErr_SetString(PythonLogicException, "Missing method 'iternext'");
03050       return NULL;
03051     }
03052 
03053     /** Default call method. <br>
03054       * Subclasses are expected to implement an override if the type supports
03055       * calls.
03056       */
03057     virtual PyObject* call(const PythonObject& args, const PythonObject& kwds)
03058     {
03059       PyErr_SetString(PythonLogicException, "Missing method 'call'");
03060       return NULL;
03061     }
03062 
03063     /** Default str method. <br>
03064       * Subclasses are expected to implement an override if the type supports
03065       * conversion to a string.
03066       */
03067     virtual PyObject* str() const
03068     {
03069       PyErr_SetString(PythonLogicException, "Missing method 'str'");
03070       return NULL;
03071     }
03072 
03073   protected:
03074     static vector<PythonType*> table;
03075 
03076     DECLARE_EXPORT static PythonType* registerPythonType(int, const type_info*);
03077 
03078 };
03079 
03080 
03081 /** @brief Template class to define Python extensions.
03082   *
03083   * The template argument should be your extension class, inheriting from
03084   * this template class:
03085   *   class MyClass : PythonExtension<MyClass>
03086   *
03087   * The structure of the C++ wrappers around the C Python API is heavily
03088   * inspired on the design of PyCXX.<br>
03089   * More information can be found on http://cxx.sourceforge.net
03090   */
03091 template<class T>
03092 class PythonExtension: public PythonExtensionBase, public NonCopyable
03093 {
03094   public:
03095     /** Constructor. */
03096     explicit PythonExtension()
03097     {
03098       PyObject_Init(this, getType().type_object());
03099     }
03100 
03101     /** Destructor. */
03102     virtual ~PythonExtension() {}
03103 
03104     /** This method keeps the type information object for your extension. */
03105     static PythonType& getType()
03106     {
03107       static PythonType* cachedTypePtr = NULL;
03108       if (cachedTypePtr) return *cachedTypePtr;
03109 
03110       // Register a new type
03111       cachedTypePtr = registerPythonType(sizeof(T), &typeid(T));
03112 
03113       // Using our own memory deallocator
03114       cachedTypePtr->supportdealloc( deallocator );
03115 
03116       return *cachedTypePtr;
03117     }
03118 
03119     /** Free the memory.<br>
03120       * See the note on the memory management in the class documentation
03121       * for PythonExtensionBase.
03122       */
03123     static void deallocator(PyObject* o) {delete static_cast<T*>(o);}
03124 };
03125 
03126 
03127 /** @brief Object is the abstract base class for the main entities.
03128   *
03129   * It handles to following capabilities:
03130   * - <b>Metadata:</b> All subclasses publish metadata about their structure.
03131   * - <b>Python object:</b> All objects live a double life as a Python object.
03132   * - <b>Callbacks:</b> When objects are created or deleted,
03133   *   interested classes or objects can get a callback notification.
03134   * - <b>Serialization:</b> Objects need to be persisted and later restored.
03135   *   Subclasses that don't need to be persisted can skip the implementation
03136   *   of the writeElement method.<br>
03137   *   Instances can be marked as hidden, which means that they are not
03138   *   serialized at all.
03139   */
03140 class Object : public PythonExtensionBase
03141 {
03142   public:
03143     /** Constructor. */
03144     explicit Object() {}
03145 
03146     /** Destructor. */
03147     virtual ~Object() {}
03148 
03149     /** Called while writing the model into an XML-file.
03150       * The user class should write itself out, using the IOutStream
03151       * members for its "simple" members and calling writeElement
03152       * recursively for any contained objects.
03153       * Not all classes are expected to implement this method. In instances
03154       * of such a class can be created but can't be persisted.
03155       * E.g. Command
03156       */
03157     virtual void writeElement(XMLOutput *, const Keyword &, mode=DEFAULT) const
03158     {throw LogicException("Class can't be persisted");}
03159 
03160     /** Called while restoring the model from an XML-file.<br>
03161       * This is called for each element within the "this" element,
03162       * for which the "this" element is immediate parent.<br>
03163       * It is called when the open element tag is encountered.
03164       */
03165     virtual void beginElement(XMLInput&, const Attribute&) {}
03166 
03167     /** Called while restoring the model from an XML-file.<br>
03168       * This is called when the corresponding close element tag
03169       * is encountered, and the Data() member of pElement is valid.
03170       */
03171     virtual void endElement(XMLInput&, const Attribute&, const DataElement&) = 0;
03172 
03173     /** Mark the object as hidden or not. Hidden objects are not exported
03174       * and are used only as dummy constructs. */
03175     virtual void setHidden(bool b) {}
03176 
03177     /** Returns whether an entity is real or dummy. */
03178     virtual bool getHidden() const {return false;}
03179 
03180     /** This returns the type information on the object, a bit similar to
03181       * the standard type_info information. */
03182     virtual const MetaClass& getType() const = 0;
03183 
03184     /** Return the memory size of the object in bytes. */
03185     virtual size_t getSize() const = 0;
03186 
03187     /** This template function can generate a factory method for objects that
03188       * can be constructed with their default constructor.  */
03189     template <class T>
03190     static Object* createDefault()
03191     {
03192       return new T();
03193     }
03194 
03195     /** This template function can generate a factory method for objects that
03196       * need a string argument in their constructor. */
03197     template <class T>
03198     static Object* createString(const string& n)
03199     {
03200       return new T(n);
03201     }
03202 
03203     /** Template function that generates a factory method callable
03204       * from Python. */
03205     template<class T>
03206     static PyObject* create
03207     (PyTypeObject* pytype, PyObject* args, PyObject* kwds)
03208     {
03209       try
03210       {
03211         // Find or create the C++ object
03212         PythonAttributeList atts(kwds);
03213         Object* x = T::reader(T::metadata, atts);
03214 
03215         // Object was deleted
03216         if (!x)
03217         {
03218           Py_INCREF(Py_None);
03219           return Py_None;
03220         }
03221 
03222         // Iterate over extra keywords, and set attributes.   @todo move this responsability to the readers...
03223         PyObject *key, *value;
03224         Py_ssize_t pos = 0;
03225         while (PyDict_Next(kwds, &pos, &key, &value))
03226         {
03227           PythonObject field(value);
03228           Attribute attr(PyString_AsString(key));
03229           if (!attr.isA(Tags::tag_name) && !attr.isA(Tags::tag_type) && !attr.isA(Tags::tag_action))
03230           {
03231             int result = x->setattro(attr, field);
03232             if (result && !PyErr_Occurred())
03233               PyErr_Format(PyExc_AttributeError,
03234                   "attribute '%s' on '%s' can't be updated",
03235                   PyString_AsString(key), x->ob_type->tp_name);
03236           }
03237         };
03238         Py_INCREF(x);
03239         return x;
03240       }
03241       catch (...)
03242       {
03243         PythonType::evalException();
03244         return NULL;
03245       }
03246     }
03247 
03248     /** Return an XML representation of the object.<br>
03249       * If a file object is passed as argument, the representation is directly
03250       * written to it.<br>
03251       * If no argument is given the representation is returned as a string.
03252       */
03253     static DECLARE_EXPORT PyObject* toXML(PyObject*, PyObject*);
03254 };
03255 
03256 
03257 //
03258 // UTILITY CLASSES FOR MULTITHREADING
03259 //
03260 
03261 
03262 /** @brief This class is a wrapper around platform specific mutex functions. */
03263 class Mutex: public NonCopyable
03264 {
03265   public:
03266 #ifndef MT
03267     // No threading support, empty class
03268     Mutex() {}
03269     ~Mutex()  {}
03270     void lock() {}
03271     void unlock() {}
03272 #elif defined(HAVE_PTHREAD_H)
03273     // Pthreads
03274     Mutex()         {pthread_mutex_init(&mtx, 0);}
03275     ~Mutex()        {pthread_mutex_destroy(&mtx);}
03276     void lock()     {pthread_mutex_lock(&mtx);}
03277     void unlock()   {pthread_mutex_unlock(&mtx);}
03278   private:
03279     pthread_mutex_t mtx;
03280 #else
03281     // Windows critical section
03282     Mutex() {InitializeCriticalSection(&critsec);}
03283     ~Mutex()  {DeleteCriticalSection(&critsec);}
03284     void lock() {EnterCriticalSection(&critsec);}
03285     void unlock() {LeaveCriticalSection(&critsec);}
03286   private:
03287     CRITICAL_SECTION critsec;
03288 #endif
03289 };
03290 
03291 
03292 /** @brief This is a convenience class that makes it easy (and
03293   * exception-safe) to lock a mutex in a scope.
03294   */
03295 class ScopeMutexLock: public NonCopyable
03296 {
03297   protected:
03298     Mutex& mtx;
03299   public:
03300     ScopeMutexLock(Mutex& imtx): mtx(imtx) {mtx.lock ();}
03301     ~ScopeMutexLock() {mtx.unlock();}
03302 };
03303 
03304 
03305 /** @brief This class supports parallel execution of a number of functions.
03306   *
03307   * Currently Pthreads and Windows threads are supported as the implementation
03308   * of the multithreading.
03309   */
03310 class ThreadGroup : public NonCopyable
03311 {
03312   public:
03313     /** Prototype of the thread function. */
03314     typedef void (*callable)(void*);
03315 
03316     /** Constructor which defaults to have as many worker threads as there are
03317       * cores on the machine.
03318       */
03319     ThreadGroup() : countCallables(0)
03320     {
03321       maxParallel = Environment::getProcessorCores();
03322     };
03323 
03324     /** Constructor with a predefined number of worker threads. */
03325     ThreadGroup(int i) : countCallables(0)
03326     {
03327       setMaxParallel(i);
03328     };
03329 
03330     /** Add a new function to be called and its argument. */
03331     void add(callable func, void* args)
03332     {
03333       callables.push( make_pair(func,args) );
03334       ++countCallables;
03335     }
03336 
03337     /** Execute all functions and wait for them to finish. */
03338     DECLARE_EXPORT void execute();
03339 
03340     /** Returns the number of parallel workers that is activated.<br>
03341       * By default we activate as many worker threads as there are cores on
03342       * the machine.
03343       */
03344     int getMaxParallel() const {return maxParallel;}
03345 
03346     /** Updates the number of parallel workers that is activated. */
03347     void setMaxParallel(int b)
03348     {
03349       if (b<1)
03350         throw DataException("Invalid number of parallel execution threads");
03351 #ifndef MT
03352       maxParallel = (b>1 ? 1 : b);
03353 #else
03354       maxParallel = b;
03355 #endif
03356     }
03357 
03358   private:
03359     typedef pair<callable,void*> callableWithArgument;
03360 
03361     /** Mutex to protect the curCommand data field during multi-threaded
03362       * execution.
03363       * @see selectCommand
03364       */
03365     Mutex lock;
03366 
03367     /** Specifies the maximum number of commands in the list that can be
03368       * executed in parallel.
03369       * The default value is 1, i.e. sequential execution.<br>
03370       * The value of this field is NOT inherited from parent command lists.<br>
03371       * Note that the maximum applies to this command list only, and it isn't
03372       * a system-wide limit on the creation of threads.
03373       */
03374     int maxParallel;
03375 
03376     /** Stack with all registered functions and their invocation arguments. */
03377     stack<callableWithArgument> callables;
03378 
03379     /** Count registered callables. */
03380     unsigned int countCallables;
03381 
03382     /** This functions runs a single command execution thread. It is used as
03383       * a holder for the main routines of a trheaded routine.
03384       */
03385 #if defined(HAVE_PTHREAD_H) || !defined(MT)
03386     static void* wrapper(void *arg);
03387 #else
03388     static unsigned __stdcall wrapper(void *);
03389 #endif
03390 
03391     /** This method selects the next function to be executed.
03392       * @see wrapper
03393       */
03394     DECLARE_EXPORT callableWithArgument selectNextCallable();
03395 };
03396 
03397 
03398 //
03399 // RED-BLACK TREE CLASS
03400 //
03401 
03402 /** @brief This class implements a binary tree data structure. It is used as a
03403   * container for entities keyed by their name.
03404   *
03405   * Technically, the data structure can be described as a red-black tree
03406   * with intrusive tree nodes.
03407   * @see HasName
03408   */
03409 class Tree : public NonCopyable
03410 {
03411   public:
03412     /** The algorithm assigns a color to each node in the tree. The color is
03413       * used to keep the tree balanced.<br>
03414       * A node with color 'none' is a node that hasn't been inserted yet in
03415       * the tree.
03416       */
03417     enum NodeColor {red, black, none };
03418 
03419     /** @brief This class represents a node in the tree.
03420       *
03421       * Elements which we want to represent in the tree will need to inherit
03422       * from this class, since this tree container is intrusive.
03423       */
03424     class TreeNode
03425     {
03426         friend class Tree;
03427 
03428       public:
03429         /** Destructor. */
03430         virtual ~TreeNode() {}
03431 
03432         /** Returns the name of this node. This name is used to sort the
03433           * nodes. */
03434         const string& getName() const {return nm;}
03435 
03436         /** Comparison operator. */
03437         bool operator < (const TreeNode& o) {return nm < o.nm;}
03438 
03439         /** Constructor. */
03440         TreeNode(const string& n) : nm(n), color(none)
03441         {
03442           if (n.empty())
03443             throw DataException("Can't create entity without name");
03444         }
03445 
03446         /** Return a pointer to the node following this one. */
03447         TreeNode* increment() const
03448         {
03449           TreeNode *node = const_cast<TreeNode*>(this);
03450           if (node->right != NULL)
03451           {
03452             node = node->right;
03453             while (node->left != NULL) node = node->left;
03454           }
03455           else
03456           {
03457             TreeNode* y = node->parent;
03458             while (node == y->right)
03459             {
03460               node = y;
03461               y = y->parent;
03462             }
03463             if (node->right != y) node = y;
03464           }
03465           return node;
03466         }
03467 
03468         /** Return a pointer to the node preceding this one. */
03469         TreeNode* decrement() const
03470         {
03471           TreeNode *node = const_cast<TreeNode*>(this);
03472           if (node->color == red && node->parent->parent == node)
03473             node = node->right;
03474           else if (node->left != NULL)
03475           {
03476             TreeNode* y = node->left;
03477             while (y->right != NULL) y = y->right;
03478             node = y;
03479           }
03480           else
03481           {
03482             TreeNode* y = node->parent;
03483             while (node == y->left)
03484             {
03485               node = y;
03486               y = y->parent;
03487             }
03488             node = y;
03489           }
03490           return node;
03491         }
03492 
03493       private:
03494         /** Constructor. */
03495         TreeNode() {}
03496 
03497         /** Name. */
03498         string nm;
03499 
03500         /** Color of the node. This is used to keep the tree balanced. */
03501         NodeColor color;
03502 
03503         /** Pointer to the parent node. */
03504         TreeNode* parent;
03505 
03506         /** Pointer to the left child node. */
03507         TreeNode* left;
03508 
03509         /** Pointer to the right child node. */
03510         TreeNode* right;
03511     };
03512 
03513     /** Default constructor. */
03514     Tree(bool b = false) : count(0), clearOnDestruct(b)
03515     {
03516       // Color is used to distinguish header from root, in iterator.operator++
03517       header.color = red;
03518       header.parent = NULL;
03519       header.left = &header;
03520       header.right = &header;
03521     }
03522 
03523     /** Destructor.<br>
03524       * By default, the objects in the tree are not deleted when the tree
03525       * is deleted. This is done for performance reasons: the program can shut
03526       * down faster.
03527       */
03528     ~Tree() {if(clearOnDestruct) clear();}
03529 
03530     /** Returns an iterator to the start of the list.<br>
03531       * The user will need to take care of properly acquiring a read lock on
03532       * on the tree object.
03533       */
03534     TreeNode* begin() const {return const_cast<TreeNode*>(header.left);}
03535 
03536     /** Returns an iterator pointing beyond the last element in the list.<br>
03537       * The user will need to take care of properly acquiring a read lock on
03538       * on the tree object.
03539       */
03540     TreeNode* end() const {return const_cast<TreeNode*>(&header);}
03541 
03542     /** Returns true if the list is empty.<br>
03543       * Its complexity is O(1). */
03544     bool empty() const
03545     {
03546       ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
03547       return header.parent == NULL;
03548     }
03549 
03550     /** Renames an existing node, and adjusts its position in the tree. */
03551     void rename(TreeNode* obj, string newname)
03552     {
03553       bool found;
03554       findLowerBound(newname, &found);
03555       if (found)
03556         throw DataException("Can't rename '" + obj->nm + "' to '"
03557             + newname + "': name already in use");
03558       erase(obj);
03559       // @todo: there is a small risk for multithreading trouble when the tree is unlocked between the delete and re-insert
03560       obj->nm = newname;
03561       insert(obj);
03562     };
03563 
03564     /** This method returns the number of nodes inserted in this tree.<br>
03565       * Its complexity is O(1), so it can be called on large trees without any
03566       * performance impact.
03567       */
03568     size_t size() const
03569     {
03570       ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
03571       return count;
03572     }
03573 
03574     /** Verifies the integrity of the tree and returns true if everything
03575       * is correct.<br>
03576       * The tree should be locked before calling this function.
03577       */
03578     DECLARE_EXPORT void verify() const;
03579 
03580     /** Remove all elements from the tree. */
03581     DECLARE_EXPORT void clear();
03582 
03583     /** Remove a node from the tree. */
03584     DECLARE_EXPORT void erase(TreeNode* x);
03585 
03586     /** Search for an element in the tree.<br>
03587       * Profiling shows this function has a significant impact on the CPU
03588       * time (mainly because of the string comparisons), and has been
03589       * optimized as much as possible.
03590       */
03591     TreeNode* find(const string& k) const
03592     {
03593       ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
03594       int comp;
03595       for (TreeNode* x = header.parent; x; x = comp<0 ? x->left : x->right)
03596       {
03597         comp = k.compare(x->nm);
03598         if (!comp) return x;
03599       }
03600       TreeNode* result = end();
03601       return result;
03602     }
03603 
03604     /** Find the element with this given key or the element
03605       * immediately preceding it.<br>
03606       * The second argument is a boolean that is set to true when the
03607       * element is found in the list.
03608       */
03609     TreeNode* findLowerBound(const string& k, bool* f) const
03610     {
03611       ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
03612       TreeNode* lower = end();
03613       for (TreeNode* x = header.parent; x;)
03614       {
03615         int comp = k.compare(x->nm);
03616         if (!comp)
03617         {
03618           // Found
03619           if (f) *f = true;
03620           return x;
03621         }
03622         if (comp<0) x = x->left;
03623         else lower = x, x = x->right;
03624       }
03625       if (f) *f = false;
03626       return lower;
03627     }
03628 
03629     /** Insert a new node in the tree. */
03630     TreeNode* insert(TreeNode* v) {return insert(v, NULL);}
03631 
03632     /** Insert a new node in the tree. The second argument is a hint on
03633       * the proper location in the tree.<br>
03634       * Profiling shows this function has a significant impact on the cpu
03635       * time (mainly because of the string comparisons), and has been
03636       * optimized as much as possible.
03637       */
03638     DECLARE_EXPORT TreeNode* insert(TreeNode* v, TreeNode* hint);
03639 
03640   private:
03641     /** Restructure the tree such that the depth of the branches remains
03642       * properly balanced. This method is called during insertion. */
03643     inline void rebalance(TreeNode* x);
03644 
03645     /** Rebalancing operation used during the rebalancing. */
03646     inline void rotateLeft(TreeNode* x);
03647 
03648     /** Rebalancing operation used during the rebalancing. */
03649     inline void rotateRight(TreeNode* x);
03650 
03651     /** Method used internally by the verify() method. */
03652     unsigned int countBlackNodes(TreeNode* node) const
03653     {
03654       unsigned int sum = 0;
03655       for ( ; node != header.parent; node=node->parent)
03656         if (node->color == black) ++sum;
03657       return sum;
03658     }
03659 
03660     TreeNode* minimum(TreeNode* x) const
03661     {
03662       while (x->left) x = x->left;
03663       return x;
03664     }
03665 
03666     TreeNode* maximum(TreeNode* x) const
03667     {
03668       while (x->right) x = x->right;
03669       return x;
03670     }
03671 
03672     /** This node stores the following data:
03673       *  - parent: root of the tree.
03674       *  - left: leftmost element in the tree.
03675       *  - right: rightmost element in the tree.
03676       *  - this node itself is used as an element beyond the end of the list.
03677       */
03678     TreeNode header;
03679 
03680     /** Stores the number of elements in the tree. */
03681     size_t count;
03682 
03683     /** Controls concurrent access to the tree from different trheads.<br>
03684       * Every function reading or updating the tree should keep this mutex
03685       * locked during the operation.
03686       */
03687     Mutex treeaccess;
03688 
03689     /** Controls whether the destructor needs to be clear all objects in the
03690       * tree in its destructor.<br>
03691       * The default is to skip this cleanup! This is fine when you are dealing
03692       * with a static tree that lives throughout your program.<br>
03693       * When you create a tree with a shorter lifespan, you'll need to pass
03694       * the constructor 'true' as argument in order to avoid memory leaks.
03695       */
03696     bool clearOnDestruct;
03697 };
03698 
03699 
03700 //
03701 // UTILITY CLASS "COMMAND": for executing & undoing actions
03702 //
03703 
03704 /** @brief Abstract base class for all commands.
03705   *
03706   * Command objects are designed for algorithms that need to keep track of
03707   * their decision, efficiently undo them and redo them.
03708   *
03709   * The key methods are:
03710   *   - The constructor or other methods on the concrete subclasses
03711   *     implement the state change.
03712   *   - commit():
03713   *     Makes the change permanently.
03714   *     Undoing the change is no longer possible after calling this method.
03715   *   - rollback():
03716   *     Reverts the change permanently.
03717   *     Redoing the change is no longer possible after calling this method.
03718   *   - undo():
03719   *     Temporarily reverts the change.
03720   *     Redoing the change is still possible.
03721   *   - redo():
03722   *     Reactivates the change that was previously undone.
03723   */
03724 class Command
03725 {
03726     friend class CommandList;
03727     friend class CommandManager;
03728     friend class frepple::CommandMoveOperationPlan;
03729   public:
03730     /** Default constructor. The creation of a command should NOT execute the
03731       * command yet. The execute() method needs to be called explicitly to
03732       * do so.
03733       */
03734     Command() : owner(NULL), next(NULL), prev(NULL) {};
03735 
03736     /** This method makes the change permanent.<br>
03737       * A couple of notes on how this method should be implemented by the
03738       * subclasses:
03739       *   - Calling the method multiple times is harmless. Only the first
03740       *     call is expected to do something.
03741       */
03742     virtual void commit() {};
03743 
03744     /** This method permanently undoes the change.<br>
03745       * A couple of notes on how this method should be implemented by the
03746       * subclasses:
03747       *   - Calling the rollback() method multiple times is harmless. Only
03748       *     the first call is expected to do something.
03749       */
03750     virtual void rollback() {};
03751 
03752     /** This method temporarily undoes the change. The concrete subclasses
03753       * most maintain information that enables redoing the changes
03754       * efficiently.<br>
03755       * A couple of notes on how this method should be implemented by the
03756       * subclasses:
03757       *   - Calling the method multiple times is harmless and results in the
03758       *     same state change as calling it only once.
03759       */
03760     virtual void undo() {};
03761 
03762     /** This method reproduces a previously undone change.<br>
03763       * A couple of notes on how this method should be implemented by the
03764       * subclasses:
03765       *   - Calling the method multiple times is harmless and results in the
03766       *     same state change as calling it only once.
03767       */
03768     virtual void redo() {};
03769 
03770     /** Destructor. */
03771     virtual ~Command() {};
03772 
03773   private:
03774     /** Points to the commandlist which owns this command. The default value
03775       * is NULL, meaning there is no owner. */
03776     Command *owner;
03777 
03778     /** Points to the next command in the owner command list.<br>
03779       * The commands are chained in a double linked list data structure. */
03780     Command *next;
03781 
03782     /** Points to the previous command in the owner command list.<br>
03783       * The commands are chained in a double linked list data structure. */
03784     Command *prev;
03785 };
03786 
03787 
03788 /** @brief A container command to group a series of commands together.
03789   *
03790   * This class implements the "composite" design pattern in order to get an
03791   * efficient and intuitive hierarchical grouping of commands.
03792   * @todo handle exceptions during commit, rollback, undo, redo
03793   */
03794 class CommandList : public Command
03795 {
03796   private:
03797     /** Points to the first command in the list.<br>
03798       * Following commands can be found by following the next pointers
03799       * on the commands.<br>
03800       * The commands are this chained in a double linked list data structure.
03801       */
03802     Command* firstCommand;
03803 
03804     /** Points to the last command in the list. */
03805     Command* lastCommand;
03806   public:
03807     class iterator
03808     {
03809       public:
03810         /** Constructor. */
03811         iterator(Command* x) : cur(x) {}
03812 
03813         /** Copy constructor. */
03814         iterator(const iterator& it) {cur = it.cur;}
03815 
03816         /** Return the content of the current node. */
03817         Command& operator*() const {return *cur;}
03818 
03819         /** Return the content of the current node. */
03820         Command* operator->() const {return cur;}
03821 
03822         /** Pre-increment operator which moves the pointer to the next
03823           * element. */
03824         iterator& operator++()
03825         {
03826           cur = cur->next;
03827           return *this;
03828         }
03829 
03830         /** Post-increment operator which moves the pointer to the next
03831           * element. */
03832         iterator operator++(int)
03833         {
03834           iterator tmp = *this;
03835           cur = cur->next;
03836           return tmp;
03837         }
03838 
03839         /** Comparison operator. */
03840         bool operator==(const iterator& y) const {return cur==y.cur;}
03841 
03842         /** Inequality operator. */
03843         bool operator!=(const iterator& y) const {return cur!=y.cur;}
03844 
03845       private:
03846         Command* cur;
03847     };
03848 
03849     /** Returns an iterator over all commands in the list. */
03850     iterator begin() const {return iterator(firstCommand);}
03851 
03852     /** Returns an iterator beyond the last command. */
03853     iterator end() const {return iterator(NULL);}
03854 
03855     /** Append an additional command to the end of the list. */
03856     DECLARE_EXPORT void add(Command* c);
03857 
03858     /** Undoes all actions on the list.<br>
03859       * At the end it also clears the list of actions.
03860       */
03861     virtual DECLARE_EXPORT void rollback();
03862 
03863     /** Commits all actions on its list.<br>
03864       * At the end it also clears the list of actions.
03865       */
03866     virtual DECLARE_EXPORT void commit();
03867 
03868     /** Undoes all actions on its list.<br>
03869       * The list of actions is left intact, so the changes can still be redone.
03870       */
03871     virtual DECLARE_EXPORT void undo();
03872 
03873     /** Redoes all actions on its list.<br>
03874       * The list of actions is left intact, so the changes can still be undone.
03875       */
03876     DECLARE_EXPORT void redo();
03877 
03878     /** Returns true if no commands have been added yet to the list. */
03879     bool empty() const {return firstCommand==NULL;}
03880 
03881     /** Default constructor. */
03882     explicit CommandList() : firstCommand(NULL), lastCommand(NULL) {}
03883 
03884     /** Destructor.<br>
03885       * A commandlist should only be deleted when all of its commands
03886       * have been committed or undone. If this is not the case a warning
03887       * will be printed.
03888       */
03889     virtual DECLARE_EXPORT ~CommandList();
03890 };
03891 
03892 
03893 /** @brief This class allows management of tasks with supporting commiting them,
03894   * rolling them back, and setting bookmarks which can be undone and redone.
03895   */
03896 class CommandManager
03897 {
03898   public:
03899     /** A bookmark that keeps track of commands that can be undone and redone. */
03900     class Bookmark : public CommandList
03901     {
03902         friend class CommandManager;
03903       private:
03904         bool active;
03905         Bookmark* nextBookmark;
03906         Bookmark* prevBookmark;
03907         Bookmark* parent;
03908         Bookmark(Bookmark* p=NULL) : active(true),
03909           nextBookmark(NULL), prevBookmark(NULL), parent(p) {}
03910       public:
03911         /** Returns true if the bookmark commands are active. */
03912         bool isActive() const {return active;}
03913 
03914         /** Returns true if the bookmark is a child, grand-child or
03915           * grand-grand-child of the argument bookmark.
03916           */
03917         bool isChildOf(const Bookmark* b) const
03918         {
03919           for (const Bookmark* p = this; p; p = p->parent)
03920             if (p == b) return true;
03921           return false;
03922         }
03923     };
03924 
03925     /** An STL-like iterator to move over all bookmarks in forward order. */
03926     class iterator
03927     {
03928       public:
03929         /** Constructor. */
03930         iterator(Bookmark* x) : cur(x) {}
03931 
03932         /** Copy constructor. */
03933         iterator(const iterator& it) {cur = it.cur;}
03934 
03935         /** Return the content of the current node. */
03936         Bookmark& operator*() const {return *cur;}
03937 
03938         /** Return the content of the current node. */
03939         Bookmark* operator->() const {return cur;}
03940 
03941         /** Pre-increment operator which moves the pointer to the next
03942           * element. */
03943         iterator& operator++()
03944         {
03945           cur = cur->nextBookmark;
03946           return *this;
03947         }
03948 
03949         /** Post-increment operator which moves the pointer to the next
03950           * element. */
03951         iterator operator++(int)
03952         {
03953           iterator tmp = *this;
03954           cur = cur->nextBookmark;
03955           return tmp;
03956         }
03957 
03958         /** Comparison operator. */
03959         bool operator==(const iterator& y) const {return cur==y.cur;}
03960 
03961         /** Inequality operator. */
03962         bool operator!=(const iterator& y) const {return cur!=y.cur;}
03963 
03964       private:
03965         Bookmark* cur;
03966     };
03967 
03968     /** An STL-like iterator to move over all bookmarks in reverse order. */
03969     class reverse_iterator
03970     {
03971       public:
03972         /** Constructor. */
03973         reverse_iterator(Bookmark* x) : cur(x) {}
03974 
03975         /** Copy constructor. */
03976         reverse_iterator(const reverse_iterator& it) {cur = it.cur;}
03977 
03978         /** Return the content of the current node. */
03979         Bookmark& operator*() const {return *cur;}
03980 
03981         /** Return the content of the current node. */
03982         Bookmark* operator->() const {return cur;}
03983 
03984         /** Pre-increment operator which moves the pointer to the next
03985           * element. */
03986         reverse_iterator& operator++()
03987         {
03988           cur = cur->prevBookmark;
03989           return *this;
03990         }
03991 
03992         /** Post-increment operator which moves the pointer to the next
03993           * element. */
03994         reverse_iterator operator++(int)
03995         {
03996           reverse_iterator tmp = *this;
03997           cur = cur->prevBookmark;
03998           return tmp;
03999         }
04000 
04001         /** Comparison operator. */
04002         bool operator==(const reverse_iterator& y) const {return cur==y.cur;}
04003 
04004         /** Inequality operator. */
04005         bool operator!=(const reverse_iterator& y) const {return cur!=y.cur;}
04006 
04007       private:
04008         Bookmark* cur;
04009     };
04010 
04011   private:
04012     /** Head of a list of bookmarks.<br>
04013       * A command manager has always at least this default bookmark.
04014       */
04015     Bookmark firstBookmark;
04016 
04017     /** Tail of a list of bookmarks. */
04018     Bookmark* lastBookmark;
04019 
04020     /** Current bookmarks.<br>
04021       * If commands are added to the manager, this is the bookmark where
04022       * they'll be appended to.
04023       */
04024     Bookmark* currentBookmark;
04025 
04026   public:
04027     /** Constructor. */
04028     CommandManager()
04029     {
04030       lastBookmark = &firstBookmark;
04031       currentBookmark = &firstBookmark;
04032     }
04033 
04034     /** Destructor. */
04035     ~CommandManager()
04036     {
04037       for (Bookmark* i = lastBookmark; i && i != &firstBookmark; )
04038       {
04039         Bookmark* tmp = i;
04040         i = i->prevBookmark;
04041         delete tmp;
04042       }
04043     }
04044 
04045     /** Returns an iterator over all bookmarks in forward direction. */
04046     iterator begin() {return iterator(&firstBookmark);}
04047 
04048     /** Returns an iterator beyond the last bookmark in forward direction. */
04049     iterator end() {return iterator(NULL);}
04050 
04051     /** Returns an iterator over all bookmarks in reverse direction. */
04052     reverse_iterator rbegin() {return reverse_iterator(lastBookmark);}
04053 
04054     /** Returns an iterator beyond the last bookmark in reverse direction. */
04055     reverse_iterator rend() {return reverse_iterator(NULL);}
04056 
04057     /** Add a command to the active bookmark. */
04058     void add(Command* c) {currentBookmark->add(c);}
04059 
04060     /** Create a new bookmark. */
04061     DECLARE_EXPORT Bookmark* setBookmark();
04062 
04063     /** Undo all commands in a bookmark (and its children).<br>
04064       * It can later be redone.<br>
04065       * The active bookmark in the manager is set to the parent of
04066       * argument bookmark.
04067       */
04068     DECLARE_EXPORT void undoBookmark(Bookmark*);
04069 
04070     /** Redo all commands in a bookmark (and its children).<br>
04071       * It can later still be undone.<br>
04072       * The active bookmark in the manager is set to the argument bookmark.
04073       */
04074     DECLARE_EXPORT void redoBookmark(Bookmark*);
04075 
04076     /** Undo all commands in a bookmark (and its children).<br>
04077       * It can no longer be redone. The bookmark does however still exist.
04078       */
04079     DECLARE_EXPORT void rollback(Bookmark*);
04080 
04081     /** Commit all commands. */
04082     DECLARE_EXPORT void commit();
04083 
04084     /** Rolling back all commands. */
04085     DECLARE_EXPORT void rollback();
04086 };
04087 
04088 
04089 //
04090 // INPUT PROCESSING CLASSES
04091 //
04092 
04093 
04094 /** @brief This class will read in an XML-file and call the appropriate
04095   * handler functions of the Object classes and objects.
04096   *
04097   * This class is implemented based on the Xerces SAX XML parser.
04098   * For debugging purposes a flag is defined at the start of the file
04099   * "xmlparser.cpp". Uncomment the line and recompile to use it.
04100   *
04101   * FrePPLe creates a new parser and loads the XML schema every time
04102   * XML data need to be parsed. When this happens only a few times during a
04103   * run this is good enough.<br>
04104   * However, when the libary has to parse plenty of small XML messages this
04105   * will create a significant overhead. The code would need to be enhanced
04106   * to maintain a pool of parsers and cache their grammars.
04107   */
04108 class XMLInput : public NonCopyable,  private xercesc::DefaultHandler
04109 {
04110   public:
04111     typedef pair<Attribute,XMLElement> datapair;
04112 
04113   private:
04114     /** A pointer to an XML parser for processing the input. */
04115     xercesc::SAX2XMLReader* parser;
04116 
04117     /** This type defines the different states the parser can have. */
04118     enum state
04119     {
04120       /** The parser is sending input to an object handler. */
04121       READOBJECT,
04122       /** The parser has been instructed to ignore a tag. */
04123       IGNOREINPUT,
04124       /** The parser is shutting down, and will ignore all further data. */
04125       SHUTDOWN,
04126       /** This state is only used when the parser starts processing its first
04127         * tag. */
04128       INIT
04129     };
04130 
04131     /** This variable defines the maximum depth of the object creation stack.
04132       * This maximum is intended to protect us from malicious malformed
04133       * xml-documents, and also for allocating efficient data structures for
04134       * the parser.
04135       */
04136     const unsigned short maxdepth;
04137 
04138     /** Stack of states. */
04139     stack <state> states;
04140 
04141     /** Previous object in stack. */
04142     Object* prev;
04143 
04144     /** Stack of pairs. The pairs contain:
04145       *  - A pointer to an event handler object. The beginElement and
04146       *    endElement methods of this object will be called.
04147       *  - A user definable pointer. The purpose of this pointer is to store
04148       *    status information between calls to the handler.
04149       */
04150     vector< pair<Object*,void*> > m_EHStack;
04151 
04152     /** Stack of elements.<br>
04153       * The expression m_EStack[numElements+1] returns the current element.<br>
04154       * The expression m_EStack[numElements] returns the parent element.
04155       * @see numElements
04156       */
04157     vector<datapair> m_EStack;
04158 
04159     /** A variable to keep track of the size of the element stack. It is used
04160       * together with the variable m_EStack.
04161       * @see m_EStack
04162       */
04163     short numElements;
04164 
04165     /** This field counts how deep we are in a nested series of ignored input.
04166       * It is represented as a counter since the ignored element could contain
04167       * itself.
04168       */
04169     unsigned short ignore;
04170 
04171     /** Hash value of the current element. */
04172     stack<hashtype> endingHashes;
04173 
04174     /** This variable is normally false. It is switched to true only a) in
04175       * the method endElement() of Object objects and b) when an object
04176       * is processing its closing tag.
04177       */
04178     bool objectEnded;
04179 
04180     /** This field controls whether we continue processing after data errors
04181       * or whether we abort processing the remaining XML data.<br>
04182       * Selecting the right mode is important:
04183       *  - Setting the flag to false is appropriate for processing large
04184       *    amounts of a bulk-load operation. In this mode a single, potentially
04185       *    minor, data problem won't abort the complete process.
04186       *  - Setting the flag to true is most appropriate to process small and
04187       *    frequent messages from client applications. In this mode client
04188       *    applications are notified about data problems.
04189       *  - The default setting is true, in order to provide a maximum level of
04190       *    security for the application.
04191       */
04192     bool abortOnDataException;
04193 
04194     /** This is a pointer to the attributes.
04195       * See the xerces API documentation for further information on the usage
04196       * of the attribute list.
04197       */
04198     XMLAttributeList attributes;
04199 
04200     /** Handler called when a new element tag is encountered.
04201       * It pushes a new element on the stack and calls the current handler.
04202       */
04203     void startElement (const XMLCh* const, const XMLCh* const,
04204         const XMLCh* const, const xercesc::Attributes&);
04205 
04206     /** Handler called when closing element tag is encountered.
04207       * If this is the closing tag for the current event handler, pop it
04208       * off the handler stack. If this empties the stack, shut down parser.
04209       * Otherwise, just feed the element with the already completed
04210       * data section to the current handler, then pop it off the element
04211       * stack.
04212       */
04213     void endElement
04214     (const XMLCh* const, const XMLCh* const, const XMLCh* const);
04215 
04216     /** Handler called when character data are read in.
04217       * The data string is add it to the current element data.
04218       */
04219 #if XERCES_VERSION_MAJOR==2
04220     void characters(const XMLCh *const, const unsigned int);
04221 #else
04222     void characters(const XMLCh *const, const XMLSize_t);
04223 #endif
04224 
04225     /** Handler called by Xerces in fatal error conditions. It throws an
04226       * exception to abort the parsing procedure. */
04227     void fatalError (const xercesc::SAXParseException& e) {throw e;}
04228 
04229     /** Handler called by Xercess when reading a processing instruction. The
04230       * handler looks up the target in the repository and will call the
04231       * registered XMLinstruction.
04232       * @see XMLinstruction
04233       */
04234     void processingInstruction (const XMLCh *const, const XMLCh *const);
04235 
04236     /** Handler called by Xerces in error conditions. It throws an exception
04237       * to abort the parsing procedure. */
04238     void error (const xercesc::SAXParseException& e) {throw e;}
04239 
04240     /** Handler called by Xerces for warnings. */
04241     void warning (const xercesc::SAXParseException&);
04242 
04243     /** This method cleans up the parser state to get it ready for processing
04244       * a new document. */
04245     void reset();
04246 
04247     /** Return a pointer to the current object being read in.  */
04248     inline Object* getCurrentObject() const {return m_EHStack[m_EHStack.size()-1].first;}
04249 
04250   public:
04251     /** Constructor.
04252       * @param maxNestedElmnts Defines the maximum depth of elements an XML
04253       * document is allowed to have. The default is 20.
04254       */
04255     XMLInput(unsigned short maxNestedElmnts = 20)
04256       : parser(NULL), maxdepth(maxNestedElmnts), m_EStack(maxNestedElmnts+2),
04257         numElements(-1), ignore(0), objectEnded(false),
04258         abortOnDataException(true), attributes(NULL) {}
04259 
04260     /** Destructor. */
04261     virtual ~XMLInput() {reset();}
04262 
04263     /** Return a pointer to an array of character pointer which point
04264       * to the attributes. See the xerces documentation if this description
04265       * doesn't satisfy you...
04266       */
04267     const AttributeList& getAttributes() const {return attributes;}
04268 
04269     /** Redirect event stream into a new Object.<br>
04270       * It is also possible to pass a NULL pointer to the function. In
04271       * that situation, we simple ignore the content of that element.<br>
04272       * Important: The user is reponsible of making sure the argument
04273       * object has a proper write-lock. The release of that lock is handled
04274       * by the parser.
04275       */
04276     DECLARE_EXPORT void readto(Object*);
04277 
04278     /** Abort the parsing.
04279       * The actual shutdown cannot be called inside a SAX handler function,
04280       * so actual shutdown is deferred until the next iteration of the feed
04281       * loop.
04282       */
04283     void shutdown();
04284 
04285     /** Ignore an element. */
04286     void IgnoreElement() {readto(NULL);}
04287 
04288     /** Returns true if the current object is finishing with the current
04289       * tag. This method should only be used in the endElement() method. */
04290     bool isObjectEnd() {return objectEnded;}
04291 
04292     /** Invalidates the current object.<br>
04293       * This method is useful when, for instance, the object being parsed
04294       * is being deleted.
04295       */
04296     void invalidateCurrentObject()
04297     {
04298       if (!m_EHStack.empty())
04299         m_EHStack[m_EHStack.size()-1].first = NULL;
04300     }
04301 
04302     /** Return a pointer to the previous object being read in.<br>
04303       * In a typical use the returned pointer will require a dynamic_cast
04304       * to a subclass type.<br>
04305       * The typical usage is as follows:
04306       * <pre>
04307       *   Operation *o = dynamic_cast<Operation*>(pIn.getPreviousObject());
04308       *   if (o) doSomeThing(o);
04309       *   else throw LogicException("Incorrect object type");
04310       * </pre>
04311       */
04312     Object* getPreviousObject() const {return prev;}
04313 
04314     /** Clears the previously read object. */
04315     Object* getParentObject() const
04316     {
04317       int x = m_EHStack.size();
04318       return x>1 ? m_EHStack[x-2].first : NULL;
04319     }
04320 
04321     /** Returns a reference to the parent element. */
04322     const datapair& getParentElement() const
04323     {return m_EStack[numElements>0 ? numElements : 0];}
04324 
04325     /** Returns a reference to the current element. */
04326     const datapair& getCurrentElement() const
04327     {return m_EStack[numElements>-1 ? numElements+1 : 0];}
04328 
04329     /** This is the core parsing function, which triggers the XML parser to
04330       * start processing the input. It is normally called from the method
04331       * parse(Object*) once a proper stream has been created.
04332       * @see parse(Object*)
04333       */
04334     void parse(xercesc::InputSource&, Object*, bool=false);
04335 
04336     /** Updates the user definable pointer. This pointer is used to store
04337       * status information between handler calls. */
04338     void setUserArea(void* v)
04339     {if (!m_EHStack.empty()) m_EHStack[m_EHStack.size()-1].second = v;}
04340 
04341     /** Returns the user definable pointer. */
04342     void* getUserArea() const
04343     {return m_EHStack.empty() ? NULL : m_EHStack[m_EHStack.size()-1].second;}
04344 
04345     /** Updates whether we ignore data exceptions or whether we abort the
04346       * processing of the XML data stream. */
04347     void setAbortOnDataError(bool i) {abortOnDataException = i;}
04348 
04349     /** Returns the behavior of the parser in case of data errors.<br>
04350       * When true is returned, the processing of the XML stream continues
04351       * after a DataException. Other, more critical, exceptions types will
04352       * still abort the parsing process.<br>
04353       * False indicates that the processing of the XML stream is aborted.
04354       */
04355     bool getAbortOnDataError() const {return abortOnDataException;}
04356 
04357   protected:
04358     /** The real parsing job is delegated to subclasses.
04359       * Subclass can then define the specifics for parsing a flat file,
04360       * a string, a SOAP message, etc...
04361       * @exception RuntimeException Thrown in the following situations:
04362       *    - the xml-document is incorrectly formatted
04363       *    - the xml-parser librabry can't be initialized
04364       *    - no memory can be allocated to the xml-parser
04365       * @exception DataException Thrown when the data can't be processed
04366       *   normally by the objects being created or updated.
04367       */
04368     virtual void parse(Object* s, bool b=false)
04369     {
04370       throw LogicException("Unreachable code reached");
04371     }
04372 };
04373 
04374 
04375 /** @brief This class reads XML data from a string. */
04376 class XMLInputString : public XMLInput
04377 {
04378   public:
04379     /** Default constructor. */
04380     XMLInputString(const string& s) : data(s) {};
04381 
04382     /** Parse the specified string. */
04383     void parse(Object* pRoot, bool v = false)
04384     {
04385       /* The MemBufInputSource expects the number of bytes as second parameter.
04386        * In our case this is the same as the number of characters, but this
04387        * will not apply any more for character sets with multi-byte
04388        * characters.
04389        */
04390       xercesc::MemBufInputSource a(
04391         reinterpret_cast<const XMLByte*>(data.c_str()),
04392         static_cast<const unsigned int>(data.size()),
04393         "memory data",
04394         false);
04395       XMLInput::parse(a,pRoot,v);
04396     }
04397 
04398   private:
04399     /** String containing the data to be parsed. Note that NO local copy of the
04400       * data is made, only a reference is stored. The class relies on the code
04401       * calling the command to correctly create and destroy the string being
04402       * used.
04403       */
04404     const string data;
04405 };
04406 
04407 
04408 /** @brief This class reads XML data from a file system.
04409   *
04410   * The filename argument can be the name of a file or a directory.
04411   * If a directory is passed, all files with the extension ".xml"
04412   * will be read from it. Subdirectories are not recursed.
04413   */
04414 class XMLInputFile : public XMLInput
04415 {
04416   public:
04417     /** Constructor. The argument passed is the name of a
04418       * file or a directory. */
04419     XMLInputFile(const string& s) : filename(s) {};
04420 
04421     /** Default constructor. */
04422     XMLInputFile() {};
04423 
04424     /** Update the name of the file to be processed. */
04425     void setFileName(const string& s) {filename = s;}
04426 
04427     /** Returns the name of the file or directory to process. */
04428     string getFileName() {return filename;}
04429 
04430     /** Parse the specified file.
04431       * When a directory was passed as the argument a failure is
04432       * flagged as soon as a single file returned a failure. All
04433       * files in an directory are processed however, regardless of
04434       * failure with one of the files.
04435       * @exception RuntimeException Generated in the following conditions:
04436       *    - no input file or directory has been specified.
04437       *    - read access to the input file is not available
04438       *    - the program doesn't support reading directories on your platform
04439       */
04440     void parse(Object*, bool=false);
04441 
04442   private:
04443     /** Name of the file to be opened. */
04444     string filename;
04445 };
04446 
04447 
04448 //
04449 //  UTILITY CLASSES "HASNAME", "HASHIERARCHY", "HASDESCRIPTION"
04450 //
04451 
04452 
04453 /** @brief Base class for objects using a string as their primary key.
04454   *
04455   * Instances of this class have the following properties:
04456   *   - Have a unique name.
04457   *   - A hashtable (keyed on the name) is maintained as a container with
04458   *     all active instances.
04459   */
04460 template <class T> class HasName : public NonCopyable, public Tree::TreeNode, public Object
04461 {
04462   private:
04463     /** Maintains a global list of all created entities. The list is keyed
04464       * by the name. */
04465     static DECLARE_EXPORT Tree st;
04466     typedef T* type;
04467 
04468   public:
04469     /** @brief This class models a STL-like iterator that allows us to
04470       * iterate over the named entities in a simple and safe way.
04471       *
04472       * Objects of this class are created by the begin() and end() functions.
04473       * @todo not thread-safe: needs to lock the tree during iteration
04474       */
04475     class iterator
04476     {
04477       public:
04478         /** Constructor. */
04479         iterator(Tree::TreeNode* x) : node(x) {}
04480 
04481         /** Copy constructor. */
04482         iterator(const iterator& it) {node = it.node;}
04483 
04484         /** Return the content of the current node. */
04485         T& operator*() const {return *static_cast<T*>(node);}
04486 
04487         /** Return the content of the current node. */
04488         T* operator->() const {return static_cast<T*>(node);}
04489 
04490         /** Pre-increment operator which moves the pointer to the next
04491           * element. */
04492         iterator& operator++() {node = node->increment(); return *this;}
04493 
04494         /** Post-increment operator which moves the pointer to the next
04495           * element. */
04496         iterator operator++(int)
04497         {
04498           Tree::TreeNode* tmp = node;
04499           node = node->increment();
04500           return tmp;
04501         }
04502 
04503         /** Pre-decrement operator which moves the pointer to the previous
04504           * element. */
04505         iterator& operator--() {node = node->decrement(); return *this;}
04506 
04507         /** Post-decrement operator which moves the pointer to the previous
04508           * element. */
04509         iterator operator--(int)
04510         {
04511           Tree::TreeNode* tmp = node;
04512           node = node->decrement();
04513           return tmp;
04514         }
04515 
04516         /** Comparison operator. */
04517         bool operator==(const iterator& y) const {return node==y.node;}
04518 
04519         /** Inequality operator. */
04520         bool operator!=(const iterator& y) const {return node!=y.node;}
04521 
04522       private:
04523         Tree::TreeNode* node;
04524     };
04525 
04526     /** Returns a STL-like iterator to the end of the entity list. */
04527     static iterator end() {return st.end();}
04528 
04529     /** Returns a STL-like iterator to the start of the entity list. */
04530     static iterator begin() {return st.begin();}
04531 
04532     /** Returns false if no named entities have been defined yet. */
04533     static bool empty() {return st.empty();}
04534 
04535     /** Returns the number of defined entities. */
04536     static size_t size() {return st.size();}
04537 
04538     /** Debugging method to verify the validity of the tree.
04539       * An exception is thrown when the tree is corrupted. */
04540     static void verify() {st.verify();}
04541 
04542     /** Deletes all elements from the list. */
04543     static void clear() {st.clear();}
04544 
04545     /** Constructor. */
04546     explicit HasName(const string& n) : Tree::TreeNode(n) {}
04547 
04548     /** Constructor. */
04549     explicit HasName(const char* n) : Tree::TreeNode(n) {}
04550 
04551     /** Rename the entity. */
04552     void setName(const string& newname) {st.rename(this, newname);}
04553 
04554     /** Destructor. */
04555     ~HasName() {st.erase(this);}
04556 
04557     /** Return the name as the string representation in Python. */
04558     virtual PyObject* str() const {return PythonObject(getName());}
04559 
04560     /** Comparison operator for Python. */
04561     int compare(const PyObject* other) const
04562     {
04563       if (this->ob_type == other->ob_type
04564           || this->ob_type->tp_base == other->ob_type->tp_base)
04565         return getName().compare(static_cast<const T*>(other)->getName());
04566       else
04567       {
04568         // Different types
04569         PyErr_SetString(PythonDataException, "Wrong type in comparison");
04570         return -1;
04571       }
04572     }
04573 
04574     /** Find an entity given its name. In case it can't be found, a NULL
04575       * pointer is returned. */
04576     static T* find(const string& k)
04577     {
04578       Tree::TreeNode *i = st.find(k);
04579       return (i!=st.end() ? static_cast<T*>(i) : NULL);
04580     }
04581 
04582     /** Find the element with this given key or the element
04583       * immediately preceding it.<br>
04584       * The optional second argument is a boolean that is set to true when
04585       * the element is found in the list.
04586       */
04587     static T* findLowerBound(const string& k, bool *f = NULL)
04588     {
04589       Tree::TreeNode *i = st.findLowerBound(k, f);
04590       return (i!=st.end() ? static_cast<T*>(i) : NULL);
04591     }
04592 
04593     /** Creates a new entity. */
04594     static T* add(const string& k, const MetaClass& cls)
04595     {
04596       Tree::TreeNode *i = st.find(k);
04597       if (i!=st.end()) return static_cast<T*>(i); // Exists already
04598       if (*(cls.category) != T::metadata)
04599         throw LogicException("Invalid type " + cls.type +
04600             " for creating an object of category " + T::metadata.type);
04601       T *t = dynamic_cast<T*>(cls.factoryMethodString(k));
04602       st.insert(t);
04603       return t;
04604     }
04605 
04606     /** Registers an entity created by the default constructor. */
04607     static T* add(T* t) {return static_cast<T*>(st.insert(t));}
04608 
04609     /** Registers an entity created by the default constructor. The second
04610       * argument is a hint: when passing an entity with a name close to
04611       * the new one, the insertion will be sped up considerably.
04612       */
04613     static T* add(T* t, T* hint) {return static_cast<T*>(st.insert(t,hint));}
04614 
04615     void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement) {};
04616 
04617     /** This method is available as a object creation factory for
04618       * classes that are using a string as a key identifier, in particular
04619       * classes derived from the HasName base class.
04620       * The following attributes are recognized:
04621       * - name:<br>
04622       *   Name of the entity to be created/changed/removed.<br>
04623       *   The default value is "unspecified".
04624       * - type:<br>
04625       *   Determines the subclass to be created.<br>
04626       *   The default value is "default".
04627       * - action:<br>
04628       *   Determines the action to be performed on the object.<br>
04629       *   This can be A (for 'add'), C (for 'change'), AC (for 'add_change')
04630       *   or R (for 'remove').<br>
04631       *   'add_change' is the default value.
04632       * @see HasName
04633       */
04634     static Object* reader (const MetaClass* cat, const AttributeList& in)
04635     {
04636       // Pick up the action attribute
04637       Action act = MetaClass::decodeAction(in);
04638 
04639       // Pick up the name attribute. An error is reported if it's missing.
04640       const DataElement* nameElement = in.get(Tags::tag_name);
04641       if (!*nameElement) throw DataException("Missing name attribute");
04642       string name = nameElement->getString();
04643 
04644       // Check if it exists already
04645       bool found;
04646       T *i = T::findLowerBound(name, &found);
04647 
04648       // Validate the action
04649       switch (act)
04650       {
04651         case ADD:
04652           // Only additions are allowed
04653           if (found)
04654             throw DataException("Object '" + name + "' already exists");
04655           break;
04656 
04657         case CHANGE:
04658           // Only changes are allowed
04659           if (!found)
04660             throw DataException("Object '" + name + "' doesn't exist");
04661           return i;
04662 
04663         case REMOVE:
04664           // Delete the entity
04665           if (found)
04666           {
04667             // Send out the notification to subscribers
04668             if (i->getType().raiseEvent(i,SIG_REMOVE))
04669             {
04670               // Delete the object
04671               delete i;
04672               return NULL;
04673             }
04674             else
04675               // The callbacks disallowed the deletion!
04676               throw DataException("Can't remove object '" + name + "'");
04677           }
04678           else
04679             // Not found
04680             throw DataException("Can't find object '" + name + "' for removal");
04681         default:
04682           // case ADD_CHANGE doesn't have special cases.
04683           ;
04684       }
04685 
04686       // Return the existing instance
04687       if (found) return i;
04688 
04689       // Lookup the type in the map
04690       const MetaClass* j;
04691       if (cat->category)
04692         // Class metadata passed: we already know what type to create
04693         j = cat;
04694       else
04695       {
04696         // Category metadata passed: we need to look up the type
04697         const DataElement* type = in.get(Tags::tag_type);
04698         j = static_cast<const MetaCategory&>(*cat).findClass(
04699             *type ? Keyword::hash(type->getString()) : MetaCategory::defaultHash
04700             );
04701         if (!j)
04702         {
04703           string t(*type ? type->getString() : "default");
04704           throw DataException("No type " + t + " registered for category " + cat->type);
04705         }
04706       }
04707 
04708       // Create a new instance
04709       T* x = dynamic_cast<T*>(j->factoryMethodString(name));
04710 
04711       // Run creation callbacks
04712       // During the callback there is no write lock set yet, since we can
04713       // assume we are the only ones aware of this new object. We also want
04714       // to make sure the 'add' signal comes before the 'before_change'
04715       // callback that is part of the writelock.
04716       if (!x->getType().raiseEvent(x,SIG_ADD))
04717       {
04718         // Creation isn't allowed
04719         delete x;
04720         throw DataException("Can't create object " + name);
04721       }
04722 
04723       // Insert in the tree
04724       T::add(x, i);
04725       return x;
04726     }
04727 
04728     /** A handler that is used to persist the tree. */
04729     static void writer(const MetaCategory* c, XMLOutput* o)
04730     {
04731       if (empty()) return;
04732       o->BeginObject(*(c->grouptag));
04733       for (iterator i = begin(); i != end(); ++i)
04734         o->writeElement(*(c->typetag), *i);
04735       o->EndObject(*(c->grouptag));
04736     }
04737 };
04738 
04739 
04740 /** @brief This is a decorator class for the main objects.
04741   *
04742   * Instances of this class have a description, category and sub_category.
04743   */
04744 class HasDescription
04745 {
04746   public:
04747     /** Returns the category. */
04748     string getCategory() const {return cat;}
04749 
04750     /** Returns the sub_category. */
04751     string getSubCategory() const {return subcat;}
04752 
04753     /** Returns the getDescription. */
04754     string getDescription() const {return descr;}
04755 
04756     /** Sets the category field. */
04757     void setCategory(const string& f) {cat = f;}
04758 
04759     /** Sets the sub_category field. */
04760     void setSubCategory(const string& f) {subcat = f;}
04761 
04762     /** Sets the description field. */
04763     void setDescription(const string& f) {descr = f;}
04764 
04765     void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
04766     void endElement(XMLInput&, const Attribute&, const DataElement&);
04767 
04768   protected:
04769     /** Returns the memory size in bytes. */
04770     size_t extrasize() const {return cat.size() + subcat.size() + descr.size();}
04771 
04772   private:
04773     string cat;
04774     string subcat;
04775     string descr;
04776 };
04777 
04778 
04779 /** @brief This is a base class for the main objects.
04780   *
04781   * Instances of this class have the following properties:
04782   *  - Unique name and global hashtable are inherited from the class HasName.
04783   *  - Instances build up hierarchical trees of arbitrary depth.
04784   *  - Each object can have a single parent only.
04785   *  - Each object has a parent and can have children.
04786   *    This class thus implements the 'composite' design pattern.
04787   * The internal data structure is a singly linked linear list, which is
04788   * efficient provided the number of childre remains limited.
04789   */
04790 template <class T> class HasHierarchy : public HasName<T>
04791 {
04792 #if  (defined _MSC_VER) || (defined __BORLANDC__)
04793     // Visual C++ 6.0 and Borland C++ 5.5 seem to get confused with the private
04794     // template members
04795     friend class HasHierarchy<T>;
04796 #endif
04797 
04798   public:
04799     class memberIterator;
04800     friend class memberIterator;
04801     /** @brief This class models an STL-like iterator that allows us to
04802       * iterate over the members.
04803       *
04804       * Objects of this class are created by the beginMember() method.
04805       */
04806     class memberIterator
04807     {
04808       public:
04809         /** Constructor to iterate over member entities. */
04810         memberIterator(const HasHierarchy<T>* x) : member_iter(true)
04811         {curmember = const_cast<HasHierarchy<T>*>(x)->first_child;}
04812 
04813         /** Constructor to iterate over all entities. */
04814         memberIterator() : curmember(&*T::begin()), member_iter(false) {}
04815 
04816         /** Constructor. */
04817         memberIterator(const typename HasName<T>::iterator& it) : curmember(&*it), member_iter(false) {}
04818 
04819         /** Copy constructor. */
04820         memberIterator(const memberIterator& it)
04821         {
04822           curmember = it.curmember;
04823           member_iter = it.member_iter;
04824         }
04825 
04826         /** Return the content of the current node. */
04827         T& operator*() const {return *static_cast<T*>(curmember);}
04828 
04829         /** Return the content of the current node. */
04830         T* operator->() const {return static_cast<T*>(curmember);}
04831 
04832         /** Pre-increment operator which moves the pointer to the next member. */
04833         memberIterator& operator++()
04834         {
04835           if (member_iter)
04836             curmember = curmember->next_brother;
04837           else
04838             curmember = static_cast<T*>(curmember->increment());
04839           return *this;
04840         }
04841 
04842         /** Post-increment operator which moves the pointer to the next member. */
04843         memberIterator operator++(int)
04844         {
04845           memberIterator tmp = *this;
04846           if (member_iter)
04847             curmember = curmember->next_brother;
04848           else
04849             curmember = static_cast<T*>(curmember->increment());
04850           return tmp;
04851         }
04852 
04853         /** Comparison operator. */
04854         bool operator==(const memberIterator& y) const
04855         {return curmember == y.curmember;}
04856 
04857         /** Inequality operator. */
04858         bool operator!=(const memberIterator& y) const
04859         {return curmember != y.curmember;}
04860 
04861         /** Comparison operator. */
04862         bool operator==(const typename HasName<T>::iterator& y) const
04863         {return curmember ? (curmember == &*y) : (y == T::end());}
04864 
04865         /** Inequality operator. */
04866         bool operator!=(const typename HasName<T>::iterator& y) const
04867         {return curmember ? (curmember != &*y) : (y != T::end());}
04868 
04869       private:
04870         /** Points to a member. */
04871         HasHierarchy<T>* curmember;
04872         bool member_iter;
04873     };
04874 
04875     /** The one and only constructor. */
04876     HasHierarchy(const string& n) : HasName<T>(n), parent(NULL),
04877       first_child(NULL), next_brother(NULL) {}
04878 
04879     /** Destructor.
04880       * When deleting a node of the hierarchy, the children will get the
04881       * current parent as the new parent.
04882       * In this way the deletion of nodes doesn't create "dangling branches"
04883       * in the hierarchy. We just "collapse" a certain level.
04884       */
04885     ~HasHierarchy();
04886 
04887     /** Return a member iterator. */
04888     memberIterator beginMember() const {return this;}
04889 
04890     /** Returns true if this entity belongs to a higher hierarchical level.<br>
04891       * An entity can have only a single owner, and can't belong to multiple
04892       * hierarchies.
04893       */
04894     bool hasOwner() const {return parent!=NULL;}
04895 
04896     /** Returns true if this entity has lower level entities belonging to
04897       * it. */
04898     bool isGroup() const {return first_child!=NULL;}
04899 
04900     /** Changes the owner of the entity.<br>
04901       * The argument must be a valid pointer to an entity of the same type.<br>
04902       * A NULL pointer can be passed to clear the existing owner.<br>
04903       */
04904     void setOwner(T* f);
04905 
04906     /** Returns the owning entity. */
04907     T* getOwner() const {return parent;}
04908 
04909     /** Returns the level in the hierarchy.<br>
04910       * Level 0 means the entity doesn't have any parent.<br>
04911       * Level 1 means the entity has a parent entity with level 0.<br>
04912       * Level "x" means the entity has a parent entity whose level is "x-1".
04913       */
04914     unsigned short getHierarchyLevel() const;
04915 
04916     void beginElement(XMLInput&, const Attribute&);
04917     void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
04918     void endElement(XMLInput&, const Attribute&, const DataElement&);
04919 
04920   private:
04921     /** A pointer to the parent object. */
04922     T *parent;
04923 
04924     /** A pointer to the first child object. */
04925     T *first_child;
04926 
04927     /** A pointer to the next brother object, ie an object having the
04928       * same parent.<br>
04929       * The brothers are all linked as a single linked list, with the
04930       * first_child pointer on the parent being the root pointer of the list.
04931       */
04932     T *next_brother;
04933 };
04934 
04935 
04936 //
04937 // ASSOCIATION
04938 //
04939 
04940 /** @brief This template class represents a data structure for a load or flow
04941   * network.
04942   *
04943   * A node class has pointers to 2 root classes.<br> The 2 root classes each
04944   * maintain a singly linked list of nodes.<br>
04945   * An example to clarify the usage:
04946   *  - class "node" = a newspaper subscription.
04947   *  - class "person" = maintains a list of all his subscriptions.
04948   *  - class "newspaper" = maintains a list of all subscriptions for it.
04949   *
04950   * This data structure could be replaced with 2 linked lists, but this
04951   * specialized data type consumes considerably lower memory.
04952   *
04953   * Reading from the structure is safe in multi-threading mode.<br>
04954   * Updates to the data structure in a multi-threading mode require the user
04955   * to properly lock and unlock the container.
04956   */
04957 template <class A, class B, class C> class Association
04958 {
04959   public:
04960     class Node;
04961   private:
04962     /** @brief A abstract base class for the internal representation of the
04963       * association lists.
04964       */
04965     class List
04966     {
04967         friend class Node;
04968       public:
04969         C* first;
04970       public:
04971         List() : first(NULL) {};
04972         bool empty() const {return first==NULL;}
04973     };
04974 
04975   public:
04976     /** @brief A list type of the "first" / "from" part of the association. */
04977     class ListA : public List
04978     {
04979       public:
04980         ListA() {};
04981         /** @brief An iterator over the associated objects. */
04982         class iterator
04983         {
04984           protected:
04985             C* nodeptr;
04986           public:
04987             iterator(C* n) : nodeptr(n) {};
04988             C& operator*() const {return *nodeptr;}
04989             C* operator->() const {return nodeptr;}
04990             bool operator==(const iterator& x) const
04991             {return nodeptr == x.nodeptr;}
04992             bool operator!=(const iterator& x) const
04993             {return nodeptr != x.nodeptr;}
04994             iterator& operator++()
04995             {nodeptr = nodeptr->nextA; return *this;}
04996             iterator operator++(int i)
04997             {
04998               iterator j = *this;
04999               nodeptr = nodeptr->nextA;
05000               return j;
05001             }
05002         };
05003         /** @brief An iterator over the associated objects. */
05004         class const_iterator
05005         {
05006           protected:
05007             C* nodeptr;
05008           public:
05009             const_iterator(C* n) : nodeptr(n) {};
05010             const C& operator*() const {return *nodeptr;}
05011             const C* operator->() const {return nodeptr;}
05012             bool operator==(const const_iterator& x) const
05013             {return nodeptr == x.nodeptr;}
05014             bool operator!=(const const_iterator& x) const
05015             {return nodeptr != x.nodeptr;}
05016             const_iterator& operator++()
05017             {nodeptr = nodeptr->nextA; return *this;}
05018             const_iterator operator++(int i)
05019             {
05020               const_iterator j = *this;
05021               nodeptr = nodeptr->nextA;
05022               return j;
05023             }
05024         };
05025         iterator begin() {return iterator(this->first);}
05026         const_iterator begin() const {return const_iterator(this->first);}
05027         iterator end() {return iterator(NULL);}
05028         const_iterator end() const {return const_iterator(NULL);}
05029 
05030         /** Destructor. */
05031         ~ListA()
05032         {
05033           C* next;
05034           for (C* p=this->first; p; p=next)
05035           {
05036             next = p->nextA;
05037             delete p;
05038           }
05039         }
05040 
05041         /** Remove an association. */
05042         void erase(const C* n)
05043         {
05044           if (!n) return;
05045           if (n==this->first)
05046             this->first = n->nextA;
05047           else
05048             for (C* p=this->first; p; p=p->nextA)
05049               if(p->nextA == n)
05050               {
05051                 p->nextA = n->nextA;
05052                 return;
05053               }
05054         }
05055 
05056         /** Return the number of associations. */
05057         size_t size() const
05058         {
05059           size_t i(0);
05060           for (C* p = this->first; p; p=p->nextA) ++i;
05061           return i;
05062         }
05063 
05064         /** Search for the association effective at a certain date. */
05065         C* find(const B* b, Date d = Date::infinitePast) const
05066         {
05067           for (C* p=this->first; p; p=p->nextA)
05068             if (p->ptrB == b && p->effectivity.within(d)) return p;
05069           return NULL;
05070         }
05071 
05072         /** Search for the association with a certain name. */
05073         C* find(const string& n) const
05074         {
05075           for (C* p=this->first; p; p=p->nextA)
05076             if (p->name == n) return p;
05077           return NULL;
05078         }
05079 
05080         /** Move an association a position up in the list of associations. */
05081         void promote(C* p)
05082         {
05083           // Already at the head
05084           if (p == this->first) return;
05085 
05086           // Scan the list
05087           C* prev = NULL;
05088           for (C* ptr = this->first; ptr; ptr = ptr->nextA)
05089           {
05090             if (ptr->nextA == p)
05091             {
05092               if (prev)
05093                 prev->nextA = p;
05094               else
05095                 this->first = p;
05096               ptr->nextA = p->nextA;
05097               p->nextA = ptr;
05098               return;
05099             }
05100             prev = ptr;
05101           }
05102           throw LogicException("Association not found in the list");
05103         }
05104     };
05105 
05106     /** @brief A list type of the "second" / "to" part of the association. */
05107     class ListB : public List
05108     {
05109       public:
05110         ListB() {};
05111         /** @brief An iterator over the associated objects. */
05112         class iterator
05113         {
05114           protected:
05115             C* nodeptr;
05116           public:
05117             iterator(C* n) : nodeptr(n) {};
05118             C& operator*() const {return *nodeptr;}
05119             C* operator->() const {return nodeptr;}
05120             bool operator==(const iterator& x) const
05121             {return nodeptr == x.nodeptr;}
05122             bool operator!=(const iterator& x) const
05123             {return nodeptr != x.nodeptr;}
05124             iterator& operator++()
05125             {nodeptr = nodeptr->nextB; return *this;}
05126             iterator operator++(int i)
05127             {
05128               iterator j = *this;
05129               nodeptr = nodeptr->nextA;
05130               return j;
05131             }
05132         };
05133         /** @brief An iterator over the associated objects. */
05134         class const_iterator
05135         {
05136           protected:
05137             C* nodeptr;
05138           public:
05139             const_iterator(C* n) : nodeptr(n) {};
05140             const C& operator*() const {return *nodeptr;}
05141             const C* operator->() const {return nodeptr;}
05142             bool operator==(const const_iterator& x) const
05143             {return nodeptr == x.nodeptr;}
05144             bool operator!=(const const_iterator& x) const
05145             {return nodeptr != x.nodeptr;}
05146             const_iterator& operator++()
05147             {nodeptr = nodeptr->nextB; return *this;}
05148             const_iterator operator++(int i)
05149             {
05150               const_iterator j = *this;
05151               nodeptr = nodeptr->nextA;
05152               return j;
05153             }
05154         };
05155 
05156         /** Destructor. */
05157         ~ListB()
05158         {
05159           C* next;
05160           for (C* p=this->first; p; p=next)
05161           {
05162             next = p->nextB;
05163             delete p;
05164           }
05165         }
05166         iterator begin() {return iterator(this->first);}
05167         const_iterator begin() const {return const_iterator(this->first);}
05168         iterator end() {return iterator(NULL);}
05169         const_iterator end() const {return const_iterator(NULL);}
05170 
05171         /** Remove an association. */
05172         void erase(const C* n)
05173         {
05174           if (!n) return;
05175           if (n==this->first)
05176             this->first = n->nextB;
05177           else
05178             for (C* p=this->first; p; p=p->nextB)
05179               if(p->nextB == n)
05180               {
05181                 p->nextB = n->nextB;
05182                 return;
05183               }
05184         }
05185 
05186         /** Return the number of associations. */
05187         size_t size() const
05188         {
05189           size_t i(0);
05190           for (C* p=this->first; p; p=p->nextB) ++i;
05191           return i;
05192         }
05193 
05194         /** Search for the association effective at a certain date. */
05195         C* find(const A* b, Date d = Date::infinitePast) const
05196         {
05197           for (C* p=this->first; p; p=p->nextB)
05198             if (p->ptrA == b && p->effectivity.within(d)) return p;
05199           return NULL;
05200         }
05201 
05202         /** Search for the association with a certain name. */
05203         C* find(const string& n) const
05204         {
05205           for (C* p=this->first; p; p=p->nextB)
05206             if (p->name == n) return p;
05207           return NULL;
05208         }
05209 
05210         /** Move an association a position up in the list of associations. */
05211         void promote(C* p)
05212         {
05213           // Already at the head
05214           if (p == this->first) return;
05215 
05216           // Scan the list
05217           C* prev = NULL;
05218           for (C* ptr = this->first; ptr; ptr = ptr->nextB)
05219           {
05220             if (ptr->nextB == p)
05221             {
05222               if (prev)
05223                 prev->nextB = p;
05224               else
05225                 this->first = p;
05226               ptr->nextB = p->nextB;
05227               p->nextB = ptr;
05228               return;
05229             }
05230             prev = ptr;
05231           }
05232           throw LogicException("Association not found in the list");
05233         }
05234     };
05235 
05236     /** @brief A base class for the class representing the association
05237       * itself.
05238       */
05239     class Node
05240     {
05241       public:
05242         A* ptrA;
05243         B* ptrB;
05244         C* nextA;
05245         C* nextB;
05246         DateRange effectivity;
05247         string name;
05248       public:
05249         /** Constructor. */
05250         Node() : ptrA(NULL), ptrB(NULL), nextA(NULL), nextB(NULL) {};
05251 
05252         /** Constructor. */
05253         Node(A* a, B* b, const ListA& al, const ListB& bl)
05254           : ptrA(a), ptrB(b), nextA(NULL), nextB(NULL)
05255         {
05256           if (al.first)
05257           {
05258             // Append at the end of the A-list
05259             C* x = al.first;
05260             while (x->nextA) x = x->nextA;
05261             x->nextA = static_cast<C*>(this);
05262           }
05263           else
05264             // New start of the A-list
05265             const_cast<ListA&>(al).first = static_cast<C*>(this);
05266           if (bl.first)
05267           {
05268             // Append at the end of the B-list
05269             C* x = bl.first;
05270             while (x->nextB) x = x->nextB;
05271             x->nextB = static_cast<C*>(this);
05272           }
05273           else
05274             // New start of the B-list
05275             const_cast<ListB&>(bl).first = static_cast<C*>(this);
05276         }
05277 
05278         void setPtrA(A* a, const ListA& al)
05279         {
05280           // Don't allow updating an already valid link
05281           if (ptrA) throw DataException("Can't update existing entity");
05282           ptrA = a;
05283           if (al.first)
05284           {
05285             // Append at the end of the A-list
05286             C* x = al.first;
05287             while (x->nextA) x = x->nextA;
05288             x->nextA = static_cast<C*>(this);
05289           }
05290           else
05291             // New start of the A-list
05292             const_cast<ListA&>(al).first = static_cast<C*>(this);
05293         }
05294 
05295         void setPtrB(B* b, const ListB& bl)
05296         {
05297           // Don't allow updating an already valid link
05298           if (ptrB) throw DataException("Can't update existing entity");
05299           ptrB = b;
05300           if (bl.first)
05301           {
05302             // Append at the end of the B-list
05303             C* x = bl.first;
05304             while (x->nextB) x = x->nextB;
05305             x->nextB = static_cast<C*>(this);
05306           }
05307           else
05308             // New start of the B-list
05309             const_cast<ListB&>(bl).first = static_cast<C*>(this);
05310         }
05311 
05312         void setPtrAB(A* a, B* b, const ListA& al, const ListB& bl)
05313         {
05314           setPtrA(a, al);
05315           setPtrB(b, bl);
05316         }
05317 
05318         A* getPtrA() const {return ptrA;}
05319 
05320         B* getPtrB() const {return ptrB;}
05321 
05322         /** Update the start date of the effectivity range. */
05323         void setEffectiveStart(Date d) {effectivity.setStart(d);}
05324 
05325         /** Update the end date of the effectivity range. */
05326         void setEffectiveEnd(Date d) {effectivity.setEnd(d);}
05327 
05328         /** Update the effectivity range. */
05329         void setEffective(DateRange dr) {effectivity = dr;}
05330 
05331         /** Return the effectivity daterange.<br>
05332           * The default covers the complete time horizon.
05333           */
05334         DateRange getEffective() const {return effectivity;}
05335 
05336         /** Sets an optional name for the association.<br>
05337           * There is no garantuee of the uniqueness of this name.
05338           */
05339         void setName(const string x) {name = x;}
05340 
05341         /** Return the optional name of the association. */
05342         const string& getName() const {return name;}
05343     };
05344 };
05345 
05346 
05347 #include "frepple/entity.h"
05348 
05349 
05350 //
05351 // LIBRARY INITIALISATION
05352 //
05353 
05354 /** @brief This class holds functions that used for maintenance of the library.
05355   *
05356   * Its static member function 'initialize' should be called BEFORE the
05357   * first use of any class in the library.
05358   * The member function 'finialize' will be called automatically at the
05359   * end of the program.
05360   */
05361 class LibraryUtils
05362 {
05363   public:
05364     static void initialize(int argc, char* argv[]);
05365 };
05366 
05367 /** @brief A template class to expose iterators to Python. */
05368 template <class ME, class ITERCLASS, class DATACLASS>
05369 class FreppleIterator : public PythonExtension<ME>
05370 {
05371   public:
05372     static int initialize()
05373     {
05374       // Initialize the type
05375       PythonType& x = PythonExtension<ME>::getType();
05376       x.setName(DATACLASS::metadata->type + "Iterator");
05377       x.setDoc("frePPLe iterator for " + DATACLASS::metadata->type);
05378       x.supportiter();
05379       return x.typeReady();
05380     }
05381 
05382     FreppleIterator() : i(DATACLASS::begin())
05383     {this->initType(PythonExtension<ME>::getType().type_object());}
05384 
05385     template <class OTHER> FreppleIterator(const OTHER *o) : i(o)
05386     {this->initType(PythonExtension<ME>::getType().type_object());}
05387 
05388     template <class OTHER> FreppleIterator(const OTHER &o) : i(o)
05389     {this->initType(PythonExtension<ME>::getType().type_object());}
05390 
05391     static PyObject* create(PyObject* self, PyObject* args)
05392     {return new ME();}
05393 
05394   private:
05395     ITERCLASS i;
05396 
05397     virtual PyObject* iternext()
05398     {
05399       if (i == DATACLASS::end()) return NULL;
05400       PyObject* result = &*i;
05401       ++i;
05402       Py_INCREF(result);
05403       return result;
05404     }
05405 };
05406 
05407 /** @brief This Python function loads a frepple extension module in memory. */
05408 DECLARE_EXPORT PyObject* loadModule(PyObject*, PyObject*, PyObject*);
05409 
05410 
05411 } // end namespace
05412 } // end namespace
05413 
05414 #include "pythonutils.h"
05415 
05416 #endif  // End of FREPPLE_UTILS_H

Documentation generated for frePPLe by  doxygen