1 package org.apache.maven.doxia.module.confluence.parser;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.codehaus.plexus.util.StringUtils;
26
27
28
29
30
31
32
33
34
35
36 public class ChildBlocksBuilder
37 {
38 private boolean insideBold = false;
39
40 private boolean insideItalic = false;
41
42 private boolean insideLink = false;
43
44 private List<Block> blocks = new ArrayList<Block>();
45
46 private StringBuffer text = new StringBuffer();
47
48 private String input;
49
50 private boolean insideMonospaced;
51
52
53
54
55
56
57 public ChildBlocksBuilder( String input )
58 {
59 this.input = input;
60 }
61
62
63
64
65
66
67 public List<Block> getBlocks()
68 {
69 List<Block> specialBlocks = new ArrayList<Block>();
70
71 for ( int i = 0; i < input.length(); i++ )
72 {
73 char c = input.charAt( i );
74
75 switch ( c )
76 {
77 case '*':
78 if ( insideBold )
79 {
80 insideBold = false;
81 specialBlocks = getList( new BoldBlock( getChildren( text, specialBlocks ) ), specialBlocks );
82 text = new StringBuffer();
83 }
84 else
85 {
86 text = addTextBlockIfNecessary( blocks, specialBlocks, text );
87 insideBold = true;
88 }
89
90 break;
91 case '_':
92 if ( insideItalic )
93 {
94 insideItalic = false;
95 specialBlocks = getList( new ItalicBlock( getChildren( text, specialBlocks ) ), specialBlocks );
96 text = new StringBuffer();
97 }
98 else
99 {
100 text = addTextBlockIfNecessary( blocks, specialBlocks, text );
101 insideItalic = true;
102 }
103
104 break;
105 case '[':
106 insideLink = true;
107 text = addTextBlockIfNecessary( blocks, specialBlocks, text );
108 break;
109 case ']':
110 if ( insideLink )
111 {
112 boolean addHTMLSuffix = false;
113 String link = text.toString();
114
115 if ( !link.endsWith( ".html" ) )
116 {
117 if ( link.indexOf( "http" ) < 0 )
118 {
119 addHTMLSuffix = true;
120 }
121 }
122 if ( link.indexOf( "|" ) > 0 )
123 {
124 String[] pieces = StringUtils.split( text.toString(), "|" );
125
126 if ( addHTMLSuffix )
127 {
128 if ( pieces[1].indexOf( "#" ) < 0 )
129 {
130 pieces[1] = pieces[1].concat( ".html" );
131 }
132 else
133 {
134 if ( !pieces[1].startsWith( "#" ) )
135 {
136 String[] temp = pieces[1].split( "#" );
137 pieces[1] = temp[0] + ".html#" + temp[1];
138 }
139 }
140 }
141
142 blocks.add( new LinkBlock( pieces[1], pieces[0] ) );
143 }
144 else
145 {
146 String value = link;
147
148 if ( link.startsWith( "#" ) )
149 {
150 value = link.substring( 1 );
151 }
152
153 if ( addHTMLSuffix )
154 {
155 if ( link.indexOf( "#" ) < 0 )
156 {
157 link = link.concat( ".html" );
158 }
159 else
160 {
161 if ( !link.startsWith( "#" ) )
162 {
163 String[] temp = link.split( "#" );
164 link = temp[0] + ".html#" + temp[1];
165 }
166 }
167 }
168
169 blocks.add( new LinkBlock( link, value ) );
170 }
171
172 text = new StringBuffer();
173 insideLink = false;
174 }
175
176 break;
177 case '{':
178
179 text = addTextBlockIfNecessary( blocks, specialBlocks, text );
180
181 if ( charAt( input, i ) == '{' )
182 {
183 i++;
184 insideMonospaced = true;
185 }
186
187
188 break;
189 case '}':
190
191
192
193 if ( charAt( input, i ) == '}' )
194 {
195 i++;
196 insideMonospaced = false;
197 specialBlocks = getList( new MonospaceBlock( getChildren( text, specialBlocks ) ),
198 specialBlocks );
199 text = new StringBuffer();
200 }
201 else
202 {
203 String name = text.toString();
204 if ( name.startsWith( "anchor:" ) )
205 {
206 blocks.add( new AnchorBlock( name.substring( "anchor:".length() ) ) );
207 }
208 else
209 {
210 blocks.add( new TextBlock( "{" + name + "}" ) );
211 }
212 text = new StringBuffer();
213 }
214
215 break;
216 case '\\':
217
218
219
220 if ( charAt( input, i ) == '\\' )
221 {
222 i++;
223 text = addTextBlockIfNecessary( blocks, specialBlocks, text );
224 blocks.add( new LinebreakBlock() );
225 }
226 else
227 {
228 i++;
229 text.append( input.charAt( i ) );
230 }
231
232 break;
233 default:
234 text.append( c );
235 }
236
237 if ( !specialBlocks.isEmpty() )
238 {
239 if ( !insideItalic && !insideBold && !insideMonospaced )
240 {
241 blocks.addAll( specialBlocks );
242 specialBlocks.clear();
243 }
244 }
245
246 }
247
248 if ( text.length() > 0 )
249 {
250 blocks.add( new TextBlock( text.toString() ) );
251 }
252
253 return blocks;
254 }
255
256 private List<Block> getList( Block block, List<Block> currentBlocks )
257 {
258 List<Block> list = new ArrayList<Block>();
259
260 if ( insideBold || insideItalic || insideMonospaced )
261 {
262 list.addAll( currentBlocks );
263 }
264
265 list.add( block );
266
267 return list;
268 }
269
270 private List<Block> getChildren( StringBuffer buffer, List<Block> currentBlocks )
271 {
272 String txt = buffer.toString().trim();
273
274 if ( currentBlocks.isEmpty() && StringUtils.isEmpty( txt ) )
275 {
276 return new ArrayList<Block>();
277 }
278
279 ArrayList<Block> list = new ArrayList<Block>();
280
281 if ( !insideBold && !insideItalic && !insideMonospaced )
282 {
283 list.addAll( currentBlocks );
284 }
285
286 if ( StringUtils.isEmpty( txt ) )
287 {
288 return list;
289 }
290
291 list.add( new TextBlock( txt ) );
292
293 return list;
294 }
295
296 private static char charAt( String input, int i )
297 {
298 return input.length() > i + 1 ? input.charAt( i + 1 ) : '\0';
299 }
300
301 private StringBuffer addTextBlockIfNecessary( List<Block> blcks, List<Block> specialBlocks, StringBuffer txt )
302 {
303 if ( txt.length() == 0 )
304 {
305 return txt;
306 }
307
308 TextBlock textBlock = new TextBlock( txt.toString() );
309
310 if ( !insideBold && !insideItalic && !insideMonospaced )
311 {
312 blcks.add( textBlock );
313 }
314 else
315 {
316 specialBlocks.add( textBlock );
317 }
318
319 return new StringBuffer();
320 }
321
322 }