8c596abb044b080973d6c51897802edf2d926dde
[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, 2009 Ship-Simu 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 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
49         // Neuen Bauvertrag generieren
50         public static final function createWorksContract ($shipType, $shipName, ContractPartner $partnerInstance) {
51                 // Strings absichern
52                 $shipType = (string) $shipType;
53                 $shipName = (string) $shipName;
54
55                 // Get new instance
56                 $contractInstance = new WorksContract();
57
58                 // Schiffsnamen setzen
59                 $contractInstance->setShipName($shipName);
60
61                 // Existiert die Klasse ueberhaupt?
62                 if (!class_exists($shipType)) {
63                         // Klasse nicht gefunden
64                         throw new NoClassException ($shipType, self::EXCEPTION_CLASS_NOT_FOUND);
65                 }
66
67                 // Schiff-Instanz temporaer erzeugen und in den Bauvertrag einfuegen
68                 $shipInstance = ObjectFactory::createObjectByName($shipType, array($shipName));
69                 $contractInstance->setShipInstance($shipInstance);
70
71                 // Remove the ship instance
72                 unset($shipInstance);
73
74                 // Set itself as contract partner
75                 $contractInstance->setContractPartner($partnerInstance);
76
77                 // Instanz zurueckgeben
78                 return $contractInstance;
79         }
80
81         // Setter for ship instance
82         private final function setShipInstance (ConstructableShip $shipInstance) {
83                 $this->shipInstance = $shipInstance;
84         }
85
86         // Setter for ship name
87         private final function setShipName ($shipName) {
88                 $this->shipName = (string) $shipName;
89         }
90
91         // Getter for ship name
92         public final function getShipName () {
93                 return $this->shipName;
94         }
95
96         // Getter for ship instance
97         public final function getShipInstance () {
98                 return $this->shipInstance;
99         }
100
101         // Add detail to the contract
102         public function addContractDetails ($shipPart, $parentPart, array $dataArray) {
103                 // Secure strings
104                 $shipPart   = (string) $shipPart;
105                 $parentPart = (string) $parentPart;
106
107                 // Debug message
108                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Das Schiffsteil <strong>%s</strong> wird zusammen mit dem Konstruktionsteil <strong>%s</strong> in den Bauvertrag aufgenommen.",
109                         __CLASS__,
110                         __LINE__,
111                         $shipPart,
112                         $parentPart
113                 ));
114
115                 // Initialize the instance (shall not be done within dynamic part)
116                 $partInstance = null;
117
118                 // Try to get an instance for this ship part
119                 try {
120                         $partInstance = ObjectFactory::createObjectByName($shipPart, $dataArray);
121                 } catch (DimNotFoundInArrayException $e) {
122                         $this->debugOutput(sprintf("[main:] Die <strong>%s</strong> konnte nicht vervollst&auml;ndigt werden. Grund: <strong>%s</strong><br />",
123                                 $this->getShipInstance()->getShipName(),
124                                 $e->getMessage()
125                         ));
126
127                         // Debug message
128                         if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Versuche ein Schiffsteil in den Bauvertrag aufzunehmen.",
129                                 __CLASS__,
130                                 __LINE__
131                         ));
132
133                         // Is this ship part constructable?
134                         if (!$partInstance instanceof ConstructableShipPart) {
135                                 // Ship part not constructable!
136                                 throw new ShipPartNotConstructableException(array($shipPart), self::EXCEPTION_NOT_CONSTRUCTABLE);
137                         } elseif ($this->getShipInstance()->createShipPart($partInstance, $parentPart) === false) {
138                                 // Schiff konnte nicht gebaut werden!
139                                 throw new ShipNotConstructedException(sprintf("Das Schiff <strong>%s</strong> konnte wegen eines Fehlers nicht gebaut werden. Siehe obere Meldungen.",
140                                         $this->getShipInstance()->getShipName()
141                                 ));
142                         }
143                 } catch (NoClassException $e) {
144                         // Throw it again...
145                         throw new NoClassException($e->getMessage(), $e->getCode());
146                 }
147
148                 // Get price for this item
149                 $price = $this->getMerchantInstance()->getPriceFromList($partInstance);
150
151                 // Add price
152                 $partInstance->setPrice($price);
153         }
154
155         // Setter for contract partner
156         public final function setContractPartner (ContractPartner $partnerInstance) {
157                 $this->contractPartner = $partnerInstance;
158         }
159
160         // Getter for contract partner
161         public final function getContractPartner () {
162                 return $this->contractPartner;
163         }
164
165         // Setter for contract party
166         public final function setContractParty (ContractPartner $partyInstance) {
167                 $this->contractParty = $partyInstance;
168         }
169
170         // Getter for contract party
171         public final function getContractParty () {
172                 return $this->contractParty;
173         }
174
175         // Setter for signature
176         public final function setSigned ($signed) {
177                 $this->signed = (boolean) $signed;
178         }
179
180         // Getter for signature
181         public function isSigned () {
182                 return $this->signed;
183         }
184
185         // Sign the contract
186         public function signContract (ContractPartner $partnerInstance, ContractPartner $partyInstance) {
187                 // Is this contract already signed?
188                 if ($this->isSigned()) {
189                         // Throw an exception
190                         throw new ContractAllreadySignedException(array($this, $this->getContractPartner(), $this->getContractParty()), self::EXCEPTION_CONTRACT_ALREADY_SIGNED);
191                 }
192
193                 // Is the first contract partner still the same?
194                 if ($partnerInstance->equals($this->getContractPartner())) {
195                         // Set contract party (other partner is already set)
196                         $this->setContractParty($partyInstance);
197
198                         // Finally sign it
199                         $this->setSigned(true);
200                 } else {
201                         // Throw an exception
202                         throw new ContractPartnerMismatchException(array($this, $this->getContractPartner(), $partyInstance), self::EXCEPTION_CONTRACT_PARTNER_MISMATCH);
203                 }
204
205                 // Debug message
206                 if ((defined('DEBUG_CONTRACT')) || (defined('DEBUG_ALL'))) {
207                         if ($partnerInstance->equals($partyInstance)) {
208                                 // With itself
209                                 $this->debugOutput(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.",
210                                         __CLASS__,
211                                         __LINE__,
212                                         $partnerInstance->getObjectDescription(),
213                                         $partnerInstance->getCompanyName(),
214                                         $this->getShipInstance()->getObjectDescription(),
215                                         $this->getShipInstance()->getShipName()
216                                 ));
217                         } else {
218                                 // Other contract party
219                                 $this->debugOutput(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.",
220                                         __CLASS__,
221                                         __LINE__,
222                                         $partnerInstance->getObjectDescription(),
223                                         $partnerInstance->getCompanyName(),
224                                         $partyInstance->getObjectDescription(),
225                                         $partyInstance->getCompanyName(),
226                                         $this->getShipInstance()->getObjectDescription(),
227                                         $this->getShipInstance()->getShipName()
228                                 ));
229                         }
230                 }
231         }
232
233         // Setter for merchant instance
234         public final function setMerchantInstance (Merchant $merchantInstance) {
235                 $this->merchantInstance = $merchantInstance;
236         }
237
238         // Getter for merchant instance
239         public final function getMerchantInstance () {
240                 return $this->merchantInstance;
241         }
242
243         // Getter for total price
244         public final function getTotalPrice () {
245                 // Get ship instance
246                 $shipInstance = $this->getShipInstance();
247
248                 // Is this a ship?
249                 if (is_null($shipInstance)) {
250                         // Opps! Empty partner instance?
251                         throw new NullPointerException($shipInstance, self::EXCEPTION_IS_NULL_POINTER);
252                 } elseif (!is_object($shipInstance)) {
253                         // Not an object! ;-(
254                         throw new InvalidObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
255                 } elseif (!$shipInstance instanceof ConstructableShip) {
256                         // Does not have the required feature (method)
257                         throw new ShipIsInvalidException(array($shipInstance), self::EXCEPTION_INVALID_SHIP_INSTANCE);
258                 }
259
260                 // Get the structure array
261                 $struct = $shipInstance->getStructuresArray();
262
263                 // Is this a ship?
264                 if (is_null($struct)) {
265                         // Opps! Empty partner instance?
266                         throw new EmptyStructuresListException($this, self::EXCEPTION_EMPTY_STRUCTURES_ARRAY);
267                 }
268
269                 // Init total price
270                 $totalPrice = 0;
271
272                 // Iterate through the list
273                 for ($iter = $struct->getIterator(); $iter->valid(); $iter->next()) {
274                         // Get item
275                         $item = $iter->current();
276
277                         // Is this a ship?
278                         if (is_null($item)) {
279                                 // Opps! Empty partner instance?
280                                 throw new NullPointerException($item, self::EXCEPTION_IS_NULL_POINTER);
281                         } elseif (!is_object($item)) {
282                                 // Not an object! ;-(
283                                 throw new InvalidObjectException($item, self::EXCEPTION_IS_NO_OBJECT);
284                         } elseif (!$item instanceof BaseSimulator) {
285                                 // Does not have the required feature (method)
286                                 throw new MissingMethodException(array($item, 'getPartInstance'), self::EXCEPTION_MISSING_METHOD);
287                         }
288
289                         // Get part instance
290                         $part = $item->getPartInstance();
291
292                         // Is this a ship?
293                         if (is_null($part)) {
294                                 // Opps! Empty partner instance?
295                                 throw new NullPointerException($part, self::EXCEPTION_IS_NULL_POINTER);
296                         } elseif (!is_object($part)) {
297                                 // Not an object! ;-(
298                                 throw new InvalidObjectException($part, self::EXCEPTION_IS_NO_OBJECT);
299                         } elseif (!method_exists($part, 'getPrice')) {
300                                 // Does not have the required feature (method)
301                                 throw new MissingMethodException(array($part, 'getPrice'), self::EXCEPTION_MISSING_METHOD);
302                         }
303
304                         // Get price for one item
305                         $price = $part->getPrice();
306
307                         // Is there numCabin() available?
308                         if (method_exists($item, 'getNumCabin')) {
309                                 // Get total cabin and multiply it with the price
310                                 $price = $price * $item->getNumCabin();
311                         }
312
313                         // Add price to total price
314                         $totalPrice += $price;
315                 }
316
317                 // Total price calculated?
318                 if ($totalPrice === 0) {
319                         // Throw exception
320                         throw new TotalPriceNotCalculatedException($this, self::EXCEPTION_TOTAL_PRICE_NOT_CALCULATED);
321                 }
322
323                 // Return total price
324                 return $totalPrice;
325         }
326 }
327
328 // [EOF]
329 ?>