UNPKG

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