UNPKG

@accordproject/concerto-core

Version:

Core Implementation for the Concerto Modeling Language

214 lines • 7.08 kB
/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 'use strict'; const Decorated = require('./decorated'); const ModelUtil = require('../modelutil'); const IllegalModelException = require('./illegalmodelexception'); // Types needed for TypeScript generation. /* eslint-disable no-unused-vars */ /* istanbul ignore next */ if (global === undefined) { const ModelFile = require('./modelfile'); } /* eslint-enable no-unused-vars */ /** * Declaration defines the structure (model/schema) of composite data. * It is composed of a set of Properties, may have an identifying field, and may * have a super-type. * A Declaration is conceptually owned by a ModelFile which * defines all the classes that are part of a namespace. * * @abstract * @class * @memberof module:concerto-core */ class Declaration extends Decorated { /** * Create a Declaration from an Abstract Syntax Tree. The AST is the * result of parsing. * * @param {ModelFile} modelFile - the ModelFile for this class * @param {Object} ast - the AST created by the parser * @throws {IllegalModelException} */ constructor(modelFile, ast) { super(ast); this.modelFile = modelFile; this.process(); } /** * Process the AST and build the model * * @throws {IllegalModelException} * @private */ process() { super.process(); if (!ModelUtil.isValidIdentifier(this.ast.name)) { throw new IllegalModelException(`Invalid class name '${this.ast.name}'`, this.modelFile, this.ast.location); } this.name = this.ast.name; this.fqn = ModelUtil.getFullyQualifiedName(this.modelFile.getNamespace(), this.name); } /** * Semantic validation of the structure of this decorated. Subclasses should * override this method to impose additional semantic constraints on the * contents/relations of fields. * * @param {...*} args the validation arguments * @throws {IllegalModelException} * @protected */ validate(...args) { super.validate(...args); const modelFile = this.getModelFile(); // #648 - check for clashes against imported types if (modelFile.isImportedType(this.getName())) { const dangerouslyAllowReservedSystemTypeNamesInUserModels = Boolean(modelFile.getModelManager()?.options?.dangerouslyAllowReservedSystemTypeNamesInUserModels); if (dangerouslyAllowReservedSystemTypeNamesInUserModels && this.isReservedSystemTypeImport(modelFile, this.getName())) { return; } throw new IllegalModelException(`Type '${this.getName()}' clashes with an imported type with the same name.`, this.modelFile, this.ast.location); } } /** * Determines whether a type name resolves to a reserved type in the Concerto * system namespace. * @param {ModelFile} modelFile - the current model file * @param {string} typeName - local/imported type name * @returns {boolean} true if the resolved import is a reserved system type */ isReservedSystemTypeImport(modelFile, typeName) { const importedType = modelFile.getType(typeName); if (!importedType || typeof importedType === 'string') { return false; } const importedModelFile = importedType.getModelFile(); if (!importedModelFile || !importedModelFile.isSystemModelFile()) { return false; } return importedType.isConcept() || importedType.isAsset() || importedType.isTransaction() || importedType.isParticipant() || importedType.isEvent(); } /** * Returns the ModelFile that defines this class. * * @public * @return {ModelFile} the owning ModelFile */ getModelFile() { return this.modelFile; } /** * Returns the short name of a class. This name does not include the * namespace from the owning ModelFile. * * @return {string} the short name of this class */ getName() { return this.name; } /** * Return the namespace of this class. * @return {string} namespace - a namespace. */ getNamespace() { return this.modelFile.getNamespace(); } /** * Returns the fully qualified name of this class. * The name will include the namespace if present. * * @return {string} the fully-qualified name of this class */ getFullyQualifiedName() { return this.fqn; } /** * Returns false as scalars are never identified. * @returns {Boolean} false as scalars are never identified */ isIdentified() { return false; } /** * Returns false as scalars are never identified. * @returns {Boolean} false as scalars are never identified */ isSystemIdentified() { return false; } /** * Returns the name of the identifying field for this class. Note * that the identifying field may come from a super type. * * @return {string} the name of the id field for this class or null if it does not exist */ getIdentifierFieldName() { return null; } /** * Returns the FQN of the super type for this class or null if this * class does not have a super type. * * @return {string} the FQN name of the super type or null */ getType() { return null; } /** * Returns the string representation of this class * @return {String} the string representation of the class */ toString() { return null; } /** * Returns true if this class is the definition of an enum. * * @return {boolean} true if the class is an enum */ isEnum() { return false; } /** * Returns true if this class is the definition of a class declaration. * * @return {boolean} true if the class is a class */ isClassDeclaration() { return false; } /** * Returns true if this class is the definition of a scalar declaration. * * @return {boolean} true if the class is a scalar */ isScalarDeclaration() { return false; } /** * Returns true if this class is the definition of a map-declaration. * * @return {boolean} true if the class is a map-declaration */ isMapDeclaration() { return false; } } module.exports = Declaration; //# sourceMappingURL=declaration.js.map