15
15
import org .apache .log4j .Logger ;
16
16
import org .apache .poi .xwpf .usermodel .*;
17
17
import org .apache .thrift .TException ;
18
+ import org .apache .xmlbeans .XmlCursor ;
18
19
import org .apache .xmlbeans .XmlException ;
19
20
import org .eclipse .sw360 .datahandler .common .CommonUtils ;
20
21
import org .eclipse .sw360 .datahandler .common .SW360Utils ;
29
30
import org .eclipse .sw360 .datahandler .thrift .licenses .LicenseService ;
30
31
import org .eclipse .sw360 .datahandler .thrift .licenses .Todo ;
31
32
import org .eclipse .sw360 .datahandler .thrift .projects .Project ;
33
+ import org .eclipse .sw360 .datahandler .thrift .projects .ProjectLink ;
34
+ import org .eclipse .sw360 .datahandler .thrift .projects .ProjectService ;
32
35
import org .eclipse .sw360 .datahandler .thrift .users .User ;
33
36
import org .eclipse .sw360 .datahandler .thrift .users .UserService ;
34
37
@@ -47,17 +50,24 @@ public class DocxGenerator extends OutputGenerator<byte[]> {
47
50
private static final Logger LOGGER = Logger .getLogger (DocxGenerator .class );
48
51
private static final String UNKNOWN_LICENSE_NAME = "Unknown license name" ;
49
52
private static final String UNKNOWN_FILE_NAME = "Unknown file name" ;
53
+ private static final String UNKNOWN_LICENSE = "Unknown" ;
50
54
private static final String TODO_DEFAULT_TEXT = "todo not determined so far." ;
51
55
52
56
private static final String DOCX_TEMPLATE_FILE = "/templateFrontpageContent.docx" ;
53
57
private static final String DOCX_TEMPLATE_REPORT_FILE = "/templateReport.docx" ;
54
58
private static final String DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ;
55
59
private static final String DOCX_OUTPUT_TYPE = "docx" ;
56
- public static final String UNKNOWN_LICENSE = "Unknown" ;
60
+
57
61
private static final long ADDITIONAL_REQ_THRESHOLD = 3 ;
58
- public static final int ADDITIONAL_REQ_TABLE_INDEX = 5 ;
62
+
63
+ public static final int OVERVIEW_TABLE_INDEX = 0 ;
64
+ public static final int SPECIAL_OSS_RISKS_TABLE_INDEX = 1 ;
59
65
public static final int DEV_DETAIL_TABLE_INDEX = 2 ;
66
+ public static final int THIRD_PARTY_COMPONENT_OVERVIEW_TABLE_INDEX = 3 ;
60
67
private static final int COMMON_RULES_TABLE_INDEX = 4 ;
68
+ public static final int ADDITIONAL_REQ_TABLE_INDEX = 5 ;
69
+
70
+
61
71
62
72
public DocxGenerator (OutputFormatVariant outputFormatVariant , String description ) {
63
73
super (DOCX_OUTPUT_TYPE , description , true , DOCX_MIME_TYPE , outputFormatVariant );
@@ -136,7 +146,7 @@ private void fillDisclosureDocument(
136
146
fillReleaseBulletList (document , projectLicenseInfoResults );
137
147
fillReleaseDetailList (document , projectLicenseInfoResults , includeObligations );
138
148
fillLicenseList (document , projectLicenseInfoResults );
139
- }
149
+ }
140
150
141
151
private void fillReportDocument (
142
152
XWPFDocument document ,
@@ -147,6 +157,7 @@ private void fillReportDocument(
147
157
Collection <ObligationParsingResult > obligationResults ,
148
158
User user ) throws XmlException , TException {
149
159
160
+ String businessUnit = project .getBusinessUnit ();
150
161
String projectName = project .getName ();
151
162
String projectVersion = project .getVersion ();
152
163
String obligationsText = project .getObligationsText ();
@@ -157,11 +168,13 @@ private void fillReportDocument(
157
168
String deliveryChannelsText = project .getDeliveryChannels ();
158
169
String remarksAdditionalRequirementsText = project .getRemarksAdditionalRequirements ();
159
170
String projectDescription = project .getDescription ();
160
-
171
+ // extract licenses that appear at least ADDITIONAL_REQ_THRESHOLD times
172
+ Set <String > mostLicenses = extractMostCommonLicenses (obligationResults , ADDITIONAL_REQ_THRESHOLD );
161
173
162
174
fillOwnerGroup (document , project );
163
175
fillAttendeesTable (document , project );
164
176
177
+ replaceText (document , "$bunit" , businessUnit );
165
178
replaceText (document , "$license-info-header" , licenseInfoHeaderText );
166
179
replaceText (document , "$project-name" , projectName );
167
180
replaceText (document , "$project-version" , projectVersion );
@@ -175,13 +188,13 @@ private void fillReportDocument(
175
188
replaceText (document , "$product-description" , projectDescription );
176
189
177
190
fillSpecialOSSRisksTable (document , project , obligationResults );
178
- fillDevelopmentDetailsTable (document , project , user );
191
+ fillDevelopmentDetailsTable (document , project , user , projectLicenseInfoResults );
179
192
fillOverview3rdPartyComponentTable (document , projectLicenseInfoResults );
193
+
180
194
fillCommonRulesTable (document , project );
181
- fillAdditionalRequirementsTable (document , obligationResults );
195
+ replaceText (document , "$list_comma_sep_licenses_above_threshold" , String .join (", " , mostLicenses ));
196
+ fillAdditionalRequirementsTable (document , obligationResults , mostLicenses );
182
197
183
- // because of the impossible API component subsections must be the last thing in the docx file
184
- // the rest of the sections must be generated after this
185
198
writeComponentSubsections (document , projectLicenseInfoResults , obligationResults );
186
199
}
187
200
@@ -194,9 +207,9 @@ private void fillOwnerGroup(XWPFDocument document, Project project) throws XmlEx
194
207
}
195
208
196
209
private void fillAttendeesTable (XWPFDocument document , Project project ) throws XmlException , TException {
197
- XWPFTable table = document .getTables ().get (0 );
210
+ XWPFTable table = document .getTables ().get (OVERVIEW_TABLE_INDEX );
198
211
199
- int currentRow = 6 ;
212
+ int currentRow = 7 ;
200
213
201
214
UserService .Iface userClient = new ThriftClients ().makeUserClient ();
202
215
@@ -220,7 +233,12 @@ private void fillAttendeesTable(XWPFDocument document, Project project) throws X
220
233
continue ;
221
234
}
222
235
223
- User user = userClient .getByEmail (email );
236
+ User user = null ;
237
+ try {
238
+ user = userClient .getByEmail (email );
239
+ } catch (TException te ) {
240
+ // a resulting null user object is handled below by replacing with email
241
+ }
224
242
225
243
XWPFTableRow row = table .insertNewTableRow (currentRow ++);
226
244
String name = email ;
@@ -229,7 +247,7 @@ private void fillAttendeesTable(XWPFDocument document, Project project) throws X
229
247
}
230
248
String department = "N.A." ;
231
249
if (user != null ) {
232
- name = user .getDepartment ();
250
+ department = user .getDepartment ();
233
251
}
234
252
235
253
row .addNewTableCell ().setText (name );
@@ -241,7 +259,7 @@ private void fillAttendeesTable(XWPFDocument document, Project project) throws X
241
259
}
242
260
243
261
private void fillSpecialOSSRisksTable (XWPFDocument document , Project project , Collection <ObligationParsingResult > obligationResults ) throws XmlException , TException {
244
- XWPFTable table = document .getTables ().get (1 );
262
+ XWPFTable table = document .getTables ().get (SPECIAL_OSS_RISKS_TABLE_INDEX );
245
263
final int [] currentRow = new int []{0 };
246
264
247
265
obligationResults .stream ()
@@ -260,7 +278,7 @@ private void fillSpecialOSSRisksTable(XWPFDocument document, Project project, Co
260
278
}
261
279
262
280
private void fillOverview3rdPartyComponentTable (XWPFDocument document , Collection <LicenseInfoParsingResult > projectLicenseInfoResults ) throws XmlException {
263
- XWPFTable table = document .getTables ().get (3 );
281
+ XWPFTable table = document .getTables ().get (THIRD_PARTY_COMPONENT_OVERVIEW_TABLE_INDEX );
264
282
265
283
int currentRow = 1 ;
266
284
for (LicenseInfoParsingResult result : projectLicenseInfoResults ) {
@@ -292,17 +310,31 @@ private static Optional<ObligationParsingResult> obligationsForRelease(Release r
292
310
return obligationResults .stream ().filter (opr -> opr .getRelease () == release ).findFirst ();
293
311
}
294
312
295
- private void writeComponentSubsections (XWPFDocument document , Collection <LicenseInfoParsingResult > projectLicenseInfoResults , Collection <ObligationParsingResult > obligationResults ) throws XmlException {
313
+ private void writeComponentSubsections (XWPFDocument document , Collection <LicenseInfoParsingResult > projectLicenseInfoResults , Collection <ObligationParsingResult > obligationResults ) throws SW360Exception , XmlException {
314
+ XmlCursor cursor = document .getTables ().get (ADDITIONAL_REQ_TABLE_INDEX ).getCTTbl ().newCursor ();
315
+ cursor .toEndToken ();
296
316
297
317
for (LicenseInfoParsingResult result : projectLicenseInfoResults ) {
318
+ while (cursor .currentTokenType () != XmlCursor .TokenType .START && cursor .hasNextToken ()) {
319
+ cursor .toNextToken ();
320
+ }
298
321
299
- XWPFParagraph title = document .createParagraph ();
322
+ if (cursor .currentTokenType () != XmlCursor .TokenType .START ) {
323
+ throw new SW360Exception ("Corrupt template; unable find start token" );
324
+ }
325
+
326
+ XWPFParagraph title = document .insertNewParagraph (cursor );
300
327
title .setStyle (STYLE_HEADING_3 );
301
328
title .setNumID (new BigInteger ("2" ));
302
329
XWPFRun titleRun = title .createRun ();
303
330
titleRun .setText (result .getVendor () + " " + result .getName ());
304
331
305
- XWPFParagraph description = document .createParagraph ();
332
+ if (cursor .hasNextToken ()) {
333
+ cursor .toNextToken ();
334
+ } else {
335
+ throw new SW360Exception ("Corrupt template; unable to proceed to next token" );
336
+ }
337
+ XWPFParagraph description = document .insertNewParagraph (cursor );
306
338
XWPFRun descriptionRun = description .createRun ();
307
339
308
340
LicenseInfo licenseInfo = result .getLicenseInfo ();
@@ -331,7 +363,7 @@ private void writeComponentSubsections(XWPFDocument document, Collection<License
331
363
332
364
int currentRow = 0 ;
333
365
Collection <Obligation > obligations = obligationsResult .getObligations ();
334
- XWPFTable table = document .createTable ( );
366
+ XWPFTable table = document .insertNewTbl ( cursor );
335
367
for (Obligation o : obligations ) {
336
368
XWPFTableRow row = table .insertNewTableRow (currentRow ++);
337
369
String licensesString = String .join (" " , o .getLicenseIDs ());
@@ -343,29 +375,34 @@ private void writeComponentSubsections(XWPFDocument document, Collection<License
343
375
}
344
376
}
345
377
346
- private void fillDevelopmentDetailsTable (XWPFDocument document , Project project , User user ) throws TException {
378
+ private void fillDevelopmentDetailsTable (XWPFDocument document , Project project , User user , Collection < LicenseInfoParsingResult > projectLicenseInfoResults ) throws TException {
347
379
XWPFTable table = document .getTables ().get (DEV_DETAIL_TABLE_INDEX );
348
380
349
381
int currentRow = 1 ;
350
382
351
- ComponentService .Iface compClient = new ThriftClients ().makeComponentClient ();
352
- List <ReleaseLink > rll = compClient .getLinkedReleases (project .getReleaseIdToUsage ());
383
+ for (LicenseInfoParsingResult result : projectLicenseInfoResults ) {
384
+ if (result .getStatus () != LicenseInfoRequestStatus .SUCCESS ) {
385
+ // this error handling is for extra safety since projectLicenseInfoResults is provided by the caller
386
+ // and we assume valid input so we silently ignoring it.
387
+ continue ;
388
+ }
353
389
354
- for (ReleaseLink rl : rll ) {
355
- Release r = compClient .getReleaseById (rl .getId (), user );
356
- Component component = compClient .getComponentById (r .getComponentId (), user );
390
+ Release r = result .getRelease ();
391
+ if (r == null ) {
392
+ continue ;
393
+ }
357
394
358
395
XWPFTableRow row = table .insertNewTableRow (currentRow ++);
359
396
360
- row .addNewTableCell ().setText (component .getName ());
397
+ row .addNewTableCell ().setText (r .getName ());
361
398
362
- String operatingSystems = component .getOperatingSystemsSize () == 0 ? "Unknown operating systems " : String .join (" " , component .getOperatingSystems ());
399
+ String operatingSystems = r .getOperatingSystemsSize () == 0 ? "N/A " : String .join (" " , r .getOperatingSystems ());
363
400
row .addNewTableCell ().setText (operatingSystems );
364
401
365
- String langs = component .getLanguagesSize () == 0 ? "Unknown languages " : String .join (" " , component .getLanguages ());
402
+ String langs = r .getLanguagesSize () == 0 ? "N/A " : String .join (" " , r .getLanguages ());
366
403
row .addNewTableCell ().setText (langs );
367
404
368
- String platforms = component .getSoftwarePlatformsSize () == 0 ? "Unknown platforms " : String .join (" " , component .getSoftwarePlatforms ());
405
+ String platforms = r .getSoftwarePlatformsSize () == 0 ? "N/A " : String .join (" " , r .getSoftwarePlatforms ());
369
406
row .addNewTableCell ().setText (platforms );
370
407
}
371
408
}
@@ -379,21 +416,19 @@ protected static Set<String> extractMostCommonLicenses(Collection<ObligationPars
379
416
.entrySet ().stream ()
380
417
.filter (entry -> entry .getValue ().longValue () >= threshold )
381
418
.map (entry -> entry .getKey ())
419
+ .map (license -> license .replace ("\n " , "" ).replace ("\r " , "" ))
382
420
.collect (Collectors .toSet ());
383
421
}
384
422
385
- private void fillAdditionalRequirementsTable (XWPFDocument document , Collection <ObligationParsingResult > obligationResults ) throws XmlException {
386
- // extract licenses that appear at least ADDITIONAL_REQ_THRESHOLD times
387
- Set <String > mostLicenses = extractMostCommonLicenses (obligationResults , ADDITIONAL_REQ_THRESHOLD );
388
-
423
+ private void fillAdditionalRequirementsTable (XWPFDocument document , Collection <ObligationParsingResult > obligationResults , Set <String > mostLicenses ) throws XmlException {
389
424
XWPFTable table = document .getTables ().get (ADDITIONAL_REQ_TABLE_INDEX );
390
425
final int [] currentRow = new int []{0 };
391
426
392
427
obligationResults .stream ()
393
428
.filter (opr -> opr .getStatus () == ObligationInfoRequestStatus .SUCCESS )
394
429
.flatMap (opr -> opr .getObligations ().stream ())
395
430
.filter (o -> o .getLicenseIDs ().stream ()
396
- .anyMatch (lid -> mostLicenses .parallelStream ().anyMatch (mlid -> mlid .equals (lid ))))
431
+ .anyMatch (lid -> mostLicenses .parallelStream ().anyMatch (mlid -> mlid .equals (lid . replace ( " \n " , "" ). replace ( " \r " , "" ) ))))
397
432
.forEach (o -> {
398
433
currentRow [0 ] = currentRow [0 ] + 1 ;
399
434
XWPFTableRow row = table .insertNewTableRow (currentRow [0 ]);
0 commit comments