<?php
// Own namespace
-namespace CoreFramework\Iterator\Registry;
+namespace Org\Mxchange\CoreFramework\Iterator\Registry;
// Import framework stuff
-use CoreFramework\Generic\FrameworkInterface;
-use CoreFramework\Generic\NullPointerException;
-use CoreFramework\Iterator\BaseIterator;
-use CoreFramework\Registry\Register;
-use CoreFramework\Registry\Registerable;
-use CoreFramework\Registry\Sub\SubRegistry;
+use Org\Mxchange\CoreFramework\EntryPoint\ApplicationEntryPoint;
+use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
+use Org\Mxchange\CoreFramework\Generic\NullPointerException;
+use Org\Mxchange\CoreFramework\Iterator\BaseIterator;
+use Org\Mxchange\CoreFramework\Registry\Register;
+use Org\Mxchange\CoreFramework\Registry\Registerable;
+use Org\Mxchange\CoreFramework\Registry\Sub\SubRegistry;
+use Org\Mxchange\CoreFramework\Traits\Registry\RegisterTrait;
// Import SPL stuff
+use \BadMethodCallException;
use \LogicException;
/**
- * A Registry iterator
+ * A registry iterator
*
* @author Roland Haeder <webmaster@ship-simu.org>
* @version 0.0.0
- * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.ship-simu.org
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class RegistryIterator extends BaseIterator implements IteratableRegistry {
+ // Load traits
+ use RegisterTrait;
+
/**
* All found registry keys
*/
- private $registryKeys = array();
+ private $registryKeys = [];
/**
- * Current array key
+ * An array containing keys ob sub-registries which keys should only be
+ * included in the iterator.
*/
- private $key = NULL;
+ private $onlyRegistries = [];
/**
- * Valid status (default: not valid)
+ * Current array key
*/
- private $valid = FALSE;
+ private $key = NULL;
/**
* Protected constructor
*
* @return void
*/
- protected function __construct () {
+ private function __construct () {
// Call parent constructor
parent::__construct(__CLASS__);
+
+ // Init registry keys array
+ $this->registryKeys = [
+ // Generic registry
+ 'generic' => [],
+ // Instance registry
+ 'instance' => [],
+ ];
}
/**
return $iteratorInstance;
}
+ /**
+ * Setter for only-registries array
+ *
+ * @param $onlyRegistries Array with keys only being iterated over
+ * @return void
+ */
+ private function setOnlyRegistries (array $onlyRegistries) {
+ $this->onlyRegistries = $onlyRegistries;
+ }
+
/**
* Initializes this iterator by scanning over the registry for all keys.
*
- * @param $callbackInstance An instance of a FrameworkInterface class to call back (optional)
- * @param $criteriaKey Criteria key (optional)
- * @param $criteriaMethod Method to call back (optional)
+ * @param $onlyRegistries Only iterate on these sub-registry keys, default is all
* @return void
* @throws LogicException If a registry entry does not implement Registerable
* @throws NullPointerException If criteriaKey or criteriaMethod is not set but a call-back instance is set
*/
- public function initIterator (FrameworkInterface $callbackInstance = NULL, $criteriaKey = NULL, $criteriaMethod = NULL) {
- // Is the call-back instance set?
- if ($callbackInstance instanceof FrameworkInterface) {
- // Then also criteria key and method name must be given
- if (is_null($criteriaKey)) {
- // Throw NPE
- throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
- } elseif (is_null($criteriaMethod)) {
- // Throw NPE
- throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
- }
-
- // Set all
- $iteratorInstance->setCallbackInstance($callbackInstance);
- $iteratorInstance->setCriteriaKey($criteriaKey);
- } // END - if
+ public function initIterator (array $onlyRegistries = []) {
+ // Set it in this registry
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR: onlyRegistries()=%d - CALLED!', count($onlyRegistries)));
+ $this->setOnlyRegistries($onlyRegistries);
// Get generic registry entries from it
$entries = $this->getRegistryInstance()->getGenericRegistry();
- // Init registry keys array
- $this->registryKeys['generic'] = array();
-
// Anything in there?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[generic]: entries()=%d', count($entries)));
if (count($entries) > 0) {
// Debugging:
- /* DEBUG-DIE: */ die(sprintf('[%s:%d]: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE)));
- } // END - if
+ /* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: UNFINISHED: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE)));
+ }
// Get instance registry entries from it
$entries = $this->getRegistryInstance()->getInstanceRegistry();
- // Init registry keys array
- $this->registryKeys['instance'] = array();
-
// Anything in there?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: entries()=%d', count($entries)));
if (count($entries) > 0) {
// Then run over all
foreach ($entries as $key => $entry) {
- // Debug message
+ // Is an unwanted registry found?
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,entry[]=%s', $key, gettype($entry)));
-
- // Is it 'socket_registry' ?
- if ($key == 'socket_registry') {
- // Skip this entry
+ if (substr($key, -8, 8) == 'registry') {
+ // Skip this!
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is a registry key, skipping ...', $key));
continue;
- } // END - if
+ }
// Is it an instance of a sub-registry?
- if ($entry instanceof SubRegistry) {
+ if (count($onlyRegistries) > 0 && !in_array($key, $onlyRegistries, TRUE)) {
+ // Not in requested registries
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is not wanted, skipping ...', $key));
+ continue;
+ } elseif ($entry instanceof SubRegistry) {
// Get iterator from this instance
- $iteratorInstance = $entry->getIterator();
-
- // Debugging:
- //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,iteratorInstance=%s', __METHOD__, __LINE__, $key, print_r($iteratorInstance, TRUE)));
-
- // Get all keys
- $keys = $iteratorInstance->getRegistryKeys();
-
- // Should be there
- if (!isset($keys['instance'])) {
- // Should not happen
- throw new LogicException(sprintf('key=%s,keys[instance] is not set.', $key));
- } // END - if
+ $subRegistryInstances = $entry->getInstanceRegistry();
// Add all sub-registry keys to this registry keys array
- $this->registryKeys['instance'][$key] = $keys['instance'];
-
- // Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,keys=%s', $key, print_r($this->registryKeys['instance'][$key], TRUE)));
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: subRegistryInstances()=%d', count($subRegistryInstances)));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: key=%s,subRegistryInstances=%s', __METHOD__, __LINE__, $key, print_r($subRegistryInstances, TRUE)));
+ foreach (array_keys($subRegistryInstances) as $subKey) {
+ // Add it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Adding key=%s,subKey=%s ...', $key, $subKey));
+ array_push($this->registryKeys['instance'], $subKey);
+
+ // Is the current key set?
+ if (is_null($this->key)) {
+ // Init key
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting subKey=%s as first key ...', $subKey));
+ $this->key = $subKey;
+ }
+ }
// Skip below code
continue;
} elseif (!($entry instanceof Registerable)) {
// Not registerable?!
throw new LogicException(sprintf('entry[]=%s does not implement Registerable.', gettype($entry)));
- } elseif (is_null($this->key)) {
- // Debug message
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting key=%s ...', $key));
+ }
- // Init key/valid
+ // Is the current key set?
+ if (is_null($this->key)) {
+ // Init key
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting key=%s as first key ...', $key));
$this->key = $key;
- $this->valid = TRUE;
}
- // Debugging:
- //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,entry=%s', __METHOD__, __LINE__, $key, print_r($entry, TRUE)));
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,entry[]=%s - Adding ...', $key, gettype($entry)));
-
// Add key to array
- $this->registryKeys['instance'][$key] = array();
- } // END - foreach
- } // END - if
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s - Adding ...', $key));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: key=%s,entry=%s', __METHOD__, __LINE__, $key, print_r($entry, TRUE)));
+ array_push($this->registryKeys['instance'], $key);
+ }
+ }
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('REGISTRY-ITERATOR: EXIT!');
}
/**
* Getter for current value from group or generic
*
* @return $current Current value in iteration
+ * @throws NullPointerException If current key points to a non-existing entry in searched registries
*/
public function current () {
// Default is null
- $current = null;
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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)));
+ $current = NULL;
+ $entries = [];
+
+ // Get all registries
+ $allRegistries = $this->getRegistryInstance()->getInstanceRegistry();
+
+ // Loop through all sub-sets
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: allRegistries()=%d', $this->key(), count($allRegistries)));
+ foreach ($allRegistries as $registryKey => $registryInstance) {
+ // Is this key wanted?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s', $this->key(), $registryKey));
+ if (count($this->onlyRegistries) == 0 || in_array($registryKey, $this->onlyRegistries)) {
+ // Yes, then loop through them only
+ $instances = $registryInstance->getInstanceRegistry();
+
+ // The key should be there
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: Handling registryKey=%s ...', $this->key(), $registryKey));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: instances=%s', __METHOD__, __LINE__, print_r($instances, TRUE)));
+ if (!isset($instances[$this->key()])) {
+ // Skip below code
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s has no this->key=%s, skipping ...', $this->key(), $registryKey));
+ continue;
+ }
+
+ // Set as current element and leave loop
+ $current = $instances[$this->key()];
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s,current=%s found. - BREAK!', $this->key(), $registryKey, $current->__toString()));
+ break;
+ }
+ }
- $this->partialStub('Please implement this method.');
+ // Is current still NULL?
+ if (is_null($current)) {
+ // This cannot happen and indicates a logic error
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ }
// Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: current[%s]=%s - EXIT!', $this->key(), gettype($current), $current));
return $current;
}
*/
public function key () {
// Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key));
return $this->key;
}
* Advances to the next entry
*
* @return void
+ * @throws BadMethodCallException If $this->valid() returns FALSE
+ * @throws UnexpectedValueException If $registryType is not changed
*/
public function next () {
- $this->partialStub('Please implement this method.');
+ // Is valid() still TRUE?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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)));
+ if (!$this->valid()) {
+ // Bad method call!
+ throw new BadMethodCallException(sprintf('this->key[%s]=%s is no longer valid, but method was called.', gettype($this->key()), $this->key()));
+ } elseif ((count($this->registryKeys['generic']) == 0) && (count($this->registryKeys['instance']) == 0)) {
+ // Both arrays are empty
+ throw new BadMethodCallException('No array elements in "generic" and "instance" found but method called.');
+ }
+
+ // Default is not valid
+ $nextIndex = -1;
+ $isNextValid = FALSE;
+ $registryType = 'invalid';
+
+ // Get first array element ...
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: this->registryKeys[generic]()=%d,this->registryKeys[instance]()=%d', $this->key(), count($this->registryKeys['generic']), count($this->registryKeys['instance'])));
+ if (count($this->registryKeys['generic']) > 0) {
+ // First generic array
+ /* UNFINISHED */ ApplicationEntryPoint::exitApplication(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)));
+ } elseif (count($this->registryKeys['instance']) > 0) {
+ // Second instance, current key's index + 1
+ $nextIndex = array_search($this->key(), $this->registryKeys['instance']) + 1;
+ $isNextValid = isset($this->registryKeys['instance'][$nextIndex]);
+ $registryType = 'instance';
+ }
+
+ // Is it still valid?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: isNextValid=%d', $this->key(), intval($isNextValid)));
+ if (!$isNextValid) {
+ // Throw exception
+ throw new BadMethodCallException(sprintf('this->key=%s is last key in this iteration. Forgot to invoke valid() before?', $this->key()));
+ } elseif ($registryType == 'invalid') {
+ // Not changed!
+ throw new UnexpectedValueException('registryType has not been changed.');
+ }
+
+ // Yes, then advance to that entry
+ $this->key = $this->registryKeys[$registryType][$nextIndex];
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key()));
}
/**
* Rewinds to the beginning of the iteration
*
* @return void
+ * @throws BadMethodCallException If $this->key is already the first element
*/
public function rewind () {
- // Debugging:
- /* 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)));
+ // Is current key first key?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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)));
+ if (array_search($this->key(), $this->getRegistryKeys()) === 0) {
+ // rewind() cannot rewind first entry!
+ throw new BadMethodCallException(sprintf('this->key=%s is already first element, but method was called.', $this->key()));
+ } elseif ((count($this->registryKeys['generic']) == 0) && (count($this->registryKeys['instance']) == 0)) {
+ // Both arrays are empty
+ throw new BadMethodCallException('No array elements in "generic" and "instance" found but method called.');
+ }
+
+ // Get first array element ...
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: this->registryKeys[generic]()=%d,this->registryKeys[instance]()=%d', $this->key(), count($this->registryKeys['generic']), count($this->registryKeys['instance'])));
+ if (count($this->registryKeys['generic']) > 0) {
+ // First generic array
+ /* UNFINISHED */ ApplicationEntryPoint::exitApplication(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)));
+ } elseif (count($this->registryKeys['instance']) > 0) {
+ // Second instance
+ $this->key = $this->registryKeys['instance'][0];
+ }
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key()));
}
/**
* @return $valid Whether the current key is still valid
*/
public function valid () {
+ // Is the element there?
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key()));
+ //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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)));
+ $valid = (in_array($this->key(), $this->registryKeys['instance']) || in_array($this->key(), $this->registryKeys['generic']));
+
// Return flag
- return $this->valid;
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: valid=%d - EXIT!', $this->key(), intval($valid)));
+ return $valid;
}
}