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