Source code: com/arranger/jarl/Jarl.java
1 package com.arranger.jarl;
2
3 import com.arranger.jarl.base.*;
4 import com.arranger.jarl.filter.IFilter;
5 import com.arranger.jarl.filter.IFilterDef;
6 import com.arranger.jarl.script.jarlsp.JarlSPCompiler;
7 import com.arranger.jarl.stroke.IStroke;
8 import com.arranger.jarl.stroke.IStrokeDef;
9 import com.arranger.jarl.trait.ContainerTrait;
10 import com.arranger.jarl.trait.ITrait;
11 import com.arranger.jarl.trait.ITraitDef;
12 import com.arranger.jarl.util.*;
13 import com.arranger.jarl.widget.ContainerWidget;
14 import com.arranger.jarl.widget.IWidget;
15 import com.arranger.jarl.widget.IWidgetDef;
16 import org.w3c.dom.Document;
17 import org.w3c.dom.Element;
18 import org.w3c.dom.Node;
19 import org.w3c.dom.NodeList;
20
21 import java.awt.*;
22 import java.io.File;
23 import java.io.FileWriter;
24 import java.util.*;
25 import java.util.List;
26
27 /**
28 * Jarl is the main package for rendering..
29 */
30 public class Jarl {
31
32 protected static final String DEFAULT_WIDTH = "400";
33 protected static final String DEFAULT_HEIGHT = "225";
34 protected static final String DEFAULT_STROKE_WIDTH = "5";
35
36 //rendering objects
37 protected IContext m_context = new Context();
38 protected IRenderManager m_renderManager = new RenderManager();
39 protected IGradientManager m_gradientManager = new GradientManager();
40 protected Time m_startTime;
41 protected Time m_endTime;
42
43 //configuration objects
44 protected List m_widgetPackages = new ArrayList();
45 protected Map m_widgetDefs = new HashMap();
46 protected List m_traitPackages = new ArrayList();
47 protected Map m_traitDefs = new HashMap();
48 protected List m_strokePackages = new ArrayList();
49 protected Map m_strokeDefs = new HashMap();
50 protected List m_filterPackages = new ArrayList();
51 protected Map m_filterDefs = new HashMap();
52 protected boolean m_useBMP = true;
53 protected String m_description;
54 protected Time m_screenshot;
55
56 public static void main(String[] args) throws Exception {
57 JDKUtil.checkJDKVersion();
58 String jarlConfig = args[0];
59 String outputDir = "output";
60 String imagePrefix = "image";
61 if (args.length > 1) {
62 outputDir = args[1];
63 }
64 if (args.length > 2) {
65 imagePrefix = args[2];
66 }
67
68 Jarl jarl = new Jarl();
69 jarl.getContext().addStatusListener(new IStatusListener() {
70 public void onStatus(String message) {
71 System.out.println(message);
72 }
73
74 public void onError(Throwable throwable) {
75 System.out.println(Debug.getStackTrace(throwable));
76 }
77 });
78 jarl.init(jarlConfig);
79 jarl.render(outputDir, imagePrefix);
80 }
81
82 public Jarl() {
83 m_context.setRenderManager(m_renderManager);
84 m_context.setGradientManager(m_gradientManager);
85 m_context.setJarl(this);
86 }
87
88 public IContext getContext() {
89 return m_context;
90 }
91
92 public IRenderManager getRenderManager() {
93 return m_renderManager;
94 }
95
96 public Time getStartTime() {
97 return m_startTime;
98 }
99
100 public Time getEndTime() {
101 return m_endTime;
102 }
103
104 public List getWidgetPackages() {
105 return m_widgetPackages;
106 }
107
108 public Map getWidgetDefs() {
109 return m_widgetDefs;
110 }
111
112 public List getTraitPackages() {
113 return m_traitPackages;
114 }
115
116 public Map getTraitDefs() {
117 return m_traitDefs;
118 }
119
120 public List getStrokePackages() {
121 return m_strokePackages;
122 }
123
124 public Map getStrokeDefs() {
125 return m_strokeDefs;
126 }
127
128 public List getFilterPackages() {
129 return m_filterPackages;
130 }
131
132 public Map getFilterDefs() {
133 return m_filterDefs;
134 }
135
136 public boolean isUseBMP() {
137 return m_useBMP;
138 }
139
140 public String getDescription() {
141 return m_description;
142 }
143
144 public Time getScreenshot() {
145 return m_screenshot;
146 }
147
148 /**
149 * Initializes with all the directives in the config file
150 *
151 * @param configFile
152 * @throws Exception
153 */
154 public void init(String configFile) throws Exception {
155 Element element = getConfigElement(configFile);
156 _init(element);
157 }
158
159 public void initRemote(String configText) throws Exception {
160 Element element = XMLUtil.loadDocumentFromXML(configText).getDocumentElement();
161 _init(element);
162 }
163
164 protected void _init(Element element) throws Exception {
165 //description
166 Element elem = (Element)XMLUtil.selectSingleNode(element, "description");
167 if (elem != null) {
168 m_description = XMLUtil.getNodeText(elem);
169 }
170
171 Element elemScreenshot = (Element)XMLUtil.selectSingleNode(element, "screenshot");
172 if (elemScreenshot != null) {
173 m_screenshot = Time.getTime(XMLUtil.getNodeText(elemScreenshot).trim());
174 //getContext().onStatus("screenshot: " + m_screenshot.getFrame());
175 }
176
177 //rendering hints
178 NodeList nodeList = XMLUtil.selectNodeList(element, "render/renderhints/renderhint");
179 initRenderHints(nodeList);
180
181 //rendering time
182 elem = (Element)XMLUtil.selectSingleNode(element, "render/time");
183 Time.init(elem);
184 m_startTime = Time.getTime(elem, "startTime");
185 m_endTime = Time.getTime(elem, "endTime");
186
187 //rendering size
188 elem = (Element)XMLUtil.selectSingleNode(element, "render/size");
189 m_context.setWidth(Integer.parseInt(getAttribute(elem, "width", DEFAULT_WIDTH)));
190 m_context.setHeight(Integer.parseInt(getAttribute(elem, "height", DEFAULT_HEIGHT)));
191 m_context.setStrokeWidth(Float.parseFloat(getAttribute(elem, "strokeWidth", DEFAULT_STROKE_WIDTH)));
192
193 //rendering format
194 elem = (Element)XMLUtil.selectSingleNode(element, "render/format");
195 m_useBMP = "true".equalsIgnoreCase(getAttribute(elem, "useBMP", "true"));
196
197 //gradient manager
198 m_gradientManager.init(null);
199
200 //trait packages
201 nodeList = XMLUtil.selectNodeList(element, "traitPackages/traitPackage");
202 initPackages(nodeList, m_traitPackages);
203
204 //stroke packages
205 nodeList = XMLUtil.selectNodeList(element, "strokePackages/strokePackage");
206 initPackages(nodeList, m_strokePackages);
207
208 //widget packages
209 nodeList = XMLUtil.selectNodeList(element, "widgetPackages/widgetPackage");
210 initPackages(nodeList, m_widgetPackages);
211
212 //filter packages
213 nodeList = XMLUtil.selectNodeList(element, "filterPackages/filterPackage");
214 initPackages(nodeList, m_filterPackages);
215
216 //trait defs
217 nodeList = XMLUtil.selectNodeList(element, "traitDefs/traitDef");
218 initTraitDefs(nodeList);
219
220 //stroke defs
221 nodeList = XMLUtil.selectNodeList(element, "strokeDefs/strokeDef");
222 initStrokeDefs(nodeList);
223
224 //filter defs
225 nodeList = XMLUtil.selectNodeList(element, "filterDefs/filterDef");
226 initFilterDefs(nodeList);
227
228 //widget defs
229 nodeList = XMLUtil.selectNodeList(element, "widgetDefs/widgetDef");
230 initWidgetDefs(nodeList);
231
232 //widgets
233 nodeList = XMLUtil.selectNodeList(element, "widgets/widget");
234 initWidgets(nodeList);
235
236 //filters
237 nodeList = XMLUtil.selectNodeList(element, "filters/filter");
238 initFilters(null, nodeList);
239
240 //debug settings
241 nodeList = XMLUtil.selectNodeList(element, "render/systemWidgets/systemWidget");
242 initSystemWidgets(nodeList);
243 }
244
245 /**
246 * Render this bad boy
247 *
248 * @param outputDirectory
249 * @param prefix
250 * @throws Exception
251 */
252 public void render(String outputDirectory, String prefix) throws Exception {
253 File file = new File(outputDirectory);
254 file.mkdirs();
255
256 Time time = (Time)m_startTime.clone();
257 while (time.isLess(m_endTime) || time.equals(m_endTime)) {
258 m_context.setAbsoluteTime(time);
259 Image image = m_renderManager.render(m_context);
260 if (m_useBMP) {
261 IOUtil.save(image, new File(outputDirectory + '/' + prefix + time.getFrame() + ".bmp"));
262 } else {
263 IOUtil.saveJPEG(image, new File(outputDirectory + '/' + prefix + time.getFrame() + ".jpg"));
264 }
265 time.increment();
266 }
267 }
268
269 /**------------------------------------------------
270 * Configuration stuff
271 * ------------------------------------------------**/
272
273
274 protected void initRenderHints(NodeList nodeList) {
275 int length = nodeList.getLength();
276 for (int index = 0; index < length; index++) {
277 Element elem = (Element)nodeList.item(index);
278 String name = elem.getAttribute("name");
279 String value = elem.getAttribute("value");
280
281 Object key = ObjectUtil.getStaticProperty(RenderingHints.class, name);
282 Object val = ObjectUtil.getStaticProperty(RenderingHints.class, value);
283
284 RenderingHints renderingHints = m_context.getRenderingHints();
285 if (renderingHints == null) {
286 renderingHints = new RenderingHints((RenderingHints.Key)key, val);
287 m_context.setRenderingHints(renderingHints);
288 } else {
289 renderingHints.add(new RenderingHints((RenderingHints.Key)key, val));
290 }
291 }
292 }
293
294 protected void initPackages(NodeList nodeList, List packageList) {
295 int length = nodeList.getLength();
296 for (int index = 0; index < length; index++) {
297 Node node = nodeList.item(index);
298 String packageName = XMLUtil.getNodeText(node);
299 if (!packageName.endsWith(".")) {
300 packageName += ".";
301 }
302
303 packageList.add(packageName);
304 }
305 }
306
307 protected void initWidgetDefs(NodeList nodeList) throws Exception {
308 int length = nodeList.getLength();
309 for (int index = 0; index < length; index++) {
310 Element elem = (Element)nodeList.item(index);
311 String name = elem.getAttribute("name");
312 String clazz = elem.getAttribute("class");
313
314 IWidgetDef widgetDef = (IWidgetDef)loadClassFromPackages(clazz, m_widgetPackages);
315 widgetDef.initDef(m_context, elem);
316 m_widgetDefs.put(name, widgetDef);
317
318 //init any child traits and strokes
319 initTraits(widgetDef, XMLUtil.selectNodeList(elem, "traits/trait"));
320 initStrokes(widgetDef, XMLUtil.selectNodeList(elem, "strokes/stroke"));
321 initFilters(widgetDef, XMLUtil.selectNodeList(elem, "filters/filter"));
322
323 initSubWidgetDefs(widgetDef, elem);
324 }
325 }
326
327 protected void initSubWidgetDefs(IWidgetDef widgetDef, Element elem) throws Exception {
328 if (widgetDef instanceof ContainerWidget) {
329 NodeList childList = XMLUtil.selectNodeList(elem, "widgetDef");
330 List widgets = initWidgets(childList);
331 ((ContainerWidget)widgetDef).getChildren().addAll(widgets);
332 for (Iterator it = widgets.iterator(); it.hasNext();) {
333 IWidget widget = (IWidget)it.next();
334 widget.setParent(widgetDef);
335 m_context.getRenderManager().unregister(widget);
336 }
337 }
338 }
339
340 protected void initTraitDefs(NodeList nodeList) throws Exception {
341 int length = nodeList.getLength();
342 for (int index = 0; index < length; index++) {
343 Element elem = (Element)nodeList.item(index);
344 String name = elem.getAttribute("name");
345 String clazz = elem.getAttribute("class");
346
347 ITraitDef traitDef = (ITraitDef)loadClassFromPackages(clazz, m_traitPackages);
348 traitDef.initDef(m_context, elem);
349 m_traitDefs.put(name, traitDef);
350
351 if (traitDef instanceof ContainerTrait) {
352 NodeList childList = XMLUtil.selectNodeList(elem, "traitDef");
353 List traits = initTraits(null, childList);
354 ((ContainerTrait)traitDef).getChildren().addAll(traits);
355 }
356 }
357 }
358
359 protected void initStrokeDefs(NodeList nodeList) throws Exception {
360 int length = nodeList.getLength();
361 for (int index = 0; index < length; index++) {
362 Element elem = (Element)nodeList.item(index);
363 String name = elem.getAttribute("name");
364 String clazz = elem.getAttribute("class");
365
366 IStrokeDef strokeDef = (IStrokeDef)loadClassFromPackages(clazz, m_strokePackages);
367 strokeDef.initDef(m_context, elem);
368 m_strokeDefs.put(name, strokeDef);
369 }
370 }
371
372 protected void initFilterDefs(NodeList nodeList) throws Exception {
373 int length = nodeList.getLength();
374 for (int index = 0; index < length; index++) {
375 Element elem = (Element)nodeList.item(index);
376 String name = elem.getAttribute("name");
377 String clazz = elem.getAttribute("class");
378
379 IFilterDef filterDef = (IFilterDef)loadClassFromPackages(clazz, m_filterPackages);
380 filterDef.initDef(m_context, elem);
381 m_filterDefs.put(name, filterDef);
382 }
383 }
384
385 protected List initWidgets(NodeList nodeList) throws Exception {
386 List widgets = new ArrayList();
387 int length = nodeList.getLength();
388 for (int index = 0; index < length; index++) {
389 IWidget widget = null;
390 Element elem = (Element)nodeList.item(index);
391
392 //look for a widget definition first
393 String widgetDefName = elem.getAttribute("widgetDef");
394 if (!StringTools.isEmpty(widgetDefName)) {
395 IWidgetDef widgetDef = (IWidgetDef)m_widgetDefs.get(widgetDefName);
396 if (widgetDef == null) {
397 throw new Exception("Unable to find widgetDef: " + widgetDefName);
398 }
399 widget = widgetDef.initInstance(m_context, elem);
400 } else {
401 String clazz = elem.getAttribute("class");
402 IWidgetDef widgetDef = (IWidgetDef)loadClassFromPackages(clazz, m_widgetPackages);
403 widgetDef.initDef(m_context, elem);
404 widget = widgetDef.initInstance(m_context, elem);
405 }
406 if (widget == null) {
407 throw new Exception("Unable to find widget for elem: " + XMLUtil.toString(elem));
408 }
409
410 //init any child traits and strokes
411 initTraits(widget, XMLUtil.selectNodeList(elem, "traits/trait"));
412 initStrokes(widget, XMLUtil.selectNodeList(elem, "strokes/stroke"));
413 initFilters(widget, XMLUtil.selectNodeList(elem, "filters/filter"));
414 widgets.add(widget);
415 if (widget instanceof IWidgetDef) {
416 initSubWidgetDefs((IWidgetDef)widget, elem);
417 }
418
419 }
420 return widgets;
421 }
422
423 protected List initTraits(IWidget widget, NodeList nodeList) throws Exception {
424 List traits = new ArrayList();
425 int length = nodeList.getLength();
426 for (int index = 0; index < length; index++) {
427 ITrait trait = null;
428 Element elem = (Element)nodeList.item(index);
429
430 //look for a trait definition first
431 String traitDefName = elem.getAttribute("traitDef");
432 if (!StringTools.isEmpty(traitDefName)) {
433 ITraitDef traitDef = (ITraitDef)m_traitDefs.get(traitDefName);
434 if (traitDef == null) {
435 throw new Exception("Unable to find traitDef: " + traitDefName);
436 }
437 trait = traitDef.initInstance(m_context, elem);
438 } else {
439 String clazz = elem.getAttribute("class");
440 ITraitDef traitDef = (ITraitDef)loadClassFromPackages(clazz, m_traitPackages);
441 traitDef.initDef(m_context, elem);
442 trait = traitDef.initInstance(m_context, elem);
443 }
444 if (trait == null) {
445 throw new Exception("Unable to find trait for elem: " + XMLUtil.toString(elem));
446 }
447
448 if (widget != null) { //this will be null for container traits
449 widget.getTraits().add(trait);
450 }
451 traits.add(trait);
452 }
453 return traits;
454 }
455
456 /**
457 * set any instance of {@link com.arranger.jarl.stroke.IStroke} associated
458 * with this widget
459 * @param widget
460 * @param nodeList
461 */
462 protected List initStrokes(IWidget widget, NodeList nodeList) throws Exception {
463 List strokes = new ArrayList();
464 int length = nodeList.getLength();
465 for (int index = 0; index < length; index++) {
466 IStroke stroke = null;
467 Element elem = (Element)nodeList.item(index);
468
469 //look for a stroke definition first
470 String strokeDefName = elem.getAttribute("strokeDef");
471 if (!StringTools.isEmpty(strokeDefName)) {
472 IStrokeDef strokeDef = (IStrokeDef)m_strokeDefs.get(strokeDefName);
473 if (strokeDef == null) {
474 throw new Exception("Unable to find strokeDef: " + strokeDefName);
475 }
476 stroke = strokeDef.initInstance(m_context, elem);
477 } else {
478 String clazz = elem.getAttribute("class");
479 IStrokeDef strokeDef = (IStrokeDef)loadClassFromPackages(clazz, m_strokePackages);
480 strokeDef.initDef(m_context, elem);
481 stroke = strokeDef.initInstance(m_context, elem);
482 }
483 if (stroke == null) {
484 throw new Exception("Unable to find stroke for elem: " + XMLUtil.toString(elem));
485 }
486
487 if (widget != null) { //this will be null for container strokes
488 widget.getStrokes().add(stroke);
489 }
490 strokes.add(stroke);
491 }
492 return strokes;
493 }
494
495 /**
496 * set any instance of {@link IFilter} associated
497 * with this widget
498 * @param widget
499 * @param nodeList
500 */
501 protected List initFilters(IWidget widget, NodeList nodeList) throws Exception {
502 List filters = new ArrayList();
503 int length = nodeList.getLength();
504 for (int index = 0; index < length; index++) {
505 IFilter filter = null;
506 Element elem = (Element)nodeList.item(index);
507
508 //look for a filter definition first
509 String filterDefName = elem.getAttribute("filterDef");
510 if (!StringTools.isEmpty(filterDefName)) {
511 IFilterDef filterDef = (IFilterDef)m_filterDefs.get(filterDefName);
512 if (filterDef == null) {
513 throw new Exception("Unable to find filterDef: " + filterDefName);
514 }
515 filter = filterDef.initInstance(m_context, elem);
516 } else {
517 String clazz = elem.getAttribute("class");
518 IFilterDef filterDef = (IFilterDef)loadClassFromPackages(clazz, m_filterPackages);
519 filterDef.initDef(m_context, elem);
520 filter = filterDef.initInstance(m_context, elem);
521 }
522 if (filter == null) {
523 throw new Exception("Unable to find filter for elem: " + XMLUtil.toString(elem));
524 }
525
526 if (widget != null) { //this will be null for global filters
527 widget.getFilters().add(filter);
528 }
529 filters.add(filter);
530 }
531 return filters;
532 }
533
534 protected String getAttribute(Element elem, String attrName, String defValue) {
535 if (elem == null) {
536 return defValue;
537 }
538 String value = elem.getAttribute(attrName);
539 return StringTools.isEmpty(value) ? defValue : value;
540 }
541
542 protected void initSystemWidgets(NodeList nodeList) {
543 if (nodeList == null) {
544 return;
545 }
546 int length = nodeList.getLength();
547 for (int index = 0; index < length; index++) {
548 Element elem = (Element)nodeList.item(index);
549
550 if (!"true".equalsIgnoreCase(elem.getAttribute("enabled"))) {
551 continue;
552 }
553
554 String widgetDefName = elem.getAttribute("widgetDef");
555 IWidgetDef widgetDef = (IWidgetDef)m_widgetDefs.get(widgetDefName);
556 IWidget widget = widgetDef.initInstance(m_context, elem);
557 widget.setStartTime(m_startTime);
558 widget.setEndTime(m_endTime);
559 }
560 }
561
562 protected Object loadClassFromPackages(String clazz, List packageList) throws Exception {
563 for (Iterator it = packageList.iterator(); it.hasNext();) {
564 String className = ((String)it.next()) + clazz;
565 try {
566 return Class.forName(className).newInstance();
567 } catch (Exception ignored) {
568 }
569 }
570 throw new ClassNotFoundException(clazz);
571 }
572
573 /**
574 * This will preprocess the config file processing any includes,
575 * then parse, compile, execute and then build up the dom
576 * @param configFile
577 */
578 protected Element getConfigElement(String configFile) throws Exception {
579 String resultXMLFile = processXMLFile(configFile, getContext());
580 Document document = XMLUtil.loadDocument(resultXMLFile);
581 return document.getDocumentElement();
582 }
583
584 public static String processXMLFile(String configFile, IContext context) throws Exception {
585 String xmlText = XMLUtil.preprocesXML(new File(configFile), new Stack());
586
587 File file = new File("gen/com/arranger/jarl/config");
588 file.mkdirs();
589 String name = StringTools.normalizePath(configFile);
590 name = StringTools.getLastSegment(name, File.separator, false);
591 String tempLocation = StringTools.appendPath(file.getAbsolutePath(), name);
592 FileWriter writer = (FileWriter)IOUtil.getWriter(tempLocation);
593 writer.write(xmlText);
594 writer.close();
595
596 //parse, compile and execute
597 JarlSPCompiler compiler = new JarlSPCompiler();
598 compiler.setClassOutput(new File("classes").getAbsolutePath());
599 String parsedFile = compiler.parse(new File(tempLocation), context);
600 compiler.compile(new File(parsedFile));
601 String resultXMLFile = compiler.execute(parsedFile, context);
602 return resultXMLFile;
603 }
604 }