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