]> git.mxchange.org Git - core.git/blob - framework/main/classes/iterator/registry/class_RegistryIterator.php
Continued:
[core.git] / framework / main / classes / iterator / registry / class_RegistryIterator.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Iterator\Registry;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
7 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
8 use Org\Mxchange\CoreFramework\Iterator\BaseIterator;
9 use Org\Mxchange\CoreFramework\Registry\Register;
10 use Org\Mxchange\CoreFramework\Registry\Registerable;
11 use Org\Mxchange\CoreFramework\Registry\Sub\SubRegistry;
12
13 // Import SPL stuff
14 use \BadMethodCallException;
15 use \LogicException;
16
17 /**
18  * A registry iterator
19  *
20  * @author              Roland Haeder <webmaster@ship-simu.org>
21  * @version             0.0.0
22  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
23  * @license             GNU GPL 3.0 or any newer version
24  * @link                http://www.ship-simu.org
25  *
26  * This program is free software: you can redistribute it and/or modify
27  * it under the terms of the GNU General Public License as published by
28  * the Free Software Foundation, either version 3 of the License, or
29  * (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
38  */
39 class RegistryIterator extends BaseIterator implements IteratableRegistry {
40         /**
41          * All found registry keys
42          */
43         private $registryKeys = [];
44
45         /**
46          * An array containing keys ob sub-registries which keys should only be
47          * included in the iterator.
48          */
49         private $onlyRegistries = [];
50
51         /**
52          * Current array key
53          */
54         private $key = NULL;
55
56         /**
57          * Protected constructor
58          *
59          * @return      void
60          */
61         protected function __construct () {
62                 // Call parent constructor
63                 parent::__construct(__CLASS__);
64
65                 // Init registry keys array
66                 $this->registryKeys = [
67                         // Generic registry
68                         'generic' => [],
69                         // Instance registry
70                         'instance' => [],
71                 ];
72         }
73
74         /**
75          * Creates an instance of this class
76          *
77          * @param       $registryInstance       An instance of a Register class
78          * @return      $iteratorInstance       An instance of a Iterator class
79          */
80         public final static function createRegistryIterator (Register $registryInstance) {
81                 // Get new instance
82                 $iteratorInstance = new RegistryIterator();
83
84                 // Set registry here
85                 $iteratorInstance->setRegistryInstance($registryInstance);
86
87                 // Return the prepared instance
88                 return $iteratorInstance;
89         }
90
91         /**
92          * Setter for only-registries array
93          *
94          * @param       $onlyRegistries         Array with keys only being iterated over
95          * @return      void
96          */
97         private function setOnlyRegistries (array $onlyRegistries) {
98                 $this->onlyRegistries = $onlyRegistries;
99         }
100
101         /**
102          * Initializes this iterator by scanning over the registry for all keys.
103          *
104          * @param       $onlyRegistries         Only iterate on these sub-registry keys, default is all
105          * @return      void
106          * @throws      LogicException  If a registry entry does not implement Registerable
107          * @throws      NullPointerException    If criteriaKey or criteriaMethod is not set but a call-back instance is set
108          */
109         public function initIterator (array $onlyRegistries = []) {
110                 // Set it in this registry
111                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR: onlyRegistries()=%d - CALLED!', count($onlyRegistries)));
112                 $this->setOnlyRegistries($onlyRegistries);
113
114                 // Get generic registry entries from it
115                 $entries = $this->getRegistryInstance()->getGenericRegistry();
116
117                 // Anything in there?
118                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[generic]: entries()=%d', count($entries)));
119                 if (count($entries) > 0) {
120                         // Debugging:
121                         /* DEBUG-DIE: */ die(sprintf('[%s:%d]: UNFINISHED: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE)));
122                 } // END - if
123
124                 // Get instance registry entries from it
125                 $entries = $this->getRegistryInstance()->getInstanceRegistry();
126
127                 // Anything in there?
128                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: entries()=%d', count($entries)));
129                 if (count($entries) > 0) {
130                         // Then run over all
131                         foreach ($entries as $key => $entry) {
132                                 // Is an unwanted registry found?
133                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,entry[]=%s', $key, gettype($entry)));
134                                 if (substr($key, -8, 8) == 'registry') {
135                                         // Skip this!
136                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is a registry key, skipping ...', $key));
137                                         continue;
138                                 }
139
140                                 // Is it an instance of a sub-registry?
141                                 if (count($onlyRegistries) > 0 && !in_array($key, $onlyRegistries, TRUE)) {
142                                         // Not in requested registries
143                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is not wanted, skipping ...', $key));
144                                         continue;
145                                 } elseif ($entry instanceof SubRegistry) {
146                                         // Get iterator from this instance
147                                         $subRegistryInstances = $entry->getInstanceRegistry();
148
149                                         // Add all sub-registry keys to this registry keys array
150                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: subRegistryInstances()=%d', count($subRegistryInstances)));
151                                         //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,subRegistryInstances=%s', __METHOD__, __LINE__, $key, print_r($subRegistryInstances, TRUE)));
152                                         foreach (array_keys($subRegistryInstances) as $subKey) {
153                                                 // Add it
154                                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Adding key=%s,subKey=%s ...', $key, $subKey));
155                                                 array_push($this->registryKeys['instance'], $subKey);
156
157                                                 // Is the current key set?
158                                                 if (is_null($this->key)) {
159                                                         // Init key
160                                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting subKey=%s as first key ...', $subKey));
161                                                         $this->key = $subKey;
162                                                 }
163                                         }
164
165                                         // Skip below code
166                                         continue;
167                                 } elseif (!($entry instanceof Registerable)) {
168                                         // Not registerable?!
169                                         throw new LogicException(sprintf('entry[]=%s does not implement Registerable.', gettype($entry)));
170                                 }
171
172                                 // Is the current key set?
173                                 if (is_null($this->key)) {
174                                         // Init key
175                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting key=%s as first key ...', $key));
176                                         $this->key = $key;
177                                 }
178
179                                 // Add key to array
180                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s - Adding ...', $key));
181                                 //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,entry=%s', __METHOD__, __LINE__, $key, print_r($entry, TRUE)));
182                                 array_push($this->registryKeys['instance'], $key);
183                         } // END - foreach
184                 } // END - if
185
186                 // Trace message
187                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('REGISTRY-ITERATOR: EXIT!');
188         }
189
190         /**
191          * Getter for all registry keys (array)
192          *
193          * @return      $registryKeys   Registry keys
194          */
195         public final function getRegistryKeys () {
196                 // Return it
197                 return $this->registryKeys;
198         }
199
200         /**
201          * Getter for current value from group or generic
202          *
203          * @return      $current        Current value in iteration
204          * @throws      NullPointerException    If current key points to a non-existing entry in searched registries
205          */
206         public function current () {
207                 // Default is null
208                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
209                 //* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE)));
210                 $current = NULL;
211                 $entries = [];
212
213                 // Get all registries
214                 $allRegistries = $this->getRegistryInstance()->getInstanceRegistry();
215
216                 // Loop through all sub-sets
217                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: allRegistries()=%d', $this->key(), count($allRegistries)));
218                 foreach ($allRegistries as $registryKey => $registryInstance) {
219                         // Is this key wanted?
220                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s', $this->key(), $registryKey));
221                         if (count($this->onlyRegistries) == 0 || in_array($registryKey, $this->onlyRegistries)) {
222                                 // Yes, then loop through them only
223                                 $instances = $registryInstance->getInstanceRegistry();
224
225                                 // The key should be there
226                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: Handling registryKey=%s ...', $this->key(), $registryKey));
227                                 //* DEBUG-DIE: */ die(sprintf('[%s:%d]: instances=%s', __METHOD__, __LINE__, print_r($instances, TRUE)));
228                                 if (!isset($instances[$this->key()])) {
229                                         // Skip below code
230                                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s has no this->key=%s, skipping ...', $this->key(), $registryKey));
231                                         continue;
232                                 }
233
234                                 // Set as current element and leave loop
235                                 $current = $instances[$this->key()];
236                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s,current=%s found. - BREAK!', $this->key(), $registryKey, $current->__toString()));
237                                 break;
238                         }
239                 }
240
241                 // Is current still NULL?
242                 if (is_null($current)) {
243                         // This cannot happen and indicates a logic error
244                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
245                 }
246
247                 // Return it
248                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: current[%s]=%s - EXIT!', $this->key(), gettype($current), $current));
249                 return $current;
250         }
251
252         /**
253          * Getter for key from group or generic
254          *
255          * @return      $key    Current key in iteration
256          */
257         public function key () {
258                 // Return it
259                 return $this->key;
260         }
261
262         /**
263          * Advances to the next entry
264          *
265          * @return      void
266          * @throws      BadMethodCallException  If $this->valid() returns FALSE
267          */
268         public function next () {
269                 // Is valid() still TRUE?
270                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
271                 /* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE)));
272                 if (!$this->valid()) {
273                         // Bad method call!
274                         throw new BadMethodCallException(sprintf('this->key[%s]=%s is no longer valid, but method was called.', gettype($this->key()), $this->key()));
275                 }
276         }
277
278         /**
279          * Rewinds to the beginning of the iteration
280          *
281          * @return      void
282          * @throws      BadMethodCallException  If $this->key is already the first element
283          */
284         public function rewind () {
285                 // Is current key first key?
286                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
287                 /* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE)));
288                 if (array_search($this->key(), $this->getRegistryKeys()) === 0) {
289                         // rewind() cannot rewind first entry!
290                         throw new BadMethodCallException(sprintf('this->key=%s is already first element, but method was called.', $this->key()));
291                 }
292         }
293
294         /**
295          * Checks wether the current entry is valid (not at the end of the list)
296          *
297          * @return      $valid  Whether the current key is still valid
298          */
299         public function valid () {
300                 // Is the element there?
301                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
302                 //* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), print_r($this->registryKeys, TRUE)));
303                 $valid = (in_array($this->key(), $this->registryKeys['instance']) || in_array($this->key(), $this->registryKeys['generic']));
304
305                 // Return flag
306                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: valid=%d - EXIT!', $this->key(), intval($valid)));
307                 return $valid;
308         }
309
310 }