001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.format.render.bbcodehtml;
023:
024: import org.jboss.portal.format.parser.ParseEvent;
025: import org.jboss.portal.format.parser.ParseEventHandler;
026: import org.jboss.portal.format.parser.TextEvent;
027: import org.jboss.portal.format.parser.bbcode.BBCodeParser;
028: import org.jboss.portal.format.parser.entity.CharacterEntityReferenceEvent;
029: import org.jboss.portal.format.parser.entity.HTML4_0CharacterEntityReferenceParser;
030: import org.jboss.portal.format.parser.entity.XML1_0CharacterEntityReferenceParser;
031: import org.jboss.portal.format.parser.html.TagParser;
032: import org.jboss.portal.format.parser.linebreak.LineBreakParser;
033: import org.jboss.portal.format.render.AbstractRenderer;
034: import org.jboss.portal.format.template.DelegateContext;
035:
036: import java.util.ResourceBundle;
037:
038: /**
039: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
040: * @version $Revision: 8784 $
041: */
042: public class ToHTMLRenderer extends AbstractRenderer {
043:
044: /*
045: * Different parsers.
046: */
047:
048: private final BBCodeParser codeParser = new BBCodeParser();
049: private final TagParser tagParser = new TagParser();
050: private final XML1_0CharacterEntityReferenceParser XMLCERP = new XML1_0CharacterEntityReferenceParser();
051: private final HTML4_0CharacterEntityReferenceParser HTMLCERP = new HTML4_0CharacterEntityReferenceParser();
052: private final LineBreakParser lineBreakParser = new LineBreakParser();
053:
054: /** Context used by the code handler templates. */
055: private final DelegateContext ctx = new DelegateContext();
056:
057: /** Code depth. */
058: private int isInPre = 0;
059:
060: /** Config. */
061: private ToHTMLConfig config;
062:
063: /*
064: * Templates.
065: */
066:
067: /** Setup the renderer with the given template repository. */
068: public ToHTMLRenderer(ToHTMLConfig config, ResourceBundle bundle) {
069: if (config == null) {
070: throw new IllegalArgumentException("no config");
071: }
072: if (bundle == null) {
073: throw new IllegalArgumentException("no bundle");
074: }
075: this .config = config;
076: codeParser.setHandler(bbCodeHandler);
077: tagParser.setHandler(tagHandler);
078: XMLCERP.setHandler(XMLCRPHandler);
079: HTMLCERP.setHandler(HTMLCRPHandler);
080: lineBreakParser.setHandler(lineBreakHandler);
081: ctx.put("L_CODE", bundle
082: .getString(BBCodeParser.BUNDLE_KEY_CODE));
083: ctx.put("L_QUOTE", bundle
084: .getString(BBCodeParser.BUNDLE_KEY_QUOTE));
085: ctx.put("L_WROTE", bundle
086: .getString(BBCodeParser.BUNDLE_KEY_WROTE));
087: }
088:
089: public ToHTMLRenderer(ResourceBundle bundle) {
090: this (new ToHTMLConfig(), bundle);
091: }
092:
093: public ToHTMLConfig getConfig() {
094: return config;
095: }
096:
097: public void setConfig(ToHTMLConfig config) {
098: this .config = config;
099: }
100:
101: public void render(char[] chars, int offset, int length) {
102: codeParser.parse(chars, offset, length);
103: }
104:
105: public ParseEventHandler bbCodeHandler = new ParseEventHandler() {
106: public void handle(ParseEvent event) {
107: if (event instanceof BBCodeParser.OpenEvent) {
108: BBCodeParser.OpenEvent openEvent = (BBCodeParser.OpenEvent) event;
109: String string = openEvent.getString();
110: switch (openEvent.getType()) {
111: case BBCodeParser.EVENT_BOLD:
112: config.r_b_open.render(ctx, writer);
113: break;
114: case BBCodeParser.EVENT_ITALIC:
115: config.r_i_open.render(ctx, writer);
116: break;
117: case BBCodeParser.EVENT_UNDERLINE:
118: config.r_u_open.render(ctx, writer);
119: break;
120: case BBCodeParser.EVENT_COLOR:
121: ctx.put("COLOR", string);
122: config.r_color_open.render(ctx, writer);
123: break;
124: case BBCodeParser.EVENT_SIZE:
125: ctx.put("SIZE", string);
126: config.r_size_open.render(ctx, writer);
127: break;
128: case BBCodeParser.EVENT_QUOTE:
129: if (string == null) {
130: config.r_quote_open.render(ctx, writer);
131: } else {
132: ctx.put("USERNAME", string);
133: config.r_quote_username_open
134: .render(ctx, writer);
135: }
136: break;
137: case BBCodeParser.EVENT_CODE:
138: isInPre++;
139: config.r_code_open.render(ctx, writer);
140: break;
141: case BBCodeParser.EVENT_UNORDERED_LIST:
142: config.r_ulist_open.render(ctx, writer);
143: break;
144: case BBCodeParser.EVENT_NUMERICALLY_ORDERED_LIST:
145: ctx.put("LIST_TYPE", "1");
146: config.r_olist_open.render(ctx, writer);
147: break;
148: case BBCodeParser.EVENT_ALPHABETICALLY_ORDERED_LIST:
149: ctx.put("LIST_TYPE", "a");
150: config.r_olist_open.render(ctx, writer);
151: break;
152: case BBCodeParser.EVENT_ITEM:
153: config.r_listitem.render(ctx, writer);
154: break;
155: case BBCodeParser.EVENT_LINK:
156: ctx.put("URL", string);
157: ctx.put("DESCRIPTION", string);
158: config.r_url.render(ctx, writer);
159: break;
160: }
161: } else if (event instanceof BBCodeParser.CloseEvent) {
162: BBCodeParser.CloseEvent closeEvent = (BBCodeParser.CloseEvent) event;
163: switch (closeEvent.getType()) {
164: case BBCodeParser.EVENT_BOLD:
165: config.r_b_close.render(ctx, writer);
166: break;
167: case BBCodeParser.EVENT_ITALIC:
168: config.r_i_close.render(ctx, writer);
169: break;
170: case BBCodeParser.EVENT_UNDERLINE:
171: config.r_u_close.render(ctx, writer);
172: break;
173: case BBCodeParser.EVENT_COLOR:
174: config.r_color_close.render(ctx, writer);
175: break;
176: case BBCodeParser.EVENT_SIZE:
177: config.r_size_close.render(ctx, writer);
178: break;
179: case BBCodeParser.EVENT_QUOTE:
180: config.r_quote_close.render(ctx, writer);
181: break;
182: case BBCodeParser.EVENT_CODE:
183: isInPre--;
184: config.r_code_close.render(ctx, writer);
185: break;
186: case BBCodeParser.EVENT_UNORDERED_LIST:
187: config.r_ulist_close.render(ctx, writer);
188: break;
189: case BBCodeParser.EVENT_NUMERICALLY_ORDERED_LIST:
190: config.r_olist_close.render(ctx, writer);
191: break;
192: case BBCodeParser.EVENT_ALPHABETICALLY_ORDERED_LIST:
193: config.r_olist_close.render(ctx, writer);
194: break;
195: case BBCodeParser.EVENT_ITEM:
196: break;
197: case BBCodeParser.EVENT_LINK:
198: break;
199: }
200: } else {
201: TextEvent textEvent = (TextEvent) event;
202: if (isInPre > 0) {
203: XMLCERP.parse(textEvent.chars(),
204: textEvent.offset(), textEvent.length());
205: } else {
206: tagParser.parse(textEvent.chars(), textEvent
207: .offset(), textEvent.length());
208: }
209: }
210: }
211: };
212:
213: public ParseEventHandler tagHandler = new ParseEventHandler() {
214: public void handle(ParseEvent event) {
215: if (event instanceof TagParser.OpenEvent) {
216: TagParser.OpenEvent openEvent = (TagParser.OpenEvent) event;
217: switch (openEvent.getType()) {
218: case TagParser.EVENT_TAG:
219: String tag = openEvent.getTag();
220: if (config.print(tag)) {
221: if ("pre".equals(tag)) {
222: isInPre++;
223: }
224: write("<");
225: write(tag);
226: write(openEvent.getAttribute());
227: write(">");
228: } else if (config.getOuputMode() == ToHTMLConfig.OUTPUT_MODE_DISPLAY) {
229: write("<");
230: write(tag);
231: write(openEvent.getAttribute());
232: write(">");
233: }
234: break;
235: }
236: } else if (event instanceof TagParser.CloseEvent) {
237: TagParser.CloseEvent closeEvent = (TagParser.CloseEvent) event;
238: switch (closeEvent.getType()) {
239: case TagParser.EVENT_TAG:
240: String tag = closeEvent.getTag();
241: if (config.print(tag)) {
242: if ("pre".equals(tag)) {
243: isInPre--;
244: }
245: write("</");
246: write(tag);
247: write(">");
248: } else if (config.getOuputMode() == ToHTMLConfig.OUTPUT_MODE_DISPLAY) {
249: write("</");
250: write(tag);
251: write(">");
252: }
253: break;
254: }
255: } else {
256: TextEvent textEvent = (TextEvent) event;
257: XMLCERP.parse(textEvent.chars(), textEvent.offset(),
258: textEvent.length());
259: }
260: }
261: };
262:
263: public ParseEventHandler XMLCRPHandler = new ParseEventHandler() {
264: public void handle(ParseEvent event) {
265: if (event instanceof CharacterEntityReferenceEvent) {
266: CharacterEntityReferenceEvent cere = (CharacterEntityReferenceEvent) event;
267: lineBreakParser.parse(cere.chars(), cere.offset(), cere
268: .length());
269: } else {
270: TextEvent te = (TextEvent) event;
271: HTMLCERP.parse(te.chars(), te.offset(), te.length());
272: }
273: }
274: };
275:
276: public ParseEventHandler HTMLCRPHandler = new ParseEventHandler() {
277: public void handle(ParseEvent event) {
278: TextEvent textEvent = (TextEvent) event;
279: lineBreakParser.parse(textEvent.chars(),
280: textEvent.offset(), textEvent.length());
281: }
282: };
283:
284: public ParseEventHandler lineBreakHandler = new ParseEventHandler() {
285: public void handle(ParseEvent event) {
286: if (event instanceof TextEvent) {
287: TextEvent textEvent = (TextEvent) event;
288: if (isInPre == 0) {
289: write(textEvent.chars(), textEvent.offset(),
290: textEvent.length());
291: } else {
292: // Break the content in small chunks
293: char[] chars = textEvent.chars();
294: int offset = textEvent.offset();
295: int length = textEvent.length();
296: int maxSize = config.getMaxTextWidth();
297: while (length > maxSize) {
298: write(chars, offset, maxSize);
299: length -= maxSize;
300: offset += maxSize;
301: write("\n");
302: }
303: // Ouput the last chunk
304: write(chars, offset, length);
305: }
306: } else {
307: if (isInPre == 0) {
308: write("<br/>");
309: } else {
310: write("\n");
311: }
312: }
313: }
314: };
315: }
|