1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package oqube.muse;
37
38 import java.util.regex.Pattern;
39 import java.util.regex.Matcher;
40 import java.util.List;
41
42 /***
43 * This lexer wraps another sink to format accumulated text lines.
44 *
45 * A flow lexer wraps the {@link MuseSink} methods so that the string gets
46 * proper formatting for inline (or *flow*) elements that appear in this block.
47 * The basic idea is then to let block lexers call the wrapped sink methods
48 * instead of the real methods. When {@link MuseSink.text(String)} method is
49 * called, this indicates that parsing is inside a block level element so text
50 * gets accumulated in an internal buffer.
51 *
52 * When any block level method is called on this sink, the chain of lexer is
53 * asked to format the accumulated text: this text is parsed for appropriate
54 * patterns and each lexer as a chance to do something with matching framgments.
55 *
56 * Note that the order of lexers in the chain may be important. It is customary
57 * to add the {@see IdentityLexer} at the bottom of the stack to pass final
58 * nested text elements to wrapped sink.
59 *
60 *
61 * @author abailly@oqube.muse.com
62 * @version $Id$
63 */
64 public abstract class FlowLexer extends AbstractLexer implements MuseSink {
65
66 protected StringBuffer text;
67
68
69 private MuseSink wrappedSink;
70
71 /***
72 * Returns the wrapped sink.
73 *
74 * @return a wrapped MuseSink instance.
75 */
76 public MuseSink getWrappedSink() {
77 return wrappedSink;
78 }
79
80 /***
81 * Sets the sink to wrap for this lexer.
82 *
83 * @param wrappedSink
84 * the Sink to wrap.
85 */
86 public void setWrappedSink(MuseSink wrappedSink) {
87 this.wrappedSink = wrappedSink;
88 if (next != null)
89 ((FlowLexer) next).setWrappedSink(wrappedSink);
90 }
91
92 /***
93 * Construct a new FlowLexer for given pattern.
94 *
95 * @param pattern
96 * the pattern that this lexer matches.
97 * @see java.util.regex.Pattern
98 */
99 public FlowLexer(String pattern) {
100 super(pattern);
101 }
102
103 public void setLineWidth(int lw) {
104 }
105
106 public void startPara() {
107 wrappedSink.startPara();
108 }
109
110 /***
111 * Accumulates text in this lexer. Note that this method is used only in the
112 * first lexer of the chain.
113 */
114 public void text(String txt) {
115
116 if (text == null)
117 text = new StringBuffer();
118
119 Pattern p = Pattern.compile("^(.*)-$");
120 Matcher m = p.matcher(txt);
121 if (m.matches())
122 text.append(m.group(1));
123 else
124 text.append(txt).append(' ');
125 }
126
127 public void rawText(String text) {
128 wrappedSink.rawText(text);
129 }
130
131
132
133
134
135 protected void format(String s) {
136 int i = 0;
137
138 matcher.reset(s);
139 while (matcher.find()) {
140
141 int st = matcher.start();
142 if (st > i) {
143 String sub = s.substring(i, st);
144
145 assert next != null;
146 ((FlowLexer) next).format(sub);
147 }
148 handler();
149 i = matcher.end();
150 }
151
152 if (i > 0 && i < s.length() - 2) {
153
154 assert s.substring(i).length() > 0;
155 ((FlowLexer) next).format(s.substring(i));
156 } else if (i == 0 && s.length() > 0) {
157 assert s.substring(i).length() > 0;
158 ((FlowLexer) next).format(s);
159 }
160 }
161
162 public void endPara() {
163 if (text != null) {
164 format(text.toString());
165 text = null;
166 }
167 wrappedSink.endPara();
168 }
169
170 public void startList() {
171 if (text != null) {
172 format(text.toString());
173 text = null;
174 }
175 wrappedSink.startList();
176 }
177
178 public void endList() {
179 wrappedSink.endList();
180 }
181
182 public void startItem() {
183 if (text != null) {
184 format(text.toString());
185 text = null;
186 }
187 wrappedSink.startItem();
188 }
189
190 public void endItem() {
191 if (text != null) {
192 format(text.toString());
193 text = null;
194 }
195 wrappedSink.endItem();
196 }
197
198 public void startQuote() {
199 if (text != null) {
200 format(text.toString());
201 text = null;
202 }
203 wrappedSink.startQuote();
204 }
205
206 public void endQuote() {
207 if (text != null) {
208 format(text.toString());
209 text = null;
210 }
211 wrappedSink.endQuote();
212 }
213
214 public void startCenter() {
215 if (text != null) {
216 format(text.toString());
217 text = null;
218 }
219 wrappedSink.startCenter();
220 }
221
222 public void endCenter() {
223 if (text != null) {
224 format(text.toString());
225 text = null;
226 }
227 wrappedSink.endCenter();
228 }
229
230 public void startEnums() {
231 if (text != null) {
232 format(text.toString());
233 text = null;
234 }
235 wrappedSink.startEnums();
236 }
237
238 public void endEnums() {
239 if (text != null) {
240 format(text.toString());
241 text = null;
242 }
243 wrappedSink.endEnums();
244 }
245
246 public void startDocument() {
247 wrappedSink.startDocument();
248 }
249
250 public void endDocument() {
251 if (text != null) {
252 format(text.toString());
253 text = null;
254 }
255 wrappedSink.startDocument();
256 }
257
258 public void startHeader() {
259 wrappedSink.startHeader();
260 }
261
262 public void endHeader() {
263 wrappedSink.endHeader();
264 }
265
266 public void startBody() {
267 wrappedSink.startBody();
268 }
269
270 public void endBody() {
271 wrappedSink.endBody();
272 }
273
274 public void startFooter() {
275 wrappedSink.startFooter();
276 }
277
278 public void endFooter() {
279 wrappedSink.endFooter();
280 }
281
282 public void startEmph() {
283 wrappedSink.startEmph();
284 }
285
286 public void endEmph() {
287 wrappedSink.endEmph();
288 }
289
290 public void startStrong() {
291 wrappedSink.startStrong();
292 }
293
294 public void endStrong() {
295 wrappedSink.endStrong();
296 }
297
298 public void startUline() {
299 wrappedSink.startUline();
300 }
301
302 public void endUline() {
303 wrappedSink.endUline();
304 }
305
306 public void startVerb() {
307 wrappedSink.startVerb();
308 }
309
310 public void endVerb() {
311 wrappedSink.endVerb();
312 }
313
314 public void flow(String s, String content) {
315 wrappedSink.flow(s, content);
316 }
317
318 public void block(String s, String content) {
319 wrappedSink.block(s, content);
320 }
321
322 public void startTitle1() {
323 wrappedSink.startTitle1();
324 }
325
326 public void endTitle1() {
327 if (text != null) {
328 format(text.toString());
329 text = null;
330 }
331 wrappedSink.endTitle1();
332 }
333
334 public void startTitle2() {
335 wrappedSink.startTitle2();
336 }
337
338 public void endTitle2() {
339 if (text != null) {
340 format(text.toString());
341 text = null;
342 }
343 wrappedSink.endTitle2();
344 }
345
346 public void startTitle3() {
347 wrappedSink.startTitle3();
348 }
349
350 public void endTitle3() {
351 if (text != null) {
352 format(text.toString());
353 text = null;
354 }
355 wrappedSink.endTitle3();
356 }
357
358 public void startTitle4() {
359 wrappedSink.startTitle4();
360 }
361
362 public void endTitle4() {
363 if (text != null) {
364 format(text.toString());
365 text = null;
366 }
367 wrappedSink.endTitle4();
368 }
369
370 public void startTableData() {
371 wrappedSink.startTableData();
372 }
373
374 public void endTableData() {
375 if (text != null) {
376 format(text.toString());
377 text = null;
378 }
379 wrappedSink.endTableData();
380 }
381
382 public void startTableHeader() {
383 wrappedSink.startTableHeader();
384 }
385
386 public void endTableHeader() {
387 if (text != null) {
388 format(text.toString());
389 text = null;
390 }
391 wrappedSink.endTableHeader();
392 }
393
394
395
396
397
398
399 public void endTable() {
400 wrappedSink.endTable();
401 }
402
403
404
405
406
407
408 public void startTable() {
409 if (text != null) {
410 format(text.toString());
411 text = null;
412 }
413 wrappedSink.startTable();
414 }
415
416
417
418
419 public void endTableRow() {
420 wrappedSink.endTableRow();
421 }
422
423
424
425
426 public void startTableRow() {
427 wrappedSink.startTableRow();
428 }
429
430 public void link(String s, String t) {
431 wrappedSink.link(s, t);
432 }
433
434 public void anchor(String s) {
435 wrappedSink.anchor(s);
436 }
437
438 public void addMetadata(String s, String t) {
439 wrappedSink.addMetadata(s, t);
440 }
441
442 public void separator() {
443 wrappedSink.separator();
444 }
445
446 }