001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: HTMLFormatter.java,v $
031: * Revision 1.5 2005/10/11 18:54:06 colinmacleod
032: * Fixed some checkstyle and javadoc issues.
033: *
034: * Revision 1.4 2005/10/02 14:06:33 colinmacleod
035: * Added/improved log4j logging.
036: *
037: * Revision 1.3 2005/04/09 18:04:18 colinmacleod
038: * Changed copyright text to GPL v2 explicitly.
039: *
040: * Revision 1.2 2005/01/06 22:41:01 colinmacleod
041: * Moved up a version number.
042: * Changed copyright notices to 2005.
043: * Updated the documentation:
044: * - started working on multiproject:site docu.
045: * - changed the logo.
046: * Added checkstyle and fixed LOADS of style issues.
047: * Added separate thirdparty subproject.
048: * Added struts (in web), util and webgui (in webtheme) from ivata op.
049: *
050: * Revision 1.3 2004/03/21 21:16:37 colinmacleod
051: * Shortened name to ivata op.
052: *
053: * Revision 1.2 2004/02/01 22:07:32 colinmacleod
054: * Added full names to author tags
055: *
056: * Revision 1.1.1.1 2004/01/27 20:59:47 colinmacleod
057: * Moved ivata op to SourceForge.
058: *
059: * Revision 1.2 2003/10/15 14:13:39 colin
060: * Fixes for XDoclet.
061: *
062: * Revision 1.1 2003/02/24 19:33:33 colin
063: * Moved to new subproject.
064: *
065: * Revision 1.4 2003/02/04 17:43:46 colin
066: * copyright notice
067: *
068: * Revision 1.3 2002/09/06 15:06:31 colin
069: * added null checking on input format text
070: *
071: * Revision 1.2 2002/06/21 16:00:30 colin
072: * added protected accessors (get/set) to the Vector of formats.
073: *
074: * Revision 1.1 2002/04/26 13:52:44 colin
075: * move to EJB/JBuilder project
076: *
077: * Revision 1.12 2002/02/02 19:10:52 colin
078: * changed formatEmail methods to just return null when you pass null
079: * to them
080: *
081: * Revision 1.11 2002/01/25 18:04:06 colin
082: * Formatted for JavaDoc.
083: *
084: * Revision 1.10 2002/01/20 19:40:24 colin
085: * added tab and tree tags
086: * implemented address book functionality
087: *
088: * Revision 1.9 2002/01/20 19:28:25 colin
089: * added tab and tree tags
090: * implemented address book functionality
091: *
092: * Revision 1.8 2001/12/20 17:11:44 colin
093: * tidied up the HTMLFormatter code, and improved InternetAddress
094: * handling
095: * truncated email addresses which are too long in index.jsp
096: * changed non-alphanumeric symbols (such as apostrophe ') to their
097: * HTML equivalents in compose and display
098: * made error messages in the compose window limited in width
099: * (word-wrap)
100: * converted URLs into links
101: *
102: * Revision 1.7 2001/12/12 20:24:57 colin
103: * fixed the following bugs:
104: * made display window same width as index
105: * made leading spaces non-breaking
106: * put a little header with from/to/subject information before
107: * forwarded and replied to mails
108: * stopped append re: to messages which are already re: (same applies
109: * to forward)
110: * convert people's email addresses into links (mailto)
111: * word wrap the messages (replies) in compose
112: * make the subject line spread right over the whole space in display
113: *
114: * Revision 1.6 2001/11/24 19:19:53 colin
115: * display, compose, reply and forward features of webmail implemented
116: *
117: * Revision 1.5 2001/11/08 01:38:56 colin
118: * implemented new Solero theme in shop
119: *
120: * Revision 1.4 2001/10/22 19:50:51 colin
121: * commit everything before move from monifieth1 to lucenec1
122: *
123: * Revision 1.3 2001/10/16 17:52:02 colin
124: * updated mail classes to set formatterName="nothing" instead of null
125: * several rebuilds to avoid problem of classes not recompiling
126: *
127: * Revision 1.2 2001/10/14 18:01:02 colin
128: * added '..' to shortened lines
129: *
130: * Revision 1.1 2001/10/07 00:30:16 colin
131: * no message
132: *
133: * Revision 1.1.1.1 2001/10/06 15:40:20 colin
134: * initial import into CVS
135: * -----------------------------------------------------------------------------
136: */
137: package com.ivata.mask.web.format;
138:
139: import org.apache.log4j.Logger;
140:
141: import java.util.Iterator;
142: import java.util.List;
143: import java.util.Vector;
144:
145: /**
146: * <p>
147: * This class defines a standard way of formatting HTML. It can be used as as a
148: * parameter to methods from other classes indicating that output should be
149: * truncated, spaces should be converted to non-breaking, or the string should
150: * be parsed for URLs.
151: * </p>
152: * <p>
153: * The actual conversions are achieved by add-in classes, with {@linkHTMLFormat
154: * HTMLFormat} as their superclass. This means the formatter can provided a rich
155: * selection of different formats without having knowledge of the processing of
156: * each one.
157: * <p>
158: * <p>
159: * To use this class, created an instance of the formats you wish to use, and an
160: * instance of this class too. Call any methods on the formats to set up the
161: * exact function of each one. Then call {@link #add add}for each format on the
162: * <code>HTMLFormatter</code> instance. Passing a text to
163: * {@link #format format}will ensure that each format is applied in the order
164: * in which they were added to the formatter.
165: * </p>
166: *
167: * @since ivata masks 0.2 (2001-10-03)
168: * @author Colin MacLeod
169: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
170: * @version $Revision: 1.5 $
171: */
172: public class HTMLFormatter extends Object {
173: /**
174: * Logger for this class.
175: */
176: private static final Logger logger = Logger
177: .getLogger(HTMLFormatter.class);
178:
179: /**
180: * <p>
181: * Stores all of the formats which will be applied.
182: * </p>
183: */
184: private List formats = new Vector();
185: /**
186: * Used to note the position of any link format, so it does not interfere
187: * with character entity format.
188: */
189: private LinkFormat linkFormat = null;
190:
191: /**
192: * Creates a new instance of HTMLFormatter with default settings.
193: */
194: public HTMLFormatter() {
195: super ();
196: }
197:
198: /**
199: * <p>
200: * If the object is not null, fill the attribute with this value otherwise
201: * return nothing.
202: * </p>
203: *
204: * <p>
205: * This is useful for HTML tags where you want to created an attribute value
206: * only if the object <code>objectParam</code> is non-null.
207: * </p>
208: *
209: * @param attribute
210: * the attribute name of the attribute to be set if
211: * <code>objectParam</code> is non-null
212: * @param objectParam
213: * an Object to assign attribute to if it is non-null
214: * @return if <code>objectParam</code> is not null, a string assigning the
215: * attribute sAttrubte to the value of
216: * <code>objectParam.toString()</code>, otherwise an empty
217: * string.
218: * @see #getBooleanAttribute(String attribute, boolean check)
219: * @see #getNotNull(Object o, String nullString)
220: */
221: public static final String getAttributeNotNull(
222: final String attribute, final Object objectParam) {
223: if (logger.isDebugEnabled()) {
224: logger.debug("getAttributeNotNull(String attribute = "
225: + attribute + ", Object objectParam = "
226: + objectParam + ") - start");
227: }
228:
229: if (objectParam == null) {
230: if (logger.isDebugEnabled()) {
231: logger
232: .debug("getAttributeNotNull - end - return value = ");
233: }
234: return "";
235: } else {
236: String returnString = " " + attribute + "='"
237: + objectParam.toString() + "'";
238: if (logger.isDebugEnabled()) {
239: logger
240: .debug("getAttributeNotNull - end - return value = "
241: + returnString);
242: }
243: return returnString;
244: }
245: }
246:
247: /**
248: * <p>
249: * If the boolean is true, fill the attribute with no value, otherwise
250: * return nothing.
251: * </p>
252: *
253: * <p>
254: * This is useful for HTML tags where you want to create an attribute only
255: * if the condition is <code>true</code>.
256: * </p>
257: *
258: * @param attribute
259: * the attribute name of the attribute to be set if check is
260: * <code>true</code>.
261: * @param check
262: * a boolean to evaluate.
263: * @return if check is <code>true</code>, the attribute string, otherwise
264: * an empty string.
265: * @see #getAttributeNotNull(String attribute, Object o)
266: * @see #getNotNull(Object o)
267: */
268: public static final String getBooleanAttribute(
269: final String attribute, final boolean check) {
270: if (logger.isDebugEnabled()) {
271: logger.debug("getBooleanAttribute(String attribute = "
272: + attribute + ", boolean check = " + check
273: + ") - start");
274: }
275:
276: if (check) {
277: String returnString = " " + attribute;
278: if (logger.isDebugEnabled()) {
279: logger
280: .debug("getBooleanAttribute - end - return value = "
281: + returnString);
282: }
283: return returnString;
284: } else {
285: if (logger.isDebugEnabled()) {
286: logger
287: .debug("getBooleanAttribute - end - return value = ");
288: }
289: return "";
290: }
291: }
292:
293: /**
294: * <p>
295: * This is the most important method of all.
296: * </p>
297: *
298: * <p>
299: * First call the methods setConvert.... to specify how to convert the
300: * string, then use this method to format the given string according to the
301: * set rules
302: * </p>.
303: *
304: * @param formatString
305: * String to format
306: * @return String containing formatted text, according to the current state
307: * of this HTMLFormatter instance.
308: * @see HTMLFormat#format
309: */
310: public String format(final String formatString) {
311: if (logger.isDebugEnabled()) {
312: logger.debug("format(String formatString = " + formatString
313: + ") - start");
314: }
315:
316: // rubbish in, rubbish out...
317: if (formatString == null) {
318: if (logger.isDebugEnabled()) {
319: logger.debug("format(String) - end - return value = "
320: + null);
321: }
322: return null;
323: }
324: String returnString = formatString;
325: // go through all of the format objects provided and call each one
326: for (Iterator i = formats.iterator(); i.hasNext();) {
327: HTMLFormat format = (HTMLFormat) i.next();
328: returnString = format.format(returnString);
329: }
330:
331: if (logger.isDebugEnabled()) {
332: logger.debug("format(String) - end - return value = "
333: + returnString);
334: }
335: return returnString;
336: }
337:
338: /**
339: * <p>
340: * Adds the format to the internal list of <code>HTMLFormat</code>
341: * instances this formatter holds.
342: * </p>
343: *
344: * @param format
345: * the format instance to add. This will be processed after all
346: * existing formats.
347: */
348: public final void add(final HTMLFormat format) {
349: if (logger.isDebugEnabled()) {
350: logger.debug("add(HTMLFormat format = " + format
351: + ") - start");
352: }
353:
354: // see if there is a convert character entities after the link format,
355: // and warn it if there is
356: if (linkFormat == null) {
357: // see if this is a link format
358: if (LinkFormat.class.isInstance(format)) {
359: linkFormat = (LinkFormat) format;
360: }
361: } else if (CharacterEntityFormat.class.isInstance(format)) {
362: // warn the link format
363: linkFormat.setConvertHTMLEntities(true);
364: }
365: formats.add(format);
366:
367: if (logger.isDebugEnabled()) {
368: logger.debug("add(HTMLFormat) - end");
369: }
370: }
371:
372: /**
373: * <p>
374: * Locates a format in the object, identified by class.
375: * </p>
376: *
377: * @param findClass
378: * the <code>Class</code> of the format to locate in the
379: * formatter's internal list.
380: * @return first format found with the class specified, or <code>null</code>
381: * if no format with this class has been set in the formatter
382: */
383: public final HTMLFormat findFormat(final Class findClass) {
384: if (logger.isDebugEnabled()) {
385: logger.debug("findFormat(Class findClass = " + findClass
386: + ") - start");
387: }
388:
389: HTMLFormat formatReturn = null;
390: for (Iterator i = formats.iterator(); i.hasNext();) {
391: HTMLFormat format = (HTMLFormat) i.next();
392: // see if this instance matches the class we're looking for
393: if (findClass.isInstance(format)) {
394: formatReturn = format;
395: break;
396: }
397: }
398:
399: if (logger.isDebugEnabled()) {
400: logger.debug("findFormat(Class) - end - return value = "
401: + formatReturn);
402: }
403: return formatReturn;
404: }
405:
406: /**
407: * <p>
408: * Get the internal list of all of the formats used by this formatter.
409: * </p>
410: *
411: * @return a <code>Vector</code> containing all of the formats from this
412: * formatter.
413: */
414: public final List getFormats() {
415: if (logger.isDebugEnabled()) {
416: logger.debug("getFormats() - start");
417: }
418:
419: if (logger.isDebugEnabled()) {
420: logger.debug("getFormats() - end - return value = "
421: + formats);
422: }
423: return formats;
424: }
425:
426: /**
427: * <p>
428: * Set the internal list of all of the formats used by this formatter.
429: * </p>
430: *
431: * @param formatsParam
432: * a <code>Vector</code> containing all of the formats from
433: * this formatter.
434: */
435: protected final void setFormats(final List formatsParam) {
436: if (logger.isDebugEnabled()) {
437: logger.debug("setFormats(List formatsParam = "
438: + formatsParam + ") - start");
439: }
440:
441: this .formats = formatsParam;
442:
443: if (logger.isDebugEnabled()) {
444: logger.debug("setFormats(List) - end");
445: }
446: }
447: }
|