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

Documentation generated for frePPLe by  doxygen