]> git.mxchange.org Git - core.git/blob - framework/main/classes/class_BaseFrameworkSystem.php
0cfc19bb40e37307ca2940a7703c7fb80b4fd785
[core.git] / framework / main / classes / class_BaseFrameworkSystem.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Object;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Criteria\Criteria;
8 use Org\Mxchange\CoreFramework\Criteria\Local\LocalSearchCriteria;
9 use Org\Mxchange\CoreFramework\Crypto\Cryptable;
10 use Org\Mxchange\CoreFramework\Database\Frontend\DatabaseWrapper;
11 use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint;
12 use Org\Mxchange\CoreFramework\Factory\Database\Wrapper\DatabaseWrapperFactory;
13 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
14 use Org\Mxchange\CoreFramework\Filesystem\PathWriteProtectedException;
15 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
16 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
17 use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException;
18 use Org\Mxchange\CoreFramework\Handler\Handleable;
19 use Org\Mxchange\CoreFramework\Helper\Helper;
20 use Org\Mxchange\CoreFramework\Loader\ClassLoader;
21 use Org\Mxchange\CoreFramework\Localization\ManageableLanguage;
22 use Org\Mxchange\CoreFramework\Manager\ManageableApplication;
23 use Org\Mxchange\CoreFramework\Middleware\Debug\DebugMiddleware;
24 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
25 use Org\Mxchange\CoreFramework\Result\Database\CachedDatabaseResult;
26 use Org\Mxchange\CoreFramework\Result\Search\SearchableResult;
27 use Org\Mxchange\CoreFramework\State\Stateable;
28 use Org\Mxchange\CoreFramework\Stream\Input\InputStream;
29 use Org\Mxchange\CoreFramework\Stream\Output\OutputStreamer;
30 use Org\Mxchange\CoreFramework\Stream\Output\OutputStream;
31 use Org\Mxchange\CoreFramework\User\ManageableAccount;
32 use Org\Mxchange\CoreFramework\Utils\String\StringUtils;
33
34 // Import SPL stuff
35 use \stdClass;
36 use \InvalidArgumentException;
37 use \Iterator;
38 use \ReflectionClass;
39 use \SplFileInfo;
40
41 /**
42  * The simulator system class is the super class of all other classes. This
43  * class handles saving of games etc.
44  *
45  * @author              Roland Haeder <webmaster@shipsimu.org>
46  * @version             0.0.0
47  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
48  * @license             GNU GPL 3.0 or any newer version
49  * @link                http://www.shipsimu.org
50  *
51  * This program is free software: you can redistribute it and/or modify
52  * it under the terms of the GNU General Public License as published by
53  * the Free Software Foundation, either version 3 of the License, or
54  * (at your option) any later version.
55  *
56  * This program is distributed in the hope that it will be useful,
57  * but WITHOUT ANY WARRANTY; without even the implied warranty of
58  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
59  * GNU General Public License for more details.
60  *
61  * You should have received a copy of the GNU General Public License
62  * along with this program. If not, see <http://www.gnu.org/licenses/>.
63  */
64 abstract class BaseFrameworkSystem extends stdClass implements FrameworkInterface {
65         /**
66          * Length of output from hash()
67          */
68         private static $hashLength = NULL;
69
70         /**
71          * Self-referencing instance
72          */
73         private static $instance = NULL;
74
75         /**
76          * The real class name
77          */
78         private $realClass = __CLASS__;
79
80         /**
81          * Search criteria instance
82          */
83         private $searchInstance = NULL;
84
85         /**
86          * Database result instance
87          */
88         private $resultInstance = NULL;
89
90         /**
91          * Instance for user class
92          */
93         private $userInstance = NULL;
94
95         /**
96          * Instance of a crypto helper
97          */
98         private $cryptoInstance = NULL;
99
100         /**
101          * Instance of an Iterator class
102          */
103         private $iteratorInstance = NULL;
104
105         /**
106          * A helper instance for the form
107          */
108         private $helperInstance = NULL;
109
110         /**
111          * An instance of a InputStream class
112          */
113         private $inputStreamInstance = NULL;
114
115         /**
116          * An instance of a OutputStream class
117          */
118         private $outputStreamInstance = NULL;
119
120         /**
121          * Handler instance
122          */
123         private $handlerInstance = NULL;
124
125         /**
126          * An instance of a database wrapper class
127          */
128         private $wrapperInstance = NULL;
129
130         /**
131          * State instance
132          */
133         private $stateInstance = NULL;
134
135         /**
136          * Call-back instance
137          */
138         private $callbackInstance = NULL;
139
140         /**
141          * Generic array
142          */
143         private $genericArray = array();
144
145         /***********************
146          * Exception codes.... *
147          ***********************/
148
149         // @todo Try to clean these constants up
150         const EXCEPTION_IS_NULL_POINTER              = 0x001;
151         const EXCEPTION_IS_NO_OBJECT                 = 0x002;
152         const EXCEPTION_IS_NO_ARRAY                  = 0x003;
153         const EXCEPTION_MISSING_METHOD               = 0x004;
154         const EXCEPTION_CLASSES_NOT_MATCHING         = 0x005;
155         const EXCEPTION_INDEX_OUT_OF_BOUNDS          = 0x006;
156         const EXCEPTION_DIMENSION_ARRAY_INVALID      = 0x007;
157         const EXCEPTION_ITEM_NOT_TRADEABLE           = 0x008;
158         const EXCEPTION_ITEM_NOT_IN_PRICE_LIST       = 0x009;
159         const EXCEPTION_GENDER_IS_WRONG              = 0x00a;
160         const EXCEPTION_BIRTH_DATE_IS_INVALID        = 0x00b;
161         const EXCEPTION_EMPTY_STRUCTURES_ARRAY       = 0x00c;
162         const EXCEPTION_HAS_ALREADY_PERSONELL_LIST   = 0x00d;
163         const EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES      = 0x00e;
164         const EXCEPTION_TOTAL_PRICE_NOT_CALCULATED   = 0x00f;
165         const EXCEPTION_HARBOR_HAS_NO_SHIPYARDS      = 0x010;
166         const EXCEPTION_CONTRACT_PARTNER_INVALID     = 0x011;
167         const EXCEPTION_CONTRACT_PARTNER_MISMATCH    = 0x012;
168         const EXCEPTION_CONTRACT_ALREADY_SIGNED      = 0x013;
169         const EXCEPTION_UNEXPECTED_EMPTY_STRING      = 0x014;
170         const EXCEPTION_PATH_NOT_FOUND               = 0x015;
171         const EXCEPTION_INVALID_PATH_NAME            = 0x016;
172         const EXCEPTION_READ_PROTECED_PATH           = 0x017;
173         const EXCEPTION_WRITE_PROTECED_PATH          = 0x018;
174         const EXCEPTION_DIR_POINTER_INVALID          = 0x019;
175         const EXCEPTION_FILE_POINTER_INVALID         = 0x01a;
176         const EXCEPTION_INVALID_RESOURCE             = 0x01b;
177         const EXCEPTION_UNEXPECTED_OBJECT            = 0x01c;
178         const EXCEPTION_LIMIT_ELEMENT_IS_UNSUPPORTED = 0x01d;
179         const EXCEPTION_GETTER_IS_MISSING            = 0x01e;
180         const EXCEPTION_ARRAY_EXPECTED               = 0x01f;
181         const EXCEPTION_ARRAY_HAS_INVALID_COUNT      = 0x020;
182         const EXCEPTION_ID_IS_INVALID_FORMAT         = 0x021;
183         const EXCEPTION_MD5_CHECKSUMS_MISMATCH       = 0x022;
184         const EXCEPTION_UNEXPECTED_STRING_SIZE       = 0x023;
185         const EXCEPTION_SIMULATOR_ID_INVALID         = 0x024;
186         const EXCEPTION_MISMATCHING_COMPRESSORS      = 0x025;
187         const EXCEPTION_CONTAINER_ITEM_IS_NULL       = 0x026;
188         const EXCEPTION_ITEM_IS_NO_ARRAY             = 0x027;
189         const EXCEPTION_CONTAINER_MAYBE_DAMAGED      = 0x028;
190         const EXCEPTION_INVALID_STRING               = 0x029;
191         const EXCEPTION_VARIABLE_NOT_SET             = 0x02a;
192         const EXCEPTION_ATTRIBUTES_ARE_MISSING       = 0x02b;
193         const EXCEPTION_ARRAY_ELEMENTS_MISSING       = 0x02c;
194         const EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED  = 0x02d;
195         const EXCEPTION_UNSPPORTED_OPERATION         = 0x02e;
196         const EXCEPTION_FACTORY_REQUIRE_PARAMETER    = 0x02f;
197         const EXCEPTION_MISSING_ELEMENT              = 0x030;
198         const EXCEPTION_HEADERS_ALREADY_SENT         = 0x031;
199         const EXCEPTION_DEFAULT_CONTROLLER_GONE      = 0x032;
200         const EXCEPTION_CLASS_NOT_FOUND              = 0x033;
201         const EXCEPTION_REQUIRED_INTERFACE_MISSING   = 0x034;
202         const EXCEPTION_FATAL_ERROR                  = 0x035;
203         const EXCEPTION_FILE_NOT_FOUND               = 0x036;
204         const EXCEPTION_ASSERTION_FAILED             = 0x037;
205         const EXCEPTION_FILE_NOT_REACHABLE           = 0x038;
206         const EXCEPTION_FILE_CANNOT_BE_READ          = 0x039;
207         const EXCEPTION_FILE_CANNOT_BE_WRITTEN       = 0x03a;
208         const EXCEPTION_PATH_CANNOT_BE_WRITTEN       = 0x03b;
209         const EXCEPTION_DATABASE_UPDATED_NOT_ALLOWED = 0x03c;
210         const EXCEPTION_FILTER_CHAIN_INTERCEPTED     = 0x03d;
211         const EXCEPTION_INVALID_SOCKET               = 0x03e;
212         const EXCEPTION_SELF_INSTANCE                = 0x03f;
213
214         /**
215          * Startup time in miliseconds
216          */
217         private static $startupTime = 0;
218
219         /**
220          * Protected super constructor
221          *
222          * @param       $className      Name of the class
223          * @return      void
224          */
225         protected function __construct (string $className) {
226                 // Set real class
227                 $this->setRealClass($className);
228
229                 // Is the startup time set? (0 cannot be true anymore)
230                 if (self::$startupTime == 0) {
231                         // Then set it
232                         self::$startupTime = microtime(true);
233                 } // END - if
234         }
235
236         /**
237          * Destructor for all classes. You should not call this method on your own.
238          *
239          * @return      void
240          */
241         public function __destruct () {
242                 // Flush any updated entries to the database
243                 $this->flushPendingUpdates();
244
245                 // Is this object already destroyed?
246                 if ($this->__toString() != 'DestructedObject') {
247                         // Destroy all informations about this class but keep some text about it alive
248                         $this->setRealClass('DestructedObject');
249                 } elseif ((defined('DEBUG_DESTRUCTOR')) && (is_object($this->getDebugInstance()))) {
250                         // Already destructed object
251                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('The object <span class="object_name">%s</span> is already destroyed.',
252                                 $this->__toString()
253                         ));
254                 } else {
255                         // Do not call this twice
256                         trigger_error(__METHOD__ . ': Called twice.');
257                         exit;
258                 }
259         }
260
261         /**
262          * The __call() method where all non-implemented methods end up
263          *
264          * @param       $methodName             Name of the missing method
265          * @args        $args                   Arguments passed to the method
266          * @return      void
267          */
268         public final function __call ($methodName, $args) {
269                 // Set self-instance
270                 self::$instance = $this;
271
272                 // Call static method
273                 self::__callStatic($methodName, $args);
274
275                 // Clear self-instance
276                 self::$instance = NULL;
277         }
278
279         /**
280          * The __callStatic() method where all non-implemented static methods end up
281          *
282          * @param       $methodName             Name of the missing method
283          * @param       $args                   Arguments passed to the method
284          * @return      void
285          * @throws      InvalidArgumentException If self::$instance is not a framework's own object
286          */
287         public static final function __callStatic ($methodName, $args) {
288                 // Trace message
289                 //* PRINT-DEBUG: */ printf('[%s:%d]: methodName=%s,args[]=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $methodName, gettype($args));
290
291                 // Init argument string and class name
292                 $argsString = '';
293                 $className = 'unknown';
294
295                 // Is self-instance set?
296                 if (self::$instance instanceof FrameworkInterface) {
297                         // Framework's own instance
298                         $className = self::$instance->__toString();
299                 } elseif (!is_null(self::$instance)) {
300                         // Invalid argument!
301                         throw new InvalidArgumentException(sprintf('self::instance[%s] is not expected.', gettype(self::$instance)), self::EXCEPTION_SELF_INSTANCE);
302                 }
303
304                 // Is it NULL, empty or an array?
305                 if (is_null($args)) {
306                         // No arguments
307                         $argsString = 'NULL';
308                 } elseif (is_array($args)) {
309                         // Start braces
310                         $argsString = '(';
311
312                         // Some arguments are there
313                         foreach ($args as $arg) {
314                                 // Add data about the argument
315                                 $argsString .= gettype($arg) . ':';
316
317                                 if (is_null($arg)) {
318                                         // Found a NULL argument
319                                         $argsString .= 'NULL';
320                                 } elseif (is_string($arg)) {
321                                         // Add length for strings
322                                         $argsString .= strlen($arg);
323                                 } elseif ((is_int($arg)) || (is_float($arg))) {
324                                         // ... integer/float
325                                         $argsString .= $arg;
326                                 } elseif (is_array($arg)) {
327                                         // .. or size if array
328                                         $argsString .= count($arg);
329                                 } elseif (is_object($arg)) {
330                                         // Get reflection
331                                         $reflection = new ReflectionClass($arg);
332
333                                         // Is an other object, maybe no __toString() available
334                                         $argsString .= $reflection->getName();
335                                 } elseif ($arg === true) {
336                                         // ... is boolean 'true'
337                                         $argsString .= 'true';
338                                 } elseif ($arg === false) {
339                                         // ... is boolean 'false'
340                                         $argsString .= 'false';
341                                 }
342
343                                 // Comma for next one
344                                 $argsString .= ', ';
345                         } // END - foreach
346
347                         // Last comma found?
348                         if (substr($argsString, -2, 1) == ',') {
349                                 // Remove last comma
350                                 $argsString = substr($argsString, 0, -2);
351                         } // END - if
352
353                         // Close braces
354                         $argsString .= ')';
355                 } else {
356                         // Invalid arguments!
357                         $argsString = sprintf('!INVALID:%s!', gettype($args));
358                 }
359
360                 // Output stub message
361                 // @TODO __CLASS__ does always return BaseFrameworkSystem but not the extending (=child) class
362                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s::%s]: Stub! Args: %s',
363                         $className,
364                         $methodName,
365                         $argsString
366                 ));
367
368                 // Return nothing
369                 return NULL;
370         }
371
372         /**
373          * Getter for $realClass
374          *
375          * @return      $realClass The name of the real class (not BaseFrameworkSystem)
376          */
377         public function __toString () {
378                 return $this->realClass;
379         }
380
381         /**
382          * Magic method to catch setting of missing but set class fields/attributes
383          *
384          * @param       $name   Name of the field/attribute
385          * @param       $value  Value to store
386          * @return      void
387          */
388         public final function __set ($name, $value) {
389                 $this->debugBackTrace(sprintf('Tried to set a missing field. name=%s, value[%s]=%s',
390                         $name,
391                         gettype($value),
392                         print_r($value, true)
393                 ));
394         }
395
396         /**
397          * Magic method to catch getting of missing fields/attributes
398          *
399          * @param       $name   Name of the field/attribute
400          * @return      void
401          */
402         public final function __get ($name) {
403                 $this->debugBackTrace(sprintf('Tried to get a missing field. name=%s',
404                         $name
405                 ));
406         }
407
408         /**
409          * Magic method to catch unsetting of missing fields/attributes
410          *
411          * @param       $name   Name of the field/attribute
412          * @return      void
413          */
414         public final function __unset ($name) {
415                 $this->debugBackTrace(sprintf('Tried to unset a missing field. name=%s',
416                         $name
417                 ));
418         }
419
420         /**
421          * Magic method to catch object serialization
422          *
423          * @return      $unsupported    Unsupported method
424          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
425          */
426         public final function __sleep () {
427                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
428         }
429
430         /**
431          * Magic method to catch object deserialization
432          *
433          * @return      $unsupported    Unsupported method
434          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
435          */
436         public final function __wakeup () {
437                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
438         }
439
440         /**
441          * Magic method to catch calls when an object instance is called
442          *
443          * @return      $unsupported    Unsupported method
444          * @throws      UnsupportedOperationException   Objects of this framework cannot be serialized
445          */
446         public final function __invoke () {
447                 throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
448         }
449
450         /**
451          * Setter for the real class name
452          *
453          * @param       $realClass      Class name (string)
454          * @return      void
455          */
456         public final function setRealClass ($realClass) {
457                 // Set real class
458                 $this->realClass = (string) $realClass;
459         }
460
461         /**
462          * Setter for database result instance
463          *
464          * @param       $resultInstance         An instance of a database result class
465          * @return      void
466          * @todo        SearchableResult and UpdateableResult shall have a super interface to use here
467          */
468         protected final function setResultInstance (SearchableResult $resultInstance) {
469                 $this->resultInstance =  $resultInstance;
470         }
471
472         /**
473          * Getter for database result instance
474          *
475          * @return      $resultInstance         An instance of a database result class
476          */
477         public final function getResultInstance () {
478                 return $this->resultInstance;
479         }
480
481         /**
482          * Setter for search instance
483          *
484          * @param       $searchInstance         Searchable criteria instance
485          * @return      void
486          */
487         public final function setSearchInstance (LocalSearchCriteria $searchInstance) {
488                 $this->searchInstance = $searchInstance;
489         }
490
491         /**
492          * Getter for search instance
493          *
494          * @return      $searchInstance         Searchable criteria instance
495          */
496         public final function getSearchInstance () {
497                 return $this->searchInstance;
498         }
499
500         /**
501          * Setter for debug instance
502          *
503          * @param       $debugInstance  The instance for debug output class
504          * @return      void
505          */
506         public final function setDebugInstance (DebugMiddleware $debugInstance) {
507                 GenericRegistry::getRegistry()->addInstance('debug', $debugInstance);
508         }
509
510         /**
511          * Getter for debug instance
512          *
513          * @return      $debugInstance  Instance to class DebugConsoleOutput or DebugWebOutput
514          */
515         public final function getDebugInstance () {
516                 // Get debug instance
517                 $debugInstance = GenericRegistry::getRegistry()->getInstance('debug');
518
519                 // Return it
520                 return $debugInstance;
521         }
522
523         /**
524          * Setter for web output instance
525          *
526          * @param       $webInstance    The instance for web output class
527          * @return      void
528          */
529         public final function setWebOutputInstance (OutputStreamer $webInstance) {
530                 GenericRegistry::getRegistry()->addInstance('web_output', $webInstance);
531         }
532
533         /**
534          * Getter for web output instance
535          *
536          * @return      $webOutputInstance - Instance to class WebOutput
537          */
538         public final function getWebOutputInstance () {
539                 $webOutputInstance = GenericRegistry::getRegistry()->getInstance('web_output');
540                 return $webOutputInstance;
541         }
542
543         /**
544          * Private getter for language instance
545          *
546          * @return      $langInstance   An instance to the language sub-system
547          */
548         protected final function getLanguageInstance () {
549                 $langInstance = GenericRegistry::getRegistry()->getInstance('language');
550                 return $langInstance;
551         }
552
553         /**
554          * Setter for language instance
555          *
556          * @param       $langInstance   An instance to the language sub-system
557          * @return      void
558          * @see         LanguageSystem
559          */
560         public final function setLanguageInstance (ManageableLanguage $langInstance) {
561                 GenericRegistry::getRegistry()->addInstance('language', $langInstance);
562         }
563
564         /**
565          * Protected setter for user instance
566          *
567          * @param       $userInstance   An instance of a user class
568          * @return      void
569          */
570         protected final function setUserInstance (ManageableAccount $userInstance) {
571                 $this->userInstance = $userInstance;
572         }
573
574         /**
575          * Getter for user instance
576          *
577          * @return      $userInstance   An instance of a user class
578          */
579         public final function getUserInstance () {
580                 return $this->userInstance;
581         }
582
583         /**
584          * Setter for Cryptable instance
585          *
586          * @param       $cryptoInstance An instance of a Cryptable class
587          * @return      void
588          */
589         protected final function setCryptoInstance (Cryptable $cryptoInstance) {
590                 $this->cryptoInstance = $cryptoInstance;
591         }
592
593         /**
594          * Getter for Cryptable instance
595          *
596          * @return      $cryptoInstance An instance of a Cryptable class
597          */
598         public final function getCryptoInstance () {
599                 return $this->cryptoInstance;
600         }
601
602         /**
603          * Setter for DatabaseWrapper instance
604          *
605          * @param       $wrapperInstance        An instance of an DatabaseWrapper
606          * @return      void
607          */
608         public final function setWrapperInstance (DatabaseWrapper $wrapperInstance) {
609                 $this->wrapperInstance = $wrapperInstance;
610         }
611
612         /**
613          * Getter for DatabaseWrapper instance
614          *
615          * @return      $wrapperInstance        An instance of an DatabaseWrapper
616          */
617         public final function getWrapperInstance () {
618                 return $this->wrapperInstance;
619         }
620
621         /**
622          * Setter for helper instance
623          *
624          * @param       $helperInstance         An instance of a helper class
625          * @return      void
626          */
627         protected final function setHelperInstance (Helper $helperInstance) {
628                 $this->helperInstance = $helperInstance;
629         }
630
631         /**
632          * Getter for helper instance
633          *
634          * @return      $helperInstance         An instance of a helper class
635          */
636         public final function getHelperInstance () {
637                 return $this->helperInstance;
638         }
639
640         /**
641          * Getter for a InputStream instance
642          *
643          * @param       $inputStreamInstance    The InputStream instance
644          */
645         protected final function getInputStreamInstance () {
646                 return $this->inputStreamInstance;
647         }
648
649         /**
650          * Setter for a InputStream instance
651          *
652          * @param       $inputStreamInstance    The InputStream instance
653          * @return      void
654          */
655         protected final function setInputStreamInstance (InputStream $inputStreamInstance) {
656                 $this->inputStreamInstance = $inputStreamInstance;
657         }
658
659         /**
660          * Getter for a OutputStream instance
661          *
662          * @param       $outputStreamInstance   The OutputStream instance
663          */
664         protected final function getOutputStreamInstance () {
665                 return $this->outputStreamInstance;
666         }
667
668         /**
669          * Setter for a OutputStream instance
670          *
671          * @param       $outputStreamInstance   The OutputStream instance
672          * @return      void
673          */
674         protected final function setOutputStreamInstance (OutputStream $outputStreamInstance) {
675                 $this->outputStreamInstance = $outputStreamInstance;
676         }
677
678         /**
679          * Setter for handler instance
680          *
681          * @param       $handlerInstance        An instance of a Handleable class
682          * @return      void
683          */
684         protected final function setHandlerInstance (Handleable $handlerInstance) {
685                 $this->handlerInstance = $handlerInstance;
686         }
687
688         /**
689          * Getter for handler instance
690          *
691          * @return      $handlerInstance        A Handleable instance
692          */
693         protected final function getHandlerInstance () {
694                 return $this->handlerInstance;
695         }
696
697         /**
698          * Setter for Iterator instance
699          *
700          * @param       $iteratorInstance       An instance of an Iterator
701          * @return      void
702          */
703         protected final function setIteratorInstance (Iterator $iteratorInstance) {
704                 $this->iteratorInstance = $iteratorInstance;
705         }
706
707         /**
708          * Getter for Iterator instance
709          *
710          * @return      $iteratorInstance       An instance of an Iterator
711          */
712         public final function getIteratorInstance () {
713                 return $this->iteratorInstance;
714         }
715
716         /**
717          * Setter for state instance
718          *
719          * @param       $stateInstance  A Stateable instance
720          * @return      void
721          */
722         public final function setStateInstance (Stateable $stateInstance) {
723                 $this->stateInstance = $stateInstance;
724         }
725
726         /**
727          * Getter for state instance
728          *
729          * @return      $stateInstance  A Stateable instance
730          */
731         public final function getStateInstance () {
732                 return $this->stateInstance;
733         }
734
735         /**
736          * Setter for call-back instance
737          *
738          * @param       $callbackInstance       An instance of a FrameworkInterface class
739          * @return      void
740          */
741         public final function setCallbackInstance (FrameworkInterface $callbackInstance) {
742                 $this->callbackInstance = $callbackInstance;
743         }
744
745         /**
746          * Getter for call-back instance
747          *
748          * @return      $callbackInstance       An instance of a FrameworkInterface class
749          */
750         protected final function getCallbackInstance () {
751                 return $this->callbackInstance;
752         }
753
754         /**
755          * Checks whether an object equals this object. You should overwrite this
756          * method to implement own equality checks
757          *
758          * @param       $objectInstance         An instance of a FrameworkInterface object
759          * @return      $equals                         Whether both objects equals
760          */
761         public function equals (FrameworkInterface $objectInstance) {
762                 // Now test it
763                 $equals = ((
764                         $this->__toString() == $objectInstance->__toString()
765                 ) && (
766                         $this->hashCode() == $objectInstance->hashCode()
767                 ));
768
769                 // Return the result
770                 return $equals;
771         }
772
773         /**
774          * Generates a generic hash code of this class. You should really overwrite
775          * this method with your own hash code generator code. But keep KISS in mind.
776          *
777          * @return      $hashCode       A generic hash code respresenting this whole class
778          */
779         public function hashCode () {
780                 // Simple hash code
781                 return crc32($this->__toString());
782         }
783
784         /**
785          * Appends a trailing slash to a string
786          *
787          * @param       $str    A string (maybe) without trailing slash
788          * @return      $str    A string with an auto-appended trailing slash
789          */
790         public final function addMissingTrailingSlash ($str) {
791                 // Is there a trailing slash?
792                 if (substr($str, -1, 1) != '/') {
793                         $str .= '/';
794                 } // END - if
795
796                 // Return string with trailing slash
797                 return $str;
798         }
799
800         /**
801          * Debugs this instance by putting out it's full content
802          *
803          * @param       $message        Optional message to show in debug output
804          * @return      void
805          */
806         public final function debugInstance ($message = '') {
807                 // Restore the error handler to avoid trouble with missing array elements or undeclared variables
808                 restore_error_handler();
809
810                 // Init content
811                 $content = '';
812
813                 // Is a message set?
814                 if (!empty($message)) {
815                         // Construct message
816                         $content = sprintf('<div class="debug_message">
817         Message: %s
818 </div>' . PHP_EOL, $message);
819                 } // END - if
820
821                 // Generate the output
822                 $content .= sprintf('<pre>%s</pre>',
823                         trim(
824                                 htmlentities(
825                                         print_r($this, true)
826                                 )
827                         )
828                 );
829
830                 // Output it
831                 ApplicationEntryPoint::exitApplication(sprintf('<div class="debug_header">
832         %s debug output:
833 </div>
834 <div class="debug_content">
835         %s
836 </div>
837 Loaded includes:
838 <div class="debug_include_list">
839         %s
840 </div>',
841                         $this->__toString(),
842                         $content,
843                         ClassLoader::getSelfInstance()->getPrintableIncludeList()
844                 ));
845         }
846
847         /**
848          * Replaces control characters with printable output
849          *
850          * @param       $str    String with control characters
851          * @return      $str    Replaced string
852          */
853         protected function replaceControlCharacters ($str) {
854                 // Replace them
855                 $str = str_replace(
856                         chr(13), '[r]', str_replace(
857                         chr(10), '[n]', str_replace(
858                         chr(9) , '[t]',
859                         $str
860                 )));
861
862                 // Return it
863                 return $str;
864         }
865
866         /**
867          * Output a partial stub message for the caller method
868          *
869          * @param       $message        An optional message to display
870          * @return      void
871          */
872         protected function partialStub ($message = '') {
873                 // Init variable
874                 $stubMessage = 'Partial stub!';
875
876                 // Is an extra message given?
877                 if (!empty($message)) {
878                         // Then add it as well
879                         $stubMessage .= ' Message: ' . $message;
880                 } // END - if
881
882                 // Debug instance is there?
883                 if (!is_null($this->getDebugInstance())) {
884                         // Output stub message
885                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($stubMessage);
886                 } else {
887                         // Trigger an error
888                         trigger_error($stubMessage);
889                         exit;
890                 }
891         }
892
893         /**
894          * Outputs a debug backtrace and stops further script execution
895          *
896          * @param       $message        An optional message to output
897          * @param       $doExit         Whether exit the program (true is default)
898          * @return      void
899          */
900         public function debugBackTrace ($message = '', $doExit = true) {
901                 // Sorry, there is no other way getting this nice backtrace
902                 if (!empty($message)) {
903                         // Output message
904                         printf('Message: %s<br />' . PHP_EOL, $message);
905                 } // END - if
906
907                 print('<pre>');
908                 debug_print_backtrace();
909                 print('</pre>');
910
911                 // Exit program?
912                 if ($doExit === true) {
913                         exit();
914                 } // END - if
915         }
916
917         /**
918          * Creates an instance of a debugger instance
919          *
920          * @param       $className              Name of the class (currently unsupported)
921          * @param       $lineNumber             Line number where the call was made
922          * @return      $debugInstance  An instance of a debugger class
923          * @deprecated  Not fully, as the new Logger facilities are not finished yet.
924          */
925         public final static function createDebugInstance ($className, $lineNumber = NULL) {
926                 // Is the instance set?
927                 if (!GenericRegistry::getRegistry()->instanceExists('debug')) {
928                         // Init debug instance
929                         $debugInstance = NULL;
930
931                         // Try it
932                         try {
933                                 // Get a debugger instance
934                                 $debugInstance = DebugMiddleware::createDebugMiddleware(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('debug_' . FrameworkBootstrap::getRequestTypeFromSystem() . '_class'), $className);
935                         } catch (NullPointerException $e) {
936                                 // Didn't work, no instance there
937                                 exit(sprintf('Cannot create debugInstance! Exception=%s,message=%s,className=%s,lineNumber=%d' . PHP_EOL, $e->__toString(), $e->getMessage(), $className, $lineNumber));
938                         }
939
940                         // Empty string should be ignored and used for testing the middleware
941                         DebugMiddleware::getSelfInstance()->output('');
942
943                         // Set it in registry
944                         GenericRegistry::getRegistry()->addInstance('debug', $debugInstance);
945                 } else {
946                         // Get instance from registry
947                         $debugInstance = GenericRegistry::getRegistry()->getDebugInstance();
948                 }
949
950                 // Return it
951                 return $debugInstance;
952         }
953
954         /**
955          * Simple output of a message with line-break
956          *
957          * @param       $message        Message to output
958          * @return      void
959          */
960         public function outputLine ($message) {
961                 // Simply output it
962                 print($message . PHP_EOL);
963         }
964
965         /**
966          * Outputs a debug message whether to debug instance (should be set!) or
967          * dies with or ptints the message. Do NEVER EVER rewrite the exit() call to
968          * ApplicationEntryPoint::app_exit(), this would cause an endless loop.
969          *
970          * @param       $message        Message we shall send out...
971          * @param       $doPrint        Whether print or die here (default: print)
972          * @paran       $stripTags      Whether to strip tags (default: false)
973          * @return      void
974          */
975         public function debugOutput ($message, $doPrint = true, $stripTags = false) {
976                 // Set debug instance to NULL
977                 $debugInstance = NULL;
978
979                 // Get backtrace
980                 $backtrace = debug_backtrace(!DEBUG_BACKTRACE_PROVIDE_OBJECT);
981
982                 // Is function partialStub/__callStatic ?
983                 if (in_array($backtrace[1]['function'], array('partialStub', '__call', '__callStatic'))) {
984                         // Prepend class::function:line from 3rd element
985                         $message = sprintf('[%s::%s:%d]: %s',
986                                 $backtrace[2]['class'],
987                                 $backtrace[2]['function'],
988                                 (isset($backtrace[2]['line']) ? $backtrace[2]['line'] : '0'),
989                                 $message
990                         );
991                 } else {
992                         // Prepend class::function:line from 2nd element
993                         $message = sprintf('[%s::%s:%d]: %s',
994                                 $backtrace[1]['class'],
995                                 $backtrace[1]['function'],
996                                 (isset($backtrace[1]['line']) ? $backtrace[1]['line'] : '0'),
997                                 $message
998                         );
999                 }
1000
1001                 // Try it:
1002                 try {
1003                         // Get debug instance
1004                         $debugInstance = $this->getDebugInstance();
1005                 } catch (NullPointerException $e) {
1006                         // The debug instance is not set (yet)
1007                 }
1008
1009                 // Is the debug instance there?
1010                 if (is_object($debugInstance)) {
1011                         // Use debug output handler
1012                         $debugInstance->output($message, $stripTags);
1013
1014                         if ($doPrint === false) {
1015                                 // Die here if not printed
1016                                 exit();
1017                         } // END - if
1018                 } else {
1019                         // Are debug times enabled?
1020                         if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('debug_' . FrameworkBootstrap::getRequestTypeFromSystem() . '_output_timings') == 'Y') {
1021                                 // Prepent it
1022                                 $message = $this->getPrintableExecutionTime() . $message;
1023                         } // END - if
1024
1025                         // Put directly out
1026                         if ($doPrint === true) {
1027                                 // Print message
1028                                 $this->outputLine($message);
1029                         } else {
1030                                 // Die here
1031                                 exit($message);
1032                         }
1033                 }
1034         }
1035
1036         /**
1037          * Marks up the code by adding e.g. line numbers
1038          *
1039          * @param       $phpCode                Unmarked PHP code
1040          * @return      $markedCode             Marked PHP code
1041          */
1042         public function markupCode ($phpCode) {
1043                 // Init marked code
1044                 $markedCode = '';
1045
1046                 // Get last error
1047                 $errorArray = error_get_last();
1048
1049                 // Init the code with error message
1050                 if (is_array($errorArray)) {
1051                         // Get error infos
1052                         $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>',
1053                                 basename($errorArray['file']),
1054                                 $errorArray['line'],
1055                                 $errorArray['message'],
1056                                 $errorArray['type']
1057                         );
1058                 } // END - if
1059
1060                 // Add line number to the code
1061                 foreach (explode(chr(10), $phpCode) as $lineNo => $code) {
1062                         // Add line numbers
1063                         $markedCode .= sprintf('<span id="code_line">%s</span>: %s' . PHP_EOL,
1064                                 ($lineNo + 1),
1065                                 htmlentities($code, ENT_QUOTES)
1066                         );
1067                 } // END - foreach
1068
1069                 // Return the code
1070                 return $markedCode;
1071         }
1072
1073         /**
1074          * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
1075          * beatiful for web-based front-ends. If null is given a message id
1076          * null_timestamp will be resolved and returned.
1077          *
1078          * @param       $timestamp      Timestamp to prepare (filter) for display
1079          * @return      $readable       A readable timestamp
1080          */
1081         public function doFilterFormatTimestamp ($timestamp) {
1082                 // Default value to return
1083                 $readable = '???';
1084
1085                 // Is the timestamp null?
1086                 if (is_null($timestamp)) {
1087                         // Get a message string
1088                         $readable = $this->getLanguageInstance()->getMessage('null_timestamp');
1089                 } else {
1090                         switch ($this->getLanguageInstance()->getLanguageCode()) {
1091                                 case 'de': // German format is a bit different to default
1092                                         // Split the GMT stamp up
1093                                         $dateTime  = explode(' ', $timestamp  );
1094                                         $dateArray = explode('-', $dateTime[0]);
1095                                         $timeArray = explode(':', $dateTime[1]);
1096
1097                                         // Construct the timestamp
1098                                         $readable = sprintf(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('german_date_time'),
1099                                                 $dateArray[0],
1100                                                 $dateArray[1],
1101                                                 $dateArray[2],
1102                                                 $timeArray[0],
1103                                                 $timeArray[1],
1104                                                 $timeArray[2]
1105                                         );
1106                                         break;
1107
1108                                 default: // Default is pass-through
1109                                         $readable = $timestamp;
1110                                         break;
1111                         } // END - switch
1112                 }
1113
1114                 // Return the stamp
1115                 return $readable;
1116         }
1117
1118         /**
1119          * Filter a given number into a localized number
1120          *
1121          * @param       $value          The raw value from e.g. database
1122          * @return      $localized      Localized value
1123          */
1124         public function doFilterFormatNumber ($value) {
1125                 // Generate it from config and localize dependencies
1126                 switch ($this->getLanguageInstance()->getLanguageCode()) {
1127                         case 'de': // German format is a bit different to default
1128                                 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), ',', '.');
1129                                 break;
1130
1131                         default: // US, etc.
1132                                 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), '.', ',');
1133                                 break;
1134                 } // END - switch
1135
1136                 // Return it
1137                 return $localized;
1138         }
1139
1140         /**
1141          * "Getter" for databse entry
1142          *
1143          * @return      $entry  An array with database entries
1144          * @throws      NullPointerException    If the database result is not found
1145          * @throws      InvalidDatabaseResultException  If the database result is invalid
1146          */
1147         protected final function getDatabaseEntry () {
1148                 // Is there an instance?
1149                 if (!$this->getResultInstance() instanceof SearchableResult) {
1150                         // Throw an exception here
1151                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1152                 } // END - if
1153
1154                 // Rewind it
1155                 $this->getResultInstance()->rewind();
1156
1157                 // Do we have an entry?
1158                 if ($this->getResultInstance()->valid() === false) {
1159                         // @TODO Move the constant to e.g. BaseDatabaseResult when there is a non-cached database result available
1160                         throw new InvalidDatabaseResultException(array($this, $this->getResultInstance()), CachedDatabaseResult::EXCEPTION_INVALID_DATABASE_RESULT);
1161                 } // END - if
1162
1163                 // Get next entry
1164                 $this->getResultInstance()->next();
1165
1166                 // Fetch it
1167                 $entry = $this->getResultInstance()->current();
1168
1169                 // And return it
1170                 return $entry;
1171         }
1172
1173         /**
1174          * Getter for field name
1175          *
1176          * @param       $fieldName              Field name which we shall get
1177          * @return      $fieldValue             Field value from the user
1178          * @throws      NullPointerException    If the result instance is null
1179          */
1180         public final function getField (string $fieldName) {
1181                 // Default field value
1182                 $fieldValue = NULL;
1183
1184                 // Get result instance
1185                 $resultInstance = $this->getResultInstance();
1186
1187                 // Is this instance null?
1188                 if (is_null($resultInstance)) {
1189                         // Then the user instance is no longer valid (expired cookies?)
1190                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1191                 } // END - if
1192
1193                 // Get current array
1194                 $fieldArray = $resultInstance->current();
1195                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.':<pre>'.print_r($fieldArray, true).'</pre>');
1196
1197                 // Convert dashes to underscore
1198                 $fieldName2 = StringUtils::convertDashesToUnderscores($fieldName);
1199
1200                 // Does the field exist?
1201                 if ($this->isFieldSet($fieldName)) {
1202                         // Get it
1203                         $fieldValue = $fieldArray[$fieldName2];
1204                 } elseif (defined('DEVELOPER')) {
1205                         // Missing field entry, may require debugging
1206                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldArray<pre>=' . print_r($fieldArray, true) . '</pre>,fieldName=' . $fieldName . ' not found!');
1207                 } else {
1208                         // Missing field entry, may require debugging
1209                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']:fieldName=' . $fieldName . ' not found!');
1210                 }
1211
1212                 // Return it
1213                 return $fieldValue;
1214         }
1215
1216         /**
1217          * Checks if given field is set
1218          *
1219          * @param       $fieldName      Field name to check
1220          * @return      $isSet          Whether the given field name is set
1221          * @throws      NullPointerException    If the result instance is null
1222          */
1223         public function isFieldSet (string $fieldName) {
1224                 // Get result instance
1225                 $resultInstance = $this->getResultInstance();
1226
1227                 // Is this instance null?
1228                 if (is_null($resultInstance)) {
1229                         // Then the user instance is no longer valid (expired cookies?)
1230                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
1231                 } // END - if
1232
1233                 // Get current array
1234                 $fieldArray = $resultInstance->current();
1235                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . $this->__toString() . ':' . __LINE__ . '] fieldName=' . $fieldName . ',fieldArray=<pre>'.print_r($fieldArray, true).'</pre>');
1236
1237                 // Convert dashes to underscore
1238                 $fieldName = StringUtils::convertDashesToUnderscores($fieldName);
1239
1240                 // Determine it
1241                 $isSet = isset($fieldArray[$fieldName]);
1242
1243                 // Return result
1244                 return $isSet;
1245         }
1246
1247         /**
1248          * Flushs all pending updates to the database layer
1249          *
1250          * @return      void
1251          */
1252         public function flushPendingUpdates () {
1253                 // Get result instance
1254                 $resultInstance = $this->getResultInstance();
1255
1256                 // Do we have data to update?
1257                 if ((is_object($resultInstance)) && ($resultInstance->ifDataNeedsFlush())) {
1258                         // Get wrapper class name config entry
1259                         $configEntry = $resultInstance->getUpdateInstance()->getWrapperConfigEntry();
1260
1261                         // Create object instance
1262                         $wrapperInstance = DatabaseWrapperFactory::createWrapperByConfiguredName($configEntry);
1263
1264                         // Yes, then send the whole result to the database layer
1265                         $wrapperInstance->doUpdateByResult($this->getResultInstance());
1266                 } // END - if
1267         }
1268
1269         /**
1270          * Outputs a deprecation warning to the developer.
1271          *
1272          * @param       $message        The message we shall output to the developer
1273          * @return      void
1274          * @todo        Write a logging mechanism for productive mode
1275          */
1276         public function deprecationWarning ($message) {
1277                 // Is developer mode active?
1278                 if (defined('DEVELOPER')) {
1279                         // Debug instance is there?
1280                         if (!is_null($this->getDebugInstance())) {
1281                                 // Output stub message
1282                                 self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($message);
1283                         } else {
1284                                 // Trigger an error
1285                                 trigger_error($message . "<br />\n");
1286                                 exit;
1287                         }
1288                 } else {
1289                         // @TODO Finish this part!
1290                         $this->partialStub('Developer mode inactive. Message:' . $message);
1291                 }
1292         }
1293
1294         /**
1295          * Checks whether the given PHP extension is loaded
1296          *
1297          * @param       $phpExtension   The PHP extension we shall check
1298          * @return      $isLoaded       Whether the PHP extension is loaded
1299          */
1300         public final function isPhpExtensionLoaded ($phpExtension) {
1301                 // Is it loaded?
1302                 $isLoaded = in_array($phpExtension, get_loaded_extensions());
1303
1304                 // Return result
1305                 return $isLoaded;
1306         }
1307
1308         /**
1309          * "Getter" as a time() replacement but with milliseconds. You should use this
1310          * method instead of the encapsulated getimeofday() function.
1311          *
1312          * @return      $milliTime      Timestamp with milliseconds
1313          */
1314         public function getMilliTime () {
1315                 // Get the time of day as float
1316                 $milliTime = gettimeofday(true);
1317
1318                 // Return it
1319                 return $milliTime;
1320         }
1321
1322         /**
1323          * Idles (sleeps) for given milliseconds
1324          *
1325          * @return      $hasSlept       Whether it goes fine
1326          */
1327         public function idle ($milliSeconds) {
1328                 // Sleep is fine by default
1329                 $hasSlept = true;
1330
1331                 // Idle so long with found function
1332                 if (function_exists('time_sleep_until')) {
1333                         // Get current time and add idle time
1334                         $sleepUntil = $this->getMilliTime() + abs($milliSeconds) / 1000;
1335
1336                         // New PHP 5.1.0 function found, ignore errors
1337                         $hasSlept = @time_sleep_until($sleepUntil);
1338                 } else {
1339                         /*
1340                          * My Sun station doesn't have that function even with latest PHP
1341                          * package. :(
1342                          */
1343                         usleep($milliSeconds * 1000);
1344                 }
1345
1346                 // Return result
1347                 return $hasSlept;
1348         }
1349
1350         /**
1351          * Checks whether the given encoded data was encoded with Base64
1352          *
1353          * @param       $encodedData    Encoded data we shall check
1354          * @return      $isBase64               Whether the encoded data is Base64
1355          */
1356         protected function isBase64Encoded ($encodedData) {
1357                 // Determine it
1358                 $isBase64 = (@base64_decode($encodedData, true) !== false);
1359
1360                 // Return it
1361                 return $isBase64;
1362         }
1363
1364         /**
1365          * Gets a cache key from Criteria instance
1366          *
1367          * @param       $criteriaInstance       An instance of a Criteria class
1368          * @param       $onlyKeys                       Only use these keys for a cache key
1369          * @return      $cacheKey                       A cache key suitable for lookup/storage purposes
1370          */
1371         protected function getCacheKeyByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
1372                 // Generate it
1373                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FRAMEWORK-SYSTEM: criteriaInstance=' . $criteriaInstance->__toString() . ',onlyKeys()=' . count($onlyKeys) . ' - CALLED!');
1374                 $cacheKey = sprintf('%s@%s',
1375                         $this->__toString(),
1376                         $criteriaInstance->getCacheKey($onlyKeys)
1377                 );
1378
1379                 // And return it
1380                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FRAMEWORK-SYSTEM: cacheKey=' . $cacheKey . ' - EXIT!');
1381                 return $cacheKey;
1382         }
1383
1384         /**
1385          * Getter for startup time in miliseconds
1386          *
1387          * @return      $startupTime    Startup time in miliseconds
1388          */
1389         protected function getStartupTime () {
1390                 return self::$startupTime;
1391         }
1392
1393         /**
1394          * "Getter" for a printable currently execution time in nice braces
1395          *
1396          * @return      $executionTime  Current execution time in nice braces
1397          */
1398         protected function getPrintableExecutionTime () {
1399                 // Caculate the execution time
1400                 $executionTime = microtime(true) - $this->getStartupTime();
1401
1402                 // Pack it in nice braces
1403                 $executionTime = sprintf('[ %01.5f ] ', $executionTime);
1404
1405                 // And return it
1406                 return $executionTime;
1407         }
1408
1409         /**
1410          * Hashes a given string with a simple but stronger hash function (no salt)
1411          * and hex-encode it.
1412          *
1413          * @param       $str    The string to be hashed
1414          * @return      $hash   The hash from string $str
1415          */
1416         public static final function hash ($str) {
1417                 // Hash given string with (better secure) hasher
1418                 $hash = bin2hex(mhash(MHASH_SHA256, $str));
1419
1420                 // Return it
1421                 return $hash;
1422         }
1423
1424         /**
1425          * "Getter" for length of hash() output. This will be "cached" to speed up
1426          * things.
1427          *
1428          * @return      $length         Length of hash() output
1429          */
1430         public static final function getHashLength () {
1431                 // Is it cashed?
1432                 if (is_null(self::$hashLength)) {
1433                         // No, then hash a string and save its length.
1434                         self::$hashLength = strlen(self::hash('abc123'));
1435                 } // END - if
1436
1437                 // Return it
1438                 return self::$hashLength;
1439         }
1440
1441         /**
1442          * Checks whether the given number is really a number (only chars 0-9).
1443          *
1444          * @param       $num            A string consisting only chars between 0 and 9
1445          * @param       $castValue      Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
1446          * @param       $assertMismatch         Whether to assert mismatches
1447          * @return      $ret            The (hopefully) secured numbered value
1448          */
1449         public function bigintval ($num, $castValue = true, $assertMismatch = false) {
1450                 // Filter all numbers out
1451                 $ret = preg_replace('/[^0123456789]/', '', $num);
1452
1453                 // Shall we cast?
1454                 if ($castValue === true) {
1455                         // Cast to biggest numeric type
1456                         $ret = (double) $ret;
1457                 } // END - if
1458
1459                 // Assert only if requested
1460                 if ($assertMismatch === true) {
1461                         // Has the whole value changed?
1462                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
1463                 } // END - if
1464
1465                 // Return result
1466                 return $ret;
1467         }
1468
1469         /**
1470          * Checks whether the given hexadecimal number is really a hex-number (only chars 0-9,a-f).
1471          *
1472          * @param       $num    A string consisting only chars between 0 and 9
1473          * @param       $assertMismatch         Whether to assert mismatches
1474          * @return      $ret    The (hopefully) secured hext-numbered value
1475          */
1476         public function hexval ($num, $assertMismatch = false) {
1477                 // Filter all numbers out
1478                 $ret = preg_replace('/[^0123456789abcdefABCDEF]/', '', $num);
1479
1480                 // Assert only if requested
1481                 if ($assertMismatch === true) {
1482                         // Has the whole value changed?
1483                         assert(('' . $ret . '' != '' . $num . '') && (!is_null($num)));
1484                 } // END - if
1485
1486                 // Return result
1487                 return $ret;
1488         }
1489
1490         /**
1491          * Determines if an element is set in the generic array
1492          *
1493          * @param       $keyGroup       Main group for the key
1494          * @param       $subGroup       Sub group for the key
1495          * @param       $key            Key to check
1496          * @param       $element        Element to check
1497          * @return      $isset          Whether the given key is set
1498          */
1499         protected final function isGenericArrayElementSet ($keyGroup, $subGroup, $key, $element) {
1500                 // Debug message
1501                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
1502
1503                 // Is it there?
1504                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
1505
1506                 // Return it
1507                 return $isset;
1508         }
1509         /**
1510          * Determines if a key is set in the generic array
1511          *
1512          * @param       $keyGroup       Main group for the key
1513          * @param       $subGroup       Sub group for the key
1514          * @param       $key            Key to check
1515          * @return      $isset          Whether the given key is set
1516          */
1517         protected final function isGenericArrayKeySet ($keyGroup, $subGroup, $key) {
1518                 // Debug message
1519                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1520
1521                 // Is it there?
1522                 $isset = isset($this->genericArray[$keyGroup][$subGroup][$key]);
1523
1524                 // Return it
1525                 return $isset;
1526         }
1527
1528
1529         /**
1530          * Determines if a group is set in the generic array
1531          *
1532          * @param       $keyGroup       Main group
1533          * @param       $subGroup       Sub group
1534          * @return      $isset          Whether the given group is set
1535          */
1536         protected final function isGenericArrayGroupSet ($keyGroup, $subGroup) {
1537                 // Debug message
1538                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
1539
1540                 // Is it there?
1541                 $isset = isset($this->genericArray[$keyGroup][$subGroup]);
1542
1543                 // Return it
1544                 return $isset;
1545         }
1546
1547         /**
1548          * Getter for sub key group
1549          *
1550          * @param       $keyGroup       Main key group
1551          * @param       $subGroup       Sub key group
1552          * @return      $array          An array with all array elements
1553          */
1554         protected final function getGenericSubArray ($keyGroup, $subGroup) {
1555                 // Is it there?
1556                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
1557                         // No, then abort here
1558                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
1559                         exit;
1560                 } // END - if
1561
1562                 // Debug message
1563                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',value=' . print_r($this->genericArray[$keyGroup][$subGroup], true));
1564
1565                 // Return it
1566                 return $this->genericArray[$keyGroup][$subGroup];
1567         }
1568
1569         /**
1570          * Unsets a given key in generic array
1571          *
1572          * @param       $keyGroup       Main group for the key
1573          * @param       $subGroup       Sub group for the key
1574          * @param       $key            Key to unset
1575          * @return      void
1576          */
1577         protected final function unsetGenericArrayKey ($keyGroup, $subGroup, $key) {
1578                 // Debug message
1579                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1580
1581                 // Remove it
1582                 unset($this->genericArray[$keyGroup][$subGroup][$key]);
1583         }
1584
1585         /**
1586          * Unsets a given element in generic array
1587          *
1588          * @param       $keyGroup       Main group for the key
1589          * @param       $subGroup       Sub group for the key
1590          * @param       $key            Key to unset
1591          * @param       $element        Element to unset
1592          * @return      void
1593          */
1594         protected final function unsetGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
1595                 // Debug message
1596                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
1597
1598                 // Remove it
1599                 unset($this->genericArray[$keyGroup][$subGroup][$key][$element]);
1600         }
1601
1602         /**
1603          * Append a string to a given generic array key
1604          *
1605          * @param       $keyGroup       Main group for the key
1606          * @param       $subGroup       Sub group for the key
1607          * @param       $key            Key to unset
1608          * @param       $value          Value to add/append
1609          * @return      void
1610          */
1611         protected final function appendStringToGenericArrayKey ($keyGroup, $subGroup, $key, $value, $appendGlue = '') {
1612                 // Debug message
1613                 //* 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);
1614
1615                 // Is it already there?
1616                 if ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1617                         // Append it
1618                         $this->genericArray[$keyGroup][$subGroup][$key] .= $appendGlue . (string) $value;
1619                 } else {
1620                         // Add it
1621                         $this->genericArray[$keyGroup][$subGroup][$key] = (string) $value;
1622                 }
1623         }
1624
1625         /**
1626          * Append a string to a given generic array element
1627          *
1628          * @param       $keyGroup       Main group for the key
1629          * @param       $subGroup       Sub group for the key
1630          * @param       $key            Key to unset
1631          * @param       $element        Element to check
1632          * @param       $value          Value to add/append
1633          * @return      void
1634          */
1635         protected final function appendStringToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
1636                 // Debug message
1637                 //* 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);
1638
1639                 // Is it already there?
1640                 if ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
1641                         // Append it
1642                         $this->genericArray[$keyGroup][$subGroup][$key][$element] .= $appendGlue . (string) $value;
1643                 } else {
1644                         // Add it
1645                         $this->setStringGenericArrayElement($keyGroup, $subGroup, $key, $element, $value);
1646                 }
1647         }
1648
1649         /**
1650          * Sets a string in a given generic array element
1651          *
1652          * @param       $keyGroup       Main group for the key
1653          * @param       $subGroup       Sub group for the key
1654          * @param       $key            Key to unset
1655          * @param       $element        Element to check
1656          * @param       $value          Value to add/append
1657          * @return      void
1658          */
1659         protected final function setStringGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value, $appendGlue = '') {
1660                 // Debug message
1661                 //* 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);
1662
1663                 // Set it
1664                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = (string) $value;
1665         }
1666
1667         /**
1668          * Initializes given generic array group
1669          *
1670          * @param       $keyGroup       Main group for the key
1671          * @param       $subGroup       Sub group for the key
1672          * @param       $key            Key to use
1673          * @param       $forceInit      Optionally force initialization
1674          * @return      void
1675          */
1676         protected final function initGenericArrayGroup ($keyGroup, $subGroup, $forceInit = false) {
1677                 // Debug message
1678                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',forceInit=' . intval($forceInit));
1679
1680                 // Is it already set?
1681                 if (($forceInit === false) && ($this->isGenericArrayGroupSet($keyGroup, $subGroup))) {
1682                         // Already initialized
1683                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' already initialized.');
1684                         exit;
1685                 } // END - if
1686
1687                 // Initialize it
1688                 $this->genericArray[$keyGroup][$subGroup] = array();
1689         }
1690
1691         /**
1692          * Initializes given generic array key
1693          *
1694          * @param       $keyGroup       Main group for the key
1695          * @param       $subGroup       Sub group for the key
1696          * @param       $key            Key to use
1697          * @param       $forceInit      Optionally force initialization
1698          * @return      void
1699          */
1700         protected final function initGenericArrayKey ($keyGroup, $subGroup, $key, $forceInit = false) {
1701                 // Debug message
1702                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',forceInit=' . intval($forceInit));
1703
1704                 // Is it already set?
1705                 if (($forceInit === false) && ($this->isGenericArrayKeySet($keyGroup, $subGroup, $key))) {
1706                         // Already initialized
1707                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' already initialized.');
1708                         exit;
1709                 } // END - if
1710
1711                 // Initialize it
1712                 $this->genericArray[$keyGroup][$subGroup][$key] = array();
1713         }
1714
1715         /**
1716          * Initializes given generic array element
1717          *
1718          * @param       $keyGroup       Main group for the key
1719          * @param       $subGroup       Sub group for the key
1720          * @param       $key            Key to use
1721          * @param       $element        Element to use
1722          * @param       $forceInit      Optionally force initialization
1723          * @return      void
1724          */
1725         protected final function initGenericArrayElement ($keyGroup, $subGroup, $key, $element, $forceInit = false) {
1726                 // Debug message
1727                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ',forceInit=' . intval($forceInit));
1728
1729                 // Is it already set?
1730                 if (($forceInit === false) && ($this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element))) {
1731                         // Already initialized
1732                         trigger_error(__METHOD__ . ':keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' already initialized.');
1733                         exit;
1734                 } // END - if
1735
1736                 // Initialize it
1737                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = array();
1738         }
1739
1740         /**
1741          * Pushes an element to a generic key
1742          *
1743          * @param       $keyGroup       Main group for the key
1744          * @param       $subGroup       Sub group for the key
1745          * @param       $key            Key to use
1746          * @param       $value          Value to add/append
1747          * @return      $count          Number of array elements
1748          */
1749         protected final function pushValueToGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
1750                 // Debug message
1751                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, true));
1752
1753                 // Is it set?
1754                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1755                         // Initialize array
1756                         $this->initGenericArrayKey($keyGroup, $subGroup, $key);
1757                 } // END - if
1758
1759                 // Then push it
1760                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key], $value);
1761
1762                 // Return count
1763                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
1764                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
1765                 return $count;
1766         }
1767
1768         /**
1769          * Pushes an element to a generic array element
1770          *
1771          * @param       $keyGroup       Main group for the key
1772          * @param       $subGroup       Sub group for the key
1773          * @param       $key            Key to use
1774          * @param       $element        Element to check
1775          * @param       $value          Value to add/append
1776          * @return      $count          Number of array elements
1777          */
1778         protected final function pushValueToGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
1779                 // Debug message
1780                 //* 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));
1781
1782                 // Is it set?
1783                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
1784                         // Initialize array
1785                         $this->initGenericArrayElement($keyGroup, $subGroup, $key, $element);
1786                 } // END - if
1787
1788                 // Then push it
1789                 $count = array_push($this->genericArray[$keyGroup][$subGroup][$key][$element], $value);
1790
1791                 // Return count
1792                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
1793                 //* DEBUG: */ print(__METHOD__ . ': count=' . $count . PHP_EOL);
1794                 return $count;
1795         }
1796
1797         /**
1798          * Pops an element from  a generic group
1799          *
1800          * @param       $keyGroup       Main group for the key
1801          * @param       $subGroup       Sub group for the key
1802          * @param       $key            Key to unset
1803          * @return      $value          Last "popped" value
1804          */
1805         protected final function popGenericArrayElement ($keyGroup, $subGroup, $key) {
1806                 // Debug message
1807                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1808
1809                 // Is it set?
1810                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1811                         // Not found
1812                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
1813                         exit;
1814                 } // END - if
1815
1816                 // Then "pop" it
1817                 $value = array_pop($this->genericArray[$keyGroup][$subGroup][$key]);
1818
1819                 // Return value
1820                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
1821                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, true) . PHP_EOL);
1822                 return $value;
1823         }
1824
1825         /**
1826          * Shifts an element from  a generic group
1827          *
1828          * @param       $keyGroup       Main group for the key
1829          * @param       $subGroup       Sub group for the key
1830          * @param       $key            Key to unset
1831          * @return      $value          Last "popped" value
1832          */
1833         protected final function shiftGenericArrayElement ($keyGroup, $subGroup, $key) {
1834                 // Debug message
1835                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1836
1837                 // Is it set?
1838                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1839                         // Not found
1840                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' not found.');
1841                         exit;
1842                 } // END - if
1843
1844                 // Then "shift" it
1845                 $value = array_shift($this->genericArray[$keyGroup][$subGroup][$key]);
1846
1847                 // Return value
1848                 //* DEBUG: */ print(__METHOD__ . ': genericArray=' . print_r($this->genericArray[$keyGroup][$subGroup][$key], true));
1849                 //* DEBUG: */ print(__METHOD__ . ': value[' . gettype($value) . ']=' . print_r($value, true) . PHP_EOL);
1850                 return $value;
1851         }
1852
1853         /**
1854          * Count generic array group
1855          *
1856          * @param       $keyGroup       Main group for the key
1857          * @return      $count          Count of given group
1858          */
1859         protected final function countGenericArray ($keyGroup) {
1860                 // Debug message
1861                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
1862
1863                 // Is it there?
1864                 if (!isset($this->genericArray[$keyGroup])) {
1865                         // Abort here
1866                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' not found.');
1867                         exit;
1868                 } // END - if
1869
1870                 // Then count it
1871                 $count = count($this->genericArray[$keyGroup]);
1872
1873                 // Debug message
1874                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',count=' . $count);
1875
1876                 // Return it
1877                 return $count;
1878         }
1879
1880         /**
1881          * Count generic array sub group
1882          *
1883          * @param       $keyGroup       Main group for the key
1884          * @param       $subGroup       Sub group for the key
1885          * @return      $count          Count of given group
1886          */
1887         protected final function countGenericArrayGroup ($keyGroup, $subGroup) {
1888                 // Debug message
1889                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
1890
1891                 // Is it there?
1892                 if (!$this->isGenericArrayGroupSet($keyGroup, $subGroup)) {
1893                         // Abort here
1894                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
1895                         exit;
1896                 } // END - if
1897
1898                 // Then count it
1899                 $count = count($this->genericArray[$keyGroup][$subGroup]);
1900
1901                 // Debug message
1902                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',count=' . $count);
1903
1904                 // Return it
1905                 return $count;
1906         }
1907
1908         /**
1909          * Count generic array elements
1910          *
1911          * @param       $keyGroup       Main group for the key
1912          * @param       $subGroup       Sub group for the key
1913          * @para        $key            Key to count
1914          * @return      $count          Count of given key
1915          */
1916         protected final function countGenericArrayElements ($keyGroup, $subGroup, $key) {
1917                 // Debug message
1918                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1919
1920                 // Is it there?
1921                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1922                         // Abort here
1923                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' not found.');
1924                         exit;
1925                 } elseif (!$this->isValidGenericArrayGroup($keyGroup, $subGroup)) {
1926                         // Not valid
1927                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ' is not an array.');
1928                         exit;
1929                 }
1930
1931                 // Then count it
1932                 $count = count($this->genericArray[$keyGroup][$subGroup][$key]);
1933
1934                 // Debug message
1935                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',count=' . $count);
1936
1937                 // Return it
1938                 return $count;
1939         }
1940
1941         /**
1942          * Getter for whole generic group array
1943          *
1944          * @param       $keyGroup       Key group to get
1945          * @return      $array          Whole generic array group
1946          */
1947         protected final function getGenericArray ($keyGroup) {
1948                 // Debug message
1949                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup);
1950
1951                 // Is it there?
1952                 if (!isset($this->genericArray[$keyGroup])) {
1953                         // Then abort here
1954                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ' does not exist.');
1955                         exit;
1956                 } // END - if
1957
1958                 // Return it
1959                 return $this->genericArray[$keyGroup];
1960         }
1961
1962         /**
1963          * Setter for generic array key
1964          *
1965          * @param       $keyGroup       Key group to get
1966          * @param       $subGroup       Sub group for the key
1967          * @param       $key            Key to unset
1968          * @param       $value          Mixed value from generic array element
1969          * @return      void
1970          */
1971         protected final function setGenericArrayKey ($keyGroup, $subGroup, $key, $value) {
1972                 // Debug message
1973                 //* NOISY-DEBUG: */ if (!is_object($value)) $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',value[' . gettype($value) . ']=' . print_r($value, true));
1974
1975                 // Set value here
1976                 $this->genericArray[$keyGroup][$subGroup][$key] = $value;
1977         }
1978
1979         /**
1980          * Getter for generic array key
1981          *
1982          * @param       $keyGroup       Key group to get
1983          * @param       $subGroup       Sub group for the key
1984          * @param       $key            Key to unset
1985          * @return      $value          Mixed value from generic array element
1986          */
1987         protected final function getGenericArrayKey ($keyGroup, $subGroup, $key) {
1988                 // Debug message
1989                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
1990
1991                 // Is it there?
1992                 if (!$this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) {
1993                         // Then abort here
1994                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ' does not exist.');
1995                         exit;
1996                 } // END - if
1997
1998                 // Return it
1999                 return $this->genericArray[$keyGroup][$subGroup][$key];
2000         }
2001
2002         /**
2003          * Sets a value in given generic array key/element
2004          *
2005          * @param       $keyGroup       Main group for the key
2006          * @param       $subGroup       Sub group for the key
2007          * @param       $key            Key to set
2008          * @param       $element        Element to set
2009          * @param       $value          Value to set
2010          * @return      void
2011          */
2012         protected final function setGenericArrayElement ($keyGroup, $subGroup, $key, $element, $value) {
2013                 // Debug message
2014                 //* 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));
2015
2016                 // Then set it
2017                 $this->genericArray[$keyGroup][$subGroup][$key][$element] = $value;
2018         }
2019
2020         /**
2021          * Getter for generic array element
2022          *
2023          * @param       $keyGroup       Key group to get
2024          * @param       $subGroup       Sub group for the key
2025          * @param       $key            Key to look for
2026          * @param       $element        Element to look for
2027          * @return      $value          Mixed value from generic array element
2028          */
2029         protected final function getGenericArrayElement ($keyGroup, $subGroup, $key, $element) {
2030                 // Debug message
2031                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element);
2032
2033                 // Is it there?
2034                 if (!$this->isGenericArrayElementSet($keyGroup, $subGroup, $key, $element)) {
2035                         // Then abort here
2036                         trigger_error(__METHOD__ . ': keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key . ',element=' . $element . ' does not exist.');
2037                         exit;
2038                 } // END - if
2039
2040                 // Return it
2041                 return $this->genericArray[$keyGroup][$subGroup][$key][$element];
2042         }
2043
2044         /**
2045          * Checks if a given sub group is valid (array)
2046          *
2047          * @param       $keyGroup       Key group to get
2048          * @param       $subGroup       Sub group for the key
2049          * @return      $isValid        Whether given sub group is valid
2050          */
2051         protected final function isValidGenericArrayGroup ($keyGroup, $subGroup) {
2052                 // Debug message
2053                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup);
2054
2055                 // Determine it
2056                 $isValid = (($this->isGenericArrayGroupSet($keyGroup, $subGroup)) && (is_array($this->getGenericSubArray($keyGroup, $subGroup))));
2057
2058                 // Return it
2059                 return $isValid;
2060         }
2061
2062         /**
2063          * Checks if a given key is valid (array)
2064          *
2065          * @param       $keyGroup       Key group to get
2066          * @param       $subGroup       Sub group for the key
2067          * @param       $key            Key to check
2068          * @return      $isValid        Whether given sub group is valid
2069          */
2070         protected final function isValidGenericArrayKey ($keyGroup, $subGroup, $key) {
2071                 // Debug message
2072                 //* NOISY-DEBUG: */ $this->outputLine('[' . __METHOD__ . ':' . __LINE__ . '] keyGroup=' . $keyGroup . ',subGroup=' . $subGroup . ',key=' . $key);
2073
2074                 // Determine it
2075                 $isValid = (($this->isGenericArrayKeySet($keyGroup, $subGroup, $key)) && (is_array($this->getGenericArrayKey($keyGroup, $subGroup, $key))));
2076
2077                 // Return it
2078                 return $isValid;
2079         }
2080
2081         /**
2082          * Initializes the web output instance
2083          *
2084          * @return      void
2085          */
2086         protected function initWebOutputInstance () {
2087                 // Get application instance
2088                 $applicationInstance = GenericRegistry::getRegistry()->getInstance('application');
2089
2090                 // Init web output instance
2091                 $outputInstance = ObjectFactory::createObjectByConfiguredName('output_class', array($applicationInstance));
2092
2093                 // Set it locally
2094                 $this->setWebOutputInstance($outputInstance);
2095         }
2096
2097         /**
2098          * Translates boolean true to 'Y' and false to 'N'
2099          *
2100          * @param       $boolean                Boolean value
2101          * @return      $translated             Translated boolean value
2102          */
2103         public static final function translateBooleanToYesNo (bool $boolean) {
2104                 // Make sure it is really boolean
2105                 assert(is_bool($boolean));
2106
2107                 // "Translate" it
2108                 $translated = ($boolean === true) ? 'Y' : 'N';
2109
2110                 // ... and return it
2111                 return $translated;
2112         }
2113
2114         /**
2115          * Creates a full-qualified file name (FQFN) for given file name by adding
2116          * a configured temporary file path to it.
2117          *
2118          * @param       $infoInstance   An instance of a SplFileInfo class
2119          * @return      $tempInstance   An instance of a SplFileInfo class (temporary file)
2120          * @throw       PathWriteProtectedException If the path in 'temp_file_path' is write-protected
2121          * @throws      FileIoException If the file cannot be written
2122          */
2123          protected static function createTempPathForFile (SplFileInfo $infoInstance) {
2124                 // Get config entry
2125                 $basePath = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('temp_file_path');
2126
2127                 // Is the path writeable?
2128                 if (!is_writable($basePath)) {
2129                         // Path is write-protected
2130                         throw new PathWriteProtectedException($infoInstance, self::EXCEPTION_PATH_CANNOT_BE_WRITTEN);
2131                 } // END - if
2132
2133                 // Add it
2134                 $tempInstance = new SplFileInfo($basePath . DIRECTORY_SEPARATOR . $infoInstance->getBasename());
2135
2136                 // Is it reachable?
2137                 if (!FrameworkBootstrap::isReachableFilePath($tempInstance)) {
2138                         // Not reachable
2139                         throw new FileIoException($tempInstance, self::EXCEPTION_FILE_NOT_REACHABLE);
2140                 } // END - if
2141
2142                 // Return it
2143                 return $tempInstance;
2144          }
2145
2146         /**
2147          * "Getter" for a printable state name
2148          *
2149          * @return      $stateName      Name of the node's state in a printable format
2150          */
2151         public final function getPrintableState () {
2152                 // Default is 'null'
2153                 $stateName = 'null';
2154
2155                 // Get the state instance
2156                 $stateInstance = $this->getStateInstance();
2157
2158                 // Is it an instance of Stateable?
2159                 if ($stateInstance instanceof Stateable) {
2160                         // Then use that state name
2161                         $stateName = $stateInstance->getStateName();
2162                 } // END - if
2163
2164                 // Return result
2165                 return $stateName;
2166         }
2167
2168 }