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