1
2
3
4
5
6
7
8
9
10
11
12
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
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
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
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
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 }