Source code: com/dghda/kent/ReportTemplateText.java
1 /* Copyright (C) 2001 Duane Griffin <duanegriffin@users.sourceforge.net>
2 This file is part of Kent.
3
4 Kent is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 Kent is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public
15 License along with Kent; see the file COPYING. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 */
19
20 package com.dghda.kent;
21
22 import java.awt.*;
23 import java.util.*;
24
25 /**
26 This class provides a convenient method of creating a report template text node.
27 Aside from the attributes defined in the DTD, text may include
28 substitutions, which are in the form: {source, field, row}
29 When a report result is transformed the substitution is replaced by the specified datum.
30 */
31 public class ReportTemplateText {
32
33 /** Align text to the left (default). */
34 public static final int ALIGN_LEFT = 0;
35
36 /** Align text in the centre. */
37 public static final int ALIGN_CENTRE = 1;
38
39 /** Align text to the right. */
40 public static final int ALIGN_RIGHT = 2;
41
42 /** Create a new empty text object with default settings. */
43 public ReportTemplateText() {
44 this ("", null, null, null, ALIGN_LEFT);
45 }
46
47 /** Create a new object containing the given text, with default settings. */
48 public ReportTemplateText (String text) {
49 this (text, null, null, null, ALIGN_LEFT);
50 }
51
52 /** Create a new object containing the given text, using the given font. */
53 public ReportTemplateText (String text, Font font) {
54 this (text, null, null, font, ALIGN_LEFT);
55 }
56
57 /** Create a new object containing the given text, using the given settings. */
58 public ReportTemplateText (String text, Color bg, Color fg, Font font, int align) {
59 m_Text = text;
60 m_BGColour = bg;
61 m_FGColour = fg;
62 m_Alignment = align;
63 if (font != null)
64 setFont (font);
65 }
66
67 /** Create a new text object by parsing the given element. */
68 public ReportTemplateText (org.w3c.dom.Element text) throws org.xml.sax.SAXException {
69 m_Text = XMLConstructor.getNodeText (text);
70
71 // Get any optional attributes
72 String value = text.getAttribute (BG_COLOUR_ATTR);
73 if (value != null && !value.equals (""))
74 m_BGColour = getColourFromString (value);
75
76 value = text.getAttribute (FG_COLOUR_ATTR);
77 if (value != null && !value.equals (""))
78 m_FGColour = getColourFromString (value);
79
80 String fontFamily = text.getAttribute (FONT_FAMILY_ATTR);
81 if (fontFamily != null && !fontFamily.equals (""))
82 m_FontFamily = fontFamily;
83
84 String fontSize = text.getAttribute (FONT_SIZE_ATTR);
85 if (fontSize != null && !fontSize.equals ("")) {
86 try {
87 m_FontSize = Integer.parseInt (fontSize);
88 } catch (NumberFormatException exc) {
89 throw new org.xml.sax.SAXException ("Invalid font size " + fontSize);
90 }
91 }
92
93 String fontWeight = text.getAttribute (FONT_WEIGHT_ATTR);
94 if (fontWeight != null && !fontWeight.equals ("")) {
95 if (fontWeight.equalsIgnoreCase ("normal"))
96 m_FontWeight = false;
97 else if (fontWeight.equalsIgnoreCase ("bold"))
98 m_FontWeight = true;
99 else
100 throw new org.xml.sax.SAXException ("Invalid font weight " + fontWeight);
101 }
102
103 String fontItalic = text.getAttribute (FONT_ITALIC_ATTR);
104 if (fontItalic != null && !fontItalic.equals ("")) {
105 if (fontItalic.equalsIgnoreCase ("no"))
106 m_FontItalic = false;
107 else if (fontItalic.equalsIgnoreCase ("yes"))
108 m_FontItalic = true;
109 else
110 throw new org.xml.sax.SAXException ("Invalid font italic specification " + fontItalic);
111 }
112
113 value = text.getAttribute (H_ALIGN_ATTR);
114 if (value != null && (!value.equals ("")))
115 m_Alignment = Integer.parseInt (value);
116 }
117
118 /** Sets the text. */
119 public void setText (String text) {
120 m_Text = text;
121 }
122
123 /**
124 Gets the raw text.
125 The text is returned before any substitutions.
126 */
127 public String getText() {
128 return m_Text;
129 }
130
131 /** Gets the text with all subsitutions made. */
132 public String getSubstitutedText (ReportData data) throws SubstitutionException {
133 StringBuffer result = new StringBuffer();
134
135 // Find the first substitution
136 int mark = 0;
137 int index = m_Text.indexOf ('{');
138 while (index != -1) {
139
140 // Check the brace has not been escaped
141 if (index == 0 || (m_Text.charAt (index - 1) != '\\')) {
142
143 // Add the text up to the substitution
144 result.append (m_Text.substring (mark, index));
145 mark = index + 1;
146 index = m_Text.indexOf ('}', mark);
147 if (index == -1)
148 throw new SubstitutionException ("Incomplete substitution");
149
150 // Make the substitution
151 writeSubstitution (result, m_Text.substring (mark, index), data);
152 } else {
153
154 // Write out the brace
155 result.append ('{');
156 }
157
158 // Look for the next one
159 mark = index + 1;
160 index = m_Text.indexOf ('{', mark);
161 }
162
163 // Write out the text after the last substitution
164 result.append (m_Text.substring (mark));
165 return result.toString();
166 }
167
168 /** Sets the colour to use for the background. */
169 public void setBackgroundColour (Color colour) {
170 m_BGColour = colour;
171 }
172
173 /** Gets the colour to use for the background. */
174 public Color getBackgroundColour() {
175 return m_BGColour;
176 }
177
178 /** Sets the colour to use for the foreground. */
179 public void setForegroundColour (Color colour) {
180 m_FGColour = colour;
181 }
182
183 /** Gets the colour to use for the foreground. */
184 public Color getForegroundColour() {
185 return m_FGColour;
186 }
187
188 /** Sets all the font attributes to use. */
189 public void setFont (Font font) {
190 m_FontFamily = font.getFontName();
191 m_FontSize = font.getSize();
192 m_FontWeight = ((font.getStyle() & Font.BOLD) == Font.BOLD);
193 m_FontItalic = ((font.getStyle() & Font.ITALIC) == Font.ITALIC);
194 }
195
196 /** Sets the font family to use. */
197 public void setFontFamily (String family) {
198 m_FontFamily = family;
199 }
200
201 /** Sets the font size to use. */
202 public void setFontSize (int point) {
203 m_FontSize = point;
204 }
205
206 /** Sets whether the font to use is bold. */
207 public void setFontBold (boolean bold) {
208 m_FontWeight = bold;
209 }
210
211 /** Sets whether the font to use is italic. */
212 public void setFontItalic (boolean italic) {
213 m_FontItalic = italic;
214 }
215
216 /** Returns true if any optional font attributes are specified. */
217 public boolean hasCustomFont() {
218 return (m_FontWeight || m_FontItalic || (m_FontSize > 0) || (m_FontFamily != null));
219 }
220
221 /**
222 Get the font family to use.
223 @returns null if no family has been specified.
224 */
225 public String getFontFamily() {
226 return m_FontFamily;
227 }
228
229 /**
230 Get the font size to use.
231 @returns 0 if no size has been specified.
232 */
233 public int getFontSize() {
234 return (m_FontSize > 0 ? m_FontSize : 0);
235 }
236
237 /** Get whether the font is bold. */
238 public boolean getFontBold() {
239 return m_FontWeight;
240 }
241
242 /** Get whether the font is italic. */
243 public boolean getFontItalic() {
244 return m_FontItalic;
245 }
246
247 /** Gets the font to use. */
248 public Font getFont() {
249 int style = (m_FontWeight ? Font.BOLD : Font.PLAIN) | (m_FontItalic ? Font.ITALIC : Font.PLAIN);
250 int size = (m_FontSize > 0 ? m_FontSize : 10);
251 return new Font (m_FontFamily, style, size);
252 }
253
254 /** Sets the horizontal alignment to use. */
255 public void setHAlignment (int align) {
256 m_Alignment = align;
257 }
258
259 /** Gets the horizontal alignment to use. */
260 public int getHAlignment() {
261 return m_Alignment;
262 }
263
264 /** Creates an element with the given tag representing the object. */
265 public void addElement (StringBuffer buffer, String tag, int indent) {
266
267 // Create the node & add the text
268 XMLConstructor.addIndent (buffer, indent);
269
270 buffer.append ('<');
271 buffer.append (tag);
272
273 // Add in any attributes it may have
274 if (m_BGColour != null)
275 XMLConstructor.addAttribute (buffer, BG_COLOUR_ATTR, getColourString (m_BGColour));
276 if (m_FGColour != null)
277 XMLConstructor.addAttribute (buffer, FG_COLOUR_ATTR, getColourString (m_FGColour));
278 if (m_FontFamily != null)
279 XMLConstructor.addAttribute (buffer, FONT_FAMILY_ATTR, m_FontFamily);
280 if (m_FontSize > 0)
281 XMLConstructor.addAttribute (buffer, FONT_SIZE_ATTR, Integer.toString (m_FontSize));
282 if (m_FontWeight)
283 XMLConstructor.addAttribute (buffer, FONT_WEIGHT_ATTR, "bold");
284 if (m_FontItalic)
285 XMLConstructor.addAttribute (buffer, FONT_ITALIC_ATTR, "yes");
286 if (m_Alignment != ALIGN_LEFT)
287 XMLConstructor.addAttribute (buffer, H_ALIGN_ATTR, Integer.toString (m_Alignment));
288 buffer.append ('>');
289
290 buffer.append (m_Text);
291
292 buffer.append ("</");
293 buffer.append (tag);
294 buffer.append (">\n");
295 }
296
297 /** Writes the substituted text to the given buffer. */
298 protected void writeSubstitution (StringBuffer buffer, String substitution, ReportData data) throws SubstitutionException {
299 StringTokenizer tokenizer = new StringTokenizer (substitution, ", \t");
300
301 String source = null;
302 String field = null;
303 String str = null;
304 try {
305
306 // Get the substitution info
307 source = tokenizer.nextToken();
308 field = tokenizer.nextToken();
309 str = tokenizer.nextToken();
310 int row = Integer.parseInt (str);
311
312 // Write the value
313 buffer.append (data.getColumn (source, field, row));
314 } catch (NoSuchElementException exc) {
315 throw new SubstitutionException ("Invalid substitution " + substitution);
316 } catch (NumberFormatException exc) {
317 throw new SubstitutionException ("Invalid row " + str + " specified");
318 } catch (InvalidColumnException exc) {
319 throw new SubstitutionException ("Invalid column " + field + " specified");
320 } catch (InvalidDataSetException exc) {
321 throw new SubstitutionException ("Invalid data source " + source + " specified");
322 }
323 }
324
325 /**
326 Returns a string containing the RGB values for the given colour.
327 Has the format R,G,B.
328 */
329 protected static String getColourString (Color colour) {
330 StringBuffer buffer = new StringBuffer();
331 buffer.append (colour.getRed());
332 buffer.append (',');
333 buffer.append (colour.getGreen());
334 buffer.append (',');
335 buffer.append (colour.getBlue());
336 return buffer.toString();
337 }
338
339 /**
340 Returns a Color object constructed from the given RGB values.
341 @param rgb A colour spec in the format R,G,B.
342 @throws org.xml.sax.SAXException If the colour spec was invalid.
343 */
344 protected static Color getColourFromString (String rgb) throws org.xml.sax.SAXException {
345 StringTokenizer tokenizer = new StringTokenizer (rgb, ", \t");
346 try {
347 int r = Integer.parseInt (tokenizer.nextToken());
348 int g = Integer.parseInt (tokenizer.nextToken());
349 int b = Integer.parseInt (tokenizer.nextToken());
350 return new Color (r, g, b);
351 } catch (NumberFormatException exc) {
352 throw new org.xml.sax.SAXException ("Invalid colour component in colour spec " + rgb);
353 } catch (NoSuchElementException exc) {
354 throw new org.xml.sax.SAXException ("Missing colour component in colour spec " + rgb);
355 }
356 }
357
358 private static final String BG_COLOUR_ATTR = "BackgroundColor";
359 private static final String FG_COLOUR_ATTR = "ForegroundColor";
360 private static final String FONT_FAMILY_ATTR = "FontFamily";
361 private static final String FONT_SIZE_ATTR = "FontSize";
362 private static final String FONT_WEIGHT_ATTR = "FontWeight";
363 private static final String FONT_ITALIC_ATTR = "FontItalic";
364 private static final String H_ALIGN_ATTR = "HAlignment";
365
366 private String m_Text;
367 private Color m_BGColour;
368 private Color m_FGColour;
369 private String m_FontFamily;
370 private int m_FontSize;
371 private boolean m_FontWeight;
372 private boolean m_FontItalic;
373 private int m_Alignment;
374 }