UNPKG

7.15 kBJavaScriptView Raw
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
17const Globalize = require('./globalize');
18
19/**
20 * Internal Model Utility Class
21 * <p><a href="./diagrams-private/modelutil.svg"><img src="./diagrams-private/modelutil.svg" style="height:100%;"/></a></p>
22 * @private
23 * @class
24 * @memberof module:concerto-core
25 */
26class ModelUtil {
27
28 /**
29 * Returns everything after the last dot, if present, of the source string
30 * @param {string} fqn - the source string
31 * @return {string} - the string after the last dot
32 * @private
33 */
34 static getShortName(fqn) {
35 //console.log('toShortName ' + name );
36 let result = fqn;
37 let dotIndex = fqn.lastIndexOf('.');
38 if (dotIndex > -1) {
39 result = fqn.substr(dotIndex + 1);
40 }
41
42 //console.log('result ' + result );
43 return result;
44 }
45
46 /**
47 * Returns true if the specified name is a wildcard
48 * @param {string} fqn - the source string
49 * @return {boolean} true if the specified name is a wildcard
50 * @private
51 */
52 static isWildcardName(fqn) {
53 return ModelUtil.getShortName(fqn) === '*';
54 }
55
56 /**
57 * Returns true if the specified name is a recusive wildcard
58 * @param {string} fqn - the source string
59 * @return {boolean} true if the specified name is a recusive wildcard
60 * @private
61 */
62 static isRecursiveWildcardName(fqn) {
63 return ModelUtil.getShortName(fqn) === '**';
64 }
65
66 /**
67 * Returns true if a type matches the required fully qualified name. The required
68 * name may be a wildcard or recursive wildcard
69 * @param {Typed} type - the type to test
70 * @param {string} fqn - required fully qualified name
71 * @return {boolean} true if the specified type and namespace match
72 * @private
73 */
74 static isMatchingType(type, fqn) {
75
76 // Instance of type before any complex string operations.
77 if (type.instanceOf(fqn)) {
78 // matching type or subtype
79 return true;
80 }
81
82 let ns = ModelUtil.getNamespace(fqn);
83 let typeNS = type.getNamespace();
84
85 if (ModelUtil.isWildcardName(fqn) && typeNS === ns) {
86 // matching namespace
87 } else if (ModelUtil.isRecursiveWildcardName(fqn) && (typeNS + '.').startsWith(ns + '.')) {
88 // matching recursive namespace
89 } else if (ModelUtil.isRecursiveWildcardName(fqn) && !ns) {
90 // matching root recursive namespace
91 } else {
92 // does not match
93 return false;
94 }
95
96 return true;
97 }
98
99 /**
100 * Returns the namespace for a the fully qualified name of a type
101 * @param {string} fqn - the fully qualified identifier of a type
102 * @return {string} - namespace of the type (everything before the last dot)
103 * or the empty string if there is no dot
104 * @private
105 */
106 static getNamespace(fqn) {
107 if (!fqn) {
108 throw new Error(Globalize.formatMessage('modelutil-getnamespace-nofnq'));
109 }
110
111 let result = '';
112 let dotIndex = fqn.lastIndexOf('.');
113 if (dotIndex > -1) {
114 result = fqn.substr(0, dotIndex);
115 }
116
117 return result;
118 }
119
120 /**
121 * Returns true if the type is a primitive type
122 * @param {string} typeName - the name of the type
123 * @return {boolean} - true if the type is a primitive
124 * @private
125 */
126 static isPrimitiveType(typeName) {
127 const primitiveTypes = ['Boolean', 'String', 'DateTime', 'Double', 'Integer', 'Long'];
128 return (primitiveTypes.indexOf(typeName) >= 0);
129 }
130
131 /**
132 * Returns true if the type is assignable to the propertyType.
133 *
134 * @param {ModelFile} modelFile - the ModelFile that owns the Property
135 * @param {string} typeName - the FQN of the type we are trying to assign
136 * @param {Property} property - the property that we'd like to store the
137 * type in.
138 * @return {boolean} - true if the type can be assigned to the property
139 * @private
140 */
141 static isAssignableTo(modelFile, typeName, property) {
142 const propertyTypeName = property.getFullyQualifiedTypeName();
143
144 const isDirectMatch = (typeName === propertyTypeName);
145 if (isDirectMatch || ModelUtil.isPrimitiveType(typeName) || ModelUtil.isPrimitiveType(propertyTypeName)) {
146 return isDirectMatch;
147 }
148
149 const typeDeclaration = modelFile.getType(typeName);
150 if (!typeDeclaration) {
151 throw new Error('Cannot find type ' + typeName);
152 }
153
154 return typeDeclaration.getAllSuperTypeDeclarations().
155 some(type => type.getFullyQualifiedName() === propertyTypeName);
156 }
157
158 /**
159 * Returns the passed string with the first character capitalized
160 * @param {string} string - the string
161 * @return {string} the string with the first letter capitalized
162 * @private
163 */
164 static capitalizeFirstLetter(string) {
165 return string.charAt(0).toUpperCase() + string.slice(1);
166 }
167
168 /**
169 * Returns the true if the given field is an enumerated type
170 * @param {Field} field - the string
171 * @return {boolean} true if the field is declared as an enumeration
172 * @private
173 */
174 static isEnum(field) {
175 const modelFile = field.getParent().getModelFile();
176 const typeDeclaration = modelFile.getType(field.getType());
177 return (typeDeclaration !== null && typeDeclaration.isEnum());
178 }
179
180 /**
181 * Get the fully qualified name of a type.
182 * @param {string} namespace - namespace of the type.
183 * @param {string} type - short name of the type.
184 * @returns {string} the fully qualified type name.
185 */
186 static getFullyQualifiedName(namespace, type) {
187 if (namespace) {
188 return `${namespace}.${type}`;
189 } else {
190 return type;
191 }
192 }
193
194 /**
195 * Returns the default system model table for a system model file where the class names
196 * exactly match the defaults expected by the ClassDeclarations.
197 *
198 * The default names are:
199 * - 'Transaction'
200 * - 'Asset'
201 * - 'Event'
202 * - 'Participant'
203 *
204 * @returns {string} the fully qualified type name.
205 */
206 static getIdentitySystemModelTable() {
207 const systemModelTable = new Map();
208
209 systemModelTable.set('Transaction', 'Transaction');
210 systemModelTable.set('Asset', 'Asset');
211 systemModelTable.set('Event', 'Event');
212 systemModelTable.set('Participant', 'Participant');
213
214 return systemModelTable;
215 }
216}
217
218module.exports = ModelUtil;