1
2
3
4
5
6
7 package net.sf.tomp.pp.wiki.docbook;
8
9 import java.util.HashMap;
10 import java.util.Map;
11 import java.util.regex.Matcher;
12 import java.util.regex.Pattern;
13
14 import net.sf.tomp.pp.CharReader;
15 import net.sf.tomp.pp.wiki.AbstractWikiReader;
16
17 import org.xml.sax.Attributes;
18 import org.xml.sax.SAXException;
19 import org.xml.sax.helpers.AttributesImpl;
20
21 /***
22 * TODO: nested lists, inline elements
23 * @author tomp
24 */
25 public class DocBookSlidesWikiReader extends AbstractWikiReader {
26
27 private String inList = null;
28 private boolean inProgramlisting = false;
29
30 private static Map ELEMENTS = new HashMap();
31
32 protected static void depth(String elt, int depth) {
33 ELEMENTS.put(elt, new Integer(depth));
34 }
35
36 protected int getDepth(String elt) {
37 Integer ii = (Integer)ELEMENTS.get(elt);
38 if (ii == null) return -1;
39 return ii.intValue();
40 }
41
42 static {
43 depth("slides", 0);
44 depth("foilgroup", 1);
45 depth("foil", 2);
46
47 depth("title", 3);
48
49 depth("programlisting", 5);
50
51 depth("itemizedlist", 5);
52 depth("orderedlist", 5);
53 depth("variablelist", 5);
54
55 depth("varlistentry", 6);
56
57 depth("term", 7);
58 depth("listitem", 7);
59
60 depth("tip", 5);
61 depth("warning", 5);
62 depth("note", 5);
63 depth("caution", 5);
64 depth("important", 5);
65 depth("sidebar", 5);
66 depth("abstract", 5);
67 depth("footnote", 5);
68
69 depth("para", 8);
70
71 depth("simpara", 9);
72
73 depth("figure", 3);
74
75 depth("mediaobject", 4);
76 depth("caption", 5);
77 depth("imageobject", 5);
78
79 depth("ulink", 20);
80 depth("xref", 20);
81 depth("emphasis", 20);
82
83 depth("classname", 21);
84 depth("packagename", 21);
85 depth("methodname", 21);
86 };
87
88 protected boolean isDeeperThan(String elt1, String elt2) {
89 if(elt1 == null || elt2 == null)
90 return super.isDeeperThan(elt1, elt2);
91
92 if(top.equals("foilgroup") && elt1.equals("foil")
93 && elt2.equals("title")) return false;
94
95 if(elt1.equals("figure") && elt2.equals("title"))
96 return true;
97
98 int i1 = getDepth(elt1);
99 int i2 = getDepth(elt2);
100 if(i1 == -1 || i2 == -1)
101 return super.isDeeperThan(elt1, elt2);
102 return i1 < i2;
103 }
104
105 protected void process(String line) throws SAXException {
106 if(line.startsWith("===")) {
107
108 startTitledElement("!foilgroup"+line.substring(3));
109 } else if(line.startsWith("---")) {
110
111 startTitledElement("!foil"+line.substring(3));
112 } else if(line.startsWith("*")) {
113
114 itemizedlistItem(line);
115 } else if(line.startsWith("#")) {
116
117 orderedlistItem(line);
118 } else if(line.startsWith("!mediaobject")
119 || line.startsWith("!figure")
120 ) {
121 startTitledFiledElement(line);
122 } else if(line.startsWith("!")) {
123
124 startTitledElement(line);
125 } else if(line.startsWith("{{{")) {
126
127 inProgramlisting = true;
128 AttributesImpl atts = new AttributesImpl();
129 if(line.length()>3) {
130 atts.addAttribute("", "id", "id", "CDATA", line.substring(3));
131 }
132 startElement("programlisting", atts);
133 } else if(line.startsWith("}}}")) {
134
135 endElement();
136 inProgramlisting = false;
137 } else if(line.startsWith(";")) {
138
139 variableListItem(line);
140 } else if(line.equals("")) {
141
142 emptyLine();
143 } else {
144 if(inProgramlisting)
145 characters(line+"\n");
146 else
147 processedTextElement("para", line);
148 }
149 }
150
151 protected void emptyLine() throws SAXException {
152 inList = null;
153 while(top != null
154 && (top.endsWith("para")
155 || top.endsWith("entry")
156 || top.endsWith("item")
157 || top.endsWith("list"))) {
158 endElement();
159 }
160 }
161
162 protected static final Pattern VARLIST_ITEM
163 = Pattern.compile("^//;([^//:]+)//:(.*)");
164
165 protected void variableListItem(String line) throws SAXException {
166 Matcher m = VARLIST_ITEM.matcher(line);
167 if(m.matches()) {
168 if(!"variablelist".equals(inList)) {
169 inList = "variablelist";
170 startElement(inList);
171 }
172 System.out.println("matched in "+line);
173 String terms = m.group(1);
174 String definition = m.group(2);
175 startElement("varlistentry");
176
177 processedTextElement("term", terms);
178 startElement("listitem");
179 processedTextElement("simpara", definition);
180 }
181 }
182
183 protected void listItem(String listType, String line) throws SAXException {
184 if(!listType.equals(inList)) {
185 startElement(listType+"list");
186 inList = listType;
187 }
188 startElement("listitem");
189 processedTextElement("simpara", line.substring(1));
190 }
191
192 protected void itemizedlistItem(String line) throws SAXException {
193 listItem("itemized", line);
194 }
195
196 protected void orderedlistItem(String line) throws SAXException {
197 listItem("ordered", line);
198 }
199
200 protected static final String ID_TITLE
201 = "(//#(//S*))?//s*(.*)";
202
203 protected static final String ELEMENT_ID_TITLE
204 = "//!(//w+)"+ID_TITLE;
205
206 protected static final Pattern P_ELEMENT_ID_TITLE
207 = Pattern.compile(ELEMENT_ID_TITLE);
208
209 protected void startTitledElement(String line) throws SAXException {
210 System.out.println("startTitledElement "+line);
211 Matcher m = P_ELEMENT_ID_TITLE.matcher(line);
212 if(m.matches()) {
213 String element = m.group(1);
214 String id = m.group(3);
215 String title = m.group(4);
216 startTitledElement(element, id, title);
217 }
218 }
219
220 protected static final String ELEMENT_ID_FILE_TITLE
221 = "//!(//w+)(//#(//S*))?//s*(//S+)//s+(.*)";
222
223 protected static final Pattern P_ELEMENT_ID_FILE_TITLE
224 = Pattern.compile(ELEMENT_ID_FILE_TITLE);
225
226 protected void startTitledFiledElement(String line) throws SAXException {
227 System.out.println("startTitledFiledElement "+line);
228 Matcher m = P_ELEMENT_ID_FILE_TITLE.matcher(line);
229 if(m.matches()) {
230 String element = m.group(1);
231 String id = m.group(3);
232 String file = m.group(4);
233 String title = m.group(5);
234 startTitledFiledElement(element, id, title, file);
235 }
236 }
237
238 protected AttributesImpl getAttributesWithId(String id) {
239 if(id != null && id.length() > 0) {
240 AttributesImpl atts = new AttributesImpl();
241 atts.addAttribute("", "id", "id", "CDATA", id);
242 return atts;
243 } else {
244 return EMPTY_ATTRS;
245 }
246 }
247
248 protected void startTitledElement(String element, String id, String title)
249 throws SAXException {
250 System.out.println("startTitledElement "+element+" id="+id+" title="+title);
251 startElement(element, getAttributesWithId(id));
252 if( element.equals("foilgroup")
253 || element.equals("foil")
254 ) {
255 textElement("title", title);
256 } else {
257
258 processedTextElement("simpara", title);
259 }
260 if(element.equals("footnote")
261 || element.equals("abstract")
262 ) {
263 endElement();
264 }
265 }
266
267 protected void startTitledFiledElement(String element, String id, String title, String file)
268 throws SAXException {
269 System.out.println("startTitledFiledElement "+element+" id="+id
270 +" title="+title+" file="+file);
271
272 if(element.equals("figure")) {
273
274 startElement("figure", getAttributesWithId(id));
275 textElement("title", title);
276 startElement("mediaobject");
277 AttributesImpl atts2 = new AttributesImpl();
278 atts2.addAttribute("", "fileref", "fileref", "CDATA", file);
279 startElement("imageobject", atts2);
280 endElement();
281 endElement();
282 endElement();
283
284 } else if(element.equals("mediaobject")) {
285
286 startElement("mediaobject", getAttributesWithId(id));
287 AttributesImpl atts2 = new AttributesImpl();
288 atts2.addAttribute("", "fileref", "fileref", "CDATA", file);
289 startElement("imageobject", atts2);
290 startElement("caption");
291 textElement("para", title);
292 endElement();
293 endElement();
294 endElement();
295 }
296 }
297
298 protected void processedTextElement(String element, String text, Attributes atts)
299 throws SAXException {
300
301 startElement(element, atts);
302 processInline(text);
303 endElement();
304 }
305
306 protected void processedTextElement(String element, String text)
307 throws SAXException {
308
309 processedTextElement(element, text, EMPTY_ATTRS);
310 }
311
312 protected int listDepth(String line) {
313 if(line.startsWith("*") || line.startsWith("#"))
314 return 1 + listDepth(line.substring(1));
315 else
316 return 0;
317 }
318
319 public void setParameter(String k, Object v) {
320 }
321
322 protected String rootElement() throws SAXException {
323 return "slides";
324 }
325
326 protected void processInline(String s) throws SAXException {
327 CharReader r = new CharReader(s);
328
329 EStack es = new EStack();
330 Element e = null;
331 boolean emptyElt = false;
332 boolean isInText = true;
333 int depth = 0;
334 int textBegin = r.index();
335 int afterName = 0;
336
337 try {
338 while(!r.eof()) {
339 textBegin = r.index();
340 char c = r.next();
341 if (c == '%' && (isNamechar(r.at()) || r.at() == '%')) {
342
343 do {
344 int afterPercent = r.index();
345 if (isInText && afterPercent-1 > textBegin) {
346 text(r.substring(textBegin, afterPercent-1));
347 }
348 isInText = false;
349 c = r.next();
350 if (c == '%') {
351
352
353 emptyElt = true;
354 c = r.next();
355 while(!r.eof() && isNamechar(c)) {
356 c = r.next();
357 }
358 afterName = r.eof() ? r.index()+1 : r.index();
359 e = new Element(r.substring(afterPercent+1, afterName-1), depth);
360 e.emptyTag();
361
362 r.pushback();
363
364 closeNesting(es, e.depth());
365
366 if(markup(r.at())) {
367 if(r.at() == '{') {
368 isInText = true;
369 }
370 } else {
371 isInText = true;
372 }
373
374 if(isInText) {
375 textBegin = r.index();
376 }
377 break;
378
379 } else if (isNamechar(c)) {
380
381
382 c = r.next();
383 while(!r.eof() && isNamechar(c)) {
384 c = r.next();
385 }
386 afterName = r.eof() ? r.index()+1 : r.index();
387 e = new Element(r.substring(afterPercent, afterName-1), depth);
388 es.push(e);
389 depth++;
390
391
392 c = r.nextNonspace(c);
393 if (c == '{' || c == '%') {
394
395 e.startTag();
396 } else {
397 while(!r.eof() && c != '{' && c != '%') {
398 int anBegin = r.index()-1;
399 while(!r.eof() && c != '=' && !isWhitespace(c)) {
400 c = r.next();
401 }
402 e.newAttrName(r.substring(anBegin, r.index()-1));
403
404 while(!r.eof() && !isQuote(c)) {
405 c = r.next();
406 }
407 r.pushback();
408
409 char quote = r.next();
410 c = ' ';
411 int avBegin = r.index();
412 while(!r.eof() && c != quote) {
413 c = r.next();
414 }
415 e.newAttrValue(r.substring(avBegin, r.index()-1));
416
417 c = r.next();
418 c = r.nextNonspace(c);
419
420 }
421
422 e.startTag();
423
424 }
425
426 } else {
427
428 isInText = true;
429 }
430 } while(c == '%' && !r.eof());
431
432 depth = 0;
433
434 } else if (c == '{') {
435 e = new Brackets();
436 es.push(e);
437 e.startTag();
438
439 } else if (c == '}') {
440 closeNesting(es);
441 isInText = true;
442
443 } else if (c == '*') {
444 if(r.at() == '*') {
445 if(es.isEmpty() || !isEmphasisBold(es.top())) {
446
447 e = new Element("emphasis");
448 e.newAttrName("role");
449 e.newAttrValue("bold");
450 es.push(e);
451 e.startTag();
452 } else {
453
454 es.pop().endTag();
455 }
456 } else {
457 text("*");
458 }
459 c = r.next();
460
461 } else if (c == '_') {
462 if (r.at() == '_') {
463
464 if(es.isEmpty() || !isEmphasis(es.top())) {
465
466 e = new Element("emphasis");
467 es.push(e);
468 e.startTag();
469 } else {
470
471 es.pop().endTag();
472 }
473 } else {
474 text("_");
475 }
476 c = r.next();
477
478 } else if (c == '[') {
479 if(r.at() == '[') {
480 text("[");
481 c = r.next();
482 } else {
483 c = r.next();
484 System.out.println("link begin");
485 boolean xref = false;
486
487 String text = "";
488
489 int textStart = r.index();
490
491 while(!r.eof() && c != '|' && c != ']') {
492 c = r.next();
493 }
494 int textEnd = r.index();
495 text = r.substring(textStart-1, textEnd-1);
496 if(c == '|') {
497
498 while(!r.eof() && c != ']') {
499 c = r.next();
500 }
501 int urlEnd = r.index();
502 String url = r.substring(textEnd, urlEnd-1);
503
504 xref = url.startsWith(">>>");
505 if(xref) {
506 e = new Element("xref");
507 e.newAttrName("linkend");
508 e.newAttrValue(url.substring(3));
509 e.newAttrName("endterm");
510 e.newAttrValue(text);
511 } else {
512 e = new Element("ulink");
513 e.newAttrName("url");
514 e.newAttrValue(url);
515 }
516 es.push(e);
517
518 } else {
519 xref = text.startsWith(">>>");
520 if(xref) {
521 e = new Element("xref");
522 e.newAttrName("linkend");
523 e.newAttrValue(text.substring(3));
524 } else {
525 e = new Element("ulink");
526 e.newAttrName("url");
527 e.newAttrValue(text);
528 }
529 es.push(e);
530 }
531 e.startTag();
532 if(!xref)
533 text(text);
534 es.pop().endTag();
535 }
536
537 } else if (c == '@') {
538 if(isWhitespace(r.at(r.index()-2)) && isNamechar(r.at())) {
539 c = r.next();
540 System.out.println("@name");
541
542 int eltnameStart = r.index();
543
544 while(!r.eof() && c != ' ') {
545 c = r.next();
546 }
547 int eltnameEnd = r.index();
548 String eltname = r.substring(eltnameStart-1, eltnameEnd-1);
549
550
551 while(!r.eof() && isWhitespace(c)) {
552 c = r.next();
553 }
554 int nameStart = r.index()-1;
555 while(!r.eof() && (isNamechar(c) || c == '\''
556 || c == '[' || c == ']'
557 || c == '(' || c == ')')) {
558 c = r.next();
559 }
560 int nameEnd = r.index();
561 String name = r.substring(nameStart, nameEnd-1);
562
563 e = new Element(eltname+"name");
564 es.push(e);
565 e.startTag();
566 name = name.replace('\'', ' ');
567 text(name);
568 es.pop().endTag();
569 } else {
570 c = r.next();
571 text("@"+c);
572 }
573 } else {
574
575
576 if (c == '%' && !r.eof()) {
577 c = r.next();
578 }
579
580 while(!r.eof() && notMarkup(c)) {
581 c = r.next();
582 }
583 r.pushback();
584 int firstMarkup = r.eof() ? r.index()+1 : r.index();
585 text(r.substring(textBegin, firstMarkup));
586 }
587 }
588
589 while(!es.isEmpty()) {
590 es.pop().endTag();
591 }
592
593 } catch(StringIndexOutOfBoundsException aioob) {
594 while(!es.isEmpty()) {
595 es.pop().endTag();
596 }
597 }
598
599 }
600
601 public boolean markup(char c) {
602 return (c == '|' ) || (c == '@' ) || super.markup(c);
603 }
604 }