View Javadoc

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(0);
36      private final List attributeKeys = new ArrayList(0);
37      private final List attributeValues = new ArrayList(0);
38      private boolean showLinkToPreviousSibling = false;
39      private boolean inSection = false;
40      private boolean written = false;
41  
42      /**
43       * Creates a new page.
44       * @param config The configuration to use
45       * @param fileName File name for the page, <em>without</em> file extension
46       * @param shortTitle A short navigation title
47       * @param fullTitle A full headline title
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      /* (non-Javadoc)
58       * @see net.sf.statcvs.pages.NavigationNode#setParent(net.sf.statcvs.pages.NavigationNode)
59       */
60      public void setParent(final NavigationNode parent) {
61          this.parent = parent;
62      }
63  
64      /**
65       * Sets a list of {@link Page}s that are siblings of this page.
66       * The generated page will contain a navigation list that links
67       * to all siblings. The sibling list may contain the page
68       * itself.
69       * @param siblingsTitle Title for navigation list, e.g. "Monthly Reports"
70       * @param sibling A list of {@link Page}s
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      /* (non-Javadoc)
83       * @see net.sf.statcvs.pages.NavigationNode#getURL()
84       */
85      public String getURL() {
86          return this.fileName + ".html";
87      }
88  
89      /* (non-Javadoc)
90       * @see net.sf.statcvs.pages.NavigationNode#getShortTitle()
91       */
92      public String getShortTitle() {
93          return this.shortTitle;
94      }
95  
96      /* (non-Javadoc)
97       * @see net.sf.statcvs.pages.NavigationNode#getFullTitle()
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     /* (non-Javadoc)
185      * @see net.sf.statcvs.pages.NavigationNode#write()
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.setParent(this);
198             page.write();
199         }
200         final String fileWithExtension = this.fileName + "." + this.config.getMarkup().getExtension();
201         logger.info("writing page '" + this.fullTitle + "' to " + fileWithExtension);
202         FileWriter w = null;
203         try {
204             w = new FileWriter(this.config.getRootDirectory() + fileWithExtension);
205             w.write(this.outputFormat.getHeader(this.fullTitle, this.config.getCssHandler().getLink(), config.getCharSet()));
206             w.write(this.outputFormat.startSection1(this.fullTitle));
207             w.write(getLinkToParent());
208             w.write(getNavigationLinks());
209             w.write(getAttributes());
210             w.write(this.contents.toString());
211             w.write(getLinkToPreviousSibling());
212             w.write(this.outputFormat.endSection1());
213             w.write(getGeneratedByBlock());
214             w.write(this.outputFormat.getEndOfPage());
215         } catch (final IOException ex) {
216             logger.warning(ex.getMessage());
217         } finally {
218             if (w != null) {
219                 try {
220                     w.close();
221                 } catch (final IOException e) {
222                     logger.warning(e.getMessage());
223                 }
224             }
225         }
226         this.written = true;
227 
228         // Free memory? Not sure if this has any effect ...
229         this.contents = null;
230     }
231 
232     public String asParentLink() {
233         String result = "&#171; " + HTML.getLink(getURL(), getShortTitle());
234         if (this.parent != null) {
235             result = this.parent.asParentLink() + " " + result;
236         }
237         return result;
238     }
239 
240     private String getLinkToParent() {
241         if (this.parent == null) {
242             return "";
243         }
244         return "<div id=\"parentlink\">" + this.parent.asParentLink() + "</div>\n";
245     }
246 
247     private String getNavigationLinks() {
248         if (this.siblingsTitle == null || this.siblings.isEmpty()) {
249             return "";
250         }
251         final StringBuffer s = new StringBuffer();
252         s.append(this.outputFormat.startSection2(this.siblingsTitle, "nav"));
253         s.append("<ul>\n");
254         final Iterator it = this.siblings.iterator();
255         while (it.hasNext()) {
256             final NavigationNode sibling = (NavigationNode) it.next();
257             s.append("    <li>");
258             if (sibling == this) {
259                 s.append("<span class=\"here\">" + HTML.escape(sibling.getShortTitle()) + "</span>");
260             } else {
261                 s.append(HTML.getLink(sibling.getURL(), sibling.getShortTitle()));
262             }
263             s.append("</li>\n");
264         }
265         s.append("</ul>\n");
266         s.append(this.outputFormat.endSection2());
267         return s.toString();
268     }
269 
270     private String getAttributes() {
271         if (this.attributeKeys.isEmpty()) {
272             return "";
273         }
274         final StringBuffer s = new StringBuffer();
275         s.append("<dl class=\"attributes\">\n");
276         for (int i = 0; i < this.attributeKeys.size(); i++) {
277             final String key = (String) this.attributeKeys.get(i);
278             final String value = (String) this.attributeValues.get(i);
279             s.append("    <dt>" + HTML.escape(key) + ":</dt>\n");
280             s.append("    <dd>" + value + "</dd>\n");
281         }
282         s.append("</dl>\n");
283         return s.toString();
284     }
285 
286     private String getGeneratedByBlock() {
287         final StringBuffer s = new StringBuffer();
288         s.append("<div id=\"generatedby\">");
289         s.append(Messages.getString("PAGE_GENERATED_BY"));
290         s.append(" ");
291         s.append(HTML.getLink(Messages.getString("PROJECT_URL"), Messages.getString("PROJECT_SHORTNAME")) + " " + Messages.getString("PROJECT_VERSION"));
292         s.append("</div>\n");
293         return s.toString();
294     }
295 
296     private String getLinkToPreviousSibling() {
297         if (!this.showLinkToPreviousSibling) {
298             return "";
299         }
300         final NavigationNode sibling = findPreviousSibling();
301         if (sibling == null) {
302             return "";
303         }
304         return "<p class=\"previous\">" + HTML.getLink(sibling.getURL(), sibling.getShortTitle()) + " &#187; </p>\n";
305     }
306 
307     private NavigationNode findPreviousSibling() {
308         final Iterator it = this.siblings.iterator();
309         while (it.hasNext()) {
310             final NavigationNode sibling = (NavigationNode) it.next();
311             if (sibling != this) {
312                 continue;
313             }
314             if (!it.hasNext()) {
315                 return null;
316             }
317             return (NavigationNode) it.next();
318         }
319         return null;
320     }
321 }