Source code: jbreport/core/ReportSectionImpl.java
1 /*
2 * $Id: ReportSectionImpl.java,v 1.1 2000/08/31 13:53:17 grantfin Exp $
3 *
4 * jbReport - A reporting library for Java
5 * Copyright (C) 2000 Grant Finnemore <grantfin@users.sourceforge.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 package jbreport.core;
22
23 import java.io.PrintWriter;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import org.xml.sax.Attributes;
32
33 import jbreport.Constants;
34 import jbreport.ReportElement;
35 import jbreport.ReportException;
36 import jbreport.ReportSection;
37 import jbreport.data.QueryResult;
38 import jbreport.render.BasicHTMLRenderer;
39
40 /**
41 * This is the default implementation of a ReportSection instance. It is made
42 * public as classes in other packages might need to implement the
43 * ReportSection interface.
44 *
45 * @author Grant Finnemore
46 * @version $Revision: 1.1 $
47 */
48 public
49 class ReportSectionImpl extends AbstractReportElement
50 implements ReportSection {
51
52 /** The header element of this instance */
53 private ReportElement headerElement;
54
55 /** The body element of this instance. */
56 private ReportElement bodyElement;
57
58 /** The footer element of this instance. */
59 private ReportElement footerElement;
60
61 /** Did this element create a group element implicitly? */
62 private boolean createdGroupElement = false;
63
64 /** The mapping of bound parameters */
65 private Map boundParams;
66
67 /** The renderers that have been attached to this section */
68 private Collection renderers;
69
70 //
71 // Constructors
72 //
73
74 //
75 // Implementation of the ReportSection interface
76 //
77
78 public void addRenderer(String rendererType, PrintWriter output) {
79 if(Constants.BASIC_HTML.equals(rendererType)) {
80 if(renderers == null) {
81 renderers = new ArrayList();
82 }
83 renderers.add(new BasicHTMLRenderer(output));
84 }
85 else {
86 throw new UnsupportedOperationException(rendererType);
87 }
88 }
89
90 public void render() throws ReportException {
91 for(Iterator it = renderers.iterator(); it.hasNext();) {
92 preOrderTraverse((ReportVisitor)it.next());
93 }
94 }
95
96 public void setBoundParamValue(String paramName, String value) {
97 if(boundParams == null) {
98 boundParams = new HashMap();
99 }
100 boundParams.put(paramName, value);
101 }
102
103 public String getBoundParamValue(String paramName) {
104 String result = null;
105 if(boundParams != null && boundParams.containsKey(paramName)) {
106 result = (String)boundParams.get(paramName);
107 }
108 // Should we try the parent of this element?
109 if(result == null && getParent() != null) {
110 result = getParent().getBoundParamValue(paramName);
111 }
112 return result;
113 }
114
115 public void setHeader(ReportElement elem) {
116 assertNotNull(elem, "headerElement");
117 headerElement = elem;
118 elem.setParent(this);
119 }
120
121 public ReportElement getHeader() {
122 return headerElement;
123 }
124
125 public void setBody(ReportElement elem) {
126 assertNotNull(elem, "bodyElement");
127 bodyElement = elem;
128 elem.setParent(this);
129 }
130
131 public ReportElement getBody() {
132 return bodyElement;
133 }
134
135 public void setFooter(ReportElement elem) {
136 assertNotNull(elem, "footerElement");
137 footerElement = elem;
138 elem.setParent(this);
139 }
140
141 public ReportElement getFooter() {
142 return footerElement;
143 }
144
145 //
146 // Implementation methods
147 //
148
149 //
150 // Methods overloaded from AbstractReportElement
151 //
152
153 public ReportElement copy(boolean deep) {
154 ReportSectionImpl result = (ReportSectionImpl)super.copy(deep);
155 if(deep == DEEP) {
156 if(headerElement != null) {
157 result.headerElement = headerElement.copy(deep);
158 result.headerElement.setParent(result);
159 }
160 if(bodyElement != null) {
161 result.bodyElement = bodyElement.copy(deep);
162 result.bodyElement.setParent(result);
163 }
164 if(footerElement != null) {
165 result.footerElement = footerElement.copy(deep);
166 result.footerElement.setParent(result);
167 }
168 }
169 return result;
170 }
171
172 public void loadData() throws ReportException {
173 if(headerElement != null) {
174 headerElement.loadData();
175 }
176 if(bodyElement != null) {
177 bodyElement.loadData();
178 }
179 if(footerElement != null) {
180 footerElement.loadData();
181 }
182 }
183
184 public void updateData(QueryResult queryResult) throws ReportException {
185 if(headerElement != null) {
186 ((AbstractReportElement)headerElement).updateData(queryResult);
187 }
188 if(bodyElement != null) {
189 ((AbstractReportElement)bodyElement).updateData(queryResult);
190 }
191 if(footerElement != null) {
192 ((AbstractReportElement)footerElement).updateData(queryResult);
193 }
194 }
195
196 public void xmlInitialize(String localName, Attributes attributes)
197 throws ReportException {
198 // Do the work required in the parent
199 super.xmlInitialize(localName, attributes);
200
201 // We allow for implicit declaration of groups by declaring a section in
202 // the body of an element. It is up to the code to create the necessary
203 // group element.
204
205 // We don't necessarily have a parent at this stage, so need to check
206 // the stack in the parser to see if a group should be created.
207 if(xmlHandler != null && !xmlHandler.stackEmpty()) {
208 ReportElement top = xmlHandler.peekElement();
209 if(!"group".equals(top.getType())/*need group*/
210 && !"document".equals(getType())/*is this a document*/) {
211 ReportElement group = getFactory().createElement("group");
212 group.xmlInitialize("group", attributes);
213 // Insert the group element
214 xmlHandler.pushElement(group);
215 createdGroupElement = true;
216 }
217 }
218 }
219
220 public void xmlEnd(String cdata) throws ReportException {
221 super.xmlEnd(cdata);
222 if(createdGroupElement) {
223 // We should never get here if the xmlHandler attribute is not
224 // defined.
225
226 // Pop the group element off the stack - ie. we need to pop two
227 // elements and push the first one back. This also necessitates
228 // that we manually call the correct xmlEndChild methods.
229 ReportElement top = xmlHandler.popElement();
230 ReportElement group = xmlHandler.peekElement();
231 group.xmlEndChild(top);
232 group.xmlEnd(cdata);
233 }
234 }
235
236 public void xmlEndChild(ReportElement elem) throws ReportException {
237 if("head".equals(elem.getType())) {
238 setHeader(elem);
239 }
240 else if("body".equals(elem.getType())) {
241 setBody(elem);
242 }
243 else if("footer".equals(elem.getType())) {
244 setFooter(elem);
245 }
246 else if("break".equals(elem.getType())) {
247 // Retrieve the next-from-top element on the stack, and call
248 // xmlEndChild on that element.
249 if(xmlHandler == null) {
250 throw new ReportException("Could not locate xmlHandler. This "
251 + "should only happen if a programatic "
252 + "group element was left out, and the "
253 + "break element was put in a section");
254 }
255 ((ReportElement)xmlHandler.peekElement(1)).xmlEndChild(elem);
256 }
257 else {
258 super.xmlEndChild(elem);
259 }
260 }
261
262 public void accept(ReportVisitor visitor, ReportVisitorState state)
263 throws ReportException {
264 visitor.visitReportSection(this, state);
265 }
266
267 }