]> git.mxchange.org Git - core.git/blob - framework/main/classes/stacker/class_BaseStacker.php
Continued:
[core.git] / framework / main / classes / stacker / class_BaseStacker.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Stack;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
8
9 // Import SPL stuff
10 use \BadMethodCallException;
11 use \InvalidArgumentException;
12
13 /**
14  * A general Stacker
15  *
16  * @author              Roland Haeder <webmaster@shipsimu.org>
17  * @version             0.0.0
18  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
19  * @license             GNU GPL 3.0 or any newer version
20  * @link                http://www.shipsimu.org
21  *
22  * This program is free software: you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation, either version 3 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
34  */
35 abstract class BaseStacker extends BaseFrameworkSystem {
36         // Exception codes
37         const EXCEPTION_STACKER_ALREADY_INITIALIZED = 0x050;
38         const EXCEPTION_STACKER_IS_FULL             = 0x051;
39         const EXCEPTION_NO_STACKER_FOUND            = 0x052;
40         const EXCEPTION_STACKER_IS_EMPTY            = 0x053;
41
42         /**
43          * Protected constructor
44          *
45          * @param       $className      Name of the class
46          * @return      void
47          */
48         protected function __construct (string $className) {
49                 // Call parent constructor
50                 parent::__construct($className);
51         }
52
53         /**
54          * Initializes given stacker
55          *
56          * @param       $stackerName    Name of the stack
57          * @param       $forceReInit    Force re-initialization
58          * @return      void
59          * @throws      InvalidArgumentException        If a parameter is invalid
60          * @throws      AlreadyInitializedStackerException      If the stack is already initialized
61          */
62         public function initStack (string $stackerName, bool $forceReInit = false) {
63                 // Validate parameter
64                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s,forceReInit=%d - CALLED!', $stackerName, intval($forceReInit)));
65                 if (empty($stackerName)) {
66                         // No empty stack name
67                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
68                 } elseif (($forceReInit === false) && ($this->isStackInitialized($stackerName))) {
69                         // Then throw the exception
70                         // @TODO Change to BMCE
71                         throw new AlreadyInitializedStackerException(array($this, $stackerName, $forceReInit), self::EXCEPTION_STACKER_ALREADY_INITIALIZED);
72                 }
73
74                 // Initialize the given stack
75                 $this->initGenericArrayKey('stacks', $stackerName, 'entries', $forceReInit);
76
77                 // Trace message
78                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
79         }
80
81         /**
82          * Initializes all stacks
83          *
84          * @return      void
85          * @throws      InvalidArgumentException        If a parameter is invalid
86          */
87         public function initStacks (array $stacks, bool $forceReInit = false) {
88                 // Validate parameter
89                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stacks()=%d,forceReInit=%d - CALLED!', count($stacks), intval($forceReInit)));
90                 if (count($stacks) == 0) {
91                         // No empty stack name
92                         throw new InvalidArgumentException('Array "stacks" is empty');
93                 }
94
95                 // "Walk" through all (more will be added as needed
96                 foreach ($stacks as $stackerName) {
97                         // Init this stack
98                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: Calling this->initStack(%s,%d) ...', $stackerName, intval($forceReInit)));
99                         $this->initStack($stackerName, $forceReInit);
100                 }
101
102                 // Trace message
103                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
104         }
105
106         /**
107          * Checks whether the given stack is initialized (set in array $stackers)
108          *
109          * @param       $stackerName    Name of the stack
110          * @return      $isInitialized  Whether the stack is initialized
111          * @throws      InvalidArgumentException        If a parameter is invalid
112          */
113         public function isStackInitialized (string $stackerName) {
114                 // Validate parameter
115                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
116                 if (empty($stackerName)) {
117                         // No empty stack name
118                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
119                 }
120
121                 // Is is there?
122                 $isInitialized = ($this->isValidGenericArrayKey('stacks', $stackerName, 'entries'));
123
124                 // Return result
125                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isInitialized=%d - EXIT!', intval($isInitialized)));
126                 return $isInitialized;
127         }
128
129         /**
130          * Checks whether the given stack is full
131          *
132          * @param       $stackerName    Name of the stack
133          * @return      $isFull                 Whether the stack is full
134          * @throws      InvalidArgumentException        If a parameter is invalid
135          * @throws      BadMethodCallException  If given stack is missing
136          */
137         protected function isStackFull (string $stackerName) {
138                 // Validate parameter
139                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
140                 if (empty($stackerName)) {
141                         // No empty stack name
142                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
143                 } elseif (!$this->isStackInitialized($stackerName)) {
144                         // Throw an exception
145                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
146                 }
147
148                 // So, is the stack full?
149                 $isFull = (($this->getStackCount($stackerName)) == FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('stacker_' . $stackerName . '_max_size'));
150
151                 // Return result
152                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isFull=%d - EXIT!', intval($isFull)));
153                 return $isFull;
154         }
155
156         /**
157          * Checks whether the given stack is empty
158          *
159          * @param       $stackerName            Name of the stack
160          * @return      $isEmpty                        Whether the stack is empty
161          * @throws      InvalidArgumentException        If a parameter is invalid
162          * @throws      BadMethodCallException  If given stack is missing
163          */
164         public function isStackEmpty (string $stackerName) {
165                 // Validate parameter
166                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
167                 if (empty($stackerName)) {
168                         // No empty stack name
169                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
170                 } elseif (!$this->isStackInitialized($stackerName)) {
171                         // Throw an exception
172                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
173                 }
174
175                 // So, is the stack empty?
176                 $isEmpty = (($this->getStackCount($stackerName)) == 0);
177
178                 // Return result
179                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: isEmpty=%d - EXIT!', intval($isEmpty)));
180                 return $isEmpty;
181         }
182
183         /**
184          * Getter for size of given stack (array count)
185          *
186          * @param       $stackerName    Name of the stack
187          * @return      $count                  Size of stack (array count)
188          * @throws      InvalidArgumentException        If a parameter is invalid
189          * @throws      BadMethodCallException  If given stack is missing
190          */
191         public function getStackCount (string $stackerName) {
192                 // Validate parameter
193                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
194                 if (empty($stackerName)) {
195                         // No empty stack name
196                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
197                 } elseif (!$this->isStackInitialized($stackerName)) {
198                         // Throw an exception
199                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
200                 }
201
202                 // Now, count the array of entries
203                 $count = $this->countGenericArrayElements('stacks', $stackerName, 'entries');
204
205                 // Return result
206                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: count=%d - EXIT!', $count));
207                 return $count;
208         }
209
210         /**
211          * Adds a value to given stack
212          *
213          * @param       $stackerName    Name of the stack
214          * @param       $value                  Value to add to this stacker
215          * @return      void
216          * @throws      InvalidArgumentException        If a parameter is invalid
217          * @throws      BadMethodCallException  If given stack is missing
218          * @throws      FullStackerException    Thrown if the stack is full
219          */
220         protected function addValue (string $stackerName, $value) {
221                 // Validate parameter
222                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s,value[]=%s - CALLED!', $stackerName, gettype($value)));
223                 if (empty($stackerName)) {
224                         // No empty stack name
225                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
226                 } elseif (!$this->isStackInitialized($stackerName)) {
227                         // Throw an exception
228                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
229                 } elseif ($this->isStackFull($stackerName)) {
230                         // Stacker is full
231                         throw new FullStackerException([$this, $stackerName, $value], self::EXCEPTION_STACKER_IS_FULL);
232                 }
233
234                 // Now add the value to the stack
235                 $this->pushValueToGenericArrayKey('stacks', $stackerName, 'entries', $value);
236
237                 // Trace message
238                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-STACKER: EXIT!');
239         }
240
241         /**
242          * Get last value from named stacker
243          *
244          * @param       $stackerName    Name of the stack
245          * @return      $value                  Value of last added value
246          * @throws      InvalidArgumentException        If a parameter is invalid
247          * @throws      BadMethodCallException  If the named stacker was not found
248          * @throws      BadMethodCallException  If the named stacker is empty
249          */
250         protected function getLastValue (string $stackerName) {
251                 // Validate parameter
252                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
253                 if (empty($stackerName)) {
254                         // No empty stack name
255                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
256                 } elseif (!$this->isStackInitialized($stackerName)) {
257                         // Throw an exception
258                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
259                 } elseif ($this->isStackEmpty($stackerName)) {
260                         // Throw an exception
261                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
262                 }
263
264                 // Now get the last value
265                 $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', $this->getStackCount($stackerName) - 1);
266
267                 // Return it
268                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
269                 return $value;
270         }
271
272         /**
273          * Get first value from named stacker
274          *
275          * @param       $stackerName    Name of the stack
276          * @return      $value                  Value of last added value
277          * @throws      InvalidArgumentException        If a parameter is invalid
278          * @throws      BadMethodCallException  If the named stacker was not found
279          * @throws      BadMethodCallException  If the named stacker is empty
280          */
281         protected function getFirstValue (string $stackerName) {
282                 // Validate parameter
283                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
284                 if (empty($stackerName)) {
285                         // No empty stack name
286                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
287                 } elseif (!$this->isStackInitialized($stackerName)) {
288                         // Throw an exception
289                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
290                 } elseif ($this->isStackEmpty($stackerName)) {
291                         // Throw an exception
292                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
293                 }
294
295                 // Now get the first value
296                 $value = $this->getGenericArrayElement('stacks', $stackerName, 'entries', 0);
297
298                 // Return it
299                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
300                 return $value;
301         }
302
303         /**
304          * "Pops" last entry from stack
305          *
306          * @param       $stackerName    Name of the stack
307          * @return      $value                  Value "poped" from array
308          * @throws      InvalidArgumentException        If a parameter is invalid
309          * @throws      BadMethodCallException  If the named stacker was not found
310          * @throws      BadMethodCallException  If the named stacker is empty
311          */
312         protected function popLast (string $stackerName) {
313                 // Validate parameter
314                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
315                 if (empty($stackerName)) {
316                         // No empty stack name
317                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
318                 } elseif (!$this->isStackInitialized($stackerName)) {
319                         // Throw an exception
320                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
321                 } elseif ($this->isStackEmpty($stackerName)) {
322                         // Throw an exception
323                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
324                 }
325
326                 // Now, remove the last entry, we don't care about the return value here, see elseif() block above
327                 $value = $this->popGenericArrayElement('stacks', $stackerName, 'entries');
328
329                 // Return it
330                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
331                 return $value;
332         }
333
334         /**
335          * "Pops" first entry from stack
336          *
337          * @param       $stackerName    Name of the stack
338          * @return      $value                  Value "shifted" from array
339          * @throws      InvalidArgumentException        If a parameter is invalid
340          * @throws      BadMethodCallException  If the named stacker was not found
341          * @throws      BadMethodCallException  If the named stacker is empty
342          */
343         protected function popFirst (string $stackerName) {
344                 // Validate parameter
345                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: stackerName=%s - CALLED!', $stackerName));
346                 if (empty($stackerName)) {
347                         // No empty stack name
348                         throw new InvalidArgumentException('Parameter "stackerName" is empty');
349                 } elseif (!$this->isStackInitialized($stackerName)) {
350                         // Throw an exception
351                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
352                 } elseif ($this->isStackEmpty($stackerName)) {
353                         // Throw an exception
354                         throw new BadMethodCallException(sprintf('stackerName=%s not yet initialized but method called.', $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
355                 }
356
357                 // Now, remove the last entry, we don't care about the return value here, see elseif() block above
358                 $value = $this->shiftGenericArrayElement('stacks', $stackerName, 'entries');
359
360                 // Return it
361                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-STACKER: value[]=%s - EXIT!', gettype($value)));
362                 return $value;
363         }
364
365 }