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