View Javadoc

1   /*
2    * @(#)MarketParser.java Aug 18, 2003
3    * 
4    * 
5    * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
6    * Delft, the Netherlands. All rights reserved.
7    * 
8    * See for project information <a href="http://www.simulation.tudelft.nl/">
9    * www.simulation.tudelft.nl </a>.
10   * 
11   * The source code and binary code of this software is proprietary information
12   * of Delft University of Technology.
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  		// turns on Schema Validation with Xerces
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  		// A utility class should not be instantiated
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 	// *********************** PRIVATE PARSING FUNCTIONS *******************//
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 		// note we switch lat / lon on purpose
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 }