1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gscg.experiment;
15
16 import java.io.IOException;
17 import java.net.URL;
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import javax.vecmath.Point3d;
22
23 import nl.tudelft.simulation.dsol.experiment.TimeUnit;
24 import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
25 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
26 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
27 import nl.tudelft.simulation.jstats.distributions.DistConstant;
28 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
29 import nl.tudelft.simulation.jstats.distributions.DistExponential;
30 import nl.tudelft.simulation.jstats.distributions.DistNormal;
31 import nl.tudelft.simulation.jstats.streams.Java2Random;
32 import nl.tudelft.simulation.jstats.streams.StreamInterface;
33 import nl.tudelft.simulation.logger.Logger;
34 import nl.tudelft.simulation.supplychain.demand.Demand;
35 import nl.tudelft.simulation.supplychain.product.Product;
36
37 import org.gscg.common.gui.images.LatLonToSmallMap;
38 import org.gscg.game.Game;
39 import org.gscg.gameactors.GameMarket;
40 import org.gscg.gameactors.GameDistributor;
41 import org.jdom.Element;
42 import org.jdom.Namespace;
43 import org.jdom.input.SAXBuilder;
44
45 /***
46 * The MarketParser parses xml-based experiments into their java objects.
47 * <p>
48 *
49 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
50 * Delft, the Netherlands. All rights reserved.
51 *
52 * See for project information <a href="http://www.simulation.tudelft.nl/">
53 * www.simulation.tudelft.nl </a>.
54 *
55 * The source code and binary code of this software is proprietary information
56 * of Delft University of Technology. *
57 *
58 * @author <a
59 * href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
60 * van Houten </a>
61 * @version $Revision: 1.3 $ $Date: 2005/08/09 15:43:40 $
62 * @since 1.0.0
63 */
64 public class MarketParser
65 {
66 /*** the stream to use */
67 private transient static StreamInterface DEFAULTSTREAM = new Java2Random();
68
69 /*** builder the xerces parser with validation turned on */
70 private static SAXBuilder builder = new SAXBuilder(
71 "org.apache.xerces.parsers.SAXParser", false);
72
73 static
74 {
75
76 builder.setFeature("http://xml.org/sax/features/validation", true);
77 builder.setFeature("http://apache.org/xml/features/validation/schema",
78 true);
79 }
80
81 /*** for debugging */
82 private transient static boolean DEBUG = false;
83
84 /***
85 * constructs a new MarketParser This is a Utility Class.
86 */
87 protected MarketParser()
88 {
89
90 }
91
92 /***
93 * parses a product xml-file.
94 *
95 * @param schema the schema for validation of the xml-file
96 * @param input the inputstream
97 * @param simulator the simulator
98 * @return Markets the markets
99 * @throws IOException whenever parsing fails
100 */
101 public static Markets parseMarkets(final String schema, final URL input,
102 final DEVSSimulatorInterface simulator) throws IOException
103 {
104 builder
105 .setProperty(
106 "http://apache.org/xml/properties/schema/external-schemaLocation",
107 "http://www.simulation.tudelft.nl " + schema);
108 try
109 {
110 Element rootElement = builder.build(input).getRootElement();
111 Markets markets = new Markets();
112
113 List elements = rootElement.getChildren();
114
115 for (int i = 0; i < elements.size(); i++)
116 {
117 GameMarket market = MarketParser.parseMarket((Element) elements
118 .get(i), simulator);
119 if (!Markets.addMarket(market))
120 {
121 Logger
122 .severe(
123 MarketParser.class,
124 "parseMarkets",
125 "MarketParser was unable to add market with name: "
126 + market.getName()
127 + ". Probably there is already a market with the same name. Check the .xml description.");
128 }
129 }
130 if (MarketParser.DEBUG)
131 {
132 System.err.println("DEBUG -- MarketParser: Number of Markets: "
133 + Markets.getMarketsArray().length);
134 }
135 return markets;
136 } catch (Exception exception)
137 {
138 exception.printStackTrace();
139 Logger.warning(MarketParser.class, "parseMarket", exception);
140 throw new IOException(exception.getMessage());
141 }
142 }
143
144
145
146 /***
147 * parses the market element
148 *
149 * @param element the xml-element
150 * @param simulator the simulator to use
151 * @return GameMarket
152 * @throws Exception on failure
153 */
154 private static GameMarket parseMarket(final Element element,
155 final DEVSSimulatorInterface simulator) throws Exception
156 {
157 String name = null;
158 String nickName = null;
159 double lat = Double.NaN;
160 double lon = Double.NaN;
161 double initialBalance = Double.NaN;
162 Product[] products = null;
163 Demand[] demands = null;
164 GameDistributor[] distributors = null;
165
166 Namespace space = element.getNamespace();
167 if (element.getChild("name", space) != null)
168 {
169 name = (element.getChildText("name", space));
170 }
171 if (element.getChild("nickname", space) != null)
172 {
173 nickName = (element.getChildText("nickname", space));
174 }
175 if (element.getChild("lat", space) != null)
176 {
177 lat = new Double(element.getChildText("lat", space)).doubleValue();
178 }
179 if (element.getChild("lon", space) != null)
180 {
181 lon = new Double(element.getChildText("lon", space)).doubleValue();
182 }
183 if (element.getChild("initial_balance", space) != null)
184 {
185 initialBalance = new Double(element.getChildText("initial_balance",
186 space)).doubleValue();
187 }
188 if (element.getChild("products", space) != null)
189 {
190 products = MarketParser.parseProduct(element.getChild("products",
191 space));
192 }
193 if (element.getChild("products", space) != null)
194 {
195 demands = MarketParser.parseDemand(element.getChild("products",
196 space), products, simulator);
197 }
198 if (element.getChild("distributors", space) != null)
199 {
200 distributors = MarketParser.parseDistributor(element.getChild(
201 "distributors", space));
202 }
203
204 if (MarketParser.DEBUG)
205 {
206 System.err
207 .println("DEBUG -- MarketParser: Finished parsing market: "
208 + name);
209 }
210
211
212 GameMarket market = new GameMarket(name, simulator, new Point3d(lon,
213 lat, 0.0), Game.getBank(), initialBalance, products, demands,
214 distributors);
215 market.setSmallMapLocation(LatLonToSmallMap.getSmallMapLocation(lon,
216 lat, 238, 176));
217 market.setLocationDescription(nickName);
218 return market;
219 }
220
221 /***
222 * Parses a element representing a list of products
223 *
224 * @param element the element to parse
225 * @return returns an array with products
226 * @throws Exception thrown in case of an unknown name
227 */
228 private static Product[] parseProduct(final Element element)
229 throws Exception
230 {
231 List products = element.getChildren();
232 List result = new ArrayList();
233 for (int i = 0; i < products.size(); i++)
234 {
235 Element product = (Element) products.get(i);
236 Namespace space = element.getNamespace();
237 String name = null;
238 if (product.getChild("product", space) != null)
239 {
240 name = (product.getChildText("product", space));
241 }
242 result.add(Products.getProduct(name));
243 }
244 return (Product[]) result.toArray(new Product[result.size()]);
245 }
246
247 /***
248 * Parses a element representing a list of demands
249 *
250 * @param element the element to parse
251 * @param products the products for the demands
252 * @param simulator the simulator
253 * @return returns an array with demands
254 * @throws Exception thrown in case of an unknown name
255 */
256 private static Demand[] parseDemand(final Element element,
257 final Product[] products, final SimulatorInterface simulator)
258 throws Exception
259 {
260 List demands = element.getChildren();
261 List result = new ArrayList();
262
263 for (int i = 0; i < demands.size(); i++)
264 {
265 Element demand = (Element) demands.get(i);
266 Namespace space = element.getNamespace();
267 Demand generatedDemand = null;
268 if (demand.getChild("demand_function", space) != null)
269 {
270
271 DistContinuous interval = MarketParser
272 .getDistContinuous(((Element) demand.getChild(
273 "demand_function").getChild("interval_in_days",
274 space).getChildren().get(0)), true, simulator,
275 false, false);
276 DistContinuous amount = MarketParser.getDistContinuous(
277 ((Element) demand.getChild("demand_function").getChild(
278 "amount", space).getChildren().get(0)), false,
279 simulator, false, false);
280 DistContinuous earliestDelivery = MarketParser
281 .getDistContinuous(((Element) demand.getChild(
282 "demand_function").getChild(
283 "earliest_delivery_date_in_days", space)
284 .getChildren().get(0)), true, simulator, false,
285 true);
286 DistContinuous latestDelivery = MarketParser.getDistContinuous(
287 ((Element) demand.getChild("demand_function").getChild(
288 "latest_delivery_date_in_days", space)
289 .getChildren().get(0)), true, simulator, true,
290 false);
291 generatedDemand = new Demand(products[i], interval, amount,
292 earliestDelivery, latestDelivery);
293 }
294 result.add(generatedDemand);
295 }
296 return (Demand[]) result.toArray(new Demand[result.size()]);
297 }
298
299 /***
300 * Method getDistContinuous returns an initialiazed dist continuous function
301 *
302 * @param element the element
303 * @param time the time
304 * @param simulator the simulator
305 * @param latest latest
306 * @param earliest earliest
307 * @return returns an initialiazed dist continuous function
308 */
309 private static DistContinuous getDistContinuous(final Element element,
310 final boolean time, final SimulatorInterface simulator,
311 final boolean latest, final boolean earliest)
312 {
313 try
314 {
315 Namespace space = element.getNamespace();
316 double day = TimeUnit
317 .convert(1.0, TimeUnitInterface.DAY, simulator);
318 if (element.getName().equalsIgnoreCase("triangular"))
319 {
320 double a = new Double(element.getAttributeValue("a", space))
321 .doubleValue();
322 double b = new Double(element.getAttributeValue("b", space))
323 .doubleValue();
324 double c = new Double(element.getAttributeValue("c", space))
325 .doubleValue();
326 if (earliest)
327 {
328 System.err
329 .println("MarketParser: adding additional 5 days to each value of earliest delivery function");
330 a += 5;
331 b += 5;
332 c += 5;
333 }
334 if (latest)
335 {
336 System.err
337 .println("MarketParser: adding additional 10 days to each value of latest delivery function");
338 a += 15;
339 b += 15;
340 c += 15;
341 }
342 if (!(a < b) && (b < c))
343 {
344 System.err.println("MarketParser: Parsing Market: a: " + a
345 + " b: " + b + " c: " + c);
346 }
347 if (time)
348 {
349 return new DistTriangularDiscrete(
350 MarketParser.DEFAULTSTREAM, a * day, b * day, c
351 * day);
352 }
353 return new DistTriangularDiscrete(MarketParser.DEFAULTSTREAM,
354 a, b, c);
355 }
356 if (element.getName().equalsIgnoreCase("normal"))
357 {
358 double mean = new Double(element.getChildText("mean", space))
359 .doubleValue();
360 double stdev = new Double(element.getChildText("stdev", space))
361 .doubleValue();
362 if (time)
363 {
364 return new DistNormal(MarketParser.DEFAULTSTREAM, mean
365 * day, stdev * day);
366 }
367 return new DistNormal(MarketParser.DEFAULTSTREAM, mean, stdev);
368 }
369 if (element.getName().equalsIgnoreCase("exponential"))
370 {
371 double lambda = new Double(element
372 .getChildText("lambda", space)).doubleValue();
373 if (time)
374 {
375 return new DistExponential(MarketParser.DEFAULTSTREAM,
376 lambda * day);
377 }
378 return new DistExponential(MarketParser.DEFAULTSTREAM, lambda);
379 }
380 if (element.getName().equalsIgnoreCase("constant"))
381 {
382 double c = new Double(element.getChildText("c", space))
383 .doubleValue();
384 if (time)
385 {
386 return new DistConstant(MarketParser.DEFAULTSTREAM, c * day);
387 }
388 return new DistConstant(MarketParser.DEFAULTSTREAM, c);
389 }
390 throw new IllegalArgumentException(
391 "getDistContinuous.. unknown argument: "
392 + element.getName());
393 } catch (Exception exception)
394 {
395 Logger.severe("MarketParser.class", "getDistConstant", exception);
396 return null;
397 }
398 }
399
400 /***
401 * Parses a element representing a list of distributors
402 *
403 * @param element the element to parse
404 * @return returns an array with products
405 * @throws Exception thrown in case of an unknown name
406 */
407 private static GameDistributor[] parseDistributor(final Element element)
408 throws Exception
409 {
410 List distributors = element.getChildren();
411 List result = new ArrayList();
412 for (int i = 0; i < distributors.size(); i++)
413 {
414 Element distributor = (Element) distributors.get(i);
415 Namespace space = element.getNamespace();
416 String name = null;
417 if (distributor.getChild("distributor", space) != null)
418 {
419 name = (distributor.getChildText("distributor", space));
420 }
421 Object actor = Distributors.getDistributor(name);
422 if (actor != null)
423 {
424 result.add(actor);
425 } else
426 {
427 System.err
428 .println("MarketParser: parseDistributor: no distributor found with name: "
429 + name);
430 }
431 }
432 return (GameDistributor[]) result.toArray(new GameDistributor[result
433 .size()]);
434 }
435 }