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