ngx-material-entity 0.1.1 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +7 -1
- package/README.md +536 -328
- package/classes/base.builder.d.ts +35 -0
- package/classes/date.utilities.d.ts +58 -0
- package/classes/entity.model.d.ts +13 -0
- package/classes/{entity-service.class.d.ts → entity.service.d.ts} +35 -20
- package/classes/entity.utilities.d.ts +153 -0
- package/components/confirm-dialog/confirm-dialog-data.builder.d.ts +23 -0
- package/components/confirm-dialog/confirm-dialog-data.d.ts +18 -8
- package/components/confirm-dialog/confirm-dialog.component.d.ts +15 -5
- package/components/get-validation-error-message.function.d.ts +3 -2
- package/components/input/add-array-item-dialog-data.builder.d.ts +20 -0
- package/components/input/add-array-item-dialog-data.d.ts +19 -0
- package/components/input/input.component.d.ts +151 -30
- package/components/input/input.module.d.ts +7 -4
- package/components/table/create-dialog/create-dialog-data.builder.d.ts +21 -0
- package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +21 -0
- package/components/table/create-dialog/create-entity-dialog-data.d.ts +4 -5
- package/components/table/create-dialog/create-entity-dialog.component.d.ts +21 -8
- package/components/table/edit-dialog/edit-dialog-data.builder.d.ts +24 -0
- package/components/table/edit-dialog/edit-entity-dialog-data.d.ts +7 -8
- package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +22 -0
- package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +25 -8
- package/components/table/table-data.builder.d.ts +51 -0
- package/components/table/table-data.d.ts +46 -30
- package/components/table/table.component.d.ts +53 -7
- package/components/table/table.module.d.ts +3 -1
- package/decorators/array/array-decorator-internal.data.d.ts +45 -0
- package/decorators/array/array-decorator.data.d.ts +129 -0
- package/decorators/array/array.decorator.d.ts +9 -0
- package/decorators/base/base-property.decorator.d.ts +7 -6
- package/decorators/base/decorator-types.enum.d.ts +12 -9
- package/decorators/base/dropdown-value.interface.d.ts +14 -0
- package/decorators/base/property-decorator-internal.data.d.ts +24 -0
- package/decorators/base/property-decorator.data.d.ts +70 -0
- package/decorators/boolean/boolean-decorator-internal.data.d.ts +25 -0
- package/decorators/boolean/boolean-decorator.data.d.ts +37 -0
- package/decorators/boolean/boolean.decorator.d.ts +8 -0
- package/decorators/date/date-decorator-internal.data.d.ts +44 -0
- package/decorators/date/date-decorator.data.d.ts +129 -0
- package/decorators/number/number-decorator-internal.data.d.ts +20 -0
- package/decorators/number/number-decorator.data.d.ts +36 -0
- package/decorators/number/number.decorator.d.ts +8 -0
- package/decorators/object/object-decorator-internal.data.d.ts +11 -0
- package/decorators/object/object-decorator.data.d.ts +25 -0
- package/decorators/object/object.decorator.d.ts +8 -0
- package/decorators/string/string-decorator-internal.data.d.ts +41 -0
- package/decorators/string/string-decorator.data.d.ts +77 -0
- package/decorators/string/string.decorator.d.ts +8 -0
- package/esm2020/classes/base.builder.mjs +43 -0
- package/esm2020/classes/date.utilities.mjs +138 -0
- package/esm2020/classes/entity.model.mjs +19 -0
- package/esm2020/classes/entity.service.mjs +83 -0
- package/esm2020/classes/entity.utilities.mjs +538 -0
- package/esm2020/components/confirm-dialog/confirm-dialog-data.builder.mjs +44 -0
- package/esm2020/components/confirm-dialog/confirm-dialog-data.mjs +1 -1
- package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +18 -22
- package/esm2020/components/get-validation-error-message.function.mjs +8 -3
- package/esm2020/components/input/add-array-item-dialog-data.builder.mjs +30 -0
- package/esm2020/components/input/add-array-item-dialog-data.mjs +2 -0
- package/esm2020/components/input/input.component.mjs +240 -36
- package/esm2020/components/input/input.module.mjs +23 -9
- package/esm2020/components/table/create-dialog/create-dialog-data.builder.mjs +32 -0
- package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +26 -0
- package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
- package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +31 -31
- package/esm2020/components/table/create-dialog/create-entity-dialog.module.mjs +20 -4
- package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +41 -0
- package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +1 -1
- package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +27 -0
- package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +45 -49
- package/esm2020/components/table/table-data.builder.mjs +105 -0
- package/esm2020/components/table/table-data.mjs +1 -1
- package/esm2020/components/table/table.component.mjs +91 -83
- package/esm2020/components/table/table.module.mjs +12 -4
- package/esm2020/decorators/array/array-decorator-internal.data.mjs +51 -0
- package/esm2020/decorators/array/array-decorator.data.mjs +7 -0
- package/esm2020/decorators/array/array.decorator.mjs +24 -0
- package/esm2020/decorators/base/base-property.decorator.mjs +6 -5
- package/esm2020/decorators/base/decorator-types.enum.mjs +4 -1
- package/esm2020/decorators/base/dropdown-value.interface.mjs +2 -0
- package/esm2020/decorators/base/property-decorator-internal.data.mjs +38 -0
- package/esm2020/decorators/base/property-decorator.data.mjs +6 -0
- package/esm2020/decorators/boolean/boolean-decorator-internal.data.mjs +33 -0
- package/esm2020/decorators/boolean/boolean-decorator.data.mjs +7 -0
- package/esm2020/decorators/boolean/boolean.decorator.mjs +21 -0
- package/esm2020/decorators/date/date-decorator-internal.data.mjs +48 -0
- package/esm2020/decorators/date/date-decorator.data.mjs +7 -0
- package/esm2020/decorators/number/number-decorator-internal.data.mjs +23 -0
- package/esm2020/decorators/number/number-decorator.data.mjs +7 -0
- package/esm2020/decorators/number/number.decorator.mjs +18 -0
- package/esm2020/decorators/object/object-decorator-internal.data.mjs +12 -0
- package/esm2020/decorators/object/object-decorator.data.mjs +7 -0
- package/esm2020/decorators/object/object.decorator.mjs +13 -0
- package/esm2020/decorators/string/string-decorator-internal.data.mjs +48 -0
- package/esm2020/decorators/string/string-decorator.data.mjs +7 -0
- package/esm2020/decorators/string/string.decorator.mjs +24 -0
- package/esm2020/public-api.mjs +20 -13
- package/fesm2015/ngx-material-entity.mjs +1664 -944
- package/fesm2015/ngx-material-entity.mjs.map +1 -1
- package/fesm2020/ngx-material-entity.mjs +1667 -941
- package/fesm2020/ngx-material-entity.mjs.map +1 -1
- package/package.json +7 -1
- package/public-api.d.ts +21 -10
- package/classes/entity-model.class.d.ts +0 -9
- package/classes/entity-utilities.class.d.ts +0 -95
- package/components/input/array-table/add-array-item-dialog/add-array-item-dialog.component.d.ts +0 -35
- package/components/input/array-table/add-array-item-dialog/add-array-item-dialog.module.d.ts +0 -12
- package/components/input/array-table/array-table.component.d.ts +0 -34
- package/components/input/array-table/array-table.module.d.ts +0 -19
- package/components/input/internal-input/internal-input.component.d.ts +0 -57
- package/components/input/internal-input/internal-input.module.d.ts +0 -16
- package/decorators/array.decorator.d.ts +0 -125
- package/decorators/base/property-decorator-config.interface.d.ts +0 -50
- package/decorators/boolean.decorator.d.ts +0 -42
- package/decorators/number.decorator.d.ts +0 -40
- package/decorators/object.decorator.d.ts +0 -27
- package/decorators/string.decorator.d.ts +0 -76
- package/esm2020/classes/entity-model.class.mjs +0 -19
- package/esm2020/classes/entity-service.class.mjs +0 -70
- package/esm2020/classes/entity-utilities.class.mjs +0 -296
- package/esm2020/components/input/array-table/add-array-item-dialog/add-array-item-dialog.component.mjs +0 -43
- package/esm2020/components/input/array-table/add-array-item-dialog/add-array-item-dialog.module.mjs +0 -22
- package/esm2020/components/input/array-table/array-table.component.mjs +0 -116
- package/esm2020/components/input/array-table/array-table.module.mjs +0 -66
- package/esm2020/components/input/internal-input/internal-input.component.mjs +0 -73
- package/esm2020/components/input/internal-input/internal-input.module.mjs +0 -54
- package/esm2020/decorators/array.decorator.mjs +0 -70
- package/esm2020/decorators/base/property-decorator-config.interface.mjs +0 -31
- package/esm2020/decorators/boolean.decorator.mjs +0 -44
- package/esm2020/decorators/number.decorator.mjs +0 -36
- package/esm2020/decorators/object.decorator.mjs +0 -23
- package/esm2020/decorators/string.decorator.mjs +0 -61
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import { cloneDeep, isEqual } from 'lodash';
|
|
2
|
+
import { DecoratorTypes } from '../decorators/base/decorator-types.enum';
|
|
3
|
+
import { DateUtilities } from './date.utilities';
|
|
4
|
+
/**
|
|
5
|
+
* Contains HelperMethods around handling Entities and their property-metadata.
|
|
6
|
+
*/
|
|
7
|
+
export class EntityUtilities {
|
|
8
|
+
/**
|
|
9
|
+
* Gets the properties to omit when updating the entity.
|
|
10
|
+
*
|
|
11
|
+
* @param entity - The entity to get the properties which should be left out for updating from.
|
|
12
|
+
* @returns The properties which should be left out for updating an Entity.
|
|
13
|
+
*/
|
|
14
|
+
static getOmitForUpdate(entity) {
|
|
15
|
+
const res = [];
|
|
16
|
+
for (const key of EntityUtilities.keysOf(entity)) {
|
|
17
|
+
const metadata = EntityUtilities.getPropertyMetadata(entity, key);
|
|
18
|
+
if (metadata.omitForUpdate) {
|
|
19
|
+
res.push(key);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return res;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Gets the properties to omit when creating new entities.
|
|
26
|
+
*
|
|
27
|
+
* @param entity - The entity to get the properties which should be left out for creating from.
|
|
28
|
+
* @returns The properties which should be left out for creating a new Entity.
|
|
29
|
+
*/
|
|
30
|
+
static getOmitForCreate(entity) {
|
|
31
|
+
const res = [];
|
|
32
|
+
for (const key of EntityUtilities.keysOf(entity)) {
|
|
33
|
+
const metadata = EntityUtilities.getPropertyMetadata(entity, key);
|
|
34
|
+
if (metadata.omitForCreate) {
|
|
35
|
+
res.push(key);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return res;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gets the metadata included in an property.
|
|
42
|
+
*
|
|
43
|
+
* @param entity - The entity with the property to get the metadata from.
|
|
44
|
+
* @param propertyKey - The property on the given Entity to get the metadata from.
|
|
45
|
+
* @param type - For secure Typing, defines the returned PropertyConfig.
|
|
46
|
+
* @returns The metadata of the property.
|
|
47
|
+
* @throws When no metadata can be found for the given property.
|
|
48
|
+
*/
|
|
49
|
+
static getPropertyMetadata(entity, propertyKey,
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
|
+
type) {
|
|
52
|
+
try {
|
|
53
|
+
const metadata = Reflect.getMetadata('metadata', entity, propertyKey);
|
|
54
|
+
if (!metadata) {
|
|
55
|
+
throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
|
|
56
|
+
}
|
|
57
|
+
return metadata;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the type of the property-metadata.
|
|
65
|
+
*
|
|
66
|
+
* @param entity - The entity with the property to get the type from.
|
|
67
|
+
* @param propertyKey - The property on the given Entity to get the type from.
|
|
68
|
+
* @returns The type of the metadata.
|
|
69
|
+
* @throws Will throw an error if no metadata can be found for the given property.
|
|
70
|
+
*/
|
|
71
|
+
static getPropertyType(entity, propertyKey) {
|
|
72
|
+
try {
|
|
73
|
+
const propertyType = Reflect.getMetadata('type', entity, propertyKey);
|
|
74
|
+
if (!propertyType) {
|
|
75
|
+
throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
|
|
76
|
+
}
|
|
77
|
+
return propertyType;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sets all property values based on a given entity data-object.
|
|
85
|
+
*
|
|
86
|
+
* @param target - The target object that needs to be constructed (if called inside an Entity constructor its usually this).
|
|
87
|
+
* @param entity - The data object to get the property values from.
|
|
88
|
+
* @alias new
|
|
89
|
+
* @alias build
|
|
90
|
+
* @alias construct
|
|
91
|
+
*/
|
|
92
|
+
static new(target, entity) {
|
|
93
|
+
for (const key in target) {
|
|
94
|
+
const type = EntityUtilities.getPropertyType(target, key);
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
96
|
+
let value = entity ? Reflect.get(entity, key) : undefined;
|
|
97
|
+
switch (type) {
|
|
98
|
+
case DecoratorTypes.OBJECT:
|
|
99
|
+
const objectMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
101
|
+
value = new objectMetadata.EntityClass(value);
|
|
102
|
+
break;
|
|
103
|
+
case DecoratorTypes.ARRAY:
|
|
104
|
+
const inputArray = value;
|
|
105
|
+
const resArray = [];
|
|
106
|
+
if (inputArray) {
|
|
107
|
+
const arrayMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.ARRAY);
|
|
108
|
+
for (const item of inputArray) {
|
|
109
|
+
const itemWithMetadata = new arrayMetadata.EntityClass(item);
|
|
110
|
+
resArray.push(itemWithMetadata);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
value = resArray;
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
Reflect.set(target, key, value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Checks if the values on an entity are valid.
|
|
123
|
+
* Also checks all the validators given by the metadata ("required", "maxLength" etc.).
|
|
124
|
+
*
|
|
125
|
+
* @param entity - The entity to validate.
|
|
126
|
+
* @param omit - Whether to check for creating or editing validity.
|
|
127
|
+
* @returns Whether or not the entity is valid.
|
|
128
|
+
*/
|
|
129
|
+
static isEntityValid(entity, omit) {
|
|
130
|
+
for (const key in entity) {
|
|
131
|
+
if (!EntityUtilities.isPropertyValid(entity, key, omit)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Checks if a single property value is valid.
|
|
139
|
+
*
|
|
140
|
+
* @param entity - The entity where the property is from.
|
|
141
|
+
* @param key - The name of the property.
|
|
142
|
+
* @param omit - Whether to check if the given entity is valid for creation or updating.
|
|
143
|
+
* @returns Whether or not the property value is valid.
|
|
144
|
+
* @throws Throws when it extracts an unknown metadata type.
|
|
145
|
+
*/
|
|
146
|
+
static isPropertyValid(entity, key, omit) {
|
|
147
|
+
const type = EntityUtilities.getPropertyType(entity, key);
|
|
148
|
+
const metadata = EntityUtilities.getPropertyMetadata(entity, key, type);
|
|
149
|
+
if (metadata.omitForCreate && omit === 'create') {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
if (metadata.omitForUpdate && omit === 'update') {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (metadata.required && !entity[key]) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
switch (type) {
|
|
159
|
+
case DecoratorTypes.BOOLEAN_DROPDOWN:
|
|
160
|
+
case DecoratorTypes.BOOLEAN_CHECKBOX:
|
|
161
|
+
case DecoratorTypes.BOOLEAN_TOGGLE:
|
|
162
|
+
return true;
|
|
163
|
+
case DecoratorTypes.STRING_DROPDOWN:
|
|
164
|
+
return true;
|
|
165
|
+
case DecoratorTypes.STRING:
|
|
166
|
+
case DecoratorTypes.STRING_AUTOCOMPLETE:
|
|
167
|
+
const entityString = entity[key];
|
|
168
|
+
const stringMetadata = metadata;
|
|
169
|
+
if (!this.isStringValid(entityString, stringMetadata)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
case DecoratorTypes.STRING_TEXTBOX:
|
|
174
|
+
const entityTextbox = entity[key];
|
|
175
|
+
const textboxMetadata = metadata;
|
|
176
|
+
if (!this.isTextboxValid(entityTextbox, textboxMetadata)) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case DecoratorTypes.NUMBER_DROPDOWN:
|
|
181
|
+
return true;
|
|
182
|
+
case DecoratorTypes.NUMBER:
|
|
183
|
+
const entityNumber = entity[key];
|
|
184
|
+
const numberMetadata = metadata;
|
|
185
|
+
if (!this.isNumberValid(entityNumber, numberMetadata)) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
case DecoratorTypes.OBJECT:
|
|
190
|
+
const entityObject = entity[key];
|
|
191
|
+
for (const parameterKey in entityObject) {
|
|
192
|
+
if (!EntityUtilities.isPropertyValid(entityObject, parameterKey, omit)) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
case DecoratorTypes.ARRAY_STRING_CHIPS:
|
|
198
|
+
case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
|
|
199
|
+
case DecoratorTypes.ARRAY:
|
|
200
|
+
const entityArray = entity[key];
|
|
201
|
+
const arrayMetadata = metadata;
|
|
202
|
+
if (arrayMetadata.required && !entityArray.length) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
case DecoratorTypes.DATE:
|
|
207
|
+
const entityDate = new Date(entity[key]);
|
|
208
|
+
const dateMetadata = metadata;
|
|
209
|
+
if (!this.isDateValid(entityDate, dateMetadata)) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
case DecoratorTypes.DATE_RANGE:
|
|
214
|
+
const entityDateRange = cloneDeep(entity[key]);
|
|
215
|
+
const dateRangeMetadata = metadata;
|
|
216
|
+
if (!this.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
case DecoratorTypes.DATE_TIME:
|
|
221
|
+
const entityDateTime = new Date(entity[key]);
|
|
222
|
+
const dateTimeMetadata = metadata;
|
|
223
|
+
if (!this.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
throw new Error(`Could not validate the input because the DecoratorType ${type} is not known`);
|
|
229
|
+
}
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
static isStringValid(value, metadata) {
|
|
233
|
+
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
if (metadata.minLength && value.length < metadata.minLength) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
if (metadata.regex && !value.match(metadata.regex)) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
static isTextboxValid(value, metadata) {
|
|
245
|
+
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (metadata.minLength && value.length < metadata.minLength) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
static isNumberValid(value, metadata) {
|
|
254
|
+
if (metadata.max && value > metadata.max) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (metadata.min && value < metadata.min) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
static isDateValid(value, metadata) {
|
|
263
|
+
if (metadata.min && value.getTime() < metadata.min(value).getTime()) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
if (metadata.max && value.getTime() > metadata.max(value).getTime()) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
if (metadata.filter && !metadata.filter(value)) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
static isDateRangeValid(value, metadata) {
|
|
275
|
+
if (metadata.required && (!value.start || !value.end)) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
value.start = new Date(value.start);
|
|
279
|
+
value.end = new Date(value.end);
|
|
280
|
+
if (metadata.minStart && value.start.getTime() < metadata.minStart(value.start).getTime()) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
if (metadata.maxStart && value.start.getTime() > metadata.maxStart(value.start).getTime()) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
if (metadata.minEnd && value.end.getTime() < metadata.minEnd(value.end).getTime()) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
if (metadata.maxEnd && value.end.getTime() > metadata.maxEnd(value.end).getTime()) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
if (metadata.filter) {
|
|
293
|
+
if (!metadata.filter(value.start)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
if (!metadata.filter(value.end)) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
if (value.values) {
|
|
300
|
+
for (const date of value.values) {
|
|
301
|
+
if (!metadata.filter(date)) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
static isDateTimeValid(value, metadata) {
|
|
310
|
+
if (metadata.minDate && value.getTime() < metadata.minDate(value).getTime()) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
if (metadata.maxDate && value.getTime() > metadata.maxDate(value).getTime()) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
if (metadata.filterDate && !metadata.filterDate(value)) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
const time = {
|
|
320
|
+
hours: value.getHours(),
|
|
321
|
+
minutes: value.getMinutes()
|
|
322
|
+
};
|
|
323
|
+
if (metadata.minTime) {
|
|
324
|
+
const minTime = metadata.minTime(value);
|
|
325
|
+
if (!(time.hours > minTime.hours
|
|
326
|
+
|| (time.hours === minTime.hours
|
|
327
|
+
&& time.minutes >= minTime.minutes))) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (metadata.maxTime) {
|
|
332
|
+
const maxTime = metadata.maxTime(value);
|
|
333
|
+
if (!(time.hours < maxTime.hours
|
|
334
|
+
|| (time.hours === maxTime.hours
|
|
335
|
+
&& time.minutes <= maxTime.minutes))) {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (metadata.filterTime) {
|
|
340
|
+
if (!metadata.filterTime(time)) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Checks if an entity is "dirty" (if its values have changed).
|
|
348
|
+
*
|
|
349
|
+
* @param entity - The entity after all changes.
|
|
350
|
+
* @param entityPriorChanges - The entity before the changes.
|
|
351
|
+
* @returns Whether or not the entity is dirty.
|
|
352
|
+
*/
|
|
353
|
+
static dirty(entity, entityPriorChanges) {
|
|
354
|
+
if (!entityPriorChanges) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
const differences = this.differencesForDirty(entity, entityPriorChanges);
|
|
359
|
+
return differences.length ? true : false;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
static differencesForDirty(entity, entityPriorChanges) {
|
|
363
|
+
const res = [];
|
|
364
|
+
for (const key in entity) {
|
|
365
|
+
if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
|
|
366
|
+
res.push({
|
|
367
|
+
key: key,
|
|
368
|
+
before: entityPriorChanges[key],
|
|
369
|
+
after: entity[key]
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return res;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Compares two Entities and returns their difference in an object.
|
|
377
|
+
*
|
|
378
|
+
* @param entity - The first entity to compare.
|
|
379
|
+
* @param entityPriorChanges - The second entity to compare.
|
|
380
|
+
* @returns The difference between the two Entities in form of a Partial.
|
|
381
|
+
*/
|
|
382
|
+
static difference(entity, entityPriorChanges) {
|
|
383
|
+
const res = {};
|
|
384
|
+
for (const key in entity) {
|
|
385
|
+
if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
|
|
386
|
+
res[key] = entity[key];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return res;
|
|
390
|
+
}
|
|
391
|
+
static isEqual(value, valuePriorChanges, metadata) {
|
|
392
|
+
if (this.isDateRange(value) && this.isDateRange(valuePriorChanges)) {
|
|
393
|
+
const dateRange = cloneDeep(value);
|
|
394
|
+
dateRange.start = new Date(value.start);
|
|
395
|
+
dateRange.end = new Date(value.end);
|
|
396
|
+
dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, metadata);
|
|
397
|
+
const dateRangePriorChanges = cloneDeep(valuePriorChanges);
|
|
398
|
+
dateRangePriorChanges.start = new Date(valuePriorChanges.start);
|
|
399
|
+
dateRangePriorChanges.end = new Date(valuePriorChanges.end);
|
|
400
|
+
dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, metadata);
|
|
401
|
+
return isEqual(dateRange, dateRangePriorChanges);
|
|
402
|
+
}
|
|
403
|
+
if (metadata.displayStyle === 'date') {
|
|
404
|
+
const date = new Date(DateUtilities.asDate(value));
|
|
405
|
+
const datePriorChanges = new Date(DateUtilities.asDate(valuePriorChanges));
|
|
406
|
+
date.setHours(0, 0, 0, 0);
|
|
407
|
+
datePriorChanges.setHours(0, 0, 0, 0);
|
|
408
|
+
return isEqual(date, datePriorChanges);
|
|
409
|
+
}
|
|
410
|
+
return isEqual(value, valuePriorChanges);
|
|
411
|
+
}
|
|
412
|
+
static isDateRange(value) {
|
|
413
|
+
const dateRange = value;
|
|
414
|
+
if (dateRange.start && dateRange.end) {
|
|
415
|
+
try {
|
|
416
|
+
new Date(dateRange.start);
|
|
417
|
+
new Date(dateRange.end);
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
catch (error) { }
|
|
421
|
+
;
|
|
422
|
+
}
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Compare function for sorting entity keys by their order value.
|
|
427
|
+
*
|
|
428
|
+
* @param a - First key of entity.
|
|
429
|
+
* @param b - Second key of entity.
|
|
430
|
+
* @param entity - Current entity (used to get metadata of entity keys).
|
|
431
|
+
* @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
|
|
432
|
+
*/
|
|
433
|
+
static compareOrder(a, b, entity) {
|
|
434
|
+
const metadataA = EntityUtilities.getPropertyMetadata(entity, a);
|
|
435
|
+
const metadataB = EntityUtilities.getPropertyMetadata(entity, b);
|
|
436
|
+
if (metadataA.position.order === -1) {
|
|
437
|
+
if (metadataB.position.order === -1) {
|
|
438
|
+
return 0;
|
|
439
|
+
}
|
|
440
|
+
return 1;
|
|
441
|
+
}
|
|
442
|
+
else if (metadataB.position.order === -1) {
|
|
443
|
+
return -1;
|
|
444
|
+
}
|
|
445
|
+
return ((metadataA.position.order) - (metadataB.position.order));
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Gets the bootstrap column values for "lg", "md", "sm".
|
|
449
|
+
*
|
|
450
|
+
* @param entity - Entity to get the bootstrap column values of the key.
|
|
451
|
+
* @param key - Key of the property to get bootstrap column values from.
|
|
452
|
+
* @param type - Defines for which screen size the column values should be returned.
|
|
453
|
+
* @returns Bootstrap column value.
|
|
454
|
+
*/
|
|
455
|
+
static getWidth(entity, key, type) {
|
|
456
|
+
const metadata = EntityUtilities.getPropertyMetadata(entity, key);
|
|
457
|
+
switch (type) {
|
|
458
|
+
case 'lg':
|
|
459
|
+
return metadata.defaultWidths[0];
|
|
460
|
+
case 'md':
|
|
461
|
+
return metadata.defaultWidths[1];
|
|
462
|
+
case 'sm':
|
|
463
|
+
return metadata.defaultWidths[2];
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Resets all changes on an entity.
|
|
468
|
+
*
|
|
469
|
+
* @param entity - The entity to reset.
|
|
470
|
+
* @param entityPriorChanges - The entity before any changes.
|
|
471
|
+
*/
|
|
472
|
+
static resetChangesOnEntity(entity, entityPriorChanges) {
|
|
473
|
+
for (const key in entityPriorChanges) {
|
|
474
|
+
Reflect.set(entity, key, Reflect.get(entityPriorChanges, key));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Gets the rows that are used to display the given entity.
|
|
479
|
+
*
|
|
480
|
+
* @param entity - The entity to get the rows from.
|
|
481
|
+
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
482
|
+
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
483
|
+
* @returns The sorted Rows containing the row number and the keys to display in that row.
|
|
484
|
+
*/
|
|
485
|
+
static getEntityRows(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
|
|
486
|
+
const res = [];
|
|
487
|
+
const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
|
|
488
|
+
const numberOfRows = this.getNumberOfRows(keys, entity);
|
|
489
|
+
for (let i = 1; i <= numberOfRows; i++) {
|
|
490
|
+
const row = {
|
|
491
|
+
row: i,
|
|
492
|
+
keys: this.getKeysForRow(keys, entity, i)
|
|
493
|
+
};
|
|
494
|
+
res.push(row);
|
|
495
|
+
}
|
|
496
|
+
const lastRow = {
|
|
497
|
+
row: numberOfRows + 1,
|
|
498
|
+
keys: this.getKeysForRow(keys, entity, -1)
|
|
499
|
+
};
|
|
500
|
+
res.push(lastRow);
|
|
501
|
+
return res;
|
|
502
|
+
}
|
|
503
|
+
static getKeysForRow(keys, entity, i) {
|
|
504
|
+
return keys
|
|
505
|
+
.filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.row === i)
|
|
506
|
+
.sort((a, b) => EntityUtilities.compareOrder(a, b, entity));
|
|
507
|
+
}
|
|
508
|
+
static getNumberOfRows(keys, entity) {
|
|
509
|
+
return keys
|
|
510
|
+
.map(k => EntityUtilities.getPropertyMetadata(entity, k).position.row)
|
|
511
|
+
.sort((a, b) => (a > b ? -1 : 1))[0];
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Gets the keys of the provided entity correctly typed.
|
|
515
|
+
*
|
|
516
|
+
* @param entity - The entity to get the keys of.
|
|
517
|
+
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
518
|
+
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
519
|
+
* @returns An array of keys of the entity.
|
|
520
|
+
*/
|
|
521
|
+
static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
|
|
522
|
+
let keys = Reflect.ownKeys(entity);
|
|
523
|
+
if (hideOmitForCreate) {
|
|
524
|
+
const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
|
|
525
|
+
keys = keys.filter(k => !omitForCreateKeys.includes(k));
|
|
526
|
+
}
|
|
527
|
+
if (hideOmitForEdit) {
|
|
528
|
+
const omitForUpdateKeys = EntityUtilities.getOmitForUpdate(entity);
|
|
529
|
+
keys = keys.filter(k => !omitForUpdateKeys.includes(k));
|
|
530
|
+
}
|
|
531
|
+
return keys;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc
|
|
535
|
+
EntityUtilities.construct = EntityUtilities.new;
|
|
536
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc
|
|
537
|
+
EntityUtilities.build = EntityUtilities.new;
|
|
538
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LnV0aWxpdGllcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1tYXRlcmlhbC1lbnRpdHkvc3JjL2NsYXNzZXMvZW50aXR5LnV0aWxpdGllcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM1QyxPQUFPLEVBQWlCLGNBQWMsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBUXhGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQW9CakQ7O0dBRUc7QUFDSCxNQUFNLE9BQWdCLGVBQWU7SUFFakM7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQTRCLE1BQWtCO1FBQ2pFLE1BQU0sR0FBRyxHQUF5QixFQUFFLENBQUM7UUFDckMsS0FBSyxNQUFNLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlDLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbEUsSUFBSSxRQUFRLENBQUMsYUFBYSxFQUFFO2dCQUN4QixHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2pCO1NBQ0o7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBNEIsTUFBa0I7UUFDakUsTUFBTSxHQUFHLEdBQXlCLEVBQUUsQ0FBQztRQUNyQyxLQUFLLE1BQU0sR0FBRyxJQUFJLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDOUMsTUFBTSxRQUFRLEdBQUcsZUFBZSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNsRSxJQUFJLFFBQVEsQ0FBQyxhQUFhLEVB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QyxtRkFBbUY7QUFDNUUscUJBQUssR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY2xvbmVEZWVwLCBpc0VxdWFsIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IERlY29yYXRvclR5cGUsIERlY29yYXRvclR5cGVzIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9iYXNlL2RlY29yYXRvci10eXBlcy5lbnVtJztcbmltcG9ydCB7IFByb3BlcnR5RGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2Jhc2UvcHJvcGVydHktZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRW50aXR5QXJyYXlEZWNvcmF0b3JDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uL2RlY29yYXRvcnMvYXJyYXkvYXJyYXktZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsLCBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL3N0cmluZy9zdHJpbmctZGVjb3JhdG9yLWludGVybmFsLmRhdGEnO1xuaW1wb3J0IHsgRGVmYXVsdE51bWJlckRlY29yYXRvckNvbmZpZ0ludGVybmFsIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9udW1iZXIvbnVtYmVyLWRlY29yYXRvci1pbnRlcm5hbC5kYXRhJztcbmltcG9ydCB7IERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCwgRGF0ZVRpbWVEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwsIERlZmF1bHREYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2RhdGUvZGF0ZS1kZWNvcmF0b3ItaW50ZXJuYWwuZGF0YSc7XG5pbXBvcnQgeyBEYXRlUmFuZ2UgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2RhdGUvZGF0ZS1kZWNvcmF0b3IuZGF0YSc7XG5pbXBvcnQgeyBUaW1lIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERhdGVVdGlsaXRpZXMgfSBmcm9tICcuL2RhdGUudXRpbGl0aWVzJztcblxuLyoqXG4gKiBTaG93cyBpbmZvcm1hdGlvbiBhYm91dCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHR3byBlbnRpdGllcy5cbiAqL1xuaW50ZXJmYWNlIERpZmZlcmVuY2U8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4ge1xuICAgIC8qKlxuICAgICAqIFRoZSBrZXkgd2hlcmUgdGhlIHR3byBlbnRpdGllcyBoYXZlIGRpZmZlcmVudCB2YWx1ZXMuXG4gICAgICovXG4gICAga2V5OiBrZXlvZiBFbnRpdHlUeXBlLFxuICAgIC8qKlxuICAgICAqIFRoZSB2YWx1ZSBiZWZvcmUgYW55IGNoYW5nZXMuXG4gICAgICovXG4gICAgYmVmb3JlOiB1bmtub3duLFxuICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHZhbHVlIGFmdGVyIGNoYW5nZXMuXG4gICAgICovXG4gICAgYWZ0ZXI6IHVua25vd25cbn1cblxuLyoqXG4gKiBDb250YWlucyBIZWxwZXJNZXRob2RzIGFyb3VuZCBoYW5kbGluZyBFbnRpdGllcyBhbmQgdGhlaXIgcHJvcGVydHktbWV0YWRhdGEuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBFbnRpdHlVdGlsaXRpZXMge1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJvcGVydGllcyB0byBvbWl0IHdoZW4gdXBkYXRpbmcgdGhlIGVudGl0eS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIGdldCB0aGUgcHJvcGVydGllcyB3aGljaCBzaG91bGQgYmUgbGVmdCBvdXQgZm9yIHVwZGF0aW5nIGZyb20uXG4gICAgICogQHJldHVybnMgVGhlIHByb3BlcnRpZXMgd2hpY2ggc2hvdWxkIGJlIGxlZnQgb3V0IGZvciB1cGRhdGluZyBhbiBFbnRpdHkuXG4gICAgICovXG4gICAgc3RhdGljIGdldE9taXRGb3JVcGRhdGU8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4oZW50aXR5OiBFbnRpdHlUeXBlKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICBjb25zdCByZXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5KSkge1xuICAgICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgICAgICBpZiAobWV0YWRhdGEub21pdEZvclVwZGF0ZSkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0aWVzIHRvIG9taXQgd2hlbiBjcmVhdGluZyBuZXcgZW50aXRpZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBnZXQgdGhlIHByb3BlcnRpZXMgd2hpY2ggc2hvdWxkIGJlIGxlZnQgb3V0IGZvciBjcmVhdGluZyBmcm9tLlxuICAgICAqIEByZXR1cm5zIFRoZSBwcm9wZXJ0aWVzIHdoaWNoIHNob3VsZCBiZSBsZWZ0IG91dCBmb3IgY3JlYXRpbmcgYSBuZXcgRW50aXR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRPbWl0Rm9yQ3JlYXRlPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KGVudGl0eTogRW50aXR5VHlwZSk6IChrZXlvZiBFbnRpdHlUeXBlKVtdIHtcbiAgICAgICAgY29uc3QgcmVzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBFbnRpdHlVdGlsaXRpZXMua2V5c09mKGVudGl0eSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXkpO1xuICAgICAgICAgICAgaWYgKG1ldGFkYXRhLm9taXRGb3JDcmVhdGUpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbWV0YWRhdGEgaW5jbHVkZWQgaW4gYW4gcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB3aXRoIHRoZSBwcm9wZXJ0eSB0byBnZXQgdGhlIG1ldGFkYXRhIGZyb20uXG4gICAgICogQHBhcmFtIHByb3BlcnR5S2V5IC0gVGhlIHByb3BlcnR5IG9uIHRoZSBnaXZlbiBFbnRpdHkgdG8gZ2V0IHRoZSBtZXRhZGF0YSBmcm9tLlxuICAgICAqIEBwYXJhbSB0eXBlIC0gRm9yIHNlY3VyZSBUeXBpbmcsIGRlZmluZXMgdGhlIHJldHVybmVkIFByb3BlcnR5Q29uZmlnLlxuICAgICAqIEByZXR1cm5zIFRoZSBtZXRhZGF0YSBvZiB0aGUgcHJvcGVydHkuXG4gICAgICogQHRocm93cyBXaGVuIG5vIG1ldGFkYXRhIGNhbiBiZSBmb3VuZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQcm9wZXJ0eU1ldGFkYXRhPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3QsIFQgZXh0ZW5kcyBEZWNvcmF0b3JUeXBlcz4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgcHJvcGVydHlLZXk6IGtleW9mIEVudGl0eVR5cGUsXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgICAgdHlwZT86IFRcbiAgICApOiBEZWNvcmF0b3JUeXBlPFQ+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gUmVmbGVjdC5nZXRNZXRhZGF0YSgnbWV0YWRhdGEnLCBlbnRpdHksIHByb3BlcnR5S2V5IGFzIHN0cmluZykgYXMgRGVjb3JhdG9yVHlwZTxUPjtcbiAgICAgICAgICAgIGlmICghbWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGBDb3VsZCBub3QgZmluZCBtZXRhZGF0YSBmb3IgcHJvcGVydHkgJHtTdHJpbmcocHJvcGVydHlLZXkpfSBvbiB0aGUgZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoZW50aXR5KX1gXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgbWV0YWRhdGEgZm9yIHByb3BlcnR5ICR7U3RyaW5nKHByb3BlcnR5S2V5KX0gb24gdGhlIGVudGl0eSAke0pTT04uc3RyaW5naWZ5KGVudGl0eSl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHR5cGUgb2YgdGhlIHByb3BlcnR5LW1ldGFkYXRhLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgd2l0aCB0aGUgcHJvcGVydHkgdG8gZ2V0IHRoZSB0eXBlIGZyb20uXG4gICAgICogQHBhcmFtIHByb3BlcnR5S2V5IC0gVGhlIHByb3BlcnR5IG9uIHRoZSBnaXZlbiBFbnRpdHkgdG8gZ2V0IHRoZSB0eXBlIGZyb20uXG4gICAgICogQHJldHVybnMgVGhlIHR5cGUgb2YgdGhlIG1ldGFkYXRhLlxuICAgICAqIEB0aHJvd3MgV2lsbCB0aHJvdyBhbiBlcnJvciBpZiBubyBtZXRhZGF0YSBjYW4gYmUgZm91bmQgZm9yIHRoZSBnaXZlbiBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0UHJvcGVydHlUeXBlPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsIHByb3BlcnR5S2V5OiBrZXlvZiBFbnRpdHlUeXBlXG4gICAgKTogRGVjb3JhdG9yVHlwZXMge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcHJvcGVydHlUeXBlID0gUmVmbGVjdC5nZXRNZXRhZGF0YSgndHlwZScsIGVudGl0eSwgcHJvcGVydHlLZXkgYXMgc3RyaW5nKSBhcyBEZWNvcmF0b3JUeXBlcztcbiAgICAgICAgICAgIGlmICghcHJvcGVydHlUeXBlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgdHlwZSBtZXRhZGF0YSBmb3IgcHJvcGVydHkgJHtTdHJpbmcocHJvcGVydHlLZXkpfSBvbiB0aGUgZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoZW50aXR5KX1gXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwcm9wZXJ0eVR5cGU7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgYENvdWxkIG5vdCBmaW5kIHR5cGUgbWV0YWRhdGEgZm9yIHByb3BlcnR5ICR7U3RyaW5nKHByb3BlcnR5S2V5KX0gb24gdGhlIGVudGl0eSAke0pTT04uc3RyaW5naWZ5KGVudGl0eSl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgYWxsIHByb3BlcnR5IHZhbHVlcyBiYXNlZCBvbiBhIGdpdmVuIGVudGl0eSBkYXRhLW9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgdGFyZ2V0IG9iamVjdCB0aGF0IG5lZWRzIHRvIGJlIGNvbnN0cnVjdGVkIChpZiBjYWxsZWQgaW5zaWRlIGFuIEVudGl0eSBjb25zdHJ1Y3RvciBpdHMgdXN1YWxseSB0aGlzKS5cbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGRhdGEgb2JqZWN0IHRvIGdldCB0aGUgcHJvcGVydHkgdmFsdWVzIGZyb20uXG4gICAgICogQGFsaWFzIG5ld1xuICAgICAqIEBhbGlhcyBidWlsZFxuICAgICAqIEBhbGlhcyBjb25zdHJ1Y3RcbiAgICAgKi9cbiAgICBzdGF0aWMgbmV3PEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KHRhcmdldDogRW50aXR5VHlwZSwgZW50aXR5PzogRW50aXR5VHlwZSk6IHZvaWQge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0YXJnZXQpIHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlUeXBlKHRhcmdldCwga2V5KTtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnRcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IGVudGl0eSA/IFJlZmxlY3QuZ2V0KGVudGl0eSwga2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuT0JKRUNUOlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBvYmplY3RNZXRhZGF0YSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKHRhcmdldCwga2V5LCBEZWNvcmF0b3JUeXBlcy5PQkpFQ1QpO1xuICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hcmd1bWVudFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IG5ldyBvYmplY3RNZXRhZGF0YS5FbnRpdHlDbGFzcyh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVk6XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlucHV0QXJyYXk6IEVudGl0eVR5cGVbXSA9IHZhbHVlIGFzIEVudGl0eVR5cGVbXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzQXJyYXk6IEVudGl0eVR5cGVbXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyYXlNZXRhZGF0YSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKHRhcmdldCwga2V5LCBEZWNvcmF0b3JUeXBlcy5BUlJBWSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaW5wdXRBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1XaXRoTWV0YWRhdGE6IEVudGl0eVR5cGUgPSBuZXcgYXJyYXlNZXRhZGF0YS5FbnRpdHlDbGFzcyhpdGVtKSBhcyBFbnRpdHlUeXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc0FycmF5LnB1c2goaXRlbVdpdGhNZXRhZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSByZXNBcnJheTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBSZWZsZWN0LnNldCh0YXJnZXQsIGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbWVtYmVyLW9yZGVyaW5nLCBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgc3RhdGljIGNvbnN0cnVjdCA9IEVudGl0eVV0aWxpdGllcy5uZXc7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9tZW1iZXItb3JkZXJpbmcsIGpzZG9jL3JlcXVpcmUtanNkb2NcbiAgICBzdGF0aWMgYnVpbGQgPSBFbnRpdHlVdGlsaXRpZXMubmV3O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSB2YWx1ZXMgb24gYW4gZW50aXR5IGFyZSB2YWxpZC5cbiAgICAgKiBBbHNvIGNoZWNrcyBhbGwgdGhlIHZhbGlkYXRvcnMgZ2l2ZW4gYnkgdGhlIG1ldGFkYXRhIChcInJlcXVpcmVkXCIsIFwibWF4TGVuZ3RoXCIgZXRjLikuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byB2YWxpZGF0ZS5cbiAgICAgKiBAcGFyYW0gb21pdCAtIFdoZXRoZXIgdG8gY2hlY2sgZm9yIGNyZWF0aW5nIG9yIGVkaXRpbmcgdmFsaWRpdHkuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIGVudGl0eSBpcyB2YWxpZC5cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbnRpdHlWYWxpZDxFbnRpdHlUeXBlIGV4dGVuZHMgb2JqZWN0PihlbnRpdHk6IEVudGl0eVR5cGUsIG9taXQ6ICdjcmVhdGUnIHwgJ3VwZGF0ZScpOiBib29sZWFuIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZW50aXR5KSB7XG4gICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc1Byb3BlcnR5VmFsaWQoZW50aXR5LCBrZXksIG9taXQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYSBzaW5nbGUgcHJvcGVydHkgdmFsdWUgaXMgdmFsaWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB3aGVyZSB0aGUgcHJvcGVydHkgaXMgZnJvbS5cbiAgICAgKiBAcGFyYW0ga2V5IC0gVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5LlxuICAgICAqIEBwYXJhbSBvbWl0IC0gV2hldGhlciB0byBjaGVjayBpZiB0aGUgZ2l2ZW4gZW50aXR5IGlzIHZhbGlkIGZvciBjcmVhdGlvbiBvciB1cGRhdGluZy5cbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCB0aGUgcHJvcGVydHkgdmFsdWUgaXMgdmFsaWQuXG4gICAgICogQHRocm93cyBUaHJvd3Mgd2hlbiBpdCBleHRyYWN0cyBhbiB1bmtub3duIG1ldGFkYXRhIHR5cGUuXG4gICAgICovXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNQcm9wZXJ0eVZhbGlkPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGtleToga2V5b2YgRW50aXR5VHlwZSxcbiAgICAgICAgb21pdDogJ2NyZWF0ZScgfCAndXBkYXRlJ1xuICAgICk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB0eXBlID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5VHlwZShlbnRpdHksIGtleSk7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsID0gRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXksIHR5cGUpO1xuXG4gICAgICAgIGlmIChtZXRhZGF0YS5vbWl0Rm9yQ3JlYXRlICYmIG9taXQgPT09ICdjcmVhdGUnKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEub21pdEZvclVwZGF0ZSAmJiBvbWl0ID09PSAndXBkYXRlJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLnJlcXVpcmVkICYmICFlbnRpdHlba2V5XSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0RST1BET1dOOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX0NIRUNLQk9YOlxuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5CT09MRUFOX1RPR0dMRTpcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HX0RST1BET1dOOlxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5TVFJJTkc6XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLlNUUklOR19BVVRPQ09NUExFVEU6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5U3RyaW5nID0gZW50aXR5W2tleV0gYXMgdW5rbm93biBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyaW5nTWV0YWRhdGEgPSBtZXRhZGF0YSBhcyBEZWZhdWx0U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWw7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzU3RyaW5nVmFsaWQoZW50aXR5U3RyaW5nLCBzdHJpbmdNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuU1RSSU5HX1RFWFRCT1g6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5VGV4dGJveCA9IGVudGl0eVtrZXldIGFzIHVua25vd24gYXMgc3RyaW5nO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRleHRib3hNZXRhZGF0YSA9IG1ldGFkYXRhIGFzIFRleHRib3hTdHJpbmdEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNUZXh0Ym94VmFsaWQoZW50aXR5VGV4dGJveCwgdGV4dGJveE1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5OVU1CRVJfRFJPUERPV046XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLk5VTUJFUjpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlOdW1iZXIgPSBlbnRpdHlba2V5XSBhcyB1bmtub3duIGFzIG51bWJlcjtcbiAgICAgICAgICAgICAgICBjb25zdCBudW1iZXJNZXRhZGF0YSA9IG1ldGFkYXRhIGFzIERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbDtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNOdW1iZXJWYWxpZChlbnRpdHlOdW1iZXIsIG51bWJlck1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEZWNvcmF0b3JUeXBlcy5PQkpFQ1Q6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5T2JqZWN0ID0gZW50aXR5W2tleV0gYXMgdW5rbm93biBhcyBFbnRpdHlUeXBlO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGFyYW1ldGVyS2V5IGluIGVudGl0eU9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIUVudGl0eVV0aWxpdGllcy5pc1Byb3BlcnR5VmFsaWQoZW50aXR5T2JqZWN0LCBwYXJhbWV0ZXJLZXksIG9taXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkFSUkFZX1NUUklOR19DSElQUzpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVlfU1RSSU5HX0FVVE9DT01QTEVURV9DSElQUzpcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuQVJSQVk6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5QXJyYXkgPSBlbnRpdHlba2V5XSBhcyB1bmtub3duIGFzIFtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5TWV0YWRhdGEgPSBtZXRhZGF0YSBhcyBFbnRpdHlBcnJheURlY29yYXRvckNvbmZpZ0ludGVybmFsPEVudGl0eVR5cGU+O1xuICAgICAgICAgICAgICAgIGlmIChhcnJheU1ldGFkYXRhLnJlcXVpcmVkICYmICFlbnRpdHlBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRGVjb3JhdG9yVHlwZXMuREFURTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlEYXRlOiBEYXRlID0gbmV3IERhdGUoZW50aXR5W2tleV0gYXMgdW5rbm93biBhcyBEYXRlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRlTWV0YWRhdGEgPSBtZXRhZGF0YSBhcyBEZWZhdWx0RGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0RhdGVWYWxpZChlbnRpdHlEYXRlLCBkYXRlTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEVfUkFOR0U6XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXR5RGF0ZVJhbmdlOiBEYXRlUmFuZ2UgPSBjbG9uZURlZXAoZW50aXR5W2tleV0gYXMgdW5rbm93biBhcyBEYXRlUmFuZ2UpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGVSYW5nZU1ldGFkYXRhID0gbWV0YWRhdGEgYXMgRGF0ZVJhbmdlRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0RhdGVSYW5nZVZhbGlkKGVudGl0eURhdGVSYW5nZSwgZGF0ZVJhbmdlTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERlY29yYXRvclR5cGVzLkRBVEVfVElNRTpcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdHlEYXRlVGltZTogRGF0ZSA9IG5ldyBEYXRlKGVudGl0eVtrZXldIGFzIHVua25vd24gYXMgRGF0ZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZVRpbWVNZXRhZGF0YSA9IG1ldGFkYXRhIGFzIERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0RhdGVUaW1lVmFsaWQoZW50aXR5RGF0ZVRpbWUsIGRhdGVUaW1lTWV0YWRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHZhbGlkYXRlIHRoZSBpbnB1dCBiZWNhdXNlIHRoZSBEZWNvcmF0b3JUeXBlICR7dHlwZX0gaXMgbm90IGtub3duYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNTdHJpbmdWYWxpZCh2YWx1ZTogc3RyaW5nLCBtZXRhZGF0YTogRGVmYXVsdFN0cmluZ0RlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhMZW5ndGggJiYgdmFsdWUubGVuZ3RoID4gbWV0YWRhdGEubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbkxlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPCBtZXRhZGF0YS5taW5MZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEucmVnZXggJiYgIXZhbHVlLm1hdGNoKG1ldGFkYXRhLnJlZ2V4KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzVGV4dGJveFZhbGlkKHZhbHVlOiBzdHJpbmcsIG1ldGFkYXRhOiBUZXh0Ym94U3RyaW5nRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heExlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPiBtZXRhZGF0YS5tYXhMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWluTGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA8IG1ldGFkYXRhLm1pbkxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzTnVtYmVyVmFsaWQodmFsdWU6IG51bWJlciwgbWV0YWRhdGE6IERlZmF1bHROdW1iZXJEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWF4ICYmIHZhbHVlID4gbWV0YWRhdGEubWF4KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pbiAmJiB2YWx1ZSA8IG1ldGFkYXRhLm1pbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVZhbGlkKHZhbHVlOiBEYXRlLCBtZXRhZGF0YTogRGVmYXVsdERhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAobWV0YWRhdGEubWluICYmIHZhbHVlLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbih2YWx1ZSkuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGFkYXRhLm1heCAmJiB2YWx1ZS5nZXRUaW1lKCkgPiBtZXRhZGF0YS5tYXgodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXIgJiYgIW1ldGFkYXRhLmZpbHRlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpc0RhdGVSYW5nZVZhbGlkKHZhbHVlOiBEYXRlUmFuZ2UsIG1ldGFkYXRhOiBEYXRlUmFuZ2VEYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKG1ldGFkYXRhLnJlcXVpcmVkICYmICghdmFsdWUuc3RhcnQgfHwgIXZhbHVlLmVuZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZS5zdGFydCA9IG5ldyBEYXRlKHZhbHVlLnN0YXJ0KTtcbiAgICAgICAgdmFsdWUuZW5kID0gbmV3IERhdGUodmFsdWUuZW5kKTtcbiAgICAgICAgaWYgKG1ldGFkYXRhLm1pblN0YXJ0ICYmIHZhbHVlLnN0YXJ0LmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pblN0YXJ0KHZhbHVlLnN0YXJ0KS5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0YWRhdGEubWF4U3RhcnQgJiYgdmFsdWUuc3RhcnQuZ2V0VGltZSgpID4gbWV0YWRhdGEubWF4U3RhcnQodmFsdWUuc3RhcnQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5FbmQgJiYgdmFsdWUuZW5kLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbkVuZCh2YWx1ZS5lbmQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhFbmQgJiYgdmFsdWUuZW5kLmdldFRpbWUoKSA+IG1ldGFkYXRhLm1heEVuZCh2YWx1ZS5lbmQpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXIpIHtcbiAgICAgICAgICAgIGlmICghbWV0YWRhdGEuZmlsdGVyKHZhbHVlLnN0YXJ0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbWV0YWRhdGEuZmlsdGVyKHZhbHVlLmVuZCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUudmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBkYXRlIG9mIHZhbHVlLnZhbHVlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW1ldGFkYXRhLmZpbHRlcihkYXRlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVRpbWVWYWxpZCh2YWx1ZTogRGF0ZSwgbWV0YWRhdGE6IERhdGVUaW1lRGF0ZURlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5EYXRlICYmIHZhbHVlLmdldFRpbWUoKSA8IG1ldGFkYXRhLm1pbkRhdGUodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhEYXRlICYmIHZhbHVlLmdldFRpbWUoKSA+IG1ldGFkYXRhLm1heERhdGUodmFsdWUpLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXJEYXRlICYmICFtZXRhZGF0YS5maWx0ZXJEYXRlKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRpbWU6IFRpbWUgPSB7XG4gICAgICAgICAgICBob3VyczogdmFsdWUuZ2V0SG91cnMoKSxcbiAgICAgICAgICAgIG1pbnV0ZXM6IHZhbHVlLmdldE1pbnV0ZXMoKVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5taW5UaW1lKSB7XG4gICAgICAgICAgICBjb25zdCBtaW5UaW1lOiBUaW1lID0gbWV0YWRhdGEubWluVGltZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA+IG1pblRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgfHwgKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA9PT0gbWluVGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgICAgICAgICAgJiYgdGltZS5taW51dGVzID49IG1pblRpbWUubWludXRlc1xuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5tYXhUaW1lKSB7XG4gICAgICAgICAgICBjb25zdCBtYXhUaW1lOiBUaW1lID0gbWV0YWRhdGEubWF4VGltZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA8IG1heFRpbWUuaG91cnNcbiAgICAgICAgICAgICAgICAgICAgfHwgKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZS5ob3VycyA9PT0gbWF4VGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgICAgICAgICAgJiYgdGltZS5taW51dGVzIDw9IG1heFRpbWUubWludXRlc1xuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRhZGF0YS5maWx0ZXJUaW1lKSB7XG4gICAgICAgICAgICBpZiAoIW1ldGFkYXRhLmZpbHRlclRpbWUodGltZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGFuIGVudGl0eSBpcyBcImRpcnR5XCIgKGlmIGl0cyB2YWx1ZXMgaGF2ZSBjaGFuZ2VkKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IGFmdGVyIGFsbCBjaGFuZ2VzLlxuICAgICAqIEBwYXJhbSBlbnRpdHlQcmlvckNoYW5nZXMgLSBUaGUgZW50aXR5IGJlZm9yZSB0aGUgY2hhbmdlcy5cbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCB0aGUgZW50aXR5IGlzIGRpcnR5LlxuICAgICAqL1xuICAgIHN0YXRpYyBkaXJ0eTxFbnRpdHlUeXBlIGV4dGVuZHMgb2JqZWN0PihlbnRpdHk6IEVudGl0eVR5cGUsIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoIWVudGl0eVByaW9yQ2hhbmdlcykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZGlmZmVyZW5jZXMgPSB0aGlzLmRpZmZlcmVuY2VzRm9yRGlydHkoZW50aXR5LCBlbnRpdHlQcmlvckNoYW5nZXMpO1xuICAgICAgICAgICAgcmV0dXJuIGRpZmZlcmVuY2VzLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGRpZmZlcmVuY2VzRm9yRGlydHk8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgZW50aXR5UHJpb3JDaGFuZ2VzOiBFbnRpdHlUeXBlXG4gICAgKTogRGlmZmVyZW5jZTxFbnRpdHlUeXBlPltdIHtcbiAgICAgICAgY29uc3QgcmVzOiBEaWZmZXJlbmNlPEVudGl0eVR5cGU+W10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZW50aXR5KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNFcXVhbChlbnRpdHlba2V5XSwgZW50aXR5UHJpb3JDaGFuZ2VzW2tleV0sIEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KSkpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgICAgICAgICAgICBiZWZvcmU6IGVudGl0eVByaW9yQ2hhbmdlc1trZXldLFxuICAgICAgICAgICAgICAgICAgICBhZnRlcjogZW50aXR5W2tleV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXBhcmVzIHR3byBFbnRpdGllcyBhbmQgcmV0dXJucyB0aGVpciBkaWZmZXJlbmNlIGluIGFuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZmlyc3QgZW50aXR5IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIGVudGl0eVByaW9yQ2hhbmdlcyAtIFRoZSBzZWNvbmQgZW50aXR5IHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMgVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIEVudGl0aWVzIGluIGZvcm0gb2YgYSBQYXJ0aWFsLlxuICAgICAqL1xuICAgIHN0YXRpYyBkaWZmZXJlbmNlPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGVudGl0eVByaW9yQ2hhbmdlczogRW50aXR5VHlwZVxuICAgICk6IFBhcnRpYWw8RW50aXR5VHlwZT4ge1xuICAgICAgICBjb25zdCByZXM6IFBhcnRpYWw8RW50aXR5VHlwZT4gPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZW50aXR5KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNFcXVhbChlbnRpdHlba2V5XSwgZW50aXR5UHJpb3JDaGFuZ2VzW2tleV0sIEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5KSkpIHtcbiAgICAgICAgICAgICAgICByZXNba2V5XSA9IGVudGl0eVtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNFcXVhbCh2YWx1ZTogdW5rbm93biwgdmFsdWVQcmlvckNoYW5nZXM6IHVua25vd24sIG1ldGFkYXRhOiBQcm9wZXJ0eURlY29yYXRvckNvbmZpZ0ludGVybmFsKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICh0aGlzLmlzRGF0ZVJhbmdlKHZhbHVlKSAmJiB0aGlzLmlzRGF0ZVJhbmdlKHZhbHVlUHJpb3JDaGFuZ2VzKSkge1xuICAgICAgICAgICAgY29uc3QgZGF0ZVJhbmdlID0gY2xvbmVEZWVwKHZhbHVlKTtcbiAgICAgICAgICAgIGRhdGVSYW5nZS5zdGFydCA9IG5ldyBEYXRlKHZhbHVlLnN0YXJ0KTtcbiAgICAgICAgICAgIGRhdGVSYW5nZS5lbmQgPSBuZXcgRGF0ZSh2YWx1ZS5lbmQpO1xuICAgICAgICAgICAgZGF0ZVJhbmdlLnZhbHVlcyA9IERhdGVVdGlsaXRpZXMuZ2V0RGF0ZXNCZXR3ZWVuKFxuICAgICAgICAgICAgICAgIGRhdGVSYW5nZS5zdGFydCxcbiAgICAgICAgICAgICAgICBkYXRlUmFuZ2UuZW5kLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhIGFzIERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29uc3QgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzID0gY2xvbmVEZWVwKHZhbHVlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgICAgIGRhdGVSYW5nZVByaW9yQ2hhbmdlcy5zdGFydCA9IG5ldyBEYXRlKHZhbHVlUHJpb3JDaGFuZ2VzLnN0YXJ0KTtcbiAgICAgICAgICAgIGRhdGVSYW5nZVByaW9yQ2hhbmdlcy5lbmQgPSBuZXcgRGF0ZSh2YWx1ZVByaW9yQ2hhbmdlcy5lbmQpO1xuICAgICAgICAgICAgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzLnZhbHVlcyA9IERhdGVVdGlsaXRpZXMuZ2V0RGF0ZXNCZXR3ZWVuKFxuICAgICAgICAgICAgICAgIGRhdGVSYW5nZVByaW9yQ2hhbmdlcy5zdGFydCxcbiAgICAgICAgICAgICAgICBkYXRlUmFuZ2VQcmlvckNoYW5nZXMuZW5kLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhIGFzIERhdGVSYW5nZURhdGVEZWNvcmF0b3JDb25maWdJbnRlcm5hbFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBpc0VxdWFsKGRhdGVSYW5nZSwgZGF0ZVJhbmdlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKG1ldGFkYXRhIGFzIERlZmF1bHREYXRlRGVjb3JhdG9yQ29uZmlnSW50ZXJuYWwpLmRpc3BsYXlTdHlsZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoRGF0ZVV0aWxpdGllcy5hc0RhdGUodmFsdWUpKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGVQcmlvckNoYW5nZXMgPSBuZXcgRGF0ZShEYXRlVXRpbGl0aWVzLmFzRGF0ZSh2YWx1ZVByaW9yQ2hhbmdlcykpO1xuICAgICAgICAgICAgZGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgICAgICAgICAgIGRhdGVQcmlvckNoYW5nZXMuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgICAgICAgICByZXR1cm4gaXNFcXVhbChkYXRlLCBkYXRlUHJpb3JDaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNFcXVhbCh2YWx1ZSwgdmFsdWVQcmlvckNoYW5nZXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGlzRGF0ZVJhbmdlKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgRGF0ZVJhbmdlIHtcbiAgICAgICAgY29uc3QgZGF0ZVJhbmdlID0gdmFsdWUgYXMgRGF0ZVJhbmdlO1xuICAgICAgICBpZiAoZGF0ZVJhbmdlLnN0YXJ0ICYmIGRhdGVSYW5nZS5lbmQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbmV3IERhdGUoZGF0ZVJhbmdlLnN0YXJ0KTtcbiAgICAgICAgICAgICAgICBuZXcgRGF0ZShkYXRlUmFuZ2UuZW5kKVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7fTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZSBmdW5jdGlvbiBmb3Igc29ydGluZyBlbnRpdHkga2V5cyBieSB0aGVpciBvcmRlciB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhIC0gRmlyc3Qga2V5IG9mIGVudGl0eS5cbiAgICAgKiBAcGFyYW0gYiAtIFNlY29uZCBrZXkgb2YgZW50aXR5LlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBDdXJyZW50IGVudGl0eSAodXNlZCB0byBnZXQgbWV0YWRhdGEgb2YgZW50aXR5IGtleXMpLlxuICAgICAqIEByZXR1cm5zIDAgaWYgYm90aCB2YWx1ZXMgaGF2ZSB0aGUgc2FtZSBvcmRlciwgYSBuZWdhdGl2ZSB2YWx1ZSBpZiAnYScgY29tZXMgYmVmb3JlICdiJywgYSBwb3NpdGl2ZSB2YWx1ZSBpZiAnYScgY29tZXMgYmVoaW5kICdiJy5cbiAgICAgKi9cbiAgICBzdGF0aWMgY29tcGFyZU9yZGVyPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KGE6IGtleW9mIEVudGl0eVR5cGUsIGI6IGtleW9mIEVudGl0eVR5cGUsIGVudGl0eTogRW50aXR5VHlwZSk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhQSA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgYSk7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhQiA9IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgYik7XG5cbiAgICAgICAgaWYgKG1ldGFkYXRhQS5wb3NpdGlvbi5vcmRlciA9PT0gLTEpIHtcbiAgICAgICAgICAgIGlmIChtZXRhZGF0YUIucG9zaXRpb24ub3JkZXIgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChtZXRhZGF0YUIucG9zaXRpb24ub3JkZXIgPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKChtZXRhZGF0YUEucG9zaXRpb24ub3JkZXIgKSAtIChtZXRhZGF0YUIucG9zaXRpb24ub3JkZXIgKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgZm9yIFwibGdcIiwgXCJtZFwiLCBcInNtXCIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gRW50aXR5IHRvIGdldCB0aGUgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgb2YgdGhlIGtleS5cbiAgICAgKiBAcGFyYW0ga2V5IC0gS2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQgYm9vdHN0cmFwIGNvbHVtbiB2YWx1ZXMgZnJvbS5cbiAgICAgKiBAcGFyYW0gdHlwZSAtIERlZmluZXMgZm9yIHdoaWNoIHNjcmVlbiBzaXplIHRoZSBjb2x1bW4gdmFsdWVzIHNob3VsZCBiZSByZXR1cm5lZC5cbiAgICAgKiBAcmV0dXJucyBCb290c3RyYXAgY29sdW1uIHZhbHVlLlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRXaWR0aDxFbnRpdHlUeXBlIGV4dGVuZHMgb2JqZWN0PihlbnRpdHk6IEVudGl0eVR5cGUsIGtleToga2V5b2YgRW50aXR5VHlwZSwgdHlwZTogJ2xnJyB8ICdtZCcgfCAnc20nKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgbWV0YWRhdGEgPSBFbnRpdHlVdGlsaXRpZXMuZ2V0UHJvcGVydHlNZXRhZGF0YShlbnRpdHksIGtleSk7XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnbGcnOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzBdO1xuICAgICAgICAgICAgY2FzZSAnbWQnOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzFdO1xuICAgICAgICAgICAgY2FzZSAnc20nOlxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5kZWZhdWx0V2lkdGhzWzJdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzZXRzIGFsbCBjaGFuZ2VzIG9uIGFuIGVudGl0eS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBUaGUgZW50aXR5IHRvIHJlc2V0LlxuICAgICAqIEBwYXJhbSBlbnRpdHlQcmlvckNoYW5nZXMgLSBUaGUgZW50aXR5IGJlZm9yZSBhbnkgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzZXRDaGFuZ2VzT25FbnRpdHk8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4oZW50aXR5OiBFbnRpdHlUeXBlLCBlbnRpdHlQcmlvckNoYW5nZXM6IEVudGl0eVR5cGUpOiB2b2lkIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZW50aXR5UHJpb3JDaGFuZ2VzKSB7XG4gICAgICAgICAgICBSZWZsZWN0LnNldChlbnRpdHksIGtleSwgUmVmbGVjdC5nZXQoZW50aXR5UHJpb3JDaGFuZ2VzLCBrZXkpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJvd3MgdGhhdCBhcmUgdXNlZCB0byBkaXNwbGF5IHRoZSBnaXZlbiBlbnRpdHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBnZXQgdGhlIHJvd3MgZnJvbS5cbiAgICAgKiBAcGFyYW0gaGlkZU9taXRGb3JDcmVhdGUgLSBXaGV0aGVyIG9yIG5vdCBrZXlzIHdpdGggdGhlIG1ldGFkYXRhIG9taXRGb3JDcmVhdGUgc2hvdWxkIGJlIGZpbHRlcmVkIG91dC5cbiAgICAgKiBAcGFyYW0gaGlkZU9taXRGb3JFZGl0IC0gV2hldGhlciBvciBub3Qga2V5cyB3aXRoIHRoZSBtZXRhZGF0YSBvbWl0Rm9yVXBkYXRlIHNob3VsZCBiZSBmaWx0ZXJlZCBvdXQuXG4gICAgICogQHJldHVybnMgVGhlIHNvcnRlZCBSb3dzIGNvbnRhaW5pbmcgdGhlIHJvdyBudW1iZXIgYW5kIHRoZSBrZXlzIHRvIGRpc3BsYXkgaW4gdGhhdCByb3cuXG4gICAgICovXG4gICAgc3RhdGljIGdldEVudGl0eVJvd3M8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4oXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgaGlkZU9taXRGb3JDcmVhdGU6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAgICAgaGlkZU9taXRGb3JFZGl0OiBib29sZWFuID0gZmFsc2VcbiAgICApOiBFbnRpdHlSb3c8RW50aXR5VHlwZT5bXSB7XG4gICAgICAgIGNvbnN0IHJlczogRW50aXR5Um93PEVudGl0eVR5cGU+W10gPSBbXTtcblxuICAgICAgICBjb25zdCBrZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSA9IEVudGl0eVV0aWxpdGllcy5rZXlzT2YoZW50aXR5LCBoaWRlT21pdEZvckNyZWF0ZSwgaGlkZU9taXRGb3JFZGl0KTtcbiAgICAgICAgY29uc3QgbnVtYmVyT2ZSb3dzOiBudW1iZXIgPSB0aGlzLmdldE51bWJlck9mUm93czxFbnRpdHlUeXBlPihrZXlzLCBlbnRpdHkpO1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBudW1iZXJPZlJvd3M7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgcm93OiBFbnRpdHlSb3c8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICAgICAgcm93OiBpLFxuICAgICAgICAgICAgICAgIGtleXM6IHRoaXMuZ2V0S2V5c0ZvclJvdzxFbnRpdHlUeXBlPihrZXlzLCBlbnRpdHksIGkpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzLnB1c2gocm93KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsYXN0Um93OiBFbnRpdHlSb3c8RW50aXR5VHlwZT4gPSB7XG4gICAgICAgICAgICByb3c6IG51bWJlck9mUm93cyArIDEsXG4gICAgICAgICAgICBrZXlzOiB0aGlzLmdldEtleXNGb3JSb3c8RW50aXR5VHlwZT4oa2V5cywgZW50aXR5LCAtMSlcbiAgICAgICAgfTtcbiAgICAgICAgcmVzLnB1c2gobGFzdFJvdyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5c0ZvclJvdzxFbnRpdHlUeXBlIGV4dGVuZHMgb2JqZWN0PihcbiAgICAgICAga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10sXG4gICAgICAgIGVudGl0eTogRW50aXR5VHlwZSxcbiAgICAgICAgaTogbnVtYmVyXG4gICAgKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICByZXR1cm4ga2V5c1xuICAgICAgICAgICAgLmZpbHRlcihrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykucG9zaXRpb24ucm93ID09PSBpKVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IEVudGl0eVV0aWxpdGllcy5jb21wYXJlT3JkZXIoYSwgYiwgZW50aXR5KSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0TnVtYmVyT2ZSb3dzPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdLCBlbnRpdHk6IEVudGl0eVR5cGUpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4ga2V5c1xuICAgICAgICAgICAgLm1hcChrID0+IEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwgaykucG9zaXRpb24ucm93KVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IChhID4gYiA/IC0xIDogMSkpWzBdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGtleXMgb2YgdGhlIHByb3ZpZGVkIGVudGl0eSBjb3JyZWN0bHkgdHlwZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGVudGl0eSB0byBnZXQgdGhlIGtleXMgb2YuXG4gICAgICogQHBhcmFtIGhpZGVPbWl0Rm9yQ3JlYXRlIC0gV2hldGhlciBvciBub3Qga2V5cyB3aXRoIHRoZSBtZXRhZGF0YSBvbWl0Rm9yQ3JlYXRlIHNob3VsZCBiZSBmaWx0ZXJlZCBvdXQuXG4gICAgICogQHBhcmFtIGhpZGVPbWl0Rm9yRWRpdCAtIFdoZXRoZXIgb3Igbm90IGtleXMgd2l0aCB0aGUgbWV0YWRhdGEgb21pdEZvclVwZGF0ZSBzaG91bGQgYmUgZmlsdGVyZWQgb3V0LlxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIGtleXMgb2YgdGhlIGVudGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMga2V5c09mPEVudGl0eVR5cGUgZXh0ZW5kcyBvYmplY3Q+KFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGhpZGVPbWl0Rm9yQ3JlYXRlOiBib29sZWFuID0gZmFsc2UsXG4gICAgICAgIGhpZGVPbWl0Rm9yRWRpdDogYm9vbGVhbiA9IGZhbHNlXG4gICAgKTogKGtleW9mIEVudGl0eVR5cGUpW10ge1xuICAgICAgICBsZXQga2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBSZWZsZWN0Lm93bktleXMoZW50aXR5KSBhcyAoa2V5b2YgRW50aXR5VHlwZSlbXTtcbiAgICAgICAgaWYgKGhpZGVPbWl0Rm9yQ3JlYXRlKSB7XG4gICAgICAgICAgICBjb25zdCBvbWl0Rm9yQ3JlYXRlS2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMuZ2V0T21pdEZvckNyZWF0ZShlbnRpdHkpO1xuICAgICAgICAgICAga2V5cyA9IGtleXMuZmlsdGVyKGsgPT4gIW9taXRGb3JDcmVhdGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlkZU9taXRGb3JFZGl0KSB7XG4gICAgICAgICAgICBjb25zdCBvbWl0Rm9yVXBkYXRlS2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMuZ2V0T21pdEZvclVwZGF0ZShlbnRpdHkpO1xuICAgICAgICAgICAga2V5cyA9IGtleXMuZmlsdGVyKGsgPT4gIW9taXRGb3JVcGRhdGVLZXlzLmluY2x1ZGVzKGspKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ga2V5cztcbiAgICB9XG59XG5cbi8qKlxuICogQSByb3cgdGhhdCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0byBkaXNwbGF5IGFuIGVudGl0eS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlSb3c8RW50aXR5VHlwZSBleHRlbmRzIG9iamVjdD4ge1xuICAgIC8qKlxuICAgICAqIFRoZSByb3cgaW4gd2hpY2ggdGhpcyBzaG91bGQgYmUgZGlzcGxheWVkLlxuICAgICAqL1xuICAgIHJvdzogbnVtYmVyLFxuICAgIC8qKlxuICAgICAqIFRoZSBrZXlzIG9mIHRoZSB2YWx1ZXMgdGhhdCBzaG91bGQgYmUgZGlzcGxheWVkIGluIHRoYXQgcm93LlxuICAgICAqL1xuICAgIGtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdXG59Il19
|