]> git.mxchange.org Git - core.git/blobdiff - framework/main/classes/iterator/registry/class_RegistryIterator.php
Continued:
[core.git] / framework / main / classes / iterator / registry / class_RegistryIterator.php
index 522ad93440943dedebf33b95600791c8d923ca9c..9c9d0b4a44053849aeb6c5a4e7a6c261f193545e 100644 (file)
@@ -1,20 +1,25 @@
 <?php
 // Own namespace
-namespace CoreFramework\Iterator\Registry;
+namespace Org\Mxchange\CoreFramework\Iterator\Registry;
 
 // Import framework stuff
-use CoreFramework\Iterator\BaseIterator;
-use CoreFramework\Registry\Register;
+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;
 
 // Import SPL stuff
-use \Iterator;
+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 - 2020 Core Developer Team
  * @license            GNU GPL 3.0 or any newer version
  * @link               http://www.ship-simu.org
  *
@@ -31,7 +36,28 @@ use \Iterator;
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-class RegistryIterator extends BaseIterator implements Iterator {
+class RegistryIterator extends BaseIterator implements IteratableRegistry {
+       /**
+        * All found registry keys
+        */
+       private $registryKeys = [];
+
+       /**
+        * An array containing keys ob sub-registries which keys should only be
+        * included in the iterator.
+        */
+       private $onlyRegistries = [];
+
+       /**
+        * Current array key
+        */
+       private $key = NULL;
+
+       /**
+        * Registry instance (implementing Register)
+        */
+       private $registryInstance = NULL;
+
        /**
         * Protected constructor
         *
@@ -40,6 +66,14 @@ class RegistryIterator extends BaseIterator implements Iterator {
        protected function __construct () {
                // Call parent constructor
                parent::__construct(__CLASS__);
+
+               // Init registry keys array
+               $this->registryKeys = [
+                       // Generic registry
+                       'generic' => [],
+                       // Instance registry
+                       'instance' => [],
+               ];
        }
 
        /**
@@ -59,18 +93,183 @@ class RegistryIterator extends BaseIterator implements Iterator {
                return $iteratorInstance;
        }
 
+       /**
+        * Setter for registry instance
+        *
+        * @param       $registryInstance               An instance of a Register class
+        * @return      void
+        */
+       protected final function setRegistryInstance (Register $registryInstance) {
+               $this->registryInstance = $registryInstance;
+       }
+
+       /**
+        * Getter for registry instance
+        *
+        * @return      $registryInstance       The debug registry instance
+        */
+       protected final function getRegistryInstance () {
+               return $this->registryInstance;
+       }
+
+       /**
+        * 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       $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 (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();
+
+               // 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: */ ApplicationEntryPoint::exitApplication(sprintf('[%s:%d]: UNFINISHED: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE)));
+               } // END - if
+
+               // Get instance registry entries from it
+               $entries = $this->getRegistryInstance()->getInstanceRegistry();
+
+               // 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) {
+                               // Is an unwanted registry found?
+                               //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,entry[]=%s', $key, gettype($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;
+                               }
+
+                               // Is it an instance of a sub-registry?
+                               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
+                                       $subRegistryInstances = $entry->getInstanceRegistry();
+
+                                       // Add all sub-registry keys to this registry keys array
+                                       //* 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)));
+                               }
+
+                               // 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;
+                               }
+
+                               // Add key to array
+                               //* 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);
+                       } // END - foreach
+               } // END - if
+
+               // Trace message
+               //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('REGISTRY-ITERATOR: EXIT!');
+       }
+
+       /**
+        * Getter for all registry keys (array)
+        *
+        * @return      $registryKeys   Registry keys
+        */
+       public final function getRegistryKeys () {
+               // Return it
+               return $this->registryKeys;
+       }
+
        /**
         * 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;
        }
 
@@ -80,40 +279,110 @@ class RegistryIterator extends BaseIterator implements Iterator {
         * @return      $key    Current key in iteration
         */
        public function key () {
-               // Default is null
-               $key = null;
-
-               $this->partialStub('Please implement this method.');
-
                // Return it
-               return $key;
+               //* 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 () {
-               $this->partialStub('Please implement this method.');
+               // 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()));
        }
 
        /**
         * Checks wether the current entry is valid (not at the end of the list)
         *
-        * @return      void
+        * @return      $valid  Whether the current key is still valid
         */
        public function valid () {
-               $this->partialStub('Please implement this method.');
+               // 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
+               //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: valid=%d - EXIT!', $this->key(), intval($valid)));
+               return $valid;
        }
 
 }