utils.h

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

Documentation generated for frePPLe by  doxygen