]> git.mxchange.org Git - hub.git/blob - application/hub/main/lists/class_BaseList.php
Move to generic 'core' project, because getIndexKey() is generic code
[hub.git] / application / hub / main / lists / class_BaseList.php
1 <?php
2 /**
3  * A general list class
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 Hub Developer Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24 class BaseList extends BaseHubSystem implements IteratorAggregate, Countable {
25         // Exception constants
26         const EXCEPTION_GROUP_ALREADY_ADDED = 0xf20;
27         const EXCEPTION_GROUP_NOT_FOUND     = 0xf21;
28         const EXCEPTION_INVALID_HASH        = 0xf22;
29
30         /**
31          * List groups array
32          */
33         private $listGroups = array();
34
35         /**
36          * List entries array
37          */
38         private $listEntries = array();
39
40         /**
41          * List index array
42          */
43         private $listIndex = array();
44
45         /**
46          * Protected constructor
47          *
48          * @param       $className      Name of the class
49          * @return      void
50          */
51         protected function __construct ($className) {
52                 // Call parent constructor
53                 parent::__construct($className);
54         }
55
56         /**
57          * Getter for iterator instance from this list
58          *
59          * @return      $iteratorInstance       An instance of a Iterator class
60          */
61         public function getIterator () {
62                 // Prepare a default iterator
63                 $iteratorInstance = ObjectFactory::createObjectByConfiguredName('default_iterator_class', array($this));
64
65                 // And return it
66                 return $iteratorInstance;
67         }
68
69         /**
70          * Checks wether the given group is set
71          *
72          * @param       $groupName      Group to check if found in list
73          * @return      $isset          Wether the group is valid
74          */
75         public function isGroupSet ($groupName) {
76                 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName);
77                 return isset($this->listGroups[$groupName]);
78         }
79
80         /**
81          * Adds the given group or if already added issues a ListGroupAlreadyAddedException
82          *
83          * @param       $groupName      Group to add
84          * @return      void
85          * @throws      ListGroupAlreadyAddedException  If the given group is already added
86          */
87         public function addGroup ($groupName) {
88                 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - START');
89                 // Is the group already added?
90                 if ($this->isGroupSet($groupName)) {
91                         // Throw the exception here
92                         throw new ListGroupAlreadyAddedException(array($this, $groupName), self::EXCEPTION_GROUP_ALREADY_ADDED);
93                 } // END - if
94
95                 // Add the group which is a simple array
96                 $this->listGroups[$groupName] = ObjectFactory::createObjectByConfiguredName('list_group_class');
97                 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - FINISHED');
98         }
99
100         /**
101          * Adds the given instance to list group and sub group
102          *
103          * @param       $groupName      Group to add instance to
104          * @param       $subGroup       Sub group to add instance to
105          * @param       $instance       An instance of Visitable
106          * @return      void
107          * @throws      NoListGroupException    If the given group is not found
108          */
109         public function addInstance ($groupName, $subGroup, Visitable $instance) {
110                 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName  . '/' . $subGroup . ' - START');
111                 // Is the group there?
112                 if (!$this->isGroupSet($groupName)) {
113                         // Throw the exception here
114                         throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
115                 } // END - if
116
117                 // Is the sub group there?
118                 if (!$this->listGroups[$groupName]->isGroupSet($subGroup)) {
119                         // Automatically add it
120                         $this->listGroups[$groupName]->addGroup($subGroup);
121                 } // END - if
122
123                 // Generate the hash
124                 $hash = $this->generateHash($groupName, $subGroup, $instance);
125
126                 // Now add it to the group list and hash it
127                 $this->listGroups[$groupName]->addEntry($subGroup, $hash);
128
129                 // Add the hash to the index
130                 $this->listIndex[] = $hash;
131
132                 // Add the instance itself to the list
133                 $this->listEntries[$hash] = $instance;
134                 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName  . '/' . $subGroup . ' - FINISHED');
135         }
136
137         /**
138          * Gets an array from given list
139          *
140          * @param       $list   The requested list
141          * @return      $array  The requested array
142          * @throws      NoListGroupException    If the given group is not found
143          */
144         public final function getArrayFromList ($list) {
145                 // Is the group there?
146                 if ((!is_null($list)) && (!$this->isGroupSet($list))) {
147                         // Throw the exception here
148                         throw new NoListGroupException(array($this, $list), self::EXCEPTION_GROUP_NOT_FOUND);
149                 } // END - if
150
151                 // Init array
152                 $array = array();
153
154                 // Is there another list?
155                 if (!is_null($list)) {
156                         // Then get it as well
157                         $array = $this->listGroups[$list]->getArrayFromList(null);
158                 } // END - if
159
160                 // Walk through all entries
161                 foreach ($this->listIndex as $hash) {
162                         //* DEBUG: */ print __METHOD__.':hash='.$hash."\n";
163                         // Is the list entry set?
164                         if ($this->isHashValid($hash)) {
165                                 // Add it
166                                 $array[] = $this->listEntries[$hash];
167                                 //* DEBUG: */ print __METHOD__.": ADDED!\n";
168                         } // END - if
169                 } // END - foreach
170
171                 // Return it
172                 return $array;
173         }
174
175         /**
176          * Adds the given entry to list group
177          *
178          * @param       $groupName      Group to add instance to
179          * @param       $entry          An entry of any type
180          * @return      void
181          * @throws      NoListGroupException    If the given group is not found
182          */
183         public function addEntry ($groupName, $entry) {
184                 //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - START');
185                 // Is the group already added?
186                 if (!$this->isGroupSet($groupName)) {
187                         // Throw the exception here
188                         throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
189                 } // END - if
190
191                 // Generate hash
192                 $hash = $this->generateHash($groupName, $groupName, $entry);
193                 //* DEBUG: */ $this->debugOutput(__METHOD__ . ': groupName=' . $groupName . ', entry=' . $entry . ', hash=' . $hash);
194
195                 // Add the hash to the index
196                 $this->listIndex[] = $hash;
197                 //* DEBUG: */ print $groupName.'/'.count($this->listIndex)."\n";
198
199                 // Now add the entry to the list
200                 $this->listEntries[$hash] = $entry;
201                 //* DEBUG: */ print $groupName.'/'.count($this->listEntries)."\n";
202                 //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - FINISHED');
203         }
204
205         /**
206          * Removes given entry from the list group
207          *
208          * @param       $groupName      Group where we should remove the entry from
209          * @param       $entry          The entry we should remove
210          * @return      void
211          * @throws      NoListGroupException    If the given group is not found
212          */
213         public function removeEntry ($groupName, $entry) {
214                 //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - START');
215                 // Is the group already added?
216                 if (!$this->isGroupSet($groupName)) {
217                         // Throw the exception here
218                         throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
219                 } // END - if
220
221                 // Generate hash
222                 $hash = $this->generateHash($groupName, $groupName, $entry);
223                 //* DEBUG: */ $this->debugOutput(__METHOD__ . ': groupName=' . $groupName . ', entry=' . $entry . ', hash=' . $hash);
224
225                 // Remove it from the list ...
226                 unset($this->listEntries[$hash]);
227
228                 // ... and hash list as well
229                 unset($this->listIndex[array_search($hash, $this->listIndex)]);
230                 //* DEBUG: */ $this->debugOutput(__METHOD__.'('.$this->__toString().'): '.$groupName . ' - FINISHED');
231         }
232
233         /**
234          * Generates a hash from given group, sub group and entry
235          *
236          * @param       $groupName      Group to add instance to
237          * @param       $subGroup       Sub group to add instance to
238          * @param       $entry          An entry of any type
239          * @return      $hash           The generated
240          */
241         private function generateHash ($groupName, $subGroup, $entry) {
242                 // Created entry, 'null' is default
243                 $entry2 = 'null';
244
245                 // Determine type of entry
246                 if (is_null($entry)) {
247                         // Ignore this
248                 } elseif ($entry instanceof FrameworkInterface) {
249                         // Own instance detected
250                         $entry2 = $entry->hashCode();
251                 } elseif ((is_int($entry)) || (is_float($entry)) || (is_resource($entry))) {
252                         // Integer/float/resource detected
253                         $entry2 = gettype($entry) . ':' . $entry;
254                 } elseif (is_string($entry)) {
255                         // String found
256                         $entry2 = crc32($entry) . ':' . strlen($entry);
257                 } elseif ((is_array($entry)) && (isset($entry['id']))) {
258                         // Supported array found
259                         $entry2 = crc32($entry['id']) . ':' . count($entry);
260                 } else {
261                         // Unsupported type detected
262                         $this->debugOutut(__METHOD__ . ': entry type ' . gettype($entry) . ' is unsupported.');
263
264                         // @TODO Extend this somehow?
265                         $entry2 = gettype($entry);
266                 }
267
268                 // Construct string which we shall hash
269                 $hashString = $groupName . ':' . $subGroup . ':' . $entry2;
270
271                 // Hash it with fastest hasher
272                 $hash = crc32($hashString);
273
274                 // And return it
275                 return $hash;
276         }
277
278         /**
279          * Counts all entries in this list
280          *
281          * @return      $count  All entries in this list
282          */
283         public final function count () {
284                 return count($this->listIndex);
285         }
286
287         /**
288          * Checks wether the given hash is valid
289          *
290          * @param       $hash           The hash we should validate
291          * @return      $isValid        Wether the given hash is valid
292          */
293         public final function isHashValid ($hash) {
294                 // Check it
295                 $isValid = ((in_array($hash, $this->listIndex)) && (isset($this->listEntries[$hash])));
296
297                 // Return the result
298                 return $isValid;
299         }
300
301         /**
302          * Getter for hash from given hash index
303          *
304          * @param       $hashIndex      Index holding the hash
305          * @return      $hash           The hash
306          */
307         public final function getHash ($hashIndex) {
308                 // Get it ...
309                 $hash = $this->listIndex[$hashIndex];
310
311                 // ... and return it
312                 return $hash;
313         }
314
315         /**
316          * Gets an entry from given hash index
317          *
318          * @param       $hashIndex      The hash index to resolve the mapped entry
319          * @return      $entry          Solved entry from list
320          * @throws      InvalidListHashException        If the solved hash index is invalid
321          */
322         public function getEntry ($hashIndex) {
323                 // Get the hash value
324                 $hash = $this->getHash($hashIndex);
325
326                 // Is the hash valid?
327                 if (!$this->isHashValid($hash)) {
328                         // Throw an exception here
329                         throw new InvalidListHashException(array($this, $hash, $hashIndex), self::EXCEPTION_INVALID_HASH);
330                 } // END - if
331
332                 // Now copy the entry
333                 $entry = $this->listEntries[$hash];
334
335                 // Return it
336                 return $entry;
337         }
338
339         /**
340          * Gets a full array from given group name
341          *
342          * @param       $groupName      The group name to get a list for
343          * @return      $entries        The array with all entries
344          * @throws      NoListGroupException    If the specified group is invalid
345          */
346         public function getArrayFromGroup ($groupName) {
347                 // Is the group valid?
348                 if (!$this->isGroupSet($groupName)) {
349                         // Throw the exception here
350                         throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
351                 } // END - if
352
353                 // Init the entries' array
354                 $entries = array();
355
356                 // Get an iterator
357                 $iteratorInstance = $this->listGroups[$groupName]->getIterator();
358
359                 // Go through all entries
360                 while ($iteratorInstance->valid()) {
361                         // Get key
362                         $entryIndex = $iteratorInstance->key();
363
364                         // ... and the final entry which is the stored instance
365                         $entry = $this->getEntry($entryIndex);
366
367                         // Add it to the list
368                         $entries[$iteratorInstance->current()] = $entry;
369
370                         // Skip to next one
371                         $iteratorInstance->next();
372                 } // END - while
373
374                 // Return the list
375                 return $entries;
376         }
377
378         /**
379          * Updates the given entry by hash with given array
380          *
381          * @param       $hash           Hash for this entry
382          * @param       $entryArray     Array with entry we should update
383          * @return      void
384          * @throws      InvalidListHashException        If the solved hash index is invalid
385          */
386         public function updateCurrentEntryByHash ($hash, array $entryArray) {
387                 // Is the hash valid?
388                 if (!$this->isHashValid($hash)) {
389                         // Throw an exception here, hashIndex is unknown at this point
390                         throw new InvalidListHashException(array($this, $hash, -999), self::EXCEPTION_INVALID_HASH);
391                 } // END - if
392
393                 // Set the entry
394                 $this->listEntries[$hash] = $entryArray;
395         }
396 }
397
398 //
399 ?>