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