View Javadoc

1   /*
2    * @(#)ScenarioParser.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.scenario;
15  
16  import java.io.IOException;
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.Calendar;
20  import java.util.Iterator;
21  import java.util.List;
22  
23  import nl.tudelft.simulation.logger.Logger;
24  import nl.tudelft.simulation.supplychain.product.Product;
25  
26  import org.gscg.common.interactionlayer.messaging.ScenarioText;
27  import org.gscg.experiment.Markets;
28  import org.gscg.experiment.Products;
29  import org.jdom.Element;
30  import org.jdom.Namespace;
31  import org.jdom.input.SAXBuilder;
32  
33  /***
34   * The ScenarioParser parses xml-based scenarios into a sequence of events.
35   * <p>
36   * 
37   * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
38   * Delft, the Netherlands. All rights reserved.
39   * 
40   * See for project information <a href="http://www.simulation.tudelft.nl/">
41   * www.simulation.tudelft.nl </a>.
42   * 
43   * The source code and binary code of this software is proprietary information
44   * of Delft University of Technology.
45   * 
46   * @author <a
47   *         href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
48   *         van Houten </a>
49   * @version $Revision: 1.1 $ $Date: 2005/06/16 12:34:01 $
50   * @since 1.0.0
51   */
52  public class ScenarioParser
53  {
54  	/*** builder the xerces parser with validation turned on */
55  	private static SAXBuilder builder = new SAXBuilder(
56  			"org.apache.xerces.parsers.SAXParser", false);
57  	static
58  	{
59  		// turns on Schema Validation with Xerces
60  		builder.setFeature("http://xml.org/sax/features/validation", true);
61  		builder.setFeature("http://apache.org/xml/features/validation/schema",
62  				true);
63  	}
64  
65  	/*** for debugging */
66  	private static final boolean DEBUG = false;
67  
68  	/***
69  	 * constructs a new ExperimentParser This is a Utility Class.
70  	 */
71  	protected ScenarioParser()
72  	{
73  		// A utility class should not be instantiated
74  	}
75  
76  	/***
77  	 * parses a scenario xml-file.
78  	 * 
79  	 * @param schema the schema for validation of the xml-file
80  	 * @param input the inputstream
81  	 * @return Scenario the experiment
82  	 * @throws IOException whenever parsing fails
83  	 */
84  	public static Scenario parseScenario(final String schema, final URL input)
85  			throws IOException
86  	{
87  		builder
88  				.setProperty(
89  						"http://apache.org/xml/properties/schema/external-schemaLocation",
90  						"http://www.simulation.tudelft.nl " + schema);
91  		try
92  		{
93  			Element rootElement = builder.build(input).getRootElement();
94  			Scenario scenario = new Scenario();
95  			if (rootElement.getChild("name") != null)
96  			{
97  				scenario.setProperty(Scenario.SCENARIO_NAME, rootElement
98  						.getChildText("name"));
99  			}
100 			if (rootElement.getChild("analyst") != null)
101 			{
102 				scenario.setProperty(Scenario.SCENARIO_ANALYST, rootElement
103 						.getChildText("analyst"));
104 			}
105 			scenario.setUrl(input);
106 
107 			List eventList = rootElement.getChildren("event");
108 			ArrayList eventArray = new ArrayList();
109 			for (Iterator i = eventList.iterator(); i.hasNext();)
110 			{
111 				Event event = ScenarioParser.parseEvent((Element) i.next());
112 				eventArray.add(event);
113 			}
114 			Event[] event = new Event[eventArray.size()];
115 			scenario.setActions((Event[]) eventArray.toArray(event));
116 			return scenario;
117 		} catch (Exception exception)
118 		{
119 			Logger.warning(ScenarioParser.class, "parseScenario", exception);
120 			throw new IOException(exception.getMessage());
121 		}
122 	}
123 
124 	// *********************** PRIVATE PARSING FUNCTIONS *******************//
125 
126 	/***
127 	 * parses the dateTime
128 	 * 
129 	 * @param value the string value in the yyyy-mm-ddThh:mm:ss format
130 	 * @return long the amount of milliseconds since 1970.
131 	 */
132 	private static long parseDateTime(final String value)
133 	{
134 		Calendar calendar = Calendar.getInstance();
135 		String concatDate = value.split("T")[0];
136 		String concatTime = value.split("T")[1];
137 		String[] date = concatDate.split("-");
138 		String[] time = concatTime.split(":");
139 		calendar.set(new Integer(date[0]).intValue(), new Integer(date[1])
140 				.intValue() - 1, new Integer(date[2]).intValue(), new Integer(
141 				time[0]).intValue(), new Integer(time[1]).intValue(),
142 				new Integer(time[2]).intValue());
143 		return calendar.getTimeInMillis();
144 	}
145 
146 	/***
147 	 * parses the event
148 	 * 
149 	 * @param element the xml-element
150 	 * @return Event
151 	 * @throws Exception on failure
152 	 */
153 	private static Event parseEvent(final Element element) throws Exception
154 	{
155 		Event event = null;
156 		long startTime = 0L;
157 		if (element.getChild("startTime") != null)
158 		{
159 			startTime = ScenarioParser.parseDateTime(element
160 					.getChildText("startTime"));
161 		}
162 		// make a selection based on an actor basis
163 		Namespace space = element.getNamespace();
164 		if (element.getChild("manufacturerEvent", space) != null)
165 		{
166 			event = ScenarioParser.parseManufacturerEvent(element.getChild(
167 					"manufacturerEvent", space));
168 		} else if (element.getChild("distributorEvent", space) != null)
169 		{
170 			event = ScenarioParser.parseDistributorEvent(element.getChild(
171 					"distributorEvent", space));
172 		} else if (element.getChild("marketEvent", space) != null)
173 		{
174 			event = ScenarioParser.parseMarketEvent(element.getChild(
175 					"marketEvent", space), startTime);
176 		} else if (element.getChild("priceEvent", space) != null)
177 		{
178 			event = ScenarioParser.parsePriceEvent(element.getChild(
179 					"priceEvent", space), startTime);
180 		} else if (element.getChild("largeNewsMessageEvent", space) != null)
181 		{
182 			event = ScenarioParser.parseLargeNewsMessageEvent(element,
183 					startTime);
184 		} else
185 		{
186 			throw new IllegalArgumentException(
187 					"Unknown event type in scenario xml.");
188 		}
189 		return event;
190 	}
191 
192 	/***
193 	 * Method parseManufacturerEvent
194 	 * 
195 	 * @param element the element to get the data from
196 	 * @return Return an event
197 	 */
198 	private static Event parseManufacturerEvent(final Element element)
199 	{
200 		return null;
201 	}
202 
203 	/***
204 	 * Method parseDistributorEvent
205 	 * 
206 	 * @param element the element to get the data from
207 	 * @return Return an event
208 	 */
209 	private static Event parseDistributorEvent(final Element element)
210 	{
211 		return null;
212 	}
213 
214 	/***
215 	 * Method parsePriceEvent
216 	 * 
217 	 * @param element the element to get the data from
218 	 * @param startTime the start time of the event
219 	 * @return Returns an event
220 	 */
221 	private static Event parsePriceEvent(final Element element,
222 			final long startTime)
223 	{
224 		String methodName = null;
225 		Object[] args = new Object[]{};
226 		Product product = null;
227 		Namespace space = element.getNamespace();
228 		if (element.getChild("changeMarketPrice", space) != null)
229 		{
230 			Element changePriceElement = element.getChild("changeMarketPrice",
231 					space);
232 			methodName = "changePrice";
233 			Boolean bool = null;
234 			Double percentage = null;
235 			if (changePriceElement.getChild("product", space) != null)
236 			{
237 				String productName = changePriceElement.getChildText("product",
238 						space);
239 				product = Products.getProduct(productName);
240 			}
241 			if (changePriceElement.getChild("increase", space) != null)
242 			{
243 				if (changePriceElement.getChildText("increase", space)
244 						.equalsIgnoreCase("true"))
245 				{
246 					bool = new Boolean(true);
247 				} else
248 				{
249 					bool = new Boolean(false);
250 				}
251 			}
252 			if (changePriceElement.getChild("percentage", space) != null)
253 			{
254 				percentage = new Double(changePriceElement.getChildText(
255 						"percentage", space));
256 			}
257 			args = new Object[]{bool, percentage};
258 		}
259 		if (ScenarioParser.DEBUG)
260 		{
261 			System.out
262 					.println("ScenarioParser: scheduling price event for product: "
263 							+ product);
264 		}
265 		return new Event(product, startTime, methodName, args);
266 	}
267 
268 	/***
269 	 * Method parseMarketEvent
270 	 * 
271 	 * @param element the element to get the data from
272 	 * @param startTime the start time of the event
273 	 * @return Returns an event
274 	 */
275 	private static Event parseMarketEvent(final Element element,
276 			final long startTime)
277 	{
278 		String actorName = null;
279 		String methodName = null;
280 		Object[] args = new Object[]{};
281 		Namespace space = element.getNamespace();
282 		if (element.getChild("market", space) != null)
283 		{
284 			actorName = element.getChildText("market", space);
285 		}
286 		if (element.getChild("changeDemand", space) != null)
287 		{
288 			Element changeDemandElement = element.getChild("changeDemand",
289 					space);
290 			methodName = "changeDemand";
291 			Product product = null;
292 			Boolean bool = null;
293 			Double percentage = null;
294 			if (changeDemandElement.getChild("product", space) != null)
295 			{
296 				String productName = changeDemandElement.getChildText(
297 						"product", space);
298 				product = Products.getProduct(productName);
299 			}
300 			if (changeDemandElement.getChild("increase", space) != null)
301 			{
302 				if (changeDemandElement.getChildText("increase", space)
303 						.equalsIgnoreCase("true"))
304 				{
305 					bool = new Boolean(true);
306 				} else
307 				{
308 					bool = new Boolean(false);
309 				}
310 			}
311 			if (changeDemandElement.getChild("percentage", space) != null)
312 			{
313 				percentage = new Double(changeDemandElement.getChildText(
314 						"percentage", space));
315 			}
316 			args = new Object[]{product, bool, percentage};
317 		}
318 		if (ScenarioParser.DEBUG)
319 		{
320 			System.out
321 					.println("ScenarioParser: scheduling market events for market: "
322 							+ actorName);
323 		}
324 		if (actorName == null)
325 		{
326 			System.err.println("ScenarioParser: ACTORNAME: BUT NULL");
327 		}
328 		Object obj = Markets.getMarket(actorName);
329 		if (obj == null)
330 		{
331 			System.err
332 					.println("ScenarioParser: LOOKING FOR MARKET: ACTORNAME: BUT NOT FOUND");
333 		}
334 		return new Event(Markets.getMarket(actorName), startTime, methodName,
335 				args);
336 	}
337 
338 	/***
339 	 * Method parseLargeNewsMessageEvent
340 	 * 
341 	 * @param element the element to get the data from
342 	 * @param startTime the start time of the event
343 	 * @return Returns an event
344 	 */
345 	private static Event parseLargeNewsMessageEvent(final Element element,
346 			final long startTime)
347 	{
348 		String subject = null;
349 		String content = null;
350 		String summary = null;
351 		String region = null;
352 		String type = null;
353 		Object[] args = new Object[]{};
354 		Namespace space = element.getNamespace();
355 		if (element.getChild("largeNewsMessageEvent", space) != null)
356 		{
357 			Element largeNewsMessageEventElement = element.getChild(
358 					"largeNewsMessageEvent", space);
359 
360 			if (largeNewsMessageEventElement.getChild("subject", space) != null)
361 			{
362 				subject = largeNewsMessageEventElement.getChildText("subject",
363 						space);
364 			}
365 			if (largeNewsMessageEventElement.getChild("content", space) != null)
366 			{
367 				content = largeNewsMessageEventElement.getChildText("content",
368 						space);
369 			}
370 			if (largeNewsMessageEventElement.getChild("summary", space) != null)
371 			{
372 				summary = largeNewsMessageEventElement.getChildText("summary",
373 						space);
374 			}
375 			if (largeNewsMessageEventElement.getChild("region", space) != null)
376 			{
377 				region = largeNewsMessageEventElement.getChildText("region",
378 						space);
379 			}
380 			if (largeNewsMessageEventElement.getChild("type", space) != null)
381 			{
382 				type = largeNewsMessageEventElement.getChildText("type", space);
383 			}
384 		}
385 		args = new Object[]{subject, content, summary, region, type};
386 		return new Event(ScenarioText.getScenarioText(), startTime,
387 				"fireNewsMessageEvent", args);
388 	}
389 }