1 package net.sf.statcvs.pages;
2
3 import java.io.FileWriter;
4 import java.io.IOException;
5 import java.text.DecimalFormat;
6 import java.text.NumberFormat;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.Date;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.logging.Logger;
13
14 import net.sf.statcvs.Messages;
15 import net.sf.statcvs.charts.ChartImage;
16 import net.sf.statcvs.model.Directory;
17 import net.sf.statcvs.output.ReportConfig;
18 import net.sf.statcvs.renderer.TableRenderer;
19 import net.sf.statcvs.reports.TableReport;
20
21 public class Page implements NavigationNode {
22 private final static NumberFormat[] DOUBLE_FORMATS = { new DecimalFormat("0"), new DecimalFormat("0.0"), new DecimalFormat("0.00"),
23 new DecimalFormat("0.000"), new DecimalFormat("0.0000") };
24 private final static Logger logger = Logger.getLogger("sf.net.statcvs");
25
26 private final ReportConfig config;
27 private final String fileName;
28 private final String shortTitle;
29 private final String fullTitle;
30 private final MarkupSyntax outputFormat;
31 private StringBuffer contents = new StringBuffer();
32 private NavigationNode parent = null;
33 private String siblingsTitle = null;
34 private List siblings = Collections.EMPTY_LIST;
35 private final List children = new ArrayList();
36 private final List attributeKeys = new ArrayList();
37 private final List attributeValues = new ArrayList();
38 private boolean showLinkToPreviousSibling = false;
39 private boolean inSection = false;
40 private boolean written = false;
41
42
43
44
45
46
47
48
49 public Page(final ReportConfig config, final String fileName, final String shortTitle, final String fullTitle) {
50 this.config = config;
51 this.fileName = fileName;
52 this.shortTitle = shortTitle;
53 this.fullTitle = fullTitle;
54 this.outputFormat = config.getMarkup();
55 }
56
57
58
59
60 public void setParent(final NavigationNode parent) {
61 this.parent = parent;
62 }
63
64
65
66
67
68
69
70
71
72 public void setSiblings(final String siblingsTitle, final List siblingPages) {
73 this.siblingsTitle = siblingsTitle;
74 this.siblings = siblingPages;
75 }
76
77 public void addChild(final NavigationNode child) {
78 this.children.add(child);
79 child.setParent(this);
80 }
81
82
83
84
85 public String getURL() {
86 return this.fileName + ".html";
87 }
88
89
90
91
92 public String getShortTitle() {
93 return this.shortTitle;
94 }
95
96
97
98
99 public String getFullTitle() {
100 return this.fullTitle;
101 }
102
103 public void setShowLinkToPreviousSibling(final boolean showLink) {
104 this.showLinkToPreviousSibling = showLink;
105 }
106
107 public void addAttribute(final String key, final int value) {
108 addAttribute(key, Integer.toString(value));
109 }
110
111 public void addAttribute(final String key, final int value, final String unit) {
112 addAttribute(key, Integer.toString(value) + " " + unit);
113 }
114
115 public void addAttribute(final String key, final Date value) {
116 addRawAttribute(key, HTML.getDateAndTime(value));
117 }
118
119 public void addAttribute(final String key, final String value) {
120 addRawAttribute(key, HTML.escape(value));
121 }
122
123 public void addAttribute(final String key, final double value, final int decimalPlaces) {
124 addAttribute(key, DOUBLE_FORMATS[decimalPlaces].format(value));
125 }
126
127 public void addAttribute(final String key, final double value, final int decimalPlaces, final String unit) {
128 addAttribute(key, DOUBLE_FORMATS[decimalPlaces].format(value) + " " + unit);
129 }
130
131 public void addRawAttribute(final String key, final String rawValue) {
132 this.attributeKeys.add(key);
133 this.attributeValues.add(rawValue);
134 }
135
136 public void addRawContent(final String s) {
137 this.contents.append(s);
138 }
139
140 public void addSection(final String title) {
141 if (this.inSection) {
142 this.contents.append(this.outputFormat.endSection2());
143 }
144 this.contents.append(this.outputFormat.startSection2(title));
145 this.inSection = true;
146 }
147
148 public void addLink(final String url, final String text) {
149 this.addRawContent("<p>" + HTML.getLink(url, text) + "</p>\n");
150 }
151
152 public void add(final ChartImage chart) {
153 if (chart == null) {
154 return;
155 }
156 addRawContent("<p class=\"chart\"><img src=\"" + HTML.escape(chart.getURL()) + "\" alt=\"" + HTML.escape(chart.getFullTitle()) + "\" width=\""
157 + chart.getWidth() + "\" height=\"" + chart.getHeight() + "\" /></p>");
158 chart.write();
159 }
160
161 public void add(final ChartImage chart, final String linkURL) {
162 if (chart == null) {
163 return;
164 }
165 addRawContent("<p class=\"chart\"><a href=\"" + HTML.escape(linkURL) + "\"><img src=\"" + HTML.escape(chart.getURL()) + "\" alt=\""
166 + HTML.escape(chart.getFullTitle()) + "\" width=\"" + chart.getWidth() + "\" height=\"" + chart.getHeight() + "\" /></a></p>");
167 chart.write();
168 }
169
170 public void add(final TableReport table) {
171 table.calculate();
172 addRawContent(new TableRenderer(table.getTable(), this.outputFormat).getRenderedTable());
173 }
174
175 public void add(final Directory directory, final boolean withRootLinks) {
176 addRawContent(new DirectoryTreeFormatter(directory, withRootLinks).getFormatted());
177 }
178
179 public void add(final PageGroup pages) {
180 addRawContent(pages.asLinkList());
181 addChild(pages);
182 }
183
184
185
186
187 public void write() {
188 if (this.written) {
189 return;
190 }
191 if (this.inSection) {
192 this.contents.append(this.outputFormat.endSection2());
193 }
194 final Iterator it = this.children.iterator();
195 while (it.hasNext()) {
196 final NavigationNode page = (NavigationNode) it.next();
197 page.write();
198 }
199 final String fileWithExtension = this.fileName + "." + this.config.getMarkup().getExtension();
200 logger.info("writing page '" + this.fullTitle + "' to " + fileWithExtension);
201 FileWriter w = null;
202 try {
203 w = new FileWriter(this.config.getRootDirectory() + fileWithExtension);
204 w.write(this.outputFormat.getHeader(this.fullTitle, this.config.getCssHandler().getLink()));
205 w.write(this.outputFormat.startSection1(this.fullTitle));
206 w.write(getLinkToParent());
207 w.write(getNavigationLinks());
208 w.write(getAttributes());
209 w.write(this.contents.toString());
210 w.write(getLinkToPreviousSibling());
211 w.write(this.outputFormat.endSection1());
212 w.write(getGeneratedByBlock());
213 w.write(this.outputFormat.getEndOfPage());
214 } catch (final IOException ex) {
215 logger.warning(ex.getMessage());
216 } finally {
217 if (w != null) {
218 try {
219 w.close();
220 } catch (final IOException e) {
221 logger.warning(e.getMessage());
222 }
223 }
224 }
225 this.written = true;
226
227
228 this.contents = null;
229 }
230
231 public String asParentLink() {
232 String result = "« " + HTML.getLink(getURL(), getShortTitle());
233 if (this.parent != null) {
234 result = this.parent.asParentLink() + " " + result;
235 }
236 return result;
237 }
238
239 private String getLinkToParent() {
240 if (this.parent == null) {
241 return "";
242 }
243 return "<div id=\"parentlink\">" + this.parent.asParentLink() + "</div>\n";
244 }
245
246 private String getNavigationLinks() {
247 if (this.siblingsTitle == null || this.siblings.isEmpty()) {
248 return "";
249 }
250 final StringBuffer s = new StringBuffer();
251 s.append(this.outputFormat.startSection2(this.siblingsTitle, "nav"));
252 s.append("<ul>\n");
253 final Iterator it = this.siblings.iterator();
254 while (it.hasNext()) {
255 final NavigationNode sibling = (NavigationNode) it.next();
256 s.append(" <li>");
257 if (sibling == this) {
258 s.append("<span class=\"here\">" + HTML.escape(sibling.getShortTitle()) + "</span>");
259 } else {
260 s.append(HTML.getLink(sibling.getURL(), sibling.getShortTitle()));
261 }
262 s.append("</li>\n");
263 }
264 s.append("</ul>\n");
265 s.append(this.outputFormat.endSection2());
266 return s.toString();
267 }
268
269 private String getAttributes() {
270 if (this.attributeKeys.isEmpty()) {
271 return "";
272 }
273 final StringBuffer s = new StringBuffer();
274 s.append("<dl class=\"attributes\">\n");
275 for (int i = 0; i < this.attributeKeys.size(); i++) {
276 final String key = (String) this.attributeKeys.get(i);
277 final String value = (String) this.attributeValues.get(i);
278 s.append(" <dt>" + HTML.escape(key) + ":</dt>\n");
279 s.append(" <dd>" + value + "</dd>\n");
280 }
281 s.append("</dl>\n");
282 return s.toString();
283 }
284
285 private String getGeneratedByBlock() {
286 final StringBuffer s = new StringBuffer();
287 s.append("<div id=\"generatedby\">");
288 s.append(Messages.getString("PAGE_GENERATED_BY"));
289 s.append(" ");
290 s.append(HTML.getLink(Messages.getString("PROJECT_URL"), Messages.getString("PROJECT_SHORTNAME")) + " " + Messages.getString("PROJECT_VERSION"));
291 s.append("</div>\n");
292 return s.toString();
293 }
294
295 private String getLinkToPreviousSibling() {
296 if (!this.showLinkToPreviousSibling) {
297 return "";
298 }
299 final NavigationNode sibling = findPreviousSibling();
300 if (sibling == null) {
301 return "";
302 }
303 return "<p class=\"previous\">" + HTML.getLink(sibling.getURL(), sibling.getShortTitle()) + " » </p>\n";
304 }
305
306 private NavigationNode findPreviousSibling() {
307 final Iterator it = this.siblings.iterator();
308 while (it.hasNext()) {
309 final NavigationNode sibling = (NavigationNode) it.next();
310 if (sibling != this) {
311 continue;
312 }
313 if (!it.hasNext()) {
314 return null;
315 }
316 return (NavigationNode) it.next();
317 }
318 return null;
319 }
320 }