3131import java .nio .file .Path ;
3232import java .nio .file .Paths ;
3333import java .util .Collection ;
34+ import java .util .Collections ;
3435import java .util .Comparator ;
3536import java .util .HashMap ;
3637import java .util .LinkedList ;
3738import java .util .List ;
3839import java .util .Map ;
3940import java .util .Map .Entry ;
4041import java .util .Objects ;
42+ import java .util .stream .Collectors ;
4143import java .util .stream .Stream ;
4244import java .util .zip .ZipEntry ;
4345import java .util .zip .ZipOutputStream ;
@@ -67,12 +69,16 @@ public class ReportGenerator {
6769
6870 private static final String REFERENCE_METHOD_USE_LABEL = "referenced-method-uses" ;
6971
72+ private static final String BROKEN_FILE_LABEL = "broken-files" ;
73+
7074 // TODO romeara - In the future, should we investigate dynamic call-through to make this an actual handshake, and
7175 // not a manual constant? Aka ask the service what is allowed?
7276 // This is determined in conjunction with what the KB cloud services will allow - DO NOT adjust this number without
7377 // consultation with the maximum allowed by that service
7478 private static final int REFERENCE_MAX_CHUNK_SIZE = 1000 ;
7579
80+ private static final int BROKEN_FILE_MAX_CHUNK_SIZE = 1000 ;
81+
7682 private static final Gson GSON = new Gson ();
7783
7884 /** Logger reference to output information to the application log files */
@@ -104,9 +110,33 @@ public ReportGenerator(String hostName, String analyzedDirectory, @Nullable Stri
104110 * @return The path of the generated report on the file system
105111 * @throws IOException
106112 * If there is an error writing the report to the file system
113+ * @deprecated Use {@link #generateReport(Multimap, Map, Path, String)} instead
107114 */
115+ @ Deprecated
108116 public Path generateReport (Multimap <ReferencedMethod , MethodUse > references , Path outputDirectory , String outputFileName ) throws IOException {
117+ return generateReport (references , Collections .emptyMap (), outputDirectory , outputFileName );
118+ }
119+
120+ /**
121+ * Generates a report of the provided method references within a project
122+ *
123+ * @param references
124+ * The references to describe in a report
125+ * @param brokenFiles
126+ * Paths of any files for which analysis was attempted, by failed due to parser incompatibly of broken
127+ * file formatting (mapped to a message indicating the specific error)
128+ * @param outputDirectory
129+ * The directory to output the report to
130+ * @param outputFileName
131+ * The file name to use for the report (without extension)
132+ * @return The path of the generated report on the file system
133+ * @throws IOException
134+ * If there is an error writing the report to the file system
135+ */
136+ public Path generateReport (Multimap <ReferencedMethod , MethodUse > references , Map <Path , String > brokenFiles , Path outputDirectory , String outputFileName )
137+ throws IOException {
109138 Objects .requireNonNull (references );
139+ Objects .requireNonNull (brokenFiles );
110140 Objects .requireNonNull (outputDirectory );
111141 Objects .requireNonNull (outputFileName );
112142
@@ -125,7 +155,11 @@ public Path generateReport(Multimap<ReferencedMethod, MethodUse> references, Pat
125155 methodUses .add (new ReferencedMethodUsesJson (id .getSignature (), entry .getKey (), entry .getValue ()));
126156 }
127157
128- return writeReport (destinationFile , uniqueMethodKeys , methodUses );
158+ List <BrokenFileJson > brokenFileRecords = brokenFiles .entrySet ().stream ()
159+ .map (entry -> new BrokenFileJson (entry .getKey ().toString (), entry .getValue ()))
160+ .collect (Collectors .toList ());
161+
162+ return writeReport (destinationFile , uniqueMethodKeys , methodUses , brokenFileRecords );
129163 }
130164
131165 /**
@@ -137,14 +171,18 @@ public Path generateReport(Multimap<ReferencedMethod, MethodUse> references, Pat
137171 * List of unique, opaque keys referencing discovered methods
138172 * @param methodUses
139173 * Detailed description(s) of the method uses discovered
174+ * @param brokenFiles
175+ * Description of files which failed to parse
140176 * @return The path the report was written to
141177 * @throws IOException
142178 * If there is an error writing the report
143179 */
144- private Path writeReport (Path destinationFile , List <MethodIdJson > uniqueMethodKeys , List <ReferencedMethodUsesJson > methodUses ) throws IOException {
180+ private Path writeReport (Path destinationFile , List <MethodIdJson > uniqueMethodKeys , List <ReferencedMethodUsesJson > methodUses ,
181+ List <BrokenFileJson > brokenFiles ) throws IOException {
145182 Objects .requireNonNull (destinationFile );
146183 Objects .requireNonNull (uniqueMethodKeys );
147184 Objects .requireNonNull (methodUses );
185+ Objects .requireNonNull (brokenFiles );
148186
149187 Map <Path , Path > outputFileMapping = new HashMap <>();
150188
@@ -185,6 +223,18 @@ private Path writeReport(Path destinationFile, List<MethodIdJson> uniqueMethodKe
185223 }
186224 }
187225
226+ List <List <BrokenFileJson >> brokenFilePartitions = Lists .partition (brokenFiles , BROKEN_FILE_MAX_CHUNK_SIZE );
227+
228+ for (int index = 0 ; index < brokenFilePartitions .size (); index ++) {
229+ List <BrokenFileJson > brokenFilePartition = brokenFilePartitions .get (index );
230+
231+ Path brokenFilesFile = workingDirectory .resolve (BROKEN_FILE_LABEL + "-" + index + ".json" );
232+ try (BufferedWriter writer = Files .newBufferedWriter (brokenFilesFile )) {
233+ GSON .toJson (new BrokenFilesReportJson (brokenFilePartition ), writer );
234+ outputFileMapping .put (brokenFilesFile , Paths .get (BROKEN_FILE_LABEL ).resolve (brokenFilesFile .getFileName ()));
235+ }
236+ }
237+
188238 writeZipFile (destinationFile , outputFileMapping );
189239
190240 // GH-22: Explicitly clean up temporary files once use of them is complete
0 commit comments