1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.tuigwaa.cms.core.wiki.base;
17
18 import java.net.URL;
19 import java.util.Iterator;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.seasar.tuigwaa.cms.core.CmsRequest;
24 import org.seasar.tuigwaa.cms.core.CmsResponse;
25 import org.seasar.tuigwaa.cms.core.Resource;
26 import org.seasar.tuigwaa.cms.core.wiki.WikiContext;
27 import org.seasar.tuigwaa.cms.core.wiki.engine.SimpleNode;
28 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiAlias;
29 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiAlign;
30 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiAnnotation;
31 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiAnyOther;
32 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiArgs;
33 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiBlockPlugin;
34 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiCSVTable;
35 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiDefineList;
36 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiDefinedWord;
37 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiDeleteline;
38 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiErrors;
39 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiExcerpt;
40 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiExplanationWord;
41 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiFloatAlign;
42 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiGenerateTree;
43 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiHeading;
44 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiHorizontalline;
45 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiInlinePlugin;
46 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiInterwiki;
47 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiLetters;
48 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiLink;
49 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiList;
50 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiListMember;
51 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiPagename;
52 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiParagraph;
53 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiParserVisitor;
54 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiPreshaped;
55 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiSkipToNewline;
56 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiStrongItalic;
57 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiSyntaxError;
58 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiTable;
59 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiTablecolumn;
60 import org.seasar.tuigwaa.cms.core.wiki.engine.WikiTablemember;
61 import org.seasar.tuigwaa.plugin.Plugin;
62 import org.seasar.tuigwaa.plugin.PluginException;
63 import org.seasar.tuigwaa.plugin.PluginRequest;
64 import org.seasar.tuigwaa.system.TgwSecurityException;
65
66 import com.isenshi.util.TextStringBuffer;
67
68 /***
69 * @author someda
70 */
71 public class TextWikiVisitor implements WikiParserVisitor {
72
73 private static final int LINESIZE = 80;
74
75 TextStringBuffer buf;
76
77 private CmsRequest request;
78
79 private CmsResponse response;
80
81 private WikiConfiguration config;
82
83 private WikiContext ctx;
84
85 private int[] listIndex = { 0, 0, 0 };
86
87 private int[] headerIndex = { 0, 0, 0 };
88
89 private static final String INDENT = " ";
90
91 private Log log = LogFactory.getLog(getClass());
92
93 public TextWikiVisitor(CmsRequest request, CmsResponse response,
94 WikiConfiguration config) {
95 this.request = request;
96 this.response = response;
97 this.config = config;
98 this.ctx = config.getWikiContext();
99 buf = new TextStringBuffer(LINESIZE);
100 }
101
102 public Object visit(SimpleNode node, Object data) {
103 return null;
104 }
105
106 public Object visit(WikiSyntaxError node, Object data) {
107 appendError(node.letter);
108 return null;
109 }
110
111 public Object visit(WikiSkipToNewline node, Object data) {
112 buf.append(node.letter);
113 return null;
114 }
115
116 public Object visit(WikiGenerateTree node, Object data) {
117 for (int i = 0; i < node.jjtGetNumChildren(); i++)
118 node.jjtGetChild(i).jjtAccept(this, data);
119
120 if (node.annotation.size() > 0) {
121 buf.appendNewline();
122 buf.appendRepeatString("-", LINESIZE / 3);
123
124 Iterator itr = node.annotation.iterator();
125 int idx = 1;
126 while (itr.hasNext()) {
127 buf.appendNewline();
128 buf.append("(*" + idx + ")");
129 SimpleNode n = (SimpleNode) itr.next();
130 for (int i = 0; i < n.jjtGetNumChildren(); i++) {
131 n.jjtGetChild(i).jjtAccept(this, data);
132 }
133 idx++;
134 }
135 }
136 return buf.toString();
137 }
138
139 public Object visit(WikiParagraph node, Object data) {
140
141 buf.appendNewline();
142 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
143 node.jjtGetChild(i).jjtAccept(this, data);
144 }
145 return null;
146 }
147
148 public Object visit(WikiExcerpt node, Object data) {
149
150 boolean isTagNeed = VisitorUtils.isExcerptStartNeeded(node);
151
152 if (isTagNeed) {
153 String current = buf.getNewlineHeading();
154 buf.setNewlineHeading(">" + current);
155 }
156 buf.appendNewline();
157 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
158 if (node.jjtGetChild(i) instanceof WikiParagraph) {
159 WikiParagraph p = (WikiParagraph) node.jjtGetChild(i);
160 for (int j = 0; j < p.jjtGetNumChildren(); j++)
161 p.jjtGetChild(j).jjtAccept(this, data);
162 } else {
163 node.jjtGetChild(i).jjtAccept(this, data);
164 }
165 }
166
167 buf.setNewlineHeading("");
168 if (node.level == 1 && isTagNeed) {
169 buf.appendNewline();
170 }
171
172 return null;
173 }
174
175 public Object visit(WikiList node, Object data) {
176
177 buf.appendNewline();
178
179 int curtype = 0;
180 int curlevel = 0;
181 int pretype = 0;
182 int prelevel = 0;
183 int[] level = { 0, 0, 0 };
184
185 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
186
187 if (node.jjtGetChild(i) instanceof WikiListMember) {
188 WikiListMember child = (WikiListMember) node.jjtGetChild(i);
189
190 curtype = child.type;
191 curlevel = child.level;
192
193
194 if (curlevel > prelevel)
195 startList(curtype, curlevel);
196
197
198 if (curlevel < prelevel) {
199 for (int j = curlevel; j < prelevel; j++) {
200 if (level[j] != 0) {
201 endList(pretype, prelevel);
202 level[j] = 0;
203 }
204 }
205 if (level[curlevel - 1] != curtype)
206 startList(curtype, curlevel);
207 }
208
209
210 if (curlevel == prelevel && curtype != pretype) {
211 endList(pretype, prelevel);
212 startList(curtype, curlevel);
213 }
214
215
216 if (curlevel != prelevel || curtype != pretype) {
217 level[curlevel - 1] = curtype;
218 pretype = curtype;
219 prelevel = curlevel;
220 }
221 child.jjtAccept(this, data);
222 }
223 }
224
225 endAllList();
226 return null;
227 }
228
229 public Object visit(WikiListMember node, Object data) {
230
231 buf.setNewlineHeading(getRepeatedString(INDENT, node.level * 2));
232 buf.appendNewline();
233 if (node.type == WikiHelper.LIST_TYPE_NUMERICAL) {
234 for (int i = 0; i < node.level - 1; i++) {
235 if (listIndex[i] != 0)
236 buf.append(listIndex[i] + ".");
237 }
238 buf.append((++listIndex[node.level - 1]) + ".");
239 } else {
240 buf.append("-");
241 }
242 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
243 node.jjtGetChild(i).jjtAccept(this, data);
244 }
245 return null;
246 }
247
248 public Object visit(WikiDefineList node, Object data) {
249 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
250 node.jjtGetChild(i).jjtAccept(this, data);
251 }
252 return null;
253 }
254
255 public Object visit(WikiDefinedWord node, Object data) {
256 if (node.jjtGetNumChildren() > 0) {
257 buf.appendNewline();
258 buf.append("[[");
259 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
260 node.jjtGetChild(i).jjtAccept(this, data);
261 }
262 buf.append("]]");
263 }
264 return null;
265 }
266
267 public Object visit(WikiExplanationWord node, Object data) {
268 buf.setNewlineHeading("\t");
269 buf.appendNewline();
270 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
271 node.jjtGetChild(i).jjtAccept(this, data);
272 }
273 buf.setNewlineHeading("");
274 return null;
275 }
276
277 public Object visit(WikiPreshaped node, Object data) {
278
279 buf.appendNewline();
280 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
281 buf.append("\t");
282 node.jjtGetChild(i).jjtAccept(this, data);
283 buf.appendNewline();
284 }
285 return null;
286 }
287
288 public Object visit(WikiTable node, Object data) {
289 processTable(node, data);
290 return null;
291 }
292
293 public Object visit(WikiTablecolumn node, Object data) {
294
295 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
296 node.jjtGetChild(i).jjtAccept(this, data);
297 }
298 buf.append("|");
299 return null;
300 }
301
302 public Object visit(WikiTablemember node, Object data) {
303 buf.appendNewline();
304 buf.append("|");
305 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
306 node.jjtGetChild(i).jjtAccept(this, data);
307 }
308 return null;
309 }
310
311 public Object visit(WikiCSVTable node, Object data) {
312 processTable(node, data);
313 return null;
314 }
315
316 public Object visit(WikiHeading node, Object data) {
317
318 buf.appendNewline();
319
320 buf.append("(");
321 for (int i = 0; i < node.level - 1; i++) {
322 buf.append(headerIndex[i] + "-");
323 }
324 buf.append((++headerIndex[node.level - 1]) + ")");
325 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
326 node.jjtGetChild(i).jjtAccept(this, data);
327 }
328
329 for (int i = node.level; i < headerIndex.length; i++) {
330 headerIndex[i] = 0;
331 }
332 return null;
333 }
334
335 public Object visit(WikiAlign node, Object data) {
336 buf.appendNewline();
337 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
338 node.jjtGetChild(i).jjtAccept(this, data);
339 }
340 return null;
341 }
342
343
344 public Object visit(WikiFloatAlign node, Object data) {
345 buf.appendNewline();
346 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
347 node.jjtGetChild(i).jjtAccept(this, data);
348 }
349 return null;
350 }
351
352 public Object visit(WikiHorizontalline node, Object data) {
353 buf.appendNewline();
354 buf.appendRepeatString("-", LINESIZE / 2);
355 return null;
356 }
357
358
359 public Object visit(WikiBlockPlugin node, Object data) {
360 buf.appendNewline();
361 PluginRequest prequest = VisitorUtils.createPluginRequest(node);
362 buf.append("#" + prequest.toString());
363 return null;
364 }
365
366 public Object visit(WikiLetters node, Object data) {
367
368 if (node.isEmail) {
369 buf.append(node.letter);
370 } else if (node.isURL) {
371 buf.append(node.letter);
372 } else if (node.isAnchor) {
373
374 } else if (node.isWikiname) {
375 processSecurityLink(node.letter, node.letter, null);
376 } else if (node.isNewline) {
377 buf.appendNewline();
378 } else {
379 buf.append(node.letter);
380 }
381 return null;
382 }
383
384 public Object visit(WikiAnyOther node, Object data) {
385 buf.append(node.letter);
386 return null;
387 }
388
389 public Object visit(WikiStrongItalic node, Object data) {
390 buf.append("''");
391 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
392 node.jjtGetChild(i).jjtAccept(this, data);
393 }
394 buf.append("''");
395 return null;
396 }
397
398 public Object visit(WikiDeleteline node, Object data) {
399 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
400 node.jjtGetChild(i).jjtAccept(this, data);
401 }
402 return null;
403 }
404
405 public Object visit(WikiAnnotation node, Object data) {
406 buf.append("(*" + node.num + ")");
407 return null;
408 }
409
410 public Object visit(WikiInterwiki node, Object data) {
411 buf.append("[[" + node.image + "]]");
412 return null;
413 }
414
415 public Object visit(WikiLink node, Object data) {
416
417 String[] s = WikiHelper.split(node.image, WikiHelper.LINK_DELIMITER);
418 buf.appendLink(s[0], s[1]);
419 return null;
420 }
421
422 public Object visit(WikiAlias node, Object data) {
423 String[] s = WikiHelper.split(node.image, WikiHelper.ALIAS_DELIMITER);
424
425 if (node.islink) {
426 buf.appendLink(s[0], s[1]);
427 } else {
428 String[] t = WikiHelper.split(s[1], WikiHelper.ANCHOR_MARK);
429 if (t[0] == null || t[0].equals("")) {
430 buf.appendLink(s[0], WikiHelper.ANCHOR_MARK + t[1]);
431 } else {
432 processSecurityLink(t[0], s[0], t[1]);
433 }
434 }
435 return null;
436 }
437
438 public Object visit(WikiPagename node, Object data) {
439 String[] s = WikiHelper.split(node.image, WikiHelper.ANCHOR_MARK);
440 processSecurityLink(s[0], s[0], s[1]);
441 return null;
442 }
443
444 public Object visit(WikiInlinePlugin node, Object data) {
445
446 String name = node.name;
447
448 boolean ispluginused = false;
449 int inlinestart = 0;
450 PluginRequest prequest = VisitorUtils.createPluginRequest(node);
451 if (prequest.getArgs() != null)
452 inlinestart = 1;
453
454 String childstr = getChildString(node, data, inlinestart);
455 prequest.setChild(childstr);
456
457 if (config.isPluginLoaded(name)) {
458 Plugin plugin = config.getPlugin(name);
459 try {
460 buf
461 .append((String) plugin.service(request, response,
462 prequest));
463 ispluginused = true;
464 } catch (PluginException pe) {
465 log.error(pe.getMessage());
466 } catch (Exception e) {
467 e.printStackTrace();
468
469 }
470 }
471
472 if (!ispluginused) {
473 buf.append("&" + prequest.toString() + ";");
474 }
475 return null;
476 }
477
478 public Object visit(WikiArgs node, Object data) {
479 return null;
480 }
481
482 public Object visit(WikiErrors node, Object data) {
483 appendError(node.letter);
484 return null;
485 }
486
487 private void appendError(String str) {
488 buf.append(" *(" + str + ")* ");
489 }
490
491 private void processSecurityLink(String pagename, String body, String anchor) {
492 try {
493 if (ctx.isPageExist(pagename, request)) {
494 Resource resource = ctx.getResource(request, pagename);
495 if (resource.isFolder()) {
496 if (!pagename.endsWith("/"))
497 pagename = pagename + "/";
498 }
499 URL url = ctx.getURLByName(pagename, request);
500 if (anchor == null || "".equals(anchor)) {
501 buf.appendLink(body, url.toString());
502 } else {
503 buf.appendLink(body, url.toString()
504 + WikiHelper.ANCHOR_MARK + anchor);
505 }
506 } else {
507 URL url = ctx.getCreatePageURL(pagename, request);
508 buf.appendLink("?" + body, url.toString());
509 }
510 } catch (TgwSecurityException tse) {
511 buf.append(body);
512 }
513 }
514
515 private void startList(int type, int level) {
516
517 }
518
519 private void endList(int type, int level) {
520 if (type == WikiHelper.LIST_TYPE_NUMERICAL) {
521 listIndex[level - 1] = 0;
522 }
523 }
524
525 private void endAllList() {
526 for (int i = 0; i < listIndex.length; i++) {
527 listIndex[i] = 0;
528 }
529 buf.setNewlineHeading("");
530 }
531
532 private String getChildString(SimpleNode node, Object data, int idx) {
533 int start = buf.nextIndex();
534 String childstr = null;
535 for (int i = idx; i < node.jjtGetNumChildren(); i++) {
536 node.jjtGetChild(i).jjtAccept(this, data);
537 }
538 int end = buf.nextIndex();
539 if (start != end)
540 childstr = buf.cut(start, end);
541 return childstr;
542 }
543
544 private void processTable(SimpleNode node, Object data) {
545
546 VisitorUtils.prepareWikiTable(node, data);
547 int prenum = 0;
548 int start = buf.nextIndex();
549 int end = buf.nextIndex();
550 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
551 if (node.jjtGetChild(i) instanceof WikiTablemember) {
552 if (node.jjtGetChild(i).jjtGetNumChildren() != prenum) {
553 if (prenum != 0) {
554 adjust(start, end);
555 }
556 start = buf.nextIndex();
557
558 }
559 } else {
560 adjust(start, end);
561 prenum = 0;
562 continue;
563 }
564 prenum = node.jjtGetChild(i).jjtGetNumChildren();
565 node.jjtGetChild(i).jjtAccept(this, data);
566 end = buf.nextIndex();
567 }
568 adjust(start, end);
569 }
570
571 private void adjust(int start, int end) {
572
573 if (end > start) {
574 String str = buf.cut(start, end);
575 String[] lines = str.split("\n");
576 int maxlength = getMaxlength(lines);
577 int[] maxcolsize = getMaxcolsize(lines);
578
579 String decorator = getRepeatedString("-", maxlength);
580
581 buf.appendNewline();
582 buf.append(decorator);
583 buf.appendNewline();
584 for (int i = 0; i < lines.length; i++) {
585 if (!lines[i].equals("")) {
586 String[] cols = lines[i].split("//|");
587 for (int j = 0; j < cols.length; j++) {
588 String col = cols[j];
589 buf.append(col);
590 buf.appendRepeatString(" ", maxcolsize[j]
591 - col.getBytes().length);
592 buf.append("|");
593 }
594 buf.appendNewline();
595 buf.append(decorator);
596 buf.appendNewline();
597 }
598 }
599 }
600 }
601
602 private int getMaxlength(String[] lines) {
603 int maxlength = 0;
604 for (int i = 0; i < lines.length; i++) {
605 int size = lines[i].getBytes().length;
606 if (maxlength < size) {
607 maxlength = size;
608 }
609 }
610 return maxlength;
611 }
612
613 private int[] getMaxcolsize(String[] lines) {
614
615 int[] maxcolsize = null;
616 boolean first = true;
617 for (int i = 0; i < lines.length; i++) {
618 if (!"".equals(lines[i])) {
619 String[] cols = lines[i].split("//|");
620 if (first) {
621 maxcolsize = new int[cols.length];
622 first = false;
623 }
624
625 for (int j = 0; j < cols.length; j++) {
626 int size = cols[j].getBytes().length;
627 if (maxcolsize[j] < size) {
628 maxcolsize[j] = size;
629 }
630 }
631 }
632 }
633 return maxcolsize;
634 }
635
636 private String getRepeatedString(String str, int num) {
637 StringBuffer buf = new StringBuffer();
638 for (int i = 0; i < num; i++) {
639 buf.append(str);
640 }
641 return buf.toString();
642 }
643 }