Source code: com/dghda/kent/ReportTemplate.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.util.*;
23
24 import org.w3c.dom.*;
25
26 import org.xml.sax.*;
27
28 /**
29 This class provides a convenient method of creating a report template.
30 Report templates are based on report templates in the Kugar reporting tool
31 (a part of the KOffice suite). The main difference is these templates are
32 not primarily designed for exact positioning, and are not as sophisticated.
33 */
34 public class ReportTemplate {
35
36 /** The default page length. */
37 public static final int DEFAULT_PAGE_LENGTH = 30;
38
39 /** The name of the report template DTD. */
40 public static final String TEMPLATE_DTD = "template.dtd";
41
42 /** Constructs a new empty report template. */
43 protected ReportTemplate() {
44 }
45
46 /**
47 Constructs a new report template using default settings for the title.
48 @param title The report's title
49 */
50 public ReportTemplate (String title) {
51 this (title, null);
52 }
53
54 /**
55 Constructs a new report template using default settings for the title and subtitle.
56 @param title The report's title
57 @param subtitle The report's subtitle (may be null)
58 */
59 public ReportTemplate (String title, String subtitle) {
60 this (new ReportTemplateText (title), (subtitle == null ? null : new ReportTemplateText (subtitle)));
61 }
62
63 /**
64 Constructs a new report template.
65 @param title The report's title
66 */
67 public ReportTemplate (ReportTemplateText title) {
68 this (title, null);
69 }
70
71 /**
72 Constructs a new report template.
73 @param title The report's title
74 @param subtitle The report's subtitle (may be null)
75 */
76 public ReportTemplate (ReportTemplateText title, ReportTemplateText subtitle) {
77
78 // Create, add and initialise the report's header
79 m_Title = title;
80 m_Subtitle = subtitle;
81 }
82
83 /** Constructs a report template object from the given XML document. */
84 public static ReportTemplate constructReportTemplate (ReportEngine engine, String template) throws SAXException, javax.xml.parsers.ParserConfigurationException {
85 ReportTemplate result = new ReportTemplate();
86 Document doc = XMLConstructor.parseDocument (template, engine.getDTDPath (TEMPLATE_DTD));
87
88 // Parse the report header
89 Element rHeader = XMLConstructor.getSingleElementByTag (doc.getDocumentElement(), "ReportHeader");
90 result.m_Title = new ReportTemplateText (XMLConstructor.getSingleElementByTag (rHeader, "Title"));
91 Element subtitle = XMLConstructor.getOptionalElementByTag (rHeader, "Subtitle");
92 if (subtitle != null)
93 result.m_Subtitle = new ReportTemplateText (subtitle);
94 constructTextElements (result.m_ReportHeader, rHeader);
95
96 // Parse the page header
97 Element pHeader = XMLConstructor.getOptionalElementByTag (doc.getDocumentElement(), "PageHeader");
98 if (pHeader != null) {
99 String value = pHeader.getAttribute ("PageLength");
100 try {
101 if (value != null) {
102 result.setPageLength (Integer.parseInt (value));
103 }
104 } catch (NumberFormatException exc) {
105 throw new SAXException ("Invalid page length " + value);
106 }
107 constructTextElements (result.m_PageHeader, pHeader);
108 }
109
110 // Parse the body
111 Element body = XMLConstructor.getSingleElementByTag (doc.getDocumentElement(), "Body");
112 NodeList nodes = body.getChildNodes();
113 for (int index = 0; index != nodes.getLength(); ++index) {
114 Node node = nodes.item (index);
115
116 // In theory there shouldn't be any other type, but...
117 if (node.getNodeType() != Node.ELEMENT_NODE)
118 continue;
119
120 // Add the data set/text
121 Element elem = (Element) node;
122 if (elem.getTagName().equalsIgnoreCase ("DataSet")) {
123 result.m_Body.add (new ReportTemplateDataSet (elem));
124 } else if (elem.getTagName().equalsIgnoreCase ("Text")) {
125 result.m_Body.add (new ReportTemplateText (elem));
126 } else {
127 throw new SAXException ("Invalid tag " + elem.getTagName() + " in report template body");
128 }
129 }
130
131 // Parse the page footer
132 Element pFooter = XMLConstructor.getOptionalElementByTag (doc.getDocumentElement(), "PageFooter");
133 if (pFooter != null)
134 constructTextElements (result.m_PageFooter, pFooter);
135
136 // Parse the report footer
137 Element rFooter = XMLConstructor.getOptionalElementByTag (doc.getDocumentElement(), "ReportFooter");
138 if (rFooter != null)
139 constructTextElements (result.m_ReportFooter, rFooter);
140
141 return result;
142 }
143
144 /** Returns the report's title. */
145 public String getTitle() {
146 return m_Title.getText();
147 }
148
149 /** Returns the report's sub-title, or null if it doesn't have one. */
150 public String getSubtitle() {
151 if (m_Subtitle == null)
152 return null;
153 else
154 return m_Subtitle.getText();
155 }
156
157 /**
158 Sets the page length.
159 The page header and footer will be printed after this many lines.
160 */
161 public void setPageLength (int pageLength) {
162 if (pageLength < 1)
163 throw new IllegalArgumentException ("Invalid value for page length: " + pageLength);
164 m_PageLength = pageLength;
165 }
166
167 /**
168 Returns the report's page length.
169 If there is no page header, or there is no page length specified, the
170 default value of 30 will be returned.
171 */
172 public int getPageLength() {
173 return m_PageLength;
174 }
175
176 /** Adds the given text to the page header. */
177 public synchronized void addPageHeaderText (ReportTemplateText text) {
178 m_PageHeader.add (text);
179 }
180
181 /** Adds the given data set to the report's body. */
182 public synchronized void addDataSet (ReportTemplateDataSet dataSet) {
183 m_Body.add (dataSet);
184 }
185
186 /** Adds the given text to the report's body with default settings. */
187 public synchronized void addText (String text) {
188 addText (new ReportTemplateText (text));
189 }
190
191 /** Adds the given text to the report's body. */
192 public synchronized void addText (ReportTemplateText text) {
193 m_Body.add (text);
194 }
195
196 /** Adds the given text to the page footer. */
197 public synchronized void addPageFooterText (ReportTemplateText text) {
198 m_PageFooter.add (text);
199 }
200
201 /** Adds the given text to the report footer. */
202 public synchronized void addReportFooterText (ReportTemplateText text) {
203 m_ReportFooter.add (text);
204 }
205
206 /**
207 Returns an iterator that will iterate over the contents of the report header.
208 Items returned will be ReportTemplateText objects.
209 */
210 public synchronized Iterator getReportHeaderIterator() {
211 Vector temp = new Vector (m_ReportHeader);
212 return temp.iterator();
213 }
214
215 /**
216 Returns an iterator that will iterate over the contents of the page header.
217 Items returned will be ReportTemplateText objects.
218 */
219 public synchronized Iterator getPageHeaderIterator() {
220 Vector temp = new Vector (m_PageHeader);
221 return temp.iterator();
222 }
223
224 /**
225 Returns an iterator that will iterate over the contents of the template's body.
226 Items returned will be either ReportTemplateText or ReportTemplateDataSet objects.
227 */
228 public synchronized Iterator getBodyIterator() {
229 Vector temp = new Vector (m_Body);
230 return temp.iterator();
231 }
232
233 /**
234 Returns an iterator that will iterate over the text contents of the page footer.
235 Items returned will be ReportTemplateText objects.
236 */
237 public synchronized Iterator getPageFooterIterator() {
238 Vector temp = new Vector (m_PageFooter);
239 return temp.iterator();
240 }
241
242 /**
243 Returns an iterator that will iterate over the contents of the report footer.
244 Items returned will be ReportTemplateText objects.
245 */
246 public synchronized Iterator getReportFooterIterator() {
247 Vector temp = new Vector (m_ReportFooter);
248 return temp.iterator();
249 }
250
251 /** Returns the report template document. */
252 public synchronized String getTemplate() {
253 StringBuffer result = new StringBuffer();
254
255 // Pre-amble
256 result.append ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
257 result.append ("<!DOCTYPE KentTemplate SYSTEM \"");
258 result.append (TEMPLATE_DTD);
259 result.append ("\">\n\n");
260 result.append ("<KentTemplate>\n");
261
262 // Report header
263 result.append (" <ReportHeader>\n");
264 m_Title.addElement (result, "Title", 2);
265 if (m_Subtitle != null)
266 m_Subtitle.addElement (result, "Subtitle", 2);
267 addTextElements (result, m_ReportHeader.iterator(), 2);
268 result.append (" </ReportHeader>\n");
269
270 // Page header
271 result.append (" <PageHeader PageLength=\"");
272 result.append (Integer.toString (m_PageLength));
273 result.append ("\">\n");
274 addTextElements (result, m_PageHeader.iterator(), 2);
275 result.append (" </PageHeader>\n");
276
277 // Body
278 result.append (" <Body>\n");
279 Iterator i = m_Body.iterator();
280 while (i.hasNext()) {
281 Object obj = i.next();
282 if (obj instanceof ReportTemplateDataSet) {
283 ReportTemplateDataSet dataSet = (ReportTemplateDataSet) obj;
284 dataSet.addElement (result, 2);
285 } else {
286 ReportTemplateText text = (ReportTemplateText) obj;
287 text.addElement (result, "Text", 2);
288 }
289 }
290 result.append (" </Body>\n");
291
292 // Page Footer
293 result.append (" <PageFooter>\n");
294 addTextElements (result, m_PageFooter.iterator(), 2);
295 result.append (" </PageFooter>\n");
296
297 // Report Footer
298 result.append (" <ReportFooter>\n");
299 addTextElements (result, m_ReportFooter.iterator(), 2);
300 result.append (" </ReportFooter>\n");
301
302 // Ta-da!
303 result.append ("</KentTemplate>\n");
304
305 return result.toString();
306 }
307
308 protected void addTextElements (StringBuffer buffer, Iterator i, int indent) {
309 while (i.hasNext()) {
310 ReportTemplateText text = (ReportTemplateText) i.next();
311 text.addElement (buffer, "Text", indent);
312 }
313 }
314
315 protected static void constructTextElements (List list, org.w3c.dom.Element elem) throws SAXException {
316 NodeList nodes = elem.getElementsByTagName ("Text");
317 for (int index = 0; index != nodes.getLength(); ++index) {
318 Element text = (Element) nodes.item (index);
319 list.add (new ReportTemplateText (text));
320 }
321 }
322
323 private ReportTemplateText m_Title;
324 private ReportTemplateText m_Subtitle;
325 private ArrayList m_ReportHeader = new ArrayList();
326 private ArrayList m_PageHeader = new ArrayList();
327 private ArrayList m_Body = new ArrayList();
328 private ArrayList m_PageFooter = new ArrayList();
329 private ArrayList m_ReportFooter = new ArrayList();
330 private int m_PageLength = DEFAULT_PAGE_LENGTH;
331 }