80ae2eacc3a765c9f60431dd5f1f113bdda9ceda
[shipsimu.git] / application / ship-simu / main / class_WorksContract.php
1 <?php
2 /**
3  * The work constract class which can be used for contract parties
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 WorksContract extends BaseFrameworkSystem implements SignableContract {
25         // Zukuenftiger Schiffsname
26         private $shipName         = "";
27
28         // Instanz zum Schiffstypen
29         private $shipInstance     = null;
30
31         // Contract partner
32         private $contractPartner  = null;
33
34         // Other contract partner
35         private $contractParty    = null;
36
37         // Is the contract signed?
38         private $signed           = false;
39
40         // Merchant instance
41         private $merchantInstance = null;
42
43         // Konstruktor
44         protected function __construct () {
45                 // Call parent constructor
46                 parent::__construct(__CLASS__);
47
48                 // Set description
49                 $this->setObjectDescription("Bauvertrag");
50
51                 // Unique-ID generieren
52                 $this->generateUniqueId();
53
54                 // Clean up a little
55                 $this->removeSystemArray();
56         }
57
58         // Neuen Bauvertrag generieren
59         public final static function createWorksContract ($shipType, $shipName, ContractPartner $partnerInstance) {
60                 // Strings absichern
61                 $shipType = (string) $shipType;
62                 $shipName = (string) $shipName;
63
64                 // Get new instance
65                 $contractInstance = new WorksContract();
66
67                 // Debug-Meldung ausgeben
68                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $contractInstance->getDebugInstance()->output(sprintf("[%s:%d] Neuer Bauvertrag wird f&uuml;r das Schiff <strong>%s</strong> mit der <strong>%s</strong> <strong>%s</strong> erstellt.<br />\n",
69                         __CLASS__,
70                         __LINE__,
71                         $shipName,
72                         $partnerInstance->getObjectDescription(),
73                         $partnerInstance->getCompanyName()
74                 ));
75
76                 // Schiffsnamen setzen
77                 $contractInstance->setShipName($shipName);
78
79                 // Existiert die Klasse ueberhaupt?
80                 if (!class_exists($shipType)) {
81                         // Klasse nicht gefunden
82                         throw new ClassNotFoundException ($shipType, self::EXCEPTION_CLASS_NOT_FOUND);
83                 }
84
85                 // Schiff-Instanz temporaer erzeugen und in den Bauvertrag einfuegen
86                 $shipInstance = ObjectFactory::createObjectByName($shipType, array($shipName));
87                 $contractInstance->setShipInstance($shipInstance);
88
89                 // Remove the ship instance
90                 unset($shipInstance);
91
92                 // Set itself as contract partner
93                 $contractInstance->setContractPartner($partnerInstance);
94
95                 // Instanz zurueckgeben
96                 return $contractInstance;
97         }
98
99         // Setter for ship instance
100         private final function setShipInstance (ConstructableShip $shipInstance) {
101                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das Schiff <strong>%s</strong> wird in den Bauvertrag aufgenommen.<br />\n",
102                         __CLASS__,
103                         __LINE__,
104                         $shipInstance->getShipName()
105                 ));
106                 $this->shipInstance = $shipInstance;
107         }
108
109         // Setter for ship name
110         private final function setShipName ($shipName) {
111                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das neue Schiff wird <strong>%s</strong> heissen.<br />\n",
112                         __CLASS__,
113                         __LINE__,
114                         $shipName
115                 ));
116                 $this->shipName = (string) $shipName;
117         }
118
119         // Getter for ship name
120         public final function getShipName () {
121                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiffsname <strong>%s</strong> angefordert.<br />\n",
122                         __CLASS__,
123                         __LINE__,
124                         $this->shipName
125                 ));
126                 return $this->shipName;
127         }
128
129         // Getter for ship instance
130         public final function getShipInstance () {
131                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Schiff-Instanz angefordert.<br />\n",
132                         __CLASS__,
133                         __LINE__
134                 ));
135                 return $this->shipInstance;
136         }
137
138         // Add detail to the contract
139         public function addContractDetails ($shipPart, $parentPart, array $dataArray) {
140                 // Secure strings
141                 $shipPart   = (string) $shipPart;
142                 $parentPart = (string) $parentPart;
143
144                 // Debug message
145                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Das Schiffsteil <strong>%s</strong> wird zusammen mit dem Konstruktionsteil <strong>%s</strong> in den Bauvertrag aufgenommen.<br />\n",
146                         __CLASS__,
147                         __LINE__,
148                         $shipPart,
149                         $parentPart
150                 ));
151
152                 // Initialize the instance (shall not be done within dynamic part)
153                 $partInstance = null;
154
155                 // Try to get an instance for this ship part
156                 try {
157                         $partInstance = ObjectFactory::createObjectByName($shipPart, $dataArray);
158                 } catch (DimNotFoundInArrayException $e) {
159                         $this->getDebugInstance()->output(sprintf("[main:] Die <strong>%s</strong> konnte nicht vervollst&auml;ndigt werden. Grund: <strong>%s</strong><br />",
160                                 $this->getShipInstance()->getShipName(),
161                                 $e->getMessage()
162                         ));
163
164                         // Debug message
165                         if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Versuche ein Schiffsteil in den Bauvertrag aufzunehmen.<br />\n",
166                                 __CLASS__,
167                                 __LINE__
168                         ));
169
170                         // Is this ship part constructable?
171                         if (!$partInstance instanceof ConstructableShipPart) {
172                                 // Ship part not constructable!
173                                 throw new ShipPartNotConstructableException(array($shipPart), self::EXCEPTION_NOT_CONSTRUCTABLE);
174                         } elseif (!$this->getShipInstance()->createShipPart($partInstance, $parentPart)) {
175                                 // Schiff konnte nicht gebaut werden!
176                                 throw new ShipNotConstructedException(sprintf("Das Schiff <strong>%s</strong> konnte wegen eines Fehlers nicht gebaut werden. Siehe obere Meldungen.",
177                                         $this->getShipInstance()->getShipName()
178                                 ));
179                         }
180                 } catch (ClassNotFoundException $e) {
181                         // Throw it again...
182                         throw new ClassNotFoundException($e->getMessage(), $e->getCode());
183                 }
184
185                 // Get price for this item
186                 $price = $this->getMerchantInstance()->getPriceFromList($partInstance);
187
188                 // Final debug message
189                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> kostet <strong>%s</strong>.<br />\n",
190                         __CLASS__,
191                         __LINE__,
192                         $partInstance->getObjectDescription(),
193                         $this->getMerchantInstance()->formatCurrency($price)
194                 ));
195
196                 // Add price
197                 $partInstance->setPrice($price);
198
199                 // Final debug message
200                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s</strong> wurde in den Bauvertrag aufgenommen.<br />\n",
201                         __CLASS__,
202                         __LINE__,
203                         $partInstance->getObjectDescription()
204                 ));
205         }
206
207         // Setter for contract partner
208         public final function setContractPartner (ContractPartner $partnerInstance) {
209                 $this->contractPartner = $partnerInstance;
210         }
211
212         // Getter for contract partner
213         public final function getContractPartner () {
214                 return $this->contractPartner;
215         }
216
217         // Setter for contract party
218         public final function setContractParty (ContractPartner $partyInstance) {
219                 $this->contractParty = $partyInstance;
220         }
221
222         // Getter for contract party
223         public final function getContractParty () {
224                 return $this->contractParty;
225         }
226
227         // Setter for signature
228         public final function setSigned ($signed) {
229                 $this->signed = (boolean) $signed;
230         }
231
232         // Getter for signature
233         public function isSigned () {
234                 return $this->signed;
235         }
236
237         // Sign the contract
238         public function signContract (ContractPartner $partnerInstance, ContractPartner $partyInstance) {
239                 // Is this contract already signed?
240                 if ($this->isSigned()) {
241                         // Throw an exception
242                         throw new ContractAllreadySignedException(array($this, $this->getContractPartner(), $this->getContractParty()), self::EXCEPTION_CONTRACT_ALREADY_SIGNED);
243                 }
244
245                 // Is the first contract partner still the same?
246                 if ($partnerInstance->equals($this->getContractPartner())) {
247                         // Set contract party (other partner is already set)
248                         $this->setContractParty($partyInstance);
249
250                         // Finally sign it
251                         $this->setSigned(true);
252                 } else {
253                         // Throw an exception
254                         throw new ContractPartnerMismatchException(array($this, $this->getContractPartner(), $partyInstance), self::EXCEPTION_CONTRACT_PARTNER_MISMATCH);
255                 }
256
257                 // Debug message
258                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) {
259                         if ($partnerInstance->equals($partyInstance)) {
260                                 // With itself
261                                 $this->getDebugInstance()->output(sprintf("[%s:%d] Die <strong>%s</strong> <em><strong>%s</strong></em> stimmt einem Bauvertrag &uuml;ber das <strong>%s</strong> <em><strong>%s</strong></em> zu.<br />\n",
262                                         __CLASS__,
263                                         __LINE__,
264                                         $partnerInstance->getObjectDescription(),
265                                         $partnerInstance->getCompanyName(),
266                                         $this->getShipInstance()->getObjectDescription(),
267                                         $this->getShipInstance()->getShipName()
268                                 ));
269                         } else {
270                                 // Other contract party
271                                 $this->getDebugInstance()->output(sprintf("[%s:%d] Die <strong>%s</strong> <em><strong>%s</strong></em> geht mit der <strong>%s</strong> <em><strong>%s</strong></em> einen Bauvertrag &uuml;ber das <strong>%s</strong> <em><strong>%s</strong></em> ein.<br />\n",
272                                         __CLASS__,
273                                         __LINE__,
274                                         $partnerInstance->getObjectDescription(),
275                                         $partnerInstance->getCompanyName(),
276                                         $partyInstance->getObjectDescription(),
277                                         $partyInstance->getCompanyName(),
278                                         $this->getShipInstance()->getObjectDescription(),
279                                         $this->getShipInstance()->getShipName()
280                                 ));
281                         }
282                 }
283         }
284
285         // Setter for merchant instance
286         public final function setMerchantInstance (Merchant $merchantInstance) {
287                 $this->merchantInstance = $merchantInstance;
288         }
289
290         // Getter for merchant instance
291         public final function getMerchantInstance () {
292                 return $this->merchantInstance;
293         }
294
295         // Getter for total price
296         public final function getTotalPrice () {
297                 // Get ship instance
298                 $shipInstance = $this->getShipInstance();
299
300                 // Is this a ship?
301                 if (is_null($shipInstance)) {
302                         // Opps! Empty partner instance?
303                         throw new NullPointerException($shipInstance, self::EXCEPTION_IS_NULL_POINTER);
304                 } elseif (!is_object($shipInstance)) {
305                         // Not an object! ;-(
306                         throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
307                 } elseif (!$shipInstance instanceof ConstructableShip) {
308                         // Does not have the required feature (method)
309                         throw new ShipIsInvalidException(array($shipInstance), self::EXCEPTION_INVALID_SHIP_INSTANCE);
310                 }
311
312                 // Get the structure array
313                 $struct = $shipInstance->getStructuresArray();
314
315                 // Is this a ship?
316                 if (is_null($struct)) {
317                         // Opps! Empty partner instance?
318                         throw new EmptyStructuresListException($this, self::EXCEPTION_EMPTY_STRUCTURES_ARRAY);
319                 }
320
321                 // Init total price
322                 $totalPrice = 0;
323
324                 // Iterate through the list
325                 for ($iter = $struct->getIterator(); $iter->valid(); $iter->next()) {
326                         // Get item
327                         $item = $iter->current();
328
329                         // Is this a ship?
330                         if (is_null($item)) {
331                                 // Opps! Empty partner instance?
332                                 throw new NullPointerException($item, self::EXCEPTION_IS_NULL_POINTER);
333                         } elseif (!is_object($item)) {
334                                 // Not an object! ;-(
335                                 throw new NoObjectException($item, self::EXCEPTION_IS_NO_OBJECT);
336                         } elseif (!method_exists($item, 'getPartInstance')) {
337                                 // Does not have the required feature (method)
338                                 throw new MissingMethodException(array($item, 'getPartInstance'), self::EXCEPTION_MISSING_METHOD);
339                         }
340
341                         // Get part instance
342                         $part = $item->getPartInstance();
343
344                         // Is this a ship?
345                         if (is_null($part)) {
346                                 // Opps! Empty partner instance?
347                                 throw new NullPointerException($part, self::EXCEPTION_IS_NULL_POINTER);
348                         } elseif (!is_object($part)) {
349                                 // Not an object! ;-(
350                                 throw new NoObjectException($part, self::EXCEPTION_IS_NO_OBJECT);
351                         } elseif (!method_exists($part, 'getPrice')) {
352                                 // Does not have the required feature (method)
353                                 throw new MissingMethodException(array($part, 'getPrice'), self::EXCEPTION_MISSING_METHOD);
354                         }
355
356                         // Get price for one item
357                         $price = $part->getPrice();
358
359                         // Is there numCabin() available?
360                         if (method_exists($item, 'getNumCabin')) {
361                                 // Get total cabin and multiply it with the price
362                                 $price = $price * $item->getNumCabin();
363                         }
364
365                         // Add price to total price
366                         $totalPrice += $price;
367                 }
368
369                 // Total price calculated?
370                 if ($totalPrice === 0) {
371                         // Throw exception
372                         throw new TotalPriceNotCalculatedException($this, self::EXCEPTION_TOTAL_PRICE_NOT_CALCULATED);
373                 }
374
375                 // Return total price
376                 return $totalPrice;
377         }
378 }
379
380 // [EOF]
381 ?>