5 * @author Roland Haeder <webmaster@ship-simu.org>
7 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 Hub Developer Team
8 * @license GNU GPL 3.0 or any newer version
9 * @link http://www.ship-simu.org
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.
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.
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/>.
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;
33 private $listGroups = array();
38 private $listEntries = array();
43 private $listIndex = array();
46 * Protected constructor
48 * @param $className Name of the class
51 protected function __construct ($className) {
52 // Call parent constructor
53 parent::__construct($className);
55 // Remove some attributes
56 $this->removeNumberFormaters();
57 $this->removeSystemArray();
61 * Getter for iterator instance from this list
63 * @return $iteratorInstance An instance of a Iterator class
65 public function getIterator () {
66 // Prepare a default iterator
67 $iteratorInstance = ObjectFactory::createObjectByConfiguredName('default_iterator_class');
70 return $iteratorInstance;
74 * Checks wether the given group is set
76 * @param $groupName Group to check if found in list
77 * @return $isset Wether the group is valid
79 public function isGroupSet ($groupName) {
80 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName);
81 return isset($this->listGroups[$groupName]);
85 * Adds the given group or if already added issues a ListGroupAlreadyAddedException
87 * @param $groupName Group to add
89 * @throws ListGroupAlreadyAddedException If the given group is already added
91 public function addGroup ($groupName) {
92 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - START');
93 // Is the group already added?
94 if ($this->isGroupSet($groupName)) {
95 // Throw the exception here
96 throw new ListGroupAlreadyAddedException(array($this, $groupName), self::EXCEPTION_GROUP_ALREADY_ADDED);
99 // Add the group which is a simple array
100 $this->listGroups[$groupName] = ObjectFactory::createObjectByConfiguredName('list_group_class');
101 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - FINISHED');
105 * Adds the given instance to list group and sub group
107 * @param $groupName Group to add instance to
108 * @param $subGroup Sub group to add instance to
109 * @param $instance An instance of Visitable
111 * @throws NoListGroupException If the given group is not found
113 public function addInstance ($groupName, $subGroup, Visitable $instance) {
114 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . '/' . $subGroup . ' - START');
115 // Is the group there?
116 if (!$this->isGroupSet($groupName)) {
117 // Throw the exception here
118 throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
121 // Is the sub group there?
122 if (!$this->listGroups[$groupName]->isGroupSet($subGroup)) {
123 // Automatically add it
124 $this->listGroups[$groupName]->addGroup($subGroup);
128 $hash = $this->generateHash($groupName, $subGroup, $instance);
130 // Now add it to the group list and hash it
131 $this->listGroups[$groupName]->addEntry($subGroup, $hash);
133 // Add the hash to the index
134 $this->listIndex[] = $hash;
136 // Add the instance itself to the list
137 $this->listEntries[$hash] = $instance;
138 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . '/' . $subGroup . ' - START');
142 * Adds the given entry to list group
144 * @param $groupName Group to add instance to
145 * @param $entry An entry of any type
147 * @throws NoListGroupException If the given group is not found
149 public function addEntry ($groupName, $entry) {
150 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - START');
151 // Is the group already added?
152 if (!$this->isGroupSet($groupName)) {
153 // Throw the exception here
154 throw new NoListGroupException(array($this, $groupName), self::EXCEPTION_GROUP_NOT_FOUND);
158 $hash = $this->generateHash($groupName, $groupName, $entry);
160 // Add the hash to the index
161 $this->listIndex[] = $hash;
163 // Now add the entry to the list
164 $this->listEntries[$hash] = $entry;
165 //* DEBUG: */ $this->debugOutput(__METHOD__.': '.$groupName . ' - FINISHED');
169 * Generates a hash from given group, sub group and entry
171 * @param $groupName Group to add instance to
172 * @param $subGroup Sub group to add instance to
173 * @param $entry An entry of any type
174 * @return $hash The generated
176 private function generateHash ($groupName, $subGroup, $entry) {
177 // Created entry, 'null' is default
180 // Determine type of entry
181 if (is_null($entry)) {
183 } elseif ($entry instanceof FrameworkInterface) {
184 // Own instance detected
185 $entry2 = $entry->hashCode();
186 } elseif ((is_int($entry)) || (is_float($entry)) || (is_resource($entry))) {
187 // Integer/float/resource detected
188 $entry2 = gettype($entry) . ':' . $entry;
189 } elseif (is_string($entry)) {
191 $entry2 = crc32($entry) . ':' . strlen($entry);
193 // Unsupported type detected
194 $this->debugOutut(__METHOD__ . ': entry type ' . gettype($entry) . ' is unsupported.');
196 // @TODO Extend this somehow?
197 $entry2 = gettype($entry);
200 // Construct string which we shall hash
201 $hashString = $groupName . ':' . $subGroup . ':' . $entry2;
203 // Hash it with fastest hasher
204 $hash = crc32($hashString);
211 * Counts all entries in this list
213 * @return $count All entries in this list
215 public final function count () {
216 return count($this->listIndex);
220 * Checks wether the given hash is valid
222 * @param $hash The hash we should validate
223 * @return $isValid Wether the given hash is valid
225 public final function isHashValid ($hash) {
227 $isValid = ((in_array($hash, $this->listIndex)) && (isset($this->listEntries[$hash])));
234 * Gets an entry from given hash index
236 * @param $hashIndex The hash index to resolve the mapped entry
237 * @return $entry Solved entry from list
238 * @throws InvalidListHashException If the solved hash index is invalid
240 public function getEntry ($hashIndex) {
241 // Get the hash value
242 $hash = $this->listIndex[$hashIndex];
244 // Is the hash valid?
245 if (!$this->isHashValid($hash)) {
246 // Throw an exception here
247 throw new InvalidListHashException(array($this, $hash, $hashIndex), self::EXCEPTION_INVALID_HASH);
250 // Now copy the entry
251 $entry = $this->listEntries[$hash];