This repository has been archived by the owner on Nov 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
/
CommandProfiles.ts
210 lines (193 loc) · 8.67 KB
/
CommandProfiles.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/
import { ImperativeError } from "../../../error";
import { IProfile, IProfileLoaded } from "../../../profiles";
import { ImperativeExpect } from "../../../expect";
/**
* Profiles map created by the command profile loader and passed to the handler via parameters. Handlers can
* retreive loaded profiles from the map via the profile type.
* @export
* @class CommandProfiles
*/
export class CommandProfiles {
/**
* The loaded profiles map - profiles are retrieved via the type key. More than one profile of a particular type
* can be loaded by the command processor (depending on dependencies, etc.)
* @private
* @type {Map<string, IProfile[]>}
* @memberof CommandProfiles
*/
private mMap: Map<string, IProfile[]>;
/**
* The loaded profiles map with meta info - profiles are retrieved via the type key. More than one profile of a particular type
* can be loaded by the command processor (depending on dependencies, etc.)
* @private
* @type {Map<string, IProfileLoaded[]>}
* @memberof CommandProfiles
*/
private mMetaMap: Map<string, IProfileLoaded[]> = new Map<string, IProfileLoaded[]>();
/**
* Creates an instance of CommandProfiles.
* @param {Map<string, IProfile[]>} map - The map of profiles
* @memberof CommandProfiles
*/
constructor(map: Map<string, IProfile[]>, metaMap?: Map<string, IProfileLoaded[]>) {
// Simple validation of input parameters
const err: string = "Command Profiles Internal Error:";
ImperativeExpect.toNotBeNullOrUndefined(map, `${err} No map was supplied.`);
ImperativeExpect.toBeEqual(map instanceof Map, true, `${err} The "map" supplied is not an instance of a map.`);
// Ensure the correctness of each map entry
map.forEach((value, key) => {
ImperativeExpect.toBeAnArray(value, `${err} The "profiles" supplied for type "${key}" is NOT an array.`);
ImperativeExpect.toBeEqual((value.length > 0), true, `${err} No profiles supplied for type "${key}".`);
});
this.mMap = map;
if (metaMap) {
this.addMeta(metaMap);
}
}
/**
* Gets the first (or by name) meta profile in the map - automatically throws an exception (unless disabled)
* @deprecated
* @template T - The expected profile mapping to be returned
* @param {string} type - The profile type
* @param {string} [name=""] - The name of the profile to retrieve
* @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not
* found - this is provided as convince for the handlers (will fail your command if not found) - This would
* normally be the result of a command configuration problem.
* @returns {T} - The first profile in the map (or the one located by name)
* @memberof CommandProfiles
*/
public getMeta<T extends IProfileLoaded>(type: string, failNotFound = true, name = ""): T {
let profile: IProfileLoaded;
// If a profile is returned for the type, then we'll check if a profile of a specific name was requseted
// if not, just return the first profile found (first loaded)
if (this.metaMap.get(type) != null) {
if (name != null && name.trim().length > 0) {
for (const prof of this.metaMap.get(type)) {
if (prof.name === name) {
profile = prof;
break;
}
}
} else {
profile = this.metaMap.get(type)[0];
}
} else if (failNotFound) {
this.fail(type);
}
return profile as T;
}
/**
* Gets the first (or by name) profile in the map - automatically throws an exception (unless disabled)
* @deprecated Load profile properties from `IHandlerParameters.arguments` property instead.
* @template T - The expected profile mapping to be returned
* @param {string} type - The profile type
* @param {string} [name=""] - The name of the profile to retrieve
* @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not
* found - this is provided as convince for the handlers (will fail your command if not found) - This would
* normally be the result of a command configuration problem.
* @returns {T} - The first profile in the map (or the one located by name)
* @memberof CommandProfiles
*/
public get<T extends IProfile>(type: string, failNotFound = true, name = ""): T {
let profile: IProfile;
// If a profile is returned for the type, then we'll check if a profile of a specific name was requseted
// if not, just return the first profile found (first loaded)
if (this.map.get(type) != null) {
if (name != null && name.trim().length > 0) {
for (const prof of this.map.get(type)) {
if (prof.name === name) {
profile = prof;
break;
}
}
} else {
profile = this.map.get(type)[0];
}
} else if (failNotFound) {
this.fail(type);
}
return profile as T;
}
/**
* Gets all profiles for the type specified,
* @deprecated
* @template T - extends IProfile
* @param {string} type - The profile type to retrieve loaded profiles
* @returns {T[]} - The list of profile types
* @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not
* found - this is provided as convince for the handlers (will fail your command if not found) - This would
* normally be the result of a command configuration problem.
* @memberof CommandProfiles
*/
public getAll<T extends IProfile>(type: string, failNotFound = true): T[] {
const profiles: IProfile[] = this.map.get(type);
if (profiles == null && failNotFound) {
this.fail(type);
}
return profiles as T[];
}
/**
* Add to an instance of CommandProfiles
* @private
* @param {Map<string, IProfileLoaded[]>} map - The map of profiles with meta information
* @memberof CommandProfiles
*/
private addMeta(map: Map<string, IProfileLoaded[]>) {
// Simple validation of input parameters
const err: string = "Command Profiles Internal Error:";
ImperativeExpect.toNotBeNullOrUndefined(map, `${err} No map was supplied.`);
ImperativeExpect.toBeEqual(map instanceof Map, true, `${err} The "map" supplied is not an instance of a map.`);
// Ensure the correctness of each map entry
map.forEach((value, key) => {
ImperativeExpect.toBeAnArray(value, `${err} The "profiles" supplied for type "${key}" is NOT an array.`);
ImperativeExpect.toBeEqual((value.length > 0), true, `${err} No profiles supplied for type "${key}".`);
});
this.mMetaMap = map;
}
/**
* Internal accessor for the map
* @readonly
* @private
* @type {Map<string, IProfile[]>} - The profile Map
* @memberof CommandProfiles
*/
private get map(): Map<string, IProfile[]> {
return this.mMap;
}
/**
* Internal accessor for the meta map
* @readonly
* @private
* @type {Map<string, IProfileLoaded[]>} - The profile Map
* @memberof CommandProfiles
*/
private get metaMap(): Map<string, IProfileLoaded[]> {
return this.mMetaMap;
}
/**
* Throw an error failing the get(requested by the caller if no profiles are available)
* @private
* @param {string} type - the profile type to get from the map
* @memberof CommandProfiles
*/
private fail(type: string) {
throw new ImperativeError({
msg: `Internal Error: No profiles of type "${type}" were loaded for this command.`,
additionalDetails: `This error can occur for one of two reasons:\n` +
` - The "profile" property on the command definition document ` +
`does NOT specify the requested profile type\n` +
` - The profile type is marked "optional", no profiles of type "${type}" have been created, ` +
`and the command handler requested a profile of type "${type}" with "failNotFound=true"`
});
}
}