More smaller fixes, factory added to ship-simu
[shipsimu.git] / application / ship-simu / main / companies / class_ShippingCompany.php
1 <?php
2 /**
3  * A shipping company may be founded with this class
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright(c) 2007, 2008 Roland Haeder, this is free software
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 ShippingCompany extends BaseSimulator implements Customer, ContractPartner {
25         /**
26          * Full name of this company
27          */
28         private $companyName     = "Namenlose Reederei";
29
30         /**
31          * Shorted name of this company
32          */
33         private $shortName       = "";
34
35         /**
36          * Instance of the founder
37          */
38         private $founderInstance = null;
39
40         /**
41          * Employed people by this company
42          */
43         private $employeeList    = null;
44
45         /**
46          * Headquarter harbor instance
47          */
48         private $hqInstance      = null;
49
50         /**
51          * List of all assigned shipyards
52          */
53         private $shipyardList   = null;
54
55         /**
56          * List of owned ships
57          */
58         private $ownedShips      = null;
59
60         /**
61          * Work constracts this company is currently working on
62          */
63         private $contractList    = null;
64
65         /**
66          * Main constructor
67          *
68          * @return      void
69          */
70         protected function __construct () {
71                 // Call parent constructor
72                 parent::__construct(__CLASS__);
73
74                 // Set description
75                 $this->setObjectDescription("Reederei");
76
77                 // Generate unique ID number
78                 $this->createUniqueID();
79
80                 // Clean up a little
81                 $this->removeSystemArray();
82         }
83
84         // Reederei gruenden (create wegen Namenskonvention)
85         public final static function createShippingCompany ($companyName, Harbor $hqInstance) {
86                 // Get new instance
87                 $companyInstance = new ShippingCompany();
88
89                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $companyInstance->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> wird gegr&uuml;ndet.<br />\n",
90                         __CLASS__,
91                         __LINE__,
92                         $companyName
93                 ));
94
95                 // Firmennamen setzen
96                 $companyInstance->setCompanyName($companyName);
97
98                 // Kuerzel setzen
99                 $companyInstance->createShortName();
100
101                 // Sitz festlegen
102                 $companyInstance->setHQInstance($hqInstance);
103
104                 // Werftenliste erstellen
105                 $companyInstance->createshipyardList();
106
107                 // Angestellten-Liste erstellen
108                 $companyInstance->createEmployeeList();
109
110                 // Auftragsliste erstellen
111                 $companyInstance->createContractList();
112
113                 // Clean up a little
114                 $companyInstance->removeWidth();
115                 $companyInstance->removeHeight();
116                 $companyInstance->removeLength();
117                 $companyInstance->removeDraught();
118                 $companyInstance->removePartInstance();
119
120                 // Instanz zurueckgeben
121                 return $companyInstance;
122         }
123
124         // Angestellten-Liste erstellen
125         private function createEmployeeList () {
126                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erh&auml;lt eine Angestelltenliste.<br />\n",
127                         __CLASS__,
128                         __LINE__,
129                         $this->getCompanyName()
130                 ));
131                 $this->employeeList = new FrameworkArrayObject();
132         }
133
134         // Werftenliste erstellen
135         public function createShipyardList () {
136                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erh&auml;lt eine Werftsliste.<br />\n",
137                         __CLASS__,
138                         __LINE__,
139                         $this->getCompanyName()
140                 ));
141                 $this->shipyardList = new FrameworkArrayObject();
142         }
143
144         // Auftragsliste erstellen
145         public function createContractList () {
146                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erh&auml;lt eine Auftragsliste.<br />\n",
147                         __CLASS__,
148                         __LINE__,
149                         $this->getCompanyName()
150                 ));
151                 $this->contractList = new FrameworkArrayObject();
152         }
153
154         // Setter-Methode fuer Firmennamen
155         public final function setCompanyName ($companyName) {
156                 $this->companyName = (string) $companyName;
157         }
158
159         // Getter-Methode fuer Firmennamen
160         public final function getCompanyName () {
161                 return $this->companyName;
162         }
163
164         // Setter-Methode fuer Firmensitz
165         public final function setHQInstance (Harbor $hqInstance) {
166                 $this->hqInstance = $hqInstance;
167         }
168
169         // Kuerzel setzen
170         private function createShortName () {
171                 // Mindestens eine Leerstelle?
172                 $dummy = explode(" ", $this->getCompanyName());
173                 foreach ($dummy as $part) {
174                         $this->shortName .= substr($part, 0, 1);
175                 }
176         }
177
178         // Reedereien Werften bauen lassen
179         public function createShipyardInHarbor($shipyardName, Harbor $harborInstance) {
180                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> baut im <strong>%s</strong> eine Werft <strong>%s</strong>.<br />\n",
181                         __CLASS__,
182                         __LINE__,
183                         $this->getCompanyName(),
184                         $harborInstance->getHarborName(),
185                         $shipyardName
186                 ));
187
188                 // Wird im HQ gebaut?
189                 if ($this->hqInstance->equals($harborInstance)) {
190                         // Die neue Werft wird im HQ gebaut!
191                         $this->hqInstance->addNewShipyardNotify($shipyardName, $this);
192                         // Die Werft drueber in Kenntnis setzen, welcher Reederei sie angehoert
193                 } else {
194                         // Ausserhalb des Heimathafens soll eine Werft gebaut werden
195                         $harborInstance->addNewShipyardNotify($shipyardName, $this);
196                 }
197         }
198
199         // Setter fuer Reederei-Gruender
200         public final function setCompanyFounder(CompanyEmployee $founderInstance) {
201                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> ist von <strong>%s %s</strong> gegr&uuml;ndet worden.<br />\n",
202                         __CLASS__,
203                         __LINE__,
204                         $this->getCompanyName(),
205                         $founderInstance->getSurname(),
206                         $founderInstance->getFamily()
207                 ));
208                 $this->founderInstance = $founderInstance;
209         }
210
211         // Getter for founder instance
212         public final function getFounderInstance () {
213                 return $this->founderInstance;
214         }
215
216         // Neue(n) Angestellte(n) in Angestellten-Liste aufnehmen
217         public function addNewEmployee (SimulatorPersonell $employeeInstance) {
218                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s %s</strong> tritt der Reederei <strong>%s</strong> als <strong>%s</strong> bei und erh&auml;lt ein Gehalt von <strong>%s</strong>.<br />\n",
219                         __CLASS__,
220                         __LINE__,
221                         $employeeInstance->getSurname(),
222                         $employeeInstance->getFamily(),
223                         $this->getCompanyName(),
224                         $employeeInstance->getObjectDescription(),
225                         $this->formatCurrency($employeeInstance->getSalary())
226                 ));
227                 $this->employeeList->append($employeeInstance);
228         }
229
230         // Neue Werft in Liste aufnehmen
231         public function addNewShipyard (Shipyard $shipyardInstance) {
232                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erh&auml;lt die Werft <strong>%s</strong> hinzugef&uuml;gt.<br />\n",
233                         __CLASS__,
234                         __LINE__,
235                         $this->getCompanyName(),
236                         $shipyardInstance->getShipyardName()
237                 ));
238                 $this->shipyardList->append($shipyardInstance);
239         }
240
241         // Neue Mitarbeiter per Zufall einstellen/rekrutieren
242         public function recruitRandomEmployees($amount, SimulatorPersonell $personellInstance) {
243                 // Anzahl Mitarbeiter absichern
244                 $amount = (int) $amount;
245
246                 // Debug-Meldung ausgeben
247                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt per Zufall <strong>%d</strong> neue Mitarbeiter ein.<br />\n",
248                         __CLASS__,
249                         __LINE__,
250                         $this->getCompanyName(),
251                         $amount
252                 ));
253
254                 // Gesamtanzahl verfuegbarer Erwerbsloser holen
255                 $totalUnemployed = $personellInstance->getAllUnemployed();
256
257                 // Existiert die gewuenschte Anzahl freier Arbeiter? (doppelt geht derzeit nicht)
258                 if ($totalUnemployed < $amount) {
259                         // Reichte nicht aus!
260                         throw new ToMuchEmployeesException(array($amount, $personellInstance->getAllUnemployed()), self::EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES);
261                 }
262
263                 // Get list for all unemployed people
264                 $list = $personellInstance->getSpecialPersonellList(false); // Should be cached
265
266                 // Get iterator of the list
267                 $iterator = $list->getIterator();
268
269                 // Get the requested amount of personell
270                 for ($idx = 0; $idx < $amount; $idx++) {
271                         $employee = null;
272                         // Is this personl unemployed?
273                         while (is_null($employee) || $employee->isEmployed()) {
274                                 // Generate random number
275                                 $pos = mt_rand(0, ($totalUnemployed - 1)); // Don't remove the -1 here:
276                                 // E.g. 100 entries means latest position is 99...
277
278                                 // Seek for the position
279                                 $iterator->seek($pos);
280
281                                 // Is the current position valid?
282                                 if ($iterator->valid()) {
283                                         // Element holen
284                                         $employee = $iterator->current();
285                                 } else {
286                                         // Should normally not happen... :(
287                                         throw new StructuresOutOfBoundsException($idx, self::EXCEPTION_INDEX_OUT_OF_BOUNDS);
288                                 }
289                         }
290
291                         // A dummy just for the description and real class
292                         $dummy = CompanyEmployee::createCompanyEmployee("", "", "M", 1970, 1, 1, $employee->isMarried(), 0);
293
294                         // Make this person employed and give him some money to work
295                         $employee->setEmployed(true);
296                         $employee->setObjectDescription($dummy->getObjectDescription());
297                         $employee->setRealClass($dummy->__toString());
298                         $employee->increaseSalary((mt_rand(7, 14) * 100)); // Are 700 to 1400 EUR for the begin okay?
299
300                         // Debug message
301                         if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt den/die Angestellte(n) <strong>%s %s</strong> ein.<br />\n",
302                                 __CLASS__,
303                                 __LINE__,
304                                 $this->getCompanyName(),
305                                 $employee->getSurname(),
306                                 $employee->getFamily()
307                         ));
308
309                         // Add this employee
310                         $this->addNewEmployee($employee);
311                 } // End - for
312
313                 // Cache resetten
314                 $personellInstance->resetCache();
315
316                 // Debug-Meldung ausgeben
317                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat per Zufall <strong>%d</strong> neue Mitarbeiter eingestellt.<br />\n",
318                         __CLASS__,
319                         __LINE__,
320                         $this->getCompanyName(),
321                         $amount
322                 ));
323         } // End - method
324
325         // Distribute all personells on all shipyards
326         public function distributeAllPersonellOnShipyards () {
327                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> verteilt alle ihre <strong>%d</strong> Mitarbeiter auf alle <strong>%d</strong> Werft(en).<br />\n",
328                         __CLASS__,
329                         __LINE__,
330                         $this->getCompanyName(),
331                         $this->getTotalEmployee(),
332                         $this->getTotalShipyards()
333                 ));
334
335                 // Do we have some shipyards?
336                 if (is_null($this->shipyardList)) {
337                         // No shipyards created
338                         throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
339                 }
340
341                 // Get iterator for shipyards
342                 $shipyardIter = $this->shipyardList->getIterator();
343
344                 // Iterate through all employees
345                 for ($idx = $this->employeeList->getIterator(); $idx->valid(); $idx->next()) {
346                         // Is the shipyard iterator still okay?
347                         if (!$shipyardIter->valid()) {
348                                 // Rewind to first position
349                                 $shipyardIter->seek(0);
350                         }
351
352                         // Get Shipyard object
353                         $shipyard = $shipyardIter->current();
354
355                         // Is this a Shipyard object?
356                         if (is_null($shipyard)) {
357                                 // No class returned
358                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
359                         } elseif (!is_object($shipyard)) {
360                                 // Not an object! ;-(
361                                 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
362                         } elseif (!$shipyard->isClass("Shipyard")) {
363                                 // Nope, so throw exception
364                                 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
365                         }
366
367                         // Add employee to the shipyard
368                         $shipyard->addNewPersonell($idx->current());
369
370                         // Continue to next shipyard
371                         $shipyardIter->next();
372                 }
373         }
374
375         // Getter for total employees
376         public final function getTotalEmployee () {
377                 // Count all...
378                 $total = $this->employeeList->count();
379
380                 // Debug message
381                 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Mitarbeiter.<br />\n",
382                         __CLASS__,
383                         __LINE__,
384                         $this->getCompanyName(),
385                         $total
386                 ));
387
388                 // Return amount
389                 return $total;
390         }
391
392         // Getter for total shipyards
393         public final function getTotalShipyards () {
394                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] F&uuml;r die Reederei <strong>%s</strong> werden die Anzahl der Werften in allen H&auml;fen ermittelt.<br />\n",
395                         __CLASS__,
396                         __LINE__,
397                         $this->getCompanyName()
398                 ));
399
400                 // Do we have some shipyards?
401                 if (is_null($this->shipyardList)) {
402                         // No shipyards created
403                         throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
404                 }
405
406                 // Get iterator
407                 $total = $this->shipyardList->count();
408
409                 // Debug message
410                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Werft(en).<br />\n",
411                         __CLASS__,
412                         __LINE__,
413                         $this->getCompanyName(),
414                         $total
415                 ));
416
417                 // Return amount
418                 return $total;
419         }
420
421         // Add a ship type (class) to all shipyards
422         public function addShipTypeToAllShipyards ($shipType) {
423                 // Secure strings
424                 $shipType = (string) $shipType;
425
426                 // Is the class there?
427                 if (!class_exists($shipType)) {
428                         // Throw exception
429                         throw new ClassNotFoundException($shipType, self::EXCEPTION_CLASS_NOT_FOUND);
430                 }
431
432                 // Create dummy ship
433                 eval(sprintf("\$shipInstance = %s::create%s(\"M/S Dummy\");",
434                         $shipType,
435                         $shipType
436                 ));
437
438                 // Debug message
439                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> baut in allen Werften bald Schiffe vom Typ <strong>%s</strong>.<br />\n",
440                         __CLASS__,
441                         __LINE__,
442                         $this->getCompanyName(),
443                         $shipInstance->getObjectDescription()
444                 ));
445
446                 // Iterate shipyard list
447                 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
448                         // Get current element
449                         $shipyard = $idx->current();
450
451                         // Is this a shipyard?
452                         if (is_null($shipyard)) {
453                                 // Opps! Empty list?
454                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
455                         } elseif (!is_object($shipyard)) {
456                                 // Not an object! ;-(
457                                 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
458                         } elseif (!$shipyard->isClass("Shipyard")) {
459                                 // Class is not a shipyard
460                                 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
461                         }
462
463                         // Add the new ship type to the shipyard
464                         $shipyard->addNewConstructableShipType($shipType);
465                 }
466         }
467
468         // Validate the requested ship type with the company if they can construct it
469         public function validateWorksContractShipType (SignableContract $contractInstance) {
470                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> pr&uuml;ft den Bauauftrag der <strong>%s</strong>.<br />\n",
471                         __CLASS__,
472                         __LINE__,
473                         $this->getCompanyName(),
474                         $contractInstance->getShipName()
475                 ));
476
477                 // First get the ship type
478                 $shipInstance = $contractInstance->getShipInstance();
479
480                 // Ist there a ship instance?
481                 if (is_null($shipInstance)) {
482                         // Opps! Empty entry?
483                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
484                 } elseif (!is_object($shipInstance)) {
485                         // Not an object! ;-(
486                         throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
487                 }
488
489                 // Get it's real class name
490                 $shipType = $shipInstance->__toString();
491
492                 // Debug message
493                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> pr&uuml;ft, ob die <strong>%s</strong> (Typ:<strong>%s</strong>) gebaut werden kann.<br />\n",
494                         __CLASS__,
495                         __LINE__,
496                         $this->getCompanyName(),
497                         $contractInstance->getShipName(),
498                         $shipInstance->getObjectDescription()
499                 ));
500
501                 // Now check if the ship type is in any list and return the result
502                 return ($this->isShipTypeConstructable($shipType));
503         }
504
505         // Is the ship type constructable?
506         public function isShipTypeConstructable ($shipType) {
507                 // The type must be a string!
508                 $shipType = (string) $shipType;
509
510                 // Debug message
511                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> fragt alle Werften ab, ob diese Schiffe vom Typ <strong>%s</strong> bauen k&ouml;nnen.<br />\n",
512                         __CLASS__,
513                         __LINE__,
514                         $this->getCompanyName(),
515                         $shipType
516                 ));
517
518                 // First everthing is failed...
519                 $result = false;
520
521                 // Iterate through all shipyards
522                 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
523                         // Get current Shipyard instance
524                         $shipyard = $idx->current();
525
526                         // Is this a shipyard?
527                         if (is_null($shipyard)) {
528                                 // Opps! Empty list?
529                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
530                         } elseif (!is_object($shipyard)) {
531                                 // Not an object! ;-(
532                                 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
533                         } elseif (!$shipyard->isClass("Shipyard")) {
534                                 // Class is not a shipyard
535                                 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
536                         }
537
538                         // Validate if the first found shipyard can construct the requested type
539                         $result = $shipyard->isShipTypeConstructable($shipType);
540
541                         // Does this shipyard construct the requested ship type?
542                         if ($result) break; // Then abort the search!
543                 }
544
545                 // Debug message
546                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat die Suche nach einer Werft beendet, die Schiffe vom Typ <strong>%s</strong> bauen kann.<br />\n",
547                         __CLASS__,
548                         __LINE__,
549                         $this->getCompanyName(),
550                         $shipType
551                 ));
552
553                 // Return result
554                 return $result;
555         }
556
557         // As a customer the shipping company can add new contracts
558         public function addNewWorksContract (SignableContract $contractInstance) {
559                 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erstellt einen Bauauftrag f&uuml;r ein <strong>%s</strong> mit dem Namen <strong>%s</strong>.<br />\n",
560                         __CLASS__,
561                         __LINE__,
562                         $this->getCompanyName(),
563                         $contractInstance->getShipInstance()->getObjectDescription(),
564                         $contractInstance->getShipInstance()->getShipName()
565                 ));
566                 $this->contractList->append($contractInstance);
567         }
568
569         // As a customer the shippng company can withdraw from a contract
570         public function withdrawFromContract (SignableContract $contractInstance) {
571                 ApplicationEntryPoint::app_die("WITHDRAW:<pre>".print_r($contractInstance, true)."</pre>");
572         }
573
574         // Get latest added contract instance
575         public final function getLastContractInstance () {
576                 // Get iterator
577                 $iter = $this->contractList->getIterator();
578
579                 // Get latest entry (total - 1)
580                 $iter->seek($iter->count() - 1);
581
582                 // Return entry
583                 return $iter->current();
584         }
585
586         // Sign a contract with an other party which must also implement Customer
587         public function signContract (SignableContract $contractInstance, ContractPartner $partnerInstance) {
588                 // Check wether the other party is our contract partner
589                 if (!$partnerInstance->isContractPartner($contractInstance)) {
590                         // Invalid contract partner!
591                         throw new InvalidContractPartnerException($partnerInstance, self::EXCEPTION_CONTRACT_PARTNER_INVALID);
592                 }
593
594                 // Determine if company "signs" own contract (must be done) or with an other party
595                 if ($this->equals($partnerInstance)) {
596                         // With itself
597                         if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erteilt an sich selbst einen Bauauftrag f&uuml;r das <strong>%s</strong> &quot;<strong>%s</strong>&quot;.<br />\n",
598                                 __CLASS__,
599                                 __LINE__,
600                                 $this->getCompanyName(),
601                                 $contractInstance->getShipInstance()->getObjectDescription(),
602                                 $contractInstance->getShipInstance()->getShipName()
603                         ));
604                 } else {
605                         // Other external company
606                         if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> unterzeichnet einen Bauauftrag f&uuml;r das <strong>%s</strong> &quot;<strong>%s</strong>&quot; mit der <strong>%s</strong>.<br />\n",
607                                 __CLASS__,
608                                 __LINE__,
609                                 $this->getCompanyName(),
610                                 $contractInstance->getShipInstance()->getObjectDescription(),
611                                 $contractInstance->getShipInstance()->getShipName(),
612                                 $partnerInstance->getCompanyName()
613                         ));
614                 }
615
616                 // Sign the contract
617                 $contractInstance->signContract($this, $partnerInstance);
618
619                 /**
620                  * @todo        Maybe do something more here...
621                  */
622         }
623
624         // Is this the right contract partner?
625         public function isContractPartner (SignableContract $contractInstance) {
626                 // Get contract partner instance and compare it with $this contract partner
627                 return ($this->equals($contractInstance->getContractPartner()));
628         }
629
630         // Setter for merchant instance
631         public final function setMerchantInstance (Merchant $merchantInstance) {
632                 // Get contract
633                 $contractInstance = $this->getLastContractInstance();
634
635                 if (is_null($contractInstance)) {
636                         // Opps! Empty contract instance?
637                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
638                 } elseif (!is_object($contractInstance)) {
639                         // Not an object! ;-(
640                         throw new NoObjectException($contractInstance, self::EXCEPTION_IS_NO_OBJECT);
641                 } elseif (!$contractInstance->isClass('WorksContract')) {
642                         // Is not a merchant
643                         throw new ClassMismatchException(array($contractInstance->__toString(), "WorksContract"), self::EXCEPTION_CLASSES_NOT_MATCHING);
644                 }
645
646                 // Set the merchant in the contract (for getting prices)
647                 $contractInstance->setMerchantInstance($merchantInstance);
648         }
649
650         /**
651          * Stub!
652          */
653         public function saveObjectToDatabase () {
654                 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
655                         $this->__toString(),
656                         __FUNCTION__
657                 ));
658         }
659
660         /**
661          * Limits this object with an ObjectLimits instance
662          */
663         public function limitObject (ObjectLimits $limitInstance) {
664                 ApplicationEntryPoint::app_die("".__METHOD__." reached! Stub!");
665         }
666 }
667
668 // [EOF]
669 ?>