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