@accordproject/concerto-core 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Concerto v3.1.0
2
+ * Concerto v3.2.0
3
3
  * Licensed under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License.
5
5
  * You may obtain a copy of the License at
@@ -239,7 +239,12 @@ class ClassDeclaration extends Decorated {
239
239
  }), this.modelFile, this.ast.location);
240
240
  } else {
241
241
  // check that identifiers are strings
242
- if (idField.getType() !== 'String') {
242
+ const isPrimitiveString = idField.getType() === 'String';
243
+ const modelFile = idField.getParent().getModelFile();
244
+ const declaration = modelFile.getType(idField.getType());
245
+ const isScalarString = declaration !== null && declaration.isScalarDeclaration?.() && declaration.getType?.() === 'String';
246
+
247
+ if (!isPrimitiveString && !isScalarString) {
243
248
  let formatter = Globalize('en').messageFormatter('classdeclaration-validate-identifiernotstring');
244
249
  throw new IllegalModelException(formatter({
245
250
  'class': this.name,
@@ -14,6 +14,8 @@
14
14
 
15
15
  'use strict';
16
16
 
17
+ const { MetaModelNamespace } = require('@accordproject/concerto-metamodel');
18
+
17
19
  const Property = require('./property');
18
20
  const NumberValidator = require('./numbervalidator');
19
21
  const StringValidator = require('./stringvalidator');
@@ -46,6 +48,7 @@ class Field extends Property {
46
48
  */
47
49
  constructor(parent, ast) {
48
50
  super(parent, ast);
51
+ this.scalarField = null; // cache scalar field
49
52
  }
50
53
 
51
54
  /**
@@ -58,22 +61,28 @@ class Field extends Property {
58
61
 
59
62
  this.validator = null;
60
63
 
61
- switch(this.getType()) {
64
+ switch (this.getType()) {
62
65
  case 'Integer':
63
66
  case 'Double':
64
67
  case 'Long':
65
- if(this.ast.validator) {
66
- this.validator = new NumberValidator(this, this.ast.validator);
68
+ if (this.ast.validator) {
69
+ this.validator = new NumberValidator(
70
+ this,
71
+ this.ast.validator
72
+ );
67
73
  }
68
74
  break;
69
75
  case 'String':
70
- if(this.ast.validator) {
71
- this.validator = new StringValidator(this, this.ast.validator);
76
+ if (this.ast.validator) {
77
+ this.validator = new StringValidator(
78
+ this,
79
+ this.ast.validator
80
+ );
72
81
  }
73
82
  break;
74
83
  }
75
84
 
76
- if(this.ast.defaultValue) {
85
+ if (this.ast.defaultValue) {
77
86
  this.defaultValue = this.ast.defaultValue;
78
87
  } else {
79
88
  this.defaultValue = null;
@@ -93,10 +102,9 @@ class Field extends Property {
93
102
  * @return {string | number} the default value for the field or null
94
103
  */
95
104
  getDefaultValue() {
96
- if(this.defaultValue) {
105
+ if (this.defaultValue) {
97
106
  return this.defaultValue;
98
- }
99
- else {
107
+ } else {
100
108
  return null;
101
109
  }
102
110
  }
@@ -106,7 +114,17 @@ class Field extends Property {
106
114
  * @return {String} the string version of the property.
107
115
  */
108
116
  toString() {
109
- return 'Field {name=' + this.name + ', type=' + this.getFullyQualifiedTypeName() + ', array=' + this.array + ', optional=' + this.optional +'}';
117
+ return (
118
+ 'Field {name=' +
119
+ this.name +
120
+ ', type=' +
121
+ this.getFullyQualifiedTypeName() +
122
+ ', array=' +
123
+ this.array +
124
+ ', optional=' +
125
+ this.optional +
126
+ '}'
127
+ );
110
128
  }
111
129
 
112
130
  /**
@@ -117,6 +135,69 @@ class Field extends Property {
117
135
  isField() {
118
136
  return true;
119
137
  }
138
+
139
+ /**
140
+ * Returns true if the field's type is a scalar
141
+ * @returns {boolean} true if the field is a scalar type
142
+ */
143
+ isTypeScalar() {
144
+ if (this.isPrimitive()) {
145
+ return false;
146
+ } else {
147
+ const type = this.getParent()
148
+ .getModelFile()
149
+ .getType(this.getType());
150
+ return type.isScalarDeclaration?.();
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Unboxes a field that references a scalar type to an
156
+ * underlying Field definition.
157
+ * @throws {Error} throws an error if this field is not a scalar type.
158
+ * @returns {Field} the primitive field for this scalar
159
+ */
160
+ getScalarField() {
161
+ if(this.scalarField) {
162
+ return this.scalarField;
163
+ }
164
+ if (!this.isTypeScalar()) {
165
+ throw new Error(`Field ${this.name} is not a scalar property.`);
166
+ }
167
+ const type = this.getParent().getModelFile().getType(this.getType());
168
+ const fieldAst = JSON.parse(JSON.stringify(type.ast));
169
+
170
+ switch (type.ast.$class) {
171
+ case `${MetaModelNamespace}.StringScalar`:
172
+ fieldAst.$class = `${MetaModelNamespace}.StringProperty`;
173
+ break;
174
+ case `${MetaModelNamespace}.BooleanScalar`:
175
+ fieldAst.$class = `${MetaModelNamespace}.BooleanProperty`;
176
+ break;
177
+
178
+ case `${MetaModelNamespace}.DateTimeScalar`:
179
+ fieldAst.$class = `${MetaModelNamespace}.DateTimeProperty`;
180
+ break;
181
+
182
+ case `${MetaModelNamespace}.DoubleScalar`:
183
+ fieldAst.$class = `${MetaModelNamespace}.DoubleProperty`;
184
+ break;
185
+
186
+ case `${MetaModelNamespace}.IntegerScalar`:
187
+ fieldAst.$class = `${MetaModelNamespace}.IntegerProperty`;
188
+ break;
189
+
190
+ case `${MetaModelNamespace}.LongScalar`:
191
+ fieldAst.$class = `${MetaModelNamespace}.LongProperty`;
192
+ break;
193
+ default:
194
+ throw new Error(`Unrecognized scalar type ${type.ast.$class}`);
195
+ }
196
+
197
+ fieldAst.name = this.ast.name;
198
+ this.scalarField = new Field(this.getParent(), fieldAst);
199
+ return this.scalarField;
200
+ }
120
201
  }
121
202
 
122
203
  module.exports = Field;
@@ -59,7 +59,11 @@ class Introspector {
59
59
  const modelFiles = this.modelManager.getModelFiles();
60
60
  for(let n=0; n < modelFiles.length; n++) {
61
61
  const modelFile = modelFiles[n];
62
- result = result.concat(modelFile.getAllDeclarations());
62
+ result = result.concat(
63
+ modelFile.getAllDeclarations()
64
+ .filter(declaration => !declaration.isScalarDeclaration?.()
65
+ )
66
+ );
63
67
  }
64
68
  return result;
65
69
  }
@@ -21,6 +21,7 @@ const semver = require('semver');
21
21
  const AssetDeclaration = require('./assetdeclaration');
22
22
  const EnumDeclaration = require('./enumdeclaration');
23
23
  const ConceptDeclaration = require('./conceptdeclaration');
24
+ const ScalarDeclaration = require('./scalardeclaration');
24
25
  const ParticipantDeclaration = require('./participantdeclaration');
25
26
  const TransactionDeclaration = require('./transactiondeclaration');
26
27
  const EventDeclaration = require('./eventdeclaration');
@@ -61,7 +62,7 @@ class ModelFile extends Decorated {
61
62
  this.modelManager = modelManager;
62
63
  this.external = false;
63
64
  this.declarations = [];
64
- this.localTypes = new Map();
65
+ this.localTypes = null;
65
66
  this.imports = [];
66
67
  this.importShortNames = new Map();
67
68
  this.importWildcardNamespaces = [];
@@ -92,13 +93,13 @@ class ModelFile extends Decorated {
92
93
 
93
94
  // Set up the decorators.
94
95
  this.process();
95
-
96
96
  // Populate from the AST
97
97
  this.fromAst(this.ast);
98
98
  // Check version compatibility
99
99
  this.isCompatibleVersion();
100
100
 
101
101
  // Now build local types from Declarations
102
+ this.localTypes = new Map();
102
103
  for(let index in this.declarations) {
103
104
  let classDeclaration = this.declarations[index];
104
105
  let localType = this.getNamespace() + '.' + classDeclaration.getName();
@@ -451,6 +452,10 @@ class ModelFile extends Decorated {
451
452
  * @return {ClassDeclaration} the ClassDeclaration, or null if the type does not exist
452
453
  */
453
454
  getLocalType(type) {
455
+ if(!this.localTypes) {
456
+ throw new Error('Internal error: local types are not yet initialized. Do not try to resolve types inside `process`.');
457
+ }
458
+
454
459
  if(!type.startsWith(this.getNamespace())) {
455
460
  type = this.getNamespace() + '.' + type;
456
461
  }
@@ -583,19 +588,28 @@ class ModelFile extends Decorated {
583
588
  return this.getDeclarations(EnumDeclaration);
584
589
  }
585
590
 
591
+ /**
592
+ * Get the ScalarDeclaration defined in this ModelFile
593
+ * @return {ScalarDeclaration[]} the ScalarDeclaration defined in the model file
594
+ */
595
+ getScalarDeclarations() {
596
+ return this.getDeclarations(ScalarDeclaration);
597
+ }
598
+
586
599
  /**
587
600
  * Get the instances of a given type in this ModelFile
588
601
  * @param {Function} type - the type of the declaration
589
- * @return {ClassDeclaration[]} the ClassDeclaration defined in the model file
602
+ * @return {Object[]} the ClassDeclaration defined in the model file
590
603
  */
591
604
  getDeclarations(type) {
592
605
  let result = [];
593
606
  for(let n=0; n < this.declarations.length; n++) {
594
- let classDeclaration = this.declarations[n];
595
- if(classDeclaration instanceof type) {
596
- result.push(classDeclaration);
607
+ let declaration = this.declarations[n];
608
+ if(declaration instanceof type) {
609
+ result.push(declaration);
597
610
  }
598
611
  }
612
+
599
613
  return result;
600
614
  }
601
615
 
@@ -760,6 +774,16 @@ class ModelFile extends Decorated {
760
774
  else if(thing.$class === `${MetaModelNamespace}.ConceptDeclaration`) {
761
775
  this.declarations.push( new ConceptDeclaration(this, thing) );
762
776
  }
777
+ else if([
778
+ `${MetaModelNamespace}.BooleanScalar`,
779
+ `${MetaModelNamespace}.IntegerScalar`,
780
+ `${MetaModelNamespace}.LongScalar`,
781
+ `${MetaModelNamespace}.DoubleScalar`,
782
+ `${MetaModelNamespace}.StringScalar`,
783
+ `${MetaModelNamespace}.DateTimeScalar`,
784
+ ].includes(thing.$class)) {
785
+ this.declarations.push( new ScalarDeclaration(this, thing) );
786
+ }
763
787
  else {
764
788
  let formatter = Globalize('en').messageFormatter('modelfile-constructor-unrecmodelelem');
765
789
 
@@ -22,6 +22,7 @@ const Validator = require('./validator');
22
22
  /* istanbul ignore next */
23
23
  if (global === undefined) {
24
24
  const Field = require('./field');
25
+ const ScalarDeclaration = require('./scalardeclaration');
25
26
  }
26
27
  /* eslint-enable no-unused-vars */
27
28
 
@@ -35,7 +36,7 @@ class NumberValidator extends Validator{
35
36
 
36
37
  /**
37
38
  * Create a NumberValidator.
38
- * @param {Field} field - the field this validator is attached to
39
+ * @param {Object} field - the field or scalar declaration this validator is attached to
39
40
  * @param {Object} ast - The ast for the range defined as [lower,upper] (inclusive).
40
41
  *
41
42
  * @throws {IllegalModelException}
@@ -88,24 +88,33 @@ class Property extends Decorated {
88
88
  throw new Error('No name for type ' + JSON.stringify(this.ast));
89
89
  }
90
90
 
91
- if (this.ast.$class === `${MetaModelNamespace}.BooleanProperty`) {
91
+ switch (this.ast.$class) {
92
+ case `${MetaModelNamespace}.EnumProperty`:
93
+ break;
94
+ case `${MetaModelNamespace}.BooleanProperty`:
92
95
  this.type = 'Boolean';
93
- } else if (this.ast.$class === `${MetaModelNamespace}.StringProperty`) {
94
- this.type = 'String';
95
- } else if (this.ast.$class === `${MetaModelNamespace}.IntegerProperty`) {
96
+ break;
97
+ case `${MetaModelNamespace}.DateTimeProperty`:
98
+ this.type = 'DateTime';
99
+ break;
100
+ case `${MetaModelNamespace}.DoubleProperty`:
101
+ this.type = 'Double';
102
+ break;
103
+ case `${MetaModelNamespace}.IntegerProperty`:
96
104
  this.type = 'Integer';
97
- } else if (this.ast.$class === `${MetaModelNamespace}.LongProperty`) {
105
+ break;
106
+ case `${MetaModelNamespace}.LongProperty`:
98
107
  this.type = 'Long';
99
- } else if (this.ast.$class === `${MetaModelNamespace}.DoubleProperty`) {
100
- this.type = 'Double';
101
- } else if (this.ast.$class === `${MetaModelNamespace}.DateTimeProperty`) {
102
- this.type = 'DateTime';
103
- } else if (this.ast.$class === `${MetaModelNamespace}.ObjectProperty`) {
108
+ break;
109
+ case `${MetaModelNamespace}.StringProperty`:
110
+ this.type = 'String';
111
+ break;
112
+ case `${MetaModelNamespace}.ObjectProperty`:
104
113
  this.type = this.ast.type ? this.ast.type.name : null;
105
- } else if (this.ast.$class === `${MetaModelNamespace}.RelationshipProperty`) {
114
+ break;
115
+ case `${MetaModelNamespace}.RelationshipProperty`:
106
116
  this.type = this.ast.type.name;
107
- } else {
108
- this.type = null;
117
+ break;
109
118
  }
110
119
  this.array = false;
111
120
 
@@ -176,7 +185,6 @@ class Property extends Decorated {
176
185
  if(!modelFile) {
177
186
  throw new Error('Parent of property ' + this.name + ' does not have a ModelFile!');
178
187
  }
179
-
180
188
  const result = modelFile.getFullyQualifiedTypeName(this.type);
181
189
  if(!result) {
182
190
  throw new Error('Failed to find fully qualified type name for property ' + this.name + ' with type ' + this.type );
@@ -0,0 +1,341 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const { MetaModelNamespace } = require('@accordproject/concerto-metamodel');
18
+
19
+ const Decorated = require('./decorated');
20
+ const IllegalModelException = require('./illegalmodelexception');
21
+ const ModelUtil = require('../modelutil');
22
+ const NumberValidator = require('./numbervalidator');
23
+ const StringValidator = require('./stringvalidator');
24
+
25
+ // Types needed for TypeScript generation.
26
+ /* eslint-disable no-unused-vars */
27
+ /* istanbul ignore next */
28
+ if (global === undefined) {
29
+ const ModelFile = require('./modelfile');
30
+ const Validator = require('./validator');
31
+ }
32
+ /* eslint-enable no-unused-vars */
33
+
34
+ /**
35
+ * ScalarDeclaration defines the structure (model/schema) of composite data.
36
+ * It is composed of a set of Properties, may have an identifying field, and may
37
+ * have a super-type.
38
+ * A ScalarDeclaration is conceptually owned by a ModelFile which
39
+ * defines all the classes that are part of a namespace.
40
+ *
41
+ * @abstract
42
+ * @class
43
+ * @memberof module:concerto-core
44
+ */
45
+ class ScalarDeclaration extends Decorated {
46
+ /**
47
+ * Create a ScalarDeclaration from an Abstract Syntax Tree. The AST is the
48
+ * result of parsing.
49
+ *
50
+ * @param {ModelFile} modelFile - the ModelFile for this class
51
+ * @param {Object} ast - the AST created by the parser
52
+ * @throws {IllegalModelException}
53
+ */
54
+ constructor(modelFile, ast) {
55
+ super(ast);
56
+ this.modelFile = modelFile;
57
+ this.process();
58
+ }
59
+
60
+ /**
61
+ * Returns the ModelFile that defines this class.
62
+ *
63
+ * @public
64
+ * @return {ModelFile} the owning ModelFile
65
+ */
66
+ getModelFile() {
67
+ return this.modelFile;
68
+ }
69
+
70
+ /**
71
+ * Process the AST and build the model
72
+ *
73
+ * @throws {IllegalModelException}
74
+ * @private
75
+ */
76
+ process() {
77
+ super.process();
78
+
79
+ this.name = this.ast.name;
80
+ this.superType = null;
81
+ this.superTypeDeclaration = null;
82
+ this.idField = null;
83
+ this.timestamped = false;
84
+ this.abstract = false;
85
+ this.validator = null;
86
+
87
+ if (this.ast.$class === `${MetaModelNamespace}.BooleanScalar`) {
88
+ this.type = 'Boolean';
89
+ } else if (this.ast.$class === `${MetaModelNamespace}.IntegerScalar`) {
90
+ this.type = 'Integer';
91
+ } else if (this.ast.$class === `${MetaModelNamespace}.LongScalar`) {
92
+ this.type = 'Long';
93
+ } else if (this.ast.$class === `${MetaModelNamespace}.DoubleScalar`) {
94
+ this.type = 'Double';
95
+ } else if (this.ast.$class === `${MetaModelNamespace}.StringScalar`) {
96
+ this.type = 'String';
97
+ } else if (this.ast.$class === `${MetaModelNamespace}.DateTimeScalar`) {
98
+ this.type = 'DateTime';
99
+ } else {
100
+ this.type = null;
101
+ }
102
+
103
+ switch(this.getType()) {
104
+ case 'Integer':
105
+ case 'Double':
106
+ case 'Long':
107
+ if(this.ast.validator) {
108
+ this.validator = new NumberValidator(this, this.ast.validator);
109
+ }
110
+ break;
111
+ case 'String':
112
+ if(this.ast.validator) {
113
+ this.validator = new StringValidator(this, this.ast.validator);
114
+ }
115
+ break;
116
+ }
117
+
118
+ if(this.ast.defaultValue) {
119
+ this.defaultValue = this.ast.defaultValue;
120
+ } else {
121
+ this.defaultValue = null;
122
+ }
123
+
124
+ this.fqn = ModelUtil.getFullyQualifiedName(this.modelFile.getNamespace(), this.name);
125
+ }
126
+
127
+ /**
128
+ * Semantic validation of the structure of this class. Subclasses should
129
+ * override this method to impose additional semantic constraints on the
130
+ * contents/relations of fields.
131
+ *
132
+ * @throws {IllegalModelException}
133
+ * @protected
134
+ */
135
+ validate() {
136
+ super.validate();
137
+
138
+ const declarations = this.getModelFile().getAllDeclarations();
139
+ for (let n = 0; n < declarations.length; n++) {
140
+ let declaration = declarations[n];
141
+
142
+ // check we don't have an asset with the same name
143
+ for (let i = n + 1; i < declarations.length; i++) {
144
+ let otherDeclaration = declarations[i];
145
+ if (declaration.getFullyQualifiedName() === otherDeclaration.getFullyQualifiedName()) {
146
+ throw new IllegalModelException(`Duplicate class name ${declaration.getName()}`);
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Returns the short name of a class. This name does not include the
154
+ * namespace from the owning ModelFile.
155
+ *
156
+ * @return {string} the short name of this class
157
+ */
158
+ getName() {
159
+ return this.name;
160
+ }
161
+
162
+ /**
163
+ * Return the namespace of this class.
164
+ * @return {string} namespace - a namespace.
165
+ */
166
+ getNamespace() {
167
+ return this.modelFile.getNamespace();
168
+ }
169
+
170
+ /**
171
+ * Returns the fully qualified name of this class.
172
+ * The name will include the namespace if present.
173
+ *
174
+ * @return {string} the fully-qualified name of this class
175
+ */
176
+ getFullyQualifiedName() {
177
+ return this.fqn;
178
+ }
179
+
180
+ /**
181
+ * Returns false as scalars are never identified.
182
+ * @returns {Boolean} false as scalars are never identified
183
+ */
184
+ isIdentified() {
185
+ return false;
186
+ }
187
+
188
+ /**
189
+ * Returns false as scalars are never identified.
190
+ * @returns {Boolean} false as scalars are never identified
191
+ */
192
+ isSystemIdentified() {
193
+ return false;
194
+ }
195
+
196
+ /**
197
+ * Returns null as scalars are never identified.
198
+ * @return {null} null, as scalars are never identified
199
+ */
200
+ getIdentifierFieldName() {
201
+ return null;
202
+ }
203
+
204
+
205
+ /**
206
+ * Returns the FQN of the super type for this class or null if this
207
+ * class does not have a super type.
208
+ *
209
+ * @return {string} the FQN name of the super type or null
210
+ */
211
+ getType() {
212
+ return this.type;
213
+ }
214
+
215
+ /**
216
+ * Throws an error as scalars do not have supertypes.
217
+ */
218
+ getSuperType() {
219
+ throw new Error('Scalars do not have super types.');
220
+ }
221
+
222
+ /**
223
+ * Get the super type class declaration for this class.
224
+ * @return {ScalarDeclaration | null} the super type declaration, or null if there is no super type.
225
+ */
226
+ getSuperTypeDeclaration() {
227
+ return null;
228
+ }
229
+
230
+ /**
231
+ * Returns the validator string for this scalar definition
232
+ * @return {Validator} the validator for the field or null
233
+ */
234
+ getValidator() {
235
+ return this.validator;
236
+ }
237
+
238
+ /**
239
+ * Returns the default value for the field or null
240
+ * @return {string | number | null} the default value for the field or null
241
+ */
242
+ getDefaultValue() {
243
+ if(this.defaultValue) {
244
+ return this.defaultValue;
245
+ }
246
+ else {
247
+ return null;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Returns the string representation of this class
253
+ * @return {String} the string representation of the class
254
+ */
255
+ toString() {
256
+ return 'ScalarDeclaration {id=' + this.getFullyQualifiedName() + '}';
257
+ }
258
+
259
+ /**
260
+ * Returns true if this class is abstract.
261
+ *
262
+ * @return {boolean} true if the class is abstract
263
+ */
264
+ isAbstract() {
265
+ return true;
266
+ }
267
+
268
+ /**
269
+ * Returns true if this class is the definition of an asset.
270
+ *
271
+ * @return {boolean} true if the class is an asset
272
+ */
273
+ isAsset() {
274
+ return false;
275
+ }
276
+
277
+ /**
278
+ * Returns true if this class is the definition of a participant.
279
+ *
280
+ * @return {boolean} true if the class is a participant
281
+ */
282
+ isParticipant() {
283
+ return false;
284
+ }
285
+
286
+ /**
287
+ * Returns true if this class is the definition of a transaction.
288
+ *
289
+ * @return {boolean} true if the class is a transaction
290
+ */
291
+ isTransaction() {
292
+ return false;
293
+ }
294
+
295
+ /**
296
+ * Returns true if this class is the definition of an event.
297
+ *
298
+ * @return {boolean} true if the class is an event
299
+ */
300
+ isEvent() {
301
+ return false;
302
+ }
303
+
304
+ /**
305
+ * Returns true if this class is the definition of a concept.
306
+ *
307
+ * @return {boolean} true if the class is a concept
308
+ */
309
+ isConcept() {
310
+ return false;
311
+ }
312
+
313
+ /**
314
+ * Returns true if this class is the definition of an enum.
315
+ *
316
+ * @return {boolean} true if the class is an enum
317
+ */
318
+ isEnum() {
319
+ return false;
320
+ }
321
+
322
+ /**
323
+ * Returns true if this class is the definition of a class declaration.
324
+ *
325
+ * @return {boolean} true if the class is a class
326
+ */
327
+ isClassDeclaration() {
328
+ return false;
329
+ }
330
+
331
+ /**
332
+ * Returns true if this class is the definition of a scalar declaration.
333
+ *
334
+ * @return {boolean} true if the class is a scalar
335
+ */
336
+ isScalarDeclaration() {
337
+ return true;
338
+ }
339
+ }
340
+
341
+ module.exports = ScalarDeclaration;