View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.cms.core.pdf;
17  
18  import java.io.IOException;
19  import java.io.Reader;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  
23  import com.lowagie.text.Chunk;
24  import com.lowagie.text.DocListener;
25  import com.lowagie.text.Element;
26  import com.lowagie.text.ExceptionConverter;
27  import com.lowagie.text.ListItem;
28  import com.lowagie.text.Paragraph;
29  import com.lowagie.text.Phrase;
30  import com.lowagie.text.TextElementArray;
31  import com.lowagie.text.html.simpleparser.HTMLWorker;
32  import com.lowagie.text.html.simpleparser.IncCell;
33  import com.lowagie.text.html.simpleparser.IncTable;
34  import com.lowagie.text.html.simpleparser.StyleSheet;
35  import com.lowagie.text.pdf.PdfPTable;
36  
37  
38  /***
39   * Extends HTMLWorker to use CJKFactoryProperties instead of 
40   * FactoryProperties while parsing.
41   * 
42   * @author someda
43   */
44  public class CJKHTMLWorker extends HTMLWorker {
45  
46  	public CJKHTMLWorker(DocListener doc){
47  		super(doc);
48  	}
49  	
50      public static ArrayList parseToList(Reader reader, StyleSheet style) throws IOException {
51          CJKHTMLWorker worker = new CJKHTMLWorker(null);
52          if (style != null)
53              worker.style = style;
54          worker.document = worker;
55          worker.objectList = new ArrayList();
56          worker.parse(reader);
57          return worker.objectList;
58      }
59  	
60      public void startElement(String tag, HashMap h) {
61          if (!tagsSupported.containsKey(tag))
62              return;
63          style.applyStyle(tag, h);
64          String follow = (String)CJKFactoryProperties.followTags.get(tag);
65          if (follow != null) {
66              HashMap prop = new HashMap();
67              prop.put(follow, null);
68              cprops.addToChain(follow, prop);
69              return;
70          }
71          if (tag.equals("a")) {
72              cprops.addToChain(tag, h);
73              if (currentParagraph == null)
74                  currentParagraph = new Paragraph();
75              stack.push(currentParagraph);
76              currentParagraph = new Paragraph();
77              return;
78          }
79          if (tag.equals("br")) {
80              if (currentParagraph == null)
81                  currentParagraph = new Paragraph();
82              currentParagraph.add(CJKFactoryProperties.createChunk("\n", cprops));
83              return;
84          }
85          if (tag.equals("font") || tag.equals("span")) {
86              cprops.addToChain(tag, h);
87              return;
88          }
89          endElement("p");
90          if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
91              if (!h.containsKey("size"))
92                  h.put("size", tag.substring(1));
93              cprops.addToChain(tag, h);
94              return;
95          }
96          if (tag.equals("ul")) {
97              if (pendingLI)
98                  endElement("li");
99              skipText = true;
100             cprops.addToChain(tag, h);
101             com.lowagie.text.List list = new com.lowagie.text.List(false, 10);
102             list.setListSymbol("\u2022");
103             stack.push(list);
104             return;
105         }
106         if (tag.equals("ol")) {
107             if (pendingLI)
108                 endElement("li");
109             skipText = true;
110             cprops.addToChain(tag, h);
111             com.lowagie.text.List list = new com.lowagie.text.List(true, 10);
112             stack.push(list);
113             return;
114         }
115         if (tag.equals("li")) {
116             if (pendingLI)
117                 endElement("li");
118             skipText = false;
119             pendingLI = true;
120             cprops.addToChain(tag, h);
121             stack.push(new com.lowagie.text.ListItem());
122             return;
123         }
124         if (tag.equals("div") || tag.equals("body")) {
125             cprops.addToChain(tag, h);
126             return;
127         }
128         if (tag.equals("pre")) {
129             if (!h.containsKey("face")) {
130                 h.put("face", "Courier");
131             }
132             cprops.addToChain(tag, h);
133             isPRE = true;
134             return;
135         }
136         if (tag.equals("p")) {
137             cprops.addToChain(tag, h);
138             currentParagraph = CJKFactoryProperties.createParagraph(h);
139             return;
140         }
141         if (tag.equals("tr")) {
142             if (pendingTR)
143                 endElement("tr");
144             skipText = true;
145             pendingTR = true;
146             cprops.addToChain("tr", h);
147             return;
148         }
149         if (tag.equals("td") || tag.equals("th")) {
150             if (pendingTD)
151                 endElement(tag);
152             skipText = false;
153             pendingTD = true;
154             cprops.addToChain("td", h);
155             stack.push(new IncCell(tag, cprops));
156             return;
157         }
158         if (tag.equals("table")) {
159             cprops.addToChain("table", h);
160             IncTable table = new IncTable(h);
161             stack.push(table);
162             tableState.push(new boolean[]{pendingTR, pendingTD});
163             pendingTR = pendingTD = false;
164             skipText = true;
165             return;
166         }
167     }
168     
169     public void endElement(String tag) {
170         if (!tagsSupported.containsKey(tag))
171             return;
172         try {
173             String follow = (String)CJKFactoryProperties.followTags.get(tag);
174             if (follow != null) {
175                 cprops.removeChain(follow);
176                 return;
177             }
178             if (tag.equals("font") || tag.equals("span")) {
179                 cprops.removeChain(tag);
180                 return;
181             }
182             if (tag.equals("a")) {
183                 String href = cprops.getProperty("href");
184                 if (currentParagraph == null)
185                     currentParagraph = new Paragraph();
186                 if (href != null) {
187                     ArrayList chunks = currentParagraph.getChunks();
188                     for (int k = 0; k < chunks.size(); ++k) {
189                         Chunk ck = (Chunk)chunks.get(k);
190                         ck.setAnchor(href);
191                     }
192                 }
193                 Paragraph tmp = (Paragraph)stack.pop();
194                 Phrase tmp2 = new Phrase();
195                 tmp2.add(currentParagraph);
196                 tmp.add(tmp2);
197                 currentParagraph = tmp;
198                 cprops.removeChain("a");
199                 return;
200             }
201             if (tag.equals("br")) {
202                 return;
203             }
204             if (currentParagraph != null) {
205                 if (stack.empty())
206                     document.add(currentParagraph);
207                 else {
208                     Object obj = stack.pop();;
209                     if (obj instanceof TextElementArray) {
210                         TextElementArray current = (TextElementArray)obj;
211                         current.add(currentParagraph);
212                     }
213                     stack.push(obj);
214                 }
215             }
216             currentParagraph = null;
217             if (tag.equals("ul") || tag.equals("ol")) {
218                 if (pendingLI)
219                     endElement("li");
220                 skipText = false;
221                 cprops.removeChain(tag);
222                 if (stack.empty())
223                     return;
224                 Object obj = stack.pop();
225                 if (!(obj instanceof com.lowagie.text.List)) {
226                     stack.push(obj);
227                     return;
228                 }
229                 if (stack.empty())
230                     document.add((Element)obj);
231                 else
232                     ((TextElementArray)stack.peek()).add(obj);
233                 return;
234             }
235             if (tag.equals("li")) {
236                 pendingLI = false;
237                 skipText = true;
238                 cprops.removeChain(tag);
239                 if (stack.empty())
240                     return;
241                 Object obj = stack.pop();
242                 if (!(obj instanceof ListItem)) {
243                     stack.push(obj);
244                     return;
245                 }
246                 if (stack.empty()) {
247                     document.add((Element)obj);
248                     return;
249                 }
250                 Object list = stack.pop();
251                 if (!(list instanceof com.lowagie.text.List)) {
252                     stack.push(list);
253                     return;
254                 }
255                 ListItem item = (ListItem)obj;
256                 ((com.lowagie.text.List)list).add(item);
257                 ArrayList cks = item.getChunks();
258                 if (cks.size() > 0)
259                     item.listSymbol().setFont(((Chunk)cks.get(0)).font());
260                 stack.push(list);
261                 return;
262             }
263             if (tag.equals("div") || tag.equals("body")) {
264                 cprops.removeChain(tag);
265                 return;
266             }
267             if (tag.equals("pre")) {
268                 cprops.removeChain(tag);
269                 isPRE = false;
270                 return;
271             }
272             if (tag.equals("p")) {
273                 cprops.removeChain(tag);
274                 pendingP = false;
275                 return;
276             }
277             if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
278                 cprops.removeChain(tag);
279                 return;
280             }
281             if (tag.equals("table")) {
282                 if (pendingTR)
283                     endElement("tr");
284                 cprops.removeChain("table");
285                 IncTable table = (IncTable) stack.pop();
286                 PdfPTable tb = table.buildTable();
287                 tb.setSplitRows(true);
288                 if (stack.empty())
289                     document.add(tb);
290                 else
291                     ((TextElementArray)stack.peek()).add(tb);
292                 boolean state[] = (boolean[])tableState.pop();
293                 pendingTR = state[0];
294                 pendingTD = state[1];
295                 skipText = false;
296                 return;
297             }
298             if (tag.equals("tr")) {
299                 if (pendingTD)
300                     endElement("td");
301                 pendingTR = false;
302                 cprops.removeChain("tr");
303                 ArrayList cells = new ArrayList();
304                 IncTable table = null;
305                 while (true) {
306                     Object obj = stack.pop();
307                     if (obj instanceof IncCell) {
308                         cells.add(((IncCell)obj).getCell());
309                     }
310                     if (obj instanceof IncTable) {
311                         table = (IncTable)obj;
312                         break;
313                     }
314                 }
315                 table.addCols(cells);
316                 table.endRow();
317                 stack.push(table);
318                 skipText = true;
319                 return;
320             }
321             if (tag.equals("td") || tag.equals("th")) {
322                 pendingTD = false;
323                 cprops.removeChain("td");
324                 skipText = true;
325                 return;
326             }
327         }
328         catch (Exception e) {
329             throw new ExceptionConverter(e);
330         }
331     }
332     
333     public void text(String str) {
334         if (skipText)
335             return;
336         String content = str;
337         if (isPRE) {
338             if (currentParagraph == null)
339                 currentParagraph = new Paragraph();
340             currentParagraph.add(CJKFactoryProperties.createChunk(content, cprops));
341             return;
342         }
343         if (content.trim().length() == 0 && content.indexOf(' ') < 0) {
344             return;
345         }
346         
347         StringBuffer buf = new StringBuffer();
348         int len = content.length();
349         char character;
350         boolean newline = false;
351         for (int i = 0; i < len; i++) {
352             switch(character = content.charAt(i)) {
353                 case ' ':
354                     if (!newline) {
355                         buf.append(character);
356                     }
357                     break;
358                 case '\n':
359                     if (i > 0) {
360                         newline = true;
361                         buf.append(' ');
362                     }
363                     break;
364                 case '\r':
365                     break;
366                 case '\t':
367                     break;
368                     default:
369                         newline = false;
370                         buf.append(character);
371             }
372         }
373         if (currentParagraph == null)
374             currentParagraph = CJKFactoryProperties.createParagraph(cprops);
375         currentParagraph.add(CJKFactoryProperties.createChunk(buf.toString(), cprops));
376     }
377 	
378 }