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 | ;
|
16 |
|
17 | const 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 | */
|
26 | class 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 |
|
194 | module.exports = ModelUtil;
|