abb48a9327f5a8cc2faebbfb368e93ccceed2c6c
[core.git] / inc / classes / main / class_BaseFrameworkSystem.php
1 <?php
2 /**
3  * The simulator system class is the super class of all other classes. This
4  * class handles saving of games etc.
5  *
6  * @author              Roland Haeder <webmaster@shipsimu.org>
7  * @version             0.0.0
8  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
9  * @license             GNU GPL 3.0 or any newer version
10  * @link                http://www.shipsimu.org
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  */
25 class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
26         /**
27          * The real class name
28          */
29         private $realClass = 'BaseFrameworkSystem';
30
31         /**
32          * Instance of a request class
33          */
34         private $requestInstance = NULL;
35
36         /**
37          * Instance of a response class
38          */
39         private $responseInstance = NULL;
40
41         /**
42          * Search criteria instance
43          */
44         private $searchInstance = NULL;
45
46         /**
47          * Update criteria instance
48          */
49         private $updateInstance = NULL;
50
51         /**
52          * The file I/O instance for the template loader
53          */
54         private $fileIoInstance = NULL;
55
56         /**
57          * Resolver instance
58          */
59         private $resolverInstance = NULL;
60
61         /**
62          * Template engine instance
63          */
64         private $templateInstance = NULL;
65
66         /**
67          * Database result instance
68          */
69         private $resultInstance = NULL;
70
71         /**
72          * Instance for user class
73          */
74         private $userInstance = NULL;
75
76         /**
77          * A controller instance
78          */
79         private $controllerInstance = NULL;
80
81         /**
82          * Instance of a RNG
83          */
84         private $rngInstance = NULL;
85
86         /**
87          * Instance of a crypto helper
88          */
89         private $cryptoInstance = NULL;
90
91         /**
92          * Instance of an Iterator class
93          */
94         private $iteratorInstance = NULL;
95
96         /**
97          * Instance of the list
98          */
99         private $listInstance = NULL;
100
101         /**
102          * Instance of a menu
103          */
104         private $menuInstance = NULL;
105
106         /**
107          * Instance of the image
108          */
109         private $imageInstance = NULL;
110
111         /**
112          * Instance of the stacker
113          */
114         private $stackerInstance = NULL;
115
116         /**
117          * A Compressor instance
118          */
119         private $compressorInstance = NULL;
120
121         /**
122          * A Parseable instance
123          */
124         private $parserInstance = NULL;
125
126         /**
127          * A ProtocolHandler instance
128          */
129         private $protocolInstance = NULL;
130
131         /**
132          * A database wrapper instance
133          */
134         private $databaseInstance = NULL;
135
136         /**
137          * A helper instance for the form
138          */
139         private $helperInstance = NULL;
140
141         /**
142          * An instance of a Sourceable class
143          */
144         private $sourceInstance = NULL;
145
146         /**
147          * An instance of a InputStreamable class
148          */
149         private $inputStreamInstance = NULL;
150
151         /**
152          * An instance of a OutputStreamable class
153          */
154         private $outputStreamInstance = NULL;
155
156         /**
157          * Networkable handler instance
158          */
159         private $handlerInstance = NULL;
160
161         /**
162          * Visitor handler instance
163          */
164         private $visitorInstance = NULL;
165
166         /**
167          * DHT instance
168          */
169         private $dhtInstance = NULL;
170
171         /**
172          * An instance of a database wrapper class
173          */
174         private $wrapperInstance = NULL;
175
176         /**
177          * Thousands separator
178          */
179         private $thousands = '.'; // German
180
181         /**
182          * Decimal separator
183          */
184         private $decimals  = ','; // German
185
186         /**
187          * Socket resource
188          */
189         private $socketResource = FALSE;
190
191         /**
192          * Package data
193          */
194         private $packageData = array();
195
196         /**
197          * Generic array
198          */
199         private $genericArray = array();
200
201         /***********************
202          * Exception codes.... *
203          ***********************/
204
205         // @todo Try to clean these constants up
206         const EXCEPTION_IS_NULL_POINTER              = 0x001;
207         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
208         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
209         const EXCEPTION_MISSING_METHOD               = 0x004;
210         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
211         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
212         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
213         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
214         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
215         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
216         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
217         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
218         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
219         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
220         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
221         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
222         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
223         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
224         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
225         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
226         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
227         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
228         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
229         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
230         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
231         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
232         const EXCEPTION_INVALID_RESOURCE             = 0x01b;
233         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
234         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
235         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
236         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
237         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
238         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
239         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
240         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
241         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
242         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
243         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
244         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
245         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
246         const EXCEPTION_INVALID_STRING               = 0x029;
247         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
248         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
249         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
250         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
251         const EXCEPTION_UNSPPORTED_OPERATION         = 0x02e;
252         const EXCEPTION_MISSING_ELEMENT              = 0x030;
253         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x031;
254         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
255         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
256         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
257         const EXCEPTION_FATAL_ERROR                  = 0x035;
258         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
259         const EXCEPTION_ASSERTION_FAILED             = 0x037;
260         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x038;
261         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x039;
262         const EXCEPTION_FILTER_CHAIN_INTERCEPTED     = 0x040;
263
264         /**
265          * Hexadecimal->Decimal translation array
266          */
267         private static $hexdec = array(
268                 '0' => 0,
269                 '1' => 1,
270                 '2' => 2,
271                 '3' => 3,
272                 '4' => 4,
273                 '5' => 5,
274                 '6' => 6,
275                 '7' => 7,
276                 '8' => 8,
277                 '9' => 9,
278                 'a' => 10,
279                 'b' => 11,
280                 'c' => 12,
281                 'd' => 13,
282                 'e' => 14,
283                 'f' => 15
284         );
285
286         /**
287          * Decimal->hexadecimal translation array
288          */
289         private static $dechex = array(
290                  0 => '0',
291                  1 => '1',
292                  2 => '2',
293                  3 => '3',
294                  4 => '4',
295                  5 => '5',
296                  6 => '6',
297                  7 => '7',
298                  8 => '8',
299                  9 => '9',
300                 10 => 'a',
301                 11 => 'b',
302                 12 => 'c',
303                 13 => 'd',
304                 14 => 'e',
305                 15 => 'f'
306         );
307
308         /**
309          * Startup time in miliseconds
310          */
311         private static $startupTime = 0;
312
313         /**
314          * Protected super constructor
315          *
316          * @param       $className      Name of the class
317          * @return      void
318          */
319         protected function __construct ($className) {
320                 // Set real class
321                 $this->setRealClass($className);
322
323                 // Set configuration instance if no registry ...
324                 if (!$this instanceof Register) {
325                         // ... because registries doesn't need to be configured
326                         $this->setConfigInstance(FrameworkConfiguration::getSelfInstance());
327                 } // END - if
328
329                 // Is the startup time set? (0 cannot be TRUE anymore)
330                 if (self::$startupTime == 0) {
331                         // Then set it
332                         self::$startupTime = microtime(TRUE);
333                 } // END - if
334         }
335
336         /**
337          * Destructor for all classes
338          *
339          * @return      void
340          */
341         public function __destruct () {
342                 // Flush any updated entries to the database
343                 $this->flushPendingUpdates();
344
345                 // Is this object already destroyed?
346                 if ($this->__toString() != 'DestructedObject') {
347                         // Destroy all informations about this class but keep some text about it alive
348                         $this->setRealClass('DestructedObject');
349                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
350                         // Already destructed object
351                         self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:] The object <span class="object_name">%s</span> is already destroyed.',
352                                 __CLASS__,
353                                 $this->__toString()
354                         ));
355                 } else {
356                         // Do not call this twice
357                         trigger_error(__METHOD__ . ': Called twice.');
358                         exit;
359                 }
360         }
361
362         /**
363          * The __call() method where all non-implemented methods end up
364          *
365          * @param       $methodName             Name of the missing method
366          * @args        $args                   Arguments passed to the method
367          * @return      void
368          */
369         public final function __call ($methodName, $args) {
370                 return self::__callStatic($methodName, $args);
371         }
372
373         /**
374          * The __callStatic() method where all non-implemented static methods end up
375          *
376          * @param       $methodName             Name of the missing method
377          * @args        $args                   Arguments passed to the method
378          * @return      void
379          */
380         public static final function __callStatic ($methodName, $args) {
381                 // Init argument string
382                 $argsString = '';
383
384                 // Is it empty or an array?
385                 if (empty($args)) {
386                         // No arguments
387                         $argsString = 'NULL';
388                 } elseif (is_array($args)) {
389                         // Some arguments are there
390                         foreach ($args as $arg) {
391                                 // Add the value itself if not array. This prevents 'array to string conversion' message
392                                 if (is_array($arg)) {
393                                         $argsString .= 'Array';
394                                 } else {
395                                         $argsString .= $arg;
396                                 }
397
398                                 // Add data about the argument
399                                 $argsString .= ' (' . gettype($arg);
400
401                                 if (is_string($arg)) {
402                                         // Add length for strings
403                                         $argsString .= ', ' . strlen($arg);
404                                 } elseif (is_array($arg)) {
405                                         // .. or size if array
406                                         $argsString .= ', ' . count($arg);
407                                 } elseif ($arg === TRUE) {
408                                         // ... is boolean 'TRUE'
409                                         $argsString .= ', TRUE';
410                                 } elseif ($arg === FALSE) {
411                                         // ... is boolean 'FALSE'
412                                         $argsString .= ', FALSE';
413                                 }
414
415                                 // Closing bracket
416                                 $argsString .= '), ';
417                         } // END - foreach
418
419                         // Remove last comma
420                         if (substr($argsString, -2, 1) == ',') {
421                                 $argsString = substr($argsString, 0, -2);
422                         } // END - if
423                 } else {
424                         // Invalid arguments!
425                         $argsString = '!INVALID:' . gettype($args) . '!';
426                 }
427
428                 // Output stub message
429                 // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class
430                 self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[unknown::%s:] Stub! Args: %s',
431                         $methodName,
432                         $argsString
433                 ));
434
435                 // Return nothing
436                 return NULL;
437         }
438
439         /**
440          * Getter for $realClass
441          *
442          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
443          */
444         public function __toString () {
445                 return $this->realClass;
446         }
447
448         /**
449          * Magic function to catch setting of missing but set class fields/attributes
450          *
451          * @param       $name   Name of the field/attribute
452          * @param       $value  Value to store
453          * @return      void
454          */
455         public final function __set ($name, $value) {
456                 $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s',
457                         $name,
458                         gettype($value),
459                         $value
460                 ));
461         }
462
463         /**
464          * Magic function to catch getting of missing fields/attributes
465          *
466          * @param       $name   Name of the field/attribute
467          * @return      void
468          */
469         public final function __get ($name) {
470                 $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s',
471                         $name
472                 ));
473         }
474
475         /**
476          * Magic function to catch unsetting of missing fields/attributes
477          *
478          * @param       $name   Name of the field/attribute
479          * @return      void
480          */
481         public final function __unset ($name) {
482                 $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s',
483                         $name
484                 ));
485         }
486
487         /**
488          * Setter for the real class name
489          *
490          * @param       $realClass      Class name (string)
491          * @return      void
492          */
493         public final function setRealClass ($realClass) {
494                 // Set real class
495                 $this->realClass = (string) $realClass;
496         }
497
498         /**
499          * Setter for database result instance
500          *
501          * @param       $resultInstance         An instance of a database result class
502          * @return      void
503          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
504          */
505         protected final function setResultInstance (SearchableResult $resultInstance) {
506                 $this->resultInstance =  $resultInstance;
507         }
508
509         /**
510          * Getter for database result instance
511          *
512          * @return      $resultInstance         An instance of a database result class
513          */
514         public final function getResultInstance () {
515                 return $this->resultInstance;
516         }
517
518         /**
519          * Setter for template engine instances
520          *
521          * @param       $templateInstance       An instance of a template engine class
522          * @return      void
523          */
524         protected final function setTemplateInstance (CompileableTemplate $templateInstance) {
525                 $this->templateInstance = $templateInstance;
526         }
527
528         /**
529          * Getter for template engine instances
530          *
531          * @return      $templateInstance       An instance of a template engine class
532          */
533         protected final function getTemplateInstance () {
534                 return $this->templateInstance;
535         }
536
537         /**
538          * Setter for search instance
539          *
540          * @param       $searchInstance         Searchable criteria instance
541          * @return      void
542          */
543         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
544                 $this->searchInstance = $searchInstance;
545         }
546
547         /**
548          * Getter for search instance
549          *
550          * @return      $searchInstance         Searchable criteria instance
551          */
552         public final function getSearchInstance () {
553                 return $this->searchInstance;
554         }
555
556         /**
557          * Setter for update instance
558          *
559          * @param       $updateInstance         Searchable criteria instance
560          * @return      void
561          */
562         public final function setUpdateInstance (LocalUpdateCriteria $updateInstance) {
563                 $this->updateInstance = $updateInstance;
564         }
565
566         /**
567          * Getter for update instance
568          *
569          * @return      $updateInstance         Updateable criteria instance
570          */
571         public final function getUpdateInstance () {
572                 return $this->updateInstance;
573         }
574
575         /**
576          * Setter for resolver instance
577          *
578          * @param       $resolverInstance       Instance of a command resolver class
579          * @return      void
580          */
581         public final function setResolverInstance (Resolver $resolverInstance) {
582                 $this->resolverInstance = $resolverInstance;
583         }
584
585         /**
586          * Getter for resolver instance
587          *
588          * @return      $resolverInstance       Instance of a command resolver class
589          */
590         public final function getResolverInstance () {
591                 return $this->resolverInstance;
592         }
593
594         /**
595          * Setter for language instance
596          *
597          * @param       $configInstance         The configuration instance which shall
598          *                                                              be FrameworkConfiguration
599          * @return      void
600          */
601         public final function setConfigInstance (FrameworkConfiguration $configInstance) {
602                 Registry::getRegistry()->addInstance('config', $configInstance);
603         }
604
605         /**
606          * Getter for configuration instance
607          *
608          * @return      $configInstance         Configuration instance
609          */
610         public final function getConfigInstance () {
611                 $configInstance = Registry::getRegistry()->getInstance('config');
612                 return $configInstance;
613         }
614
615         /**
616          * Setter for debug instance
617          *
618          * @param       $debugInstance  The instance for debug output class
619          * @return      void
620          */
621         public final function setDebugInstance (DebugMiddleware $debugInstance) {
622                 Registry::getRegistry()->addInstance('debug', $debugInstance);
623         }
624
625         /**
626          * Getter for debug instance
627          *
628          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
629          */
630         public final function getDebugInstance () {
631                 // Get debug instance
632                 $debugInstance = Registry::getRegistry()->getInstance('debug');
633
634                 // Return it
635                 return $debugInstance;
636         }
637
638         /**
639          * Setter for web output instance
640          *
641          * @param       $webInstance    The instance for web output class
642          * @return      void
643          */
644         public final function setWebOutputInstance (OutputStreamer $webInstance) {
645                 Registry::getRegistry()->addInstance('web_output', $webInstance);
646         }
647
648         /**
649          * Getter for web output instance
650          *
651          * @return      $webOutputInstance - Instance to class WebOutput
652          */
653         public final function getWebOutputInstance () {
654                 $webOutputInstance = Registry::getRegistry()->getInstance('web_output');
655                 return $webOutputInstance;
656         }
657
658         /**
659          * Setter for database instance
660          *
661          * @param       $databaseInstance       The instance for the database connection (forced DatabaseConnection)
662          * @return      void
663          */
664         public final function setDatabaseInstance (DatabaseConnection $databaseInstance) {
665                 Registry::getRegistry()->addInstance('db_instance', $databaseInstance);
666         }
667
668         /**
669          * Getter for database layer
670          *
671          * @return      $databaseInstance       The database layer instance
672          */
673         public final function getDatabaseInstance () {
674                 // Get instance
675                 $databaseInstance = Registry::getRegistry()->getInstance('db_instance');
676
677                 // Return instance
678                 return $databaseInstance;
679         }
680
681         /**
682          * Setter for compressor channel
683          *
684          * @param       $compressorInstance             An instance of CompressorChannel
685          * @return      void
686          */
687         public final function setCompressorChannel (CompressorChannel $compressorInstance) {
688                 Registry::getRegistry()->addInstance('compressor', $compressorInstance);
689         }
690
691         /**
692          * Getter for compressor channel
693          *
694          * @return      $compressorInstance             The compressor channel
695          */
696         public final function getCompressorChannel () {
697                 $compressorInstance = Registry::getRegistry()->getInstance('compressor');
698                 return $compressorInstance;
699         }
700
701         /**
702          * Protected getter for a manageable application helper class
703          *
704          * @return      $applicationInstance    An instance of a manageable application helper class
705          */
706         protected final function getApplicationInstance () {
707                 $applicationInstance = Registry::getRegistry()->getInstance('application');
708                 return $applicationInstance;
709         }
710
711         /**
712          * Setter for a manageable application helper class
713          *
714          * @param       $applicationInstance    An instance of a manageable application helper class
715          * @return      void
716          */
717         public final function setApplicationInstance (ManageableApplication $applicationInstance) {
718                 Registry::getRegistry()->addInstance('application', $applicationInstance);
719         }
720
721         /**
722          * Setter for request instance
723          *
724          * @param       $requestInstance        An instance of a Requestable class
725          * @return      void
726          */
727         public final function setRequestInstance (Requestable $requestInstance) {
728                 $this->requestInstance = $requestInstance;
729         }
730
731         /**
732          * Getter for request instance
733          *
734          * @return      $requestInstance        An instance of a Requestable class
735          */
736         public final function getRequestInstance () {
737                 return $this->requestInstance;
738         }
739
740         /**
741          * Setter for response instance
742          *
743          * @param       $responseInstance       An instance of a Responseable class
744          * @return      void
745          */
746         public final function setResponseInstance (Responseable $responseInstance) {
747                 $this->responseInstance = $responseInstance;
748         }
749
750         /**
751          * Getter for response instance
752          *
753          * @return      $responseInstance       An instance of a Responseable class
754          */
755         public final function getResponseInstance () {
756                 return $this->responseInstance;
757         }
758
759         /**
760          * Private getter for language instance
761          *
762          * @return      $langInstance   An instance to the language sub-system
763          */
764         protected final function getLanguageInstance () {
765                 $langInstance = Registry::getRegistry()->getInstance('language');
766                 return $langInstance;
767         }
768
769         /**
770          * Setter for language instance
771          *
772          * @param       $langInstance   An instance to the language sub-system
773          * @return      void
774          * @see         LanguageSystem
775          */
776         public final function setLanguageInstance (ManageableLanguage $langInstance) {
777                 Registry::getRegistry()->addInstance('language', $langInstance);
778         }
779
780         /**
781          * Private getter for file IO instance
782          *
783          * @return      $fileIoInstance         An instance to the file I/O sub-system
784          */
785         protected final function getFileIoInstance () {
786                 return $this->fileIoInstance;
787         }
788
789         /**
790          * Setter for file I/O instance
791          *
792          * @param       $fileIoInstance         An instance to the file I/O sub-system
793          * @return      void
794          */
795         public final function setFileIoInstance (IoHandler $fileIoInstance) {
796                 $this->fileIoInstance = $fileIoInstance;
797         }
798
799         /**
800          * Protected setter for user instance
801          *
802          * @param       $userInstance   An instance of a user class
803          * @return      void
804          */
805         protected final function setUserInstance (ManageableAccount $userInstance) {
806                 $this->userInstance = $userInstance;
807         }
808
809         /**
810          * Getter for user instance
811          *
812          * @return      $userInstance   An instance of a user class
813          */
814         public final function getUserInstance () {
815                 return $this->userInstance;
816         }
817
818         /**
819          * Setter for controller instance (this surely breaks a bit the MVC patterm)
820          *
821          * @param       $controllerInstance             An instance of the controller
822          * @return      void
823          */
824         public final function setControllerInstance (Controller $controllerInstance) {
825                 $this->controllerInstance = $controllerInstance;
826         }
827
828         /**
829          * Getter for controller instance (this surely breaks a bit the MVC patterm)
830          *
831          * @return      $controllerInstance             An instance of the controller
832          */
833         public final function getControllerInstance () {
834                 return $this->controllerInstance;
835         }
836
837         /**
838          * Setter for RNG instance
839          *
840          * @param       $rngInstance    An instance of a random number generator (RNG)
841          * @return      void
842          */
843         protected final function setRngInstance (RandomNumberGenerator $rngInstance) {
844                 $this->rngInstance = $rngInstance;
845         }
846
847         /**
848          * Getter for RNG instance
849          *
850          * @return      $rngInstance    An instance of a random number generator (RNG)
851          */
852         public final function getRngInstance () {
853                 return $this->rngInstance;
854         }
855
856         /**
857          * Setter for Cryptable instance
858          *
859          * @param       $cryptoInstance An instance of a Cryptable class
860          * @return      void
861          */
862         protected final function setCryptoInstance (Cryptable $cryptoInstance) {
863                 $this->cryptoInstance = $cryptoInstance;
864         }
865
866         /**
867          * Getter for Cryptable instance
868          *
869          * @return      $cryptoInstance An instance of a Cryptable class
870          */
871         public final function getCryptoInstance () {
872                 return $this->cryptoInstance;
873         }
874
875         /**
876          * Setter for the list instance
877          *
878          * @param       $listInstance   A list of Listable
879          * @return      void
880          */
881         protected final function setListInstance (Listable $listInstance) {
882                 $this->listInstance = $listInstance;
883         }
884
885         /**
886          * Getter for the list instance
887          *
888          * @return      $listInstance   A list of Listable
889          */
890         protected final function getListInstance () {
891                 return $this->listInstance;
892         }
893
894         /**
895          * Setter for the menu instance
896          *
897          * @param       $menuInstance   A RenderableMenu instance
898          * @return      void
899          */
900         protected final function setMenuInstance (RenderableMenu $menuInstance) {
901                 $this->menuInstance = $menuInstance;
902         }
903
904         /**
905          * Getter for the menu instance
906          *
907          * @return      $menuInstance   A RenderableMenu instance
908          */
909         protected final function getMenuInstance () {
910                 return $this->menuInstance;
911         }
912
913         /**
914          * Setter for image instance
915          *
916          * @param       $imageInstance  An instance of an image
917          * @return      void
918          */
919         public final function setImageInstance (BaseImage $imageInstance) {
920                 $this->imageInstance = $imageInstance;
921         }
922
923         /**
924          * Getter for image instance
925          *
926          * @return      $imageInstance  An instance of an image
927          */
928         public final function getImageInstance () {
929                 return $this->imageInstance;
930         }
931
932         /**
933          * Setter for stacker instance
934          *
935          * @param       $stackerInstance        An instance of an stacker
936          * @return      void
937          */
938         public final function setStackerInstance (Stackable $stackerInstance) {
939                 $this->stackerInstance = $stackerInstance;
940         }
941
942         /**
943          * Getter for stacker instance
944          *
945          * @return      $stackerInstance        An instance of an stacker
946          */
947         public final function getStackerInstance () {
948                 return $this->stackerInstance;
949         }
950
951         /**
952          * Setter for compressor instance
953          *
954          * @param       $compressorInstance     An instance of an compressor
955          * @return      void
956          */
957         public final function setCompressorInstance (Compressor $compressorInstance) {
958                 $this->compressorInstance = $compressorInstance;
959         }
960
961         /**
962          * Getter for compressor instance
963          *
964          * @return      $compressorInstance     An instance of an compressor
965          */
966         public final function getCompressorInstance () {
967                 return $this->compressorInstance;
968         }
969
970         /**
971          * Setter for Parseable instance
972          *
973          * @param       $parserInstance An instance of an Parseable
974          * @return      void
975          */
976         public final function setParserInstance (Parseable $parserInstance) {
977                 $this->parserInstance = $parserInstance;
978         }
979
980         /**
981          * Getter for Parseable instance
982          *
983          * @return      $parserInstance An instance of an Parseable
984          */
985         public final function getParserInstance () {
986                 return $this->parserInstance;
987         }
988
989         /**
990          * Setter for ProtocolHandler instance
991          *
992          * @param       $protocolInstance       An instance of an ProtocolHandler
993          * @return      void
994          */
995         public final function setProtocolInstance (ProtocolHandler $protocolInstance = NULL) {
996                 $this->protocolInstance = $protocolInstance;
997         }
998
999         /**
1000          * Getter for ProtocolHandler instance
1001          *
1002          * @return      $protocolInstance       An instance of an ProtocolHandler
1003          */
1004         public final function getProtocolInstance () {
1005                 return $this->protocolInstance;
1006         }
1007
1008         /**
1009          * Setter for DatabaseWrapper instance
1010          *
1011          * @param       $wrapperInstance        An instance of an DatabaseWrapper
1012          * @return      void
1013          */
1014         public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) {
1015                 $this->wrapperInstance = $wrapperInstance;
1016         }
1017
1018         /**
1019          * Getter for DatabaseWrapper instance
1020          *
1021          * @return      $wrapperInstance        An instance of an DatabaseWrapper
1022          */
1023         public final function getWrapperInstance () {
1024                 return $this->wrapperInstance;
1025         }
1026
1027         /**
1028          * Setter for socket resource
1029          *
1030          * @param       $socketResource         A valid socket resource
1031          * @return      void
1032          */
1033         public final function setSocketResource ($socketResource) {
1034                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource=' . $socketResource . ',previous[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1035                 $this->socketResource = $socketResource;
1036         }
1037
1038         /**
1039          * Getter for socket resource
1040          *
1041          * @return      $socketResource         A valid socket resource
1042          */
1043         public final function getSocketResource () {
1044                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . '::' . __FUNCTION__ . ': socketResource[' . gettype($this->socketResource) . ']=' . $this->socketResource);
1045                 return $this->socketResource;
1046         }
1047
1048         /**
1049          * Setter for helper instance
1050          *
1051          * @param       $helperInstance         An instance of a helper class
1052          * @return      void
1053          */
1054         protected final function setHelperInstance (Helper $helperInstance) {
1055                 $this->helperInstance = $helperInstance;
1056         }
1057
1058         /**
1059          * Getter for helper instance
1060          *
1061          * @return      $helperInstance         An instance of a helper class
1062          */
1063         public final function getHelperInstance () {
1064                 return $this->helperInstance;
1065         }
1066
1067         /**
1068          * Setter for a Sourceable instance
1069          *
1070          * @param       $sourceInstance The Sourceable instance
1071          * @return      void
1072          */
1073         protected final function setSourceInstance (Sourceable $sourceInstance) {
1074                 $this->sourceInstance = $sourceInstance;
1075         }
1076
1077         /**
1078          * Getter for a Sourceable instance
1079          *
1080          * @return      $sourceInstance The Sourceable instance
1081          */
1082         protected final function getSourceInstance () {
1083                 return $this->sourceInstance;
1084         }
1085
1086         /**
1087          * Getter for a InputStreamable instance
1088          *
1089          * @param       $inputStreamInstance    The InputStreamable instance
1090          */
1091         protected final function getInputStreamInstance () {
1092                 return $this->inputStreamInstance;
1093         }
1094
1095         /**
1096          * Setter for a InputStreamable instance
1097          *
1098          * @param       $inputStreamInstance    The InputStreamable instance
1099          * @return      void
1100          */
1101         protected final function setInputStreamInstance (InputStreamable $inputStreamInstance) {
1102                 $this->inputStreamInstance = $inputStreamInstance;
1103         }
1104
1105         /**
1106          * Getter for a OutputStreamable instance
1107          *
1108          * @param       $outputStreamInstance   The OutputStreamable instance
1109          */
1110         protected final function getOutputStreamInstance () {
1111                 return $this->outputStreamInstance;
1112         }
1113
1114         /**
1115          * Setter for a OutputStreamable instance
1116          *
1117          * @param       $outputStreamInstance   The OutputStreamable instance
1118          * @return      void
1119          */
1120         protected final function setOutputStreamInstance (OutputStreamable $outputStreamInstance) {
1121                 $this->outputStreamInstance = $outputStreamInstance;
1122         }
1123
1124         /**
1125          * Setter for handler instance
1126          *
1127          * @param       $handlerInstance        An instance of a Handleable class
1128          * @return      void
1129          */
1130         protected final function setHandlerInstance (Handleable $handlerInstance) {
1131                 $this->handlerInstance = $handlerInstance;
1132         }
1133
1134         /**
1135          * Getter for handler instance
1136          *
1137          * @return      $handlerInstance        A Networkable instance
1138          */
1139         protected final function getHandlerInstance () {
1140                 return $this->handlerInstance;
1141         }
1142
1143         /**
1144          * Setter for visitor instance
1145          *
1146          * @param       $visitorInstance        A Visitor instance
1147          * @return      void
1148          */
1149         protected final function setVisitorInstance (Visitor $visitorInstance) {
1150                 $this->visitorInstance = $visitorInstance;
1151         }
1152
1153         /**
1154          * Getter for visitor instance
1155          *
1156          * @return      $visitorInstance        A Visitor instance
1157          */
1158         protected final function getVisitorInstance () {
1159                 return $this->visitorInstance;
1160         }
1161
1162         /**
1163          * Setter for DHT instance
1164          *
1165          * @param       $dhtInstance    A Distributable instance
1166          * @return      void
1167          */
1168         protected final function setDhtInstance (Distributable $dhtInstance) {
1169                 $this->dhtInstance = $dhtInstance;
1170         }
1171
1172         /**
1173          * Getter for DHT instance
1174          *
1175          * @return      $dhtInstance    A Distributable instance
1176          */
1177         protected final function getDhtInstance () {
1178                 return $this->dhtInstance;
1179         }
1180
1181         /**
1182          * Setter for raw package Data
1183          *
1184          * @param       $packageData    Raw package Data
1185          * @return      void
1186          */
1187         public final function setPackageData (array $packageData) {
1188                 $this->packageData = $packageData;
1189         }
1190
1191         /**
1192          * Getter for raw package Data
1193          *
1194          * @return      $packageData    Raw package Data
1195          */
1196         public function getPackageData () {
1197                 return $this->packageData;
1198         }
1199
1200
1201         /**
1202          * Setter for Iterator instance
1203          *
1204          * @param       $iteratorInstance       An instance of an Iterator
1205          * @return      void
1206          */
1207         protected final function setIteratorInstance (Iterator $iteratorInstance) {
1208                 $this->iteratorInstance = $iteratorInstance;
1209         }
1210
1211         /**
1212          * Getter for Iterator instance
1213          *
1214          * @return      $iteratorInstance       An instance of an Iterator
1215          */
1216         public final function getIteratorInstance () {
1217                 return $this->iteratorInstance;
1218         }
1219
1220         /**
1221          * Checks whether an object equals this object. You should overwrite this
1222          * method to implement own equality checks
1223          *
1224          * @param       $objectInstance         An instance of a FrameworkInterface object
1225          * @return      $equals                         Whether both objects equals
1226          */
1227         public function equals (FrameworkInterface $objectInstance) {
1228                 // Now test it
1229                 $equals = ((
1230                         $this->__toString() == $objectInstance->__toString()
1231                 ) && (
1232                         $this->hashCode() == $objectInstance->hashCode()
1233                 ));
1234
1235                 // Return the result
1236                 return $equals;
1237         }
1238
1239         /**
1240          * Generates a generic hash code of this class. You should really overwrite
1241          * this method with your own hash code generator code. But keep KISS in mind.
1242          *
1243          * @return      $hashCode       A generic hash code respresenting this whole class
1244          */
1245         public function hashCode () {
1246                 // Simple hash code
1247                 return crc32($this->__toString());
1248         }
1249
1250         /**
1251          * Formats computer generated price values into human-understandable formats
1252          * with thousand and decimal separators.
1253          *
1254          * @param       $value          The in computer format value for a price
1255          * @param       $currency       The currency symbol (use HTML-valid characters!)
1256          * @param       $decNum         Number of decimals after commata
1257          * @return      $price          The for the current language formated price string
1258          * @throws      MissingDecimalsThousandsSeparatorException      If decimals or
1259          *                                                                                              thousands separator
1260          *                                                                                              is missing
1261          */
1262         public function formatCurrency ($value, $currency = '&euro;', $decNum = 2) {
1263                 // Are all required attriutes set?
1264                 if ((!isset($this->decimals)) || (!isset($this->thousands))) {
1265                         // Throw an exception
1266                         throw new MissingDecimalsThousandsSeparatorException($this, self::EXCEPTION_ATTRIBUTES_ARE_MISSING);
1267                 } // END - if
1268
1269                 // Cast the number
1270                 $value = (float) $value;
1271
1272                 // Reformat the US number
1273                 $price = number_format($value, $decNum, $this->decimals, $this->thousands) . $currency;
1274
1275                 // Return as string...
1276                 return $price;
1277         }
1278
1279         /**
1280          * Appends a trailing slash to a string
1281          *
1282          * @param       $str    A string (maybe) without trailing slash
1283          * @return      $str    A string with an auto-appended trailing slash
1284          */
1285         public final function addMissingTrailingSlash ($str) {
1286                 // Is there a trailing slash?
1287                 if (substr($str, -1, 1) != '/') {
1288                         $str .= '/';
1289                 } // END - if
1290
1291                 // Return string with trailing slash
1292                 return $str;
1293         }
1294
1295         /**
1296          * Prepare the template engine (WebTemplateEngine by default) for a given
1297          * application helper instance (ApplicationHelper by default).
1298          *
1299          * @param               $applicationInstance    An application helper instance or
1300          *                                                                              null if we shall use the default
1301          * @return              $templateInstance               The template engine instance
1302          * @throws              NullPointerException    If the discovered application
1303          *                                                                              instance is still null
1304          */
1305         protected function prepareTemplateInstance (ManageableApplication $applicationInstance = NULL) {
1306                 // Is the application instance set?
1307                 if (is_null($applicationInstance)) {
1308                         // Get the current instance
1309                         $applicationInstance = $this->getApplicationInstance();
1310
1311                         // Still null?
1312                         if (is_null($applicationInstance)) {
1313                                 // Thrown an exception
1314                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1315                         } // END - if
1316                 } // END - if
1317
1318                 // Initialize the template engine
1319                 $templateInstance = ObjectFactory::createObjectByConfiguredName('web_template_class');
1320
1321                 // Return the prepared instance
1322                 return $templateInstance;
1323         }
1324
1325         /**
1326          * Debugs this instance by putting out it's full content
1327          *
1328          * @param       $message        Optional message to show in debug output
1329          * @return      void
1330          */
1331         public final function debugInstance ($message = '') {
1332                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
1333                 restore_error_handler();
1334
1335                 // Init content
1336                 $content = '';
1337
1338                 // Is a message set?
1339                 if (!empty($message)) {
1340                         // Construct message
1341                         $content = sprintf('<div class="debug_message">Message: %s</div>' . PHP_EOL, $message);
1342                 } // END - if
1343
1344                 // Generate the output
1345                 $content .= sprintf('<pre>%s</pre>',
1346                         trim(
1347                                 htmlentities(
1348                                         print_r($this, TRUE)
1349                                 )
1350                         )
1351                 );
1352
1353                 // Output it
1354                 ApplicationEntryPoint::app_exit(sprintf('<div class="debug_header">%s debug output:</div><div class="debug_content">%s</div>Loaded includes: <div class="debug_include_list">%s</div>',
1355                         $this->__toString(),
1356                         $content,
1357                         ClassLoader::getSelfInstance()->getPrintableIncludeList()
1358                 ));
1359         }
1360
1361         /**
1362          * Replaces control characters with printable output
1363          *
1364          * @param       $str    String with control characters
1365          * @return      $str    Replaced string
1366          */
1367         protected function replaceControlCharacters ($str) {
1368                 // Replace them
1369                 $str = str_replace(
1370                         chr(13), '[r]', str_replace(
1371                         chr(10), '[n]', str_replace(
1372                         chr(9) , '[t]',
1373                         $str
1374                 )));
1375
1376                 // Return it
1377                 return $str;
1378         }
1379
1380         /**
1381          * Output a partial stub message for the caller method
1382          *
1383          * @param       $message        An optional message to display
1384          * @return      void
1385          */
1386         protected function partialStub ($message = '') {
1387                 // Get the backtrace
1388                 $backtrace = debug_backtrace();
1389
1390                 // Generate the class::method string
1391                 $methodName = 'UnknownClass-&gt;unknownMethod';
1392                 if ((isset($backtrace[1]['class'])) && (isset($backtrace[1]['function']))) {
1393                         $methodName = $backtrace[1]['class'] . '-&gt;' . $backtrace[1]['function'];
1394                 } // END - if
1395
1396                 // Construct the full message
1397                 $stubMessage = sprintf('[%s:] Partial stub!',
1398                         $methodName
1399                 );
1400
1401                 // Is the extra message given?
1402                 if (!empty($message)) {
1403                         // Then add it as well
1404                         $stubMessage .= ' Message: ' . $message;
1405                 } // END - if
1406
1407                 // Debug instance is there?
1408                 if (!is_null($this->getDebugInstance())) {
1409                         // Output stub message
1410                         self::createDebugInstance(__CLASS__)->debugOutput($stubMessage);
1411                 } else {
1412                         // Trigger an error
1413                         trigger_error($stubMessage);
1414                         exit;
1415                 }
1416         }
1417
1418         /**
1419          * Outputs a debug backtrace and stops further script execution
1420          *
1421          * @param       $message        An optional message to output
1422          * @param       $doExit         Whether exit the program (TRUE is default)
1423          * @return      void
1424          */
1425         public function debugBackTrace ($message = '', $doExit = TRUE) {
1426                 // Sorry, there is no other way getting this nice backtrace
1427                 if (!empty($message)) {
1428                         // Output message
1429                         printf('Message: %s<br />' . chr(10), $message);
1430                 } // END - if
1431
1432                 print('<pre>');
1433                 debug_print_backtrace();
1434                 print('</pre>');
1435
1436                 // Exit program?
1437                 if ($doExit === TRUE) {
1438                         exit();
1439                 } // END - if
1440         }
1441
1442         /**
1443          * Creates an instance of a debugger instance
1444          *
1445          * @param       $className              Name of the class (currently unsupported)
1446          * @return      $debugInstance  An instance of a debugger class
1447          */
1448         public final static function createDebugInstance ($className) {
1449                 // Is the instance set?
1450                 if (!Registry::getRegistry()->instanceExists('debug')) {
1451                         // Init debug instance
1452                         $debugInstance = NULL;
1453
1454                         // Try it
1455                         try {
1456                                 // Get a debugger instance
1457                                 $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkConfiguration::getSelfInstance()->getConfigEntry('debug_class'));
1458                         } catch (NullPointerException $e) {
1459                                 // Didn't work, no instance there
1460                                 exit('Cannot create debugInstance! Exception=' . $e->__toString() . ', message=' . $e->getMessage());
1461                         }
1462
1463                         // Empty string should be ignored and used for testing the middleware
1464                         DebugMiddleware::getSelfInstance()->output('');
1465
1466                         // Set it in its own class. This will set it in the registry
1467                         $debugInstance->setDebugInstance($debugInstance);
1468                 } else {
1469                         // Get instance from registry
1470                         $debugInstance = Registry::getRegistry()->getDebugInstance();
1471                 }
1472
1473                 // Return it
1474                 return $debugInstance;
1475         }
1476
1477         /**
1478          * Simple output of a message with line-break
1479          *
1480          * @param       $message        Message to output
1481          * @return      void
1482          */
1483         public function outputLine ($message) {
1484                 // Simply output it
1485                 print($message . PHP_EOL);
1486         }
1487
1488         /**
1489          * Outputs a debug message whether to debug instance (should be set!) or
1490          * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to
1491          * ApplicationEntryPoint::app_exit(), this would cause an endless loop.
1492          *
1493          * @param       $message        Message we shall send out...
1494          * @param       $doPrint        Whether print or die here (default: print)
1495          * @paran       $stripTags      Whether to strip tags (default: FALSE)
1496          * @return      void
1497          */
1498         public function debugOutput ($message, $doPrint = TRUE, $stripTags = FALSE) {
1499                 // Set debug instance to NULL
1500                 $debugInstance = NULL;
1501
1502                 // Try it:
1503                 try {
1504                         // Get debug instance
1505                         $debugInstance = $this->getDebugInstance();
1506                 } catch (NullPointerException $e) {
1507                         // The debug instance is not set (yet)
1508                 }
1509
1510                 // Is the debug instance there?
1511                 if (is_object($debugInstance)) {
1512                         // Use debug output handler
1513                         $debugInstance->output($message, $stripTags);
1514
1515                         if ($doPrint === FALSE) {
1516                                 // Die here if not printed
1517                                 exit();
1518                         } // END - if
1519                 } else {
1520                         // Are debug times enabled?
1521                         if ($this->getConfigInstance()->getConfigEntry('debug_output_timings') == 'Y') {
1522                                 // Prepent it
1523                                 $message = $this->getPrintableExecutionTime() . $message;
1524                         } // END - if
1525
1526                         // Put directly out
1527                         if ($doPrint === TRUE) {
1528                                 // Print message
1529                                 $this->outputLine($message);
1530                         } else {
1531                                 // Die here
1532                                 exit($message);
1533                         }
1534                 }
1535         }
1536
1537         /**
1538          * Converts e.g. a command from URL to a valid class by keeping out bad characters
1539          *
1540          * @param       $str            The string, what ever it is needs to be converted
1541          * @return      $className      Generated class name
1542          */
1543         public function convertToClassName ($str) {
1544                 // Init class name
1545                 $className = '';
1546
1547                 // Convert all dashes in underscores
1548                 $str = $this->convertDashesToUnderscores($str);
1549
1550                 // Now use that underscores to get classname parts for hungarian style
1551                 foreach (explode('_', $str) as $strPart) {
1552                         // Make the class name part lower case and first upper case
1553                         $className .= ucfirst(strtolower($strPart));
1554                 } // END - foreach
1555
1556                 // Return class name
1557                 return $className;
1558         }
1559
1560         /**
1561          * Converts dashes to underscores, e.g. useable for configuration entries
1562          *
1563          * @param       $str    The string with maybe dashes inside
1564          * @return      $str    The converted string with no dashed, but underscores
1565          */
1566         public final function convertDashesToUnderscores ($str) {
1567                 // Convert them all
1568                 $str = str_replace('-', '_', $str);
1569
1570                 // Return converted string
1571                 return $str;
1572         }
1573
1574         /**
1575          * Marks up the code by adding e.g. line numbers
1576          *
1577          * @param       $phpCode                Unmarked PHP code
1578          * @return      $markedCode             Marked PHP code
1579          */
1580         public function markupCode ($phpCode) {
1581                 // Init marked code
1582                 $markedCode = '';
1583
1584                 // Get last error
1585                 $errorArray = error_get_last();
1586
1587                 // Init the code with error message
1588                 if (is_array($errorArray)) {
1589                         // Get error infos
1590                         $markedCode = sprintf('<div id="error_header">File: <span id="error_data">%s</span>, Line: <span id="error_data">%s</span>, Message: <span id="error_data">%s</span>, Type: <span id="error_data">%s</span></div>',
1591                                 basename($errorArray['file']),
1592                                 $errorArray['line'],
1593                                 $errorArray['message'],
1594                                 $errorArray['type']
1595                         );
1596                 } // END - if
1597
1598                 // Add line number to the code
1599                 foreach (explode(chr(10), $phpCode) as $lineNo => $code) {
1600                         // Add line numbers
1601                         $markedCode .= sprintf('<span id="code_line">%s</span>: %s' . chr(10),
1602                                 ($lineNo + 1),
1603                                 htmlentities($code, ENT_QUOTES)
1604                         );
1605                 } // END - foreach
1606
1607                 // Return the code
1608                 return $markedCode;
1609         }
1610
1611         /**
1612          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
1613          * beatiful for web-based front-ends. If null is given a message id
1614          * null_timestamp will be resolved and returned.
1615          *
1616          * @param       $timestamp      Timestamp to prepare (filter) for display
1617          * @return      $readable       A readable timestamp
1618          */
1619         public function doFilterFormatTimestamp ($timestamp) {
1620                 // Default value to return
1621                 $readable = '???';
1622
1623                 // Is the timestamp null?
1624                 if (is_null($timestamp)) {
1625                         // Get a message string
1626                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
1627                 } else {
1628                         switch ($this->getLanguageInstance()->getLanguageCode()) {
1629                                 case 'de': // German format is a bit different to default
1630                                         // Split the GMT stamp up
1631                                         $dateTime  = explode(' ', $timestamp  );
1632                                         $dateArray = explode('-', $dateTime[0]);
1633                                         $timeArray = explode(':', $dateTime[1]);
1634
1635                                         // Construct the timestamp
1636                                         $readable = sprintf($this->getConfigInstance()->getConfigEntry('german_date_time'),
1637                                                 $dateArray[0],
1638                                                 $dateArray[1],
1639                                                 $dateArray[2],
1640                                                 $timeArray[0],
1641                                                 $timeArray[1],
1642                                                 $timeArray[2]
1643                                         );
1644                                         break;
1645
1646                                 default: // Default is pass-through
1647                                         $readable = $timestamp;
1648                                         break;
1649                         } // END - switch
1650                 }
1651
1652                 // Return the stamp
1653                 return $readable;
1654         }
1655
1656         /**
1657          * Filter a given number into a localized number
1658          *
1659          * @param       $value          The raw value from e.g. database
1660          * @return      $localized      Localized value
1661          */
1662         public function doFilterFormatNumber ($value) {
1663                 // Generate it from config and localize dependencies
1664                 switch ($this->getLanguageInstance()->getLanguageCode()) {
1665                         case 'de': // German format is a bit different to default
1666                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), ',', '.');
1667                                 break;
1668
1669                         default: // US, etc.
1670                                 $localized = number_format($value, $this->getConfigInstance()->getConfigEntry('decimals'), '.', ',');
1671                                 break;
1672                 } // END - switch
1673
1674                 // Return it
1675                 return $localized;
1676         }
1677
1678         /**
1679          * "Getter" for databse entry
1680          *
1681          * @return      $entry  An array with database entries
1682          * @throws      NullPointerException    If the database result is not found
1683          * @throws      InvalidDatabaseResultException  If the database result is invalid
1684          */
1685         protected final function getDatabaseEntry () {
1686                 // Is there an instance?
1687                 if (is_null($this->getResultInstance())) {
1688                         // Throw an exception here
1689                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1690                 } // END - if
1691
1692                 // Rewind it
1693                 $this->getResultInstance()->rewind();
1694
1695                 // Do we have an entry?
1696                 if ($this->getResultInstance()->valid() === FALSE) {
1697                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), DatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
1698                 } // END - if
1699
1700                 // Get next entry
1701                 $this->getResultInstance()->next();
1702
1703                 // Fetch it
1704                 $entry = $this->getResultInstance()->current();
1705
1706                 // And return it
1707                 return $entry;
1708         }
1709
1710         /**
1711          * Getter for field name
1712          *
1713          * @param       $fieldName              Field name which we shall get
1714          * @return      $fieldValue             Field value from the user
1715          * @throws      NullPointerException    If the result instance is null
1716          */
1717         public final function getField ($fieldName) {
1718                 // Default field value
1719                 $fieldValue = NULL;
1720
1721                 // Get result instance
1722                 $resultInstance = $this->getResultInstance();
1723
1724                 // Is this instance null?
1725                 if (is_null($resultInstance)) {
1726                         // Then the user instance is no longer valid (expired cookies?)
1727                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1728                 } // END - if
1729
1730                 // Get current array
1731                 $fieldArray = $resultInstance->current();
1732                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, TRUE).'</pre>');
1733
1734                 // Convert dashes to underscore
1735                 $fieldName = $this->convertDashesToUnderscores($fieldName);
1736
1737                 // Does the field exist?
1738                 if (isset($fieldArray[$fieldName])) {
1739                         // Get it
1740                         $fieldValue = $fieldArray[$fieldName];
1741                 } else {
1742                         // Missing field entry, may require debugging
1743                         self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ':fieldname=' . $fieldName . ' not found!');
1744                 }
1745
1746                 // Return it
1747                 return $fieldValue;
1748         }
1749
1750         /**
1751          * Flushs all pending updates to the database layer
1752          *
1753          * @return      void
1754          */
1755         public function flushPendingUpdates () {
1756                 // Get result instance
1757                 $resultInstance = $this->getResultInstance();
1758
1759                 // Do we have data to update?
1760                 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
1761                         // Get wrapper class name config entry
1762                         $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
1763
1764                         // Create object instance
1765                         $wrapperInstance = ObjectFactory::createObjectByConfiguredName($configEntry);
1766
1767                         // Yes, then send the whole result to the database layer
1768                         $wrapperInstance->doUpdateByResult($this->getResultInstance());
1769                 } // END - if
1770         }
1771
1772         /**
1773          * Outputs a deprecation warning to the developer.
1774          *
1775          * @param       $message        The message we shall output to the developer
1776          * @return      void
1777          * @todo        Write a logging mechanism for productive mode
1778          */
1779         public function deprecationWarning ($message) {
1780                 // Is developer mode active?
1781                 if (defined('DEVELOPER')) {
1782                         // Debug instance is there?
1783                         if (!is_null($this->getDebugInstance())) {
1784                                 // Output stub message
1785                                 self::createDebugInstance(__CLASS__)->debugOutput($message);
1786                         } else {
1787                                 // Trigger an error
1788                                 trigger_error($message . "<br />\n");
1789                                 exit;
1790                         }
1791                 } else {
1792                         // @TODO Finish this part!
1793                         $this->partialStub('Developer mode inactive. Message:' . $message);
1794                 }
1795         }
1796
1797         /**
1798          * Checks whether the given PHP extension is loaded
1799          *
1800          * @param       $phpExtension   The PHP extension we shall check
1801          * @return      $isLoaded       Whether the PHP extension is loaded
1802          */
1803         public final function isPhpExtensionLoaded ($phpExtension) {
1804                 // Is it loaded?
1805                 $isLoaded = in_array($phpExtension, get_loaded_extensions());
1806
1807                 // Return result
1808                 return $isLoaded;
1809         }
1810
1811         /**
1812          * "Getter" as a time() replacement but with milliseconds. You should use this
1813          * method instead of the encapsulated getimeofday() function.
1814          *
1815          * @return      $milliTime      Timestamp with milliseconds
1816          */
1817         public function getMilliTime () {
1818                 // Get the time of day as float
1819                 $milliTime = gettimeofday(TRUE);
1820
1821                 // Return it
1822                 return $milliTime;
1823         }
1824
1825         /**
1826          * Idles (sleeps) for given milliseconds
1827          *
1828          * @return      $hasSlept       Whether it goes fine
1829          */
1830         public function idle ($milliSeconds) {
1831                 // Sleep is fine by default
1832                 $hasSlept = TRUE;
1833
1834                 // Idle so long with found function
1835                 if (function_exists('time_sleep_until')) {
1836                         // Get current time and add idle time
1837                         $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
1838
1839                         // New PHP 5.1.0 function found, ignore errors
1840                         $hasSlept = @time_sleep_until($sleepUntil);
1841                 } else {
1842                         /*
1843                          * My Sun station doesn't have that function even with latest PHP
1844                          * package. :(
1845                          */
1846                         usleep($milliSeconds * 1000);
1847                 }
1848
1849                 // Return result
1850                 return $hasSlept;
1851         }
1852         /**
1853          * Converts a hexadecimal string, even with negative sign as first string to
1854          * a decimal number using BC functions.
1855          *
1856          * This work is based on comment #86673 on php.net documentation page at:
1857          * <http://de.php.net/manual/en/function.dechex.php#86673>
1858          *
1859          * @param       $hex    Hexadecimal string
1860          * @return      $dec    Decimal number
1861          */
1862         protected function hex2dec ($hex) {
1863                 // Convert to all lower-case
1864                 $hex = strtolower($hex);
1865
1866                 // Detect sign (negative/positive numbers)
1867                 $sign = '';
1868                 if (substr($hex, 0, 1) == '-') {
1869                         $sign = '-';
1870                         $hex = substr($hex, 1);
1871                 } // END - if
1872
1873                 // Decode the hexadecimal string into a decimal number
1874                 $dec = 0;
1875                 for ($i = strlen($hex) - 1, $e = 1; $i >= 0; $i--, $e = bcmul($e, 16)) {
1876                         $factor = self::$hexdec[substr($hex, $i, 1)];
1877                         $dec = bcadd($dec, bcmul($factor, $e));
1878                 } // END - for
1879
1880                 // Return the decimal number
1881                 return $sign . $dec;
1882         }
1883
1884         /**
1885          * Converts even very large decimal numbers, also signed, to a hexadecimal
1886          * string.
1887          *
1888          * This work is based on comment #97756 on php.net documentation page at:
1889          * <http://de.php.net/manual/en/function.hexdec.php#97756>
1890          *
1891          * @param       $dec            Decimal number, even with negative sign
1892          * @param       $maxLength      Optional maximum length of the string
1893          * @return      $hex    Hexadecimal string
1894          */
1895         protected function dec2hex ($dec, $maxLength = 0) {
1896                 // maxLength can be zero or devideable by 2
1897                 assert(($maxLength == 0) || (($maxLength % 2) == 0));
1898
1899                 // Detect sign (negative/positive numbers)
1900                 $sign = '';
1901                 if ($dec < 0) {
1902                         $sign = '-';
1903                         $dec = abs($dec);
1904                 } // END - if
1905
1906                 // Encode the decimal number into a hexadecimal string
1907                 $hex = '';
1908                 do {
1909                         $hex = self::$dechex[($dec % (2 ^ 4))] . $hex;
1910                         $dec /= (2 ^ 4);
1911                 } while ($dec >= 1);
1912
1913                 /*
1914                  * Leading zeros are required for hex-decimal "numbers". In some
1915                  * situations more leading zeros are wanted, so check for both
1916                  * conditions.
1917                  */
1918                 if ($maxLength > 0) {
1919                         // Prepend more zeros
1920                         $hex = str_pad($hex, $maxLength, '0', STR_PAD_LEFT);
1921                 } elseif ((strlen($hex) % 2) != 0) {
1922                         // Only make string's length dividable by 2
1923                         $hex = '0' . $hex;
1924                 }
1925
1926                 // Return the hexadecimal string
1927                 return $sign . $hex;
1928         }
1929
1930         /**
1931          * Converts a ASCII string (0 to 255) into a decimal number.
1932          *
1933          * @param       $asc    The ASCII string to be converted
1934          * @return      $dec    Decimal number
1935          */
1936         protected function asc2dec ($asc) {
1937                 // Convert it into a hexadecimal number
1938                 $hex = bin2hex($asc);
1939
1940                 // And back into a decimal number
1941                 $dec = $this->hex2dec($hex);
1942
1943                 // Return it
1944                 return $dec;
1945         }
1946
1947         /**
1948          * Converts a decimal number into an ASCII string.
1949          *
1950          * @param       $dec            Decimal number
1951          * @return      $asc    An ASCII string
1952          */
1953         protected function dec2asc ($dec) {
1954                 // First convert the number into a hexadecimal string
1955                 $hex = $this->dec2hex($dec);
1956
1957                 // Then convert it into the ASCII string
1958                 $asc = $this->hex2asc($hex);
1959
1960                 // Return it
1961                 return $asc;
1962         }
1963
1964         /**
1965          * Converts a hexadecimal number into an ASCII string. Negative numbers
1966          * are not allowed.
1967          *
1968          * @param       $hex    Hexadecimal string
1969          * @return      $asc    An ASCII string
1970          */
1971         protected function hex2asc ($hex) {
1972                 // Check for length, it must be devideable by 2
1973                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('hex='.$hex);
1974                 assert((strlen($hex) % 2) == 0);
1975
1976                 // Walk the string
1977                 $asc = '';
1978                 for ($idx = 0; $idx < strlen($hex); $idx+=2) {
1979                         // Get the decimal number of the chunk
1980                         $part = hexdec(substr($hex, $idx, 2));
1981
1982                         // Add it to the final string
1983                         $asc .= chr($part);
1984                 } // END - for
1985
1986                 // Return the final string
1987                 return $asc;
1988         }
1989
1990         /**
1991          * Checks whether the given encoded data was encoded with Base64
1992          *
1993          * @param       $encodedData    Encoded data we shall check
1994          * @return      $isBase64               Whether the encoded data is Base64
1995          */
1996         protected function isBase64Encoded ($encodedData) {
1997                 // Determine it
1998                 $isBase64 = (@base64_decode($encodedData, TRUE) !== FALSE);
1999
2000                 // Return it
2001                 return $isBase64;
2002         }
2003
2004         /**
2005          * "Getter" to get response/request type from analysis of the system.
2006          *
2007          * @return      $responseType   Analyzed response type
2008          */
2009         protected function getResponseTypeFromSystem () {
2010                 // Default is console
2011                 $responseType = 'console';
2012
2013                 // Is 'HTTP_HOST' set?
2014                 if (isset($_SERVER['HTTP_HOST'])) {
2015                         // Then it is a HTTP response/request
2016                         $responseType = 'http';
2017                 } // END - if
2018
2019                 // Return it
2020                 return $responseType;
2021         }
2022
2023         /**
2024          * Gets a cache key from Criteria instance
2025          *
2026          * @param       $criteriaInstance       An instance of a Criteria class
2027          * @param       $onlyKeys                       Only use these keys for a cache key
2028          * @return      $cacheKey                       A cache key suitable for lookup/storage purposes
2029          */
2030         protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
2031                 // Generate it
2032                 $cacheKey = sprintf('%s@%s',
2033                         $this->__toString(),
2034                         $criteriaInstance->getCacheKey($onlyKeys)
2035                 );
2036
2037                 // And return it
2038                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput($this->__toString() . ': cacheKey=' . $cacheKey);
2039                 return $cacheKey;
2040         }
2041
2042         /**
2043          * Getter for startup time in miliseconds
2044          *
2045          * @return      $startupTime    Startup time in miliseconds
2046          */
2047         protected function getStartupTime () {
2048                 return self::$startupTime;
2049         }
2050
2051         /**
2052          * "Getter" for a printable currently execution time in nice braces
2053          *
2054          * @return      $executionTime  Current execution time in nice braces
2055          */
2056         protected function getPrintableExecutionTime () {
2057                 // Caculate the execution time
2058                 $executionTime = microtime(TRUE) - $this->getStartupTime();
2059
2060                 // Pack it in nice braces
2061                 $executionTime = sprintf('[ %01.5f ] ', $executionTime);
2062
2063                 // And return it
2064                 return $executionTime;
2065         }
2066
2067         /**
2068          * Hashes a given string with a simple but stronger hash function (no salts)
2069          *
2070          * @param       $str    The string to be hashed
2071          * @return      $hash   The hash from string $str
2072          */
2073         public function hashString ($str) {
2074                 // Hash given string with (better secure) hasher
2075                 $hash = mhash(MHASH_SHA256, $str);
2076
2077                 // Return it
2078                 return $hash;
2079         }
2080
2081         /**
2082          * Checks whether the given number is really a number (only chars 0-9).
2083          *
2084          * @param       $num            A string consisting only chars between 0 and 9
2085          * @param       $castValue      Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
2086          * @param       $assertMismatch         Whether to assert mismatches
2087          * @return      $ret            The (hopefully) secured numbered value
2088          */
2089         public function bigintval ($num, $castValue = TRUE, $assertMismatch = FALSE) {
2090                 // Filter all numbers out
2091                 $ret = preg_replace('/[^0123456789]/', '', $num);
2092
2093                 // Shall we cast?
2094                 if ($castValue === TRUE) {
2095                         // Cast to biggest numeric type
2096                         $ret = (double) $ret;
2097                 } // END - if
2098
2099                 // Assert only if requested
2100                 if ($assertMismatch === TRUE) {
2101                         // Has the whole value changed?
2102                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2103                 } // END - if
2104
2105                 // Return result
2106                 return $ret;
2107         }
2108
2109         /**
2110          * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
2111          *
2112          * @param       $num    A string consisting only chars between 0 and 9
2113          * @param       $assertMismatch         Whether to assert mismatches
2114          * @return      $ret    The (hopefully) secured hext-numbered value
2115          */
2116         public function hexval ($num, $assertMismatch = FALSE) {
2117                 // Filter all numbers out
2118                 $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
2119
2120                 // Assert only if requested
2121                 if ($assertMismatch === TRUE) {
2122                         // Has the whole value changed?
2123                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
2124                 } // END - if
2125
2126                 // Return result
2127                 return $ret;
2128         }
2129
2130         /**
2131          * Checks whether start/end marker are set
2132          *
2133          * @param       $data   Data to be checked
2134          * @return      $isset  Whether start/end marker are set
2135          */
2136         public final function ifStartEndMarkersSet ($data) {
2137                 // Determine it
2138                 $isset = ((substr($data, 0, strlen(BaseRawDataHandler::STREAM_START_MARKER)) == BaseRawDataHandler::STREAM_START_MARKER) && (substr($data, -1 * strlen(BaseRawDataHandler::STREAM_END_MARKER), strlen(BaseRawDataHandler::STREAM_END_MARKER)) == BaseRawDataHandler::STREAM_END_MARKER));
2139
2140                 // ... and return it
2141                 return $isset;
2142         }
2143
2144         /**
2145          * Determines if an element is set in the generic array
2146          *
2147          * @param       $keyGroup       Main group for the key
2148          * @param       $subGroup       Sub group for the key
2149          * @param       $key            Key to check
2150          * @param       $element        Element to check
2151          * @return      $isset          Whether the given key is set
2152          */
2153         protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
2154                 // Debug message
2155                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2156
2157                 // Is it there?
2158                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2159
2160                 // Return it
2161                 return $isset;
2162         }
2163         /**
2164          * Determines if a key is set in the generic array
2165          *
2166          * @param       $keyGroup       Main group for the key
2167          * @param       $subGroup       Sub group for the key
2168          * @param       $key            Key to check
2169          * @return      $isset          Whether the given key is set
2170          */
2171         protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
2172                 // Debug message
2173                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2174
2175                 // Is it there?
2176                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
2177
2178                 // Return it
2179                 return $isset;
2180         }
2181
2182
2183         /**
2184          * Determines if a group is set in the generic array
2185          *
2186          * @param       $keyGroup       Main group
2187          * @param       $subGroup       Sub group
2188          * @return      $isset          Whether the given group is set
2189          */
2190         protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
2191                 // Debug message
2192                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2193
2194                 // Is it there?
2195                 $isset = isset($this->genericArray[$keyGroup][$subGroup]);
2196
2197                 // Return it
2198                 return $isset;
2199         }
2200
2201         /**
2202          * Getter for sub key group
2203          *
2204          * @param       $keyGroup       Main key group
2205          * @param       $subGroup       Sub key group
2206          * @return      $array          An array with all array elements
2207          */
2208         protected final function getGenericSubArray ($keyGroup, $subGroup) {
2209                 // Is it there?
2210                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2211                         // No, then abort here
2212                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2213                         exit;
2214                 } // END - if
2215
2216                 // Debug message
2217                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], TRUE));
2218
2219                 // Return it
2220                 return $this->genericArray[$keyGroup][$subGroup];
2221         }
2222
2223         /**
2224          * Unsets a given key in generic array
2225          *
2226          * @param       $keyGroup       Main group for the key
2227          * @param       $subGroup       Sub group for the key
2228          * @param       $key            Key to unset
2229          * @return      void
2230          */
2231         protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) {
2232                 // Debug message
2233                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2234
2235                 // Remove it
2236                 unset($this->genericArray[$keyGroup][$subGroup][$key]);
2237         }
2238
2239         /**
2240          * Unsets a given element in generic array
2241          *
2242          * @param       $keyGroup       Main group for the key
2243          * @param       $subGroup       Sub group for the key
2244          * @param       $key            Key to unset
2245          * @param       $element        Element to unset
2246          * @return      void
2247          */
2248         protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2249                 // Debug message
2250                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2251
2252                 // Remove it
2253                 unset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
2254         }
2255
2256         /**
2257          * Append a string to a given generic array key
2258          *
2259          * @param       $keyGroup       Main group for the key
2260          * @param       $subGroup       Sub group for the key
2261          * @param       $key            Key to unset
2262          * @param       $value          Value to add/append
2263          * @return      void
2264          */
2265         protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') {
2266                 // Debug message
2267                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE) . ',appendGlue=' . $appendGlue);
2268
2269                 // Is it already there?
2270                 if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2271                         // Append it
2272                         $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value;
2273                 } else {
2274                         // Add it
2275                         $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value;
2276                 }
2277         }
2278
2279         /**
2280          * Append a string to a given generic array element
2281          *
2282          * @param       $keyGroup       Main group for the key
2283          * @param       $subGroup       Sub group for the key
2284          * @param       $key            Key to unset
2285          * @param       $element        Element to check
2286          * @param       $value          Value to add/append
2287          * @return      void
2288          */
2289         protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
2290                 // Debug message
2291                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE) . ',appendGlue=' . $appendGlue);
2292
2293                 // Is it already there?
2294                 if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2295                         // Append it
2296                         $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value;
2297                 } else {
2298                         // Add it
2299                         $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value;
2300                 }
2301         }
2302
2303         /**
2304          * Initializes given generic array group
2305          *
2306          * @param       $keyGroup       Main group for the key
2307          * @param       $subGroup       Sub group for the key
2308          * @param       $key            Key to use
2309          * @param       $forceInit      Optionally force initialization
2310          * @return      void
2311          */
2312         protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = FALSE) {
2313                 // Debug message
2314                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit));
2315
2316                 // Is it already set?
2317                 if (($forceInit === FALSE) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) {
2318                         // Already initialized
2319                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.');
2320                         exit;
2321                 } // END - if
2322
2323                 // Initialize it
2324                 $this->genericArray[$keyGroup][$subGroup] = array();
2325         }
2326
2327         /**
2328          * Initializes given generic array key
2329          *
2330          * @param       $keyGroup       Main group for the key
2331          * @param       $subGroup       Sub group for the key
2332          * @param       $key            Key to use
2333          * @param       $forceInit      Optionally force initialization
2334          * @return      void
2335          */
2336         protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = FALSE) {
2337                 // Debug message
2338                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit));
2339
2340                 // Is it already set?
2341                 if (($forceInit === FALSE) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) {
2342                         // Already initialized
2343                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.');
2344                         exit;
2345                 } // END - if
2346
2347                 // Initialize it
2348                 $this->genericArray[$keyGroup][$subGroup][$key] = array();
2349         }
2350
2351         /**
2352          * Initializes given generic array element
2353          *
2354          * @param       $keyGroup       Main group for the key
2355          * @param       $subGroup       Sub group for the key
2356          * @param       $key            Key to use
2357          * @param       $element        Element to use
2358          * @param       $forceInit      Optionally force initialization
2359          * @return      void
2360          */
2361         protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = FALSE) {
2362                 // Debug message
2363                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit));
2364
2365                 // Is it already set?
2366                 if (($forceInit === FALSE) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) {
2367                         // Already initialized
2368                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.');
2369                         exit;
2370                 } // END - if
2371
2372                 // Initialize it
2373                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = array();
2374         }
2375
2376         /**
2377          * Pushes an element to a generic key
2378          *
2379          * @param       $keyGroup       Main group for the key
2380          * @param       $subGroup       Sub group for the key
2381          * @param       $key            Key to use
2382          * @param       $value          Value to add/append
2383          * @return      $count          Number of array elements
2384          */
2385         protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2386                 // Debug message
2387                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2388
2389                 // Is it set?
2390                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2391                         // Initialize array
2392                         $this->initGenericArrayKey($keyGroup, $subGroup, $key);
2393                 } // END - if
2394
2395                 // Then push it
2396                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value);
2397
2398                 // Return count
2399                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2400                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2401                 return $count;
2402         }
2403
2404         /**
2405          * Pushes an element to a generic array element
2406          *
2407          * @param       $keyGroup       Main group for the key
2408          * @param       $subGroup       Sub group for the key
2409          * @param       $key            Key to use
2410          * @param       $element        Element to check
2411          * @param       $value          Value to add/append
2412          * @return      $count          Number of array elements
2413          */
2414         protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2415                 // Debug message
2416                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2417
2418                 // Is it set?
2419                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2420                         // Initialize array
2421                         $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element);
2422                 } // END - if
2423
2424                 // Then push it
2425                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value);
2426
2427                 // Return count
2428                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2429                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
2430                 return $count;
2431         }
2432
2433         /**
2434          * Pops an element from  a generic group
2435          *
2436          * @param       $keyGroup       Main group for the key
2437          * @param       $subGroup       Sub group for the key
2438          * @param       $key            Key to unset
2439          * @return      $value          Last "popped" value
2440          */
2441         protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) {
2442                 // Debug message
2443                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2444
2445                 // Is it set?
2446                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2447                         // Not found
2448                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2449                         exit;
2450                 } // END - if
2451
2452                 // Then "pop" it
2453                 $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]);
2454
2455                 // Return value
2456                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2457                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
2458                 return $value;
2459         }
2460
2461         /**
2462          * Shifts an element from  a generic group
2463          *
2464          * @param       $keyGroup       Main group for the key
2465          * @param       $subGroup       Sub group for the key
2466          * @param       $key            Key to unset
2467          * @return      $value          Last "popped" value
2468          */
2469         protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) {
2470                 // Debug message
2471                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2472
2473                 // Is it set?
2474                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2475                         // Not found
2476                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
2477                         exit;
2478                 } // END - if
2479
2480                 // Then "shift" it
2481                 $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]);
2482
2483                 // Return value
2484                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], TRUE));
2485                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, TRUE) . PHP_EOL);
2486                 return $value;
2487         }
2488
2489         /**
2490          * Count generic array group
2491          *
2492          * @param       $keyGroup       Main group for the key
2493          * @return      $count          Count of given group
2494          */
2495         protected final function countGenericArray ($keyGroup) {
2496                 // Debug message
2497                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2498
2499                 // Is it there?
2500                 if (!isset($this->genericArray[$keyGroup])) {
2501                         // Abort here
2502                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.');
2503                         exit;
2504                 } // END - if
2505
2506                 // Then count it
2507                 $count = count($this->genericArray[$keyGroup]);
2508
2509                 // Debug message
2510                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count);
2511
2512                 // Return it
2513                 return $count;
2514         }
2515
2516         /**
2517          * Count generic array sub group
2518          *
2519          * @param       $keyGroup       Main group for the key
2520          * @param       $subGroup       Sub group for the key
2521          * @return      $count          Count of given group
2522          */
2523         protected final function countGenericArrayGroup ($keyGroup, $subGroup) {
2524                 // Debug message
2525                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2526
2527                 // Is it there?
2528                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
2529                         // Abort here
2530                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2531                         exit;
2532                 } // END - if
2533
2534                 // Then count it
2535                 $count = count($this->genericArray[$keyGroup][$subGroup]);
2536
2537                 // Debug message
2538                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count);
2539
2540                 // Return it
2541                 return $count;
2542         }
2543
2544         /**
2545          * Count generic array elements
2546          *
2547          * @param       $keyGroup       Main group for the key
2548          * @param       $subGroup       Sub group for the key
2549          * @para        $key            Key to count
2550          * @return      $count          Count of given key
2551          */
2552         protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) {
2553                 // Debug message
2554                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2555
2556                 // Is it there?
2557                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2558                         // Abort here
2559                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
2560                         exit;
2561                 } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) {
2562                         // Not valid
2563                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.');
2564                         exit;
2565                 }
2566
2567                 // Then count it
2568                 $count = count($this->genericArray[$keyGroup][$subGroup][$key]);
2569
2570                 // Debug message
2571                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count);
2572
2573                 // Return it
2574                 return $count;
2575         }
2576
2577         /**
2578          * Getter for whole generic group array
2579          *
2580          * @param       $keyGroup       Key group to get
2581          * @return      $array          Whole generic array group
2582          */
2583         protected final function getGenericArray ($keyGroup) {
2584                 // Debug message
2585                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
2586
2587                 // Is it there?
2588                 if (!isset($this->genericArray[$keyGroup])) {
2589                         // Then abort here
2590                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.');
2591                         exit;
2592                 } // END - if
2593
2594                 // Return it
2595                 return $this->genericArray[$keyGroup];
2596         }
2597
2598         /**
2599          * Setter for generic array key
2600          *
2601          * @param       $keyGroup       Key group to get
2602          * @param       $subGroup       Sub group for the key
2603          * @param       $key            Key to unset
2604          * @param       $value          Mixed value from generic array element
2605          * @return      void
2606          */
2607         protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
2608                 // Debug message
2609                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2610
2611                 // Set value here
2612                 $this->genericArray[$keyGroup][$subGroup][$key] = $value;
2613         }
2614
2615         /**
2616          * Getter for generic array key
2617          *
2618          * @param       $keyGroup       Key group to get
2619          * @param       $subGroup       Sub group for the key
2620          * @param       $key            Key to unset
2621          * @return      $value          Mixed value from generic array element
2622          */
2623         protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) {
2624                 // Debug message
2625                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2626
2627                 // Is it there?
2628                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
2629                         // Then abort here
2630                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.');
2631                         exit;
2632                 } // END - if
2633
2634                 // Return it
2635                 return $this->genericArray[$keyGroup][$subGroup][$key];
2636         }
2637
2638         /**
2639          * Sets a value in given generic array key/element
2640          *
2641          * @param       $keyGroup       Main group for the key
2642          * @param       $subGroup       Sub group for the key
2643          * @param       $key            Key to set
2644          * @param       $element        Element to set
2645          * @param       $value          Value to set
2646          * @return      void
2647          */
2648         protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2649                 // Debug message
2650                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',value[' . gettype($value) . ']=' . print_r($value, TRUE));
2651
2652                 // Then set it
2653                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value;
2654         }
2655
2656         /**
2657          * Getter for generic array element
2658          *
2659          * @param       $keyGroup       Key group to get
2660          * @param       $subGroup       Sub group for the key
2661          * @param       $key            Key to look for
2662          * @param       $element        Element to look for
2663          * @return      $value          Mixed value from generic array element
2664          */
2665         protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2666                 // Debug message
2667                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2668
2669                 // Is it there?
2670                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2671                         // Then abort here
2672                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.');
2673                         exit;
2674                 } // END - if
2675
2676                 // Return it
2677                 return $this->genericArray[$keyGroup][$subGroup][$key][$element];
2678         }
2679
2680         /**
2681          * Checks if a given sub group is valid (array)
2682          *
2683          * @param       $keyGroup       Key group to get
2684          * @param       $subGroup       Sub group for the key
2685          * @return      $isValid        Whether given sub group is valid
2686          */
2687         protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) {
2688                 // Debug message
2689                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2690
2691                 // Determine it
2692                 $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup))));
2693
2694                 // Return it
2695                 return $isValid;
2696         }
2697
2698         /**
2699          * Checks if a given key is valid (array)
2700          *
2701          * @param       $keyGroup       Key group to get
2702          * @param       $subGroup       Sub group for the key
2703          * @param       $key            Key to check
2704          * @return      $isValid        Whether given sub group is valid
2705          */
2706         protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) {
2707                 // Debug message
2708                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2709
2710                 // Determine it
2711                 $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key))));
2712
2713                 // Return it
2714                 return $isValid;
2715         }
2716 }
2717
2718 // [EOF]
2719 ?>