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

mybatis / generator / 1950

15 Jan 2026 10:12PM UTC coverage: 88.976% (+0.06%) from 88.914%
1950

Pull #1416

github

web-flow
Merge 542424ec6 into e55778ad1
Pull Request #1416: Major Refactoring - IntrospectedTable No Longer Responsible for Code Generation, Plugins Potentially Impacted

2342 of 3166 branches covered (73.97%)

439 of 500 new or added lines in 26 files covered. (87.8%)

9 existing lines in 3 files now uncovered.

11582 of 13017 relevant lines covered (88.98%)

0.89 hits per line

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

38.68
/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

39
import org.jspecify.annotations.Nullable;
40
import org.mybatis.generator.codegen.CalculatedContextValues;
41
import org.mybatis.generator.codegen.GenerationEngine;
42
import org.mybatis.generator.codegen.GenerationResults;
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 List<GenerationResults> generationResultsList = new ArrayList<>();
1✔
73

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

101
        this.shellCallback = Objects.requireNonNullElseGet(shellCallback, () -> new DefaultShellCallback(false));
1✔
102
        this.warnings = Objects.requireNonNullElseGet(warnings, ArrayList::new);
1✔
103
        this.configuration.validate();
1✔
104
    }
1✔
105

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

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

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

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

205
        generationResultsList.clear();
1✔
206
        ObjectFactory.reset();
1✔
207
        RootClassInfo.reset();
1✔
208

209
        setupCustomClassloader();
1✔
210

211
        ProgressCallback localProgressCallback = Objects.requireNonNullElse(progressCallback, NULL_PROGRESS_CALLBACK);
1✔
212
        Set<String> localFullyQualifiedTableNames =
1✔
213
                Objects.requireNonNullElse(fullyQualifiedTableNames, Collections.emptySet());
1✔
214
        Set<String> localContextIds = Objects.requireNonNullElse(contextIds, Collections.emptySet());
1✔
215

216
        List<Context> contextsToRun = calculateContextsToRun(localFullyQualifiedTableNames, localContextIds);
1✔
217

218
        List<CalculatedContextValues> contextValuesList = calculateContextValues(contextsToRun);
1✔
219

220
        runAllIntrospections(contextValuesList, localFullyQualifiedTableNames, localProgressCallback);
1✔
221

222
        List<GenerationEngine> generationEngines = createGenerationEngines(contextValuesList, localProgressCallback);
1✔
223

224
        runGenerationEngines(generationEngines, localProgressCallback);
1✔
225

226
        if (writeFiles) {
1!
NEW
227
            writeGeneratedFiles(localProgressCallback);
×
228
        }
229

230
        localProgressCallback.done();
1✔
231
    }
1✔
232

233
    private void setupCustomClassloader() {
234
        if (!configuration.getClassPathEntries().isEmpty()) {
1!
235
            ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
×
236
            ObjectFactory.addExternalClassLoader(classLoader);
×
237
        }
238
    }
1✔
239

240
    private List<Context> calculateContextsToRun(Set<String> fullyQualifiedTableNames, Set<String> contextIds) {
241
        List<Context> contextsToRun;
242
        if (fullyQualifiedTableNames.isEmpty()) {
1!
243
            contextsToRun = configuration.getContexts();
1✔
244
        } else {
NEW
245
            contextsToRun = configuration.getContexts().stream()
×
NEW
246
                    .filter(c -> contextIds.contains(c.getId()))
×
NEW
247
                    .toList();
×
248
        }
249

250
        return contextsToRun;
1✔
251
    }
252

253
    private List<CalculatedContextValues> calculateContextValues(List<Context> contextsToRun) {
254
        return contextsToRun.stream()
1✔
255
                .map(this::createContextValues)
1✔
256
                .toList();
1✔
257
    }
258

259
    private CalculatedContextValues createContextValues(Context context) {
260
        return new CalculatedContextValues.Builder()
1✔
261
                .withContext(context)
1✔
262
                .withWarnings(warnings)
1✔
263
                .build();
1✔
264
    }
265

266
    private void runAllIntrospections(List<CalculatedContextValues> contextValuesList,
267
                                      Set<String> fullyQualifiedTableNames, ProgressCallback progressCallback)
268
            throws SQLException, InterruptedException {
269
        int totalSteps = contextValuesList.stream()
1✔
270
                .map(CalculatedContextValues::context)
1✔
271
                .mapToInt(Context::getIntrospectionSteps)
1✔
272
                .sum();
1✔
273
        progressCallback.introspectionStarted(totalSteps);
1✔
274

275
        for (CalculatedContextValues contextValues : contextValuesList) {
1✔
276
            contextValues.addIntrospectedTables(
1✔
277
                    runContextIntrospection(fullyQualifiedTableNames, contextValues, progressCallback));
1✔
278
        }
1✔
279
    }
1✔
280

281
    private List<IntrospectedTable> runContextIntrospection(Set<String> fullyQualifiedTableNames,
282
                                                            CalculatedContextValues contextValues,
283
                                                            ProgressCallback progressCallback)
284
            throws SQLException, InterruptedException {
285
        return new IntrospectionEngine.Builder()
1✔
286
                .withContextValues(contextValues)
1✔
287
                .withFullyQualifiedTableNames(fullyQualifiedTableNames)
1✔
288
                .withWarnings(warnings)
1✔
289
                .withProgressCallback(progressCallback)
1✔
290
                .build()
1✔
291
                .introspectTables();
1✔
292
    }
293

294
    private List<GenerationEngine> createGenerationEngines(List<CalculatedContextValues> contextValuesList,
295
                                                           ProgressCallback progressCallback) {
296
        return contextValuesList.stream()
1✔
297
                .map(cv -> createGenerationEngine(cv, progressCallback))
1✔
298
                .toList();
1✔
299
    }
300

301
    private GenerationEngine createGenerationEngine(CalculatedContextValues contextValues,
302
                                                    ProgressCallback progressCallback) {
303
        return new GenerationEngine.Builder()
1✔
304
                .withContextValues(contextValues)
1✔
305
                .withProgressCallback(progressCallback)
1✔
306
                .withWarnings(warnings)
1✔
307
                .withIntrospectedTables(contextValues.introspectedTables())
1✔
308
                .build();
1✔
309
    }
310

311
    private void runGenerationEngines(List<GenerationEngine> generationEngines, ProgressCallback progressCallback)
312
            throws InterruptedException {
313
        // calculate the number of steps
314
        int totalSteps = generationEngines.stream().mapToInt(GenerationEngine::getGenerationSteps).sum();
1✔
315
        progressCallback.generationStarted(totalSteps);
1✔
316

317
        // now run the generators
318
        for (GenerationEngine generationEngine: generationEngines) {
1✔
319
            var generationResults = generationEngine.generate();
1✔
320
            generationResultsList.add(generationResults);
1✔
321
        }
1✔
322
    }
1✔
323

324
    private void writeGeneratedFiles(ProgressCallback progressCallback) throws IOException, InterruptedException {
NEW
325
        Set<String> projects = new HashSet<>();
×
NEW
326
        int totalSteps = generationResultsList.stream().mapToInt(GenerationResults::getNumberOfGeneratedFiles).sum();
×
NEW
327
        progressCallback.saveStarted(totalSteps);
×
328

NEW
329
        for (GenerationResults generationResults : generationResultsList) {
×
NEW
330
            for (GeneratedXmlFile gxf : generationResults.generatedXmlFiles()) {
×
NEW
331
                projects.add(gxf.getTargetProject());
×
NEW
332
                writeGeneratedXmlFile(gxf, generationResults.xmlFormatter(), progressCallback);
×
NEW
333
            }
×
334

NEW
335
            for (GeneratedJavaFile gjf : generationResults.generatedJavaFiles()) {
×
NEW
336
                projects.add(gjf.getTargetProject());
×
NEW
337
                writeGeneratedJavaFile(gjf, generationResults.javaFormatter(), generationResults.javaFileEncoding(),
×
338
                        progressCallback);
UNCOV
339
            }
×
340

NEW
341
            for (GeneratedKotlinFile gkf : generationResults.generatedKotlinFiles()) {
×
NEW
342
                projects.add(gkf.getTargetProject());
×
NEW
343
                writeGeneratedKotlinFile(gkf, generationResults.kotlinFormatter(),
×
NEW
344
                        generationResults.kotlinFileEncoding(),
×
345
                        progressCallback);
NEW
346
            }
×
347

NEW
348
            for (GenericGeneratedFile gf : generationResults.generatedGenericFiles()) {
×
NEW
349
                projects.add(gf.getTargetProject());
×
NEW
350
                writeGenericGeneratedFile(gf, progressCallback);
×
UNCOV
351
            }
×
UNCOV
352
        }
×
353

NEW
354
        for (String project : projects) {
×
NEW
355
            shellCallback.refreshProject(project);
×
NEW
356
        }
×
UNCOV
357
    }
×
358

359
    private void writeGeneratedJavaFile(GeneratedJavaFile gjf, JavaFormatter javaFormatter,
360
                                        @Nullable String javaFileEncoding, ProgressCallback progressCallback)
361
            throws InterruptedException, IOException {
362
        Path targetFile;
NEW
363
        String source = javaFormatter.getFormattedContent(gjf.getCompilationUnit());
×
364
        try {
365
            File directory = shellCallback.getDirectory(gjf.getTargetProject(), gjf.getTargetPackage());
×
366
            targetFile = directory.toPath().resolve(gjf.getFileName());
×
367
            if (Files.exists(targetFile)) {
×
368
                if (shellCallback.isMergeSupported()) {
×
NEW
369
                    source = shellCallback.mergeJavaFile(source, targetFile.toFile(),
×
370
                            MergeConstants.getOldElementTags(), javaFileEncoding);
×
371
                } else if (shellCallback.isOverwriteEnabled()) {
×
372
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
373
                } else {
374
                    targetFile = getUniqueFileName(directory, gjf.getFileName());
×
375
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
376
                }
377
            }
378

NEW
379
            progressCallback.checkCancel();
×
NEW
380
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
381
            writeFile(targetFile.toFile(), source, javaFileEncoding);
×
382
        } catch (ShellException e) {
×
383
            warnings.add(e.getMessage());
×
384
        }
×
385
    }
×
386

387
    private void writeGeneratedKotlinFile(GeneratedKotlinFile gf, KotlinFormatter kotlinFormatter,
388
                                          @Nullable String kotlinFileEncoding, ProgressCallback progressCallback)
389
            throws InterruptedException, IOException {
390
        Path targetFile;
NEW
391
        String source = kotlinFormatter.getFormattedContent(gf.getKotlinFile());
×
392
        try {
393
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
394
            targetFile = directory.toPath().resolve(gf.getFileName());
×
395
            if (Files.exists(targetFile)) {
×
396
                if (shellCallback.isOverwriteEnabled()) {
×
397
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
398
                } else {
399
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
400
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
401
                }
402
            }
403

NEW
404
            progressCallback.checkCancel();
×
NEW
405
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
406
            writeFile(targetFile.toFile(), source, kotlinFileEncoding);
×
407
        } catch (ShellException e) {
×
408
            warnings.add(e.getMessage());
×
409
        }
×
410
    }
×
411

412
    private void writeGenericGeneratedFile(GenericGeneratedFile gf, ProgressCallback progressCallback)
413
            throws InterruptedException, IOException {
414
        Path targetFile;
NEW
415
        String source = gf.getFormattedContent();
×
416
        try {
417
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
418
            targetFile = directory.toPath().resolve(gf.getFileName());
×
419
            if (Files.exists(targetFile)) {
×
420
                if (shellCallback.isOverwriteEnabled()) {
×
421
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
422
                } else {
423
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
424
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
425
                }
426
            }
427

NEW
428
            progressCallback.checkCancel();
×
NEW
429
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
430
            writeFile(targetFile.toFile(), source, gf.getFileEncoding().orElse(null));
×
431
        } catch (ShellException e) {
×
432
            warnings.add(e.getMessage());
×
433
        }
×
434
    }
×
435

436
    private void writeGeneratedXmlFile(GeneratedXmlFile gxf, XmlFormatter xmlFormatter,
437
                                       ProgressCallback progressCallback)
438
            throws InterruptedException, IOException {
439
        Path targetFile;
NEW
440
        String source = xmlFormatter.getFormattedContent(gxf.getDocument());
×
441
        try {
442
            File directory = shellCallback.getDirectory(gxf.getTargetProject(), gxf.getTargetPackage());
×
443
            targetFile = directory.toPath().resolve(gxf.getFileName());
×
444
            if (Files.exists(targetFile)) {
×
445
                if (gxf.isMergeable()) {
×
NEW
446
                    source = XmlFileMergerJaxp.getMergedSource(source, targetFile.toFile());
×
447
                } else if (shellCallback.isOverwriteEnabled()) {
×
448
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
449
                } else {
450
                    targetFile = getUniqueFileName(directory, gxf.getFileName());
×
451
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
452
                }
453
            }
454

NEW
455
            progressCallback.checkCancel();
×
NEW
456
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
457
            writeFile(targetFile.toFile(), source, "UTF-8"); //$NON-NLS-1$
×
458
        } catch (ShellException e) {
×
459
            warnings.add(e.getMessage());
×
460
        }
×
461
    }
×
462

463
    /**
464
     * Writes, or overwrites, the contents of the specified file.
465
     *
466
     * @param file
467
     *            the file
468
     * @param content
469
     *            the content
470
     * @param fileEncoding
471
     *            the file encoding
472
     * @throws IOException
473
     *             Signals that an I/O exception has occurred.
474
     */
475
    private void writeFile(File file, String content, @Nullable String fileEncoding) throws IOException {
476
        try (OutputStream fos = Files.newOutputStream(file.toPath(), StandardOpenOption.CREATE,
×
477
                StandardOpenOption.TRUNCATE_EXISTING)) {
478
            OutputStreamWriter osw;
479
            if (fileEncoding == null) {
×
480
                osw = new OutputStreamWriter(fos);
×
481
            } else {
482
                osw = new OutputStreamWriter(fos, Charset.forName(fileEncoding));
×
483
            }
484

485
            try (BufferedWriter bw = new BufferedWriter(osw)) {
×
486
                bw.write(content);
×
487
            }
488
        }
489
    }
×
490

491
    /**
492
     * Gets the unique file name.
493
     *
494
     * @param directory
495
     *            the directory
496
     * @param fileName
497
     *            the file name
498
     * @return the unique file name
499
     */
500
    private Path getUniqueFileName(File directory, String fileName) {
501
        Path answer = null;
×
502

503
        // try up to 1000 times to generate a unique file name
504
        StringBuilder sb = new StringBuilder();
×
505
        for (int i = 1; i < 1000; i++) {
×
506
            sb.setLength(0);
×
507
            sb.append(fileName);
×
508
            sb.append('.');
×
509
            sb.append(i);
×
510

511
            Path testFile = directory.toPath().resolve(sb.toString());
×
512
            if (Files.notExists(testFile)) {
×
513
                answer = testFile;
×
514
                break;
×
515
            }
516
        }
517

518
        if (answer == null) {
×
519
            throw new RuntimeException(getString(
×
520
                    "RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
×
521
        }
522

523
        return answer;
×
524
    }
525

526
    /**
527
     * Returns the list of generated Java files after a call to one of the generate methods.
528
     * This is useful if you prefer to process the generated files yourself and do not want
529
     * the generator to write them to disk.
530
     *
531
     * @return the list of generated Java files
532
     */
533
    public List<GeneratedJavaFile> getGeneratedJavaFiles() {
534
        return generationResultsList.stream()
1✔
535
                .map(GenerationResults::generatedJavaFiles)
1✔
536
                .flatMap(Collection::stream)
1✔
537
                .toList();
1✔
538
    }
539

540
    /**
541
     * Returns the list of generated Kotlin files after a call to one of the generate methods.
542
     * This is useful if you prefer to process the generated files yourself and do not want
543
     * the generator to write them to disk.
544
     *
545
     * @return the list of generated Kotlin files
546
     */
547
    public List<GeneratedKotlinFile> getGeneratedKotlinFiles() {
548
        return generationResultsList.stream()
1✔
549
                .map(GenerationResults::generatedKotlinFiles)
1✔
550
                .flatMap(Collection::stream)
1✔
551
                .toList();
1✔
552
    }
553

554
    /**
555
     * Returns the list of generated XML files after a call to one of the generate methods.
556
     * This is useful if you prefer to process the generated files yourself and do not want
557
     * the generator to write them to disk.
558
     *
559
     * @return the list of generated XML files
560
     */
561
    public List<GeneratedXmlFile> getGeneratedXmlFiles() {
562
        return generationResultsList.stream()
1✔
563
                .map(GenerationResults::generatedXmlFiles)
1✔
564
                .flatMap(Collection::stream)
1✔
565
                .toList();
1✔
566
    }
567

568
    /**
569
     * Returns the list of generated generic files after a call to one of the generate methods.
570
     * This is useful if you prefer to process the generated files yourself and do not want
571
     * the generator to write them to disk.
572
     *
573
     * <p>The list will be empty unless you have used a plugin that generates generic files
574
     * or are using a custom runtime.
575
     *
576
     * @return the list of generated generic files
577
     */
578
    public List<GenericGeneratedFile> getGeneratedGenericFiles() {
NEW
579
        return generationResultsList.stream()
×
NEW
580
                .map(GenerationResults::generatedGenericFiles)
×
UNCOV
581
                .flatMap(Collection::stream)
×
UNCOV
582
                .toList();
×
583
    }
584
}
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