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