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