<?php
// Own namespace
-namespace Org\Mxchange\CoreFramework\Stacker;
+namespace Org\Mxchange\CoreFramework\Stack;
// Import framework stuff
+use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
+use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
+// Import SPL stuff
+use \BadMethodCallException;
+use \InvalidArgumentException;
+
/**
* A general Stacker
*
* @author Roland Haeder <webmaster@shipsimu.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 - 2023 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.shipsimu.org
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
abstract class BaseStacker extends BaseFrameworkSystem {
- // Exception codes
- const EXCEPTION_STACKER_ALREADY_INITIALIZED = 0x050;
- const EXCEPTION_STACKER_IS_FULL = 0x051;
- const EXCEPTION_NO_STACKER_FOUND = 0x052;
- const EXCEPTION_STACKER_IS_EMPTY = 0x053;
+ /**
+ * Array "caches" configuration entries for saving "expensive" method
+ * invocations
+ */
+ private $cachedMaxStackSizes = [];
/**
* Protected constructor
* @param $className Name of the class
* @return void
*/
- protected function __construct ($className) {
+ protected function __construct (string $className) {
// Call parent constructor
parent::__construct($className);
}
* @param $stackerName Name of the stack
* @param $forceReInit Force re-initialization
* @return void
- * @throws AlreadyInitializedStackerException If the stack is already initialized
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If the stack is already initialized
*/
- public function initStack ($stackerName, $forceReInit = false) {
- // Is the stack already initialized?
- if (($forceReInit === false) && ($this->isStackInitialized($stackerName))) {
+ public function initStack (string $stackerName, bool $forceReInit = false) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s,forceReInit=%d - CALLED!', $stackerName, intval($forceReInit)));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (($forceReInit === false) && ($this->isStackInitialized($stackerName))) {
// Then throw the exception
- throw new AlreadyInitializedStackerException(array($this, $stackerName, $forceReInit), self::EXCEPTION_STACKER_ALREADY_INITIALIZED);
- } // END - if
+ throw new BadMethodCallException(array($this, $stackerName, $forceReInit), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
+ }
- // Initialize the given stack
+ // Initialize the given stack and "cache" configuration entry
$this->initGenericArrayKey('stacks', $stackerName, 'entries', $forceReInit);
+ $this->cachedMaxStackSizes[$stackerName] = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry(sprintf('stacker_%s_max_size', $stackerName));
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
}
/**
* Initializes all stacks
*
* @return void
+ * @throws InvalidArgumentException If a parameter is invalid
*/
- public function initStacks (array $stacks, $forceReInit = false) {
+ public function initStacks (array $stacks, bool $forceReInit = false) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stacks()=%d,forceReInit=%d - CALLED!', count($stacks), intval($forceReInit)));
+ if (count($stacks) == 0) {
+ // No empty stack name
+ throw new InvalidArgumentException('Array "stacks" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ }
+
// "Walk" through all (more will be added as needed
foreach ($stacks as $stackerName) {
// Init this stack
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: Invoking this->initStack(%s,%d) ...', $stackerName, intval($forceReInit)));
$this->initStack($stackerName, $forceReInit);
- } // END - foreach
+ }
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
}
/**
*
* @param $stackerName Name of the stack
* @return $isInitialized Whether the stack is initialized
+ * @throws InvalidArgumentException If a parameter is invalid
*/
- public function isStackInitialized ($stackerName) {
+ public function isStackInitialized (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ }
+
// Is is there?
$isInitialized = ($this->isValidGenericArrayKey('stacks', $stackerName, 'entries'));
// Return result
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isInitialized=%d - EXIT!', intval($isInitialized)));
return $isInitialized;
}
*
* @param $stackerName Name of the stack
* @return $isFull Whether the stack is full
- * @throws NoStackerException If given stack is missing
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If given stack is missing
*/
- protected function isStackFull ($stackerName) {
- // Is the stack not yet initialized?
- if (!$this->isStackInitialized($stackerName)) {
+ protected function isStackFull (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
- } // END - if
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
+ }
// So, is the stack full?
- $isFull = (($this->getStackCount($stackerName)) == $this->getConfigInstance()->getConfigEntry('stacker_' . $stackerName . '_max_size'));
+ $isFull = (($this->getStackCount($stackerName)) == $this->cachedMaxStackSizes[$stackerName]);
// Return result
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isFull=%d - EXIT!', intval($isFull)));
return $isFull;
}
*
* @param $stackerName Name of the stack
* @return $isEmpty Whether the stack is empty
- * @throws NoStackerException If given stack is missing
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If given stack is missing
*/
- public function isStackEmpty ($stackerName) {
- // Is the stack not yet initialized?
- if (!$this->isStackInitialized($stackerName)) {
+ public function isStackEmpty (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
- } // END - if
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
+ }
// So, is the stack empty?
$isEmpty = (($this->getStackCount($stackerName)) == 0);
// Return result
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isEmpty=%d - EXIT!', intval($isEmpty)));
return $isEmpty;
}
*
* @param $stackerName Name of the stack
* @return $count Size of stack (array count)
- * @throws NoStackerException If given stack is missing
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If given stack is missing
*/
- public function getStackCount ($stackerName) {
- // Is the stack not yet initialized?
- if (!$this->isStackInitialized($stackerName)) {
+ public function getStackCount (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
- } // END - if
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
+ }
// Now, count the array of entries
$count = $this->countGenericArrayElements('stacks', $stackerName, 'entries');
// Return result
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: count=%d - EXIT!', $count));
return $count;
}
* @param $stackerName Name of the stack
* @param $value Value to add to this stacker
* @return void
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If given stack is missing
* @throws FullStackerException Thrown if the stack is full
*/
- protected function addValue ($stackerName, $value) {
- // Is the stack not yet initialized or full?
- if (!$this->isStackInitialized($stackerName)) {
- // Then do it here
- $this->initStack($stackerName);
+ protected function addValueToStack (string $stackerName, $value) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s,value[]=%s - CALLED!', $stackerName, gettype($value)));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
+ // Throw an exception
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
} elseif ($this->isStackFull($stackerName)) {
// Stacker is full
- throw new FullStackerException(array($this, $stackerName, $value), self::EXCEPTION_STACKER_IS_FULL);
+ throw new BadMethodCallException(sprintf('stackerName=%s is full but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
}
// Now add the value to the stack
$this->pushValueToGenericArrayKey('stacks', $stackerName, 'entries', $value);
+
+ // Trace message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
}
/**
*
* @param $stackerName Name of the stack
* @return $value Value of last added value
- * @throws NoStackerException If the named stacker was not found
- * @throws EmptyStackerException If the named stacker is empty
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If the named stacker was not found
+ * @throws BadMethodCallException If the named stacker is empty
*/
- protected function getLastValue ($stackerName) {
- // Is the stack not yet initialized or full?
- if (!$this->isStackInitialized($stackerName)) {
+ protected function getLastValue (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
} elseif ($this->isStackEmpty($stackerName)) {
// Throw an exception
- throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
}
+ // Calculate last index
+ $lastIndex = $this->getStackCount($stackerName) - 1;
+
// Now get the last value
- $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', $this->getStackCount($stackerName) - 1);
+ $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', $lastIndex);
// Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
return $value;
}
*
* @param $stackerName Name of the stack
* @return $value Value of last added value
- * @throws NoStackerException If the named stacker was not found
- * @throws EmptyStackerException If the named stacker is empty
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If the named stacker was not found
+ * @throws BadMethodCallException If the named stacker is empty
*/
- protected function getFirstValue ($stackerName) {
- // Is the stack not yet initialized or full?
- if (!$this->isStackInitialized($stackerName)) {
+ protected function getFirstValue (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
} elseif ($this->isStackEmpty($stackerName)) {
// Throw an exception
- throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
}
// Now get the first value
- $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', 0);
+ $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', '0');
// Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
return $value;
}
*
* @param $stackerName Name of the stack
* @return $value Value "poped" from array
- * @throws NoStackerException If the named stacker was not found
- * @throws EmptyStackerException If the named stacker is empty
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If the named stacker was not found
+ * @throws BadMethodCallException If the named stacker is empty
*/
- protected function popLast ($stackerName) {
- // Is the stack not yet initialized or full?
- if (!$this->isStackInitialized($stackerName)) {
+ protected function popLast (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
} elseif ($this->isStackEmpty($stackerName)) {
// Throw an exception
- throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
+ throw new BadMethodCallException(sprintf('stackerName=%s is empty but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
}
// Now, remove the last entry, we don't care about the return value here, see elseif() block above
- return $this->popGenericArrayElement('stacks', $stackerName, 'entries');
+ $value = $this->popGenericArrayElement('stacks', $stackerName, 'entries');
+
+ // Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
+ return $value;
}
/**
*
* @param $stackerName Name of the stack
* @return $value Value "shifted" from array
- * @throws NoStackerException If the named stacker was not found
- * @throws EmptyStackerException If the named stacker is empty
+ * @throws InvalidArgumentException If a parameter is invalid
+ * @throws BadMethodCallException If the named stacker was not found
+ * @throws BadMethodCallException If the named stacker is empty
*/
- protected function popFirst ($stackerName) {
- // Is the stack not yet initialized or full?
- if (!$this->isStackInitialized($stackerName)) {
+ protected function popFirst (string $stackerName) {
+ // Validate parameter
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
+ if (empty($stackerName)) {
+ // No empty stack name
+ throw new InvalidArgumentException('Parameter "stackerName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif (!$this->isStackInitialized($stackerName)) {
// Throw an exception
- throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
} elseif ($this->isStackEmpty($stackerName)) {
// Throw an exception
- throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
+ throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
}
// Now, remove the last entry, we don't care about the return value here, see elseif() block above
- return $this->shiftGenericArrayElement('stacks', $stackerName, 'entries');
+ $value = $this->shiftGenericArrayElement('stacks', $stackerName, 'entries');
+
+ // Return it
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
+ return $value;
}
}