3 namespace Org\Mxchange\CoreFramework\Iterator\Registry;
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;
14 use \BadMethodCallException;
20 * @author Roland Haeder <webmaster@ship-simu.org>
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
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.
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.
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/>.
39 class RegistryIterator extends BaseIterator implements IteratableRegistry {
41 * All found registry keys
43 private $registryKeys = [];
46 * An array containing keys ob sub-registries which keys should only be
47 * included in the iterator.
49 private $onlyRegistries = [];
57 * Protected constructor
61 protected function __construct () {
62 // Call parent constructor
63 parent::__construct(__CLASS__);
65 // Init registry keys array
66 $this->registryKeys = [
75 * Creates an instance of this class
77 * @param $registryInstance An instance of a Register class
78 * @return $iteratorInstance An instance of a Iterator class
80 public final static function createRegistryIterator (Register $registryInstance) {
82 $iteratorInstance = new RegistryIterator();
85 $iteratorInstance->setRegistryInstance($registryInstance);
87 // Return the prepared instance
88 return $iteratorInstance;
92 * Setter for only-registries array
94 * @param $onlyRegistries Array with keys only being iterated over
97 private function setOnlyRegistries (array $onlyRegistries) {
98 $this->onlyRegistries = $onlyRegistries;
102 * Initializes this iterator by scanning over the registry for all keys.
104 * @param $onlyRegistries Only iterate on these sub-registry keys, default is all
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
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);
114 // Get generic registry entries from it
115 $entries = $this->getRegistryInstance()->getGenericRegistry();
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) {
121 /* DEBUG-DIE: */ die(sprintf('[%s:%d]: UNFINISHED: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE)));
124 // Get instance registry entries from it
125 $entries = $this->getRegistryInstance()->getInstanceRegistry();
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) {
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') {
136 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is a registry key, skipping ...', $key));
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));
145 } elseif ($entry instanceof SubRegistry) {
146 // Get iterator from this instance
147 $subRegistryInstances = $entry->getInstanceRegistry();
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) {
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);
157 // Is the current key set?
158 if (is_null($this->key)) {
160 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting subKey=%s as first key ...', $subKey));
161 $this->key = $subKey;
167 } elseif (!($entry instanceof Registerable)) {
168 // Not registerable?!
169 throw new LogicException(sprintf('entry[]=%s does not implement Registerable.', gettype($entry)));
172 // Is the current key set?
173 if (is_null($this->key)) {
175 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting key=%s as first key ...', $key));
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);
187 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('REGISTRY-ITERATOR: EXIT!');
191 * Getter for all registry keys (array)
193 * @return $registryKeys Registry keys
195 public final function getRegistryKeys () {
197 return $this->registryKeys;
201 * Getter for current value from group or generic
203 * @return $current Current value in iteration
204 * @throws NullPointerException If current key points to a non-existing entry in searched registries
206 public function current () {
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)));
213 // Get all registries
214 $allRegistries = $this->getRegistryInstance()->getInstanceRegistry();
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();
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()])) {
230 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s has no this->key=%s, skipping ...', $this->key(), $registryKey));
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()));
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);
248 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: current[%s]=%s - EXIT!', $this->key(), gettype($current), $current));
253 * Getter for key from group or generic
255 * @return $key Current key in iteration
257 public function key () {
263 * Advances to the next entry
266 * @throws BadMethodCallException If $this->valid() returns FALSE
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()) {
274 throw new BadMethodCallException(sprintf('this->key[%s]=%s is no longer valid, but method was called.', gettype($this->key()), $this->key()));
279 * Rewinds to the beginning of the iteration
282 * @throws BadMethodCallException If $this->key is already the first element
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()));
295 * Checks wether the current entry is valid (not at the end of the list)
297 * @return $valid Whether the current key is still valid
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']));
306 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: valid=%d - EXIT!', $this->key(), intval($valid)));