View Javadoc

1   /*
2    * Copyright 2008-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.maven.issues.bugzilla;
17  
18  import java.io.IOException;
19  import java.io.StringReader;
20  import java.util.List;
21  import java.util.ResourceBundle;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.maven.doxia.module.xdoc.XdocParser;
26  import org.apache.maven.doxia.parser.ParseException;
27  import org.apache.maven.doxia.sink.Sink;
28  import org.apache.maven.reporting.AbstractMavenReportRenderer;
29  import org.codehaus.plexus.util.StringUtils;
30  import org.eclipse.mylyn.internal.bugzilla.core.BugzillaAttribute;
31  import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
32  import org.eclipse.mylyn.tasks.core.data.TaskData;
33  
34  import de.smartics.maven.issues.RendererConfig;
35  
36  /**
37   * The renderer provides helper methods to render a table.
38   *
39   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
40   */
41  public abstract class AbstractIssuesReportRenderer extends
42      AbstractMavenReportRenderer
43  {
44    // ********************************* Fields *********************************
45  
46    // --- constants ------------------------------------------------------------
47  
48    /**
49     * Reference to the logger for this class.
50     */
51    private static final Log LOG = LogFactory
52        .getLog(AbstractIssuesReportRenderer.class);
53  
54    // --- members --------------------------------------------------------------
55  
56    /**
57     * The configuration to control the rendering process.
58     */
59    protected final RendererConfig config;
60  
61    /**
62     * The issue information to render in the report.
63     */
64    protected final List<TaskData> issues;
65  
66    // ****************************** Initializer *******************************
67  
68    // ****************************** Constructors ******************************
69  
70    /**
71     * Default constructor.
72     *
73     * @param config the configuration to control the rendering process.
74     * @param sink the sink to write to.
75     * @param issues the issue information to render in the report.
76     */
77    protected AbstractIssuesReportRenderer(final RendererConfig config,
78        final Sink sink, final List<TaskData> issues)
79    {
80      super(sink);
81      this.config = config;
82      this.issues = issues;
83      if (LOG.isTraceEnabled())
84      {
85        LOG.trace("Created renderer class instance '" + getClass().getName()
86                  + "' using this configuration: " + config);
87      }
88    }
89  
90    // ****************************** Inner Classes *****************************
91  
92    // ********************************* Methods ********************************
93  
94    // --- init -----------------------------------------------------------------
95  
96    // --- get&set --------------------------------------------------------------
97  
98    /**
99     * Returns a short description of the report.
100    *
101    * @return a short description of the report.
102    */
103   protected abstract String getDescription();
104 
105   /**
106    * Returns a short description of the report when there are no results.
107    *
108    * @return a short description of the report when there are no results.
109    */
110   protected abstract String getNoResultsDescription();
111 
112   /**
113    * Returns the title set in the configuration and if unset there, the label
114    * provided by the configuration's resource bundle.
115    *
116    * @param key the key to select the label if the title is not explicitly set.
117    * @return the localized title to render.
118    */
119   protected String getTitle(final String key)
120   {
121     final String title = config.getTitle();
122     if (title != null)
123     {
124       return title;
125     }
126     return config.getBundle().getString(key);
127   }
128 
129   /**
130    * Returns the description set in the configuration and if unset there, the
131    * label provided by the configuration's resource bundle.
132    *
133    * @param key the key to select the label if the title is not explicitly set.
134    * @return the localized description to render.
135    */
136   protected String getDescription(final String key)
137   {
138     final String description = config.getDescription();
139     if (description != null)
140     {
141       return description;
142     }
143     return config.getBundle().getString(key);
144   }
145 
146   /**
147    * Returns the description if the query matches no issue set in the
148    * configuration and if unset there, the label provided by the configuration's
149    * resource bundle.
150    *
151    * @param key the key to select the label if the title is not explicitly set.
152    * @return the localized description to render.
153    */
154   protected String getNoResultsDescription(final String key)
155   {
156     final String description = config.getNoResultsDescription();
157     if (description != null)
158     {
159       return description;
160     }
161     return config.getBundle().getString(key);
162   }
163 
164   // --- business -------------------------------------------------------------
165 
166   /**
167    * Renders the title block of the report.
168    *
169    * @param noResults <code>true</code> if the report renders no results (no
170    *          issue matches the query), <code>false</code> otherwise.
171    */
172   protected void renderTitle(final boolean noResults)
173   {
174     sink.sectionTitle1();
175     sink.text(getTitle());
176     sink.sectionTitle1_();
177     renderDescription(noResults);
178   }
179 
180   /**
181    * Renders the description below the main title.
182    *
183    * @param noResults <code>true</code> if the report renders no results (no
184    *          issue matches the query), <code>false</code> otherwise.
185    */
186   private void renderDescription(final boolean noResults)
187   {
188     if (noResults)
189     {
190       final String description = getNoResultsDescription();
191       if (StringUtils.isNotBlank(description))
192       {
193         sink.paragraph();
194         sink.text(description);
195         sink.paragraph_();
196       }
197     }
198     else
199     {
200       final boolean written = writeBodyContent();
201       if (!written)
202       {
203         final String description = getDescription();
204         if (StringUtils.isNotBlank(description))
205         {
206           sink.paragraph();
207           sink.text(description);
208           sink.paragraph_();
209         }
210       }
211     }
212   }
213 
214   /**
215    * Writes the body content.
216    *
217    * @return <code>true</code> if the content is successfully written,
218    *         <code>false</code> otherwise.
219    */
220   private boolean writeBodyContent()
221   {
222     try
223     {
224       final String bodyContent = config.getDescriptionFileBodyContent();
225       if (!"".equals(bodyContent))
226       {
227         final XdocParser parser = new XdocParser();
228         parser.parse(new StringReader(bodyContent), sink);
229         // sink.rawText(bodyContent);
230         return true;
231       }
232     }
233     catch (final IOException e)
234     {
235       if (LOG.isWarnEnabled())
236       {
237         LOG.warn("Cannot read description file '"
238                  + config.getDescriptionFile().getAbsolutePath() + "'.");
239       }
240     }
241     catch (final ParseException e)
242     {
243       if (LOG.isWarnEnabled())
244       {
245         LOG.warn("Cannot read description file '"
246                  + config.getDescriptionFile().getAbsolutePath() + "'.");
247       }
248     }
249     return false;
250   }
251 
252   /**
253    * Renders the footer text.
254    */
255   protected void renderFooter()
256   {
257     final String footerText = config.getFooterText();
258     if (StringUtils.isNotBlank(footerText))
259     {
260       sink.rawText(footerText);
261     }
262   }
263 
264   /**
265    * Renders a table header.
266    */
267   protected void renderTableHeader()
268   {
269     final ResourceBundle bundle = config.getBundle();
270     final List<String> columns = config.getColumns();
271     final List<String> columnWidths = config.getColumnWidths();
272 
273     int i = 0;
274     sink.tableRow();
275     for (String column : columns)
276     {
277       final String label = ReportHelper.getLabel(bundle, column);
278       final String width = columnWidths.get(i);
279       if ("0".equals(width))
280       {
281         sink.tableHeaderCell();
282       }
283       else
284       {
285         sink.tableHeaderCell(width);
286       }
287       sink.text(label);
288       sink.tableHeaderCell_();
289       i++;
290     }
291     sink.tableRow_();
292   }
293 
294   /**
295    * Renders a table row.
296    *
297    * @param issue the issue whose values will be rendered to the columns.
298    */
299   protected void renderTableRow(final TaskData issue)
300   {
301     final boolean renderEmailAddresses = config.isRenderEmailAdresses();
302     final TaskAttribute root = issue.getRoot();
303     sink.tableRow();
304     final List<String> columns = config.getColumns();
305     for (String column : columns)
306     {
307       // TODO: Remove this dependency to Bugzilla (should be moved in the
308       // config). BugzillaAttribute.BUG_ID.getKey()
309       if (BugzillaAttribute.BUG_ID.getKey().equals(column))
310       {
311         final String id = issue.getTaskId();
312         // TODO: Remove this dependency to Bugzilla (should be moved in the
313         // config): "/show_bug.cgi?id="
314         final String url = issue.getRepositoryUrl() + "/show_bug.cgi?id=" + id;
315         ReportHelper.renderTableCellWithLink(sink, url, id);
316       }
317       else if (renderEmailAddresses
318                && ReportHelper.PERSON_NAME_TO_EMAIL.containsKey(column))
319       {
320         final String eMailKey = ReportHelper.PERSON_NAME_TO_EMAIL.get(column);
321         ReportHelper.renderTableCellWithMailto(sink, root, column, eMailKey);
322       }
323       else
324       {
325         ReportHelper.renderTableCell(sink, root, column);
326       }
327     }
328     sink.tableRow_();
329   }
330 
331   // --- object basics --------------------------------------------------------
332 
333 }