utils.h
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba *
4  * *
5  * This library is free software; you can redistribute it and/or modify it *
6  * under the terms of the GNU Affero General Public License as Objecthed *
7  * by the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This library is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU Affero General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Affero General Public *
16  * License along with this program. *
17  * If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  ***************************************************************************/
20 
21 /** @file utils.h
22  * @brief Header file for auxilary classes.
23  *
24  * @namespace frepple::utils
25  * @brief Utilities for the frePPle core
26  */
27 
28 #ifndef FREPPLE_UTILS_H
29 #define FREPPLE_UTILS_H
30 
31 /* Python.h has to be included first.
32  For a debugging build on windows we avoid using the debug version of Python
33  since that also requires Python and all its modules to be compiled in debug
34  mode.
35  Visual Studio will complain if system headers are #included both with
36  and without _DEBUG defined, so we have to #include all the system headers
37  used by pyconfig.h right here.
38 */
39 #if defined(_DEBUG) && defined(_MSC_VER)
40 #include <stddef.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <errno.h>
46 #include <ctype.h>
47 #include <wchar.h>
48 #include <basetsd.h>
49 #include <io.h>
50 #include <limits.h>
51 #include <float.h>
52 #include <string.h>
53 #include <math.h>
54 #include <time.h>
55 #undef _DEBUG
56 #include "Python.h"
57 #define _DEBUG
58 #else
59 #include "Python.h"
60 #endif
61 #include "datetime.h"
62 
63 // For compatibility with earlier Python releases
64 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
65 typedef int Py_ssize_t;
66 #define PY_SSIZE_T_MAX INT_MAX
67 #define PY_SSIZE_T_MIN INT_MIN
68 #endif
69 
70 #ifndef DOXYGEN
71 #include <iostream>
72 #include <fstream>
73 #include <sstream>
74 #include <stdexcept>
75 #include <ctime>
76 #include <assert.h>
77 #include <typeinfo>
78 #include <float.h>
79 #endif
80 
81 // We want to use singly linked lists, but these are not part of the C++
82 // standard though. Sigh...
83 #ifndef DOXYGEN
84 #ifdef HAVE_EXT_SLIST
85 // Singly linked lists as extension: gcc 3.x
86 #include <ext/slist>
87 using namespace gnu_cxx;
88 #else
89 #ifdef HAVE_SLIST
90 // Singly linked lists available in std stl: gcc 2.95
91 #include <slist>
92 #else
93 // Not available: use a double linked list instead
94 #define slist list
95 #endif
96 #endif
97 #endif
98 
99 // STL include files
100 #ifndef DOXYGEN
101 #include <list>
102 #include <map>
103 #include <set>
104 #include <string>
105 #include <stack>
106 #include <vector>
107 #include <algorithm>
108 #endif
109 using namespace std;
111 /** @def PACKAGE_VERSION
112  * Defines the version of frePPLe.
113  */
114 #ifdef HAVE_CONFIG_H
115 #undef PACKAGE_BUGREPORT
116 #undef PACKAGE_NAME
117 #undef PACKAGE_STRING
118 #undef PACKAGE_TARNAME
119 #undef PACKAGE_VERSION
120 #include <config.h>
121 #else
122 // Define the version for (windows) compilers that don't use autoconf
123 #define PACKAGE_VERSION "2.0"
124 #endif
126 // Header for multithreading
127 #if defined(MT)
128 #if defined(HAVE_PTHREAD_H)
129 #include <pthread.h>
130 #elif defined(WIN32)
131 #define WIN32_LEAN_AND_MEAN
132 #include <windows.h>
133 #include <process.h>
134 #else
135 #error Multithreading not supported on your platform
136 #endif
137 #endif
139 // For the disabled and ansi-challenged people...
140 #ifndef DOXYGEN
141 #ifndef HAVE_STRNCASECMP
142 # ifdef _MSC_VER
143 # define strncasecmp _strnicmp
144 # else
145 # ifdef HAVE_STRNICMP
146 # define strncasecmp(s1,s2,n) strnicmp(s1,s2,n)
147 # else
148  // Last resort. Force it through...
149 # define strncasecmp(s1,s2,n) strnuppercmp(s1,s2,n)
150 # endif
151 # endif
152 #endif
153 #endif
155 /** @def ROUNDING_ERROR
156  * This constant defines the magnitude of what can still be considered
157  * as a rounding error.
158  */
159 #define ROUNDING_ERROR 0.000001
161 // Header files for the Xerces-c XML parser.
162 #ifndef DOXYGEN
163 #define XERCES_STATIC_LIBRARY
164 #include <xercesc/util/PlatformUtils.hpp>
165 #include <xercesc/sax2/SAX2XMLReader.hpp>
166 #include <xercesc/sax2/Attributes.hpp>
167 #include <xercesc/sax2/DefaultHandler.hpp>
168 #include <xercesc/framework/MemBufInputSource.hpp>
169 #include <xercesc/sax2/XMLReaderFactory.hpp>
170 #include <xercesc/util/XMLUni.hpp>
171 #include <xercesc/framework/MemBufInputSource.hpp>
172 #include <xercesc/framework/LocalFileInputSource.hpp>
173 #include <xercesc/framework/StdInInputSource.hpp>
174 #include <xercesc/framework/URLInputSource.hpp>
175 #include <xercesc/util/XMLException.hpp>
176 #endif
177 
178 /** @def DECLARE_EXPORT
179  * Used to define which symbols to export from a Windows DLL.
180  * @def MODULE_EXPORT
181  * Signature used for a module initialization routine. It assures the
182  * function is exported appropriately when running on Windows.<br>
183  * A module will need to define a function with the following prototype:
184  * @code
185  * MODULE_EXPORT string initialize(const CommandLoadLibrary::ParameterList&);
186  * @endcode
187  */
188 #undef DECLARE_EXPORT
189 #undef MODULE_EXPORT
190 #if defined(WIN32) && !defined(DOXYGEN)
191  #ifdef FREPPLE_CORE
192  #define DECLARE_EXPORT __declspec (dllexport)
193  #else
194  #define DECLARE_EXPORT __declspec (dllimport)
195  #endif
196  #define MODULE_EXPORT extern "C" __declspec (dllexport)
197 #else
198  #define DECLARE_EXPORT
199  #define MODULE_EXPORT extern "C"
200 #endif
201 
202 
203 namespace frepple
204 {
205 
206 // Forward declarations
207 class CommandMoveOperationPlan;
208 
209 namespace utils
210 {
211 
212 // Forward declarations
213 class Object;
214 class Keyword;
215 class XMLInput;
216 class AttributeList;
217 
218 // Include the list of predefined tags
219 #include "frepple/tags.h"
220 
221 
222 /** This type defines what operation we want to do with the entity. */
223 enum Action
224 {
225  /** or A.<br>
226  * Add an new entity, and report an error if the entity already exists. */
227  ADD = 0,
228  /** or C.<br>
229  * Change an existing entity, and report an error if the entity doesn't
230  * exist yet. */
231  CHANGE = 1,
232  /** or D.<br>
233  * Delete an entity, and report an error if the entity doesn't exist. */
234  REMOVE = 2,
235  /** or AC.<br>
236  * Change an entity or create a new one if it doesn't exist yet.<br>
237  * This is the default action.
238  */
240 };
241 
242 
243 /** Writes an action description to an output stream. */
244 inline ostream & operator << (ostream & os, const Action & d)
245 {
246  switch (d)
247  {
248  case ADD: os << "ADD"; return os;
249  case CHANGE: os << "CHANGE"; return os;
250  case REMOVE: os << "REMOVE"; return os;
251  case ADD_CHANGE: os << "ADD_CHANGE"; return os;
252  default: assert(false); return os;
253  }
254 }
255 
256 
257 /** This type defines the types of callback events possible. */
258 enum Signal
259 {
260  /** Adding a new entity. */
261  SIG_ADD = 0,
262  /** Deleting an entity. */
264 };
265 
266 
267 /** Writes a signal description to an output stream. */
268 inline ostream & operator << (ostream & os, const Signal & d)
269 {
270  switch (d)
271  {
272  case SIG_ADD: os << "ADD"; return os;
273  case SIG_REMOVE: os << "REMOVE"; return os;
274  default: assert(false); return os;
275  }
276 }
277 
278 
279 /** This is the datatype used for hashing an XML-element to a numeric value. */
280 typedef unsigned int hashtype;
281 
282 /** This stream is the general output for all logging and debugging messages. */
283 extern DECLARE_EXPORT ostream logger;
284 
285 /** Auxilary structure for easy indenting in the log stream. */
286 struct indent
287 {
288  short level;
289  indent(short l) : level(l) {}
290  indent operator() (short l) {return indent(l);}
291 };
292 
293 /** Print a number of spaces to the output stream. */
294 inline ostream& operator <<(ostream &os, const indent& i)
295 {
296  for (short c = i.level; c>0; --c) os << ' ';
297  return os;
298 }
299 
300 
301 
302 //
303 // CUSTOM EXCEPTION CLASSES
304 //
305 
306 
307 /** @brief An exception of this type is thrown when data errors are found.
308  *
309  * The normal handling of this error is to catch the exception and
310  * continue execution of the rest of the program.<br>
311  * When a DataException is thrown the object is expected to remain in
312  * valid and consistent state.
313  */
314 class DataException : public logic_error
315 {
316  public:
317  DataException(const char * c) : logic_error(c) {}
318  DataException(const string s) : logic_error(s) {}
319 };
320 
321 
322 /** @brief An exception of this type is thrown when the library gets in an
323  * inconsistent state from which the normal course of action can't continue.
324  *
325  * The normal handling of this error is to exit the program, and report the
326  * problem. This exception indicates a bug in the program code.
327  */
328 class LogicException: public logic_error
329 {
330  public:
331  LogicException(const char * c) : logic_error(c) {}
332  LogicException(const string s) : logic_error(s) {}
333 };
334 
335 
336 /** @brief An exception of this type is thrown when the library runs into
337  * problems that are specific at runtime. <br>
338  * These could either be memory problems, threading problems, file system
339  * problems, etc...
340  *
341  * Errors of this type can be caught by the client applications and the
342  * application can continue in most cases.<br>
343  * This exception shouldn't be used for issueing warnings. Warnings should
344  * simply be logged in the logfile and actions continue in some default way.
345  */
346 class RuntimeException: public runtime_error
347 {
348  public:
349  RuntimeException(const char * c) : runtime_error(c) {}
350  RuntimeException(const string s) : runtime_error(s) {}
351 };
352 
353 
354 /** @brief Python exception class matching with frepple::LogicException. */
355 extern DECLARE_EXPORT PyObject* PythonLogicException;
356 
357 /** @brief Python exception class matching with frepple::DataException. */
358 extern DECLARE_EXPORT PyObject* PythonDataException;
359 
360 /** @brief Python exception class matching with frepple::RuntimeException. */
361 extern DECLARE_EXPORT PyObject* PythonRuntimeException;
362 
363 
364 //
365 // UTILITY CLASS "NON-COPYABLE"
366 //
367 
368 /** @brief Class NonCopyable is a base class.<br>Derive your own class from
369  * it when you want to prohibit copy construction and copy assignment.
370  *
371  * Some objects, particularly those which hold complex resources like files
372  * or network connections, have no sensible copy semantics. Sometimes there
373  * are possible copy semantics, but these would be of very limited usefulness
374  * and be very difficult to implement correctly. Sometimes you're implementing
375  * a class that doesn't need to be copied just yet and you don't want to
376  * take the time to write the appropriate functions. Deriving from
377  * noncopyable will prevent the otherwise implicitly-generated functions
378  * (which don't have the proper semantics) from becoming a trap for other
379  * programmers.<br>
380  * The traditional way to deal with these is to declare a private copy
381  * constructor and copy assignment, and then document why this is done. But
382  * deriving from NonCopyable is simpler and clearer, and doesn't require
383  * additional documentation.
384  */
386 {
387  protected:
390 
391  private:
392  /** This copy constructor isn't implemented.<br>
393  * It's here just so we can declare them as private so that this, and
394  * any derived class, do not have copy constructors.
395  */
396  NonCopyable(const NonCopyable&);
397 
398  /** This assignment operator isn't implemented.<br>
399  * It's here just so we can declare them as private so that this, and
400  * any derived class, do not have copy constructors.
401  */
402  NonCopyable& operator=(const NonCopyable&);
403 };
404 
405 
406 /** @brief This class is used to maintain the Python interpreter.
407  *
408  * A single interpreter is used throughout the lifetime of the
409  * application.<br>
410  * The implementation is implemented in a thread-safe way (within the
411  * limitations of the Python threading model, of course).
412  *
413  * During the initialization the code checks for a file 'init.py' in its
414  * search path and, if it does exist, the statements in the file will be
415  * executed. In this way a library of globally available functions
416  * can easily be initialized.
417  *
418  * The stderr and stdout streams of Python are redirected by default to
419  * the frePPLe log stream.
420  *
421  * The following frePPLe functions are available from within Python.<br>
422  * All of these are in the module called frePPLe.
423  * - The following <b>classes</b> and their attributes are accessible for
424  * reading and writing.<br>
425  * Each object has a toXML() method that returns its XML representation
426  * as a string, or writes it to a file is a file is passed as argument.
427  * - buffer
428  * - buffer_default
429  * - buffer_infinite
430  * - buffer_procure
431  * - calendar
432  * - addBucket(integer identifier)
433  * - events()
434  * - calendarBucket
435  * - calendar_boolean
436  * - calendar_double
437  * - calendar_void
438  * - customer
439  * - customer_default
440  * - demand
441  * - demand_default
442  * - flow
443  * - flowplan
444  * - item
445  * - item_default
446  * - load
447  * - loadplan
448  * - location
449  * - location_default
450  * - operation
451  * - operation_alternate
452  * - addAlternate(operation=x, priority=y, effective_start=z1, effective_end=z2)
453  * - operation_fixed_time
454  * - operation_routing
455  * - addStep(tuple of operations)
456  * - operation_time_per
457  * - operationplan
458  * - parameters
459  * - problem (read-only)
460  * - resource
461  * - plan(list of dates to define the time periods)
462  * - resource_default
463  * - resource_infinite
464  * - setup_matrix
465  * - setup_matrix_default
466  * - solver
467  * - solve()
468  * - solver_mrp
469  * - commit()
470  * - rollback()
471  * - The following functions or attributes return <b>iterators</b> over the
472  * frePPLe objects:<br>
473  * - buffers()
474  * - buffer.members
475  * - buffer.flows
476  * - buffer.flowplans
477  * - calendar.buckets
478  * - calendars()
479  * - customers()
480  * - customer.members
481  * - demands()
482  * - demand.operationplans
483  * - demand.pegging
484  * - demand.members
485  * - operation.flows
486  * - operation.loads
487  * - items()
488  * - item.members
489  * - locations()
490  * - location.members
491  * - operations()
492  * - operation.operationplans
493  * - problems()
494  * - resources()
495  * - resource.members
496  * - resource.loads
497  * - resource.loadplans
498  * - setup_matrices()
499  * - solvers()
500  * - <b>printsize()</b>:<br>
501  * Prints information about the memory consumption.
502  * - <b>loadmodule(string [,parameter=value, ...])</b>:<br>
503  * Dynamically load a module in memory.
504  * - <b>readXMLdata(string [,bool] [,bool])</b>:<br>
505  * Processes an XML string passed as argument.
506  * - <b>log(string)</b>:<br>
507  * Prints a string to the frePPLe log file.<br>
508  * This is used for redirecting the stdout and stderr of Python.
509  * - <b>readXMLfile(string [,bool] [,bool])</b>:<br>
510  * Read an XML-file.
511  * - <b>saveXMLfile(string)</b>:<br>
512  * Save the model to an XML-file.
513  * - <b>saveplan(string)</b>:<br>
514  * Save the main plan information to a file.
515  * - <b>erase(boolean)</b>:<br>
516  * Erase the model (arg true) or only the plan (arg false, default).
517  * - <b>version</b>:<br>
518  * A string variable with the version number.
519  *
520  * The technical implementation is inspired by and inherited from the following
521  * article: "Embedding Python in Multi-Threaded C/C++ Applications", see
522  * http://www.linuxjournal.com/article/3641
523  */
525 {
526  public:
527  /** Initializes the interpreter. */
528  static DECLARE_EXPORT void initialize(int argc, char** argv);
529 
530  /** Finalizes the interpreter. */
531  static DECLARE_EXPORT void finalize();
532 
533  /** Execute some python code. */
534  static DECLARE_EXPORT void execute(const char*);
535 
536  /** Execute a file with Python code. */
537  static DECLARE_EXPORT void executeFile(string);
538 
539  /** Register a new method to Python.<br>
540  * Arguments:
541  * - The name of the built-in function/method
542  * - The function that implements it.
543  * - Combination of METH_* flags, which mostly describe the args
544  * expected by the C func.
545  * - The __doc__ attribute, or NULL.
546  */
547  static DECLARE_EXPORT void registerGlobalMethod(
548  const char*, PyCFunction, int, const char*, bool = true
549  );
550 
551  /** Register a new method to Python. */
552  static DECLARE_EXPORT void registerGlobalMethod
553  (const char*, PyCFunctionWithKeywords, int, const char*, bool = true);
554 
555  /** Return a pointer to the main extension module. */
556  static PyObject* getModule() {return module;}
557 
558  /** Return the preferred encoding of the Python interpreter. */
559  static DECLARE_EXPORT const char* getPythonEncoding();
560 
561  /** Create a new Python thread state.<br>
562  * Each OS-level thread needs to initialize a Python thread state as well.
563  * When a new thread is created in the OS, this method should be called
564  * to create a Python thread state as well.<br>
565  * See the Python PyGILState_Ensure API.
566  */
567  static DECLARE_EXPORT void addThread();
568 
569  /** Delete a Python thread state.<br>
570  * Each OS-level thread has a Python thread state.
571  * When an OS thread is deleted, this method should be called
572  * to delete the Python thread state as well.<br>
573  * See the Python PyGILState_Release API.
574  */
575  static DECLARE_EXPORT void deleteThread();
576 
577  private:
578  /** A pointer to the frePPLe extension module. */
579  static DECLARE_EXPORT PyObject *module;
580 
581  /** Python API: Used for redirecting the Python output to the same file
582  * as the application.
583  */
584  static DECLARE_EXPORT PyObject *python_log(PyObject*, PyObject*);
585 
586  /** Python unicode strings are encoded to this locale when bringing them into
587  * frePPLe.<br>
588  */
589  static DECLARE_EXPORT string encoding;
590 
591  /** Main thread info. */
592  static DECLARE_EXPORT PyThreadState* mainThreadState;
593 };
594 
595 
596 /** A utility function to do wildcard matching in strings.<br>
597  * The function recognizes two wildcard characaters:
598  * - ?: matches any single character
599  * - *: matches any sequence of characters
600  *
601  * The code is written by Jack Handy (jakkhandy@hotmail.com) and published
602  * on http://www.codeproject.com/KB/string/wildcmp.aspx. No specific license
603  * constraints apply on using the code.
604  */
605 DECLARE_EXPORT bool matchWildcard(const char*, const char*);
606 
607 
608 //
609 // METADATA AND OBJECT FACTORY
610 //
611 
612 /** @brief This class defines a keyword for the frePPLe data model.
613  *
614  * The keywords are used to define the attribute names for the objects.<br>
615  * They are used as:
616  * - Element and attribute names in XML documents
617  * - Attribute names in the Python extension.
618  *
619  * Special for this class is the requirement to have a "perfect" hash
620  * function, i.e. a function that returns a distinct number for each
621  * defined tag. The class prints a warning message when the hash
622  * function doesn't satisfy this criterion.
623  */
624 class Keyword : public NonCopyable
625 {
626  private:
627  /** Stores the hash value of this tag. */
628  hashtype dw;
629 
630  /** Store different preprocessed variations of the name of the tag.
631  * These are all stored in memory for improved performance. */
632  string strName, strStartElement, strEndElement, strElement, strAttribute;
633 
634  /** Name of the string transcoded to its Xerces-internal representation. */
635  XMLCh* xmlname;
636 
637  /** A function to verify the uniquess of our hashes. */
638  void check();
639 
640  public:
641  /** Container for maintaining a list of all tags. */
642  typedef map<hashtype,Keyword*> tagtable;
643 
644  /** This is the constructor.<br>
645  * The tag doesn't belong to an XML namespace. */
646  DECLARE_EXPORT Keyword(const string&);
647 
648  /** This is the constructor. The tag belongs to the XML namespace passed
649  * as second argument.<br>
650  * Note that we still require the first argument to be unique, since it
651  * is used as a keyword for the Python extensions.
652  */
653  DECLARE_EXPORT Keyword(const string&, const string&);
654 
655  /** Destructor. */
657 
658  /** Returns the hash value of the tag. */
659  hashtype getHash() const {return dw;}
660 
661  /** Returns the name of the tag. */
662  const string& getName() const {return strName;}
663 
664  /** Returns a pointer to an array of XML characters. This format is used
665  * by Xerces for the internal representation of character strings. */
666  const XMLCh* getXMLCharacters() const {return xmlname;}
667 
668  /** Returns a string to start an XML element with this tag: <TAG */
669  const string& stringStartElement() const {return strStartElement;}
670 
671  /** Returns a string to end an XML element with this tag: </TAG> */
672  const string& stringEndElement() const {return strEndElement;}
673 
674  /** Returns a string to start an XML element with this tag: <TAG> */
675  const string& stringElement() const {return strElement;}
676 
677  /** Returns a string to start an XML attribute with this tag: TAG=" */
678  const string& stringAttribute() const {return strAttribute;}
679 
680  /** This is the hash function. See the note on the perfectness of
681  * this function at the start. This function should be as simple
682  * as possible while still garantueeing the perfectness.<br>
683  * The hash function is based on the Xerces-C implementation,
684  * with the difference that the hash calculated by our function is
685  * portable between platforms.<br>
686  * The hash modulus is 954991 (which is the biggest prime number
687  * lower than 1000000).
688  */
689  static DECLARE_EXPORT hashtype hash(const char*);
690 
691  /** This is the hash function.
692  * @see hash(const char*)
693  */
694  static hashtype hash(const string& c) {return hash(c.c_str());}
695 
696  /** This is the hash function taken an XML character string as input.<br>
697  * The function is expected to return exactly the same result as when a
698  * character pointer is passed as argument.
699  * @see hash(const char*)
700  */
701  static DECLARE_EXPORT hashtype hash(const XMLCh*);
702 
703  /** Finds a tag when passed a certain string. If no tag exists yet, it
704  * will be created. */
705  static DECLARE_EXPORT const Keyword& find(const char*);
706 
707  /** Return a reference to a table with all defined tags. */
708  static DECLARE_EXPORT tagtable& getTags();
709 
710  /** Prints a list of all tags that have been defined. This can be useful
711  * for debugging and also for creating a good hashing function.<br>
712  * GNU gperf is a program that can generate a perfect hash function for
713  * a given set of symbols.
714  */
715  static DECLARE_EXPORT void printTags();
716 };
717 
718 
719 /** @brief This abstract class is the base class used for callbacks.
720  * @see MetaClass::callback
721  * @see FunctorStatic
722  * @see FunctorInstance
723  */
724 class Functor : public NonCopyable
725 {
726  public:
727  /** This is the callback method.<br>
728  * The return value should be true in case the action is allowed to
729  * happen. In case a subscriber disapproves the action false is
730  * returned.<br>
731  * It is important that the callback methods are implemented in a
732  * thread-safe and re-entrant way!!!
733  */
734  virtual bool callback(Object* v, const Signal a) const = 0;
735 
736  /** Destructor. */
737  virtual ~Functor() {}
738 };
739 
740 
741 // The following handler functions redirect the call from Python onto a
742 // matching virtual function in a PythonExtensionBase subclass.
743 extern "C"
744 {
745  /** Handler function called from Python. Internal use only. */
746  DECLARE_EXPORT PyObject* getattro_handler (PyObject*, PyObject*);
747  /** Handler function called from Python. Internal use only. */
748  DECLARE_EXPORT int setattro_handler (PyObject*, PyObject*, PyObject*);
749  /** Handler function called from Python. Internal use only. */
750  DECLARE_EXPORT int compare_handler (PyObject*, PyObject*);
751  /** Handler function called from Python. Internal use only. */
752  DECLARE_EXPORT PyObject* iternext_handler (PyObject*);
753  /** Handler function called from Python. Internal use only. */
754  DECLARE_EXPORT PyObject* call_handler(PyObject*, PyObject*, PyObject*);
755  /** Handler function called from Python. Internal use only. */
756  DECLARE_EXPORT PyObject* str_handler(PyObject*);
757 }
758 
759 
760 /** @brief This class is a thin wrapper around the type information in Python.
761  *
762  * This class defines a number of convenience functions to interact with the
763  * PyTypeObject struct of the Python C API.
764  */
765 class PythonType : public NonCopyable
766 {
767  private:
768  /** This static variable is a template for cloning type definitions.<br>
769  * It is copied for each type object we create.
770  */
771  static const PyTypeObject PyTypeObjectTemplate;
772 
773  /** Incremental size of the method table.<br>
774  * We allocate memory for the method definitions per block, not
775  * one-by-one.
776  */
777  static const unsigned short methodArraySize = 5;
778 
779  /** The Python type object which this class is wrapping. */
780  PyTypeObject* table;
781 
782  public:
783  /** A static function that evaluates an exception and sets the Python
784  * error string properly.<br>
785  * This function should only be called from within a catch-block, since
786  * internally it rethrows the exception!
787  */
788  static DECLARE_EXPORT void evalException();
789 
790  /** Constructor, sets the tp_base_size member. */
791  DECLARE_EXPORT PythonType(size_t, const type_info*);
792 
793  /** Return a pointer to the actual Python PyTypeObject. */
794  PyTypeObject* type_object() const {return table;}
795 
796  /** Add a new method. */
797  DECLARE_EXPORT void addMethod(const char*, PyCFunction, int, const char*);
798 
799  /** Add a new method. */
800  DECLARE_EXPORT void addMethod(const char*, PyCFunctionWithKeywords, int, const char*);
801 
802  /** Updates tp_name. */
803  void setName (const string n)
804  {
805  string *name = new string("frepple." + n);
806  table->tp_name = const_cast<char*>(name->c_str());
807  }
808 
809  /** Updates tp_doc. */
810  void setDoc (const string n)
811  {
812  string *doc = new string(n);
813  table->tp_doc = const_cast<char*>(doc->c_str());
814  }
815 
816  /** Updates tp_base. */
817  void setBase(PyTypeObject* b)
818  {
819  table->tp_base = b;
820  }
821 
822  /** Updates the deallocator. */
823  void supportdealloc(void (*f)(PyObject*))
824  {
825  table->tp_dealloc = f;
826  }
827 
828  /** Updates tp_getattro.<br>
829  * The extension class will need to define a member function with this
830  * prototype:<br>
831  * PythonObject getattro(const XMLElement& name)
832  */
833  void supportgetattro()
834  {table->tp_getattro = getattro_handler;}
835 
836  /** Updates tp_setattro.<br>
837  * The extension class will need to define a member function with this
838  * prototype:<br>
839  * int setattro(const Attribute& attr, const PythonObject& field)
840  */
841  void supportsetattro()
842  {table->tp_setattro = setattro_handler;}
843 
844  /** Updates tp_compare.<br>
845  * The extension class will need to define a member function with this
846  * prototype:<br>
847  * int compare(const PyObject* other) const
848  */
849  void supportcompare()
850  {table->tp_compare = compare_handler;}
851 
852  /** Updates tp_iter and tp_iternext.<br>
853  * The extension class will need to define a member function with this
854  * prototype:<br>
855  * PyObject* iternext()
856  */
857  void supportiter()
858  {
859  table->tp_iter = PyObject_SelfIter;
860  table->tp_iternext = iternext_handler;
861  }
862 
863  /** Updates tp_call.<br>
864  * The extension class will need to define a member function with this
865  * prototype:<br>
866  * PyObject* call(const PythonObject& args, const PythonObject& kwds)
867  */
868  void supportcall()
869  {table->tp_call = call_handler;}
870 
871  /** Updates tp_str.<br>
872  * The extension class will need to define a member function with this
873  * prototype:<br>
874  * PyObject* str()
875  */
876  void supportstr()
877  {table->tp_str = str_handler;}
878 
879  /** Type definition for create functions. */
880  typedef PyObject* (*createfunc)(PyTypeObject*, PyObject*, PyObject*);
881 
882  /** Updates tp_new with the function passed as argument. */
883  void supportcreate(createfunc c) {table->tp_new = c;}
884 
885  /** This method needs to be called after the type information has all
886  * been updated. It adds the type to the frepple module. */
887  DECLARE_EXPORT int typeReady();
888 
889  /** Comparison operator. */
890  bool operator == (const PythonType& i) const
891  {
892  return *cppClass == *(i.cppClass);
893  }
894 
895  /** Comparison operator. */
896  bool operator == (const type_info& i) const
897  {
898  return *cppClass == i;
899  }
900 
901  /** Type info of the registering class. */
902  const type_info* cppClass;
903 };
904 
905 
906 class MetaCategory;
907 /** @brief This class stores metadata about the classes in the library.
908  * The stored information goes well beyond the standard 'type_info'.
909  *
910  * A MetaClass instance represents metadata for a specific instance type.
911  * A MetaCategory instance represents metadata for a category of object.
912  * For instance, 'Resource' is a category while 'ResourceDefault' and
913  * 'ResourceInfinite' are specific classes.<br>
914  * The metadata class also maintains subscriptions to certain events.
915  * Registered classes and objects will receive callbacks when objects are
916  * being created, changed or deleted.<br>
917  * The proper usage is to include the following code snippet in every
918  * class:<br>
919  * @code
920  * In the header file:
921  * class X : public Object
922  * {
923  * public:
924  * virtual const MetaClass& getType() {return *metadata;}
925  * static const MetaClass *metadata;
926  * }
927  * In the implementation file:
928  * const MetaClass *X::metadata;
929  * @endcode
930  * Creating a MetaClass object isn't sufficient. It needs to be registered,
931  * typically in an initialization method:
932  * @code
933  * void initialize()
934  * {
935  * ...
936  * Y::metadata = new MetaCategory("Y","Ys", reader_method, writer_method);
937  * X::metadata = new MetaClass("Y","X", factory_method);
938  * ...
939  * }
940  * @endcode
941  * @see MetaCategory
942  */
943 class MetaClass : public NonCopyable
944 {
945  friend class MetaCategory;
946  template <class T, class U> friend class FunctorStatic;
947  template <class T, class U> friend class FunctorInstance;
948 
949  public:
950  /** Type definition for a factory method calling the default
951  * constructor.. */
952  typedef Object* (*creatorDefault)();
953 
954  /** Type definition for a factory method calling the constructor that
955  * takes a string as argument. */
956  typedef Object* (*creatorString)(const string&);
957 
958  /** A string specifying the object type, i.e. the subclass within the
959  * category. */
960  string type;
961 
962  /** A reference to an Keyword of the base string. */
963  const Keyword* typetag;
964 
965  /** The category of this class. */
967 
968  /** A pointer to the Python type. */
969  PyTypeObject* pythonClass;
970 
971  /** A factory method for the registered class. */
972  union
973  {
974  creatorDefault factoryMethodDefault;
975  creatorString factoryMethodString;
976  };
977 
978  /** Destructor. */
979  virtual ~MetaClass() {}
980 
981  /** Initialize the data structure and register the class. */
982  DECLARE_EXPORT void registerClass(const string&, const string&,
983  bool = false, creatorDefault = NULL);
984 
985  /** This constructor registers the metadata of a class. */
986  MetaClass (const string& cat, const string& cls, bool def = false)
987  : pythonClass(NULL)
988  {
989  registerClass(cat,cls,def);
990  }
991 
992  /** This constructor registers the metadata of a class, with a factory
993  * method that uses the default constructor of the class. */
994  MetaClass (const string& cat, const string& cls, creatorDefault f,
995  bool def = false) : pythonClass(NULL)
996  {
997  registerClass(cat,cls,def);
998  factoryMethodDefault = f;
999  }
1000 
1001  /** This constructor registers the metadata of a class, with a factory
1002  * method that uses a constructor with a string argument. */
1003  MetaClass (const string& cat, const string& cls, creatorString f,
1004  bool def = false) : pythonClass(NULL)
1005  {
1006  registerClass(cat,cls,def);
1007  factoryMethodString = f;
1008  }
1009 
1010  /** This function will analyze the string being passed, and return the
1011  * appropriate action.
1012  * The string is expected to be one of the following:
1013  * - 'A' for action ADD
1014  * - 'C' for action CHANGE
1015  * - 'AC' for action ADD_CHANGE
1016  * - 'R' for action REMOVE
1017  * - Any other value will result in a data exception
1018  */
1019  static DECLARE_EXPORT Action decodeAction(const char*);
1020 
1021  /** This method picks up the attribute named "ACTION" from the list and
1022  * calls the method decodeAction(const XML_Char*) to analyze it.
1023  * @see decodeAction(const XML_Char*)
1024  */
1025  static DECLARE_EXPORT Action decodeAction(const AttributeList&);
1026 
1027  /** Sort two metaclass objects. This is used to sort entities on their
1028  * type information in a stable and platform independent way.
1029  * @see operator !=
1030  * @see operator ==
1031  */
1032  bool operator < (const MetaClass& b) const
1033  {
1034  return typetag->getHash() < b.typetag->getHash();
1035  }
1036 
1037  /** Compare two metaclass objects. We are not always sure that only a
1038  * single instance of a metadata object exists in the system, and a
1039  * pointer comparison is therefore not appropriate.
1040  * @see operator !=
1041  * @see operator <
1042  */
1043  bool operator == (const MetaClass& b) const
1044  {
1045  return typetag->getHash() == b.typetag->getHash();
1046  }
1047 
1048  /** Compare two metaclass objects. We are not always sure that only a
1049  * single instance of a metadata object exists in the system, and a
1050  * pointer comparison is therefore not appropriate.
1051  * @see operator ==
1052  * @see operator <
1053  */
1054  bool operator != (const MetaClass& b) const
1055  {
1056  return typetag->getHash() != b.typetag->getHash();
1057  }
1058 
1059  /** This method should be called whenever objects of this class are being
1060  * created, updated or deleted. It will run the callback method of all
1061  * subscribers.<br>
1062  * If the function returns true, all callback methods approved of the
1063  * event. If false is returned, one of the callbacks disapproved it and
1064  * the event action should be allowed to execute.
1065  */
1066  DECLARE_EXPORT bool raiseEvent(Object* v, Signal a) const;
1067 
1068  /** Connect a new subscriber to the class. */
1069  void connect(Functor *c, Signal a) const
1070  {const_cast<MetaClass*>(this)->subscribers[a].push_front(c);}
1071 
1072  /** Disconnect a subscriber from the class. */
1073  void disconnect(Functor *c, Signal a) const
1074  {const_cast<MetaClass*>(this)->subscribers[a].remove(c);}
1075 
1076  /** Print all registered factory methods to the standard output for
1077  * debugging purposes. */
1078  static DECLARE_EXPORT void printClasses();
1079 
1080  /** Find a particular class by its name. If it can't be located the return
1081  * value is NULL. */
1082  static DECLARE_EXPORT const MetaClass* findClass(const char*);
1083 
1084  /** Default constructor. */
1085  MetaClass() : type("unspecified"), typetag(&Keyword::find("unspecified")),
1086  category(NULL), pythonClass(NULL), factoryMethodDefault(NULL) {}
1087 
1088  private:
1089  /** This is a list of objects that will receive a callback when the call
1090  * method is being used.<br>
1091  * There is limited error checking in maintaining this list, and it is the
1092  * user's responsability of calling the connect() and disconnect() methods
1093  * correctly.<br>
1094  * This design garantuees maximum performance, but assumes a properly
1095  * educated user.
1096  */
1097  list<Functor*> subscribers[4];
1098 };
1099 
1100 
1101 class XMLOutput;
1102 
1103 /** @brief This class stores metadata on a data field of a class.
1104  *
1105  * A field
1106  */
1107 //class MetaField : public NonCopyable
1108 //{
1109 // private:
1110 // Keyword& name;
1111 //
1112 // public:
1113 // typedef double (*getDouble)() const;
1114 // typedef void (*setDouble)(double);
1115 // typedef int (*getInt)() const;
1116 // typedef void (*setInt)(int);
1117 // typedef long (*getLong)() const;
1118 // typedef void (*setLong)(long);
1119 // typedef unsigned long (*getUnsignedLong)() const;
1120 // typedef void (*setUnsignedLong)(unsigned long);
1121 // typedef bool (*getBool)() const;
1122 // typedef void (*setBool)(int);
1123 // typedef bool (*getString)() const;
1124 // typedef void (*setString)(string);
1125 // typedef Date (*getDate)() const;
1126 // typedef void (*setDate)(Date);
1127 // typedef TimePeriod (*getTimePeriod)() const;
1128 // typedef void (*setTimePeriod)(TimePeriod);
1129 // /* Other types: list of things... */
1130 //
1131 // /** Constructor. */
1132 // MetaField(Keyword&, getDouble, setDouble);
1133 // MetaField(Keyword&, getInt, setInt);
1134 // MetaField(Keyword&, getBool, setBool);
1135 // MetaField(Keyword&, getString, setString );
1136 // template <class T> MetaField(Keyword&, T*(*getFunction)() const, void (*setFunction)(T*));
1137 //
1138 // bool get(Object*);
1139 // int get(Object*);
1140 // double get(Object*);
1141 // string get(Object*);
1142 //
1143 // void set(Object*, bool);
1144 // void set(Object*, int);
1145 // void set(Object*, double);
1146 // void set(Object*, string);
1147 //
1148 // /* for class MetaClass: */
1149 // void write(writer, object*);
1150 // void read(reader, Object*);
1151 //};
1152 
1153 
1154 /** @brief A MetaCategory instance represents metadata for a category of
1155  * object.
1156  *
1157  * A MetaClass instance represents metadata for a specific instance type.
1158  * For instance, 'Resource' is a category while 'ResourceDefault' and
1159  * 'ResourceInfinite' are specific classes.<br>
1160  * A category has the following specific pieces of data:
1161  * - A reader function for creating objects.<br>
1162  * The reader function creates objects for all classes registered with it.
1163  * - A writer function for persisting objects.<br>
1164  * The writer function will typically iterate over all objects of the
1165  * category and call the writeElement method on them.
1166  * - A group tag used for the grouping objects of the category in the XML
1167  * output stream.
1168  * @see MetaClass
1169  */
1170 class MetaCategory : public MetaClass
1171 {
1172  friend class MetaClass;
1173  template<class T> friend class HasName;
1174  public:
1175  /** The name used to name a collection of objects of this category. */
1176  string group;
1177 
1178  /** A XML tag grouping objects of the category. */
1180 
1181  /** Type definition for the read control function. */
1182  typedef Object* (*readController)(const MetaClass*, const AttributeList&);
1183 
1184  /** Type definition for the write control function. */
1185  typedef void (*writeController)(const MetaCategory*, XMLOutput *o);
1186 
1187  /** This template method is available as a object creation factory for
1188  * classes without key fields and which rely on a default constructor.
1189  */
1190  static Object* ControllerDefault (const MetaClass*, const AttributeList&);
1191 
1192  /** Destructor. */
1193  virtual ~MetaCategory() {}
1194 
1195  /** Constructor. */
1196  DECLARE_EXPORT MetaCategory (const string& t, const string& g,
1197  readController = NULL, writeController = NULL);
1198 
1199  /** Type definition for the map of all registered classes. */
1200  typedef map < hashtype, const MetaClass*, less<hashtype> > ClassMap;
1201 
1202  /** Type definition for the map of all categories. */
1203  typedef map < hashtype, const MetaCategory*, less<hashtype> > CategoryMap;
1204 
1205  /** Looks up a category name in the registry. If the catgory can't be
1206  * located the return value is NULL. */
1207  static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const char*);
1208 
1209  /** Looks up a category name in the registry. If the catgory can't be
1210  * located the return value is NULL. */
1211  static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const hashtype);
1212 
1213  /** Looks up a category name in the registry. If the catgory can't be
1214  * located the return value is NULL. */
1215  static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const char*);
1216 
1217  /** Looks up a category name in the registry. If the category can't be
1218  * located the return value is NULL. */
1219  static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const hashtype);
1220 
1221  /** Find a class in this category with a specified name.<br>
1222  * If the catrgory can't be found the return value is NULL.
1223  */
1224  DECLARE_EXPORT const MetaClass* findClass(const char*) const;
1225 
1226  /** Find a class in this category with a specified name.<br>
1227  * If the catrgory can't be found the return value is NULL.
1228  */
1229  DECLARE_EXPORT const MetaClass* findClass(const hashtype) const;
1230 
1231  /** This method takes care of the persistence of all categories. It loops
1232  * through all registered categories (in the order of their registration)
1233  * and calls the persistance handler.
1234  */
1235  static DECLARE_EXPORT void persist(XMLOutput *);
1236 
1237  /** A control function for reading objects of a category.
1238  * The controller function manages the creation and destruction of
1239  * objects in this category.
1240  */
1241  readController readFunction;
1242 
1243  private:
1244  /** A map of all classes registered for this category. */
1245  ClassMap classes;
1246 
1247  /** Compute the hash for "default" once and store it in this variable for
1248  * efficiency. */
1249  static DECLARE_EXPORT const hashtype defaultHash;
1250 
1251  /** This is the root for a linked list of all categories.
1252  * Categories are chained to the list in the order of their registration.
1253  */
1254  static DECLARE_EXPORT const MetaCategory* firstCategory;
1255 
1256  /** A pointer to the next category in the singly linked list. */
1257  const MetaCategory* nextCategory;
1258 
1259  /** A control function for writing the category.
1260  * The controller function will loop over the objects in the category and
1261  * call write them one by one.
1262  */
1263  writeController writeFunction;
1264 
1265  /** A map of all categories by their name. */
1266  static DECLARE_EXPORT CategoryMap categoriesByTag;
1267 
1268  /** A map of all categories by their group name. */
1269  static DECLARE_EXPORT CategoryMap categoriesByGroupTag;
1270 };
1271 
1272 
1273 /** @brief This class represents a static subscription to a signal.
1274  *
1275  * When the signal callback is triggered the static method callback() on the
1276  * parameter class will be called.
1277  */
1278 template <class T, class U> class FunctorStatic : public Functor
1279 {
1280  friend class MetaClass;
1281  public:
1282  /** Add a signal subscriber. */
1283  static void connect(const Signal a)
1284  {T::metadata->connect(new FunctorStatic<T,U>(), a);}
1285 
1286  /** Remove a signal subscriber. */
1287  static void disconnect(const Signal a)
1288  {
1289  MetaClass &t =
1290  const_cast<MetaClass&>(static_cast<const MetaClass&>(*T::metadata));
1291  // Loop through all subscriptions
1292  for (list<Functor*>::iterator i = t.subscribers[a].begin();
1293  i != t.subscribers[a].end(); ++i)
1294  {
1295  // Try casting the functor to the right type
1296  FunctorStatic<T,U> *f = dynamic_cast< FunctorStatic<T,U>* >(*i);
1297  if (f)
1298  {
1299  // Casting was successfull. Delete the functor.
1300  delete *i;
1301  t.subscribers[a].erase(i);
1302  return;
1303  }
1304  }
1305  // Not found in the list of subscriptions
1306  throw LogicException("Subscription doesn't exist");
1307  }
1308 
1309  private:
1310  /** This is the callback method. The functor will call the static callback
1311  * method of the subscribing class.
1312  */
1313  virtual bool callback(Object* v, const Signal a) const
1314  {return U::callback(static_cast<T*>(v),a);}
1315 };
1316 
1317 
1318 /** @brief This class represents an object subscribing to a signal.
1319  *
1320  * When the signal callback is triggered the method callback() on the
1321  * instance object will be called.
1322  */
1323 template <class T, class U> class FunctorInstance : public Functor
1324 {
1325  public:
1326  /** Connect a new subscriber to a signal.<br>
1327  * It is the users' responsibility to call the disconnect method
1328  * when the subscriber is being deleted. Otherwise the application
1329  * will crash.
1330  */
1331  static void connect(U* u, const Signal a)
1332  {if (u) T::metadata.connect(new FunctorInstance(u), a);}
1333 
1334  /** Disconnect from a signal. */
1335  static void disconnect(U *u, const Signal a)
1336  {
1337  MetaClass &t =
1338  const_cast<MetaClass&>(static_cast<const MetaClass&>(T::metadata));
1339  // Loop through all subscriptions
1340  for (list<Functor*>::iterator i = t.subscribers[a].begin();
1341  i != t.subscribers[a].end(); ++i)
1342  {
1343  // Try casting the functor to the right type
1344  FunctorInstance<T,U> *f = dynamic_cast< FunctorInstance<T,U>* >(*i);
1345  if (f && f->instance == u)
1346  {
1347  // Casting was successfull. Delete the functor.
1348  delete *i;
1349  t.subscribers[a].erase(i);
1350  return;
1351  }
1352  }
1353  // Not found in the list of subscriptions
1354  throw LogicException("Subscription doesn't exist");
1355  }
1356 
1357  /** Constructor. */
1358  FunctorInstance(U* u) : instance(u) {}
1359 
1360  private:
1361  /** This is the callback method. */
1362  virtual bool callback(Object* v, const Signal a) const
1363  {return instance ? instance->callback(static_cast<T*>(v),a) : true;}
1364 
1365  /** The object whose callback method will be called. */
1366  U* instance;
1367 };
1368 
1369 
1370 //
1371 // UTILITY CLASS "TIMER".
1372 //
1373 
1374 /** @brief This class is used to measure the processor time used by the
1375  * program.
1376  *
1377  * The accuracy of the timer is dependent on the implementation of the
1378  * ANSI C-function clock() by your compiler and your platform.
1379  * You may count on milli-second accuracy. Different platforms provide
1380  * more accurate timer functions, which can be used if the accuracy is a
1381  * prime objective.<br>
1382  * When compiled with Visual C++, the timer is returning the elapsed
1383  * time - which is not the expected ANSI behavior!<br>
1384  * Other compilers and platforms return the consumed cpu time, as expected.
1385  * When the load on a machine is low, the consumed cpu-time and the elapsed
1386  * time are close to each other. On a system with a higher load, the
1387  * elapsed time deviates a lot from the consumed cpu-time.
1388  */
1389 class Timer
1390 {
1391  public:
1392  /** Default constructor. Creating the timer object sets the start point
1393  * for the time measurement. */
1394  explicit Timer() : start_time(clock()) {}
1395 
1396  /** Reset the time counter to 0. */
1397  void restart() {start_time = clock();}
1398 
1399  /** Return the cpu-time in seconds consumed since the creation or the last
1400  * reset of the timer. */
1401  double elapsed() const {return double(clock()-start_time)/CLOCKS_PER_SEC;}
1402 
1403  private:
1404  /** Stores the time when the timer is started. */
1405  clock_t start_time;
1406 };
1407 
1408 
1409 /** Prints a timer to the outputstream. The output is formatted as a double. */
1410 inline ostream & operator << (ostream& os, const Timer& t)
1411 {
1412  return os << t.elapsed();
1413 }
1414 
1415 
1416 //
1417 // UTILITY CLASSES "DATE", "DATE_RANGE" AND "TIME".
1418 //
1419 
1420 
1421 /** @brief This class represents a time duration with an accuracy of
1422  * one second.
1423  *
1424  * The duration can be both positive and negative.
1425  */
1427 {
1428  friend ostream& operator << (ostream &, const TimePeriod &);
1429  public:
1430  /** Default constructor and constructor with timeperiod passed. */
1431  TimePeriod(const long l = 0) : lval(l) {}
1432 
1433  /** Constructor from a character string.<br>
1434  * See the parse() method for details on the format of the argument.
1435  */
1436  TimePeriod(const char* s) {parse(s);}
1437 
1438  /** Comparison between periods of time. */
1439  bool operator < (const long& b) const {return lval < b;}
1440 
1441  /** Comparison between periods of time. */
1442  bool operator > (const long& b) const {return lval > b;}
1443 
1444  /** Comparison between periods of time. */
1445  bool operator <= (const long& b) const {return lval <= b;}
1446 
1447  /** Comparison between periods of time. */
1448  bool operator >= (const long& b) const {return lval >= b;}
1449 
1450  /** Comparison between periods of time. */
1451  bool operator < (const TimePeriod& b) const {return lval < b.lval;}
1452 
1453  /** Comparison between periods of time. */
1454  bool operator > (const TimePeriod& b) const {return lval > b.lval;}
1455 
1456  /** Comparison between periods of time. */
1457  bool operator <= (const TimePeriod& b) const {return lval <= b.lval;}
1458 
1459  /** Comparison between periods of time. */
1460  bool operator >= (const TimePeriod& b) const {return lval >= b.lval;}
1461 
1462  /** Equality operator. */
1463  bool operator == (const TimePeriod& b) const {return lval == b.lval;}
1464 
1465  /** Inequality operator. */
1466  bool operator != (const TimePeriod& b) const {return lval != b.lval;}
1467 
1468  /** Increase the timeperiod. */
1469  void operator += (const TimePeriod& l) {lval += l.lval;}
1470 
1471  /** Decrease the timeperiod. */
1472  void operator -= (const TimePeriod& l) {lval -= l.lval;}
1473 
1474  /** Returns true of the duration is equal to 0. */
1475  bool operator ! () const {return lval == 0L;}
1476 
1477  /** This conversion operator creates a long value from a timeperiod. */
1478  operator long() const {return lval;}
1479 
1480  /** Converts the date to a string, formatted according to ISO 8601. */
1481  operator string() const
1482  {
1483  char str[20];
1484  toCharBuffer(str);
1485  return string(str);
1486  }
1487 
1488  /** Function that parses a input string to a time value.<br>
1489  * The string format is following the ISO 8601 specification for
1490  * durations: [-]P[nY][nM][nW][nD][T[nH][nM][nS]]<br>
1491  * Some examples to illustrate how the string is converted to a
1492  * timeperiod, expressed in seconds:<br>
1493  * P1Y = 1 year = 365 days = 31536000 seconds
1494  * P1M = 365/12 days = 2628000 seconds
1495  * P1W = 1 week = 7 days = 604800 seconds
1496  * -P1D = -1 day = -86400 seconds
1497  * PT1H = 1 hour = 3600 seconds
1498  * -PT1000000S = 1000000 seconds
1499  * P1M1WT1H = 1 month + 1 week + 1 hour = 3236400 seconds
1500  * It pretty strictly checks the spec, with a few exceptions:
1501  * - A week field ('W') may coexist with other units.
1502  * - Decimal values are not supported.
1503  * - The alternate format as a date and time is not supported.
1504  */
1505  DECLARE_EXPORT void parse(const char*);
1506 
1507  /** The maximum value for a timeperiod. */
1509 
1510  /** The minimum value for a timeperiod. */
1512 
1513  private:
1514  /** The time is stored as a number of seconds. */
1515  long lval;
1516 
1517  /** This function fills a character buffer with a text representation of
1518  * the TimePeriod.<br>
1519  * The character buffer passed MUST have room for at least 20 characters.
1520  * 20 characters is sufficient for even the most longest possible time
1521  * duration.<br>
1522  * The output format is described with the string() method.
1523  * @see string()
1524  */
1525  DECLARE_EXPORT void toCharBuffer(char*) const;
1526 };
1527 
1528 
1529 /** Prints a Timeperiod to the outputstream.
1530  * @see TimePeriod::string()
1531  */
1532 inline ostream & operator << (ostream & os, const TimePeriod & t)
1533 {
1534  char str[20];
1535  t.toCharBuffer(str);
1536  return os << str;
1537 }
1538 
1539 
1540 /** @brief This class represents a date and time with an accuracy of
1541  * one second. */
1542 class Date
1543 {
1544  friend ostream& operator << (ostream &, const Date &);
1545  private:
1546  /** This string is a format string to be used to convert a date to and
1547  * from a string format. The formats codes that are allowed are the
1548  * ones recognized by the standard C function strftime:
1549  * - %a short name of day
1550  * - %A full name of day
1551  * - %b short name of month
1552  * - %B full name of month
1553  * - %c standard string for Date and time
1554  * - %d day of month (between 1 and 31)
1555  * - %H hour (between 0 and 23)
1556  * - %I hour (between 1 and 12)
1557  * - %j day of the year (between 1 and 366)
1558  * - %m month as number (between 1 and 12)
1559  * - %M minutes (between 0 and 59)
1560  * - %p AM/PM
1561  * - %S seconds (between o and 59)
1562  * - %U week of the year (between 0 and 52, sunday as start of week)
1563  * - %w day of the week (between 0 and 6, sunday as start of week)
1564  * - %W week of the year (monday as first day of week)
1565  * - %x standard string for Date
1566  * - %X standard string for time
1567  * - %y year (between 0 and 99, without century)
1568  * - %Y year (complete)
1569  * - %Z time zone
1570  * - %% percentage sign
1571  * The default date format is %Y-%m-%dT%H:%M:%S, which is the standard
1572  * format defined in the XML Schema standard.
1573  */
1574  static DECLARE_EXPORT string format;
1575 
1576  /** The internal representation of a date is a single long value. */
1577  time_t lval;
1578 
1579  /** Checks whether we stay within the boundaries of finite Dates. */
1580  DECLARE_EXPORT void checkFinite(long long);
1581 
1582  /** A private constructor used to create the infinitePast and
1583  * infiniteFuture constants. */
1584  Date(const char* s, bool dummy) {parse(s);}
1585 
1586  /** A utility function that uses the C function localtime to compute the
1587  * details of the current time: day of the week, day of the month,
1588  * day of the year, hour, minutes, seconds
1589  */
1590  inline void getInfo(struct tm* tm_struct) const
1591  {
1592  // The standard library function localtime() is not re-entrant: the same
1593  // static structure is used for all calls. In a multi-threaded environment
1594  // the function is not to be used.
1595  // The POSIX standard defines a re-entrant version of the function:
1596  // localtime_r.
1597  // Visual C++ 6.0 and Borland 5.5 are missing it, but provide a thread-safe
1598  // variant without changing the function semantics.
1599  #ifdef HAVE_LOCALTIME_R
1600  localtime_r(&lval, tm_struct);
1601  #else
1602  *tm_struct = *localtime(&lval);
1603  #endif
1604  }
1605 
1606  public:
1607 
1608  /** Constructor initialized with a long value. */
1609  Date(const time_t l) : lval(l) {checkFinite(lval);}
1610 
1611  /** Default constructor. */
1612  // This constructor can skip the check for finite dates, and
1613  // thus gives the best performance.
1614  Date() : lval(infinitePast.lval) {}
1615 
1616  /* Note: the automatic copy constructor works fine and is faster than
1617  writing our own. */
1618 
1619  /** Constructor initialized with a string. The string needs to be in
1620  * the format specified by the "format". */
1621  Date(const char* s) {parse(s); checkFinite(lval);}
1622 
1623  /** Constructor with year, month and day as arguments. Hours, minutes
1624  * and seconds can optionally be passed too.
1625  */
1626  DECLARE_EXPORT Date(int year, int month, int day,
1627  int hr=0, int min=0, int sec=0
1628  );
1629 
1630  /** Comparison between dates. */
1631  bool operator < (const Date& b) const {return lval < b.lval;}
1632 
1633  /** Comparison between dates. */
1634  bool operator > (const Date& b) const {return lval > b.lval;}
1635 
1636  /** Equality of dates. */
1637  bool operator == (const Date& b) const {return lval == b.lval;}
1638 
1639  /** Inequality of dates. */
1640  bool operator != (const Date& b) const {return lval != b.lval;}
1641 
1642  /** Comparison between dates. */
1643  bool operator >= (const Date& b) const {return lval >= b.lval;}
1644 
1645  /** Comparison between dates. */
1646  bool operator <= (const Date& b) const {return lval <= b.lval;}
1647 
1648  /** Assignment operator. */
1649  void operator = (const Date& b) {lval = b.lval;}
1650 
1651  /** Adds some time to this date. */
1652  void operator += (const TimePeriod& l)
1653  {checkFinite(static_cast<long long>(l) + lval);}
1654 
1655  /** Subtracts some time to this date. */
1656  void operator -= (const TimePeriod& l)
1657  {checkFinite(- static_cast<long long>(l) + lval);}
1658 
1659  /** Adding a time to a date returns a new date. */
1660  Date operator + (const TimePeriod& l) const
1661  {
1662  Date d;
1663  d.checkFinite(static_cast<long long>(l) + lval);
1664  return d;
1665  }
1666 
1667  /** Subtracting a time from a date returns a new date. */
1668  Date operator - (const TimePeriod& l) const
1669  {
1670  Date d;
1671  d.checkFinite(- static_cast<long>(l) + lval);
1672  return d;
1673  }
1674 
1675  /** Subtracting two date values returns the time difference in a
1676  * TimePeriod object. */
1677  TimePeriod operator - (const Date& l) const
1678  {return static_cast<long>(lval - l.lval);}
1679 
1680  /** Check whether the date has been initialized. */
1681  bool operator ! () const {return lval == infinitePast.lval;}
1682 
1683  /** Check whether the date has been initialized. */
1684  operator bool() const {return lval != infinitePast.lval;}
1685 
1686  /** Static function returns a date object initialized with the current
1687  * Date and time. */
1688  static Date now() {return Date(time(0));}
1689 
1690  /** Converts the date to a string. The format can be controlled by the
1691  * setFormat() function. */
1692  operator string() const
1693  {
1694  char str[30];
1695  toCharBuffer(str);
1696  return string(str);
1697  }
1698 
1699  /** This function fills a character buffer with a text representation of
1700  * the date.<br>
1701  * The character buffer passed is expected to have room for
1702  * at least 30 characters. 30 characters should be sufficient for even
1703  * the most funky date format.
1704  */
1705  size_t toCharBuffer(char* str) const
1706  {
1707  struct tm t;
1708  getInfo(&t);
1709  return strftime(str, 30, format.c_str(), &t);
1710  }
1711 
1712  /** Return the seconds since the epoch, which is also the internal
1713  * representation of a date. */
1714  time_t getTicks() const {return lval;}
1715 
1716  /** Function that parses a string according to the format string. */
1717  DECLARE_EXPORT void parse(const char*, const string& = format);
1718 
1719  /** Updates the default date format. */
1720  static void setFormat(const string& n) {format = n;}
1721 
1722  /** Retrieves the default date format. */
1723  static string getFormat() {return format;}
1724 
1725  /** A constant representing the infinite past, i.e. the earliest time which
1726  * we can represent.<br>
1727  * This value is normally 1971-01-01T00:00:00.
1728  */
1730 
1731  /** A constant representing the infinite future, i.e. the latest time which
1732  * we can represent.<br>
1733  * This value is currently set to 2030-12-31T00:00:00.
1734  */
1736 
1737  /** Return the number of seconds since january 1st. */
1738  long getSecondsYear() const
1739  {
1740  struct tm t;
1741  getInfo(&t);
1742  return t.tm_yday * 86400 + t.tm_sec + t.tm_min * 60 + t.tm_hour * 3600;
1743  }
1744 
1745  /** Return the number of seconds since the start of the month. */
1746  long getSecondsMonth() const
1747  {
1748  struct tm t;
1749  getInfo(&t);
1750  return (t.tm_mday-1) * 86400 + t.tm_sec + t.tm_min * 60 + t.tm_hour * 3600;
1751  }
1752 
1753  /** Return the number of seconds since the start of the week.
1754  * The week is starting on Sunday.
1755  */
1756  long getSecondsWeek() const
1757  {
1758  struct tm t;
1759  getInfo(&t);
1760  int result = t.tm_wday * 86400 + t.tm_sec + t.tm_min * 60 + t.tm_hour * 3600;
1761  assert(result >= 0 && result < 604800L);
1762  return result;
1763  }
1764 
1765  /** Return the number of seconds since the start of the day. */
1766  long getSecondsDay() const
1767  {
1768  struct tm t;
1769  getInfo(&t);
1770  int result = t.tm_sec + t.tm_min * 60 + t.tm_hour * 3600;
1771  assert(result >= 0 && result < 86400L);
1772  return result;
1773  }
1774 
1775 #ifndef HAVE_STRPTIME
1776  private:
1777  DECLARE_EXPORT char* strptime(const char *, const char *, struct tm *);
1778 #endif
1779 };
1780 
1781 
1782 /** Prints a date to the outputstream. */
1783 inline ostream & operator << (ostream & os, const Date & d)
1784 {
1785  char str[30];
1786  d.toCharBuffer(str);
1787  return os << str;
1788 }
1789 
1790 
1791 /** @brief This class defines a date-range, i.e. a start-date and end-date pair.
1792  *
1793  * The behavior is such that the start date is considered as included in
1794  * it, but the end date is excluded from it.
1795  * In other words, a daterange is a halfopen date interval: [start,end[<br>
1796  * The start and end dates are always such that the start date is less than
1797  * or equal to the end date.
1798  */
1800 {
1801  public:
1802  /** Constructor with specified start and end dates.<br>
1803  * If the start date is later than the end date parameter, the
1804  * parameters will be swapped. */
1805  DateRange(const Date& st, const Date& nd) : start(st), end(nd)
1806  {if(st>nd) {start=nd; end=st;}}
1807 
1808  /** Default constructor.<br>
1809  * This will create a daterange covering the complete horizon.
1810  */
1811  DateRange() : start(Date::infinitePast), end(Date::infiniteFuture) {}
1812 
1813  /** Copy constructor. */
1814  DateRange(const DateRange& n) : start(n.start), end(n.end) {}
1815 
1816  /** Returns the start date. */
1817  const Date& getStart() const {return start;}
1818 
1819  /** Updates the start date.<br>
1820  * If the new start date is later than the end date, the end date will
1821  * be set equal to the new start date.
1822  */
1823  void setStart(const Date& d) {start=d; if(start>end) end=start;}
1824 
1825  /** Returns the end date. */
1826  const Date & getEnd() const {return end;}
1827 
1828  /** Updates the end date.<br>
1829  * If the new end date is earlier than the start date, the start date will
1830  * be set equal to the new end date.
1831  */
1832  void setEnd(const Date& d) {end=d; if(start>end) start=end;}
1833 
1834  /** Updates the start and end dates simultaneously. */
1835  void setStartAndEnd(const Date& st, const Date& nd)
1836  {if (st<nd) {start=st; end=nd;} else {start=nd; end=st;}}
1837 
1838  /** Returns the duration of the interval. Note that this number will always
1839  * be greater than or equal to 0, since the end date is always later than
1840  * the start date.
1841  */
1842  TimePeriod getDuration() const {return end - start;}
1843 
1844  /** Equality of date ranges. */
1845  bool operator == (const DateRange& b) const
1846  {return start==b.start && end==b.end;}
1847 
1848  /** Inequality of date ranges. */
1849  bool operator != (const DateRange& b) const
1850  {return start!=b.start || end!=b.end;}
1851 
1852  /** Move the daterange later in time. */
1853  void operator += (const TimePeriod& l) {start += l; end += l;}
1854 
1855  /** Move the daterange earlier in time. */
1856  void operator -= (const TimePeriod& l) {start -= l; end -= l;}
1857 
1858  /** Assignment operator. */
1859  void operator = (const DateRange& dr) {start = dr.start; end = dr.end;}
1860 
1861  /** Return true if two date ranges are overlapping.<br>
1862  * The start point of the first interval is included in the comparison,
1863  * whereas the end point isn't. As a result this method is not
1864  * symmetrical, ie when a.intersect(b) returns true b.intersect(a) is
1865  * not nessarily true.
1866  */
1867  bool intersect(const DateRange& dr) const
1868  {return dr.start<=end && dr.end>start;}
1869 
1870  /** Returns the number of seconds the two dateranges overlap. */
1871  TimePeriod overlap(const DateRange& dr) const
1872  {
1873  long x = (dr.end<end ? dr.end : end)
1874  - (dr.start>start ? dr.start : start);
1875  return x>0 ? x : 0;
1876  }
1877 
1878  /** Returns true if the date passed as argument does fall within the
1879  * daterange. */
1880  bool within(const Date& d) const {return d>=start && d<end;}
1881 
1882  /** Convert the daterange to a string. */
1883  DECLARE_EXPORT operator string() const;
1884 
1885  /** Updates the default seperator. */
1886  static void setSeparator(const string& n)
1887  {
1888  separator = n;
1889  separatorlength = n.size();
1890  }
1891 
1892  /** Retrieves the default seperator. */
1893  static const string& getSeparator() {return separator;}
1894 
1895  private:
1896  /** Start date of the interval. */
1897  Date start;
1898 
1899  /** End dat of the interval. */
1900  Date end;
1901 
1902  /** Separator to be used when printing this string. */
1903  static DECLARE_EXPORT string separator;
1904 
1905  /** Separator to be used when printing this string. */
1906  static DECLARE_EXPORT size_t separatorlength;
1907 };
1908 
1909 
1910 /** Prints a date range to the outputstream.
1911  * @see DateRange::string() */
1912 inline ostream & operator << (ostream & os, const DateRange & dr)
1913 {
1914  return os << dr.getStart() << DateRange::getSeparator() << dr.getEnd();
1915 }
1916 
1917 
1918 //
1919 // UTILITY CLASSES FOR INPUT AND OUTPUT
1920 //
1921 
1922 
1923 /** This type is used to define different ways of persisting an object. */
1924 enum mode
1925 {
1926  /** Write the full object or a reference. If the object is nested more
1927  * than one level deep a reference is written, otherwise the complete
1928  * object is written.<br>
1929  * This mode is the one to be used when dumping all objects to be restored
1930  * later. The other modes can dump too little or too much data.
1931  * Eg: <MODEL NAME="POL" TYPE="a"><FIELD>value</FIELD></MODEL>
1932  */
1933  DEFAULT = 0,
1934  /** Write only the key fields of the object.<br>
1935  * Eg: <MODEL NAME="POL" TYPE="a"/>
1936  */
1938  /** Write the full object, but without a header line. This method is
1939  * typically used when a subclass calls the write method of its parent
1940  * class.<br>
1941  * Eg: <FIELD>value</FIELD></MODEL>
1942  */
1944  /** Write the full object, with all its fields and a header line.<br>
1945  * Eg: <MODEL NAME="POL" TYPE="a"><FIELD>value</FIELD></MODEL>
1946  */
1947  FULL = 3
1948 };
1949 
1950 
1951 /** @ brief This utility class escapes special characters from a string.
1952  *
1953  * The following characters are replaced:
1954  * - &: replaced with &amp;
1955  * - <: replaced with &lt;
1956  * - >: replaced with &gt;
1957  * - ": replaced with &quot;
1958  * - ': replaced with &apos;
1959  * - all other characters are left unchanged
1960  * The reverse process of un-escaping the special character sequences is
1961  * taken care of by the Xerces library.
1962  *
1963  * This class works fine with UTF-8 and single-byte encodings, but will
1964  * NOT work with other multibyte encodings (such as UTF-116 or UTF-32).
1965  */
1967 {
1968  friend DECLARE_EXPORT ostream& operator << (ostream&, const XMLEscape&);
1969  private:
1970  const char* data;
1971  public:
1972  XMLEscape(const char* p) {data = p;}
1973  XMLEscape(const string& p) {data = p.c_str();}
1974 };
1975 
1976 
1977 /** Prints the escaped value of the string to the outputstream. */
1978 DECLARE_EXPORT ostream & operator << (ostream&, const XMLEscape&);
1979 
1980 
1981 /** @brief Base class for writing XML formatted data to an output stream.
1982  *
1983  * Subclasses implement writing to specific stream types, such as files
1984  * and strings.
1985  */
1987 {
1988  protected:
1989  /** Updating the output stream. */
1990  void setOutput(ostream& o) {m_fp = &o;}
1991 
1992  public:
1993  /** This type is used to define different types of output.
1994  * @see STANDARD
1995  * @see PLAN
1996  * @see PLANDETAIL
1997  */
1998  typedef unsigned short content_type;
1999 
2000  /** Constant used to mark standard export for the export.
2001  * The standard export saves just enough information to persist the full
2002  * state of the model as brief as possible.
2003  * @see PLAN
2004  * @see PLANDETAIL
2005  */
2007 
2008  /** Constant to mark an export of the standard information plus the plan
2009  * information. In this format, every entity is saved with the details
2010  * on how it is used in the plan.<br>
2011  * E.g. a resource will be saved with a reference to all its loadplans.
2012  * E.g. an operation will be saved with all its operationplans.
2013  * @see STANDARD
2014  * @see PLANDETAIL
2015  */
2017 
2018  /** Constant to mark an export of the lowest level of plan information.
2019  * In addition to the plan information pegging information is now saved.
2020  * @see STANDARD
2021  * @see PLAN
2022  */
2024 
2025  /** Returns which type of export is requested.
2026  * Constants have been defined for each type.
2027  * @see STANDARD
2028  * @see PLAN
2029  * @see PLANDETAIL
2030  */
2031  content_type getContentType() const {return content;}
2032 
2033  /** Specify the type of export.
2034  * @see STANDARD
2035  * @see PLAN
2036  * @see PLANDETAIL
2037  */
2038  void setContentType(content_type c) {content = c;}
2039 
2040  /** Updates the string that is printed as the first line of each XML
2041  * document.<br>
2042  * The default value is:
2043  * <?xml version="1.0" encoding="UTF-8"?>
2044  */
2045  void setHeaderStart(const string& s) {headerStart = s;}
2046 
2047  /** Returns the string that is printed as the first line of each XML
2048  * document. */
2049  string getHeaderStart() const {return headerStart;}
2050 
2051  /** Updates the attributes that are written for the root element of each
2052  * XML document.<br>
2053  * The default value is an empty string.
2054  */
2055  void setHeaderAtts(const string& s) {headerAtts = s;}
2056 
2057  /** Returns the attributes that are written for the root element of each
2058  * XML document. */
2059  string getHeaderAtts() const {return headerAtts;}
2060 
2061  /** Constructor with a given stream. */
2062  XMLOutput(ostream& os) : m_nIndent(0), numObjects(0),
2063  numParents(0), currentObject(NULL), parentObject(NULL), content(STANDARD),
2064  headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
2065  headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
2066  {m_fp = &os; indentstring[0] = '\0';}
2067 
2068  /** Default constructor. */
2069  XMLOutput() : m_nIndent(0), numObjects(0), numParents(0),
2070  currentObject(NULL), parentObject(NULL), content(STANDARD),
2071  headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
2072  headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
2073  {m_fp = &logger; indentstring[0] = '\0';}
2074 
2075  /** Force writing only references for nested objects. */
2076  void setReferencesOnly(bool b) {numParents = b ? 2 : 0;}
2077 
2078  /** Returns whether we write only references for nested objects or not. */
2079  bool getReferencesOnly() const {return numParents>0;}
2080 
2081  /** Start writing a new object. This method will open a new XML-tag.<br>
2082  * Output: <TAG>
2083  */
2084  void BeginObject(const Keyword& t)
2085  {
2086  *m_fp << indentstring << t.stringElement() << "\n";
2087  incIndent();
2088  }
2089 
2090  /** Start writing a new object. This method will open a new XML-tag.
2091  * Output: <TAG attributes>
2092  */
2093  void BeginObject(const Keyword& t, const string& atts)
2094  {
2095  *m_fp << indentstring << t.stringStartElement() << " " << atts << ">\n";
2096  incIndent();
2097  }
2098 
2099  /** Start writing a new object. This method will open a new XML-tag.<br>
2100  * The user is responsible to assure string values are escaped correctly with the XMLEscape class.<br>
2101  * Output: <TAG TAG1="val1">
2102  * @see XMLEscape
2103  */
2104  template <class T>
2105  void BeginObject(const Keyword& t, const Keyword& attr1, const T& val1)
2106  {
2107  *m_fp << indentstring << t.stringStartElement()
2108  << attr1.stringAttribute() << val1 << "\">\n";
2109  incIndent();
2110  }
2111 
2112  /** Start writing a new object. This method will open a new XML-tag.<br>
2113  * The user is responsible to assure string values are escaped correctly with the XMLEscape class.<br>
2114  * Output: <TAG TAG1="val1" TAG2="val2">
2115  * @see XMLEscape
2116  */
2117  template <class T, class U>
2118  void BeginObject(const Keyword& t, const Keyword& attr1, const T& val1,
2119  const Keyword& attr2, const U& val2)
2120  {
2121  *m_fp << indentstring << t.stringStartElement()
2122  << attr1.stringAttribute() << val1 << "\""
2123  << attr2.stringAttribute() << val2 << "\">\n";
2124  incIndent();
2125  }
2126 
2127  /** Start writing a new object. This method will open a new XML-tag.<br>
2128  * The user is responsible to assure string values are escaped correctly with the XMLEscape class.<br>
2129  * Output: <TAG TAG1="val1" TAG2="val2" TAG3="val3">
2130  * @see XMLEscape
2131  */
2132  template <class T, class U, class V>
2133  void BeginObject(const Keyword& t, const Keyword& attr1, const T& val1,
2134  const Keyword& attr2, const U& val2,
2135  const Keyword& attr3, const V& val3)
2136  {
2137  *m_fp << indentstring << t.stringStartElement()
2138  << attr1.stringAttribute() << val1 << "\""
2139  << attr2.stringAttribute() << val2 << "\""
2140  << attr3.stringAttribute() << val3 << "\">\n";
2141  incIndent();
2142  }
2143 
2144  /** Write the closing tag of this object and decrease the indentation
2145  * level.<br>
2146  * Output: </TAG_T>
2147  */
2148  void EndObject(const Keyword& t)
2149  {
2150  decIndent();
2151  *m_fp << indentstring << t.stringEndElement();
2152  }
2153 
2154  /** Write the string to the output. No XML-tags are added, so this method
2155  * is used for passing text straight into the output file. */
2156  void writeString(const string& c)
2157  {
2158  *m_fp << indentstring << c << "\n";
2159  }
2160 
2161  /** Write an unsigned long value enclosed opening and closing tags.<br>
2162  * Output: <TAG_T>uint</TAG_T> */
2163  void writeElement(const Keyword& t, const long unsigned int val)
2164  {
2165  *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
2166  }
2167 
2168  /** Write an integer value enclosed opening and closing tags.<br>
2169  * Output: <TAG_T>integer</TAG_T> */
2170  void writeElement(const Keyword& t, const int val)
2171  {
2172  *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
2173  }
2174 
2175  /** Write a double value enclosed opening and closing tags.<br>
2176  * Output: <TAG_T>double</TAG_T> */
2177  void writeElement(const Keyword& t, const double val)
2178  {
2179  *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
2180  }
2181 
2182  /** Write a boolean value enclosed opening and closing tags. The boolean
2183  * is written out as the string 'true' or 'false'.<br>
2184  * Output: <TAG_T>true</TAG_T>
2185  */
2186  void writeElement(const Keyword& t, const bool val)
2187  {
2188  *m_fp << indentstring << t.stringElement()
2189  << (val ? "true" : "false") << t.stringEndElement();
2190  }
2191 
2192  /** Write a string value enclosed opening and closing tags. Special
2193  * characters (i.e. & < > " ' ) are appropriately escaped.<br>
2194  * Output: <TAG_T>val</TAG_T> */
2195  void writeElement(const Keyword& t, const string& val)
2196  {
2197  if (!val.empty())
2198  *m_fp << indentstring << t.stringElement()
2199  << XMLEscape(val) << t.stringEndElement();
2200  }
2201 
2202  /** Writes an element with a string attribute.<br>
2203  * Output: <TAG_U TAG_T="string"/> */
2204  void writeElement(const Keyword& u, const Keyword& t, const string& val)
2205  {
2206  if (val.empty())
2207  *m_fp << indentstring << u.stringStartElement() << "/>\n";
2208  else
2209  *m_fp << indentstring << u.stringStartElement()
2210  << t.stringAttribute() << XMLEscape(val)
2211  << "\"/>\n";
2212  }
2213 
2214  /** Writes an element with a long attribute.<br>
2215  * Output: <TAG_U TAG_T="val"/> */
2216  void writeElement(const Keyword& u, const Keyword& t, const long val)
2217  {
2218  *m_fp << indentstring << u.stringStartElement()
2219  << t.stringAttribute() << val << "\"/>\n";
2220  }
2221 
2222  /** Writes an element with a date attribute.<br>
2223  * Output: <TAG_U TAG_T="val"/> */
2224  void writeElement(const Keyword& u, const Keyword& t, const Date& val)
2225  {
2226  *m_fp << indentstring << u.stringStartElement()
2227  << t.stringAttribute() << string(val) << "\"/>\n";
2228  }
2229 
2230  /** Writes an element with 2 string attributes.<br>
2231  * Output: <TAG_U TAG_T1="val1" TAG_T2="val2"/> */
2232  void writeElement(const Keyword& u, const Keyword& t1, const string& val1,
2233  const Keyword& t2, const string& val2)
2234  {
2235  if(val1.empty())
2236  *m_fp << indentstring << u.stringStartElement() << "/>\n";
2237  else
2238  *m_fp << indentstring << u.stringStartElement()
2239  << t1.stringAttribute() << XMLEscape(val1.c_str()) << "\""
2240  << t2.stringAttribute() << XMLEscape(val2.c_str())
2241  << "\"/>\n";
2242  }
2243 
2244  /** Writes an element with a string and a long attribute.<br>
2245  * Output: <TAG_U TAG_T1="val1" TAG_T2="val2"/> */
2246  void writeElement(const Keyword& u, const Keyword& t1, unsigned long val1,
2247  const Keyword& t2, const string& val2)
2248  {
2249  *m_fp << indentstring << u.stringStartElement()
2250  << t1.stringAttribute() << val1 << "\""
2251  << t2.stringAttribute() << XMLEscape(val2.c_str())
2252  << "\"/>\n";
2253  }
2254 
2255  /** Writes a C-type character string.<br>
2256  * Output: <TAG_T>val</TAG_T> */
2257  void writeElement(const Keyword& t, const char* val)
2258  {
2259  if (val)
2260  *m_fp << indentstring << t.stringElement()
2261  << XMLEscape(val) << t.stringEndElement();
2262  }
2263 
2264  /** Writes an timeperiod element.<br>
2265  * Output: <TAG_T>d</TAG_T> /> */
2266  void writeElement(const Keyword& t, const TimePeriod d)
2267  {
2268  *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
2269  }
2270 
2271  /** Writes an date element.<br>
2272  * Output: <TAG_T>d</TAG_T> /> */
2273  void writeElement(const Keyword& t, const Date d)
2274  {
2275  *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
2276  }
2277 
2278  /** Writes an daterange element.<br>
2279  * Output: <TAG_T>d</TAG_T> */
2280  void writeElement(const Keyword& t, const DateRange& d)
2281  {
2282  *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
2283  }
2284 
2285  /** This method writes a serializable object.<br>
2286  * If an object is nested more than 2 levels deep only a reference
2287  * to it is written, rather than the complete object.
2288  * You should call this method for all objects in your xml document,
2289  * except for the root object.
2290  * @see writeElementWithHeader(const Keyword&, Object*)
2291  */
2292  DECLARE_EXPORT void writeElement(const Keyword&, const Object*, mode = DEFAULT);
2293 
2294  /** @see writeElement(const Keyword&, const Object*, mode) */
2295  void writeElement(const Keyword& t, const Object& o, mode m = DEFAULT)
2296  {writeElement(t,&o,m);}
2297 
2298  /** This method writes a serializable object with a complete XML compliant
2299  * header.<br>
2300  * You should call this method for the root object of your xml document,
2301  * and writeElement for all objects nested in it.
2302  * @see writeElement(const Keyword&, Object*)
2303  * @see writeHeader
2304  * @exception RuntimeException Generated when multiple root elements
2305  * are available for the output document.
2306  */
2307  DECLARE_EXPORT void writeElementWithHeader(const Keyword& tag, const Object* object);
2308 
2309  /** This method writes the opening tag for an XML output.<br>
2310  * You should call this method or writeElementWithHeader() when writing
2311  * the first element of an xml document.
2312  * @see writeElementWithHeader
2313  * @exception RuntimeException Generated when multiple root elements
2314  * are available for the output document.
2315  */
2316  DECLARE_EXPORT void writeHeader(const Keyword& tag);
2317 
2318  /** Returns a pointer to the object that is currently being saved. */
2319  Object* getCurrentObject() const
2320  {return const_cast<Object*>(currentObject);}
2321 
2322  /** Returns a pointer to the parent of the object that is being saved. */
2323  Object* getPreviousObject() const
2324  {return const_cast<Object*>(parentObject);}
2325 
2326  /** Returns the number of objects that have been serialized. */
2327  unsigned long countObjects() const {return numObjects;}
2328 
2329  private:
2330  /** Output stream. */
2331  ostream* m_fp;
2332 
2333  /** This variable keeps track of the indentation level.
2334  * @see incIndent, decIndent
2335  */
2336  short int m_nIndent;
2337 
2338  /** This string is a null terminated string containing as many spaces as
2339  * indicated by the m_indent.
2340  * @see incIndent, decIndent
2341  */
2342  char indentstring[41];
2343 
2344  /** Keep track of the number of objects being stored. */
2345  unsigned long numObjects;
2346 
2347  /** Keep track of the number of objects currently in the save stack. */
2348  unsigned int numParents;
2349 
2350  /** This stores a pointer to the object that is currently being saved. */
2351  const Object *currentObject;
2352 
2353  /** This stores a pointer to the object that has previously been saved. */
2354  const Object *parentObject;
2355 
2356  /** Increase the indentation level. The indentation level is between
2357  * 0 and 40. */
2358  DECLARE_EXPORT void incIndent();
2359 
2360  /** Decrease the indentation level. */
2361  DECLARE_EXPORT void decIndent();
2362 
2363  /** Stores the type of data to be exported. */
2364  content_type content;
2365 
2366  /** This string defines what will be printed at the start of each XML
2367  * document. The default value is:
2368  * <?xml version="1.0" encoding="UTF-8"?>
2369  */
2370  string headerStart;
2371 
2372  /** This string defines what will be attributes are printed for the root
2373  * element of each XML document.
2374  * The default value is:
2375  * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2376  */
2377  string headerAtts;
2378 };
2379 
2380 
2381 /** @brief This class writes XML data to a flat file.
2382  *
2383  * Note that an object of this class can write only to a single file. If
2384  * multiple files are required multiple XMLOutputFile objects will be
2385  * required too.
2386  * @see XMLOutput
2387  */
2388 class XMLOutputFile : public XMLOutput
2389 {
2390  public:
2391  /** Constructor with a filename as argument. An exception will be
2392  * thrown if the output file can't be properly initialized. */
2393  XMLOutputFile(const string& chFilename)
2394  {
2395  of.open(chFilename.c_str(), ios::out);
2396  if(!of) throw RuntimeException("Could not open output file");
2397  setOutput(of);
2398  }
2399 
2400  /** Destructor. */
2401  ~XMLOutputFile() {of.close();}
2402 
2403  private:
2404  ofstream of;
2405 };
2406 
2407 
2408 /** @brief This class writes XML data to a string.
2409  *
2410  * The generated output is stored internally in the class, and can be
2411  * accessed by converting the XMLOutputString object to a string object.
2412  * This class can consume a lot of memory if large sets of objects are
2413  * being saved in this way.
2414  * @see XMLOutput
2415  */
2417 {
2418  public:
2419  /** Constructor with a starting string as argument. */
2420  XMLOutputString(const string& str) : os(str) {setOutput(os);}
2421 
2422  /** Default constructor. */
2423  XMLOutputString() {setOutput(os);}
2424 
2425  /** Return the output string. */
2426  const string getData() const {return os.str();}
2427 
2428  private:
2429  ostringstream os;
2430 };
2431 
2432 
2433 /** @brief A class to model keyword instances.
2434  *
2435  * The class uses hashes to do a fast comparison with the set of keywords.
2436  */
2438 {
2439  private:
2440  /** This string stores the hash value of the element. */
2441  hashtype hash;
2442 
2443  /** A pointer to the string representation of the keyword.<br>
2444  * The string buffer is to be managed by the code creating this
2445  * instance.
2446  */
2447  const char* ch;
2448 
2449  public:
2450  /** Default constructor. */
2451  explicit Attribute() : hash(0), ch(NULL) {}
2452 
2453  /** Constructor. */
2454  explicit Attribute(const string& n)
2455  : hash(Keyword::hash(n)), ch(n.c_str()) {}
2456 
2457  /** Constructor. */
2458  explicit Attribute(const char* c) : hash(Keyword::hash(c)), ch(c) {}
2459 
2460  /** Copy constructor. */
2461  Attribute(const Attribute& o) : hash(o.hash), ch(o.ch) {}
2462 
2463  /** Returns the hash value of this tag. */
2464  hashtype getHash() const {return hash;}
2465 
2466  /** Returns this tag. */
2467  void reset(const char *const c)
2468  {
2469  hash = Keyword::hash(c);
2470  ch = c;
2471  }
2472 
2473  /** Returns this tag. */
2474  void reset(const XMLCh *const c)
2475  {
2476  hash = Keyword::hash(c);
2477  // An XMLCh is normally a wchar, and would need to be transcoded
2478  // to a char. We won't bother...
2479  ch = NULL;
2480  }
2481 
2482  /** Return the element name. Since this method involves a lookup in a
2483  * table with Keywords, it has some performance impact and should be
2484  * avoided where possible. Only the hash of an element can efficiently
2485  * be retrieved.
2486  */
2487  DECLARE_EXPORT const char* getName() const;
2488 
2489  /** Returns true when this element is an instance of this tag. This method
2490  * doesn't involve a string comparison and is extremely efficient. */
2491  bool isA(const Keyword& t) const {return t.getHash() == hash;}
2492 
2493  /** Returns true when this element is an instance of this tag. This method
2494  * doesn't involve a string comparison and is extremely efficient. */
2495  bool isA(const Keyword* t) const {return t->getHash() == hash;}
2496 
2497  /** Comparison operator. */
2498  bool operator < (const Attribute& o) const {return hash < o.hash;}
2499 
2500  /** String comparison. */
2501  bool operator == (const string o) const {return o == ch;}
2502 };
2503 
2504 
2505 /** @brief This abstract class represents a attribute and value pair for
2506  * updating objects in frePPLe.
2507  *
2508  * It is instantiated in the XMLElement and PythonObject classes.
2509  * @todo only takes care of transformation from external format to C++. Not the C++ to external format yet.
2510  */
2512 {
2513  public:
2514  virtual operator bool() const
2515  {throw LogicException("DataElement is an abstract class");}
2516 
2517  /** Destructor. */
2518  virtual ~DataElement() {}
2519 
2520  void operator >> (unsigned long int& val) const {val = getUnsignedLong();}
2521 
2522  void operator >> (long& val) const {val = getLong();}
2523 
2524  void operator >> (TimePeriod& val) const {val = getTimeperiod();}
2525 
2526  void operator >> (bool& v) const {v=getBool();}
2527 
2528  void operator >> (int& val) const {val = getInt();}
2529 
2530  void operator >> (double& val) const {val = getDouble();}
2531 
2532  void operator >> (Date& val) const {val = getDate();}
2533 
2534  void operator >> (string& val) const {val = getString();}
2535 
2536  virtual long getLong() const
2537  {throw LogicException("DataElement is an abstract class");}
2538 
2539  virtual unsigned long getUnsignedLong() const
2540  {throw LogicException("DataElement is an abstract class");}
2541 
2542  virtual TimePeriod getTimeperiod() const
2543  {throw LogicException("DataElement is an abstract class");}
2544 
2545  virtual int getInt() const
2546  {throw LogicException("DataElement is an abstract class");}
2547 
2548  virtual double getDouble() const
2549  {throw LogicException("DataElement is an abstract class");}
2550 
2551  virtual Date getDate() const
2552  {throw LogicException("DataElement is an abstract class");}
2553 
2554  virtual string getString() const
2555  {throw LogicException("DataElement is an abstract class");}
2556 
2557  virtual bool getBool() const
2558  {throw LogicException("DataElement is an abstract class");}
2559 };
2560 
2561 
2562 /** @brief This class represents an XML element being read in from the
2563  * input file. */
2564 class XMLElement : public DataElement
2565 {
2566  private:
2567  /** This string stores the XML input data. */
2568  string m_strData;
2569 
2570  public:
2571  virtual operator bool() const {return !m_strData.empty();}
2572 
2573  /** Default constructor. */
2575 
2576  /** Constructor. */
2577  XMLElement(const string& v) : m_strData(v) {}
2578 
2579  /** Destructor. */
2580  virtual ~XMLElement() {}
2581 
2582  /** Re-initializes an existing element. Using this method we can avoid
2583  * destroying and recreating XMLelement objects too frequently. Instead
2584  * we can manage them in a array.
2585  */
2586  void reset() {m_strData.clear();}
2587 
2588  /** Add some characters to this data field of this element.<br>
2589  * The second argument is the number of bytes, not the number of
2590  * characters.
2591  */
2592  void addData(const char *pData, size_t len) {m_strData.append(pData,len);}
2593 
2594  /** Set the data value of this element. */
2595  void setData(const char *pData) {m_strData.assign(pData);}
2596 
2597  /** Return the data field. */
2598  const char *getData() const {return m_strData.c_str();}
2599 
2600  virtual long getLong() const {return atol(getData());}
2601 
2602  virtual unsigned long getUnsignedLong() const {return atol(getData());}
2603 
2604  virtual TimePeriod getTimeperiod() const {return TimePeriod(getData());}
2605 
2606  virtual int getInt() const {return atoi(getData());}
2607 
2608  virtual double getDouble() const {return atof(getData());}
2609 
2610  virtual Date getDate() const {return Date(getData());}
2611 
2612  /** Returns the string value of the XML data. The xerces library takes care
2613  * of appropriately unescaping special character sequences. */
2614  virtual string getString() const {return m_strData;}
2615 
2616  /** Interprets the element as a boolean value.<br>
2617  * <p>Our implementation is a bit more generous and forgiving than the
2618  * boolean datatype that is part of the XML schema v2 standard.
2619  * The standard expects the following literals:<br>
2620  * {true, false, 1, 0}</p>
2621  * <p>Our implementation uses only the first charater of the text, and is
2622  * case insensitive. It thus matches a wider range of values:<br>
2623  * {t.*, T.*, f.*, F.*, 1.*, 0.*}</p>
2624  */
2625  DECLARE_EXPORT bool getBool() const;
2626 };
2627 
2628 
2629 /** @brief This class groups some functions used to interact with the operating
2630  * system environment.
2631  *
2632  * It handles:
2633  * - The location of the configuration files.
2634  * - The maximum number of processors / threads to be used by frePPLe.
2635  * - An output stream for logging all output.
2636  * - Dynamic loading of a shared library.
2637  */
2639 {
2640  private:
2641  /** Caches the number of processor cores. */
2642  static DECLARE_EXPORT int processorcores;
2643 
2644  /** A file where output is directed to. */
2645  static DECLARE_EXPORT ofstream logfile;
2646 
2647  /** The name of the log file. */
2648  static DECLARE_EXPORT string logfilename;
2649 
2650  /** A list of all loaded modules. */
2651  static DECLARE_EXPORT set<string> moduleRegistry;
2652 
2653  public:
2654  /** Search for a file with a given name.<br>
2655  * The following directories are searched in sequence to find a match:
2656  * - The current directory.
2657  * - The directory referred to by the variable FREPPLE_HOME, if it
2658  * is defined.
2659  * - The data directory as configured during the compilation.
2660  * This applies only to linux / unix.
2661  * - The library directory as configured during the compilation.
2662  * This applies only to linux / unix.
2663  */
2664  static DECLARE_EXPORT string searchFile(const string);
2665 
2666  /** Returns the number of processor cores on your machine. */
2667  static DECLARE_EXPORT int getProcessorCores();
2668 
2669  /** Returns the name of the logfile. */
2670  static const string& getLogFile() {return logfilename;}
2671 
2672  /** Updates the filename for logging error messages and warnings.
2673  * The file is also opened for writing and the standard output and
2674  * standard error output streams are redirected to it.<br>
2675  * If the filename starts with '+' the log file is appended to
2676  * instead of being overwritten.
2677  */
2678  static DECLARE_EXPORT void setLogFile(const string& x);
2679 
2680  /** Type for storing parameters passed to a module that is loaded. */
2681  typedef map<string,XMLElement> ParameterList;
2682 
2683  /** @brief Function to dynamically load a shared library in frePPLe.
2684  *
2685  * After loading the library, the function "initialize" of the module
2686  * is executed.
2687  *
2688  * The current implementation supports the following platforms:
2689  * - Windows
2690  * - Linux
2691  * - Unix systems supporting the dlopen function in the standard way.
2692  * Some unix systems have other or deviating APIs. A pretty messy story :-<
2693  */
2694  static DECLARE_EXPORT void loadModule(string lib, ParameterList& parameters); //@todo replace argument with a AttributeList instead
2695 
2696  /** Print all modules that have been loaded. */
2697  static DECLARE_EXPORT void printModules();
2698 };
2699 
2700 
2701 /** @brief This class handles two-way translation between the data types
2702  * in C++ and Python.
2703  *
2704  * This class is basically a wrapper around a PyObject pointer.
2705  *
2706  * When creating a PythonObject from a C++ object, make sure to increment
2707  * the reference count of the object.<br>
2708  * When constructing a PythonObject from an existing Python object, the
2709  * code that provided us the PyObject pointer should have incremented the
2710  * reference count already.
2711  *
2712  * @todo endelement function should be shared with setattro function.
2713  * Unifies the python and xml worlds: shared code base to update objects!
2714  * (Code for extracting info is still python specific, and writeElement
2715  * is also xml-specific)
2716  * xml->prevObject = python->cast value to a different type
2717  *
2718  * @todo object creator should be common with the XML reader, which uses
2719  * the registered factory method.
2720  * Also supports add/add_change/remove.
2721  * Tricky: flow/load which use an additional validate() method
2722  */
2724 {
2725  private:
2726  PyObject* obj;
2727 
2728  public:
2729  /** Default constructor. The default value is equal to Py_None. */
2730  explicit PythonObject() : obj(Py_None) {Py_INCREF(obj);}
2731 
2732  /** Constructor from an existing Python object.<br>
2733  * The reference count isn't increased.
2734  */
2735  PythonObject(const PyObject* o)
2736  : obj(o ? const_cast<PyObject*>(o) : Py_None) {Py_INCREF(obj);}
2737 
2738  /** This conversion operator casts the object back to a PyObject pointer. */
2739  operator PyObject*() const {return obj;}
2740 
2741  /** Check for null value. */
2742  operator bool() const {return obj != NULL && obj != Py_None;}
2743 
2744  /** Assignment operator. */
2745  PythonObject& operator = (const PythonObject& o)
2746  {
2747  if (obj) {Py_DECREF(obj);}
2748  obj = o.obj;
2749  if (obj) {Py_INCREF(obj);}
2750  return *this;
2751  }
2752 
2753  /** Check whether the Python object is of a certain type.<br>
2754  * Subclasses of the argument type will also give a true return value.
2755  */
2756  bool check(const MetaClass* c) const
2757  {
2758  return obj ?
2759  PyObject_TypeCheck(obj, c->pythonClass) :
2760  false;
2761  }
2762 
2763  /** Check whether the Python object is of a certain type.<br>
2764  * Subclasses of the argument type will also give a true return value.
2765  */
2766  bool check(const PythonType& c) const
2767  {
2768  return obj ?
2769  PyObject_TypeCheck(obj, c.type_object()) :
2770  false;
2771  }
2772 
2773  /** Convert a Python string into a C++ string. */
2774  inline string getString() const
2775  {
2776  if (obj == Py_None)
2777  return string();
2778  else if (PyUnicode_Check(obj))
2779  {
2780  // It's a Python unicode string
2781  PyObject* x = PyUnicode_AsEncodedString(obj,
2782  PythonInterpreter::getPythonEncoding(), "ignore");
2783  string result = PyString_AsString(x);
2784  Py_DECREF(x);
2785  return result;
2786  }
2787  else if (PyString_Check(obj))
2788  // It's a Python string
2789  return PyString_AsString(obj);
2790  else
2791  {
2792  // It's not a Python string object, call the str() function on the object
2793  PyObject* x = PyObject_Str(obj);
2794  string result = PyString_AsString(x);
2795  Py_DECREF(x);
2796  return result;
2797  }
2798  }
2799 
2800  /** Extract an unsigned long from the Python object. */
2801  unsigned long getUnsignedLong() const
2802  {
2803  if (obj == Py_None) return 0;
2804  if (PyString_Check(obj))
2805  {
2806  PyObject* t = PyFloat_FromString(obj, NULL);
2807  if (!t) throw DataException("Invalid number");
2808  double x = PyFloat_AS_DOUBLE(t);
2809  Py_DECREF(t);
2810  if (x < 0 || x > ULONG_MAX)
2811  throw DataException("Invalid number");
2812  return static_cast<unsigned long>(x);
2813  }
2814  return PyLong_AsUnsignedLong(obj);
2815  }
2816 
2817  /** Convert a Python datetime.date or datetime.datetime object into a
2818  * frePPLe date. */
2819  DECLARE_EXPORT Date getDate() const;
2820 
2821  /** Convert a Python number or string into a C++ double. */
2822  inline double getDouble() const
2823  {
2824  if (obj == Py_None) return 0;
2825  if (PyString_Check(obj))
2826  {
2827  PyObject* t = PyFloat_FromString(obj, NULL);
2828  if (!t) throw DataException("Invalid number");
2829  double x = PyFloat_AS_DOUBLE(t);
2830  Py_DECREF(t);
2831  return x;
2832  }
2833  return PyFloat_AsDouble(obj);
2834  }
2835 
2836  /** Convert a Python number or string into a C++ integer. */
2837  inline int getInt() const
2838  {
2839  if (PyString_Check(obj))
2840  {
2841  PyObject* t = PyFloat_FromString(obj, NULL);
2842  if (!t) throw DataException("Invalid number");
2843  double x = PyFloat_AS_DOUBLE(t);
2844  Py_DECREF(t);
2845  if (x < INT_MIN || x > INT_MAX)
2846  throw DataException("Invalid number");
2847  return static_cast<int>(x);
2848  }
2849  int result = PyInt_AsLong(obj);
2850  if (result == -1 && PyErr_Occurred())
2851  throw DataException("Invalid number");
2852  return result;
2853  }
2854 
2855  /** Convert a Python number into a C++ long. */
2856  inline long getLong() const
2857  {
2858  if (PyString_Check(obj))
2859  {
2860  PyObject* t = PyFloat_FromString(obj, NULL);
2861  if (!t) throw DataException("Invalid number");
2862  double x = PyFloat_AS_DOUBLE(t);
2863  Py_DECREF(t);
2864  if (x < LONG_MIN || x > LONG_MIN)
2865  throw DataException("Invalid number");
2866  return static_cast<long>(x);
2867  }
2868  int result = PyInt_AsLong(obj);
2869  if (result == -1 && PyErr_Occurred())
2870  throw DataException("Invalid number");
2871  return result;
2872  }
2873 
2874  /** Convert a Python number into a C++ bool. */
2875  inline bool getBool() const
2876  {
2877  return PyObject_IsTrue(obj) ? true : false;
2878  }
2879 
2880  /** Convert a Python number as a number of seconds into a frePPLe
2881  * TimePeriod.<br>
2882  * A TimePeriod is represented as a number of seconds in Python.
2883  */
2884  TimePeriod getTimeperiod() const
2885  {
2886  if (PyString_Check(obj))
2887  {
2888  if (PyUnicode_Check(obj))
2889  {
2890  // Replace the unicode object with a string encoded in the correct locale
2891  const_cast<PyObject*&>(obj) =
2892  PyUnicode_AsEncodedString(obj, PythonInterpreter::getPythonEncoding(), "ignore");
2893  }
2894  return TimePeriod(PyString_AsString(PyObject_Str(obj)));
2895  }
2896  int result = PyInt_AsLong(obj);
2897  if (result == -1 && PyErr_Occurred())
2898  throw DataException("Invalid number");
2899  return result;
2900  }
2901 
2902  /** Constructor from a pointer to an Object.<br>
2903  * The metadata of the Object instances allow us to create a Python
2904  * object that works as a proxy for the C++ object.
2905  */
2907 
2908  /** Convert a C++ string into a (raw) Python string. */
2909  inline PythonObject(const string& val)
2910  {
2911  if (val.empty())
2912  {
2913  obj = Py_None;
2914  Py_INCREF(obj);
2915  }
2916  else
2917  obj = PyString_FromString(val.c_str());
2918  }
2919 
2920  /** Convert a C++ double into a Python number. */
2921  inline PythonObject(const double val)
2922  {
2923  obj = PyFloat_FromDouble(val);
2924  }
2925 
2926  /** Convert a C++ integer into a Python integer. */
2927  inline PythonObject(const int val)
2928  {
2929  obj = PyInt_FromLong(val);
2930  }
2931 
2932  /** Convert a C++ long into a Python long. */
2933  inline PythonObject(const long val)
2934  {
2935  obj = PyLong_FromLong(val);
2936  }
2937 
2938  /** Convert a C++ unsigned long into a Python long. */
2939  inline PythonObject(const unsigned long val)
2940  {
2941  obj = PyLong_FromUnsignedLong(val);
2942  }
2943 
2944  /** Convert a C++ boolean into a Python boolean. */
2945  inline PythonObject(const bool val)
2946  {
2947  obj = val ? Py_True : Py_False;
2948  Py_INCREF(obj);
2949  }
2950 
2951  /** Convert a frePPLe TimePeriod into a Python number representing
2952  * the number of seconds. */
2953  inline PythonObject(const TimePeriod val)
2954  {
2955  // A TimePeriod is represented as a number of seconds in Python
2956  obj = PyLong_FromLong(val);
2957  }
2958 
2959  /** Convert a frePPLe date into a Python datetime.datetime object. */
2960  DECLARE_EXPORT PythonObject(const Date& val);
2961 };
2962 
2963 
2964 /** @brief This call is a wrapper around a Python function that can be
2965  * called from the C++ code.
2966  */
2968 {
2969  public:
2970  /** Default constructor. */
2971  PythonFunction() : func(NULL) {}
2972 
2973  /** Constructor. */
2974  DECLARE_EXPORT PythonFunction(const string&);
2975 
2976  /** Constructor. */
2977  DECLARE_EXPORT PythonFunction(PyObject*);
2978 
2979  /** Copy constructor. */
2980  PythonFunction(const PythonFunction& o) : func(o.func)
2981  {
2982  if (func) {Py_INCREF(func);}
2983  }
2984 
2985  /** Assignment operator. */
2986  PythonFunction& operator= (const PythonFunction& o)
2987  {
2988  if (func) {Py_DECREF(func);}
2989  func = o.func;
2990  if (func) {Py_INCREF(func);}
2991  return *this;
2992  }
2993 
2994  /** Destructor. */
2995  ~PythonFunction() {if (func) {Py_DECREF(func);}}
2996 
2997  /** Conversion operator to a Python pointer. */
2998  operator const PyObject*() const {return func;}
2999 
3000  /** Conversion operator to a string. */
3001  operator string() const {return func ? PyEval_GetFuncName(func) : "NULL";}
3002 
3003  /** Conversion operator to bool. */
3004  operator bool() const {return func != NULL;}
3005 
3006  /** Call the Python function without arguments. */
3007  DECLARE_EXPORT PythonObject call() const;
3008 
3009  /** Call the Python function with one argument. */
3010  DECLARE_EXPORT PythonObject call(const PyObject*) const;
3011 
3012  /** Call the Python function with two arguments. */
3013  DECLARE_EXPORT PythonObject call(const PyObject*, const PyObject*) const;
3014 
3015  private:
3016  /** A pointer to the Python object. */
3017  PyObject* func;
3018 };
3019 
3020 
3021 /** @brief This class represents a dictionary of keyword + value pairs.
3022  *
3023  * This abstract class can be instantiated as XML attributes, or as a
3024  * Python keyword dictionary.
3025  * - XML:<br>
3026  * &lt;buffer name="a" onhand="10" category="A" /&gt;
3027  * - Python:<br>
3028  * buffer(name="a", onhand="10", category="A")
3029  */
3031 {
3032  public:
3033  virtual const DataElement* get(const Keyword&) const = 0;
3034  // @todo Iterator???
3035 
3036  /** Destructor. */
3037  virtual ~AttributeList() {}
3038 };
3039 
3040 
3041 /** @brief This class represents a list of XML attributes. */
3043 {
3044  private:
3045  const xercesc::Attributes* atts;
3046  XMLElement result;
3047  public:
3048  XMLAttributeList(const xercesc::Attributes* a) : atts(a) {}
3049 
3050  DECLARE_EXPORT const XMLElement* get(const Keyword& key) const;
3051 };
3052 
3053 
3054 /** @brief This class is a wrapper around a Python dictionary. */
3056 {
3057  private:
3058  PyObject* kwds;
3059  PythonObject result;
3060 
3061  public:
3062  PythonAttributeList(PyObject* a) : kwds(a) {}
3063 
3064  virtual const DataElement* get(const Keyword& k) const
3065  {
3066  if (!kwds)
3067  {
3068  const_cast<PythonAttributeList*>(this)->result = PythonObject();
3069  return &result;
3070  }
3071  PyObject* val = PyDict_GetItemString(kwds,k.getName().c_str());
3072  const_cast<PythonAttributeList*>(this)->result = PythonObject(val);
3073  return &result;
3074  }
3075 };
3076 
3077 
3078 /** @brief This is a base class for all Python extension types.
3079  *
3080  * When creating you own extensions, inherit from the PythonExtension
3081  * template class instead of this one.
3082  *
3083  * It inherits from the PyObject C struct, defined in the Python C API.<br>
3084  * These functions aren't called directly from Python. Python first calls a
3085  * handler C-function and the handler function will use a virtual call to
3086  * run the correct C++-method.
3087  *
3088  * Our extensions don't use the usual Python heap allocator. They are
3089  * created and initialized with the regular C++ new and delete. A special
3090  * deallocator is called from Python to delete objects when their reference
3091  * count reaches zero.
3092  */
3093 class PythonExtensionBase : public PyObject
3094 {
3095  public:
3096  /** Default constructor */
3098 
3099  /** Destructor. */
3101  {
3102  if (PyObject::ob_refcnt > 1)
3103  logger << "Warning: Deleting " << PyObject::ob_type->tp_name
3104  << " object that is still referenced "
3105  << (PyObject::ob_refcnt-1) << " times" << endl;
3106  }
3107 
3108  /** A function to force an object to be destroyed by the Python garbage
3109  * collection.<br>
3110  * Be very careful to use this!
3111  */
3112  void resetReferenceCount() {PyObject::ob_refcnt = 0;}
3113 
3114  /** Returns the current reference count. */
3115  Py_ssize_t getReferenceCount() const {return PyObject::ob_refcnt;}
3116 
3117  /** Initialize the object to a certain Python type. */
3118  inline void initType(const MetaClass *t)
3119  {
3120  PyObject_INIT(this,t->pythonClass);
3121  }
3122 
3123  /** Initialize the object to a certain Python type. */
3124  inline void initType(PyTypeObject *t)
3125  {
3126  PyObject_INIT(this,t);
3127  }
3128 
3129  /** Default getattro method. <br>
3130  * Subclasses are expected to implement an override if the type supports
3131  * gettattro.
3132  */
3133  virtual PyObject* getattro(const Attribute& attr)
3134  {
3135  PyErr_SetString(PythonLogicException, "Missing method 'getattro'");
3136  return NULL;
3137  }
3138 
3139  /** Default setattro method. <br>
3140  * Subclasses are expected to implement an override if the type supports
3141  * settattro.
3142  */
3143  virtual int setattro(const Attribute& attr, const PythonObject& field)
3144  {
3145  PyErr_SetString(PythonLogicException, "Missing method 'setattro'");
3146  return -1;
3147  }
3148 
3149  /** Default compare method. <br>
3150  * Subclasses are expected to implement an override if the type supports
3151  * compare.
3152  */
3153  virtual int compare(const PyObject* other) const
3154  {
3155  PyErr_SetString(PythonLogicException, "Missing method 'compare'");
3156  return -1;
3157  }
3158 
3159  /** Default iternext method. <br>
3160  * Subclasses are expected to implement an override if the type supports
3161  * iteration.
3162  */
3163  virtual PyObject* iternext()
3164  {
3165  PyErr_SetString(PythonLogicException, "Missing method 'iternext'");
3166  return NULL;
3167  }
3168 
3169  /** Default call method. <br>
3170  * Subclasses are expected to implement an override if the type supports
3171  * calls.
3172  */
3173  virtual PyObject* call(const PythonObject& args, const PythonObject& kwds)
3174  {
3175  PyErr_SetString(PythonLogicException, "Missing method 'call'");
3176  return NULL;
3177  }
3178 
3179  /** Default str method. <br>
3180  * Subclasses are expected to implement an override if the type supports
3181  * conversion to a string.
3182  */
3183  virtual PyObject* str() const
3184  {
3185  PyErr_SetString(PythonLogicException, "Missing method 'str'");
3186  return NULL;
3187  }
3188 
3189  protected:
3190  static vector<PythonType*> table;
3191 
3192  DECLARE_EXPORT static PythonType* registerPythonType(int, const type_info*);
3193 
3194 };
3195 
3196 
3197 /** @brief Template class to define Python extensions.
3198  *
3199  * The template argument should be your extension class, inheriting from
3200  * this template class:
3201  * class MyClass : PythonExtension<MyClass>
3202  *
3203  * The structure of the C++ wrappers around the C Python API is heavily
3204  * inspired on the design of PyCXX.<br>
3205  * More information can be found on http://cxx.sourceforge.net
3206  */
3207 template<class T>
3209 {
3210  public:
3211  /** Constructor.<br>
3212  * The Python metadata fields always need to be set correctly.
3213  */
3214  explicit PythonExtension()
3215  {
3216  PyObject_Init(this, getType().type_object());
3217  }
3218 
3219  /** Destructor. */
3220  virtual ~PythonExtension() {}
3221 
3222  /** This method keeps the type information object for your extension. */
3223  static PythonType& getType()
3224  {
3225  static PythonType* cachedTypePtr = NULL;
3226  if (cachedTypePtr) return *cachedTypePtr;
3227 
3228  // Register a new type
3229  cachedTypePtr = registerPythonType(sizeof(T), &typeid(T));
3230 
3231  // Using our own memory deallocator
3232  cachedTypePtr->supportdealloc( deallocator );
3233 
3234  return *cachedTypePtr;
3235  }
3236 
3237  /** Free the memory.<br>
3238  * See the note on the memory management in the class documentation
3239  * for PythonExtensionBase.
3240  */
3241  static void deallocator(PyObject* o) {delete static_cast<T*>(o);}
3242 };
3243 
3244 
3245 /** @brief Object is the abstract base class for the main entities.
3246  *
3247  * It handles to following capabilities:
3248  * - <b>Metadata:</b> All subclasses publish metadata about their structure.
3249  * - <b>Python object:</b> All objects live a double life as a Python object.
3250  * - <b>Callbacks:</b> When objects are created or deleted,
3251  * interested classes or objects can get a callback notification.
3252  * - <b>Serialization:</b> Objects need to be persisted and later restored.
3253  * Subclasses that don't need to be persisted can skip the implementation
3254  * of the writeElement method.<br>
3255  * Instances can be marked as hidden, which means that they are not
3256  * serialized at all.
3257  */
3259 {
3260  public:
3261  /** Constructor. */
3262  explicit Object() {}
3263 
3264  /** Destructor. */
3265  virtual ~Object() {}
3266 
3267  /** Called while writing the model into an XML-file.
3268  * The user class should write itself out, using the IOutStream
3269  * members for its "simple" members and calling writeElement
3270  * recursively for any contained objects.
3271  * Not all classes are expected to implement this method. In instances
3272  * of such a class can be created but can't be persisted.
3273  * E.g. Command
3274  */
3275  virtual void writeElement(XMLOutput *, const Keyword &, mode=DEFAULT) const
3276  {throw LogicException("Class can't be persisted");}
3277 
3278  /** Called while restoring the model from an XML-file.<br>
3279  * This is called for each element within the "this" element,
3280  * for which the "this" element is immediate parent.<br>
3281  * It is called when the open element tag is encountered.
3282  */
3283  virtual void beginElement(XMLInput&, const Attribute&) {}
3284 
3285  /** Called while restoring the model from an XML-file.<br>
3286  * This is called when the corresponding close element tag
3287  * is encountered, and the Data() member of pElement is valid.
3288  */
3289  virtual void endElement(XMLInput&, const Attribute&, const DataElement&) = 0;
3290 
3291  /** Mark the object as hidden or not. Hidden objects are not exported
3292  * and are used only as dummy constructs. */
3293  virtual void setHidden(bool b) {}
3294 
3295  /** Returns whether an entity is real or dummy. */
3296  virtual bool getHidden() const {return false;}
3297 
3298  /** This returns the type information on the object, a bit similar to
3299  * the standard type_info information. */
3300  virtual const MetaClass& getType() const = 0;
3301 
3302  /** Return the memory size of the object in bytes. */
3303  virtual size_t getSize() const = 0;
3304 
3305  /** This template function can generate a factory method for objects that
3306  * can be constructed with their default constructor. */
3307  template <class T>
3308  static Object* createDefault()
3309  {
3310  return new T();
3311  }
3312 
3313  /** This template function can generate a factory method for objects that
3314  * need a string argument in their constructor. */
3315  template <class T>
3316  static Object* createString(const string& n)
3317  {
3318  return new T(n);
3319  }
3320 
3321  /** Template function that generates a factory method callable
3322  * from Python. */
3323  template<class T>
3324  static PyObject* create
3325  (PyTypeObject* pytype, PyObject* args, PyObject* kwds)
3326  {
3327  try
3328  {
3329  // Find or create the C++ object
3330  PythonAttributeList atts(kwds);
3331  Object* x = T::reader(T::metadata, atts);
3332 
3333  // Object was deleted
3334  if (!x)
3335  {
3336  Py_INCREF(Py_None);
3337  return Py_None;
3338  }
3339 
3340  // Iterate over extra keywords, and set attributes. @todo move this responsability to the readers...
3341  PyObject *key, *value;
3342  Py_ssize_t pos = 0;
3343  while (PyDict_Next(kwds, &pos, &key, &value))
3344  {
3345  PythonObject field(value);
3346  Attribute attr(PyString_AsString(key));
3347  if (!attr.isA(Tags::tag_name) && !attr.isA(Tags::tag_type) && !attr.isA(Tags::tag_action))
3348  {
3349  int result = x->setattro(attr, field);
3350  if (result && !PyErr_Occurred())
3351  PyErr_Format(PyExc_AttributeError,
3352  "attribute '%s' on '%s' can't be updated",
3353  PyString_AsString(key), x->ob_type->tp_name);
3354  }
3355  };
3356  Py_INCREF(x);
3357  return x;
3358  }
3359  catch (...)
3360  {
3361  PythonType::evalException();
3362  return NULL;
3363  }
3364  }
3365 
3366  /** Return an XML representation of the object.<br>
3367  * If a file object is passed as argument, the representation is directly
3368  * written to it.<br>
3369  * If no argument is given the representation is returned as a string.
3370  */
3371  static DECLARE_EXPORT PyObject* toXML(PyObject*, PyObject*);
3372 };
3373 
3374 
3375 //
3376 // UTILITY CLASSES FOR MULTITHREADING
3377 //
3378 
3379 
3380 /** @brief This class is a wrapper around platform specific mutex functions. */
3381 class Mutex: public NonCopyable
3382 {
3383  public:
3384 #ifndef MT
3385  // No threading support, empty class
3386  Mutex() {}
3387  ~Mutex() {}
3388  void lock() {}
3389  void unlock() {}
3390 #elif defined(HAVE_PTHREAD_H)
3391  // Pthreads
3392  Mutex() {pthread_mutex_init(&mtx, 0);}
3393  ~Mutex() {pthread_mutex_destroy(&mtx);}
3394  void lock() {pthread_mutex_lock(&mtx);}
3395  void unlock() {pthread_mutex_unlock(&mtx);}
3396  private:
3397  pthread_mutex_t mtx;
3398 #else
3399  // Windows critical section
3400  Mutex() {InitializeCriticalSection(&critsec);}
3401  ~Mutex() {DeleteCriticalSection(&critsec);}
3402  void lock() {EnterCriticalSection(&critsec);}
3403  void unlock() {LeaveCriticalSection(&critsec);}
3404  private:
3405  CRITICAL_SECTION critsec;
3406 #endif
3407 };
3408 
3409 
3410 /** @brief This is a convenience class that makes it easy (and
3411  * exception-safe) to lock a mutex in a scope.
3412  */
3414 {
3415  protected:
3417  public:
3418  ScopeMutexLock(Mutex& imtx): mtx(imtx) {mtx.lock ();}
3419  ~ScopeMutexLock() {mtx.unlock();}
3420 };
3421 
3422 
3423 /** @brief This class supports parallel execution of a number of functions.
3424  *
3425  * Currently Pthreads and Windows threads are supported as the implementation
3426  * of the multithreading.
3427  */
3428 class ThreadGroup : public NonCopyable
3429 {
3430  public:
3431  /** Prototype of the thread function. */
3432  typedef void (*callable)(void*);
3433 
3434  /** Constructor which defaults to have as many worker threads as there are
3435  * cores on the machine.
3436  */
3437  ThreadGroup() : countCallables(0)
3438  {
3439  maxParallel = Environment::getProcessorCores();
3440  };
3441 
3442  /** Constructor with a predefined number of worker threads. */
3443  ThreadGroup(int i) : countCallables(0)
3444  {
3445  setMaxParallel(i);
3446  };
3447 
3448  /** Add a new function to be called and its argument. */
3449  void add(callable func, void* args)
3450  {
3451  callables.push( make_pair(func,args) );
3452  ++countCallables;
3453  }
3454 
3455  /** Execute all functions and wait for them to finish. */
3456  DECLARE_EXPORT void execute();
3457 
3458  /** Returns the number of parallel workers that is activated.<br>
3459  * By default we activate as many worker threads as there are cores on
3460  * the machine.
3461  */
3462  int getMaxParallel() const {return maxParallel;}
3463 
3464  /** Updates the number of parallel workers that is activated. */
3465  void setMaxParallel(int b)
3466  {
3467  if (b<1)
3468  throw DataException("Invalid number of parallel execution threads");
3469 #ifndef MT
3470  maxParallel = (b>1 ? 1 : b);
3471 #else
3472  maxParallel = b;
3473 #endif
3474  }
3475 
3476  private:
3477  typedef pair<callable,void*> callableWithArgument;
3478 
3479  /** Mutex to protect the curCommand data field during multi-threaded
3480  * execution.
3481  * @see selectCommand
3482  */
3483  Mutex lock;
3484 
3485  /** Specifies the maximum number of commands in the list that can be
3486  * executed in parallel.
3487  * The default value is 1, i.e. sequential execution.<br>
3488  * The value of this field is NOT inherited from parent command lists.<br>
3489  * Note that the maximum applies to this command list only, and it isn't
3490  * a system-wide limit on the creation of threads.
3491  */
3492  int maxParallel;
3493 
3494  /** Stack with all registered functions and their invocation arguments. */
3495  stack<callableWithArgument> callables;
3496 
3497  /** Count registered callables. */
3498  unsigned int countCallables;
3499 
3500  /** This functions runs a single command execution thread. It is used as
3501  * a holder for the main routines of a trheaded routine.
3502  */
3503 #if defined(HAVE_PTHREAD_H) || !defined(MT)
3504  static void* wrapper(void *arg);
3505 #else
3506  static unsigned __stdcall wrapper(void *);
3507 #endif
3508 
3509  /** This method selects the next function to be executed.
3510  * @see wrapper
3511  */
3512  DECLARE_EXPORT callableWithArgument selectNextCallable();
3513 };
3514 
3515 
3516 //
3517 // RED-BLACK TREE CLASS
3518 //
3519 
3520 /** @brief This class implements a binary tree data structure. It is used as a
3521  * container for entities keyed by their name.
3522  *
3523  * Technically, the data structure can be described as a red-black tree
3524  * with intrusive tree nodes.
3525  * @see HasName
3526  */
3527 class Tree : public NonCopyable
3528 {
3529  public:
3530  /** The algorithm assigns a color to each node in the tree. The color is
3531  * used to keep the tree balanced.<br>
3532  * A node with color 'none' is a node that hasn't been inserted yet in
3533  * the tree.
3534  */
3535  enum NodeColor {red, black, none };
3536 
3537  /** @brief This class represents a node in the tree.
3538  *
3539  * Elements which we want to represent in the tree will need to inherit
3540  * from this class, since this tree container is intrusive.
3541  */
3542  class TreeNode
3543  {
3544  friend class Tree;
3545 
3546  public:
3547  /** Destructor. */
3548  virtual ~TreeNode() {}
3549 
3550  /** Returns the name of this node. This name is used to sort the
3551  * nodes. */
3552  const string& getName() const {return nm;}
3553 
3554  /** Comparison operator. */
3555  bool operator < (const TreeNode& o) {return nm < o.nm;}
3556 
3557  /** Constructor. */
3558  TreeNode(const string& n) : nm(n), color(none)
3559  {
3560  if (n.empty())
3561  throw DataException("Can't create entity without name");
3562  }
3563 
3564  /** Return a pointer to the node following this one. */
3565  TreeNode* increment() const
3566  {
3567  TreeNode *node = const_cast<TreeNode*>(this);
3568  if (node->right != NULL)
3569  {
3570  node = node->right;
3571  while (node->left != NULL) node = node->left;
3572  }
3573  else
3574  {
3575  TreeNode* y = node->parent;
3576  while (node == y->right)
3577  {
3578  node = y;
3579  y = y->parent;
3580  }
3581  if (node->right != y) node = y;
3582  }
3583  return node;
3584  }
3585 
3586  /** Return a pointer to the node preceding this one. */
3587  TreeNode* decrement() const
3588  {
3589  TreeNode *node = const_cast<TreeNode*>(this);
3590  if (node->color == red && node->parent->parent == node)
3591  node = node->right;
3592  else if (node->left != NULL)
3593  {
3594  TreeNode* y = node->left;
3595  while (y->right != NULL) y = y->right;
3596  node = y;
3597  }
3598  else
3599  {
3600  TreeNode* y = node->parent;
3601  while (node == y->left)
3602  {
3603  node = y;
3604  y = y->parent;
3605  }
3606  node = y;
3607  }
3608  return node;
3609  }
3610 
3611  private:
3612  /** Constructor. */
3613  TreeNode() {}
3614 
3615  /** Name. */
3616  string nm;
3617 
3618  /** Color of the node. This is used to keep the tree balanced. */
3619  NodeColor color;
3620 
3621  /** Pointer to the parent node. */
3622  TreeNode* parent;
3623 
3624  /** Pointer to the left child node. */
3625  TreeNode* left;
3626 
3627  /** Pointer to the right child node. */
3628  TreeNode* right;
3629  };
3630 
3631  /** Default constructor. */
3632  Tree(bool b = false) : count(0), clearOnDestruct(b)
3633  {
3634  // Color is used to distinguish header from root, in iterator.operator++
3635  header.color = red;
3636  header.parent = NULL;
3637  header.left = &header;
3638  header.right = &header;
3639  }
3640 
3641  /** Destructor.<br>
3642  * By default, the objects in the tree are not deleted when the tree
3643  * is deleted. This is done for performance reasons: the program can shut
3644  * down faster.
3645  */
3646  ~Tree() {if(clearOnDestruct) clear();}
3647 
3648  /** Returns an iterator to the start of the list.<br>
3649  * The user will need to take care of properly acquiring a read lock on
3650  * on the tree object.
3651  */
3652  TreeNode* begin() const {return const_cast<TreeNode*>(header.left);}
3653 
3654  /** Returns an iterator pointing beyond the last element in the list.<br>
3655  * The user will need to take care of properly acquiring a read lock on
3656  * on the tree object.
3657  */
3658  TreeNode* end() const {return const_cast<TreeNode*>(&header);}
3659 
3660  /** Returns true if the list is empty.<br>
3661  * Its complexity is O(1). */
3662  bool empty() const {return header.parent == NULL;}
3663 
3664  /** Renames an existing node, and adjusts its position in the tree. */
3665  void rename(TreeNode* obj, string newname)
3666  {
3667  bool found;
3668  findLowerBound(newname, &found);
3669  if (found)
3670  throw DataException("Can't rename '" + obj->nm + "' to '"
3671  + newname + "': name already in use");
3672  erase(obj);
3673  // @todo: there is a small risk for multithreading trouble when the tree is unlocked between the delete and re-insert
3674  obj->nm = newname;
3675  insert(obj);
3676  };
3677 
3678  /** This method returns the number of nodes inserted in this tree.<br>
3679  * Its complexity is O(1), so it can be called on large trees without any
3680  * performance impact.
3681  */
3682  size_t size() const {return count;}
3683 
3684  /** Verifies the integrity of the tree and returns true if everything
3685  * is correct.<br>
3686  * The tree should be locked before calling this function.
3687  */
3688  DECLARE_EXPORT void verify() const;
3689 
3690  /** Remove all elements from the tree. */
3691  DECLARE_EXPORT void clear();
3692 
3693  /** Remove a node from the tree. */
3694  DECLARE_EXPORT void erase(TreeNode* x);
3695 
3696  /** Search for an element in the tree.<br>
3697  * Profiling shows this function has a significant impact on the CPU
3698  * time (mainly because of the string comparisons), and has been
3699  * optimized as much as possible.
3700  */
3701  TreeNode* find(const string& k) const
3702  {
3703  int comp;
3704  for (TreeNode* x = header.parent; x; x = comp<0 ? x->left : x->right)
3705  {
3706  comp = k.compare(x->nm);
3707  if (!comp) return x;
3708  }
3709  TreeNode* result = end();
3710  return result;
3711  }
3712 
3713  /** Find the element with this given key or the element
3714  * immediately preceding it.<br>
3715  * The second argument is a boolean that is set to true when the
3716  * element is found in the list.
3717  */
3718  TreeNode* findLowerBound(const string& k, bool* f) const
3719  {
3720  TreeNode* lower = end();
3721  for (TreeNode* x = header.parent; x;)
3722  {
3723  int comp = k.compare(x->nm);
3724  if (!comp)
3725  {
3726  // Found
3727  if (f) *f = true;
3728  return x;
3729  }
3730  if (comp<0) x = x->left;
3731  else lower = x, x = x->right;
3732  }
3733  if (f) *f = false;
3734  return lower;
3735  }
3736 
3737  /** Insert a new node in the tree. */
3738  TreeNode* insert(TreeNode* v) {return insert(v, NULL);}
3739 
3740  /** Insert a new node in the tree. The second argument is a hint on
3741  * the proper location in the tree.<br>
3742  * Profiling shows this function has a significant impact on the cpu
3743  * time (mainly because of the string comparisons), and has been
3744  * optimized as much as possible.
3745  */
3746  DECLARE_EXPORT TreeNode* insert(TreeNode* v, TreeNode* hint);
3747 
3748  private:
3749  /** Restructure the tree such that the depth of the branches remains
3750  * properly balanced. This method is called during insertion. */
3751  inline void rebalance(TreeNode* x);
3752 
3753  /** Rebalancing operation used during the rebalancing. */
3754  inline void rotateLeft(TreeNode* x);
3755 
3756  /** Rebalancing operation used during the rebalancing. */
3757  inline void rotateRight(TreeNode* x);
3758 
3759  /** Method used internally by the verify() method. */
3760  unsigned int countBlackNodes(TreeNode* node) const
3761  {
3762  unsigned int sum = 0;
3763  for ( ; node != header.parent; node=node->parent)
3764  if (node->color == black) ++sum;
3765  return sum;
3766  }
3767 
3768  TreeNode* minimum(TreeNode* x) const
3769  {
3770  while (x->left) x = x->left;
3771  return x;
3772  }
3773 
3774  TreeNode* maximum(TreeNode* x) const
3775  {
3776  while (x->right) x = x->right;
3777  return x;
3778  }
3779 
3780  /** This node stores the following data:
3781  * - parent: root of the tree.
3782  * - left: leftmost element in the tree.
3783  * - right: rightmost element in the tree.
3784  * - this node itself is used as an element beyond the end of the list.
3785  */
3786  TreeNode header;
3787 
3788  /** Stores the number of elements in the tree. */
3789  size_t count;
3790 
3791  /** Controls whether the destructor needs to be clear all objects in the
3792  * tree in its destructor.<br>
3793  * The default is to skip this cleanup! This is fine when you are dealing
3794  * with a static tree that lives throughout your program.<br>
3795  * When you create a tree with a shorter lifespan, you'll need to pass
3796  * the constructor 'true' as argument in order to avoid memory leaks.
3797  */
3798  bool clearOnDestruct;
3799 };
3800 
3801 
3802 //
3803 // UTILITY CLASS "COMMAND": for executing & undoing actions
3804 //
3805 
3806 /** @brief Abstract base class for all commands.
3807  *
3808  * Command objects are designed for algorithms that need to keep track of
3809  * their decision, efficiently undo them and redo them.
3810  *
3811  * The key methods are:
3812  * - The constructor or other methods on the concrete subclasses
3813  * implement the state change.
3814  * - commit():
3815  * Makes the change permanently.
3816  * Undoing the change is no longer possible after calling this method.
3817  * - rollback():
3818  * Reverts the change permanently.
3819  * Redoing the change is no longer possible after calling this method.
3820  * - undo():
3821  * Temporarily reverts the change.
3822  * Redoing the change is still possible.
3823  * - redo():
3824  * Reactivates the change that was previously undone.
3825  */
3826 class Command
3827 {
3828  friend class CommandList;
3829  friend class CommandManager;
3831  public:
3832  /** Default constructor. The creation of a command should NOT execute the
3833  * command yet. The execute() method needs to be called explicitly to
3834  * do so.
3835  */
3836  Command() : owner(NULL), next(NULL), prev(NULL) {};
3837 
3838  /** This method makes the change permanent.<br>
3839  * A couple of notes on how this method should be implemented by the
3840  * subclasses:
3841  * - Calling the method multiple times is harmless. Only the first
3842  * call is expected to do something.
3843  */
3844  virtual void commit() {};
3845 
3846  /** This method permanently undoes the change.<br>
3847  * A couple of notes on how this method should be implemented by the
3848  * subclasses:
3849  * - Calling the rollback() method multiple times is harmless. Only
3850  * the first call is expected to do something.
3851  */
3852  virtual void rollback() {};
3853 
3854  /** This method temporarily undoes the change. The concrete subclasses
3855  * most maintain information that enables redoing the changes
3856  * efficiently.<br>
3857  * A couple of notes on how this method should be implemented by the
3858  * subclasses:
3859  * - Calling the method multiple times is harmless and results in the
3860  * same state change as calling it only once.
3861  */
3862  virtual void undo() {};
3863 
3864  /** This method reproduces a previously undone change.<br>
3865  * A couple of notes on how this method should be implemented by the
3866  * subclasses:
3867  * - Calling the method multiple times is harmless and results in the
3868  * same state change as calling it only once.
3869  */
3870  virtual void redo() {};
3871 
3872  /** Destructor. */
3873  virtual ~Command() {};
3874 
3875  private:
3876  /** Points to the commandlist which owns this command. The default value
3877  * is NULL, meaning there is no owner. */
3878  Command *owner;
3879 
3880  /** Points to the next command in the owner command list.<br>
3881  * The commands are chained in a double linked list data structure. */
3882  Command *next;
3883 
3884  /** Points to the previous command in the owner command list.<br>
3885  * The commands are chained in a double linked list data structure. */
3886  Command *prev;
3887 };
3888 
3889 
3890 /** @brief A container command to group a series of commands together.
3891  *
3892  * This class implements the "composite" design pattern in order to get an
3893  * efficient and intuitive hierarchical grouping of commands.
3894  * @todo handle exceptions during commit, rollback, undo, redo
3895  */
3896 class CommandList : public Command
3897 {
3898  private:
3899  /** Points to the first command in the list.<br>
3900  * Following commands can be found by following the next pointers
3901  * on the commands.<br>
3902  * The commands are this chained in a double linked list data structure.
3903  */
3904  Command* firstCommand;
3905 
3906  /** Points to the last command in the list. */
3907  Command* lastCommand;
3908  public:
3909  class iterator
3910  {
3911  public:
3912  /** Constructor. */
3913  iterator(Command* x) : cur(x) {}
3914 
3915  /** Copy constructor. */
3916  iterator(const iterator& it) {cur = it.cur;}
3917 
3918  /** Return the content of the current node. */
3919  Command& operator*() const {return *cur;}
3920 
3921  /** Return the content of the current node. */
3922  Command* operator->() const {return cur;}
3923 
3924  /** Pre-increment operator which moves the pointer to the next
3925  * element. */
3926  iterator& operator++()
3927  {
3928  cur = cur->next;
3929  return *this;
3930  }
3931 
3932  /** Post-increment operator which moves the pointer to the next
3933  * element. */
3934  iterator operator++(int)
3935  {
3936  iterator tmp = *this;
3937  cur = cur->next;
3938  return tmp;
3939  }
3940 
3941  /** Comparison operator. */
3942  bool operator==(const iterator& y) const {return cur==y.cur;}
3943 
3944  /** Inequality operator. */
3945  bool operator!=(const iterator& y) const {return cur!=y.cur;}
3946 
3947  private:
3948  Command* cur;
3949  };
3950 
3951  /** Returns an iterator over all commands in the list. */
3952  iterator begin() const {return iterator(firstCommand);}
3953 
3954  /** Returns an iterator beyond the last command. */
3955  iterator end() const {return iterator(NULL);}
3956 
3957  /** Append an additional command to the end of the list. */
3958  DECLARE_EXPORT void add(Command* c);
3959 
3960  /** Undoes all actions on the list.<br>
3961  * At the end it also clears the list of actions.
3962  */
3963  virtual DECLARE_EXPORT void rollback();
3964 
3965  /** Commits all actions on its list.<br>
3966  * At the end it also clears the list of actions.
3967  */
3968  virtual DECLARE_EXPORT void commit();
3969 
3970  /** Undoes all actions on its list.<br>
3971  * The list of actions is left intact, so the changes can still be redone.
3972  */
3973  virtual DECLARE_EXPORT void undo();
3974 
3975  /** Redoes all actions on its list.<br>
3976  * The list of actions is left intact, so the changes can still be undone.
3977  */
3978  DECLARE_EXPORT void redo();
3979 
3980  /** Returns true if no commands have been added yet to the list. */
3981  bool empty() const {return firstCommand==NULL;}
3982 
3983  /** Default constructor. */
3984  explicit CommandList() : firstCommand(NULL), lastCommand(NULL) {}
3985 
3986  /** Destructor.<br>
3987  * A commandlist should only be deleted when all of its commands
3988  * have been committed or undone. If this is not the case a warning
3989  * will be printed.
3990  */
3991  virtual DECLARE_EXPORT ~CommandList();
3992 };
3993 
3994 
3995 /** @brief This class allows management of tasks with supporting commiting them,
3996  * rolling them back, and setting bookmarks which can be undone and redone.
3997  */
3999 {
4000  public:
4001  /** A bookmark that keeps track of commands that can be undone and redone. */
4002  class Bookmark : public CommandList
4003  {
4004  friend class CommandManager;
4005  private:
4006  bool active;
4007  Bookmark* nextBookmark;
4008  Bookmark* prevBookmark;
4009  Bookmark* parent;
4010  Bookmark(Bookmark* p=NULL) : active(true),
4011  nextBookmark(NULL), prevBookmark(NULL), parent(p) {}
4012  public:
4013  /** Returns true if the bookmark commands are active. */
4014  bool isActive() const {return active;}
4015 
4016  /** Returns true if the bookmark is a child, grand-child or
4017  * grand-grand-child of the argument bookmark.
4018  */
4019  bool isChildOf(const Bookmark* b) const
4020  {
4021  for (const Bookmark* p = this; p; p = p->parent)
4022  if (p == b) return true;
4023  return false;
4024  }
4025  };
4026 
4027  /** An STL-like iterator to move over all bookmarks in forward order. */
4028  class iterator
4029  {
4030  public:
4031  /** Constructor. */
4032  iterator(Bookmark* x) : cur(x) {}
4033 
4034  /** Copy constructor. */
4035  iterator(const iterator& it) {cur = it.cur;}
4036 
4037  /** Return the content of the current node. */
4038  Bookmark& operator*() const {return *cur;}
4039 
4040  /** Return the content of the current node. */
4041  Bookmark* operator->() const {return cur;}
4042 
4043  /** Pre-increment operator which moves the pointer to the next
4044  * element. */
4045  iterator& operator++()
4046  {
4047  cur = cur->nextBookmark;
4048  return *this;
4049  }
4050 
4051  /** Post-increment operator which moves the pointer to the next
4052  * element. */
4053  iterator operator++(int)
4054  {
4055  iterator tmp = *this;
4056  cur = cur->nextBookmark;
4057  return tmp;
4058  }
4059 
4060  /** Comparison operator. */
4061  bool operator==(const iterator& y) const {return cur==y.cur;}
4062 
4063  /** Inequality operator. */
4064  bool operator!=(const iterator& y) const {return cur!=y.cur;}
4065 
4066  private:
4067  Bookmark* cur;
4068  };
4069 
4070  /** An STL-like iterator to move over all bookmarks in reverse order. */
4072  {
4073  public:
4074  /** Constructor. */
4075  reverse_iterator(Bookmark* x) : cur(x) {}
4076 
4077  /** Copy constructor. */
4078  reverse_iterator(const reverse_iterator& it) {cur = it.cur;}
4079 
4080  /** Return the content of the current node. */
4081  Bookmark& operator*() const {return *cur;}
4082 
4083  /** Return the content of the current node. */
4084  Bookmark* operator->() const {return cur;}
4085 
4086  /** Pre-increment operator which moves the pointer to the next
4087  * element. */
4088  reverse_iterator& operator++()
4089  {
4090  cur = cur->prevBookmark;
4091  return *this;
4092  }
4093 
4094  /** Post-increment operator which moves the pointer to the next
4095  * element. */
4096  reverse_iterator operator++(int)
4097  {
4098  reverse_iterator tmp = *this;
4099  cur = cur->prevBookmark;
4100  return tmp;
4101  }
4102 
4103  /** Comparison operator. */
4104  bool operator==(const reverse_iterator& y) const {return cur==y.cur;}
4105 
4106  /** Inequality operator. */
4107  bool operator!=(const reverse_iterator& y) const {return cur!=y.cur;}
4108 
4109  private:
4110  Bookmark* cur;
4111  };
4112 
4113  private:
4114  /** Head of a list of bookmarks.<br>
4115  * A command manager has always at least this default bookmark.
4116  */
4117  Bookmark firstBookmark;
4118 
4119  /** Tail of a list of bookmarks. */
4120  Bookmark* lastBookmark;
4121 
4122  /** Current bookmarks.<br>
4123  * If commands are added to the manager, this is the bookmark where
4124  * they'll be appended to.
4125  */
4126  Bookmark* currentBookmark;
4127 
4128  public:
4129  /** Constructor. */
4131  {
4132  lastBookmark = &firstBookmark;
4133  currentBookmark = &firstBookmark;
4134  }
4135 
4136  /** Destructor. */
4138  {
4139  for (Bookmark* i = lastBookmark; i && i != &firstBookmark; )
4140  {
4141  Bookmark* tmp = i;
4142  i = i->prevBookmark;
4143  delete tmp;
4144  }
4145  }
4146 
4147  /** Returns an iterator over all bookmarks in forward direction. */
4148  iterator begin() {return iterator(&firstBookmark);}
4149 
4150  /** Returns an iterator beyond the last bookmark in forward direction. */
4151  iterator end() {return iterator(NULL);}
4152 
4153  /** Returns an iterator over all bookmarks in reverse direction. */
4154  reverse_iterator rbegin() {return reverse_iterator(lastBookmark);}
4155 
4156  /** Returns an iterator beyond the last bookmark in reverse direction. */
4158 
4159  /** Add a command to the active bookmark. */
4160  void add(Command* c) {currentBookmark->add(c);}
4161 
4162  /** Create a new bookmark. */
4163  DECLARE_EXPORT Bookmark* setBookmark();
4164 
4165  /** Undo all commands in a bookmark (and its children).<br>
4166  * It can later be redone.<br>
4167  * The active bookmark in the manager is set to the parent of
4168  * argument bookmark.
4169  */
4170  DECLARE_EXPORT void undoBookmark(Bookmark*);
4171 
4172  /** Redo all commands in a bookmark (and its children).<br>
4173  * It can later still be undone.<br>
4174  * The active bookmark in the manager is set to the argument bookmark.
4175  */
4176  DECLARE_EXPORT void redoBookmark(Bookmark*);
4177 
4178  /** Undo all commands in a bookmark (and its children).<br>
4179  * It can no longer be redone. The bookmark does however still exist.
4180  */
4181  DECLARE_EXPORT void rollback(Bookmark*);
4182 
4183  /** Commit all commands. */
4184  DECLARE_EXPORT void commit();
4185 
4186  /** Rolling back all commands. */
4187  DECLARE_EXPORT void rollback();
4188 };
4189 
4190 
4191 //
4192 // INPUT PROCESSING CLASSES
4193 //
4194 
4195 
4196 /** @brief This class will read in an XML-file and call the appropriate
4197  * handler functions of the Object classes and objects.
4198  *
4199  * This class is implemented based on the Xerces SAX XML parser.
4200  * For debugging purposes a flag is defined at the start of the file
4201  * "xmlparser.cpp". Uncomment the line and recompile to use it.
4202  *
4203  * FrePPLe creates a new parser and loads the XML schema every time
4204  * XML data need to be parsed. When this happens only a few times during a
4205  * run this is good enough.<br>
4206  * However, when the libary has to parse plenty of small XML messages this
4207  * will create a significant overhead. The code would need to be enhanced
4208  * to maintain a pool of parsers and cache their grammars.
4209  */
4210 class XMLInput : public NonCopyable, private xercesc::DefaultHandler
4211 {
4212  public:
4213  typedef pair<Attribute,XMLElement> datapair;
4214 
4215  private:
4216  /** A pointer to an XML parser for processing the input. */
4217  xercesc::SAX2XMLReader* parser;
4218 
4219  /** This type defines the different states the parser can have. */
4220  enum state
4221  {
4222  /** The parser is sending input to an object handler. */
4223  READOBJECT,
4224  /** The parser has been instructed to ignore a tag. */
4225  IGNOREINPUT,
4226  /** The parser is shutting down, and will ignore all further data. */
4227  SHUTDOWN,
4228  /** This state is only used when the parser starts processing its first
4229  * tag. */
4230  INIT
4231  };
4232 
4233  /** This variable defines the maximum depth of the object creation stack.
4234  * This maximum is intended to protect us from malicious malformed
4235  * xml-documents, and also for allocating efficient data structures for
4236  * the parser.
4237  */
4238  const unsigned short maxdepth;
4239 
4240  /** Stack of states. */
4241  stack <state> states;
4242 
4243  /** Previous object in stack. */
4244  Object* prev;
4245 
4246  /** Stack of pairs. The pairs contain:
4247  * - A pointer to an event handler object. The beginElement and
4248  * endElement methods of this object will be called.
4249  * - A user definable pointer. The purpose of this pointer is to store
4250  * status information between calls to the handler.
4251  */
4252  vector< pair<Object*,void*> > m_EHStack;
4253 
4254  /** Stack of elements.<br>
4255  * The expression m_EStack[numElements+1] returns the current element.<br>
4256  * The expression m_EStack[numElements] returns the parent element.
4257  * @see numElements
4258  */
4259  vector<datapair> m_EStack;
4260 
4261  /** A variable to keep track of the size of the element stack. It is used
4262  * together with the variable m_EStack.
4263  * @see m_EStack
4264  */
4265  short numElements;
4266 
4267  /** This field counts how deep we are in a nested series of ignored input.
4268  * It is represented as a counter since the ignored element could contain
4269  * itself.
4270  */
4271  unsigned short ignore;
4272 
4273  /** Hash value of the current element. */
4274  stack<hashtype> endingHashes;
4275 
4276  /** This variable is normally false. It is switched to true only a) in
4277  * the method endElement() of Object objects and b) when an object
4278  * is processing its closing tag.
4279  */
4280  bool objectEnded;
4281 
4282  /** This field controls whether we continue processing after data errors
4283  * or whether we abort processing the remaining XML data.<br>
4284  * Selecting the right mode is important:
4285  * - Setting the flag to false is appropriate for processing large
4286  * amounts of a bulk-load operation. In this mode a single, potentially
4287  * minor, data problem won't abort the complete process.
4288  * - Setting the flag to true is most appropriate to process small and
4289  * frequent messages from client applications. In this mode client
4290  * applications are notified about data problems.
4291  * - The default setting is true, in order to provide a maximum level of
4292  * security for the application.
4293  */
4294  bool abortOnDataException;
4295 
4296  /** This is a pointer to the attributes.
4297  * See the xerces API documentation for further information on the usage
4298  * of the attribute list.
4299  */
4300  XMLAttributeList attributes;
4301 
4302  /** A Python callback function that is called once an object has been read
4303  * from the XML input. The return value is not used.
4304  */
4305  PythonFunction userexit;
4306 
4307  /** Handler called when a new element tag is encountered.
4308  * It pushes a new element on the stack and calls the current handler.
4309  */
4310  DECLARE_EXPORT void startElement (const XMLCh* const, const XMLCh* const,
4311  const XMLCh* const, const xercesc::Attributes&);
4312 
4313  /** Handler called when closing element tag is encountered.
4314  * If this is the closing tag for the current event handler, pop it
4315  * off the handler stack. If this empties the stack, shut down parser.
4316  * Otherwise, just feed the element with the already completed
4317  * data section to the current handler, then pop it off the element
4318  * stack.
4319  */
4320  DECLARE_EXPORT void endElement
4321  (const XMLCh* const, const XMLCh* const, const XMLCh* const);
4322 
4323  /** Handler called when character data are read in.
4324  * The data string is add it to the current element data.
4325  */
4326 #if XERCES_VERSION_MAJOR==2
4327  DECLARE_EXPORT void characters(const XMLCh *const, const unsigned int);
4328 #else
4329  DECLARE_EXPORT void characters(const XMLCh *const, const XMLSize_t);
4330 #endif
4331 
4332  /** Handler called by Xerces in fatal error conditions. It throws an
4333  * exception to abort the parsing procedure. */
4334  DECLARE_EXPORT void fatalError (const xercesc::SAXParseException&);
4335 
4336  /** Handler called by Xercess when reading a processing instruction. The
4337  * handler looks up the target in the repository and will call the
4338  * registered XMLinstruction.
4339  * @see XMLinstruction
4340  */
4341  DECLARE_EXPORT void processingInstruction (const XMLCh *const, const XMLCh *const);
4342 
4343  /** Handler called by Xerces in error conditions. It throws an exception
4344  * to abort the parsing procedure. */
4345  DECLARE_EXPORT void error (const xercesc::SAXParseException&);
4346 
4347  /** Handler called by Xerces for warnings. */
4348  DECLARE_EXPORT void warning (const xercesc::SAXParseException&);
4349 
4350  /** This method cleans up the parser state to get it ready for processing
4351  * a new document. */
4352  DECLARE_EXPORT void reset();
4353 
4354  /** Return a pointer to the current object being read in. */
4355  inline Object* getCurrentObject() const {return m_EHStack[m_EHStack.size()-1].first;}
4356 
4357  public:
4358  /** Constructor.
4359  * @param maxNestedElmnts Defines the maximum depth of elements an XML
4360  * document is allowed to have. The default is 20.
4361  */
4362  XMLInput(unsigned short maxNestedElmnts = 20)
4363  : parser(NULL), maxdepth(maxNestedElmnts), m_EStack(maxNestedElmnts+2),
4364  numElements(-1), ignore(0), objectEnded(false),
4365  abortOnDataException(true), attributes(NULL) {}
4366 
4367  /** Destructor. */
4368  virtual ~XMLInput() {reset();}
4369 
4370  /** Return a pointer to an array of character pointer which point
4371  * to the attributes. See the xerces documentation if this description
4372  * doesn't satisfy you...
4373  */
4374  const AttributeList& getAttributes() const {return attributes;}
4375 
4376  /** Redirect event stream into a new Object.<br>
4377  * It is also possible to pass a NULL pointer to the function. In
4378  * that situation, we simple ignore the content of that element.<br>
4379  * Important: The user is reponsible of making sure the argument
4380  * object has a proper write-lock. The release of that lock is handled
4381  * by the parser.
4382  */
4383  DECLARE_EXPORT void readto(Object*);
4384 
4385  /** Abort the parsing.
4386  * The actual shutdown cannot be called inside a SAX handler function,
4387  * so actual shutdown is deferred until the next iteration of the feed
4388  * loop.
4389  */
4390  void shutdown();
4391 
4392  /** Ignore an element. */
4393  void IgnoreElement() {readto(NULL);}
4394 
4395  /** Returns true if the current object is finishing with the current
4396  * tag. This method should only be used in the endElement() method. */
4397  bool isObjectEnd() {return objectEnded;}
4398 
4399  /** Invalidates the current object.<br>
4400  * This method is useful when, for instance, the object being parsed
4401  * is being deleted.
4402  */
4403  void invalidateCurrentObject()
4404  {
4405  if (!m_EHStack.empty())
4406  m_EHStack[m_EHStack.size()-1].first = NULL;
4407  }
4408 
4409  /** Return a pointer to the previous object being read in.<br>
4410  * In a typical use the returned pointer will require a dynamic_cast
4411  * to a subclass type.<br>
4412  * The typical usage is as follows:
4413  * <pre>
4414  * Operation *o = dynamic_cast<Operation*>(pIn.getPreviousObject());
4415  * if (o) doSomeThing(o);
4416  * else throw LogicException("Incorrect object type");
4417  * </pre>
4418  */
4419  Object* getPreviousObject() const {return prev;}
4420 
4421  /** Clears the previously read object. */
4422  Object* getParentObject() const
4423  {
4424  int x = m_EHStack.size();
4425  return x>1 ? m_EHStack[x-2].first : NULL;
4426  }
4427 
4428  /** Returns a reference to the parent element. */
4429  const datapair& getParentElement() const
4430  {return m_EStack[numElements>0 ? numElements : 0];}
4431 
4432  /** Returns a reference to the current element. */
4433  const datapair& getCurrentElement() const
4434  {return m_EStack[numElements>-1 ? numElements+1 : 0];}
4435 
4436  /** This is the core parsing function, which triggers the XML parser to
4437  * start processing the input. It is normally called from the method
4438  * parse(Object*) once a proper stream has been created.
4439  * @see parse(Object*)
4440  */
4441  void parse(xercesc::InputSource&, Object*, bool=false);
4442 
4443  /** Updates the user definable pointer. This pointer is used to store
4444  * status information between handler calls. */
4445  void setUserArea(void* v)
4446  {if (!m_EHStack.empty()) m_EHStack[m_EHStack.size()-1].second = v;}
4447 
4448  /** Returns the user definable pointer. */
4449  void* getUserArea() const
4450  {return m_EHStack.empty() ? NULL : m_EHStack[m_EHStack.size()-1].second;}
4451 
4452  /** Updates whether we ignore data exceptions or whether we abort the
4453  * processing of the XML data stream. */
4454  void setAbortOnDataError(bool i) {abortOnDataException = i;}
4455 
4456  /** Returns the behavior of the parser in case of data errors.<br>
4457  * When true is returned, the processing of the XML stream continues
4458  * after a DataException. Other, more critical, exceptions types will
4459  * still abort the parsing process.<br>
4460  * False indicates that the processing of the XML stream is aborted.
4461  */
4462  bool getAbortOnDataError() const {return abortOnDataException;}
4463 
4464  /** Specify a Python callback function that is for every object read
4465  * from the input stream.
4466  */
4467  void setUserExit(PyObject* p) {userexit = p;}
4468 
4469  /** Return the Python callback function. */
4470  PythonFunction getUserExit() const {return userexit;}
4471 
4472  protected:
4473  /** The real parsing job is delegated to subclasses.
4474  * Subclass can then define the specifics for parsing a flat file,
4475  * a string, a SOAP message, etc...
4476  * @exception RuntimeException Thrown in the following situations:
4477  * - the XML-document is incorrectly formatted
4478  * - the XML-parser librabry can't be initialized
4479  * - no memory can be allocated to the xml-parser
4480  * @exception DataException Thrown when the data can't be processed
4481  * normally by the objects being created or updated.
4482  */
4483  virtual void parse(Object* s, bool b=false)
4484  {
4485  throw LogicException("Unreachable code reached");
4486  }
4487 };
4488 
4489 
4490 /** @brief This class reads XML data from a string. */
4491 class XMLInputString : public XMLInput
4492 {
4493  public:
4494  /** Default constructor. */
4495  XMLInputString(const string& s) : data(s) {};
4496 
4497  /** Parse the specified string. */
4498  void parse(Object* pRoot, bool v = false)
4499  {
4500  /* The MemBufInputSource expects the number of bytes as second parameter.
4501  * In our case this is the same as the number of characters, but this
4502  * will not apply any more for character sets with multi-byte
4503  * characters.
4504  */
4505  xercesc::MemBufInputSource a(
4506  reinterpret_cast<const XMLByte*>(data.c_str()),
4507  static_cast<const unsigned int>(data.size()),
4508  "memory data",
4509  false);
4510  XMLInput::parse(a,pRoot,v);
4511  }
4512 
4513  private:
4514  /** String containing the data to be parsed. Note that NO local copy of the
4515  * data is made, only a reference is stored. The class relies on the code
4516  * calling the command to correctly create and destroy the string being
4517  * used.
4518  */
4519  const string data;
4520 };
4521 
4522 
4523 /** @brief This class reads XML data from a file system.
4524  *
4525  * The filename argument can be the name of a file or a directory.
4526  * If a directory is passed, all files with the extension ".xml"
4527  * will be read from it. Subdirectories are not recursed.
4528  */
4529 class XMLInputFile : public XMLInput
4530 {
4531  public:
4532  /** Constructor. The argument passed is the name of a
4533  * file or a directory. */
4534  XMLInputFile(const string& s) : filename(s) {};
4535 
4536  /** Default constructor. */
4538 
4539  /** Update the name of the file to be processed. */
4540  void setFileName(const string& s) {filename = s;}
4541 
4542  /** Returns the name of the file or directory to process. */
4543  string getFileName() {return filename;}
4544 
4545  /** Parse the specified file.
4546  * When a directory was passed as the argument a failure is
4547  * flagged as soon as a single file returned a failure. All
4548  * files in an directory are processed however, regardless of
4549  * failure with one of the files.
4550  * @exception RuntimeException Generated in the following conditions:
4551  * - no input file or directory has been specified.
4552  * - read access to the input file is not available
4553  * - the program doesn't support reading directories on your platform
4554  */
4555  DECLARE_EXPORT void parse(Object*, bool=false);
4556 
4557  private:
4558  /** Name of the file to be opened. */
4559  string filename;
4560 };
4561 
4562 
4563 //
4564 // UTILITY CLASSES "HASNAME", "HASHIERARCHY", "HASDESCRIPTION"
4565 //
4566 
4567 
4568 /** @brief Base class for objects using a string as their primary key.
4569  *
4570  * Instances of this class have the following properties:
4571  * - Have a unique name.
4572  * - A hashtable (keyed on the name) is maintained as a container with
4573  * all active instances.
4574  */
4575 template <class T> class HasName : public NonCopyable, public Tree::TreeNode, public Object
4576 {
4577  private:
4578  /** Maintains a global list of all created entities. The list is keyed
4579  * by the name. */
4580  static DECLARE_EXPORT Tree st;
4581  typedef T* type;
4582 
4583  public:
4584  /** @brief This class models a STL-like iterator that allows us to
4585  * iterate over the named entities in a simple and safe way.
4586  *
4587  * Objects of this class are created by the begin() and end() functions.
4588  */
4589  class iterator
4590  {
4591  public:
4592  /** Constructor. */
4593  iterator(Tree::TreeNode* x) : node(x) {}
4594 
4595  /** Copy constructor. */
4596  iterator(const iterator& it) {node = it.node;}
4597 
4598  /** Return the content of the current node. */
4599  T& operator*() const {return *static_cast<T*>(node);}
4600 
4601  /** Return the content of the current node. */
4602  T* operator->() const {return static_cast<T*>(node);}
4603 
4604  /** Pre-increment operator which moves the pointer to the next
4605  * element. */
4606  iterator& operator++() {node = node->increment(); return *this;}
4607 
4608  /** Post-increment operator which moves the pointer to the next
4609  * element. */
4610  iterator operator++(int)
4611  {
4612  Tree::TreeNode* tmp = node;
4613  node = node->increment();
4614  return tmp;
4615  }
4616 
4617  /** Pre-decrement operator which moves the pointer to the previous
4618  * element. */
4619  iterator& operator--() {node = node->decrement(); return *this;}
4620 
4621  /** Post-decrement operator which moves the pointer to the previous
4622  * element. */
4623  iterator operator--(int)
4624  {
4625  Tree::TreeNode* tmp = node;
4626  node = node->decrement();
4627  return tmp;
4628  }
4629 
4630  /** Comparison operator. */
4631  bool operator==(const iterator& y) const {return node==y.node;}
4632 
4633  /** Inequality operator. */
4634  bool operator!=(const iterator& y) const {return node!=y.node;}
4635 
4636  private:
4637  Tree::TreeNode* node;
4638  };
4639 
4640  /** Returns a STL-like iterator to the end of the entity list. */
4641  static iterator end() {return st.end();}
4642 
4643  /** Returns a STL-like iterator to the start of the entity list. */
4644  static iterator begin() {return st.begin();}
4645 
4646  /** Returns false if no named entities have been defined yet. */
4647  static bool empty() {return st.empty();}
4648 
4649  /** Returns the number of defined entities. */
4650  static size_t size() {return st.size();}
4651 
4652  /** Debugging method to verify the validity of the tree.
4653  * An exception is thrown when the tree is corrupted. */
4654  static void verify() {st.verify();}
4655 
4656  /** Deletes all elements from the list. */
4657  static void clear() {st.clear();}
4658 
4659  /** Constructor. */
4660  explicit HasName(const string& n) : Tree::TreeNode(n) {}
4661 
4662  /** Constructor. */
4663  explicit HasName(const char* n) : Tree::TreeNode(n) {}
4664 
4665  /** Rename the entity. */
4666  void setName(const string& newname) {st.rename(this, newname);}
4667 
4668  /** Destructor. */
4669  ~HasName() {st.erase(this);}
4670 
4671  /** Return the name as the string representation in Python. */
4672  virtual PyObject* str() const {return PythonObject(getName());}
4673 
4674  /** Comparison operator for Python. */
4675  int compare(const PyObject* other) const
4676  {
4677  if (this->ob_type == other->ob_type
4678  || this->ob_type->tp_base == other->ob_type->tp_base)
4679  return getName().compare(static_cast<const T*>(other)->getName());
4680  else
4681  {
4682  // Different types
4683  PyErr_SetString(PythonDataException, "Wrong type in comparison");
4684  return -1;
4685  }
4686  }
4687 
4688  /** Find an entity given its name. In case it can't be found, a NULL
4689  * pointer is returned. */
4690  static T* find(const string& k)
4691  {
4692  Tree::TreeNode *i = st.find(k);
4693  return (i!=st.end() ? static_cast<T*>(i) : NULL);
4694  }
4695 
4696  /** Find the element with this given key or the element
4697  * immediately preceding it.<br>
4698  * The optional second argument is a boolean that is set to true when
4699  * the element is found in the list.
4700  */
4701  static T* findLowerBound(const string& k, bool *f = NULL)
4702  {
4703  Tree::TreeNode *i = st.findLowerBound(k, f);
4704  return (i!=st.end() ? static_cast<T*>(i) : NULL);
4705  }
4706 
4707  /** Creates a new entity. */
4708  static T* add(const string& k, const MetaClass& cls)
4709  {
4710  Tree::TreeNode *i = st.find(k);
4711  if (i!=st.end()) return static_cast<T*>(i); // Exists already
4712  if (*(cls.category) != T::metadata)
4713  throw LogicException("Invalid type " + cls.type +
4714  " for creating an object of category " + T::metadata.type);
4715  T *t = dynamic_cast<T*>(cls.factoryMethodString(k));
4716  st.insert(t);
4717  return t;
4718  }
4719 
4720  /** Registers an entity created by the default constructor. */
4721  static T* add(T* t) {return static_cast<T*>(st.insert(t));}
4722 
4723  /** Registers an entity created by the default constructor. The second
4724  * argument is a hint: when passing an entity with a name close to
4725  * the new one, the insertion will be sped up considerably.
4726  */
4727  static T* add(T* t, T* hint) {return static_cast<T*>(st.insert(t,hint));}
4728 
4729  void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement) {};
4730 
4731  /** This method is available as a object creation factory for
4732  * classes that are using a string as a key identifier, in particular
4733  * classes derived from the HasName base class.
4734  * The following attributes are recognized:
4735  * - name:<br>
4736  * Name of the entity to be created/changed/removed.<br>
4737  * The default value is "unspecified".
4738  * - type:<br>
4739  * Determines the subclass to be created.<br>
4740  * The default value is "default".
4741  * - action:<br>
4742  * Determines the action to be performed on the object.<br>
4743  * This can be A (for 'add'), C (for 'change'), AC (for 'add_change')
4744  * or R (for 'remove').<br>
4745  * 'add_change' is the default value.
4746  * @see HasName
4747  */
4748  static Object* reader (const MetaClass* cat, const AttributeList& in)
4749  {
4750  // Pick up the action attribute
4751  Action act = MetaClass::decodeAction(in);
4752 
4753  // Pick up the name attribute. An error is reported if it's missing.
4754  const DataElement* nameElement = in.get(Tags::tag_name);
4755  if (!*nameElement) throw DataException("Missing name attribute");
4756  string name = nameElement->getString();
4757 
4758  // Check if it exists already
4759  bool found;
4760  T *i = T::findLowerBound(name, &found);
4761 
4762  // Validate the action
4763  switch (act)
4764  {
4765  case ADD:
4766  // Only additions are allowed
4767  if (found)
4768  throw DataException("Object '" + name + "' already exists");
4769  break;
4770 
4771  case CHANGE:
4772  // Only changes are allowed
4773  if (!found)
4774  throw DataException("Object '" + name + "' doesn't exist");
4775  return i;
4776 
4777  case REMOVE:
4778  // Delete the entity
4779  if (found)
4780  {
4781  // Send out the notification to subscribers
4782  if (i->getType().raiseEvent(i,SIG_REMOVE))
4783  {
4784  // Delete the object
4785  delete i;
4786  return NULL;
4787  }
4788  else
4789  // The callbacks disallowed the deletion!
4790  throw DataException("Can't remove object '" + name + "'");
4791  }
4792  else
4793  // Not found
4794  throw DataException("Can't find object '" + name + "' for removal");
4795  default:
4796  // case ADD_CHANGE doesn't have special cases.
4797  ;
4798  }
4799 
4800  // Return the existing instance
4801  if (found) return i;
4802 
4803  // Lookup the type in the map
4804  const MetaClass* j;
4805  if (cat->category)
4806  // Class metadata passed: we already know what type to create
4807  j = cat;
4808  else
4809  {
4810  // Category metadata passed: we need to look up the type
4811  const DataElement* type = in.get(Tags::tag_type);
4812  j = static_cast<const MetaCategory&>(*cat).findClass(
4813  *type ? Keyword::hash(type->getString()) : MetaCategory::defaultHash
4814  );
4815  if (!j)
4816  {
4817  string t(*type ? type->getString() : "default");
4818  throw DataException("No type " + t + " registered for category " + cat->type);
4819  }
4820  }
4821 
4822  // Create a new instance
4823  T* x = dynamic_cast<T*>(j->factoryMethodString(name));
4824 
4825  // Run creation callbacks
4826  // During the callback there is no write lock set yet, since we can
4827  // assume we are the only ones aware of this new object. We also want
4828  // to make sure the 'add' signal comes before the 'before_change'
4829  // callback that is part of the writelock.
4830  if (!x->getType().raiseEvent(x,SIG_ADD))
4831  {
4832  // Creation isn't allowed
4833  delete x;
4834  throw DataException("Can't create object " + name);
4835  }
4836 
4837  // Insert in the tree
4838  T::add(x, i);
4839  return x;
4840  }
4841 
4842  /** A handler that is used to persist the tree. */
4843  static void writer(const MetaCategory* c, XMLOutput* o)
4844  {
4845  if (empty()) return;
4846  o->BeginObject(*(c->grouptag));
4847  for (iterator i = begin(); i != end(); ++i)
4848  o->writeElement(*(c->typetag), *i);
4849  o->EndObject(*(c->grouptag));
4850  }
4851 };
4852 
4853 
4854 /** @brief This is a decorator class for the main objects.
4855  *
4856  * Instances of this class have a description, category and sub_category.
4857  */
4859 {
4860  public:
4861  /** Returns the category. */
4862  string getCategory() const {return cat;}
4863 
4864  /** Returns the sub_category. */
4865  string getSubCategory() const {return subcat;}
4866 
4867  /** Returns the getDescription. */
4868  string getDescription() const {return descr;}
4869 
4870  /** Sets the category field. */
4871  void setCategory(const string& f) {cat = f;}
4872 
4873  /** Sets the sub_category field. */
4874  void setSubCategory(const string& f) {subcat = f;}
4875 
4876  /** Sets the description field. */
4877  void setDescription(const string& f) {descr = f;}
4878 
4879  void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
4880  void endElement(XMLInput&, const Attribute&, const DataElement&);
4881 
4882  protected:
4883  /** Returns the memory size in bytes. */
4884  size_t extrasize() const {return cat.size() + subcat.size() + descr.size();}
4885 
4886  private:
4887  string cat;
4888  string subcat;
4889  string descr;
4890 };
4891 
4892 
4893 /** @brief This is a base class for the main objects.
4894  *
4895  * Instances of this class have the following properties:
4896  * - Unique name and global hashtable are inherited from the class HasName.
4897  * - Instances build up hierarchical trees of arbitrary depth.
4898  * - Each object can have a single parent only.
4899  * - Each object has a parent and can have children.
4900  * This class thus implements the 'composite' design pattern.
4901  * The internal data structure is a singly linked linear list, which is
4902  * efficient provided the number of childre remains limited.
4903  */
4904 template <class T> class HasHierarchy : public HasName<T>
4905 {
4906  public:
4907  class memberIterator;
4908  friend class memberIterator;
4909  /** @brief This class models an STL-like iterator that allows us to
4910  * iterate over the members.
4911  *
4912  * Objects of this class are created by the beginMember() method.
4913  */
4915  {
4916  public:
4917  /** Constructor to iterate over member entities. */
4918  memberIterator(const HasHierarchy<T>* x) : member_iter(true)
4919  {curmember = const_cast<HasHierarchy<T>*>(x)->first_child;}
4920 
4921  /** Constructor to iterate over all entities. */
4922  memberIterator() : curmember(&*T::begin()), member_iter(false) {}
4923 
4924  /** Constructor. */
4925  memberIterator(const typename HasName<T>::iterator& it) : curmember(&*it), member_iter(false) {}
4926 
4927  /** Copy constructor. */
4929  {
4930  curmember = it.curmember;
4931  member_iter = it.member_iter;
4932  }
4933 
4934  /** Return the content of the current node. */
4935  T& operator*() const {return *static_cast<T*>(curmember);}
4936 
4937  /** Return the content of the current node. */
4938  T* operator->() const {return static_cast<T*>(curmember);}
4939 
4940  /** Pre-increment operator which moves the pointer to the next member. */
4941  memberIterator& operator++()
4942  {
4943  if (member_iter)
4944  curmember = curmember->next_brother;
4945  else
4946  curmember = static_cast<T*>(curmember->increment());
4947  return *this;
4948  }
4949 
4950  /** Post-increment operator which moves the pointer to the next member. */
4951  memberIterator operator++(int)
4952  {
4953  memberIterator tmp = *this;
4954  if (member_iter)
4955  curmember = curmember->next_brother;
4956  else
4957  curmember = static_cast<T*>(curmember->increment());
4958  return tmp;
4959  }
4960 
4961  /** Comparison operator. */
4962  bool operator==(const memberIterator& y) const
4963  {return curmember == y.curmember;}
4964 
4965  /** Inequality operator. */
4966  bool operator!=(const memberIterator& y) const
4967  {return curmember != y.curmember;}
4968 
4969  /** Comparison operator. */
4970  bool operator==(const typename HasName<T>::iterator& y) const
4971  {return curmember ? (curmember == &*y) : (y == T::end());}
4972 
4973  /** Inequality operator. */
4974  bool operator!=(const typename HasName<T>::iterator& y) const
4975  {return curmember ? (curmember != &*y) : (y != T::end());}
4976 
4977  private:
4978  /** Points to a member. */
4979  HasHierarchy<T>* curmember;
4980  bool member_iter;
4981  };
4982 
4983  /** The one and only constructor. */
4984  HasHierarchy(const string& n) : HasName<T>(n), parent(NULL),
4985  first_child(NULL), next_brother(NULL) {}
4986 
4987  /** Destructor.
4988  * When deleting a node of the hierarchy, the children will get the
4989  * current parent as the new parent.
4990  * In this way the deletion of nodes doesn't create "dangling branches"
4991  * in the hierarchy. We just "collapse" a certain level.
4992  */
4993  ~HasHierarchy();
4994 
4995  /** Return a member iterator. */
4996  memberIterator beginMember() const {return this;}
4997 
4998  /** Returns true if this entity belongs to a higher hierarchical level.<br>
4999  * An entity can have only a single owner, and can't belong to multiple
5000  * hierarchies.
5001  */
5002  bool hasOwner() const {return parent!=NULL;}
5003 
5004  /** Returns true if this entity has lower level entities belonging to
5005  * it. */
5006  bool isGroup() const {return first_child!=NULL;}
5007 
5008  /** Changes the owner of the entity.<br>
5009  * The argument must be a valid pointer to an entity of the same type.<br>
5010  * A NULL pointer can be passed to clear the existing owner.<br>
5011  */
5012  void setOwner(T* f);
5013 
5014  /** Returns the owning entity. */
5015  T* getOwner() const {return parent;}
5016 
5017  /** Returns the level in the hierarchy.<br>
5018  * Level 0 means the entity doesn't have any parent.<br>
5019  * Level 1 means the entity has a parent entity with level 0.<br>
5020  * Level "x" means the entity has a parent entity whose level is "x-1".
5021  */
5022  unsigned short getHierarchyLevel() const;
5023 
5024  void beginElement(XMLInput&, const Attribute&);
5025  void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
5026  void endElement(XMLInput&, const Attribute&, const DataElement&);
5027 
5028  private:
5029  /** A pointer to the parent object. */
5030  T *parent;
5031 
5032  /** A pointer to the first child object. */
5033  T *first_child;
5034 
5035  /** A pointer to the next brother object, ie an object having the
5036  * same parent.<br>
5037  * The brothers are all linked as a single linked list, with the
5038  * first_child pointer on the parent being the root pointer of the list.
5039  */
5040  T *next_brother;
5041 };
5042 
5043 
5044 //
5045 // ASSOCIATION
5046 //
5047 
5048 /** @brief This template class represents a data structure for a load or flow
5049  * network.
5050  *
5051  * A node class has pointers to 2 root classes.<br> The 2 root classes each
5052  * maintain a singly linked list of nodes.<br>
5053  * An example to clarify the usage:
5054  * - class "node" = a newspaper subscription.
5055  * - class "person" = maintains a list of all his subscriptions.
5056  * - class "newspaper" = maintains a list of all subscriptions for it.
5057  *
5058  * This data structure could be replaced with 2 linked lists, but this
5059  * specialized data type consumes considerably lower memory.
5060  *
5061  * Reading from the structure is safe in multi-threading mode.<br>
5062  * Updates to the data structure in a multi-threading mode require the user
5063  * to properly lock and unlock the container.
5064  */
5065 template <class A, class B, class C> class Association
5066 {
5067  public:
5068  class Node;
5069  private:
5070  /** @brief A abstract base class for the internal representation of the
5071  * association lists.
5072  */
5073  class List
5074  {
5075  friend class Node;
5076  public:
5077  C* first;
5078  public:
5079  List() : first(NULL) {};
5080  bool empty() const {return first==NULL;}
5081  };
5082 
5083  public:
5084  /** @brief A list type of the "first" / "from" part of the association. */
5085  class ListA : public List
5086  {
5087  public:
5088  ListA() {};
5089  /** @brief An iterator over the associated objects. */
5090  class iterator
5091  {
5092  protected:
5094  public:
5095  iterator(C* n) : nodeptr(n) {};
5096  C& operator*() const {return *nodeptr;}
5097  C* operator->() const {return nodeptr;}
5098  bool operator==(const iterator& x) const
5099  {return nodeptr == x.nodeptr;}
5100  bool operator!=(const iterator& x) const
5101  {return nodeptr != x.nodeptr;}
5102  iterator& operator++()
5103  {nodeptr = nodeptr->nextA; return *this;}
5104  iterator operator++(int i)
5105  {
5106  iterator j = *this;
5107  nodeptr = nodeptr->nextA;
5108  return j;
5109  }
5110  };
5111  /** @brief An iterator over the associated objects. */
5113  {
5114  protected:
5116  public:
5117  const_iterator(C* n) : nodeptr(n) {};
5118  const C& operator*() const {return *nodeptr;}
5119  const C* operator->() const {return nodeptr;}
5120  bool operator==(const const_iterator& x) const
5121  {return nodeptr == x.nodeptr;}
5122  bool operator!=(const const_iterator& x) const
5123  {return nodeptr != x.nodeptr;}
5124  const_iterator& operator++()
5125  {nodeptr = nodeptr->nextA; return *this;}
5126  const_iterator operator++(int i)
5127  {
5128  const_iterator j = *this;
5129  nodeptr = nodeptr->nextA;
5130  return j;
5131  }
5132  };
5133  iterator begin() {return iterator(this->first);}
5134  const_iterator begin() const {return const_iterator(this->first);}
5135  iterator end() {return iterator(NULL);}
5136  const_iterator end() const {return const_iterator(NULL);}
5137 
5138  /** Destructor. */
5140  {
5141  C* next;
5142  for (C* p=this->first; p; p=next)
5143  {
5144  next = p->nextA;
5145  delete p;
5146  }
5147  }
5148 
5149  /** Remove an association. */
5150  void erase(const C* n)
5151  {
5152  if (!n) return;
5153  if (n==this->first)
5154  this->first = n->nextA;
5155  else
5156  for (C* p=this->first; p; p=p->nextA)
5157  if(p->nextA == n)
5158  {
5159  p->nextA = n->nextA;
5160  return;
5161  }
5162  }
5163 
5164  /** Return the number of associations. */
5165  size_t size() const
5166  {
5167  size_t i(0);
5168  for (C* p = this->first; p; p=p->nextA) ++i;
5169  return i;
5170  }
5171 
5172  /** Search for the association effective at a certain date. */
5173  C* find(const B* b, Date d = Date::infinitePast) const
5174  {
5175  for (C* p=this->first; p; p=p->nextA)
5176  if (p->ptrB == b && p->effectivity.within(d)) return p;
5177  return NULL;
5178  }
5179 
5180  /** Search for the association with a certain name. */
5181  C* find(const string& n) const
5182  {
5183  for (C* p=this->first; p; p=p->nextA)
5184  if (p->name == n) return p;
5185  return NULL;
5186  }
5187 
5188  /** Move an association a position up in the list of associations. */
5189  void promote(C* p)
5190  {
5191  // Already at the head
5192  if (p == this->first) return;
5193 
5194  // Scan the list
5195  C* prev = NULL;
5196  for (C* ptr = this->first; ptr; ptr = ptr->nextA)
5197  {
5198  if (ptr->nextA == p)
5199  {
5200  if (prev)
5201  prev->nextA = p;
5202  else
5203  this->first = p;
5204  ptr->nextA = p->nextA;
5205  p->nextA = ptr;
5206  return;
5207  }
5208  prev = ptr;
5209  }
5210  throw LogicException("Association not found in the list");
5211  }
5212  };
5213 
5214  /** @brief A list type of the "second" / "to" part of the association. */
5215  class ListB : public List
5216  {
5217  public:
5218  ListB() {};
5219  /** @brief An iterator over the associated objects. */
5220  class iterator
5221  {
5222  protected:
5224  public:
5225  iterator(C* n) : nodeptr(n) {};
5226  C& operator*() const {return *nodeptr;}
5227  C* operator->() const {return nodeptr;}
5228  bool operator==(const iterator& x) const
5229  {return nodeptr == x.nodeptr;}
5230  bool operator!=(const iterator& x) const
5231  {return nodeptr != x.nodeptr;}
5232  iterator& operator++()
5233  {nodeptr = nodeptr->nextB; return *this;}
5234  iterator operator++(int i)
5235  {
5236  iterator j = *this;
5237  nodeptr = nodeptr->nextA;
5238  return j;
5239  }
5240  };
5241  /** @brief An iterator over the associated objects. */
5243  {
5244  protected:
5246  public:
5247  const_iterator(C* n) : nodeptr(n) {};
5248  const C& operator*() const {return *nodeptr;}
5249  const C* operator->() const {return nodeptr;}
5250  bool operator==(const const_iterator& x) const
5251  {return nodeptr == x.nodeptr;}
5252  bool operator!=(const const_iterator& x) const
5253  {return nodeptr != x.nodeptr;}
5254  const_iterator& operator++()
5255  {nodeptr = nodeptr->nextB; return *this;}
5256  const_iterator operator++(int i)
5257  {
5258  const_iterator j = *this;
5259  nodeptr = nodeptr->nextA;
5260  return j;
5261  }
5262  };
5263 
5264  /** Destructor. */
5266  {
5267  C* next;
5268  for (C* p=this->first; p; p=next)
5269  {
5270  next = p->nextB;
5271  delete p;
5272  }
5273  }
5274  iterator begin() {return iterator(this->first);}
5275  const_iterator begin() const {return const_iterator(this->first);}
5276  iterator end() {return iterator(NULL);}
5277  const_iterator end() const {return const_iterator(NULL);}
5278 
5279  /** Remove an association. */
5280  void erase(const C* n)
5281  {
5282  if (!n) return;
5283  if (n==this->first)
5284  this->first = n->nextB;
5285  else
5286  for (C* p=this->first; p; p=p->nextB)
5287  if(p->nextB == n)
5288  {
5289  p->nextB = n->nextB;
5290  return;
5291  }
5292  }
5293 
5294  /** Return the number of associations. */
5295  size_t size() const
5296  {
5297  size_t i(0);
5298  for (C* p=this->first; p; p=p->nextB) ++i;
5299  return i;
5300  }
5301 
5302  /** Search for the association effective at a certain date. */
5303  C* find(const A* b, Date d = Date::infinitePast) const
5304  {
5305  for (C* p=this->first; p; p=p->nextB)
5306  if (p->ptrA == b && p->effectivity.within(d)) return p;
5307  return NULL;
5308  }
5309 
5310  /** Search for the association with a certain name. */
5311  C* find(const string& n) const
5312  {
5313  for (C* p=this->first; p; p=p->nextB)
5314  if (p->name == n) return p;
5315  return NULL;
5316  }
5317 
5318  /** Move an association a position up in the list of associations. */
5319  void promote(C* p)
5320  {
5321  // Already at the head
5322  if (p == this->first) return;
5323 
5324  // Scan the list
5325  C* prev = NULL;
5326  for (C* ptr = this->first; ptr; ptr = ptr->nextB)
5327  {
5328  if (ptr->nextB == p)
5329  {
5330  if (prev)
5331  prev->nextB = p;
5332  else
5333  this->first = p;
5334  ptr->nextB = p->nextB;
5335  p->nextB = ptr;
5336  return;
5337  }
5338  prev = ptr;
5339  }
5340  throw LogicException("Association not found in the list");
5341  }
5342  };
5343 
5344  /** @brief A base class for the class representing the association
5345  * itself.
5346  */
5347  class Node
5348  {
5349  public:
5350  A* ptrA;
5351  B* ptrB;
5352  C* nextA;
5353  C* nextB;
5355  string name;
5357  public:
5358  /** Constructor. */
5359  Node() : ptrA(NULL), ptrB(NULL), nextA(NULL), nextB(NULL), priority(1) {};
5360 
5361  /** Constructor. */
5362  Node(A* a, B* b, const ListA& al, const ListB& bl)
5363  : ptrA(a), ptrB(b), nextA(NULL), nextB(NULL), priority(1)
5364  {
5365  if (al.first)
5366  {
5367  // Append at the end of the A-list
5368  C* x = al.first;
5369  while (x->nextA) x = x->nextA;
5370  x->nextA = static_cast<C*>(this);
5371  }
5372  else
5373  // New start of the A-list
5374  const_cast<ListA&>(al).first = static_cast<C*>(this);
5375  if (bl.first)
5376  {
5377  // Append at the end of the B-list
5378  C* x = bl.first;
5379  while (x->nextB) x = x->nextB;
5380  x->nextB = static_cast<C*>(this);
5381  }
5382  else
5383  // New start of the B-list
5384  const_cast<ListB&>(bl).first = static_cast<C*>(this);
5385  }
5386 
5387  void setPtrA(A* a, const ListA& al)
5388  {
5389  // Don't allow updating an already valid link
5390  if (ptrA) throw DataException("Can't update existing entity");
5391  ptrA = a;
5392  if (al.first)
5393  {
5394  // Append at the end of the A-list
5395  C* x = al.first;
5396  while (x->nextA) x = x->nextA;
5397  x->nextA = static_cast<C*>(this);
5398  }
5399  else
5400  // New start of the A-list
5401  const_cast<ListA&>(al).first = static_cast<C*>(this);
5402  }
5403 
5404  void setPtrB(B* b, const ListB& bl)
5405  {
5406  // Don't allow updating an already valid link
5407  if (ptrB) throw DataException("Can't update existing entity");
5408  ptrB = b;
5409  if (bl.first)
5410  {
5411  // Append at the end of the B-list
5412  C* x = bl.first;
5413  while (x->nextB) x = x->nextB;
5414  x->nextB = static_cast<C*>(this);
5415  }
5416  else
5417  // New start of the B-list
5418  const_cast<ListB&>(bl).first = static_cast<C*>(this);
5419  }
5420 
5421  void setPtrAB(A* a, B* b, const ListA& al, const ListB& bl)
5422  {
5423  setPtrA(a, al);
5424  setPtrB(b, bl);
5425  }
5426 
5427  A* getPtrA() const {return ptrA;}
5428 
5429  B* getPtrB() const {return ptrB;}
5430 
5431  /** Update the start date of the effectivity range. */
5432  void setEffectiveStart(Date d) {effectivity.setStart(d);}
5433 
5434  /** Update the end date of the effectivity range. */
5435  void setEffectiveEnd(Date d) {effectivity.setEnd(d);}
5436 
5437  /** Update the effectivity range. */
5438  void setEffective(DateRange dr) {effectivity = dr;}
5439 
5440  /** Return the effectivity daterange.<br>
5441  * The default covers the complete time horizon.
5442  */
5443  DateRange getEffective() const {return effectivity;}
5444 
5445  /** Sets an optional name for the association.<br>
5446  * There is no garantuee of the uniqueness of this name.
5447  */
5448  void setName(const string x) {name = x;}
5449 
5450  /** Return the optional name of the association. */
5451  const string& getName() const {return name;}
5452 
5453  /** Update the priority. */
5454  void setPriority(int i) {priority = i;}
5455 
5456  /** Return the priority. */
5457  int getPriority() const {return priority;}
5458  };
5459 };
5460 
5461 
5462 #include "frepple/entity.h"
5463 
5464 
5465 //
5466 // LIBRARY INITIALISATION
5467 //
5468 
5469 /** @brief This class holds functions that used for maintenance of the library.
5470  *
5471  * Its static member function 'initialize' should be called BEFORE the
5472  * first use of any class in the library.
5473  * The member function 'finialize' will be called automatically at the
5474  * end of the program.
5475  */
5477 {
5478  public:
5479  static void initialize(int argc, char* argv[]);
5480 };
5481 
5482 /** @brief A template class to expose iterators to Python. */
5483 template <class ME, class ITERCLASS, class DATACLASS>
5485 {
5486  public:
5487  static int initialize()
5488  {
5489  // Initialize the type
5490  PythonType& x = PythonExtension<ME>::getType();
5491  x.setName(DATACLASS::metadata->type + "Iterator");
5492  x.setDoc("frePPLe iterator for " + DATACLASS::metadata->type);
5493  x.supportiter();
5494  return x.typeReady();
5495  }
5496 
5497  FreppleIterator() : i(DATACLASS::begin())
5498  {this->initType(PythonExtension<ME>::getType().type_object());}
5499 
5500  template <class OTHER> FreppleIterator(const OTHER *o) : i(o)
5501  {this->initType(PythonExtension<ME>::getType().type_object());}
5502 
5503  template <class OTHER> FreppleIterator(const OTHER &o) : i(o)
5504  {this->initType(PythonExtension<ME>::getType().type_object());}
5505 
5506  static PyObject* create(PyObject* self, PyObject* args)
5507  {return new ME();}
5508 
5509  private:
5510  ITERCLASS i;
5511 
5512  virtual PyObject* iternext()
5513  {
5514  if (i == DATACLASS::end()) return NULL;
5515  PyObject* result = &*i;
5516  ++i;
5517  Py_INCREF(result);
5518  return result;
5519  }
5520 };
5521 
5522 /** @brief This Python function loads a frepple extension module in memory. */
5523 DECLARE_EXPORT PyObject* loadModule(PyObject*, PyObject*, PyObject*);
5524 
5525 
5526 } // end namespace
5527 } // end namespace
5528 
5529 #include "pythonutils.h"
5530 
5531 #endif // End of FREPPLE_UTILS_H