1
2
3
4
5
6
7
8
9
10
11
12
13 package org.gscg.gameleader.interactionlayer.util;
14
15 import java.io.Serializable;
16 import java.lang.reflect.Field;
17 import java.text.DateFormat;
18 import java.util.ArrayList;
19 import java.util.Calendar;
20 import java.util.List;
21
22 import nl.tudelft.simulation.actor.ActorInterface;
23 import nl.tudelft.simulation.dsol.experiment.TimeUnit;
24 import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
25 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
26 import nl.tudelft.simulation.language.reflection.ClassUtil;
27 import nl.tudelft.simulation.logger.Logger;
28 import nl.tudelft.simulation.supplychain.actor.SupplyChainActor;
29 import nl.tudelft.simulation.supplychain.actor.Trader;
30 import nl.tudelft.simulation.supplychain.banking.BankAccount;
31 import nl.tudelft.simulation.supplychain.content.Bill;
32 import nl.tudelft.simulation.supplychain.content.Content;
33 import nl.tudelft.simulation.supplychain.content.Order;
34 import nl.tudelft.simulation.supplychain.content.OrderBasedOnQuote;
35 import nl.tudelft.simulation.supplychain.content.OrderConfirmation;
36 import nl.tudelft.simulation.supplychain.content.Payment;
37 import nl.tudelft.simulation.supplychain.content.Quote;
38 import nl.tudelft.simulation.supplychain.content.RequestForQuote;
39 import nl.tudelft.simulation.supplychain.content.Shipment;
40 import nl.tudelft.simulation.supplychain.product.Product;
41
42 import org.gscg.gameactors.GameDistributorInteractive;
43 import org.gscg.gameleader.animation2D.mouse.IntrospectedFieldData;
44 import org.gscg.gameleader.animation2D.mouse.IntrospectionData;
45
46 /***
47 * Utility class for introspection. This class contains methods which either
48 * introspect an object and return date for the fields, or updates the values of
49 * atributes based on changes made to an object using the introspection diaglog
50 * of an animation panel.
51 * <p>
52 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
53 * Delft, the Netherlands. All rights reserved.
54 *
55 * See for project information <a href="http://www.simulation.tudelft.nl/">
56 * www.simulation.tudelft.nl </a>.
57 *
58 * The source code and binary code of this software is proprietary information
59 * of Delft University of Technology.
60 *
61 * @author <a
62 * href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
63 * van Houten </a>
64 * @version $Revision: 1.3 $ $Date: 2005/08/10 11:23:30 $
65 * @since 1.1.2
66 */
67 public final class IntrospectionUtil implements Serializable
68 {
69 /*** the serial version uid */
70 private static final long serialVersionUID = 11L;
71
72 /*** the balance field */
73 private static Field balanceField = null;
74
75 /*** the calendar */
76 private static Calendar calendar = Calendar.getInstance();
77
78 /*** the date formatter */
79 private static DateFormat dateFormat = DateFormat.getDateInstance();
80
81 /*** the start time of the simulator */
82 private static long startTime = 0L;
83
84 /*** the time unit of the simulator */
85 private static TimeUnitInterface timeUnit = null;
86
87 /*** initialize the field */
88 static
89 {
90 try
91 {
92 IntrospectionUtil.balanceField = ClassUtil.resolveField(
93 BankAccount.class, "balance");
94 balanceField.setAccessible(true);
95 } catch (Exception exception)
96 {
97 Logger.severe(IntrospectionUtil.class, "<class>", exception);
98 }
99 }
100
101 /***
102 * constructs a new IntrospectionUtil
103 */
104 private IntrospectionUtil()
105 {
106
107 super();
108 }
109
110 /***
111 * Introspects the given object
112 *
113 * @param object the object to get the data from
114 * @param key the key
115 * @return Returns an array of introspection data or null if there is no
116 * logic to process the object
117 */
118 public static IntrospectionData introspectObject(final Object object,
119 final Serializable key)
120 {
121 if (object != null)
122 {
123 List fields = new ArrayList();
124 String name = null;
125
126 if (object instanceof ActorInterface)
127 {
128 name = "Dialog for actor: "
129 + ((ActorInterface) object).getName();
130 if (GameDistributorInteractive.class.isAssignableFrom(object
131 .getClass())
132 || Trader.class.isAssignableFrom(object.getClass()))
133 {
134 IntrospectionUtil.introspectSupplyChainActor(
135 (SupplyChainActor) object, fields);
136
137
138
139
140
141 fields.add(new IntrospectedFieldData("Stock Info", "##",
142 false));
143 List products = ((Trader) object).getProductsOnStock();
144 for (int i = 0; i < products.size(); i++)
145 {
146 fields.add(new IntrospectedFieldData("Product: "
147 + ((Product) products.get(i)).getName(),
148 new Double(((Trader) object).getStock()
149 .getActualAmount(
150 (Product) products.get(i))),
151 true));
152 }
153 } else
154 {
155 IntrospectionUtil.introspectSupplyChainActor(
156 (SupplyChainActor) object, fields);
157 }
158 } else if (object instanceof Content)
159 {
160 IntrospectionUtil.introspectContent((Content) object, fields);
161 if (RequestForQuote.class.isAssignableFrom(object.getClass()))
162 {
163 name = "Dialog for Request for Quote";
164 RequestForQuote rfq = (RequestForQuote) object;
165 IntrospectionUtil.introspectRFQ(rfq, fields);
166 } else if (Quote.class.isAssignableFrom(object.getClass()))
167 {
168 name = "Dialog for Quote";
169 Quote quote = (Quote) object;
170 IntrospectionUtil.introspectRFQ(quote.getRequestForQuote(),
171 fields);
172 IntrospectionUtil.introspectQuote(quote, fields);
173 } else if (OrderBasedOnQuote.class.isAssignableFrom(object
174 .getClass()))
175 {
176 name = "Dialog for Order";
177 OrderBasedOnQuote order = (OrderBasedOnQuote) object;
178 IntrospectionUtil.introspectRFQ(order.getQuote()
179 .getRequestForQuote(), fields);
180 IntrospectionUtil.introspectQuote(order.getQuote(), fields);
181 IntrospectionUtil.introspectOrder(order, fields);
182 } else if (OrderConfirmation.class.isAssignableFrom(object
183 .getClass()))
184 {
185 name = "Dialog for Order Confirmation";
186 OrderConfirmation confirmation = (OrderConfirmation) object;
187 IntrospectionUtil.introspectRFQ(
188 ((OrderBasedOnQuote) confirmation.getOrder())
189 .getQuote().getRequestForQuote(), fields);
190 IntrospectionUtil.introspectQuote(
191 ((OrderBasedOnQuote) confirmation.getOrder())
192 .getQuote(), fields);
193 IntrospectionUtil.introspectOrder(
194 (confirmation.getOrder()), fields);
195 IntrospectionUtil.introspectOrderConfirmation(
196 (confirmation), fields);
197 } else if (Shipment.class.isAssignableFrom(object.getClass()))
198 {
199 name = "Dialog for Shipment";
200 Shipment shipment = (Shipment) object;
201 IntrospectionUtil.introspectRFQ(
202 ((OrderBasedOnQuote) shipment.getOrder())
203 .getQuote().getRequestForQuote(), fields);
204 IntrospectionUtil.introspectQuote(
205 ((OrderBasedOnQuote) shipment.getOrder())
206 .getQuote(), fields);
207 IntrospectionUtil.introspectOrder((shipment.getOrder()),
208 fields);
209 } else if (Bill.class.isAssignableFrom(object.getClass()))
210 {
211 name = "Dialog for Bill";
212 Bill bill = (Bill) object;
213 IntrospectionUtil.introspectRFQ(((OrderBasedOnQuote) bill
214 .getOrder()).getQuote().getRequestForQuote(),
215 fields);
216 IntrospectionUtil.introspectQuote(((OrderBasedOnQuote) bill
217 .getOrder()).getQuote(), fields);
218 IntrospectionUtil
219 .introspectOrder((bill.getOrder()), fields);
220 IntrospectionUtil.introspectBill(bill, fields);
221 } else if (Payment.class.isAssignableFrom(object.getClass()))
222 {
223 name = "Dialog for Payment";
224 Payment payment = (Payment) object;
225 IntrospectionUtil.introspectRFQ(
226 ((OrderBasedOnQuote) payment.getBill().getOrder())
227 .getQuote().getRequestForQuote(), fields);
228 IntrospectionUtil.introspectQuote(
229 ((OrderBasedOnQuote) payment.getBill().getOrder())
230 .getQuote(), fields);
231 IntrospectionUtil.introspectOrder((payment.getBill()
232 .getOrder()), fields);
233 IntrospectionUtil.introspectBill(payment.getBill(), fields);
234 IntrospectionUtil.introspectPayment(payment, fields);
235 }
236 } else
237 {
238 Logger.severe(IntrospectionUtil.class, "introspectObject",
239 "No logic to introspect object of class: "
240 + object.getClass());
241 return null;
242 }
243
244 return new IntrospectionData(key, (IntrospectedFieldData[]) fields
245 .toArray(new IntrospectedFieldData[fields.size()]), name);
246 }
247 return null;
248 }
249
250 /***
251 * Method updateIntrospectedObject updates an introspected object based on
252 * the given data.
253 *
254 * @param object the object to update
255 * @param data the data
256 */
257 public static void updateIntrospectedObject(final Object object,
258 final IntrospectionData data)
259 {
260 if (object != null)
261 {
262 IntrospectedFieldData[] fieldData = data.getData();
263 for (int i = 0; i < fieldData.length; i++)
264 {
265 if (fieldData[i].getName().equalsIgnoreCase("Balance"))
266 {
267
268 BankAccount account = ((SupplyChainActor) object)
269 .getBankAccount();
270 try
271 {
272 double value = ((Number) (fieldData[i].getValue()))
273 .doubleValue();
274 value = 0.01 * Math.round(100.0 * value);
275 IntrospectionUtil.balanceField.set(account, new Double(
276 value));
277 account.sendBalanceUpdateEvent();
278 } catch (Exception exception)
279 {
280 exception.printStackTrace();
281 Logger.severe(IntrospectionUtil.class,
282 "updateIntrospectedObject", exception);
283 }
284 } else if (fieldData[i].getName().startsWith("Product: "))
285 {
286 String[] split = fieldData[i].getName().split(": ");
287
288 String productName = split[1];
289
290
291 List products = ((Trader) object).getProductsOnStock();
292 for (int ii = 0; ii < products.size(); ii++)
293 {
294 Product product = (Product) products.get(ii);
295 if (product.getName().equalsIgnoreCase(productName))
296 {
297 double amount = ((Number) fieldData[i].getValue())
298 .doubleValue();
299 double currentAmount = ((Trader) object)
300 .getStock().getActualAmount(product);
301
302
303
304 if (amount != currentAmount && amount >= 0)
305 {
306 ((Trader) object).getStock().addStock(
307 product,
308 amount - currentAmount,
309 product.getUnitMarketPrice()
310 * (amount - currentAmount));
311
312 ((Trader) object).getStock()
313 .sendStockUpdateEvent(product);
314 }
315 break;
316 }
317 }
318 } else
319 {
320 Logger.warning(IntrospectionUtil.class,
321 "updateIntrospectedObject",
322 "IntrospectionUtil: unknown field"
323 + fieldData[i].getName());
324 }
325 }
326 } else
327 {
328 Logger.severe(IntrospectionUtil.class, "updateIntrospectedObject",
329 "Introspected object to update is null");
330 }
331 }
332
333
334
335
336
337 /***
338 * Introspects a supply chain actor object and adds fields to the list
339 *
340 * @param actor the actor
341 * @param fields the list with fields to edit
342 */
343 private static void introspectSupplyChainActor(
344 final SupplyChainActor actor, final List fields)
345 {
346
347 fields.add(new IntrospectedFieldData("General Info", "##", false));
348 fields.add(new IntrospectedFieldData("Name", actor.getName(), false));
349 fields.add(new IntrospectedFieldData("Location", "lat: "
350 + actor.getLocation().y + " lon: " + actor.getLocation().x,
351 false));
352 fields.add(new IntrospectedFieldData("Place", actor
353 .getLocationDescription(), false));
354
355 fields.add(new IntrospectedFieldData("Balance Info", "##", false));
356 fields.add(new IntrospectedFieldData("Balance", new Double(actor
357 .getBankAccount().getBalance()), true));
358 }
359
360 /***
361 * Introspects a content object and adds fields to the list
362 *
363 * @param content the content
364 * @param fields the list with fields to edit
365 */
366 private static void introspectContent(final Content content,
367 final List fields)
368 {
369
370 fields.add(new IntrospectedFieldData("General Info", "##", false));
371 fields.add(new IntrospectedFieldData("Sender", content.getSender()
372 .getName(), false));
373 fields.add(new IntrospectedFieldData("Sender place", content
374 .getSender().getLocationDescription(), false));
375 fields.add(new IntrospectedFieldData("Receiver", content.getReceiver()
376 .getName(), false));
377 fields.add(new IntrospectedFieldData("Receiver place", content
378 .getReceiver().getLocationDescription(), false));
379 fields.add(new IntrospectedFieldData("Product", content.getProduct()
380 .getName(), false));
381 }
382
383 /***
384 * Introspects a rfq object and adds fields to the list
385 *
386 * @param rfq the request for quote
387 * @param fields the list with fields to edit
388 */
389 private static void introspectRFQ(final RequestForQuote rfq,
390 final List fields)
391 {
392
393 fields.add(new IntrospectedFieldData("Request for Quote Info", "##",
394 false));
395 fields.add(new IntrospectedFieldData("Amount", new Double(rfq
396 .getAmount()), false));
397 fields.add(new IntrospectedFieldData("Earliest delivery date",
398 IntrospectionUtil.formatTime(rfq.getSender().getSimulator(),
399 rfq.getEarliestDeliveryDate()), false));
400 fields.add(new IntrospectedFieldData("Latest delivery date",
401 IntrospectionUtil.formatTime(rfq.getSender().getSimulator(),
402 rfq.getLatestDeliveryDate()), false));
403 }
404
405 /***
406 * Introspects a quote object and adds fields to the list
407 *
408 * @param quote the quote
409 * @param fields the list with fields to edit
410 */
411 private static void introspectQuote(final Quote quote, final List fields)
412 {
413
414 fields.add(new IntrospectedFieldData("Quote Info", "##", false));
415 fields.add(new IntrospectedFieldData("Proposed amount", new Double(
416 quote.getAmount()), false));
417 fields.add(new IntrospectedFieldData("Proposed delivery date",
418 IntrospectionUtil.formatTime(quote.getSender().getSimulator(),
419 quote.getProposedDeliveryDate()), false));
420 fields.add(new IntrospectedFieldData("Proposed price", new Double(quote
421 .getPrice()), false));
422 }
423
424 /***
425 * Introspects an order object and adds fields to the list
426 *
427 * @param order the order
428 * @param fields the list with fields to edit
429 */
430 private static void introspectOrder(final Order order, final List fields)
431 {
432
433 fields.add(new IntrospectedFieldData("Order Info", "##", false));
434 fields.add(new IntrospectedFieldData("Amount", new Double(order
435 .getAmount()), false));
436 fields.add(new IntrospectedFieldData("Delivery date", IntrospectionUtil
437 .formatTime(order.getSender().getSimulator(), order
438 .getDeliveryDate()), false));
439 }
440
441 /***
442 * Introspects an order confirmation object and adds fields to the list
443 *
444 * @param orderConfirmation the order confirmation
445 * @param fields the list with fields to edit
446 */
447 private static void introspectOrderConfirmation(
448 final OrderConfirmation orderConfirmation, final List fields)
449 {
450
451 fields.add(new IntrospectedFieldData("Order Confirmation Info", "##",
452 false));
453 fields.add(new IntrospectedFieldData("Status", orderConfirmation
454 .getStatusString(), false));
455 }
456
457 /***
458 * Introspects a bill object and adds fields to the list
459 *
460 * @param bill the bill
461 * @param fields the list with fields to edit
462 */
463 private static void introspectBill(final Bill bill, final List fields)
464 {
465
466 fields.add(new IntrospectedFieldData("Bill Info", "##", false));
467 fields.add(new IntrospectedFieldData("Price", new Double(bill
468 .getPrice()), false));
469 }
470
471 /***
472 * Introspects a payment object and adds fields to the list
473 *
474 * @param payment the payment
475 * @param fields the list with fields to edit
476 */
477 private static void introspectPayment(final Payment payment,
478 final List fields)
479 {
480
481 fields.add(new IntrospectedFieldData("Payment Info", "##", false));
482 fields.add(new IntrospectedFieldData("Price", new Double(payment
483 .getPayment()), false));
484 }
485
486 /***
487 * Method formatTime formats the given time to a String representing the
488 * date.
489 *
490 * @param simulator the simulator to use
491 * @param time the time
492 * @return returns a string representing the date
493 */
494 private static String formatTime(final SimulatorInterface simulator,
495 final double time)
496 {
497 try
498 {
499 if (IntrospectionUtil.startTime == 0L)
500 {
501 IntrospectionUtil.startTime = simulator.getReplication()
502 .getRunControl().getTreatment().getStartTime();
503 }
504
505 if (IntrospectionUtil.timeUnit == null)
506 {
507 IntrospectionUtil.timeUnit = simulator.getReplication()
508 .getRunControl().getTreatment().getTimeUnit();
509 }
510
511
512 double timeInMilliSeconds = TimeUnit.convert(time, timeUnit,
513 TimeUnitInterface.MILLISECOND);
514
515 IntrospectionUtil.calendar
516 .setTimeInMillis(IntrospectionUtil.startTime
517 + (long) timeInMilliSeconds);
518 } catch (Exception exception)
519 {
520 Logger.severe(IntrospectionUtil.class, "formatTime", exception);
521 }
522 return IntrospectionUtil.dateFormat.format(IntrospectionUtil.calendar
523 .getTime());
524 }
525 }