utils.h

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

Generated on 21 Mar 2010 for frePPLe by  doxygen 1.6.1