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

electrode-io / electrode-native / 7528

24 Oct 2025 12:58AM UTC coverage: 56.546% (-3.5%) from 60.065%
7528

push

Azure Pipelines

r0h0gg6
Merge pull request #1918 from electrode-io/cuid2-fix-2

Update yarn.lock

3566 of 7725 branches covered (46.16%)

Branch coverage included in aggregate %.

2 of 5 new or added lines in 1 file covered. (40.0%)

568 existing lines in 37 files now uncovered.

9396 of 15198 relevant lines covered (61.82%)

524.78 hits per line

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

74.8
/ern-api-gen/src/DefaultCodegen.ts
1
/* tslint:disable:variable-name */
2
import ExampleGenerator from './examples/ExampleGenerator';
2✔
3
import CliOption from './CliOption';
2✔
4
import CodegenConstants from './CodegenConstants';
2✔
5
import CodegenModelFactory from './CodegenModelFactory';
2✔
6
import CodegenModelType from './CodegenModelType';
2✔
7
import camelCase from 'lodash/camelCase';
2✔
8
import factory from './models/factory';
2✔
9
import {
2✔
10
  AbstractNumericProperty,
11
  ArrayProperty,
12
  BaseIntegerProperty,
13
  BinaryProperty,
14
  BooleanProperty,
15
  ByteArrayProperty,
16
  DateProperty,
17
  DateTimeProperty,
18
  DecimalProperty,
19
  DoubleProperty,
20
  FloatProperty,
21
  IntegerProperty,
22
  LongProperty,
23
  MapProperty,
24
  ObjectProperty,
25
  RefProperty,
26
  StringProperty,
27
  UUIDProperty,
28
} from './models/properties';
29
import {
2✔
30
  BodyParameter,
31
  CookieParameter,
32
  FormParameter,
33
  HeaderParameter,
34
  PathParameter,
35
  QueryParameter,
36
  SerializableParameter,
37
} from './models/parameters';
38
import System from './java/System';
2✔
39
import { log } from 'ern-core';
2✔
40
import File from './java/File';
2✔
41
import StringBuilder from './java/StringBuilder';
2✔
42
import {
2✔
43
  asMap,
44
  Collections,
45
  isNotEmptySet,
46
  Lists,
47
  newHashMap,
48
  newHashSet,
49
} from './java/javaUtil';
50
import StringUtils from './java/StringUtils';
2✔
51
import Json from './java/Json';
2✔
52
import StringEscapeUtils from './java/StringEscapeUtils';
2✔
53
import ArrayModel from './models/ArrayModel';
2✔
54
import ComposedModel from './models/ComposedModel';
2✔
55
import ModelImpl from './models/ModelImpl';
2✔
56
import RefModel from './models/RefModel';
2✔
57
import ApiKeyAuthDefinition from './models/auth/ApiKeyAuthDefinition';
2✔
58
import BasicAuthDefinition from './models/auth/BasicAuthDefinition';
2✔
59
import { In } from './models/auth/In';
2✔
60
import PropertyBuilder from './models/PropertyBuilder';
2✔
61
import path from 'path';
2✔
62

63
const _count2 = (_, i) => ++i;
2✔
64
const COMMON_PREFIX_RE = new RegExp('[a-zA-Z0-9]+\\z', 'g');
2✔
65
const sortByFlag = (one, another) => {
2✔
66
  const oneRequired = one.required == null ? false : one.required;
299✔
67
  const anotherRequired = another.required == null ? false : another.required;
299✔
68
  if (oneRequired === anotherRequired) {
299✔
69
    return 0;
178✔
70
  } else if (oneRequired) {
121✔
71
    return -1;
18✔
72
  } else {
73
    return 1;
103✔
74
  }
75
};
76
export default class DefaultCodegen {
2✔
77
  public static addHasMore(objs) {
78
    if (objs == null) {
4,896!
79
      return;
×
80
    }
81

82
    if (Array.isArray(objs)) {
4,896!
83
      for (let i = 0, l = objs.length, lm = l - 1; i < l; i++) {
4,896✔
84
        if (i > 0) {
1,970✔
85
          objs[i].secondaryParam = true;
493✔
86
        }
87
        objs[i].hasMore = i < lm;
1,970✔
88
      }
89
      return objs;
4,896✔
90
    }
91
    // what? insanity
92
    for (let i = 0; i < objs.size - 1; i++) {
×
93
      if (i > 0) {
×
94
        objs.put('secondaryParam', true);
×
95
      }
96
      objs.put('hasMore', i < objs.size - 1);
×
97
    }
98
    return objs;
×
99
  }
100

101
  /**
102
   * Underscore the given word.
103
   * Copied from Twitter elephant bird
104
   * https://github.com/twitter/elephant-bird/blob/master/core/src/main/java/com/twitter/elephantbird/util/Strings.java
105
   *
106
   * @param word The word
107
   * @return The underscored version of the word
108
   */
109
  public static underscore(word) {
110
    const firstPattern = '([A-Z]+)([A-Z][a-z])';
538✔
111
    const secondPattern = '([a-z\\d])([A-Z])';
538✔
112
    const replacementPattern = '$1_$2';
538✔
113
    word = word.replace(new RegExp('\\.', 'g'), '/');
538✔
114
    word = word.replace(new RegExp('\\$', 'g'), '__');
538✔
115
    word = word.replace(new RegExp(firstPattern, 'g'), replacementPattern);
538✔
116
    word = word.replace(new RegExp(secondPattern, 'g'), replacementPattern);
538✔
117
    word = word.split('-').join('_');
538✔
118
    word = word.toLowerCase();
538✔
119
    return word;
538✔
120
  }
121

122
  /**
123
   * Camelize name (parameter, property, method, etc)
124
   *
125
   * @param word string to be camelize
126
   * @param lowercaseFirstLetter lower case for first letter if set to true
127
   * @return camelized string
128
   */
129
  public static camelize(word, lowercaseFirstLetter = false) {
19,244✔
130
    word = camelCase(word);
43,784✔
131
    return (
43,784✔
132
      word &&
87,552✔
133
      word[0][lowercaseFirstLetter ? 'toLowerCase' : 'toUpperCase']() +
43,768✔
134
        word.substring(1)
135
    );
136
  }
137

138
  /**
139
   * Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number,
140
   * otherwise increase the number by 1. For example:
141
   * status    => status2
142
   * status2   => status3
143
   * myName100 => myName101
144
   *
145
   * @param name The base name
146
   * @return The next name for the base name
147
   */
148
  public static generateNextName(name) {
149
    const re = /(\d{1,})/;
×
150
    if (re.test(name)) {
×
151
      return name.replace(re, _count2);
×
152
    }
153
    return name + '2';
×
154
  }
155

156
  public __fileSuffix;
157
  public __templateDir;
158
  public __embeddedTemplateDir;
159
  public __outputFolder = '';
854✔
160
  public __languageSpecificPrimitives = newHashSet();
854✔
161
  public __modelPackage = '';
854✔
162
  public __apiPackage = '';
854✔
163
  public modelNamePrefix = '';
854✔
164
  public modelNameSuffix = '';
854✔
165
  public __testPackage = '';
854✔
166
  public __apiTemplateFiles = newHashMap();
854✔
167
  public __apiDataTemplateFile = newHashMap();
854✔
168
  public __modelTemplateFiles = newHashMap();
854✔
169
  public __apiTestTemplateFiles = newHashMap();
854✔
170
  public __modelTestTemplateFiles = newHashMap();
854✔
171
  public __apiDocTemplateFiles = newHashMap();
854✔
172
  public __modelDocTemplateFiles = newHashMap();
854✔
173
  public commonTemplateDir = '_common';
854✔
174
  public __additionalProperties = newHashMap();
854✔
175
  public __vendorExtensions = newHashMap();
854✔
176
  public __supportingFiles: any[] = [];
854✔
177
  public __cliOptions: any[] = [];
854✔
178
  public __supportedLibraries = newHashMap();
854✔
179
  public sortParamsByRequiredFlag = true;
854✔
180
  public ensureUniqueParams = true;
854✔
181
  public specialCharReplacements = newHashMap();
854✔
182
  public skipOverwrite = false;
854✔
183
  public supportsInheritance = false;
854✔
184
  public __defaultIncludes = newHashSet(
854✔
185
    'double',
186
    'int',
187
    'long',
188
    'short',
189
    'char',
190
    'float',
191
    'String',
192
    'boolean',
193
    'Boolean',
194
    'Double',
195
    'Void',
196
    'Integer',
197
    'Long',
198
    'Float',
199
  );
200
  public __typeMapping = newHashMap(
854✔
201
    ['array', 'List'],
202
    ['map', 'Map'],
203
    ['List', 'List'],
204
    ['boolean', 'Boolean'],
205
    ['string', 'String'],
206
    ['int', 'Integer'],
207
    ['float', 'Float'],
208
    ['number', 'BigDecimal'],
209
    ['DateTime', 'Date'],
210
    ['long', 'Long'],
211
    ['short', 'Short'],
212
    ['char', 'String'],
213
    ['double', 'Double'],
214
    ['object', 'Object'],
215
    ['integer', 'Integer'],
216
    ['ByteArray', 'byte[]'],
217
    ['binary', 'byte[]'],
218
  );
219
  public __instantiationTypes = newHashMap();
854✔
220
  public __reservedWords = newHashSet();
854✔
221
  public __importMapping = newHashMap(
854✔
222
    ['BigDecimal', 'java.math.BigDecimal'],
223
    ['UUID', 'java.util.UUID'],
224
    ['File', 'java.io.File'],
225
    ['Date', 'java.util.Date'],
226
    ['Timestamp', 'java.sql.Timestamp'],
227
    ['Map', 'java.util.Map'],
228
    ['HashMap', 'java.util.HashMap'],
229
    ['Array', 'java.util.List'],
230
    ['ArrayList', 'java.util.ArrayList'],
231
    ['List', 'java.util.*'],
232
    ['Set', 'java.util.*'],
233
    ['DateTime', 'org.joda.time.*'],
234
    ['LocalDateTime', 'org.joda.time.*'],
235
    ['LocalDate', 'org.joda.time.*'],
236
    ['LocalTime', 'org.joda.time.*'],
237
  );
238
  public containerType;
239
  public library;
240
  public gitUserId;
241
  public gitRepoId;
242
  public releaseNote;
243
  public httpUserAgent;
244

245
  /**
246
   * Default constructor.
247
   * This method will map between Swagger type and language-specified type, as well as mapping
248
   * between Swagger type and the corresponding import statement for the language. This will
249
   * also add some language specified CLI options, if any.
250
   *
251
   *
252
   * returns string presentation of the example path (it's a constructor)
253
   */
254
  constructor() {
255
    this.initalizeCliOptions();
854✔
256
    this.initalizeSpecialCharacterMapping();
854✔
257
  }
258

259
  public initalizeCliOptions() {
260
    this.__cliOptions.push(
854✔
261
      CliOption.newBoolean(
262
        CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
263
        CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
264
      ).defaultValue('true'),
265
    );
266
    this.__cliOptions.push(
854✔
267
      CliOption.newBoolean(
268
        CodegenConstants.ENSURE_UNIQUE_PARAMS,
269
        CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC,
270
      ).defaultValue('true'),
271
    );
272
  }
273

274
  public cliOptions() {
275
    return this.__cliOptions;
117✔
276
  }
277

278
  public processOpts() {
279
    if (
114!
280
      this.__additionalProperties.containsKey(CodegenConstants.TEMPLATE_DIR)
281
    ) {
282
      this.setTemplateDir(
×
283
        this.__additionalProperties.get(CodegenConstants.TEMPLATE_DIR),
284
      );
285
    }
286
    if (
114✔
287
      this.__additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)
288
    ) {
289
      this.setModelPackage(
3✔
290
        this.__additionalProperties.get(CodegenConstants.MODEL_PACKAGE),
291
      );
292
    }
293
    if (this.__additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
114✔
294
      this.setApiPackage(
52✔
295
        this.__additionalProperties.get(CodegenConstants.API_PACKAGE),
296
      );
297
    }
298
    if (
114!
299
      this.__additionalProperties.containsKey(
300
        CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
301
      )
302
    ) {
303
      this.setSortParamsByRequiredFlag(
×
304
        Boolean(
305
          this.__additionalProperties.get(
306
            CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
307
          ),
308
        ),
309
      );
310
    }
311
    if (
114!
312
      this.__additionalProperties.containsKey(
313
        CodegenConstants.ENSURE_UNIQUE_PARAMS,
314
      )
315
    ) {
316
      this.setEnsureUniqueParams(
×
317
        Boolean(
318
          this.__additionalProperties.get(
319
            CodegenConstants.ENSURE_UNIQUE_PARAMS,
320
          ),
321
        ),
322
      );
323
    }
324
    if (
114!
325
      this.__additionalProperties.containsKey(
326
        CodegenConstants.MODEL_NAME_PREFIX,
327
      )
328
    ) {
329
      this.setModelNamePrefix(
×
330
        this.__additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX),
331
      );
332
    }
333
    if (
114!
334
      this.__additionalProperties.containsKey(
335
        CodegenConstants.MODEL_NAME_SUFFIX,
336
      )
337
    ) {
338
      this.setModelNameSuffix(
×
339
        this.__additionalProperties.get(CodegenConstants.MODEL_NAME_SUFFIX),
340
      );
341
    }
342
  }
343

344
  public addLicenseFile() {
345
    return true;
58✔
346
  }
347

348
  public addSwaggerIgnoreFile() {
349
    return true;
58✔
350
  }
351

352
  public postProcessAllModels(objs) {
353
    if (this.supportsInheritance) {
70✔
354
      const allModels = newHashMap();
29✔
355
      for (const [key, inner] of objs) {
29✔
356
        const modelName = this.toModelName(key);
106✔
357
        for (const mo of inner.get('models')) {
106✔
358
          allModels.put(modelName, mo.get('model'));
106✔
359
        }
360
      }
361

362
      for (const [key, cm] of allModels) {
29✔
363
        if (cm.parent != null) {
106!
364
          cm.parentModel = allModels.get(cm.parent);
×
365
        }
366
        if (isNotEmptySet(cm.interfaces)) {
106✔
367
          cm.interfaceModels = [];
3✔
368
          for (const intf of cm.interfaces) {
3✔
369
            const intfModel = allModels.get(intf);
3✔
370
            if (intfModel != null) {
3!
371
              cm.interfaceModels.push(intfModel);
3✔
372
            }
373
          }
374
        }
375
      }
376
    }
377
    return objs;
70✔
378
  }
379

380
  public postProcessModels(objs) {
381
    return objs;
80✔
382
  }
383

384
  /**
385
   * post process enum defined in model's properties
386
   *
387
   * @param objs Map of models
388
   * @return maps of models with better enum support
389
   */
390
  public postProcessModelsEnum(objs) {
391
    const models = objs.get('models');
169✔
392
    for (const mo of models) {
169✔
393
      const cm = mo.get('model');
169✔
394
      if (cm.isEnum && cm.allowableValues != null) {
169!
395
        const allowableValues = cm.allowableValues;
×
396
        const values = allowableValues.get('values');
×
397
        const enumVars: any[] = [];
×
398
        const commonPrefix = this.findCommonPrefixOfVars(values);
×
399
        const truncateIdx = commonPrefix.length;
×
400
        cm.allowableValues.put('enumVars', enumVars);
×
401

402
        for (const value of values) {
×
403
          let enumName;
404
          if (truncateIdx === 0) {
×
405
            enumName = value.toString();
×
406
          } else {
407
            enumName = value.toString().substring(truncateIdx);
×
408
            if ('' === enumName) {
×
409
              enumName = value.toString();
×
410
            }
411
          }
412
          enumVars.push(
×
413
            newHashMap(
414
              ['name', this.toEnumVarName(enumName, cm.dataType)],
415
              ['value', this.toEnumValue(value.toString(), cm.dataType)],
416
            ),
417
          );
418
        }
419
      }
420
      for (const _var of cm.vars) {
169✔
421
        this.updateCodegenPropertyEnum(_var);
744✔
422
      }
423
    }
424
    return objs;
169✔
425
  }
426

427
  /**
428
   * Returns the common prefix of variables for enum naming
429
   *
430
   * @param vars List of variable names
431
   * @return the common prefix for naming
432
   */
433
  public findCommonPrefixOfVars(listStr) {
434
    try {
65✔
435
      const prefix = StringUtils.getCommonPrefix(listStr);
65✔
436
      return prefix.replace(COMMON_PREFIX_RE, '');
65✔
437
    } catch (e) {
438
      log.trace(e);
×
439
      return '';
×
440
    }
441
  }
442

443
  /**
444
   * Return the enum default value in the language specifed format
445
   *
446
   * @param value enum variable name
447
   * @param datatype data type
448
   * @return the default value for the enum
449
   */
450
  public toEnumDefaultValue(value, datatype) {
451
    return datatype + '.' + value;
×
452
  }
453

454
  /**
455
   * Return the enum value in the language specifed format
456
   * e.g. status becomes "status"
457
   *
458
   * @param value enum variable name
459
   * @param datatype data type
460
   * @return the sanitized value for enum
461
   */
462
  public toEnumValue(value, datatype) {
463
    if ('number' === '' + datatype.toLowerCase()) {
48!
464
      return value;
×
465
    }
466
    return '"' + this.escapeText(value) + '"';
48✔
467
  }
468

469
  /**
470
   * Return the sanitized variable name for enum
471
   *
472
   * @param value enum variable name
473
   * @param datatype data type
474
   * @return the sanitized variable name for enum
475
   */
476
  public toEnumVarName(value, datatype) {
477
    const __var = value.replace(new RegExp('\\W+', 'g'), '_').toUpperCase();
24✔
478
    if (__var.match('\\d.*')) {
24!
479
      return '_' + __var;
×
480
    } else {
481
      return __var;
24✔
482
    }
483
  }
484

485
  public postProcessOperations(objs) {
486
    return objs;
49✔
487
  }
488

489
  public postProcessSupportingFileData(objs) {
490
    return objs;
107✔
491
  }
492

493
  public postProcessModelProperty(model, property) {
494
    // Empty
495
  }
496

497
  public postProcessParameter(parameter) {
498
    // Empty
499
  }
500

501
  public preprocessSwagger(swagger) {
502
    // Empty
503
  }
504

505
  public processSwagger(swagger) {
506
    // Empty
507
  }
508

509
  public escapeText(input) {
510
    if (input == null) {
16,133✔
511
      return input;
8,004✔
512
    }
513
    return this.escapeUnsafeCharacters(
8,129✔
514
      StringEscapeUtils.unescapeJava(
515
        StringEscapeUtils.escapeJava(input).split('\\/').join('/'),
516
      )
517

518
        .replace(new RegExp('[\\t\\n\\r]', 'g'), ' ')
519
        .split('\\')
520
        .join('\\\\')
521
        .split('"')
522
        .join('\\"'),
523
    );
524
  }
525

526
  /**
527
   * override with any special text escaping logic to handle unsafe
528
   * characters so as to avoid code injection
529
   * @param input String to be cleaned up
530
   * @return string with unsafe characters removed or escaped
531
   */
532
  public escapeUnsafeCharacters(input) {
533
    log.warn(
×
534
      'escapeUnsafeCharacters should be overriden in the code generator with proper logic to escape unsafe characters',
535
    );
536
    return input;
×
537
  }
538

539
  /**
540
   * Escape single and/or double quote to avoid code injection
541
   * @param input String to be cleaned up
542
   * @return string with quotation mark removed or escaped
543
   */
544
  public escapeQuotationMark(input) {
545
    log.warn(
×
546
      'escapeQuotationMark should be overriden in the code generator with proper logic to escape single/double quote',
547
    );
548
    return input.split('"').join('\\"');
×
549
  }
550

551
  public defaultIncludes() {
552
    return this.__defaultIncludes;
87✔
553
  }
554

555
  public typeMapping() {
556
    return this.__typeMapping;
115✔
557
  }
558

559
  public instantiationTypes() {
560
    return this.__instantiationTypes;
202✔
561
  }
562

563
  public reservedWords() {
564
    return this.__reservedWords;
×
565
  }
566

567
  public languageSpecificPrimitives() {
568
    return this.__languageSpecificPrimitives;
5,635✔
569
  }
570

571
  public importMapping() {
572
    return this.__importMapping;
927✔
573
  }
574

575
  public testPackage() {
576
    return this.__testPackage;
×
577
  }
578

579
  public modelPackage() {
580
    return this.__modelPackage;
1,446✔
581
  }
582

583
  public apiPackage() {
584
    return this.__apiPackage;
664✔
585
  }
586

587
  public fileSuffix() {
588
    return this.__fileSuffix;
×
589
  }
590

591
  public templateDir() {
592
    return this.__templateDir;
×
593
  }
594

595
  public embeddedTemplateDir() {
596
    if (this.__embeddedTemplateDir != null) {
2,846✔
597
      return this.__embeddedTemplateDir;
1,719✔
598
    } else {
599
      return this.__templateDir;
1,127✔
600
    }
601
  }
602

603
  public getCommonTemplateDir() {
604
    return this.commonTemplateDir;
116✔
605
  }
606

607
  public etCommonTemplateDir(commonTemplateDir) {
608
    this.commonTemplateDir = commonTemplateDir;
×
609
  }
610

611
  public apiDocTemplateFiles() {
612
    return this.__apiDocTemplateFiles;
248✔
613
  }
614

615
  public modelDocTemplateFiles() {
616
    return this.__modelDocTemplateFiles;
249✔
617
  }
618

619
  public apiTestTemplateFiles() {
620
    return this.__apiTestTemplateFiles;
246✔
621
  }
622

623
  public modelTestTemplateFiles() {
624
    return this.__modelTestTemplateFiles;
249✔
625
  }
626

627
  public apiTemplateFiles() {
628
    return this.__apiTemplateFiles;
502✔
629
  }
630

631
  public apiDataTemplateFile() {
632
    return this.__apiDataTemplateFile;
108✔
633
  }
634

635
  public modelTemplateFiles() {
636
    return this.__modelTemplateFiles;
249✔
637
  }
638

639
  public apiFileFolder() {
640
    return (
×
641
      this.__outputFolder +
642
      path.sep +
643
      this.apiPackage().split('.').join(path.sep)
644
    );
645
  }
646

647
  /**
648
   * Checks to see if an API file needs to be generated for this template, helps to apply some logic when you have more than one api file which is condition based.
649
   * @param templateName
650
   * @param operation
651
   * @returns {boolean}
652
   */
653
  public shouldGenerateApiFor(templateName, operation) {
654
    return true;
95✔
655
  }
656

657
  public modelFileFolder() {
658
    return (
×
659
      this.__outputFolder +
660
      path.sep +
661
      this.modelPackage().split('.').join(path.sep)
662
    );
663
  }
664

665
  public apiTestFileFolder() {
666
    return (
×
667
      this.__outputFolder +
668
      path.sep +
669
      this.testPackage().split('.').join(path.sep)
670
    );
671
  }
672

673
  public modelTestFileFolder() {
674
    return (
×
675
      this.__outputFolder +
676
      path.sep +
677
      this.testPackage().split('.').join(path.sep)
678
    );
679
  }
680

681
  public apiDocFileFolder() {
682
    return this.__outputFolder;
×
683
  }
684

685
  public modelDocFileFolder() {
686
    return this.__outputFolder;
×
687
  }
688

689
  public additionalProperties() {
690
    return this.__additionalProperties;
2,081✔
691
  }
692

693
  public vendorExtensions() {
694
    return this.__vendorExtensions;
287✔
695
  }
696

697
  public supportingFiles() {
698
    return this.__supportingFiles;
107✔
699
  }
700

701
  public outputFolder() {
702
    return this.__outputFolder;
797✔
703
  }
704

705
  public setOutputDir(dir) {
706
    this.__outputFolder = dir;
230✔
707
  }
708

709
  public getOutputDir() {
710
    return this.outputFolder();
114✔
711
  }
712

713
  public setTemplateDir(templateDir) {
714
    this.__templateDir = templateDir;
×
715
  }
716

717
  public setModelPackage(modelPackage) {
718
    this.__modelPackage = modelPackage;
6✔
719
  }
720

721
  public setModelNamePrefix(modelNamePrefix) {
722
    this.modelNamePrefix = modelNamePrefix;
×
723
  }
724

725
  public setModelNameSuffix(modelNameSuffix) {
726
    this.modelNameSuffix = modelNameSuffix;
×
727
  }
728

729
  public setApiPackage(apiPackage) {
730
    this.__apiPackage = apiPackage;
105✔
731
  }
732

733
  public setSortParamsByRequiredFlag(sortParamsByRequiredFlag) {
734
    this.sortParamsByRequiredFlag = sortParamsByRequiredFlag;
×
735
  }
736

737
  public setEnsureUniqueParams(ensureUniqueParams) {
738
    this.ensureUniqueParams = ensureUniqueParams;
×
739
  }
740

741
  /**
742
   * Return the regular expression/JSON schema pattern (http://json-schema.org/latest/json-schema-validation.html#anchor33)
743
   *
744
   * @param pattern the pattern (regular expression)
745
   * @return properly-escaped pattern
746
   */
747
  public toRegularExpression(pattern) {
748
    return this.escapeText(pattern);
2,945✔
749
  }
750

751
  /**
752
   * Return the file name of the Api Test
753
   *
754
   * @param name the file name of the Api
755
   * @return the file name of the Api
756
   */
757
  public toApiFilename(name) {
758
    return this.toApiName(name);
173✔
759
  }
760

761
  /**
762
   * Return the file name of the Api Documentation
763
   *
764
   * @param name the file name of the Api
765
   * @return the file name of the Api
766
   */
767
  public toApiDocFilename(name) {
768
    return this.toApiName(name);
×
769
  }
770

771
  /**
772
   * Return the file name of the Api Test
773
   *
774
   * @param name the file name of the Api
775
   * @return the file name of the Api
776
   */
777
  public toApiTestFilename(name) {
778
    return this.toApiName(name) + 'Test';
×
779
  }
780

781
  /**
782
   * Return the variable name in the Api
783
   *
784
   * @param name the varible name of the Api
785
   * @return the snake-cased variable name
786
   */
787
  public toApiVarName(name) {
788
    return this.snakeCase(name);
346✔
789
  }
790

791
  /**
792
   * Return the capitalized file name of the model
793
   *
794
   * @param name the model name
795
   * @return the file name of the model
796
   */
797
  public toModelFilename(name) {
798
    return this.initialCaps(name);
×
799
  }
800

801
  /**
802
   * Return the capitalized file name of the model test
803
   *
804
   * @param name the model name
805
   * @return the file name of the model
806
   */
807
  public toModelTestFilename(name) {
808
    return this.initialCaps(name) + 'Test';
×
809
  }
810

811
  /**
812
   * Return the capitalized file name of the model documentation
813
   *
814
   * @param name the model name
815
   * @return the file name of the model
816
   */
817
  public toModelDocFilename(name) {
818
    return this.initialCaps(name);
×
819
  }
820

821
  /**
822
   * Return the operation ID (method name)
823
   *
824
   * @param operationId operation ID
825
   * @return the sanitized method name
826
   */
827
  public toOperationId(operationId) {
828
    if (StringUtils.isEmpty(operationId)) {
×
829
      throw new Error('Empty method name (operationId) not allowed');
×
830
    }
831
    return operationId;
×
832
  }
833

834
  /**
835
   * Return the variable name by removing invalid characters and proper escaping if
836
   * it's a reserved word.
837
   *
838
   * @param name the variable name
839
   * @return the sanitized variable name
840
   */
841
  public toVarName(name) {
842
    if (this.__reservedWords.contains(name)) {
×
843
      return this.escapeReservedWord(name);
×
844
    } else {
845
      return name;
×
846
    }
847
  }
848

849
  /**
850
   * Return the parameter name by removing invalid characters and proper escaping if
851
   * it's a reserved word.
852
   *
853
   * @param name Codegen property object
854
   * @return the sanitized parameter name
855
   */
856
  public toParamName(name) {
857
    name = this.removeNonNameElementToCamelCase(name);
×
858
    if (this.__reservedWords.contains(name)) {
×
859
      return this.escapeReservedWord(name);
×
860
    }
861
    return name;
×
862
  }
863

864
  /**
865
   * Return the Enum name (e.g. StatusEnum given 'status')
866
   *
867
   * @param property Codegen property
868
   * @return the Enum name
869
   */
870
  public toEnumName(property) {
871
    return StringUtils.capitalize(property.name) + 'Enum';
192✔
872
  }
873

874
  /**
875
   * Return the escaped name of the reserved word
876
   *
877
   * @param name the name to be escaped
878
   * @return the escaped reserved word
879
   *
880
   * throws Runtime exception as reserved word is not allowed (default behavior)
881
   */
882
  public escapeReservedWord(name) {
883
    throw new Error('reserved word ' + name + ' not allowed');
×
884
  }
885

886
  /**
887
   * Return the fully-qualified "Model" name for import
888
   *
889
   * @param name the name of the "Model"
890
   * @return the fully-qualified "Model" name for import
891
   */
892
  public toModelImport(name) {
893
    if ('' === this.modelPackage()) {
368!
894
      return name;
×
895
    } else {
896
      return this.modelPackage() + '.' + name;
368✔
897
    }
898
  }
899

900
  /**
901
   * Return the fully-qualified "Api" name for import
902
   *
903
   * @param name the name of the "Api"
904
   * @return the fully-qualified "Api" name for import
905
   */
906
  public toApiImport(name) {
907
    return this.apiPackage() + '.' + name;
100✔
908
  }
909

910
  /**
911
   * Initalize special character mapping
912
   */
913
  public initalizeSpecialCharacterMapping() {
914
    this.specialCharReplacements.put('$', 'Dollar');
854✔
915
    this.specialCharReplacements.put('^', 'Caret');
854✔
916
    this.specialCharReplacements.put('|', 'Pipe');
854✔
917
    this.specialCharReplacements.put('=', 'Equal');
854✔
918
    this.specialCharReplacements.put('*', 'Star');
854✔
919
    this.specialCharReplacements.put('-', 'Minus');
854✔
920
    this.specialCharReplacements.put('&', 'Ampersand');
854✔
921
    this.specialCharReplacements.put('%', 'Percent');
854✔
922
    this.specialCharReplacements.put('#', 'Hash');
854✔
923
    this.specialCharReplacements.put('@', 'At');
854✔
924
    this.specialCharReplacements.put('!', 'Exclamation');
854✔
925
    this.specialCharReplacements.put('+', 'Plus');
854✔
926
    this.specialCharReplacements.put(':', 'Colon');
854✔
927
    this.specialCharReplacements.put('>', 'Greater_Than');
854✔
928
    this.specialCharReplacements.put('<', 'Less_Than');
854✔
929
    this.specialCharReplacements.put('.', 'Period');
854✔
930
    this.specialCharReplacements.put('_', 'Underscore');
854✔
931
    this.specialCharReplacements.put('<=', 'Less_Than_Or_Equal_To');
854✔
932
    this.specialCharReplacements.put('>=', 'Greater_Than_Or_Equal_To');
854✔
933
    this.specialCharReplacements.put('!=', 'Not_Equal');
854✔
934
  }
935

936
  /**
937
   * Return the symbol name of a symbol
938
   *
939
   * @param input Symbol (e.g. $)
940
   * @return Symbol name (e.g. Dollar)
941
   */
942
  public getSymbolName(input) {
943
    return this.specialCharReplacements.get(input);
×
944
  }
945

946
  /**
947
   * Return the instantiation type of the property, especially for map and array
948
   *
949
   * @param p Swagger property object
950
   * @return string presentation of the instantiation type of the property
951
   */
952
  public toInstantiationType(p) {
953
    if (p != null && p instanceof MapProperty) {
×
954
      const ap = p;
×
955
      const additionalProperties2 = ap.getAdditionalProperties();
×
956
      const type = additionalProperties2.getType();
×
957
      if (null == type) {
×
958
        log.error(
×
959
          'No Type defined for Additional Property ' +
960
            additionalProperties2 +
961
            '\n\tIn Property: ' +
962
            p,
963
        );
964
      }
965
      const inner = this.getSwaggerType(additionalProperties2);
×
966
      return this.__instantiationTypes.get('map') + '<String, ' + inner + '>';
×
967
    } else if (p != null && p instanceof ArrayProperty) {
×
968
      const ap = p;
×
969
      const inner = this.getSwaggerType(ap.getItems());
×
970
      return this.__instantiationTypes.get('array') + '<' + inner + '>';
×
971
    } else {
972
      return null;
×
973
    }
974
  }
975

976
  /**
977
   * Return the example value of the parameter.
978
   *
979
   * @param p Swagger property object
980
   */
981
  public setParameterExampleValue(p) {
982
    // Empty
983
  }
984

985
  /**
986
   * Return the example value of the property
987
   *
988
   * @param p Swagger property object
989
   * @return string presentation of the example value of the property
990
   */
991
  public toExampleValue(p) {
992
    if (p.getExample() != null) {
5,380✔
993
      return p.getExample().toString();
108✔
994
    }
995
    if (p instanceof StringProperty) {
5,272✔
996
      return 'null';
2,121✔
997
    } else if (p instanceof BooleanProperty) {
3,151✔
998
      return 'null';
189✔
999
    } else if (p instanceof DateProperty) {
2,962!
1000
      return 'null';
×
1001
    } else if (p instanceof DateTimeProperty) {
2,962!
1002
      return 'null';
×
1003
    } else if (p instanceof DoubleProperty) {
2,962✔
1004
      const dp = p;
125✔
1005
      if ((dp as any).getExample() != null) {
125!
1006
        return (dp as any).getExample().toString();
×
1007
      }
1008
      return 'null';
125✔
1009
    } else if (p instanceof FloatProperty) {
2,837!
UNCOV
1010
      const dp = p;
×
UNCOV
1011
      if ((dp as any).getExample() != null) {
×
1012
        return (dp as any).getExample().toString();
×
1013
      }
UNCOV
1014
      return 'null';
×
1015
    } else if (p instanceof IntegerProperty) {
2,837!
1016
      const dp = p;
×
1017
      if ((dp as any).getExample() != null) {
×
1018
        return (dp as any).getExample().toString();
×
1019
      }
1020
      return 'null';
×
1021
    } else if (p instanceof LongProperty) {
2,837✔
1022
      const dp = p;
591✔
1023
      if ((dp as any).getExample() != null) {
591!
1024
        return (dp as any).getExample().toString();
×
1025
      }
1026
      return 'null';
591✔
1027
    } else {
1028
      return 'null';
2,246✔
1029
    }
1030
  }
1031

1032
  /**
1033
   * Return the default value of the property
1034
   *
1035
   * @param p Swagger property object
1036
   * @return string presentation of the default value of the property
1037
   */
1038
  public toDefaultValue(p) {
1039
    if (p != null && p instanceof StringProperty) {
1,827✔
1040
      return 'null';
717✔
1041
    } else if (p != null && p instanceof BooleanProperty) {
1,110✔
1042
      return 'null';
75✔
1043
    } else if (p != null && p instanceof DateProperty) {
1,035!
1044
      return 'null';
×
1045
    } else if (p != null && p instanceof DateTimeProperty) {
1,035!
1046
      return 'null';
×
1047
    } else if (p != null && p instanceof DoubleProperty) {
1,035✔
1048
      const dp = p;
47✔
1049
      if ((dp as any).getDefault() != null) {
47!
1050
        return (dp as any).getDefault().toString();
×
1051
      }
1052
      return 'null';
47✔
1053
    } else if (p != null && p instanceof FloatProperty) {
988!
UNCOV
1054
      const dp = p;
×
UNCOV
1055
      if ((dp as any).getDefault() != null) {
×
1056
        return (dp as any).getDefault().toString();
×
1057
      }
UNCOV
1058
      return 'null';
×
1059
    } else if (p != null && p instanceof IntegerProperty) {
988!
1060
      const dp = p;
×
1061
      if ((dp as any).getDefault() != null) {
×
1062
        return (dp as any).getDefault().toString();
×
1063
      }
1064
      return 'null';
×
1065
    } else if (p != null && p instanceof LongProperty) {
988✔
1066
      const dp = p;
173✔
1067
      if ((dp as any).getDefault() != null) {
173!
1068
        return (dp as any).getDefault().toString();
×
1069
      }
1070
      return 'null';
173✔
1071
    } else {
1072
      return 'null';
815✔
1073
    }
1074
  }
1075

1076
  /**
1077
   * Return the property initialized from a data object
1078
   * Useful for initialization with a plain object in JavaScript
1079
   *
1080
   * @param name Name of the property object
1081
   * @param p Swagger property object
1082
   * @return string presentation of the default value of the property
1083
   */
1084
  public toDefaultValueWithParam(name, p) {
1085
    return ' = data.' + name + ';';
3,061✔
1086
  }
1087

1088
  /**
1089
   * returns the swagger type for the property
1090
   * @param p Swagger property object
1091
   * @return string presentation of the type
1092
   */
1093
  public getSwaggerType(p) {
1094
    let datatype: any = null;
19,378✔
1095
    if (
19,378!
1096
      p != null &&
46,735✔
1097
      p instanceof StringProperty &&
1098
      'number' === p.getFormat()
1099
    ) {
1100
      datatype = 'BigDecimal';
×
1101
    } else if (p != null && p instanceof StringProperty) {
19,378✔
1102
      datatype = 'string';
7,979✔
1103
    } else if (p != null && p instanceof ByteArrayProperty) {
11,399!
1104
      datatype = 'ByteArray';
×
1105
    } else if (p != null && p instanceof BinaryProperty) {
11,399!
1106
      datatype = 'binary';
×
1107
    } else if (p != null && p instanceof BooleanProperty) {
11,399✔
1108
      datatype = 'boolean';
647✔
1109
    } else if (p != null && p instanceof DateProperty) {
10,752!
1110
      datatype = 'date';
×
1111
    } else if (p != null && p instanceof DateTimeProperty) {
10,752!
1112
      datatype = 'DateTime';
×
1113
    } else if (p != null && p instanceof DoubleProperty) {
10,752✔
1114
      datatype = 'double';
425✔
1115
    } else if (p != null && p instanceof FloatProperty) {
10,327!
UNCOV
1116
      datatype = 'float';
×
1117
    } else if (p != null && p instanceof IntegerProperty) {
10,327!
1118
      datatype = 'integer';
×
1119
    } else if (p != null && p instanceof LongProperty) {
10,327✔
1120
      datatype = 'long';
2,039✔
1121
    } else if (p != null && p instanceof MapProperty) {
8,288✔
1122
      datatype = 'map';
178✔
1123
    } else if (p != null && p instanceof DecimalProperty) {
8,110✔
1124
      datatype = 'number';
204✔
1125
    } else if (p != null && p instanceof UUIDProperty) {
7,906✔
1126
      datatype = 'UUID';
34✔
1127
    } else if (p != null && p instanceof RefProperty) {
7,872✔
1128
      try {
4,454✔
1129
        const r = p;
4,454✔
1130
        datatype = r.get$ref();
4,454✔
1131
        if (datatype.indexOf('#/definitions/') === 0) {
4,454!
1132
          datatype = datatype.substring('#/definitions/'.length);
4,454✔
1133
        }
1134
      } catch (e) {
1135
        log.warn(
×
1136
          `Error obtaining the datatype from RefProperty:${p}. Datatype default to Object`,
1137
        );
1138
        log.trace(e);
×
1139
        datatype = 'Object';
×
1140
      }
1141
    } else {
1142
      if (p != null) {
3,418!
1143
        datatype = p.getType();
3,418✔
1144
      }
1145
    }
1146
    return datatype;
19,378✔
1147
  }
1148

1149
  /**
1150
   * Return the snake-case of the string
1151
   *
1152
   * @param name string to be snake-cased
1153
   * @return snake-cased string
1154
   */
1155
  public snakeCase(name) {
1156
    return StringUtils.snakeCase(name);
346✔
1157
  }
1158

1159
  /**
1160
   * Capitalize the string
1161
   *
1162
   * @param name string to be capitalized
1163
   * @return capitalized string
1164
   */
1165
  public initialCaps(name) {
1166
    return StringUtils.capitalize(name);
810✔
1167
  }
1168

1169
  /**
1170
   * Output the type declaration of a given name
1171
   *
1172
   * @param name name
1173
   * @return a string presentation of the type
1174
   */
1175
  public getTypeDeclaration(name) {
1176
    if (name == null || typeof name === 'string') {
7,859✔
1177
      return name;
160✔
1178
    }
1179
    let swaggerType = this.getSwaggerType(name);
7,699✔
1180
    if (this.__typeMapping.containsKey(swaggerType)) {
7,699!
1181
      swaggerType = this.__typeMapping.get(swaggerType);
×
1182
    }
1183
    return swaggerType;
7,699✔
1184
  }
1185

1186
  /**
1187
   * Output the API (class) name (capitalized) ending with "Api"
1188
   * Return DefaultApi if name is empty
1189
   *
1190
   * @param name the name of the Api
1191
   * @return capitalized Api name ending with "Api"
1192
   */
1193
  public toApiName(name) {
1194
    if (name.length === 0) {
608!
1195
      return 'DefaultApi';
×
1196
    }
1197
    return this.initialCaps(name) + 'Api';
608✔
1198
  }
1199

1200
  /**
1201
   * Output the proper model name (capitalized)
1202
   *
1203
   * @param name the name of the model
1204
   * @return capitalized model name
1205
   */
1206
  public toModelName(name) {
1207
    return this.initialCaps(this.modelNamePrefix + name + this.modelNameSuffix);
×
1208
  }
1209

1210
  /**
1211
   * Convert Swagger Model object to Codegen Model object
1212
   *
1213
   * @param name the name of the model
1214
   * @param model Swagger Model object
1215
   * @param allDefinitions a map of all Swagger models from the spec
1216
   * @return Codegen Model object
1217
   */
1218
  public fromModel(name, model, allDefinitions = null) {
41✔
1219
    const m = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
563✔
1220
    if (this.__reservedWords.contains(name)) {
563!
1221
      m.name = this.escapeReservedWord(name);
×
1222
    } else {
1223
      m.name = name;
563✔
1224
    }
1225
    m.description = this.escapeText(model.getDescription());
563✔
1226
    m.unescapedDescription = model.getDescription();
563✔
1227
    m.classname = this.toModelName(name);
563✔
1228
    m.classVarName = this.toVarName(name);
563✔
1229
    m.classFilename = this.toModelFilename(name);
563✔
1230
    m.modelJson = Json.pretty(model);
563✔
1231
    m.externalDocs = model.getExternalDocs();
563✔
1232
    m.vendorExtensions = model.getVendorExtensions();
563✔
1233
    if (model != null && model instanceof ModelImpl) {
563✔
1234
      m.discriminator = model.getDiscriminator();
535✔
1235
    }
1236
    if (model != null && model instanceof ArrayModel) {
563!
1237
      const am = model;
×
1238
      const arrayProperty = new ArrayProperty().items(am.getItems());
×
1239
      m.hasEnums = false;
×
1240
      m.isArrayModel = true;
×
1241
      m.arrayModelType = this.fromProperty(name, arrayProperty).complexType;
×
1242
      this.addParentContainer(m, name, arrayProperty);
×
1243
    } else if (model != null && model instanceof RefModel) {
563!
1244
      // Empty
1245
    } else if (model != null && model instanceof ComposedModel) {
563✔
1246
      const composed = model;
28✔
1247
      const properties = newHashMap();
28✔
1248
      const required = [];
28✔
1249
      let allProperties;
1250
      let allRequired;
1251
      if (this.supportsInheritance) {
28✔
1252
        allProperties = newHashMap();
12✔
1253
        allRequired = [];
12✔
1254
        m.allVars = [];
12✔
1255
      } else {
1256
        allProperties = null;
16✔
1257
        allRequired = null;
16✔
1258
      }
1259
      let parent = composed.getParent();
28✔
1260
      if (composed.getInterfaces() != null) {
28!
1261
        if (m.interfaces == null) {
28!
1262
          m.interfaces = [];
28✔
1263
        }
1264
        for (const _interface of composed.getInterfaces()) {
28✔
1265
          let interfaceModel: any = null;
28✔
1266
          if (allDefinitions != null) {
28!
1267
            interfaceModel = (allDefinitions as any).get(
28✔
1268
              _interface.getSimpleRef(),
1269
            );
1270
          }
1271
          if (
28!
1272
            parent == null &&
112✔
1273
            interfaceModel != null &&
1274
            interfaceModel instanceof ModelImpl &&
1275
            interfaceModel.getDiscriminator() != null
1276
          ) {
1277
            parent = _interface;
×
1278
          } else {
1279
            const interfaceRef = this.toModelName(_interface.getSimpleRef());
28✔
1280
            m.interfaces.push(interfaceRef);
28✔
1281
            this.addImport(m, interfaceRef);
28✔
1282
            if (allDefinitions != null) {
28!
1283
              if (this.supportsInheritance) {
28✔
1284
                this.addProperties(
12✔
1285
                  allProperties,
1286
                  allRequired,
1287
                  interfaceModel,
1288
                  allDefinitions,
1289
                );
1290
              } else {
1291
                this.addProperties(
16✔
1292
                  properties,
1293
                  required,
1294
                  interfaceModel,
1295
                  allDefinitions,
1296
                );
1297
              }
1298
            }
1299
          }
1300
        }
1301
      }
1302
      if (parent != null) {
28!
1303
        const parentRef = parent.getSimpleRef();
×
1304
        m.parentSchema = parentRef;
×
1305
        m.parent = this.toModelName(parent.getSimpleRef());
×
1306
        this.addImport(m, m.parent);
×
1307
        if (allDefinitions != null) {
×
1308
          const parentModel = (allDefinitions as any).get(m.parentSchema);
×
1309
          if (this.supportsInheritance) {
×
1310
            this.addProperties(
×
1311
              allProperties,
1312
              allRequired,
1313
              parentModel,
1314
              allDefinitions,
1315
            );
1316
          } else {
1317
            this.addProperties(
×
1318
              properties,
1319
              required,
1320
              parentModel,
1321
              allDefinitions,
1322
            );
1323
          }
1324
        }
1325
      }
1326
      let child = composed.getChild();
28✔
1327
      if (
28!
1328
        child != null &&
84!
1329
        child != null &&
1330
        child instanceof RefModel &&
1331
        allDefinitions != null
1332
      ) {
1333
        const childRef = child.getSimpleRef();
×
1334
        child = (allDefinitions as any).get(childRef);
×
1335
      }
1336
      if (child != null && child != null && child instanceof ModelImpl) {
28!
1337
        this.addProperties(properties, required, child, allDefinitions);
28✔
1338
        if (this.supportsInheritance) {
28✔
1339
          this.addProperties(allProperties, allRequired, child, allDefinitions);
12✔
1340
        }
1341
      }
1342
      this.addVars(m, properties, required, allProperties, allRequired);
28✔
1343
    } else {
1344
      const impl = model;
535✔
1345
      if (impl.getEnum() != null && impl.getEnum().length > 0) {
535!
1346
        m.isEnum = true;
×
1347
        m.allowableValues = newHashMap();
×
1348
        m.allowableValues.put('values', impl.getEnum());
×
1349
        const p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
×
1350
        m.dataType = this.getSwaggerType(p);
×
1351
      }
1352
      if (
535!
1353
        impl.getAdditionalProperties &&
1,070✔
1354
        impl.getAdditionalProperties() != null
1355
      ) {
1356
        this.addAdditionPropertiesToCodeGenModel(m, impl);
×
1357
      }
1358
      this.addVars(m, impl.getProperties(), impl.getRequired());
535✔
1359
    }
1360
    if (m.vars != null) {
563!
1361
      for (const prop of m.vars) {
563✔
1362
        this.postProcessModelProperty(m, prop);
2,671✔
1363
      }
1364
    }
1365
    return m;
563✔
1366
  }
1367

1368
  public addAdditionPropertiesToCodeGenModel(codegenModel, swaggerModel) {
1369
    const swaggerAdditionalProperties = swaggerModel.getAdditionalProperties();
×
1370
    const mapProperty = new MapProperty();
×
1371
    mapProperty.setAdditionalProperties(swaggerAdditionalProperties);
×
1372
    this.addParentContainer(codegenModel, codegenModel.name, mapProperty);
×
1373
  }
1374

1375
  public addProperties(properties, required, model, allDefinitions) {
1376
    if (model != null && model instanceof ModelImpl) {
68!
1377
      const mi: any = model;
68✔
1378
      if (mi.getProperties() != null) {
68!
1379
        properties.putAll(mi.getProperties());
68✔
1380
      }
1381
      if (mi.getRequired() != null) {
68!
1382
        required.push(...mi.getRequired());
68✔
1383
      }
1384
    } else if (model != null && model instanceof RefModel) {
×
1385
      const interfaceRef = model.getSimpleRef();
×
1386
      const interfaceModel = allDefinitions.get(interfaceRef);
×
1387
      this.addProperties(properties, required, interfaceModel, allDefinitions);
×
1388
    } else if (model != null && model instanceof ComposedModel) {
×
1389
      for (const component of model.getAllOf()) {
×
1390
        this.addProperties(properties, required, component, allDefinitions);
×
1391
      }
1392
    }
1393
  }
1394

1395
  /**
1396
   * Camelize the method name of the getter and setter
1397
   *
1398
   * @param name string to be camelized
1399
   * @return Camelized string
1400
   */
1401
  public getterAndSetterCapitalize(name) {
1402
    if (name == null || name.length === 0) {
10,760!
1403
      return name;
×
1404
    }
1405
    return DefaultCodegen.camelize(this.toVarName(name));
10,760✔
1406
  }
1407

1408
  /**
1409
   * Convert Swagger Property object to Codegen Property object
1410
   *
1411
   * @param name name of the property
1412
   * @param p Swagger property object
1413
   * @return Codegen Property object
1414
   */
1415
  public fromProperty(name, p) {
1416
    if (p == null) {
5,380!
1417
      log.error('unexpected missing property for name ' + name);
×
1418
      return null;
×
1419
    }
1420
    const property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
5,380✔
1421
    property.name = this.toVarName(name);
5,380✔
1422
    property.baseName = name;
5,380✔
1423
    property.nameInCamelCase = DefaultCodegen.camelize(property.name, false);
5,380✔
1424
    property.description = this.escapeText(p.getDescription());
5,380✔
1425
    property.unescapedDescription = p.getDescription();
5,380✔
1426
    property.getter = 'get' + this.getterAndSetterCapitalize(name);
5,380✔
1427
    property.setter = 'set' + this.getterAndSetterCapitalize(name);
5,380✔
1428
    property.example = this.toExampleValue(p);
5,380✔
1429
    property.defaultValue = this.toDefaultValue(p);
5,380✔
1430
    property.defaultValueWithParam = this.toDefaultValueWithParam(name, p);
5,380✔
1431
    property.jsonSchema = Json.pretty(p);
5,380✔
1432
    property.isReadOnly = p.getReadOnly();
5,380✔
1433
    property.vendorExtensions = p.getVendorExtensions();
5,380✔
1434
    const type = this.getSwaggerType(p);
5,380✔
1435

1436
    const allowableValues = newHashMap();
5,380✔
1437

1438
    if (p instanceof AbstractNumericProperty) {
5,380✔
1439
      const np: any = p;
1,120✔
1440
      property.minimum = np.getMinimum();
1,120✔
1441
      property.maximum = np.getMaximum();
1,120✔
1442
      property.exclusiveMinimum = np.getExclusiveMinimum();
1,120✔
1443
      property.exclusiveMaximum = np.getExclusiveMaximum();
1,120✔
1444
      if (
1,120!
1445
        property.minimum != null ||
4,480✔
1446
        property.maximum != null ||
1447
        property.exclusiveMinimum != null ||
1448
        property.exclusiveMaximum != null
1449
      ) {
1450
        property.hasValidation = true;
×
1451
      }
1452

1453
      if (np.getMinimum() != null) {
1,120!
1454
        allowableValues.put('min', np.getMinimum());
×
1455
      }
1456
      if (np.getMaximum() != null) {
1,120!
1457
        allowableValues.put('max', np.getMaximum());
×
1458
      }
1459
    }
1460
    if (p instanceof StringProperty) {
5,380✔
1461
      const sp: any = p;
2,229✔
1462
      property.maxLength = sp.getMaxLength();
2,229✔
1463
      property.minLength = sp.getMinLength();
2,229✔
1464
      property.datatype = type;
2,229✔
1465
      property.isString = true;
2,229✔
1466
      property.isPrimitive = true;
2,229✔
1467
      property.pattern = this.toRegularExpression(sp.getPattern());
2,229✔
1468
      if (
2,229!
1469
        property.pattern != null ||
6,687✔
1470
        property.minLength != null ||
1471
        property.maxLength != null
1472
      ) {
1473
        property.hasValidation = true;
×
1474
      }
1475
      property.isString = true;
2,229✔
1476
    } else if (
3,151✔
1477
      p instanceof BaseIntegerProperty &&
3,839✔
1478
      !(p instanceof IntegerProperty) &&
1479
      !(p instanceof LongProperty)
1480
    ) {
1481
      property.isInteger = true;
344✔
1482
    } else if (p instanceof IntegerProperty) {
2,807!
1483
      property.isInteger = true;
×
1484
    } else if (p instanceof LongProperty) {
2,807✔
1485
      property.isLong = true;
591✔
1486
    } else if (p instanceof BooleanProperty) {
2,216✔
1487
      property.isBoolean = true;
189✔
1488
    } else if (p instanceof BinaryProperty) {
2,027!
1489
      property.isBinary = true;
×
1490
    } else if (p instanceof UUIDProperty) {
2,027✔
1491
      property.isString = true;
10✔
1492
    } else if (p instanceof ByteArrayProperty) {
2,017!
1493
      property.isByteArray = true;
×
1494
    } else if (
2,017✔
1495
      p instanceof DecimalProperty &&
2,137✔
1496
      !(p instanceof DoubleProperty) &&
1497
      !(p instanceof FloatProperty)
1498
    ) {
1499
      property.isFloat = true;
60✔
1500
    } else if (p instanceof DoubleProperty) {
1,957✔
1501
      property.isDouble = true;
125✔
1502
    } else if (p instanceof FloatProperty) {
1,832!
UNCOV
1503
      property.isFloat = true;
×
1504
    } else if (p instanceof DateProperty) {
1,832!
1505
      property.isDate = true;
×
1506
    } else if (p instanceof DateTimeProperty) {
1,832!
1507
      property.isDateTime = true;
×
1508
    } else if (p instanceof ObjectProperty) {
1,832!
UNCOV
1509
      property.isObject = true;
×
UNCOV
1510
      property.isPrimitive = true;
×
1511
    }
1512
    if (p.getEnum() != null) {
5,380✔
1513
      const _enum = p.getEnum();
243✔
1514
      property._enum = _enum;
243✔
1515
      property.isEnum = true;
243✔
1516
      allowableValues.put('values', _enum);
243✔
1517
    }
1518
    if (!allowableValues.isEmpty()) {
5,380✔
1519
      property.allowableValues = allowableValues;
243✔
1520
    }
1521

1522
    property.datatype = this.getTypeDeclaration(p);
5,380✔
1523
    property.dataFormat = p.getFormat();
5,380✔
1524
    if (property.isEnum) {
5,380✔
1525
      property.datatypeWithEnum = this.toEnumName(property);
243✔
1526
      property.enumName = this.toEnumName(property);
243✔
1527
    } else {
1528
      property.datatypeWithEnum = property.datatype;
5,137✔
1529
    }
1530
    property.baseType = this.getSwaggerType(p);
5,380✔
1531
    if (p != null && p instanceof ArrayProperty) {
5,380✔
1532
      property.isContainer = true;
646✔
1533
      property.isListContainer = true;
646✔
1534
      property.containerType = 'array';
646✔
1535
      property.baseType = this.getSwaggerType(p);
646✔
1536
      const cp = this.fromProperty(property.name, p.getItems());
646✔
1537

1538
      this.updatePropertyForArray(property, cp);
646✔
1539
    } else if (p != null && p instanceof MapProperty) {
4,734✔
1540
      property.isContainer = true;
54✔
1541
      property.isMapContainer = true;
54✔
1542
      property.containerType = 'map';
54✔
1543
      property.baseType = this.getSwaggerType(p);
54✔
1544
      const cp = this.fromProperty('inner', p.getAdditionalProperties());
54✔
1545
      this.updatePropertyForMap(property, cp);
54✔
1546
    } else {
1547
      this.setNonArrayMapProperty(property, type);
4,680✔
1548
    }
1549
    return property;
5,380✔
1550
  }
1551

1552
  /**
1553
   * Update property for array(list) container
1554
   * @param property Codegen property
1555
   * @param innerProperty Codegen inner property of map or list
1556
   */
1557
  public updatePropertyForArray(property, innerProperty) {
1558
    if (innerProperty == null) {
646!
1559
      log.warn(`skipping invalid array property ${Json.pretty(property)}`);
×
1560
    } else {
1561
      if (!this.__languageSpecificPrimitives.contains(innerProperty.baseType)) {
646✔
1562
        property.complexType = innerProperty.baseType;
400✔
1563
      } else {
1564
        property.isPrimitiveType = true;
246✔
1565
        property.baseType = innerProperty.baseType;
246✔
1566
      }
1567
      property.items = innerProperty;
646✔
1568
      if (this.isPropertyInnerMostEnum(property)) {
646✔
1569
        property.isEnum = true;
54✔
1570
        this.updateDataTypeWithEnumForArray(property);
54✔
1571
        property.allowableValues = this.getInnerEnumAllowableValues(property);
54✔
1572
      }
1573
    }
1574
  }
1575

1576
  /**
1577
   * Update property for map container
1578
   * @param property Codegen property
1579
   * @param innerProperty Codegen inner property of map or list
1580
   */
1581
  public updatePropertyForMap(property, innerProperty) {
1582
    if (innerProperty == null) {
54!
1583
      log.warn(`skipping invalid map property ${Json.pretty(property)}`);
×
1584
      return;
×
1585
    } else {
1586
      if (!this.__languageSpecificPrimitives.contains(innerProperty.baseType)) {
54!
1587
        property.complexType = innerProperty.baseType;
×
1588
      } else {
1589
        property.isPrimitiveType = true;
54✔
1590
      }
1591
      property.items = innerProperty;
54✔
1592
      if (this.isPropertyInnerMostEnum(property)) {
54!
1593
        property.isEnum = true;
×
1594
        this.updateDataTypeWithEnumForMap(property);
×
1595
        property.allowableValues = this.getInnerEnumAllowableValues(property);
×
1596
      }
1597
    }
1598
  }
1599

1600
  /**
1601
   * Update property for map container
1602
   * @param property Codegen property
1603
   * @return True if the inner most type is enum
1604
   */
1605
  public isPropertyInnerMostEnum(property) {
1606
    let currentProperty = property;
700✔
1607
    while (
700✔
1608
      currentProperty != null &&
4,146✔
1609
      (currentProperty.isMapContainer || currentProperty.isListContainer)
1610
    ) {
1611
      currentProperty = currentProperty.items;
700✔
1612
    }
1613

1614
    return currentProperty.isEnum;
700✔
1615
  }
1616

1617
  public getInnerEnumAllowableValues(property) {
1618
    let currentProperty = property;
54✔
1619
    while (
54✔
1620
      currentProperty != null &&
324✔
1621
      (currentProperty.isMapContainer || currentProperty.isListContainer)
1622
    ) {
1623
      currentProperty = currentProperty.items;
54✔
1624
    }
1625
    return currentProperty.allowableValues;
54✔
1626
  }
1627

1628
  /**
1629
   * Update datatypeWithEnum for array container
1630
   * @param property Codegen property
1631
   */
1632
  public updateDataTypeWithEnumForArray(property) {
1633
    let baseItem = property.items;
54✔
1634
    while (
54✔
1635
      baseItem != null &&
162✔
1636
      (baseItem.isMapContainer || baseItem.isListContainer)
1637
    ) {
1638
      baseItem = baseItem.items;
×
1639
    }
1640
    property.datatypeWithEnum = property.datatypeWithEnum
54✔
1641
      .split(baseItem.baseType)
1642
      .join(this.toEnumName(baseItem));
1643
    property.enumName = this.toEnumName(property);
54✔
1644
    if (property.defaultValue != null) {
54✔
1645
      property.defaultValue = property.defaultValue
16✔
1646
        .split(baseItem.baseType)
1647
        .join(this.toEnumName(baseItem));
1648
    }
1649
  }
1650

1651
  /**
1652
   * Update datatypeWithEnum for map container
1653
   * @param property Codegen property
1654
   */
1655
  public updateDataTypeWithEnumForMap(property) {
1656
    let baseItem = property.items;
×
1657
    while (
×
1658
      baseItem != null &&
×
1659
      (baseItem.isMapContainer || baseItem.isListContainer)
1660
    ) {
1661
      baseItem = baseItem.items;
×
1662
    }
1663
    property.datatypeWithEnum = property.datatypeWithEnum
×
1664
      .split(', ' + baseItem.baseType)
1665
      .join(', ' + this.toEnumName(baseItem));
1666
    property.enumName = this.toEnumName(property);
×
1667
    if (property.defaultValue != null) {
×
1668
      property.defaultValue = property.defaultValue
×
1669
        .split(', ' + property.items.baseType)
1670
        .join(', ' + this.toEnumName(property.items));
1671
    }
1672
  }
1673

1674
  public setNonArrayMapProperty(property, type) {
1675
    property.isNotContainer = true;
4,680✔
1676
    if (this.languageSpecificPrimitives().contains(type)) {
4,680✔
1677
      property.isPrimitiveType = true;
3,518✔
1678
    } else {
1679
      property.complexType = property.baseType;
1,162✔
1680
    }
1681
  }
1682

1683
  /**
1684
   * Override with any special handling of response codes
1685
   * @param responses Swagger Operation's responses
1686
   * @return default method response or <tt>null</tt> if not found
1687
   */
1688
  public findMethodResponse(responses) {
1689
    let code = null;
739✔
1690
    let resp;
1691
    for (const [responseCode, response] of responses) {
739✔
1692
      if (('' + responseCode).startsWith('2') || responseCode === 'default') {
1,236✔
1693
        if (code == null || StringUtils.compareTo(responseCode, code) > 0) {
635✔
1694
          code = responseCode;
557✔
1695
          resp = response;
557✔
1696
        }
1697
      }
1698
    }
1699

1700
    return resp;
739✔
1701
  }
1702

1703
  /**
1704
   * Convert Swagger Operation object to Codegen Operation object
1705
   *
1706
   * @param p the path of the operation
1707
   * @param httpMethod HTTP method
1708
   * @param operation Swagger operation object
1709
   * @param definitions a map of Swagger models
1710
   * @param swagger a Swagger object representing the spec
1711
   * @return Codegen Operation object
1712
   */
1713
  public fromOperation(
1714
    p,
1715
    httpMethod,
1716
    operation,
1717
    definitions,
1718
    swagger: any = null,
383✔
1719
  ) {
1720
    const op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
816✔
1721
    const imports = newHashSet();
816✔
1722
    op.vendorExtensions = operation.getVendorExtensions();
816✔
1723
    const operationId = this.removeNonNameElementToCamelCase(
816✔
1724
      this.getOrGenerateOperationId(operation, p, httpMethod),
1725
    );
1726
    op.operationId = this.toOperationId(operationId);
816✔
1727
    op.path = p;
816✔
1728
    op.summary = this.escapeText(operation.getSummary());
816✔
1729
    op.unescapedNotes = operation.getDescription();
816✔
1730
    op.notes = this.escapeText(operation.getDescription());
816✔
1731
    op.tags = operation.getTags();
816✔
1732
    op.hasConsumes = false;
816✔
1733
    op.hasProduces = false;
816✔
1734
    let consumes = [];
816✔
1735
    if (isNotEmptySet(operation.getConsumes())) {
816✔
1736
      consumes = operation.getConsumes();
170✔
1737
    } else if (swagger != null && isNotEmptySet(swagger.getConsumes())) {
646!
1738
      consumes = swagger.getConsumes();
×
1739
      log.debug(
×
1740
        `No consumes defined in operation.
1741
Using global consumes (${swagger.getConsumes()}) for ${op.operationId}`,
1742
      );
1743
    }
1744
    if (consumes != null && consumes.length) {
816✔
1745
      const c: any[] = [];
170✔
1746
      let count = 0;
170✔
1747
      for (const key of consumes) {
170✔
1748
        const mediaType = newHashMap([
224✔
1749
          'mediaType',
1750
          this.escapeText(this.escapeQuotationMark(key)),
1751
        ]);
1752
        count += 1;
224✔
1753
        if (count < consumes.length) {
224✔
1754
          mediaType.put('hasMore', 'true');
54✔
1755
        } else {
1756
          mediaType.put('hasMore', null);
170✔
1757
        }
1758
        c.push(mediaType);
224✔
1759
      }
1760
      op.consumes = c;
170✔
1761
      op.hasConsumes = true;
170✔
1762
    }
1763
    let produces = [];
816✔
1764
    if (operation.getProduces() != null) {
816!
1765
      if (operation.getProduces().length > 0) {
816✔
1766
        produces = operation.getProduces();
785✔
1767
      }
1768
    } else if (
×
1769
      swagger != null &&
×
1770
      swagger.getProduces() != null &&
1771
      swagger.getProduces().length > 0
1772
    ) {
1773
      produces = swagger.getProduces();
×
1774
      log.debug(
×
1775
        `No produces defined in operation.
1776
Using global produces (${swagger.getProduces()}) for ${op.operationId}`,
1777
      );
1778
    }
1779
    if (produces != null && produces.length > 0) {
816✔
1780
      const c: any[] = [];
785✔
1781
      let count = 0;
785✔
1782
      for (const key of produces) {
785✔
1783
        const mediaType = newHashMap([
1,326✔
1784
          'mediaType',
1785
          this.escapeText(this.escapeQuotationMark(key)),
1786
        ]);
1787
        count += 1;
1,326✔
1788
        if (count < produces.length) {
1,326✔
1789
          mediaType.put('hasMore', 'true');
541✔
1790
        } else {
1791
          mediaType.put('hasMore', null);
785✔
1792
        }
1793
        c.push(mediaType);
1,326✔
1794
      }
1795
      op.produces = c;
785✔
1796
      op.hasProduces = true;
785✔
1797
    }
1798

1799
    const responses = operation.getResponses();
816✔
1800
    if (responses != null && !responses.isEmpty()) {
816✔
1801
      const methodResponse = this.findMethodResponse(responses);
739✔
1802
      for (const [key, response] of operation.getResponses()) {
739✔
1803
        const r = this.fromResponse(key, response);
1,236✔
1804
        r.hasMore = true;
1,236✔
1805
        if (
1,236✔
1806
          r.baseType != null &&
2,076✔
1807
          !this.__defaultIncludes.contains(r.baseType) &&
1808
          !this.__languageSpecificPrimitives.contains(r.baseType)
1809
        ) {
1810
          imports.add(r.baseType);
359✔
1811
        }
1812
        r.isDefault = response === methodResponse;
1,236✔
1813
        op.responses.push(r);
1,236✔
1814
        if (r.isBinary && r.isDefault) {
1,236!
1815
          op.isResponseBinary = true;
×
1816
        }
1817
      }
1818
      op.responses[op.responses.length - 1].hasMore = false;
739✔
1819
      if (methodResponse != null) {
739✔
1820
        if (methodResponse.getSchema() != null) {
550✔
1821
          const cm = this.fromProperty('response', methodResponse.getSchema());
381✔
1822
          const responseProperty = methodResponse.getSchema();
381✔
1823
          if (
381✔
1824
            responseProperty != null &&
762✔
1825
            responseProperty instanceof ArrayProperty
1826
          ) {
1827
            const ap = responseProperty;
109✔
1828
            const innerProperty = this.fromProperty('response', ap.getItems());
109✔
1829
            op.returnBaseType = innerProperty.baseType;
109✔
1830
          } else {
1831
            if (cm.complexType != null) {
272✔
1832
              op.returnBaseType = cm.complexType;
164✔
1833
            } else {
1834
              op.returnBaseType = cm.baseType;
108✔
1835
            }
1836
          }
1837
          op.examples = new ExampleGenerator(definitions).generate(
381✔
1838
            methodResponse.getExamples(),
1839
            operation.getProduces(),
1840
            responseProperty,
1841
          );
1842
          op.defaultResponse = this.toDefaultValue(responseProperty);
381✔
1843
          op.returnType = cm.datatype;
381✔
1844
          op.hasReference =
381✔
1845
            definitions != null && definitions.containsKey(op.returnBaseType);
755✔
1846
          if (definitions != null) {
381✔
1847
            const m = definitions.get(op.returnBaseType);
374✔
1848
            if (m != null) {
374✔
1849
              const cmod = this.fromModel(op.returnBaseType, m, definitions);
273✔
1850
              op.discriminator = cmod.discriminator;
273✔
1851
            }
1852
          }
1853
          if (cm.isContainer != null) {
381✔
1854
            op.returnContainer = cm.containerType;
136✔
1855
            if ('map' === cm.containerType) {
136✔
1856
              op.isMapContainer = true;
27✔
1857
            } else if (
109!
1858
              ((o1, o2) =>
1859
                o1.toUpperCase() === (o2 === null ? o2 : o2.toUpperCase()))(
109!
1860
                'list',
1861
                cm.containerType,
1862
              )
1863
            ) {
1864
              op.isListContainer = true;
×
1865
            } else if (
109!
1866
              ((o1, o2) =>
1867
                o1.toUpperCase() === (o2 === null ? o2 : o2.toUpperCase()))(
109!
1868
                'array',
1869
                cm.containerType,
1870
              )
1871
            ) {
1872
              op.isListContainer = true;
109✔
1873
            }
1874
          } else {
1875
            op.returnSimpleType = true;
245✔
1876
          }
1877
          if (
381✔
1878
            this.languageSpecificPrimitives().contains(op.returnBaseType) ||
669✔
1879
            op.returnBaseType == null
1880
          ) {
1881
            op.returnTypeIsPrimitive = true;
93✔
1882
          }
1883
        }
1884
        this.addHeaders(methodResponse, op.responseHeaders);
550✔
1885
      }
1886
    }
1887
    const parameters = operation.getParameters();
816✔
1888
    let bodyParam = null;
816✔
1889
    const allParams: any[] = [];
816✔
1890
    const bodyParams: any[] = [];
816✔
1891
    const pathParams: any[] = [];
816✔
1892
    const queryParams: any[] = [];
816✔
1893
    const headerParams: any[] = [];
816✔
1894
    const cookieParams: any[] = [];
816✔
1895
    const formParams: any[] = [];
816✔
1896
    if (parameters != null) {
816!
1897
      for (const param of parameters) {
816✔
1898
        const po = this.fromParameter(param, imports);
985✔
1899
        if (this.ensureUniqueParams) {
985!
1900
          while (true) {
985✔
1901
            let exists = false;
985✔
1902
            for (const cp of allParams) {
985✔
1903
              if (po.paramName === (cp as any).paramName) {
426!
1904
                exists = true;
×
1905
                break;
×
1906
              }
1907
            }
1908
            if (exists) {
985!
1909
              po.paramName = DefaultCodegen.generateNextName(po.paramName);
×
1910
            } else {
1911
              break;
985✔
1912
            }
1913
          }
1914
        }
1915
        allParams.push(po);
985✔
1916
        if (param != null && param instanceof QueryParameter) {
985✔
1917
          queryParams.push(po.copy());
246✔
1918
        } else if (param != null && param instanceof PathParameter) {
739✔
1919
          pathParams.push(po.copy());
338✔
1920
        } else if (param != null && param instanceof HeaderParameter) {
401✔
1921
          headerParams.push(po.copy());
24✔
1922
        } else if (param != null && param instanceof CookieParameter) {
377!
1923
          cookieParams.push(po.copy());
×
1924
        } else if (param != null && param instanceof BodyParameter) {
377✔
1925
          bodyParam = po.copy();
269✔
1926
          bodyParams.push(po);
269✔
1927
        } else if (param != null && param instanceof FormParameter) {
108!
1928
          formParams.push(po);
108✔
1929
        }
1930
        if (po.required == null || !po.required) {
985✔
1931
          op.hasOptionalParams = true;
424✔
1932
        }
1933
      }
1934
    }
1935
    for (const i of imports) {
816✔
1936
      if (this.needToImport(i)) {
682✔
1937
        op.imports.add(i);
566✔
1938
      }
1939
    }
1940
    op.bodyParam = bodyParam;
816✔
1941
    op.httpMethod = httpMethod.toUpperCase();
816✔
1942
    if (this.sortParamsByRequiredFlag) {
816!
1943
      allParams.sort(sortByFlag);
816✔
1944
    }
1945
    op.allParams = DefaultCodegen.addHasMore(allParams);
816✔
1946
    op.bodyParams = DefaultCodegen.addHasMore(bodyParams);
816✔
1947
    op.pathParams = DefaultCodegen.addHasMore(pathParams);
816✔
1948
    op.queryParams = DefaultCodegen.addHasMore(queryParams);
816✔
1949
    op.headerParams = DefaultCodegen.addHasMore(headerParams);
816✔
1950
    op.formParams = DefaultCodegen.addHasMore(formParams);
816✔
1951
    op.nickname = op.operationId;
816✔
1952
    if (op.allParams.length > 0) {
816✔
1953
      //            op.allParams
1954
      op.hasParams = true;
686✔
1955
    }
1956
    op.externalDocs = operation.getExternalDocs();
816✔
1957
    op.__isRestfulShow = op.isRestfulShow();
816✔
1958
    op.__isRestfulIndex = op.isRestfulIndex();
816✔
1959
    op.__isRestfulCreate = op.isRestfulCreate();
816✔
1960
    op.__isRestfulUpdate = op.isRestfulUpdate();
816✔
1961
    op.__isRestfulDestroy = op.isRestfulDestroy();
816✔
1962
    op.__isRestful = op.isRestful();
816✔
1963
    return op;
816✔
1964
  }
1965

1966
  /**
1967
   * Convert Swagger Response object to Codegen Response object
1968
   *
1969
   * @param responseCode HTTP response code
1970
   * @param response Swagger Response object
1971
   * @return Codegen Response object
1972
   */
1973
  public fromResponse(responseCode, response) {
1974
    const r = CodegenModelFactory.newInstance(CodegenModelType.RESPONSE);
1,236✔
1975
    if ('default' === responseCode) {
1,236✔
1976
      r.code = '0';
226✔
1977
    } else {
1978
      r.code = responseCode;
1,010✔
1979
    }
1980
    r.message = this.escapeText(response.getDescription());
1,236✔
1981
    r.schema = response.getSchema();
1,236✔
1982
    r.examples = this.toExamples(response.getExamples());
1,236✔
1983
    r.jsonSchema = Json.pretty(response);
1,236✔
1984
    this.addHeaders(response, r.headers);
1,236✔
1985
    if (r.schema != null) {
1,236✔
1986
      const responseProperty = response.getSchema();
459✔
1987
      responseProperty.setRequired(true);
459✔
1988
      const cm = this.fromProperty('response', responseProperty);
459✔
1989
      if (
459✔
1990
        responseProperty != null &&
918✔
1991
        responseProperty instanceof ArrayProperty
1992
      ) {
1993
        const innerProperty = this.fromProperty(
109✔
1994
          'response',
1995
          responseProperty.getItems(),
1996
        );
1997
        r.baseType = innerProperty.baseType;
109✔
1998
        //     r.isListContainer = true;
1999
      } else {
2000
        if (cm.complexType != null) {
350✔
2001
          r.baseType = cm.complexType;
242✔
2002
        } else {
2003
          r.baseType = cm.baseType;
108✔
2004
        }
2005
      }
2006
      r.dataType = cm.datatype;
459✔
2007
      r.isBinary = this.isDataTypeBinary(cm.datatype);
459✔
2008
      if (cm.isContainer != null) {
459✔
2009
        r.simpleType = false;
136✔
2010
        r.containerType = cm.containerType;
136✔
2011
        r.isMapContainer = 'map' === cm.containerType;
136✔
2012
        r.isListContainer =
136✔
2013
          'list' === cm.containerType || 'array' === this.containerType;
272✔
2014
      } else {
2015
        r.simpleType = true;
323✔
2016
      }
2017
      r.primitiveType =
459✔
2018
        r.baseType == null ||
918✔
2019
        this.languageSpecificPrimitives().contains(r.baseType);
2020
    }
2021
    if (r.baseType == null) {
1,236✔
2022
      r.isMapContainer = false;
777✔
2023
      r.isListContainer = false;
777✔
2024
      r.primitiveType = true;
777✔
2025
      r.simpleType = true;
777✔
2026
    }
2027
    return r;
1,236✔
2028
  }
2029

2030
  /**
2031
   * Convert Swagger Parameter object to Codegen Parameter object
2032
   *
2033
   * @param param Swagger parameter object
2034
   * @param imports set of imports for library/package/module
2035
   * @return Codegen Parameter object
2036
   */
2037
  public fromParameter(param, imports) {
2038
    const p = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
985✔
2039
    p.baseName = param.getName();
985✔
2040
    p.description = this.escapeText(param.getDescription());
985✔
2041
    p.unescapedDescription = param.getDescription();
985✔
2042
    if (param.getRequired()) {
985✔
2043
      p.required = param.getRequired();
561✔
2044
    }
2045
    p.jsonSchema = Json.pretty(param);
985✔
2046
    if (System.getProperty('debugParser') != null) {
985!
2047
      log.info(`working on Parameter ${param}`);
×
2048
    }
2049
    if (param != null && param instanceof QueryParameter) {
985✔
2050
      p.defaultValue = param.getDefaultValue();
246✔
2051
    } else if (param != null && param instanceof HeaderParameter) {
739✔
2052
      p.defaultValue = param.getDefaultValue();
24✔
2053
    } else if (param != null && param instanceof FormParameter) {
715✔
2054
      p.defaultValue = param.getDefaultValue();
108✔
2055
    }
2056
    p.vendorExtensions = param.getVendorExtensions();
985✔
2057
    //        if (param != null && (param["__interfaces"] != null && param["__interfaces"].indexOf("io.swagger.models.parameters.SerializableParameter") >= 0 || param.constructor != null && param.constructor["__interfaces"] != null && param.constructor["__interfaces"].indexOf("io.swagger.models.parameters.SerializableParameter") >= 0)) {
2058

2059
    if (param && param instanceof SerializableParameter) {
985✔
2060
      const qp: any = param;
716✔
2061
      let property: any = null;
716✔
2062
      let collectionFormat: any = null;
716✔
2063
      const type = qp.getType();
716✔
2064
      if (null == type) {
716!
2065
        log.warn(`Type is NULL for Serializable Parameter: ${param}`);
×
2066
      }
2067
      if ('array' === type) {
716✔
2068
        let inner = qp.getItems();
62✔
2069
        if (inner == null) {
62!
2070
          log.warn(
×
2071
            `warning!  No inner type supplied for array parameter "${qp.getName()}", using String`,
2072
          );
2073
          inner = (new StringProperty() as any).description(
×
2074
            '//TODO automatically added by swagger-codegen',
2075
          );
2076
        }
2077
        property = new ArrayProperty().items(inner);
62✔
2078
        collectionFormat = qp.getCollectionFormat();
62✔
2079
        if (collectionFormat == null) {
62!
2080
          collectionFormat = 'csv';
×
2081
        }
2082
        const pr = this.fromProperty('inner', property);
62✔
2083
        p.baseType = pr.baseType;
62✔
2084
        p.isContainer = true;
62✔
2085
        p.isListContainer = true;
62✔
2086
        imports.add(pr.baseType);
62✔
2087
      } else if ('object' === type) {
654!
2088
        let inner = qp.getItems();
×
2089
        if (inner == null) {
×
2090
          log.warn(
×
2091
            `warning!  No inner type supplied for map parameter "${qp.getName()}", using String`,
2092
          );
2093
          inner = (new StringProperty() as any).description(
×
2094
            '//TODO automatically added by swagger-codegen',
2095
          );
2096
        }
2097
        property = new MapProperty(inner);
×
2098
        collectionFormat = qp.getCollectionFormat();
×
2099
        const pr = this.fromProperty('inner', inner);
×
2100
        p.baseType = pr.datatype;
×
2101
        p.isContainer = true;
×
2102
        p.isMapContainer = true;
×
2103
        imports.add(pr.baseType);
×
2104
      } else {
2105
        property = PropertyBuilder.build(
654✔
2106
          type,
2107
          qp.getFormat(),
2108
          newHashMap(['enum', qp.getEnum()]),
2109
        );
2110
      }
2111
      if (property == null) {
716!
2112
        log.warn(
×
2113
          `warning!  Property type "${type}" not found for parameter "${(
2114
            param as any
2115
          ).getName()}", using String`,
2116
        );
2117
        property = (new StringProperty() as any).description(
×
2118
          '//TODO automatically added by swagger-codegen.  Type was ' +
2119
            type +
2120
            ' but not supported',
2121
        );
2122
      }
2123
      property.setRequired((param as any).getRequired());
716✔
2124
      const cp = this.fromProperty(qp.getName(), property);
716✔
2125
      this.setParameterBooleanFlagWithCodegenProperty(p, cp);
716✔
2126
      p.dataType = cp.datatype;
716✔
2127
      p.dataFormat = cp.dataFormat;
716✔
2128
      if (cp.isEnum) {
716✔
2129
        p.datatypeWithEnum = cp.datatypeWithEnum;
27✔
2130
      }
2131
      this.updateCodegenPropertyEnum(cp);
716✔
2132
      p.isEnum = cp.isEnum;
716✔
2133
      p._enum = cp._enum;
716✔
2134
      p.allowableValues = cp.allowableValues;
716✔
2135
      if (cp.items != null && cp.items.isEnum) {
716✔
2136
        p.datatypeWithEnum = cp.datatypeWithEnum;
27✔
2137
        p.items = cp.items;
27✔
2138
      }
2139
      p.collectionFormat = collectionFormat;
716✔
2140
      if (collectionFormat != null && collectionFormat === 'multi') {
716✔
2141
        p.isCollectionFormatMulti = true;
55✔
2142
      }
2143
      p.paramName = this.toParamName(qp.getName());
716✔
2144
      if (cp.complexType != null) {
716✔
2145
        imports.add(cp.complexType);
6✔
2146
      }
2147
      p.maximum = qp.getMaximum();
716✔
2148
      p.exclusiveMaximum = qp.isExclusiveMaximum();
716✔
2149
      p.minimum = qp.getMinimum();
716✔
2150
      p.exclusiveMinimum = qp.isExclusiveMinimum();
716✔
2151
      p.maxLength = qp.getMaxLength();
716✔
2152
      p.minLength = qp.getMinLength();
716✔
2153
      p.pattern = this.toRegularExpression(qp.getPattern());
716✔
2154
      p.maxItems = qp.getMaxItems();
716✔
2155
      p.minItems = qp.getMinItems();
716✔
2156
      p.uniqueItems = qp.isUniqueItems();
716✔
2157
      p.multipleOf = qp.getMultipleOf();
716✔
2158
      if (
716!
2159
        p.maximum != null ||
1,425!
2160
        p.exclusiveMaximum != null ||
2161
        p.minimum != null ||
2162
        p.exclusiveMinimum != null ||
2163
        p.maxLength != null ||
2164
        p.minLength != null ||
2165
        p.maxItems != null ||
2166
        p.minItems != null ||
2167
        p.pattern != null
2168
      ) {
2169
        p.hasValidation = true;
716✔
2170
      }
2171
    } else {
2172
      if (!(param instanceof BodyParameter)) {
269!
2173
        log.error(`Cannot use Parameter ${param} as Body Parameter`);
×
2174
      }
2175
      const bp = param;
269✔
2176
      const model = bp.getSchema();
269✔
2177
      if (model != null && model instanceof ModelImpl) {
269✔
2178
        const impl = model;
41✔
2179
        const cm = this.fromModel(bp.getName(), impl);
41✔
2180
        if (cm.emptyVars != null && cm.emptyVars === false) {
41!
2181
          p.dataType = this.getTypeDeclaration(cm.classname);
×
2182
          imports.add(p.dataType);
×
2183
        } else {
2184
          const prop = PropertyBuilder.build(
41✔
2185
            impl.getType(),
2186
            impl.getFormat(),
2187
            null,
2188
          );
2189
          prop.setRequired(bp.getRequired());
41✔
2190
          const cp = this.fromProperty('property', prop);
41✔
2191
          if (cp != null) {
41!
2192
            p.baseType = cp.baseType;
41✔
2193
            p.dataType = cp.datatype;
41✔
2194
            p.isPrimitiveType = cp.isPrimitiveType;
41✔
2195
            p.isBinary = this.isDataTypeBinary(cp.datatype);
41✔
2196
          }
2197
          this.setParameterBooleanFlagWithCodegenProperty(p, cp);
41✔
2198
        }
2199
      } else if (model != null && model instanceof ArrayModel) {
228✔
2200
        const impl = model;
68✔
2201
        const ap: any = new ArrayProperty().items(impl.getItems());
68✔
2202
        ap.setRequired(param.getRequired());
68✔
2203
        const cp = this.fromProperty('inner', ap);
68✔
2204
        if (cp.complexType != null) {
68✔
2205
          imports.add(cp.complexType);
54✔
2206
        }
2207
        imports.add(cp.baseType);
68✔
2208
        p.dataType = cp.datatype;
68✔
2209
        p.baseType = cp.complexType || cp.baseType;
68✔
2210
        p.isPrimitiveType = cp.isPrimitiveType;
68✔
2211
        p.isContainer = true;
68✔
2212
        p.isListContainer = true;
68✔
2213
        this.setParameterBooleanFlagWithCodegenProperty(p, cp);
68✔
2214
      } else {
2215
        const sub = bp.getSchema();
160✔
2216
        if (sub != null && sub instanceof RefModel) {
160!
2217
          let name = sub.getSimpleRef();
160✔
2218
          if (this.__typeMapping.containsKey(name)) {
160!
2219
            name = this.__typeMapping.get(name);
×
2220
          } else {
2221
            name = this.toModelName(name);
160✔
2222
            if (this.__defaultIncludes.contains(name)) {
160!
2223
              imports.add(name);
×
2224
            }
2225
            imports.add(name);
160✔
2226
            name = this.getTypeDeclaration(name);
160✔
2227
          }
2228
          p.dataType = name;
160✔
2229
          p.baseType = name;
160✔
2230
        }
2231
      }
2232
      p.paramName = this.toParamName(bp.getName());
269✔
2233
    }
2234
    if (p.vendorExtensions && p.vendorExtensions.containsKey('x-example')) {
985!
2235
      p.example = p.vendorExtensions.get('x-example') + '';
×
2236
    } else if (p.isString) {
985✔
2237
      p.example = p.paramName + '_example';
456✔
2238
    } else if (p.isBoolean) {
529!
2239
      p.example = 'true';
×
2240
    } else if (p.isLong) {
529✔
2241
      p.example = '789';
122✔
2242
    } else if (p.isInteger) {
407✔
2243
      p.example = '56';
37✔
2244
    } else if (p.isFloat) {
370!
2245
      p.example = '3.4';
×
2246
    } else if (p.isDouble) {
370✔
2247
      p.example = '1.2';
80✔
2248
    } else if (p.isBinary) {
290!
2249
      p.example = 'BINARY_DATA_HERE';
×
2250
    } else if (p.isByteArray) {
290!
2251
      p.example = 'B';
×
2252
    } else if (p.isDate) {
290!
2253
      p.example = '2013-10-20';
×
2254
    } else if (p.isDateTime) {
290!
2255
      p.example = '2013-10-20T19:20:30+01:00';
×
2256
    } else if (
290!
2257
      param != null &&
580!
2258
      param instanceof FormParameter &&
2259
      (((o1, o2) => o1.toUpperCase() === (o2 === null ? o2 : o2.toUpperCase()))(
×
2260
        'file',
2261
        (param as any).getType(),
2262
      ) ||
2263
        'file' === p.baseType)
2264
    ) {
2265
      p.isFile = true;
×
2266
      p.example = '/path/to/file.txt';
×
2267
    }
2268
    this.setParameterExampleValue(p);
985✔
2269
    if (param != null && param instanceof QueryParameter) {
985✔
2270
      p.isQueryParam = true;
246✔
2271
    } else if (param != null && param instanceof PathParameter) {
739✔
2272
      p.required = true;
338✔
2273
      p.isPathParam = true;
338✔
2274
    } else if (param != null && param instanceof HeaderParameter) {
401✔
2275
      p.isHeaderParam = true;
24✔
2276
    } else if (param != null && param instanceof CookieParameter) {
377!
2277
      p.isCookieParam = true;
×
2278
    } else if (param != null && param instanceof BodyParameter) {
377✔
2279
      p.isBodyParam = true;
269✔
2280
      p.isBinary = this.isDataTypeBinary(p.dataType);
269✔
2281
    } else if (param != null && param instanceof FormParameter) {
108!
2282
      if (
108✔
2283
        ((o1, o2) =>
2284
          o1.toUpperCase() === (o2 === null ? o2 : o2.toUpperCase()))(
108!
2285
          'file',
2286
          (param as any).getType(),
2287
        )
2288
      ) {
2289
        p.isFile = true;
27✔
2290
      } else if ('file' === p.baseType) {
81!
2291
        p.isFile = true;
×
2292
      } else {
2293
        p.notFile = true;
81✔
2294
      }
2295
      p.isFormParam = true;
108✔
2296
    }
2297
    this.postProcessParameter(p);
985✔
2298
    return p;
985✔
2299
  }
2300

2301
  public isDataTypeBinary(dataType) {
2302
    return dataType && dataType.toLowerCase().startsWith('byte');
572✔
2303
  }
2304

2305
  /**
2306
   * Convert map of Swagger SecuritySchemeDefinition objects to a list of Codegen Security objects
2307
   *
2308
   * @param schemes a map of Swagger SecuritySchemeDefinition object
2309
   * @return a list of Codegen Security objects
2310
   */
2311
  public fromSecurity(schemes) {
2312
    if (schemes == null) {
447!
2313
      return Collections.emptyList();
×
2314
    }
2315
    const secs: any[] = [];
447✔
2316
    let sec;
2317
    for (const [name, schemeDefinition] of schemes) {
447✔
2318
      sec = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
414✔
2319
      sec.name = name;
414✔
2320
      sec.type = schemeDefinition.getType();
414✔
2321
      sec.isCode = sec.isPassword = sec.isApplication = sec.isImplicit = false;
414✔
2322
      if (
414✔
2323
        schemeDefinition != null &&
828✔
2324
        schemeDefinition instanceof ApiKeyAuthDefinition
2325
      ) {
2326
        const apiKeyDefinition = schemeDefinition;
151✔
2327
        sec.isBasic = sec.isOAuth = false;
151✔
2328
        sec.isApiKey = true;
151✔
2329
        sec.keyParamName = apiKeyDefinition.getName();
151✔
2330
        sec.isKeyInHeader = apiKeyDefinition.getIn() === In.HEADER;
151✔
2331
        sec.isKeyInQuery = !sec.isKeyInHeader;
151✔
2332
      } else if (
263!
2333
        schemeDefinition != null &&
526✔
2334
        schemeDefinition instanceof BasicAuthDefinition
2335
      ) {
2336
        sec.isKeyInHeader =
×
2337
          sec.isKeyInQuery =
2338
          sec.isApiKey =
2339
          sec.isOAuth =
2340
            false;
2341
        sec.isBasic = true;
×
2342
      } else {
2343
        const oauth2Definition = schemeDefinition;
263✔
2344
        sec.isKeyInHeader =
263✔
2345
          sec.isKeyInQuery =
2346
          sec.isApiKey =
2347
          sec.isBasic =
2348
            false;
2349
        sec.isOAuth = true;
263✔
2350
        sec.flow = oauth2Definition.getFlow();
263✔
2351
        switch (sec.flow) {
263✔
2352
          case 'accessCode':
263!
2353
            sec.isCode = true;
×
2354
            break;
×
2355
          case 'password':
2356
            sec.isPassword = true;
×
2357
            break;
×
2358
          case 'application':
2359
            sec.isApplication = true;
×
2360
            break;
×
2361
          case 'implicit':
2362
            sec.isImplicit = true;
263✔
2363
            break;
263✔
2364
          default:
2365
            throw new Error('unknown oauth flow: ' + sec.flow);
×
2366
        }
2367
        sec.authorizationUrl = oauth2Definition.getAuthorizationUrl();
263✔
2368
        sec.tokenUrl = oauth2Definition.getTokenUrl();
263✔
2369
        if (oauth2Definition.getScopes() != null) {
263!
2370
          const scopes: any[] = [];
263✔
2371
          let count = 0;
263✔
2372
          const numScopes = oauth2Definition.getScopes().size;
263✔
2373
          for (const [n, description] of asMap(oauth2Definition.getScopes())) {
263✔
2374
            const scope = newHashMap(
526✔
2375
              ['scope', n],
2376
              ['description', description],
2377
            );
2378
            count += 1;
526✔
2379
            if (count < numScopes) {
526✔
2380
              scope.put('hasMore', 'true');
263✔
2381
            } else {
2382
              scope.put('hasMore', null);
263✔
2383
            }
2384
            scopes.push(scope);
526✔
2385
          }
2386
          sec.scopes = scopes;
263✔
2387
        }
2388
      }
2389
      secs.push(sec);
414✔
2390
    }
2391
    if (sec) {
447✔
2392
      sec.hasMore = false;
367✔
2393
    }
2394
    return secs;
447✔
2395
  }
2396

2397
  public setReservedWordsLowerCase(words) {
2398
    this.__reservedWords = newHashSet();
610✔
2399
    for (const word of words) {
610✔
2400
      this.__reservedWords.add(word.toLowerCase());
44,774✔
2401
    }
2402
  }
2403

2404
  public isReservedWord(word) {
2405
    return word != null && this.__reservedWords.contains(word.toLowerCase());
19,935✔
2406
  }
2407

2408
  /**
2409
   * Get operationId from the operation object, and if it's blank, generate a new one from the given parameters.
2410
   *
2411
   * @param operation the operation object
2412
   * @param p the path of the operation
2413
   * @param httpMethod the HTTP method of the operation
2414
   * @return the (generated) operationId
2415
   */
2416
  public getOrGenerateOperationId(operation, p, httpMethod) {
2417
    let operationId = operation.getOperationId();
816✔
2418
    if (StringUtils.isBlank(operationId)) {
816✔
2419
      let tmpPath = p;
50✔
2420
      tmpPath = tmpPath.replace(new RegExp('\\{', 'g'), '');
50✔
2421
      tmpPath = tmpPath.replace(new RegExp('\\}', 'g'), '');
50✔
2422
      const parts = (tmpPath + '/' + httpMethod).split('/');
50✔
2423
      const builder = StringBuilder();
50✔
2424
      if ('/' === tmpPath) {
50!
2425
        builder.append('root');
×
2426
      }
2427
      for (let part of parts) {
50✔
2428
        if (part.length > 0) {
170✔
2429
          if (builder.length() === 0) {
120✔
2430
            part = StringUtils.lowerFirst(part);
50✔
2431
          } else {
2432
            part = this.initialCaps(part);
70✔
2433
          }
2434
          builder.append(part);
120✔
2435
        }
2436
      }
2437
      operationId = this.sanitizeName(builder.toString());
50✔
2438
      log.warn(
50✔
2439
        `Empty operationId found for path: ${httpMethod} ${p}.
2440
Renamed to auto-generated operationId: ${operationId}`,
2441
      );
2442
    }
2443
    return operationId;
816✔
2444
  }
2445

2446
  /**
2447
   * Check the type to see if it needs import the library/module/package
2448
   *
2449
   * @param type name of the type
2450
   * @return true if the library/module/package of the corresponding type needs to be imported
2451
   */
2452
  public needToImport(type) {
2453
    return (
2,310✔
2454
      !this.__defaultIncludes.contains(type) &&
3,723✔
2455
      !this.__languageSpecificPrimitives.contains(type)
2456
    );
2457
  }
2458

2459
  public toExamples(examples) {
2460
    if (examples == null) {
1,236✔
2461
      return null;
1,188✔
2462
    }
2463
    const output: any[] = [];
48✔
2464
    for (const [contentType, example] of asMap(examples)) {
48✔
2465
      output.push(
48✔
2466
        newHashMap(['contentType', contentType], ['example', example]),
2467
      );
2468
    }
2469
    return output;
48✔
2470
  }
2471

2472
  public addHeaders(response, target) {
2473
    if (response.getHeaders() != null) {
1,786✔
2474
      for (const [key, value] of response.getHeaders()) {
14✔
2475
        target.push(this.fromProperty(key, factory(value)));
28✔
2476
      }
2477
    }
2478
  }
2479

2480
  /**
2481
   * Add operation to group
2482
   *
2483
   * @param tag name of the tag
2484
   * @param resourcePath path of the resource
2485
   * @param operation Swagger Operation object
2486
   * @param co Codegen Operation object
2487
   * @param operations map of Codegen operations
2488
   */
2489
  public addOperationToGroup(tag, resourcePath, operation, co, operations) {
2490
    let opList = operations.get(tag);
816✔
2491
    if (opList == null) {
816✔
2492
      opList = [];
173✔
2493
      operations.put(tag, opList);
173✔
2494
    }
2495
    let uniqueName = co.operationId;
816✔
2496
    let counter = 0;
816✔
2497
    for (const op of opList) {
816✔
2498
      if (uniqueName === op.operationId) {
2,200!
2499
        uniqueName = co.operationId + '_' + counter;
×
2500
        counter++;
×
2501
      }
2502
    }
2503
    if (!(co.operationId === uniqueName)) {
816!
2504
      log.warn(`generated unique operationId ${uniqueName}`);
×
2505
    }
2506
    co.operationId = uniqueName;
816✔
2507
    co.operationIdLowerCase = uniqueName.toLowerCase();
816✔
2508
    opList.push(co);
816✔
2509
    co.baseName = tag;
816✔
2510
  }
2511

2512
  public addParentContainer(m, name, property) {
2513
    const tmp = this.fromProperty(name, property);
×
2514
    this.addImport(m, tmp.complexType);
×
2515
    m.parent = this.toInstantiationType(property);
×
2516
    const containerType = tmp.containerType;
×
2517
    const instantiationType = this.__instantiationTypes.get(containerType);
×
2518
    if (instantiationType != null) {
×
2519
      this.addImport(m, instantiationType);
×
2520
    }
2521
    const mappedType = this.__typeMapping.get(containerType);
×
2522
    if (mappedType != null) {
×
2523
      this.addImport(m, mappedType);
×
2524
    }
2525
  }
2526

2527
  /**
2528
   * Dashize the given word.
2529
   *
2530
   * @param word The word
2531
   * @return The dashized version of the word, e.g. "my-name"
2532
   */
2533
  public dashize(word) {
2534
    return DefaultCodegen.underscore(word).replace(
46✔
2535
      new RegExp('[_ ]', 'g'),
2536
      '-',
2537
    );
2538
  }
2539

2540
  public addImport(m, type) {
2541
    if (type != null && this.needToImport(type)) {
5,914✔
2542
      m.imports.add(type);
660✔
2543
    }
2544
  }
2545

2546
  public addVars(
2547
    m,
2548
    properties,
2549
    required,
2550
    allProperties?: any,
2551
    allRequired?: any,
2552
  ) {
2553
    if (arguments.length > 4) {
1,098✔
2554
      m.hasRequired = false;
563✔
2555
      if (properties != null && !properties.isEmpty()) {
563✔
2556
        m.hasVars = true;
522✔
2557
        m.hasEnums = false;
522✔
2558
        const mandatory =
2559
          required == null
522✔
2560
            ? Collections.emptySet()
522✔
2561
            : new Set(required.concat().sort());
2562
        this._addVars(m, m.vars, properties, mandatory);
522✔
2563
        m.allMandatory = m.mandatory = mandatory;
522✔
2564
      } else {
2565
        m.emptyVars = true;
41✔
2566
        m.hasVars = false;
41✔
2567
        m.hasEnums = false;
41✔
2568
      }
2569
      if (allProperties != null) {
563✔
2570
        const allMandatory =
2571
          allRequired == null
12✔
2572
            ? Collections.emptySet()
12!
2573
            : new Set(allRequired.concat().sort());
2574
        this._addVars(m, m.allVars, allProperties, allMandatory);
12✔
2575
        m.allMandatory = allMandatory;
12✔
2576
      }
2577
    } else if (arguments.length > 3) {
535!
2578
      return this._addVars(m, properties, required, allProperties);
×
2579
    } else {
2580
      return this.addVars(m, properties, required, null, null);
535✔
2581
    }
2582
  }
2583

2584
  public _addVars(m, vars, properties, mandatory) {
2585
    const propertyList = properties.entrySet().toArray();
534✔
2586
    const totalCount = propertyList.length;
534✔
2587
    for (let i = 0; i < totalCount; i++) {
534✔
2588
      const entry = propertyList[i];
2,707✔
2589
      const key = entry.getKey();
2,707✔
2590
      const prop = entry.getValue();
2,707✔
2591
      if (prop == null) {
2,707!
2592
        log.warn(`null property for ${key}`);
×
2593
        continue;
×
2594
      }
2595

2596
      const cp = this.fromProperty(key, prop);
2,707✔
2597
      if (mandatory.has) {
2,707✔
2598
        cp.required = mandatory.has(key) ? true : null;
1,129✔
2599
      } else {
2600
        cp.required = mandatory.hasOwnProperty(key) ? true : null;
1,578!
2601
      }
2602

2603
      m.hasRequired = m.hasRequired || cp.required;
2,707✔
2604
      if (cp.isEnum) {
2,707✔
2605
        m.hasEnums = true;
189✔
2606
      }
2607
      if (!cp.isReadOnly) {
2,707!
2608
        m.hasOnlyReadOnly = false;
2,707✔
2609
      }
2610
      if (i + 1 !== totalCount) {
2,707✔
2611
        cp.hasMore = true;
2,173✔
2612
        if (!propertyList[i + 1].getValue().getReadOnly()) {
2,173!
2613
          cp.hasMoreNonReadOnly = true;
2,173✔
2614
        }
2615
      }
2616
      if (cp.isContainer != null) {
2,707✔
2617
        this.addImport(m, this.__typeMapping.get('array'));
236✔
2618
      }
2619
      this.addImport(m, cp.baseType);
2,707✔
2620
      let innerCp = cp;
2,707✔
2621
      while (innerCp != null) {
2,707✔
2622
        this.addImport(m, innerCp.complexType);
2,943✔
2623
        innerCp = innerCp.items;
2,943✔
2624
      }
2625

2626
      vars.push(cp);
2,707✔
2627
      if (cp.required) {
2,707✔
2628
        m.requiredVars.push(cp);
415✔
2629
      } else {
2630
        m.optionalVars.push(cp);
2,292✔
2631
      }
2632
      if (cp.isReadOnly) {
2,707!
2633
        m.readOnlyVars.push(cp);
×
2634
      } else {
2635
        m.readWriteVars.push(cp);
2,707✔
2636
      }
2637
    }
2638
  }
2639

2640
  /**
2641
   * Remove characters that is not good to be included in method name from the input and camelize it
2642
   *
2643
   * @param name string to be camelize
2644
   * @param nonNameElementPattern a regex pattern of the characters that is not good to be included in name
2645
   * @return camelized string
2646
   */
2647
  public removeNonNameElementToCamelCase(
2648
    name,
2649
    nonNameElementPattern = '[-_:;#]',
816✔
2650
  ) {
2651
    let result = StringUtils.join(
816✔
2652
      Lists.transform(
2653
        Lists.newArrayList(name.split(nonNameElementPattern)),
2654
        (input) => StringUtils.capitalize(input),
816✔
2655
      ),
2656
      '',
2657
    );
2658
    if (result.length > 0) {
816!
2659
      result = StringUtils.lowerFirst(result);
816✔
2660
    }
2661
    return result;
816✔
2662
  }
2663

2664
  public apiFilename(templateName, tag) {
2665
    const suffix = this.apiTemplateFiles().get(templateName);
95✔
2666
    return this.apiFileFolder() + path.sep + this.toApiFilename(tag) + suffix;
95✔
2667
  }
2668

2669
  public apiDataFilename(templateName, tag) {
2670
    const suffix = this.apiDataTemplateFile().get(templateName);
54✔
2671
    return this.apiFileFolder() + path.sep + this.toModelName(tag) + suffix;
54✔
2672
  }
2673

2674
  /**
2675
   * Return the full path and API documentation file
2676
   *
2677
   * @param templateName template name
2678
   * @param tag tag
2679
   *
2680
   * @return the API documentation file name with full path
2681
   */
2682
  public apiDocFilename(templateName, tag) {
2683
    const suffix = this.apiDocTemplateFiles().get(templateName);
75✔
2684
    return this.apiDocFileFolder() + this.toApiDocFilename(tag) + suffix;
75✔
2685
  }
2686

2687
  /**
2688
   * Return the full path and API test file
2689
   *
2690
   * @param templateName template name
2691
   * @param tag tag
2692
   *
2693
   * @return the API test file name with full path
2694
   */
2695
  public apiTestFilename(templateName, tag) {
2696
    const suffix = this.apiTestTemplateFiles().get(templateName);
73✔
2697
    return (
73✔
2698
      this.apiTestFileFolder() + path.sep + this.toApiTestFilename(tag) + suffix
2699
    );
2700
  }
2701

2702
  public shouldOverwrite(filename) {
2703
    return !(this.skipOverwrite && new File(filename).exists());
1,352!
2704
  }
2705

2706
  public isSkipOverwrite() {
2707
    return this.skipOverwrite;
×
2708
  }
2709

2710
  public setSkipOverwrite(skipOverwrite) {
2711
    this.skipOverwrite = skipOverwrite;
230✔
2712
  }
2713

2714
  /**
2715
   * All library templates supported.
2716
   * (key: library name, value: library description)
2717
   * @return the supported libraries
2718
   */
2719
  public supportedLibraries() {
2720
    return this.__supportedLibraries;
×
2721
  }
2722

2723
  /**
2724
   * Set library template (sub-template).
2725
   *
2726
   * @param library Library template
2727
   */
2728
  public setLibrary(library) {
2729
    if (library != null && !this.__supportedLibraries.containsKey(library)) {
36!
2730
      throw new Error('unknown library: ' + library);
×
2731
    }
2732
    this.library = library;
36✔
2733
  }
2734

2735
  /**
2736
   * Library template (sub-template).
2737
   *
2738
   * @return Library template
2739
   */
2740
  public getLibrary() {
2741
    return this.library;
2,476✔
2742
  }
2743

2744
  /**
2745
   * Set Git user ID.
2746
   *
2747
   * @param gitUserId Git user ID
2748
   */
2749
  public setGitUserId(gitUserId) {
2750
    this.gitUserId = gitUserId;
115✔
2751
  }
2752

2753
  /**
2754
   * Git user ID
2755
   *
2756
   * @return Git user ID
2757
   */
2758
  public getGitUserId() {
2759
    return this.gitUserId;
×
2760
  }
2761

2762
  /**
2763
   * Set Git repo ID.
2764
   *
2765
   * @param gitRepoId Git repo ID
2766
   */
2767
  public setGitRepoId(gitRepoId) {
2768
    this.gitRepoId = gitRepoId;
115✔
2769
  }
2770

2771
  /**
2772
   * Git repo ID
2773
   *
2774
   * @return Git repo ID
2775
   */
2776
  public getGitRepoId() {
2777
    return this.gitRepoId;
×
2778
  }
2779

2780
  /**
2781
   * Set release note.
2782
   *
2783
   * @param releaseNote Release note
2784
   */
2785
  public setReleaseNote(releaseNote) {
2786
    this.releaseNote = releaseNote;
115✔
2787
  }
2788

2789
  /**
2790
   * Release note
2791
   *
2792
   * @return Release note
2793
   */
2794
  public getReleaseNote() {
2795
    return this.releaseNote;
×
2796
  }
2797

2798
  /**
2799
   * Set HTTP user agent.
2800
   *
2801
   * @param httpUserAgent HTTP user agent
2802
   */
2803
  public setHttpUserAgent(httpUserAgent) {
2804
    this.httpUserAgent = httpUserAgent;
1✔
2805
  }
2806

2807
  /**
2808
   * HTTP user agent
2809
   *
2810
   * @return HTTP user agent
2811
   */
2812
  public getHttpUserAgent() {
2813
    return this.httpUserAgent;
×
2814
  }
2815

2816
  public buildLibraryCliOption(supportedLibraries) {
2817
    const sb = StringBuilder('library template (sub-template) to use:');
×
2818
    for (const [key, lib] of supportedLibraries) {
×
2819
      sb.append('\n').append(key).append(' - ').append(lib);
×
2820
    }
2821
    return new CliOption('library', sb.toString());
×
2822
  }
2823

2824
  /**
2825
   * Sanitize name (parameter, property, method, etc)
2826
   *
2827
   * @param name string to be sanitize
2828
   * @return sanitized string
2829
   */
2830
  public sanitizeName(name) {
2831
    if (name == null) {
27,137!
2832
      log.error('String to be sanitized is null. Default to ERROR_UNKNOWN');
×
2833
      return 'ERROR_UNKNOWN';
×
2834
    }
2835
    if ('$' === name) {
27,137!
2836
      return 'value';
×
2837
    }
2838
    name = name.replace(new RegExp('\\[\\]', 'g'), '');
27,137✔
2839
    name = name.replace(new RegExp('\\[', 'g'), '_');
27,137✔
2840
    name = name.replace(new RegExp('\\]', 'g'), '');
27,137✔
2841
    name = name.replace(new RegExp('\\(', 'g'), '_');
27,137✔
2842
    name = name.replace(new RegExp('\\)', 'g'), '');
27,137✔
2843
    name = name.replace(new RegExp('\\.', 'g'), '_');
27,137✔
2844
    name = name.replace(new RegExp('-', 'g'), '_');
27,137✔
2845
    name = name.replace(new RegExp(' ', 'g'), '_');
27,137✔
2846
    return name.replace(new RegExp('[^a-zA-Z0-9_]', 'g'), '');
27,137✔
2847
  }
2848

2849
  /**
2850
   * Sanitize tag
2851
   *
2852
   * @param tag Tag
2853
   * @return Sanitized tag
2854
   */
2855
  public sanitizeTag(tag) {
2856
    const parts = tag.split(' ');
1,632✔
2857
    const buf = StringBuilder();
1,632✔
2858
    for (const part of parts) {
1,632✔
2859
      {
2860
        if (StringUtils.isNotEmpty(part)) {
1,632!
2861
          buf.append(StringUtils.capitalize(part));
1,632✔
2862
        }
2863
      }
2864
    }
2865
    return buf.toString().replace(new RegExp('[^a-zA-Z ]', 'g'), '');
1,632✔
2866
  }
2867

2868
  /**
2869
   * Only write if the file doesn't exist
2870
   *
2871
   * @param outputFolder Output folder
2872
   * @param supportingFile Supporting file
2873
   */
2874
  public writeOptional(outputFolder, supportingFile) {
2875
    let folder = '';
×
2876
    if (outputFolder != null && !('' === outputFolder)) {
×
2877
      folder += outputFolder + File.separator;
×
2878
    }
2879
    folder += supportingFile.folder;
×
2880
    if (!('' === folder)) {
×
2881
      folder += File.separator + supportingFile.destinationFilename;
×
2882
    } else {
2883
      folder = supportingFile.destinationFilename;
×
2884
    }
2885
    if (!new File(folder).exists()) {
×
2886
      this.__supportingFiles.push(supportingFile);
×
2887
    } else {
2888
      log.info(
×
2889
        `Skipped overwriting ${supportingFile.destinationFilename} as the file already exists in folder`,
2890
      );
2891
    }
2892
  }
2893

2894
  /**
2895
   * Set CodegenParameter boolean flag using CodegenProperty.
2896
   *
2897
   * @param parameter Codegen Parameter
2898
   * @param property  Codegen property
2899
   */
2900
  public setParameterBooleanFlagWithCodegenProperty(parameter, property) {
2901
    if (parameter == null) {
825!
2902
      log.error('Codegen Parameter cannnot be null.');
×
2903
      return;
×
2904
    }
2905
    if (property == null) {
825!
2906
      log.error('Codegen Property cannot be null.');
×
2907
      return;
×
2908
    }
2909
    if (property.isString) {
825✔
2910
      parameter.isString = true;
456✔
2911
      parameter.isPrimitiveType = true;
456✔
2912
    } else if (property.isBoolean) {
369!
2913
      parameter.isBoolean = true;
×
2914
      parameter.isPrimitiveType = true;
×
2915
    } else if (property.isLong) {
369✔
2916
      parameter.isLong = true;
122✔
2917
      parameter.isPrimitiveType = true;
122✔
2918
    } else if (property.isInteger) {
247✔
2919
      parameter.isInteger = true;
37✔
2920
      parameter.isPrimitiveType = true;
37✔
2921
    } else if (property.isDouble) {
210✔
2922
      parameter.isDouble = true;
80✔
2923
      parameter.isPrimitiveType = true;
80✔
2924
    } else if (property.isFloat) {
130!
2925
      parameter.isFloat = true;
×
2926
      parameter.isPrimitiveType = true;
×
2927
    } else if (property.isByteArray) {
130!
2928
      parameter.isByteArray = true;
×
2929
      parameter.isPrimitiveType = true;
×
2930
    } else if (property.isBinary) {
130!
2931
      parameter.isByteArray = true;
×
2932
      parameter.isPrimitiveType = true;
×
2933
    } else if (property.isDate) {
130!
2934
      parameter.isDate = true;
×
2935
      parameter.isPrimitiveType = true;
×
2936
    } else if (property.isDateTime) {
130!
2937
      parameter.isDateTime = true;
×
2938
      parameter.isPrimitiveType = true;
×
2939
    } else if (property.isObject) {
130!
2940
      parameter.isObject = true;
×
2941
      parameter.isPrimitiveType = true;
×
2942
    } else {
2943
      log.debug('Property type is not primitive: ' + property.datatype);
130✔
2944
    }
2945

2946
    if (property.isListContainer && property.items) {
825✔
2947
      if (property.items.isString) {
130✔
2948
        parameter.isItemString = true;
63✔
2949
      } else if (property.items.isBoolean) {
67!
2950
        parameter.isItemBoolean = true;
×
2951
      } else if (property.items.isLong) {
67!
2952
        parameter.isItemLong = true;
×
2953
      } else if (property.items.isInteger) {
67✔
2954
        parameter.isItemInteger = true;
13✔
2955
      } else if (property.items.isDouble) {
54!
2956
        parameter.isItemDouble = true;
×
2957
      } else if (property.items.isFloat) {
54!
2958
        parameter.isItemFloat = true;
×
2959
      } else if (property.items.isByteArray) {
54!
2960
        parameter.isItemByteArray = true;
×
2961
      } else if (property.items.isBinary) {
54!
2962
        parameter.isItemByteArray = true;
×
2963
      } else if (property.items.isDate) {
54!
2964
        parameter.isItemDate = true;
×
2965
      } else if (property.items.isDateTime) {
54!
2966
        parameter.isItemDateTime = true;
×
2967
      } else {
2968
        log.debug(`Property item type is not primitive: ${property.datatype}`);
54✔
2969
      }
2970
    }
2971
  }
2972

2973
  /**
2974
   * Update codegen property's enum by adding "enumVars" (with name and value)
2975
   *
2976
   * @param var list of CodegenProperty
2977
   */
2978
  public updateCodegenPropertyEnum(__var) {
2979
    let allowableValues = __var.allowableValues;
1,460✔
2980
    if (__var.items != null) {
1,460✔
2981
      allowableValues = __var.items.allowableValues;
106✔
2982
    }
2983
    if (allowableValues == null) {
1,460✔
2984
      return;
1,395✔
2985
    }
2986
    const values = allowableValues.get('values');
65✔
2987
    if (values == null) {
65!
2988
      return;
×
2989
    }
2990
    const enumVars: any[] = [];
65✔
2991
    const commonPrefix = this.findCommonPrefixOfVars(values);
65✔
2992
    const truncateIdx = commonPrefix.length;
65✔
2993
    for (const value of values) {
65✔
2994
      const enumVar = newHashMap();
195✔
2995
      let enumName;
2996
      if (truncateIdx === 0) {
195!
2997
        enumName = value.toString();
195✔
2998
      } else {
2999
        enumName = value.toString().substring(truncateIdx);
×
3000
        if ('' === enumName) {
×
3001
          enumName = value.toString();
×
3002
        }
3003
      }
3004
      enumVar.put('name', this.toEnumVarName(enumName, __var.datatype));
195✔
3005
      enumVar.put('value', this.toEnumValue(value.toString(), __var.datatype));
195✔
3006
      enumVars.push(enumVar);
195✔
3007
    }
3008
    allowableValues.put('enumVars', enumVars);
65✔
3009
    if (__var.defaultValue != null) {
65✔
3010
      let enumName = null;
8✔
3011
      for (const enumVar of enumVars) {
8✔
3012
        if (
24!
3013
          this.toEnumValue(__var.defaultValue, __var.datatype) ===
3014
          enumVar.get('value')
3015
        ) {
3016
          enumName = enumVar.get('name');
×
3017
          break;
×
3018
        }
3019
      }
3020
      if (enumName != null) {
8!
3021
        __var.defaultValue = this.toEnumDefaultValue(
×
3022
          enumName,
3023
          __var.datatypeWithEnum,
3024
        );
3025
      }
3026
    }
3027
  }
3028
}
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