• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / generator / 1947

14 Jan 2026 02:31PM UTC coverage: 88.838% (+0.04%) from 88.799%
1947

push

github

web-flow
Merge pull request #1411 from mybatis/renovate/github-codeql-action-digest

Update github/codeql-action digest to cdefb33

2347 of 3184 branches covered (73.71%)

11517 of 12964 relevant lines covered (88.84%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.82
/core/mybatis-generator-core/src/main/java/org/mybatis/generator/api/MyBatisGenerator.java
1
/*
2
 *    Copyright 2006-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.generator.api;
17

18
import static org.mybatis.generator.internal.util.ClassloaderUtility.getCustomClassloader;
19
import static org.mybatis.generator.internal.util.messages.Messages.getString;
20

21
import java.io.BufferedWriter;
22
import java.io.File;
23
import java.io.IOException;
24
import java.io.OutputStream;
25
import java.io.OutputStreamWriter;
26
import java.nio.charset.Charset;
27
import java.nio.file.Files;
28
import java.nio.file.Path;
29
import java.nio.file.StandardOpenOption;
30
import java.sql.SQLException;
31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.Collections;
34
import java.util.HashSet;
35
import java.util.List;
36
import java.util.Objects;
37
import java.util.Set;
38
import java.util.stream.Collectors;
39

40
import org.jspecify.annotations.Nullable;
41
import org.mybatis.generator.codegen.ContextResults;
42
import org.mybatis.generator.codegen.GenerationEngine;
43
import org.mybatis.generator.codegen.IntrospectionEngine;
44
import org.mybatis.generator.codegen.RootClassInfo;
45
import org.mybatis.generator.config.Configuration;
46
import org.mybatis.generator.config.Context;
47
import org.mybatis.generator.config.MergeConstants;
48
import org.mybatis.generator.exception.InvalidConfigurationException;
49
import org.mybatis.generator.exception.ShellException;
50
import org.mybatis.generator.internal.DefaultShellCallback;
51
import org.mybatis.generator.internal.ObjectFactory;
52
import org.mybatis.generator.internal.XmlFileMergerJaxp;
53

54
/**
55
 * This class is the main interface to MyBatis generator. A typical execution of the tool involves these steps:
56
 * <ol>
57
 * <li>Create a Configuration object. The Configuration can be the result of a parsing the XML configuration file, or it
58
 * can be created solely in Java.</li>
59
 * <li>Create a MyBatisGenerator object</li>
60
 * <li>Call one of the generate() methods</li>
61
 * </ol>
62
 *
63
 * @author Jeff Butler
64
 *
65
 * @see org.mybatis.generator.config.xml.ConfigurationParser
66
 */
67
public class MyBatisGenerator {
68
    private static final ProgressCallback NULL_PROGRESS_CALLBACK = new ProgressCallback() { };
1✔
69
    private final Configuration configuration;
70
    private final ShellCallback shellCallback;
71
    private final List<String> warnings;
72
    private final Set<String> projects = new HashSet<>();
1✔
73
    private final List<ContextResults> contextResultList = new ArrayList<>();
1✔
74

75
    /**
76
     * Constructs a MyBatisGenerator object.
77
     *
78
     * @param configuration
79
     *            The configuration for this invocation
80
     * @param shellCallback
81
     *            an instance of a ShellCallback interface. You may specify
82
     *            <code>null</code> in which case the DefaultShellCallback will
83
     *            be used.
84
     * @param warnings
85
     *            Any warnings generated during execution will be added to this
86
     *            list. Warnings do not affect the running of the tool, but they
87
     *            may affect the results. A typical warning is an unsupported
88
     *            data type. In that case, the column will be ignored and
89
     *            generation will continue. You may specify <code>null</code> if
90
     *            you do not want warnings returned.
91
     * @throws InvalidConfigurationException
92
     *             if the specified configuration is invalid
93
     */
94
    public MyBatisGenerator(Configuration configuration, @Nullable ShellCallback shellCallback,
95
            @Nullable List<String> warnings) throws InvalidConfigurationException {
1✔
96
        if (configuration == null) {
1!
97
            throw new IllegalArgumentException(getString("RuntimeError.2")); //$NON-NLS-1$
×
98
        } else {
99
            this.configuration = configuration;
1✔
100
        }
101

102
        this.shellCallback = Objects.requireNonNullElseGet(shellCallback, () -> new DefaultShellCallback(false));
1✔
103

104
        this.warnings = Objects.requireNonNullElseGet(warnings, ArrayList::new);
1✔
105

106
        this.configuration.validate();
1✔
107
    }
1✔
108

109
    /**
110
     * This is the main method for generating code. This method is long-running, but progress can be provided and the
111
     * method can be canceled through the ProgressCallback interface. This version of the method runs all configured
112
     * contexts.
113
     *
114
     * @param callback
115
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
116
     *            information
117
     * @throws SQLException
118
     *             the SQL exception
119
     * @throws IOException
120
     *             Signals that an I/O exception has occurred.
121
     * @throws InterruptedException
122
     *             if the method is canceled through the ProgressCallback
123
     */
124
    public void generate(ProgressCallback callback) throws SQLException,
125
            IOException, InterruptedException {
126
        generate(callback, null, null, true);
×
127
    }
×
128

129
    /**
130
     * This is the main method for generating code. This method is long-running, but progress can be provided and the
131
     * method can be canceled through the ProgressCallback interface.
132
     *
133
     * @param callback
134
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
135
     *            information
136
     * @param contextIds
137
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
138
     *            will be run. If the list is null or empty, then all contexts are run.
139
     * @throws SQLException
140
     *             the SQL exception
141
     * @throws IOException
142
     *             Signals that an I/O exception has occurred.
143
     * @throws InterruptedException
144
     *             if the method is canceled through the ProgressCallback
145
     */
146
    public void generate(ProgressCallback callback, Set<String> contextIds)
147
            throws SQLException, IOException, InterruptedException {
148
        generate(callback, contextIds, null, true);
×
149
    }
×
150

151
    /**
152
     * This is the main method for generating code. This method is long-running, but progress can be provided and the
153
     * method can be cancelled through the ProgressCallback interface.
154
     *
155
     * @param callback
156
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
157
     *            information
158
     * @param contextIds
159
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
160
     *            will be run. If the list is null or empty, then all contexts are run.
161
     * @param fullyQualifiedTableNames
162
     *            a set of table names to generate. The elements of the set must be Strings that exactly match what's
163
     *            specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
164
     *            qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
165
     *            will be used for code generation.
166
     * @throws SQLException
167
     *             the SQL exception
168
     * @throws IOException
169
     *             Signals that an I/O exception has occurred.
170
     * @throws InterruptedException
171
     *             if the method is canceled through the ProgressCallback
172
     */
173
    public void generate(@Nullable ProgressCallback callback, @Nullable Set<String> contextIds,
174
            @Nullable Set<String> fullyQualifiedTableNames) throws SQLException,
175
            IOException, InterruptedException {
176
        generate(callback, contextIds, fullyQualifiedTableNames, true);
×
177
    }
×
178

179
    /**
180
     * This is the main method for generating code. This method is long-running, but progress can be provided and the
181
     * method can be cancelled through the ProgressCallback interface.
182
     *
183
     * @param callback
184
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
185
     *            information
186
     * @param contextIds
187
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
188
     *            will be run. If the list is null or empty, then all contexts are run.
189
     * @param fullyQualifiedTableNames
190
     *            a set of table names to generate. The elements of the set must be Strings that exactly match what's
191
     *            specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
192
     *            qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
193
     *            will be used for code generation.
194
     * @param writeFiles
195
     *            if true, then the generated files will be written to disk.  If false,
196
     *            then the generator runs but nothing is written
197
     * @throws SQLException
198
     *             the SQL exception
199
     * @throws IOException
200
     *             Signals that an I/O exception has occurred.
201
     * @throws InterruptedException
202
     *             if the method is canceled through the ProgressCallback
203
     */
204
    public void generate(@Nullable ProgressCallback callback, @Nullable Set<String> contextIds,
205
                         @Nullable Set<String> fullyQualifiedTableNames, boolean writeFiles) throws SQLException,
206
            IOException, InterruptedException {
207

208
        if (callback == null) {
1!
209
            callback = NULL_PROGRESS_CALLBACK;
1✔
210
        }
211

212
        contextResultList.clear();
1✔
213
        ObjectFactory.reset();
1✔
214
        RootClassInfo.reset();
1✔
215

216
        // calculate the contexts to run
217
        List<Context> contextsToRun;
218
        if (contextIds == null || contextIds.isEmpty()) {
1!
219
            contextsToRun = configuration.getContexts();
1✔
220
        } else {
221
            contextsToRun = new ArrayList<>();
×
222
            for (Context context : configuration.getContexts()) {
×
223
                if (contextIds.contains(context.getId())) {
×
224
                    contextsToRun.add(context);
×
225
                }
226
            }
×
227
        }
228

229
        // setup custom classloader if required
230
        if (!configuration.getClassPathEntries().isEmpty()) {
1!
231
            ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
×
232
            ObjectFactory.addExternalClassLoader(classLoader);
×
233
        }
234

235
        // now run the introspections...
236
        int totalSteps = 0;
1✔
237
        for (Context context : contextsToRun) {
1✔
238
            totalSteps += context.getIntrospectionSteps();
1✔
239
        }
1✔
240
        callback.introspectionStarted(totalSteps);
1✔
241

242
        for (Context context : contextsToRun) {
1✔
243
            ContextResults contextResults = new ContextResults(context);
1✔
244
            this.contextResultList.add(contextResults);
1✔
245

246
            List<IntrospectedTable> introspectedTables = new IntrospectionEngine.Builder()
1✔
247
                    .withContext(context)
1✔
248
                    .withFullyQualifiedTableNames(
1✔
249
                            fullyQualifiedTableNames == null ? Collections.emptySet() : fullyQualifiedTableNames)
1!
250
                    .withWarnings(warnings)
1✔
251
                    .withProgressCallback(callback)
1✔
252
                    .withCommentGenerator(contextResults.commentGenerator())
1✔
253
                    .build()
1✔
254
                    .introspectTables();
1✔
255

256
            contextResults.addIntrospectedTables(introspectedTables);
1✔
257
        }
1✔
258

259
        // now run the generates
260
        totalSteps = 0;
1✔
261
        for (ContextResults contextResults : this.contextResultList) {
1✔
262
            totalSteps += contextResults.getGenerationSteps();
1✔
263
        }
1✔
264
        callback.generationStarted(totalSteps);
1✔
265

266
        for (ContextResults contextResults : this.contextResultList) {
1✔
267
            var generationEngine = new GenerationEngine.Builder()
1✔
268
                    .withContext(contextResults.context())
1✔
269
                    .withProgressCallback(callback)
1✔
270
                    .withWarnings(warnings)
1✔
271
                    .withIntrospectedTables(contextResults.introspectedTables())
1✔
272
                    .withCommentGenerator(contextResults.commentGenerator())
1✔
273
                    .build();
1✔
274

275
            contextResults.addGeneratedJavaFiles(generationEngine.generateJavaFiles());
1✔
276
            contextResults.addGeneratedXmlFiles(generationEngine.generateXmlFiles());
1✔
277
            contextResults.addGeneratedKotlinFiles(generationEngine.generateKotlinFiles());
1✔
278
            contextResults.addGeneratedGenericFiles(generationEngine.generateGenericFiles());
1✔
279
        }
1✔
280

281
        // now save the files
282
        if (writeFiles) {
1!
283
            totalSteps = 0;
×
284
            for (ContextResults contextResults : this.contextResultList) {
×
285
                totalSteps += contextResults.getNumberOfGeneratedFiles();
×
286
            }
×
287
            callback.saveStarted(totalSteps);
×
288

289
            for (ContextResults contextResults : this.contextResultList) {
×
290
                for (GeneratedXmlFile gxf : contextResults.generatedXmlFiles()) {
×
291
                    projects.add(gxf.getTargetProject());
×
292
                    writeGeneratedXmlFile(gxf, contextResults.xmlFormatter(), callback);
×
293
                }
×
294

295
                for (GeneratedJavaFile gjf : contextResults.generatedJavaFiles()) {
×
296
                    projects.add(gjf.getTargetProject());
×
297
                    writeGeneratedJavaFile(gjf, contextResults.javaFormatter(), contextResults.javaFileEncoding(),
×
298
                            callback);
299
                }
×
300

301
                for (GeneratedKotlinFile gkf : contextResults.generatedKotlinFiles()) {
×
302
                    projects.add(gkf.getTargetProject());
×
303
                    writeGeneratedKotlinFile(gkf, contextResults.kotlinFormatter(), contextResults.kotlinFileEncoding(),
×
304
                            callback);
305
                }
×
306

307
                for (GenericGeneratedFile gf : contextResults.generatedGenericFiles()) {
×
308
                    projects.add(gf.getTargetProject());
×
309
                    writeGenericGeneratedFile(gf, callback);
×
310
                }
×
311
            }
×
312

313
            for (String project : projects) {
×
314
                shellCallback.refreshProject(project);
×
315
            }
×
316
        }
317

318
        callback.done();
1✔
319
    }
1✔
320

321
    private void writeGeneratedJavaFile(GeneratedJavaFile gjf, JavaFormatter javaFormatter,
322
                                        @Nullable String javaFileEncoding, ProgressCallback callback)
323
            throws InterruptedException, IOException {
324
        Path targetFile;
325
        String source;
326
        try {
327
            File directory = shellCallback.getDirectory(gjf.getTargetProject(), gjf.getTargetPackage());
×
328
            targetFile = directory.toPath().resolve(gjf.getFileName());
×
329
            if (Files.exists(targetFile)) {
×
330
                if (shellCallback.isMergeSupported()) {
×
331
                    source = shellCallback.mergeJavaFile(
×
332
                            javaFormatter.getFormattedContent(gjf.getCompilationUnit()), targetFile.toFile(),
×
333
                            MergeConstants.getOldElementTags(), javaFileEncoding);
×
334
                } else if (shellCallback.isOverwriteEnabled()) {
×
335
                    source = javaFormatter.getFormattedContent(gjf.getCompilationUnit());
×
336
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
337
                } else {
338
                    source = javaFormatter.getFormattedContent(gjf.getCompilationUnit());
×
339
                    targetFile = getUniqueFileName(directory, gjf.getFileName());
×
340
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
341
                }
342
            } else {
343
                source = javaFormatter.getFormattedContent(gjf.getCompilationUnit());
×
344
            }
345

346
            callback.checkCancel();
×
347
            callback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
348
            writeFile(targetFile.toFile(), source, javaFileEncoding);
×
349
        } catch (ShellException e) {
×
350
            warnings.add(e.getMessage());
×
351
        }
×
352
    }
×
353

354
    private void writeGeneratedKotlinFile(GeneratedKotlinFile gf, KotlinFormatter kotlinFormatter,
355
                                          @Nullable String kotlinFileEncoding, ProgressCallback callback)
356
            throws InterruptedException, IOException {
357
        Path targetFile;
358
        String source;
359
        try {
360
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
361
            targetFile = directory.toPath().resolve(gf.getFileName());
×
362
            if (Files.exists(targetFile)) {
×
363
                if (shellCallback.isOverwriteEnabled()) {
×
364
                    source = kotlinFormatter.getFormattedContent(gf.getKotlinFile());
×
365
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
366
                } else {
367
                    source = kotlinFormatter.getFormattedContent(gf.getKotlinFile());
×
368
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
369
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
370
                }
371
            } else {
372
                source = kotlinFormatter.getFormattedContent(gf.getKotlinFile());
×
373
            }
374

375
            callback.checkCancel();
×
376
            callback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
377
            writeFile(targetFile.toFile(), source, kotlinFileEncoding);
×
378
        } catch (ShellException e) {
×
379
            warnings.add(e.getMessage());
×
380
        }
×
381
    }
×
382

383
    private void writeGenericGeneratedFile(GenericGeneratedFile gf, ProgressCallback callback)
384
            throws InterruptedException, IOException {
385
        Path targetFile;
386
        String source;
387
        try {
388
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
389
            targetFile = directory.toPath().resolve(gf.getFileName());
×
390
            if (Files.exists(targetFile)) {
×
391
                if (shellCallback.isOverwriteEnabled()) {
×
392
                    source = gf.getFormattedContent();
×
393
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
394
                } else {
395
                    source = gf.getFormattedContent();
×
396
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
397
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
398
                }
399
            } else {
400
                source = gf.getFormattedContent();
×
401
            }
402

403
            callback.checkCancel();
×
404
            callback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
405
            writeFile(targetFile.toFile(), source, gf.getFileEncoding().orElse(null));
×
406
        } catch (ShellException e) {
×
407
            warnings.add(e.getMessage());
×
408
        }
×
409
    }
×
410

411
    private void writeGeneratedXmlFile(GeneratedXmlFile gxf, XmlFormatter xmlFormatter, ProgressCallback callback)
412
            throws InterruptedException, IOException {
413
        Path targetFile;
414
        String source;
415
        try {
416
            File directory = shellCallback.getDirectory(gxf.getTargetProject(), gxf.getTargetPackage());
×
417
            targetFile = directory.toPath().resolve(gxf.getFileName());
×
418
            if (Files.exists(targetFile)) {
×
419
                if (gxf.isMergeable()) {
×
420
                    source = XmlFileMergerJaxp.getMergedSource(xmlFormatter.getFormattedContent(gxf.getDocument()),
×
421
                            targetFile.toFile());
×
422
                } else if (shellCallback.isOverwriteEnabled()) {
×
423
                    source = xmlFormatter.getFormattedContent(gxf.getDocument());
×
424
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
425
                } else {
426
                    source = xmlFormatter.getFormattedContent(gxf.getDocument());
×
427
                    targetFile = getUniqueFileName(directory, gxf.getFileName());
×
428
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
429
                }
430
            } else {
431
                source = xmlFormatter.getFormattedContent(gxf.getDocument());
×
432
            }
433

434
            callback.checkCancel();
×
435
            callback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
436
            writeFile(targetFile.toFile(), source, "UTF-8"); //$NON-NLS-1$
×
437
        } catch (ShellException e) {
×
438
            warnings.add(e.getMessage());
×
439
        }
×
440
    }
×
441

442
    /**
443
     * Writes, or overwrites, the contents of the specified file.
444
     *
445
     * @param file
446
     *            the file
447
     * @param content
448
     *            the content
449
     * @param fileEncoding
450
     *            the file encoding
451
     * @throws IOException
452
     *             Signals that an I/O exception has occurred.
453
     */
454
    private void writeFile(File file, String content, @Nullable String fileEncoding) throws IOException {
455
        try (OutputStream fos = Files.newOutputStream(file.toPath(), StandardOpenOption.CREATE,
×
456
                StandardOpenOption.TRUNCATE_EXISTING)) {
457
            OutputStreamWriter osw;
458
            if (fileEncoding == null) {
×
459
                osw = new OutputStreamWriter(fos);
×
460
            } else {
461
                osw = new OutputStreamWriter(fos, Charset.forName(fileEncoding));
×
462
            }
463

464
            try (BufferedWriter bw = new BufferedWriter(osw)) {
×
465
                bw.write(content);
×
466
            }
467
        }
468
    }
×
469

470
    /**
471
     * Gets the unique file name.
472
     *
473
     * @param directory
474
     *            the directory
475
     * @param fileName
476
     *            the file name
477
     * @return the unique file name
478
     */
479
    private Path getUniqueFileName(File directory, String fileName) {
480
        Path answer = null;
×
481

482
        // try up to 1000 times to generate a unique file name
483
        StringBuilder sb = new StringBuilder();
×
484
        for (int i = 1; i < 1000; i++) {
×
485
            sb.setLength(0);
×
486
            sb.append(fileName);
×
487
            sb.append('.');
×
488
            sb.append(i);
×
489

490
            Path testFile = directory.toPath().resolve(sb.toString());
×
491
            if (Files.notExists(testFile)) {
×
492
                answer = testFile;
×
493
                break;
×
494
            }
495
        }
496

497
        if (answer == null) {
×
498
            throw new RuntimeException(getString(
×
499
                    "RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
×
500
        }
501

502
        return answer;
×
503
    }
504

505
    /**
506
     * Returns the list of generated Java files after a call to one of the generate methods.
507
     * This is useful if you prefer to process the generated files yourself and do not want
508
     * the generator to write them to disk.
509
     *
510
     * @return the list of generated Java files
511
     */
512
    public List<GeneratedJavaFile> getGeneratedJavaFiles() {
513
        return contextResultList.stream()
1✔
514
                .map(ContextResults::generatedJavaFiles)
1✔
515
                .flatMap(Collection::stream)
1✔
516
                .collect(Collectors.toList());
1✔
517
    }
518

519
    /**
520
     * Returns the list of generated Kotlin files after a call to one of the generate methods.
521
     * This is useful if you prefer to process the generated files yourself and do not want
522
     * the generator to write them to disk.
523
     *
524
     * @return the list of generated Kotlin files
525
     */
526
    public List<GeneratedKotlinFile> getGeneratedKotlinFiles() {
527
        return contextResultList.stream()
1✔
528
                .map(ContextResults::generatedKotlinFiles)
1✔
529
                .flatMap(Collection::stream)
1✔
530
                .collect(Collectors.toList());
1✔
531
    }
532

533
    /**
534
     * Returns the list of generated XML files after a call to one of the generate methods.
535
     * This is useful if you prefer to process the generated files yourself and do not want
536
     * the generator to write them to disk.
537
     *
538
     * @return the list of generated XML files
539
     */
540
    public List<GeneratedXmlFile> getGeneratedXmlFiles() {
541
        return contextResultList.stream()
1✔
542
                .map(ContextResults::generatedXmlFiles)
1✔
543
                .flatMap(Collection::stream)
1✔
544
                .collect(Collectors.toList());
1✔
545
    }
546
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc