View Javadoc
1   /*
2    *    Copyright 2010-2026 the original author or authors.
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    *       https://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 org.mybatis.maven.mvnmigrate.report;
17  
18  import java.util.List;
19  import java.util.Map;
20  import java.util.Map.Entry;
21  import java.util.ResourceBundle;
22  
23  import org.apache.ibatis.migration.Change;
24  import org.apache.maven.doxia.sink.Sink;
25  import org.apache.maven.project.MavenProject;
26  
27  /**
28   * View of status report.
29   */
30  public final class MigrationStatusReportView {
31  
32    /**
33     * Generates the report.
34     *
35     * @param changes
36     *          list of {@link Change}
37     * @param sink
38     *          the {@link Sink} instance
39     * @param bundle
40     *          the {@link ResourceBundle} instance
41     */
42    public void generateReport(Map<MavenProject, List<Change>> changes, Sink sink, ResourceBundle bundle,
43        boolean isAggregate) {
44  
45      sink.head();
46      sink.title();
47      sink.text(bundle.getString("migration.status.report.header"));
48      sink.title_();
49      sink.head_();
50      sink.body();
51  
52      // Generate title
53      sink.section1();
54      sink.sectionTitle1();
55      sink.text(bundle.getString("migration.status.report.mainTitle"));
56      sink.sectionTitle1_();
57      sink.section1_();
58      sink.lineBreak();
59  
60      sink.section2();
61      sink.sectionTitle2();
62      sink.text(bundle.getString("migration.status.report.secondSectionTitle"));
63      sink.sectionTitle2_();
64  
65      for (Entry<MavenProject, List<Change>> entries : changes.entrySet()) {
66        if (isAggregate) {
67          sink.section3();
68          sink.sectionTitle3();
69          sink.text(bundle.getString("migration.status.report.moduleTitle") + entries.getKey().getName());
70          sink.sectionTitle3_();
71        }
72        generateStatisticsTable(sink, entries.getValue());
73      }
74  
75      sink.section2_();
76      sink.lineBreak();
77  
78      sink.section3();
79      sink.sectionTitle2();
80      sink.text(bundle.getString("migration.status.report.thirdSectionTitle"));
81      sink.sectionTitle2_();
82      for (Entry<MavenProject, List<Change>> entries : changes.entrySet()) {
83        if (isAggregate) {
84          sink.section3();
85          sink.sectionTitle3();
86          sink.text(bundle.getString("migration.status.report.moduleTitle") + entries.getKey().getName());
87          sink.sectionTitle3_();
88        }
89        // Generate Unused declared dependencies:
90        generateChangesTable(sink, entries.getValue());
91      }
92  
93      sink.section3_();
94  
95      // Closing the report
96      sink.body_();
97      sink.flush();
98      sink.close();
99    }
100 
101   /**
102    * Generates statistic table.
103    *
104    * @param sink
105    *          the sink
106    * @param changes
107    *          the changes
108    */
109   private void generateStatisticsTable(Sink sink, List<Change> changes) {
110     sink.table();
111 
112     sink.tableRow();
113     sink.tableCell();
114     sink.text(" Number of migration changes: ");
115     sink.tableCell_();
116 
117     sink.tableCell();
118     sink.text("" + changes.size());
119     sink.tableCell_();
120     sink.tableRow_();
121 
122     sink.tableRow();
123     sink.tableCell();
124     sink.text(" Number of pending migrations: ");
125     sink.tableCell_();
126 
127     int nop = numberOfPending(changes);
128 
129     sink.tableCell();
130     sink.text(nop + "  (" + calcPerc(changes.size(), nop) + ")  ");
131     sink.nonBreakingSpace();
132     sink.figure();
133     sink.figureGraphics(nop == 0 ? "images/icon_success_sml.gif" : "images/icon_warning_sml.gif");
134     sink.figure_();
135     sink.tableCell_();
136     sink.tableRow_();
137 
138     sink.table_();
139   }
140 
141   /**
142    * Calculates the percentage.
143    *
144    * @param tot
145    *          the tot
146    * @param nop
147    *          the nop
148    *
149    * @return the string
150    */
151   private String calcPerc(int tot, int nop) {
152     if (tot == 0) {
153       return "0%";
154     }
155     return "" + ((100 * nop) / tot) + "%";
156   }
157 
158   /**
159    * Return the number of pending change found.
160    *
161    * @param changes
162    *          list of {@link Change}
163    *
164    * @return Return the number of pending change found.
165    */
166   private int numberOfPending(List<Change> changes) {
167     int numberOfPending = 0;
168     for (Change change : changes) {
169       if (change.getAppliedTimestamp() == null) {
170         numberOfPending++;
171       }
172     }
173     return numberOfPending;
174   }
175 
176   /**
177    * Generate a table for the given dependencies iterator.
178    *
179    * @param sink
180    *          the {@link Sink} instance
181    * @param iter
182    *          list of {@link Change}
183    */
184   public void generateChangesTable(Sink sink, List<Change> iter) {
185     sink.table();
186 
187     sink.tableRow();
188     sink.tableCell();
189     sink.bold();
190     sink.text("ID");
191     sink.bold_();
192     sink.tableCell_();
193 
194     sink.tableCell();
195     sink.bold();
196     sink.text("Applied At");
197     sink.bold_();
198     sink.tableCell_();
199 
200     sink.tableCell();
201     sink.bold();
202     sink.text("Description");
203     sink.bold_();
204     sink.tableCell_();
205 
206     sink.tableCell();
207     sink.bold();
208     sink.text("Filename");
209     sink.bold_();
210     sink.tableCell_();
211 
212     sink.tableCell();
213     sink.bold();
214     sink.text("Status");
215     sink.bold_();
216     sink.tableCell_();
217 
218     sink.tableRow_();
219 
220     for (Change change : iter) {
221       sink.tableRow();
222 
223       sink.tableCell();
224       sink.text("" + change.getId());
225       sink.tableCell_();
226 
227       sink.tableCell();
228       sink.text(change.getAppliedTimestamp() == null ? " ... pending ... " : change.getAppliedTimestamp());
229       sink.tableCell_();
230 
231       sink.tableCell();
232       sink.text(change.getDescription());
233       sink.tableCell_();
234 
235       sink.tableCell();
236       sink.text(change.getFilename());
237       sink.tableCell_();
238 
239       sink.tableCell();
240       sink.figure();
241       sink.figureGraphics(
242           change.getAppliedTimestamp() != null ? "images/icon_success_sml.gif" : "images/icon_warning_sml.gif");
243       sink.figure_();
244       sink.tableCell_();
245 
246       sink.tableRow_();
247     }
248 
249     sink.table_();
250     sink.horizontalRule();
251   }
252 
253 }