@ng-formworks/core 17.2.7 → 17.3.0
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/LICENSE +21 -0
- package/README.md +833 -0
- package/esm2022/lib/framework-library/framework-library.service.mjs +175 -0
- package/esm2022/lib/framework-library/framework.mjs +15 -0
- package/esm2022/lib/framework-library/no-framework.component.mjs +18 -0
- package/esm2022/lib/framework-library/no-framework.module.mjs +27 -0
- package/esm2022/lib/framework-library/no.framework.mjs +19 -0
- package/esm2022/lib/json-schema-form.component.mjs +765 -0
- package/esm2022/lib/json-schema-form.module.mjs +26 -0
- package/esm2022/lib/json-schema-form.service.mjs +676 -0
- package/esm2022/lib/locale/de-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/en-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/es-validation-messages.mjs +57 -0
- package/esm2022/lib/locale/fr-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/index.mjs +8 -0
- package/esm2022/lib/locale/it-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/pt-validation-messages.mjs +60 -0
- package/esm2022/lib/locale/zh-validation-messages.mjs +60 -0
- package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +300 -0
- package/esm2022/lib/shared/form-group.functions.mjs +442 -0
- package/esm2022/lib/shared/format-regex.constants.mjs +54 -0
- package/esm2022/lib/shared/index.mjs +12 -0
- package/esm2022/lib/shared/json-schema.functions.mjs +784 -0
- package/esm2022/lib/shared/json.validators.mjs +884 -0
- package/esm2022/lib/shared/jsonpointer.functions.mjs +1026 -0
- package/esm2022/lib/shared/layout.functions.mjs +1154 -0
- package/esm2022/lib/shared/merge-schemas.function.mjs +345 -0
- package/esm2022/lib/shared/utility.functions.mjs +380 -0
- package/esm2022/lib/shared/validator.functions.mjs +584 -0
- package/esm2022/lib/widget-library/add-reference.component.mjs +61 -0
- package/esm2022/lib/widget-library/button.component.mjs +72 -0
- package/esm2022/lib/widget-library/checkbox.component.mjs +105 -0
- package/esm2022/lib/widget-library/checkboxes.component.mjs +147 -0
- package/esm2022/lib/widget-library/file.component.mjs +35 -0
- package/esm2022/lib/widget-library/hidden.component.mjs +54 -0
- package/esm2022/lib/widget-library/index.mjs +55 -0
- package/esm2022/lib/widget-library/input.component.mjs +119 -0
- package/esm2022/lib/widget-library/message.component.mjs +38 -0
- package/esm2022/lib/widget-library/none.component.mjs +21 -0
- package/esm2022/lib/widget-library/number.component.mjs +123 -0
- package/esm2022/lib/widget-library/one-of.component.mjs +35 -0
- package/esm2022/lib/widget-library/orderable.directive.mjs +123 -0
- package/esm2022/lib/widget-library/radios.component.mjs +153 -0
- package/esm2022/lib/widget-library/root.component.mjs +79 -0
- package/esm2022/lib/widget-library/section.component.mjs +199 -0
- package/esm2022/lib/widget-library/select-framework.component.mjs +51 -0
- package/esm2022/lib/widget-library/select-widget.component.mjs +46 -0
- package/esm2022/lib/widget-library/select.component.mjs +150 -0
- package/esm2022/lib/widget-library/submit.component.mjs +82 -0
- package/esm2022/lib/widget-library/tab.component.mjs +41 -0
- package/esm2022/lib/widget-library/tabs.component.mjs +108 -0
- package/esm2022/lib/widget-library/template.component.mjs +46 -0
- package/esm2022/lib/widget-library/textarea.component.mjs +104 -0
- package/esm2022/lib/widget-library/widget-library.module.mjs +42 -0
- package/esm2022/lib/widget-library/widget-library.service.mjs +226 -0
- package/esm2022/ng-formworks-core.mjs +5 -0
- package/esm2022/public_api.mjs +13 -0
- package/fesm2022/ng-formworks-core.mjs +10147 -0
- package/fesm2022/ng-formworks-core.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/framework-library/framework-library.service.d.ts +55 -0
- package/lib/framework-library/framework.d.ts +13 -0
- package/lib/framework-library/no-framework.component.d.ts +8 -0
- package/lib/framework-library/no-framework.module.d.ts +9 -0
- package/lib/framework-library/no.framework.d.ts +10 -0
- package/lib/json-schema-form.component.d.ts +218 -0
- package/lib/json-schema-form.module.d.ts +11 -0
- package/lib/json-schema-form.service.d.ts +115 -0
- package/lib/locale/de-validation-messages.d.ts +1 -0
- package/lib/locale/en-validation-messages.d.ts +1 -0
- package/lib/locale/es-validation-messages.d.ts +1 -0
- package/lib/locale/fr-validation-messages.d.ts +1 -0
- package/{src/lib/locale/index.ts → lib/locale/index.d.ts} +7 -7
- package/lib/locale/it-validation-messages.d.ts +1 -0
- package/lib/locale/pt-validation-messages.d.ts +1 -0
- package/lib/locale/zh-validation-messages.d.ts +1 -0
- package/lib/shared/convert-schema-to-draft6.function.d.ts +21 -0
- package/lib/shared/form-group.functions.d.ts +100 -0
- package/lib/shared/format-regex.constants.d.ts +19 -0
- package/lib/shared/index.d.ts +9 -0
- package/lib/shared/json-schema.functions.d.ts +193 -0
- package/lib/shared/json.validators.d.ts +441 -0
- package/lib/shared/jsonpointer.functions.d.ts +416 -0
- package/lib/shared/layout.functions.d.ts +83 -0
- package/lib/shared/merge-schemas.function.d.ts +19 -0
- package/lib/shared/utility.functions.d.ts +165 -0
- package/{src/lib/shared/validator.functions.ts → lib/shared/validator.functions.d.ts} +364 -601
- package/lib/widget-library/add-reference.component.d.ts +20 -0
- package/lib/widget-library/button.component.d.ts +21 -0
- package/lib/widget-library/checkbox.component.d.ts +24 -0
- package/lib/widget-library/checkboxes.component.d.ts +24 -0
- package/lib/widget-library/file.component.d.ts +21 -0
- package/lib/widget-library/hidden.component.d.ts +19 -0
- package/{src/lib/widget-library/index.ts → lib/widget-library/index.d.ts} +47 -56
- package/lib/widget-library/input.component.d.ts +22 -0
- package/lib/widget-library/message.component.d.ts +15 -0
- package/lib/widget-library/none.component.d.ts +8 -0
- package/lib/widget-library/number.component.d.ts +25 -0
- package/lib/widget-library/one-of.component.d.ts +21 -0
- package/lib/widget-library/orderable.directive.d.ts +41 -0
- package/lib/widget-library/radios.component.d.ts +23 -0
- package/lib/widget-library/root.component.d.ts +17 -0
- package/lib/widget-library/section.component.d.ts +19 -0
- package/lib/widget-library/select-framework.component.d.ts +18 -0
- package/lib/widget-library/select-widget.component.d.ts +18 -0
- package/lib/widget-library/select.component.d.ts +24 -0
- package/lib/widget-library/submit.component.d.ts +24 -0
- package/lib/widget-library/tab.component.d.ts +14 -0
- package/lib/widget-library/tabs.component.d.ts +20 -0
- package/lib/widget-library/template.component.d.ts +18 -0
- package/lib/widget-library/textarea.component.d.ts +21 -0
- package/lib/widget-library/widget-library.module.d.ts +31 -0
- package/lib/widget-library/widget-library.service.d.ts +22 -0
- package/package.json +64 -53
- package/{src/public_api.ts → public_api.d.ts} +9 -21
- package/karma.conf.js +0 -46
- package/ng-package.json +0 -11
- package/src/lib/framework-library/framework-library.service.ts +0 -195
- package/src/lib/framework-library/framework.ts +0 -11
- package/src/lib/framework-library/no-framework.component.html +0 -2
- package/src/lib/framework-library/no-framework.component.ts +0 -11
- package/src/lib/framework-library/no-framework.module.ts +0 -18
- package/src/lib/framework-library/no.framework.ts +0 -11
- package/src/lib/json-schema-form.component.html +0 -7
- package/src/lib/json-schema-form.component.ts +0 -809
- package/src/lib/json-schema-form.module.ts +0 -17
- package/src/lib/json-schema-form.service.ts +0 -907
- package/src/lib/locale/de-validation-messages.ts +0 -58
- package/src/lib/locale/en-validation-messages.ts +0 -58
- package/src/lib/locale/es-validation-messages.ts +0 -55
- package/src/lib/locale/fr-validation-messages.ts +0 -58
- package/src/lib/locale/it-validation-messages.ts +0 -58
- package/src/lib/locale/pt-validation-messages.ts +0 -58
- package/src/lib/locale/zh-validation-messages.ts +0 -58
- package/src/lib/locale-dates/en-US.ts +0 -5
- package/src/lib/shared/convert-schema-to-draft6.function.ts +0 -321
- package/src/lib/shared/form-group.functions.ts +0 -522
- package/src/lib/shared/format-regex.constants.ts +0 -73
- package/src/lib/shared/index.ts +0 -40
- package/src/lib/shared/json-schema.functions.ts +0 -788
- package/src/lib/shared/json.validators.ts +0 -878
- package/src/lib/shared/jsonpointer.functions.ts +0 -1012
- package/src/lib/shared/jspointer.functions.json.spec.ts +0 -103
- package/src/lib/shared/layout.functions.ts +0 -1233
- package/src/lib/shared/merge-schemas.function.ts +0 -329
- package/src/lib/shared/utility.functions.ts +0 -373
- package/src/lib/shared/validator.functions.spec.ts +0 -55
- package/src/lib/widget-library/add-reference.component.ts +0 -59
- package/src/lib/widget-library/button.component.ts +0 -54
- package/src/lib/widget-library/checkbox.component.ts +0 -74
- package/src/lib/widget-library/checkboxes.component.ts +0 -104
- package/src/lib/widget-library/file.component.ts +0 -36
- package/src/lib/widget-library/hidden.component.ts +0 -39
- package/src/lib/widget-library/input.component.ts +0 -76
- package/src/lib/widget-library/message.component.ts +0 -29
- package/src/lib/widget-library/none.component.ts +0 -12
- package/src/lib/widget-library/number.component.ts +0 -79
- package/src/lib/widget-library/one-of.component.ts +0 -36
- package/src/lib/widget-library/orderable.directive.ts +0 -130
- package/src/lib/widget-library/radios.component.ts +0 -101
- package/src/lib/widget-library/root.component.ts +0 -78
- package/src/lib/widget-library/section.component.ts +0 -133
- package/src/lib/widget-library/select-framework.component.ts +0 -50
- package/src/lib/widget-library/select-widget.component.ts +0 -46
- package/src/lib/widget-library/select.component.ts +0 -96
- package/src/lib/widget-library/submit.component.ts +0 -68
- package/src/lib/widget-library/tab.component.ts +0 -29
- package/src/lib/widget-library/tabs.component.ts +0 -83
- package/src/lib/widget-library/template.component.ts +0 -52
- package/src/lib/widget-library/textarea.component.ts +0 -68
- package/src/lib/widget-library/widget-library.module.ts +0 -13
- package/src/lib/widget-library/widget-library.service.ts +0 -234
- package/src/test.ts +0 -18
- package/tsconfig.lib.json +0 -25
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -17
- package/tslint.json +0 -11
|
@@ -0,0 +1,765 @@
|
|
|
1
|
+
import cloneDeep from 'lodash/cloneDeep';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, Input, Output, } from '@angular/core';
|
|
4
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
5
|
+
import { Subject } from 'rxjs';
|
|
6
|
+
import { takeUntil } from 'rxjs/operators';
|
|
7
|
+
import { JsonSchemaFormService } from './json-schema-form.service';
|
|
8
|
+
import { convertSchemaToDraft6 } from './shared/convert-schema-to-draft6.function';
|
|
9
|
+
import { resolveSchemaReferences } from './shared/json-schema.functions';
|
|
10
|
+
import { JsonPointer } from './shared/jsonpointer.functions';
|
|
11
|
+
import { forEach, hasOwn } from './shared/utility.functions';
|
|
12
|
+
import { hasValue, inArray, isArray, isEmpty, isObject } from './shared/validator.functions';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
import * as i1 from "./framework-library/framework-library.service";
|
|
15
|
+
import * as i2 from "./widget-library/widget-library.service";
|
|
16
|
+
import * as i3 from "./json-schema-form.service";
|
|
17
|
+
import * as i4 from "@angular/common";
|
|
18
|
+
import * as i5 from "@angular/forms";
|
|
19
|
+
import * as i6 from "./widget-library/root.component";
|
|
20
|
+
export const JSON_SCHEMA_FORM_VALUE_ACCESSOR = {
|
|
21
|
+
provide: NG_VALUE_ACCESSOR,
|
|
22
|
+
useExisting: forwardRef(() => JsonSchemaFormComponent),
|
|
23
|
+
multi: true,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* @module 'JsonSchemaFormComponent' - Angular JSON Schema Form
|
|
27
|
+
*
|
|
28
|
+
* Root module of the Angular JSON Schema Form client-side library,
|
|
29
|
+
* an Angular library which generates an HTML form from a JSON schema
|
|
30
|
+
* structured data model and/or a JSON Schema Form layout description.
|
|
31
|
+
*
|
|
32
|
+
* This library also validates input data by the user, using both validators on
|
|
33
|
+
* individual controls to provide real-time feedback while the user is filling
|
|
34
|
+
* out the form, and then validating the entire input against the schema when
|
|
35
|
+
* the form is submitted to make sure the returned JSON data object is valid.
|
|
36
|
+
*
|
|
37
|
+
* This library is similar to, and mostly API compatible with:
|
|
38
|
+
*
|
|
39
|
+
* - JSON Schema Form's Angular Schema Form library for AngularJs
|
|
40
|
+
* http://schemaform.io
|
|
41
|
+
* http://schemaform.io/examples/bootstrap-example.html (examples)
|
|
42
|
+
*
|
|
43
|
+
* - Mozilla's react-jsonschema-form library for React
|
|
44
|
+
* https://github.com/mozilla-services/react-jsonschema-form
|
|
45
|
+
* https://mozilla-services.github.io/react-jsonschema-form (examples)
|
|
46
|
+
*
|
|
47
|
+
* - Joshfire's JSON Form library for jQuery
|
|
48
|
+
* https://github.com/joshfire/jsonform
|
|
49
|
+
* http://ulion.github.io/jsonform/playground (examples)
|
|
50
|
+
*
|
|
51
|
+
* This library depends on:
|
|
52
|
+
* - Angular (obviously) https://angular.io
|
|
53
|
+
* - lodash, JavaScript utility library https://github.com/lodash/lodash
|
|
54
|
+
* - ajv, Another JSON Schema validator https://github.com/epoberezkin/ajv
|
|
55
|
+
*
|
|
56
|
+
* In addition, the Example Playground also depends on:
|
|
57
|
+
* - brace, Browserified Ace editor http://thlorenz.github.io/brace
|
|
58
|
+
*/
|
|
59
|
+
export class JsonSchemaFormComponent {
|
|
60
|
+
get value() {
|
|
61
|
+
return this.objectWrap ? this.jsf.data['1'] : this.jsf.data;
|
|
62
|
+
}
|
|
63
|
+
set value(value) {
|
|
64
|
+
this.setFormValues(value, false);
|
|
65
|
+
}
|
|
66
|
+
constructor(changeDetector, frameworkLibrary, widgetLibrary, jsf) {
|
|
67
|
+
this.changeDetector = changeDetector;
|
|
68
|
+
this.frameworkLibrary = frameworkLibrary;
|
|
69
|
+
this.widgetLibrary = widgetLibrary;
|
|
70
|
+
this.jsf = jsf;
|
|
71
|
+
// TODO: quickfix to avoid subscribing twice to the same emitters
|
|
72
|
+
this.unsubscribeOnActivateForm$ = new Subject();
|
|
73
|
+
this.formValueSubscription = null;
|
|
74
|
+
this.formInitialized = false;
|
|
75
|
+
this.objectWrap = false; // Is non-object input schema wrapped in an object?
|
|
76
|
+
this.previousInputs = {
|
|
77
|
+
schema: null, layout: null, data: null, options: null, framework: null,
|
|
78
|
+
widgets: null, form: null, model: null, JSONSchema: null, UISchema: null,
|
|
79
|
+
formData: null, loadExternalAssets: null, debug: null,
|
|
80
|
+
};
|
|
81
|
+
// Outputs
|
|
82
|
+
this.onChanges = new EventEmitter(); // Live unvalidated internal form data
|
|
83
|
+
this.onSubmit = new EventEmitter(); // Complete validated form data
|
|
84
|
+
this.isValid = new EventEmitter(); // Is current data valid?
|
|
85
|
+
this.validationErrors = new EventEmitter(); // Validation errors (if any)
|
|
86
|
+
this.formSchema = new EventEmitter(); // Final schema used to create form
|
|
87
|
+
this.formLayout = new EventEmitter(); // Final layout used to create form
|
|
88
|
+
// Outputs for possible 2-way data binding
|
|
89
|
+
// Only the one input providing the initial form data will be bound.
|
|
90
|
+
// If there is no inital data, input '{}' to activate 2-way data binding.
|
|
91
|
+
// There is no 2-way binding if inital data is combined inside the 'form' input.
|
|
92
|
+
this.dataChange = new EventEmitter();
|
|
93
|
+
this.modelChange = new EventEmitter();
|
|
94
|
+
this.formDataChange = new EventEmitter();
|
|
95
|
+
this.ngModelChange = new EventEmitter();
|
|
96
|
+
}
|
|
97
|
+
ngOnDestroy() {
|
|
98
|
+
this.dataChangesSubs?.unsubscribe();
|
|
99
|
+
this.statusChangesSubs?.unsubscribe();
|
|
100
|
+
this.isValidChangesSubs?.unsubscribe();
|
|
101
|
+
this.validationErrorChangesSubs?.unsubscribe();
|
|
102
|
+
this.dataChangesSubs = null;
|
|
103
|
+
this.statusChangesSubs = null;
|
|
104
|
+
this.isValidChangesSubs = null;
|
|
105
|
+
this.validationErrorChangesSubs = null;
|
|
106
|
+
}
|
|
107
|
+
resetScriptsAndStyleSheets() {
|
|
108
|
+
document.querySelectorAll('.ajsf').forEach(element => element.remove());
|
|
109
|
+
}
|
|
110
|
+
loadScripts(scriptList) {
|
|
111
|
+
const scripts = scriptList || this.frameworkLibrary.getFrameworkScripts();
|
|
112
|
+
scripts.map(script => {
|
|
113
|
+
const scriptTag = document.createElement('script');
|
|
114
|
+
scriptTag.src = script;
|
|
115
|
+
scriptTag.type = 'text/javascript';
|
|
116
|
+
scriptTag.async = true;
|
|
117
|
+
scriptTag.setAttribute('class', 'ajsf');
|
|
118
|
+
document.getElementsByTagName('head')[0].appendChild(scriptTag);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
loadStyleSheets(styleList) {
|
|
122
|
+
const stylesheets = styleList || this.frameworkLibrary.getFrameworkStylesheets();
|
|
123
|
+
stylesheets.map(stylesheet => {
|
|
124
|
+
const linkTag = document.createElement('link');
|
|
125
|
+
linkTag.rel = 'stylesheet';
|
|
126
|
+
linkTag.href = stylesheet;
|
|
127
|
+
linkTag.setAttribute('class', 'ajsf');
|
|
128
|
+
document.getElementsByTagName('head')[0].appendChild(linkTag);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
loadAssets() {
|
|
132
|
+
this.frameworkLibrary.getFrameworkAssetConfig().then(assetCfg => {
|
|
133
|
+
this.resetScriptsAndStyleSheets();
|
|
134
|
+
this.loadScripts(assetCfg.scripts);
|
|
135
|
+
this.loadStyleSheets(assetCfg.stylesheets);
|
|
136
|
+
}).catch(err => {
|
|
137
|
+
console.log(err);
|
|
138
|
+
this.resetScriptsAndStyleSheets();
|
|
139
|
+
this.loadScripts();
|
|
140
|
+
this.loadStyleSheets();
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
ngOnInit() {
|
|
144
|
+
this.updateForm();
|
|
145
|
+
this.loadAssets();
|
|
146
|
+
}
|
|
147
|
+
ngOnChanges(changes) {
|
|
148
|
+
this.updateForm();
|
|
149
|
+
// Check if there's changes in Framework then load assets if that's the
|
|
150
|
+
if (changes.framework) {
|
|
151
|
+
if (!changes.framework.isFirstChange() &&
|
|
152
|
+
(changes.framework.previousValue !== changes.framework.currentValue)) {
|
|
153
|
+
this.loadAssets();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
writeValue(value) {
|
|
158
|
+
this.setFormValues(value, false);
|
|
159
|
+
if (!this.formValuesInput) {
|
|
160
|
+
this.formValuesInput = 'ngModel';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
registerOnChange(fn) {
|
|
164
|
+
this.onChange = fn;
|
|
165
|
+
}
|
|
166
|
+
registerOnTouched(fn) {
|
|
167
|
+
this.onTouched = fn;
|
|
168
|
+
}
|
|
169
|
+
//see note
|
|
170
|
+
//https://angular.io/guide/update-to-version-15#v15-bc-06
|
|
171
|
+
setDisabledState(isDisabled) {
|
|
172
|
+
if (this.jsf.formOptions.formDisabled !== !!isDisabled) {
|
|
173
|
+
this.jsf.formOptions.formDisabled = !!isDisabled;
|
|
174
|
+
this.initializeForm();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
updateForm() {
|
|
178
|
+
let changedData;
|
|
179
|
+
if (!this.formInitialized || !this.formValuesInput ||
|
|
180
|
+
(this.language && this.language !== this.jsf.language)) {
|
|
181
|
+
this.initializeForm();
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
if (this.language && this.language !== this.jsf.language) {
|
|
185
|
+
this.jsf.setLanguage(this.language);
|
|
186
|
+
}
|
|
187
|
+
// Get names of changed inputs
|
|
188
|
+
let changedInput = Object.keys(this.previousInputs)
|
|
189
|
+
.filter(input => this.previousInputs[input] !== this[input]);
|
|
190
|
+
let resetFirst = true;
|
|
191
|
+
if (changedInput.length === 1 && changedInput[0] === 'form' &&
|
|
192
|
+
this.formValuesInput.startsWith('form.')) {
|
|
193
|
+
// If only 'form' input changed, get names of changed keys
|
|
194
|
+
changedInput = Object.keys(this.previousInputs.form || {})
|
|
195
|
+
.filter(key => !isEqual(this.previousInputs.form[key], this.form[key]))
|
|
196
|
+
.map(key => `form.${key}`);
|
|
197
|
+
resetFirst = false;
|
|
198
|
+
}
|
|
199
|
+
// If only input values have changed, update the form values
|
|
200
|
+
if (changedInput.length === 1 && changedInput[0] === this.formValuesInput) {
|
|
201
|
+
if (this.formValuesInput.indexOf('.') === -1) {
|
|
202
|
+
changedData = this[this.formValuesInput];
|
|
203
|
+
this.setFormValues(changedData, resetFirst);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const [input, key] = this.formValuesInput.split('.');
|
|
207
|
+
changedData = this[input][key];
|
|
208
|
+
this.setFormValues(changedData, resetFirst);
|
|
209
|
+
}
|
|
210
|
+
// If anything else has changed, re-render the entire form
|
|
211
|
+
}
|
|
212
|
+
else if (changedInput.length) {
|
|
213
|
+
this.initializeForm(changedData);
|
|
214
|
+
if (this.onChange) {
|
|
215
|
+
this.onChange(this.jsf.formValues);
|
|
216
|
+
}
|
|
217
|
+
if (this.onTouched) {
|
|
218
|
+
this.onTouched(this.jsf.formValues);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
//set framework theme
|
|
222
|
+
if (this.theme && this.theme !== this.frameworkLibrary.getActiveTheme()?.name) {
|
|
223
|
+
this.frameworkLibrary.requestThemeChange(this.theme);
|
|
224
|
+
}
|
|
225
|
+
// Update previous inputs
|
|
226
|
+
Object.keys(this.previousInputs)
|
|
227
|
+
.filter(input => this.previousInputs[input] !== this[input])
|
|
228
|
+
.forEach(input => this.previousInputs[input] = this[input]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
setFormValues(formValues, resetFirst = true) {
|
|
232
|
+
if (formValues) {
|
|
233
|
+
const newFormValues = this.objectWrap ? formValues['1'] : formValues;
|
|
234
|
+
if (!this.jsf.formGroup) {
|
|
235
|
+
this.jsf.formValues = formValues;
|
|
236
|
+
this.activateForm();
|
|
237
|
+
}
|
|
238
|
+
else if (resetFirst) { //changed to avoid reset events
|
|
239
|
+
this.jsf.formGroup.reset({}, { emitEvent: false });
|
|
240
|
+
}
|
|
241
|
+
if (this.jsf.formGroup) { //changed to avoid reset events
|
|
242
|
+
this.jsf.formGroup.patchValue(newFormValues, { emitEvent: false });
|
|
243
|
+
}
|
|
244
|
+
if (this.onChange) {
|
|
245
|
+
this.onChange(newFormValues);
|
|
246
|
+
}
|
|
247
|
+
if (this.onTouched) {
|
|
248
|
+
this.onTouched(newFormValues);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
this.jsf.formGroup.reset();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
submitForm() {
|
|
256
|
+
const validData = this.jsf.validData;
|
|
257
|
+
this.onSubmit.emit(this.objectWrap ? validData['1'] : validData);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* 'initializeForm' function
|
|
261
|
+
*
|
|
262
|
+
* - Update 'schema', 'layout', and 'formValues', from inputs.
|
|
263
|
+
*
|
|
264
|
+
* - Create 'schemaRefLibrary' and 'schemaRecursiveRefMap'
|
|
265
|
+
* to resolve schema $ref links, including recursive $ref links.
|
|
266
|
+
*
|
|
267
|
+
* - Create 'dataRecursiveRefMap' to resolve recursive links in data
|
|
268
|
+
* and corectly set output formats for recursively nested values.
|
|
269
|
+
*
|
|
270
|
+
* - Create 'layoutRefLibrary' and 'templateRefLibrary' to store
|
|
271
|
+
* new layout nodes and formGroup elements to use when dynamically
|
|
272
|
+
* adding form components to arrays and recursive $ref points.
|
|
273
|
+
*
|
|
274
|
+
* - Create 'dataMap' to map the data to the schema and template.
|
|
275
|
+
*
|
|
276
|
+
* - Create the master 'formGroupTemplate' then from it 'formGroup'
|
|
277
|
+
* the Angular formGroup used to control the reactive form.
|
|
278
|
+
*/
|
|
279
|
+
initializeForm(initialData) {
|
|
280
|
+
if (this.schema || this.layout || this.data || this.form || this.model ||
|
|
281
|
+
this.JSONSchema || this.UISchema || this.formData || this.ngModel ||
|
|
282
|
+
this.jsf.data) {
|
|
283
|
+
// Reset all form values to defaults
|
|
284
|
+
this.jsf.resetAllValues();
|
|
285
|
+
this.initializeOptions(); // Update options
|
|
286
|
+
this.initializeSchema(); // Update schema, schemaRefLibrary,
|
|
287
|
+
// schemaRecursiveRefMap, & dataRecursiveRefMap
|
|
288
|
+
this.initializeLayout(); // Update layout, layoutRefLibrary,
|
|
289
|
+
this.initializeData(); // Update formValues
|
|
290
|
+
if (initialData) {
|
|
291
|
+
this.jsf.formValues = initialData;
|
|
292
|
+
}
|
|
293
|
+
this.activateForm(); // Update dataMap, templateRefLibrary,
|
|
294
|
+
// formGroupTemplate, formGroup
|
|
295
|
+
// Uncomment individual lines to output debugging information to console:
|
|
296
|
+
// (These always work.)
|
|
297
|
+
// console.log('loading form...');
|
|
298
|
+
// console.log('schema', this.jsf.schema);
|
|
299
|
+
// console.log('layout', this.jsf.layout);
|
|
300
|
+
// console.log('options', this.options);
|
|
301
|
+
// console.log('formValues', this.jsf.formValues);
|
|
302
|
+
// console.log('formGroupTemplate', this.jsf.formGroupTemplate);
|
|
303
|
+
// console.log('formGroup', this.jsf.formGroup);
|
|
304
|
+
// console.log('formGroup.value', this.jsf.formGroup.value);
|
|
305
|
+
// console.log('schemaRefLibrary', this.jsf.schemaRefLibrary);
|
|
306
|
+
// console.log('layoutRefLibrary', this.jsf.layoutRefLibrary);
|
|
307
|
+
// console.log('templateRefLibrary', this.jsf.templateRefLibrary);
|
|
308
|
+
// console.log('dataMap', this.jsf.dataMap);
|
|
309
|
+
// console.log('arrayMap', this.jsf.arrayMap);
|
|
310
|
+
// console.log('schemaRecursiveRefMap', this.jsf.schemaRecursiveRefMap);
|
|
311
|
+
// console.log('dataRecursiveRefMap', this.jsf.dataRecursiveRefMap);
|
|
312
|
+
// Uncomment individual lines to output debugging information to browser:
|
|
313
|
+
// (These only work if the 'debug' option has also been set to 'true'.)
|
|
314
|
+
if (this.debug || this.jsf.formOptions.debug) {
|
|
315
|
+
const vars = [];
|
|
316
|
+
// vars.push(this.jsf.schema);
|
|
317
|
+
// vars.push(this.jsf.layout);
|
|
318
|
+
// vars.push(this.options);
|
|
319
|
+
// vars.push(this.jsf.formValues);
|
|
320
|
+
// vars.push(this.jsf.formGroup.value);
|
|
321
|
+
// vars.push(this.jsf.formGroupTemplate);
|
|
322
|
+
// vars.push(this.jsf.formGroup);
|
|
323
|
+
// vars.push(this.jsf.schemaRefLibrary);
|
|
324
|
+
// vars.push(this.jsf.layoutRefLibrary);
|
|
325
|
+
// vars.push(this.jsf.templateRefLibrary);
|
|
326
|
+
// vars.push(this.jsf.dataMap);
|
|
327
|
+
// vars.push(this.jsf.arrayMap);
|
|
328
|
+
// vars.push(this.jsf.schemaRecursiveRefMap);
|
|
329
|
+
// vars.push(this.jsf.dataRecursiveRefMap);
|
|
330
|
+
this.debugOutput = vars.map(v => JSON.stringify(v, null, 2)).join('\n');
|
|
331
|
+
}
|
|
332
|
+
this.formInitialized = true;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* 'initializeOptions' function
|
|
337
|
+
*
|
|
338
|
+
* Initialize 'options' (global form options) and set framework
|
|
339
|
+
* Combine available inputs:
|
|
340
|
+
* 1. options - recommended
|
|
341
|
+
* 2. form.options - Single input style
|
|
342
|
+
*/
|
|
343
|
+
initializeOptions() {
|
|
344
|
+
if (this.language && this.language !== this.jsf.language) {
|
|
345
|
+
this.jsf.setLanguage(this.language);
|
|
346
|
+
}
|
|
347
|
+
this.jsf.setOptions({ debug: !!this.debug });
|
|
348
|
+
let loadExternalAssets = this.loadExternalAssets || false;
|
|
349
|
+
let framework = this.framework || 'default';
|
|
350
|
+
if (isObject(this.options)) {
|
|
351
|
+
this.jsf.setOptions(this.options);
|
|
352
|
+
loadExternalAssets = this.options.loadExternalAssets || loadExternalAssets;
|
|
353
|
+
framework = this.options.framework || framework;
|
|
354
|
+
}
|
|
355
|
+
if (isObject(this.form) && isObject(this.form.options)) {
|
|
356
|
+
this.jsf.setOptions(this.form.options);
|
|
357
|
+
loadExternalAssets = this.form.options.loadExternalAssets || loadExternalAssets;
|
|
358
|
+
framework = this.form.options.framework || framework;
|
|
359
|
+
}
|
|
360
|
+
if (isObject(this.widgets)) {
|
|
361
|
+
this.jsf.setOptions({ widgets: this.widgets });
|
|
362
|
+
}
|
|
363
|
+
this.frameworkLibrary.setLoadExternalAssets(loadExternalAssets);
|
|
364
|
+
this.frameworkLibrary.setFramework(framework);
|
|
365
|
+
this.jsf.framework = this.frameworkLibrary.getFramework();
|
|
366
|
+
if (isObject(this.jsf.formOptions.widgets)) {
|
|
367
|
+
for (const widget of Object.keys(this.jsf.formOptions.widgets)) {
|
|
368
|
+
this.widgetLibrary.registerWidget(widget, this.jsf.formOptions.widgets[widget]);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (isObject(this.form) && isObject(this.form.tpldata)) {
|
|
372
|
+
this.jsf.setTpldata(this.form.tpldata);
|
|
373
|
+
}
|
|
374
|
+
if (this.theme) {
|
|
375
|
+
this.frameworkLibrary.requestThemeChange(this.theme);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 'initializeSchema' function
|
|
380
|
+
*
|
|
381
|
+
* Initialize 'schema'
|
|
382
|
+
* Use first available input:
|
|
383
|
+
* 1. schema - recommended / Angular Schema Form style
|
|
384
|
+
* 2. form.schema - Single input / JSON Form style
|
|
385
|
+
* 3. JSONSchema - React JSON Schema Form style
|
|
386
|
+
* 4. form.JSONSchema - For testing single input React JSON Schema Forms
|
|
387
|
+
* 5. form - For testing single schema-only inputs
|
|
388
|
+
*
|
|
389
|
+
* ... if no schema input found, the 'activateForm' function, below,
|
|
390
|
+
* will make two additional attempts to build a schema
|
|
391
|
+
* 6. If layout input - build schema from layout
|
|
392
|
+
* 7. If data input - build schema from data
|
|
393
|
+
*/
|
|
394
|
+
initializeSchema() {
|
|
395
|
+
// TODO: update to allow non-object schemas
|
|
396
|
+
if (isObject(this.schema)) {
|
|
397
|
+
this.jsf.AngularSchemaFormCompatibility = true;
|
|
398
|
+
this.jsf.schema = cloneDeep(this.schema);
|
|
399
|
+
}
|
|
400
|
+
else if (hasOwn(this.form, 'schema') && isObject(this.form.schema)) {
|
|
401
|
+
this.jsf.schema = cloneDeep(this.form.schema);
|
|
402
|
+
}
|
|
403
|
+
else if (isObject(this.JSONSchema)) {
|
|
404
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
405
|
+
this.jsf.schema = cloneDeep(this.JSONSchema);
|
|
406
|
+
}
|
|
407
|
+
else if (hasOwn(this.form, 'JSONSchema') && isObject(this.form.JSONSchema)) {
|
|
408
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
409
|
+
this.jsf.schema = cloneDeep(this.form.JSONSchema);
|
|
410
|
+
}
|
|
411
|
+
else if (hasOwn(this.form, 'properties') && isObject(this.form.properties)) {
|
|
412
|
+
this.jsf.schema = cloneDeep(this.form);
|
|
413
|
+
}
|
|
414
|
+
else if (isObject(this.form)) {
|
|
415
|
+
// TODO: Handle other types of form input
|
|
416
|
+
}
|
|
417
|
+
if (!isEmpty(this.jsf.schema)) {
|
|
418
|
+
// If other types also allowed, render schema as an object
|
|
419
|
+
if (inArray('object', this.jsf.schema.type)) {
|
|
420
|
+
this.jsf.schema.type = 'object';
|
|
421
|
+
}
|
|
422
|
+
// Wrap non-object schemas in object.
|
|
423
|
+
if (hasOwn(this.jsf.schema, 'type') && this.jsf.schema.type !== 'object') {
|
|
424
|
+
this.jsf.schema = {
|
|
425
|
+
'type': 'object',
|
|
426
|
+
'properties': { 1: this.jsf.schema }
|
|
427
|
+
};
|
|
428
|
+
this.objectWrap = true;
|
|
429
|
+
}
|
|
430
|
+
else if (!hasOwn(this.jsf.schema, 'type')) {
|
|
431
|
+
// Add type = 'object' if missing
|
|
432
|
+
if (isObject(this.jsf.schema.properties) ||
|
|
433
|
+
isObject(this.jsf.schema.patternProperties) ||
|
|
434
|
+
isObject(this.jsf.schema.additionalProperties)) {
|
|
435
|
+
this.jsf.schema.type = 'object';
|
|
436
|
+
// Fix JSON schema shorthand (JSON Form style)
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
this.jsf.JsonFormCompatibility = true;
|
|
440
|
+
this.jsf.schema = {
|
|
441
|
+
'type': 'object',
|
|
442
|
+
'properties': this.jsf.schema
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// If needed, update JSON Schema to draft 6 format, including
|
|
447
|
+
// draft 3 (JSON Form style) and draft 4 (Angular Schema Form style)
|
|
448
|
+
this.jsf.schema = convertSchemaToDraft6(this.jsf.schema);
|
|
449
|
+
// Initialize ajv and compile schema
|
|
450
|
+
this.jsf.compileAjvSchema();
|
|
451
|
+
// Create schemaRefLibrary, schemaRecursiveRefMap, dataRecursiveRefMap, & arrayMap
|
|
452
|
+
this.jsf.schema = resolveSchemaReferences(this.jsf.schema, this.jsf.schemaRefLibrary, this.jsf.schemaRecursiveRefMap, this.jsf.dataRecursiveRefMap, this.jsf.arrayMap);
|
|
453
|
+
if (hasOwn(this.jsf.schemaRefLibrary, '')) {
|
|
454
|
+
this.jsf.hasRootReference = true;
|
|
455
|
+
}
|
|
456
|
+
// TODO: (?) Resolve external $ref links
|
|
457
|
+
// // Create schemaRefLibrary & schemaRecursiveRefMap
|
|
458
|
+
// this.parser.bundle(this.schema)
|
|
459
|
+
// .then(schema => this.schema = resolveSchemaReferences(
|
|
460
|
+
// schema, this.jsf.schemaRefLibrary,
|
|
461
|
+
// this.jsf.schemaRecursiveRefMap, this.jsf.dataRecursiveRefMap
|
|
462
|
+
// ));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* 'initializeData' function
|
|
467
|
+
*
|
|
468
|
+
* Initialize 'formValues'
|
|
469
|
+
* defulat or previously submitted values used to populate form
|
|
470
|
+
* Use first available input:
|
|
471
|
+
* 1. data - recommended
|
|
472
|
+
* 2. model - Angular Schema Form style
|
|
473
|
+
* 3. form.value - JSON Form style
|
|
474
|
+
* 4. form.data - Single input style
|
|
475
|
+
* 5. formData - React JSON Schema Form style
|
|
476
|
+
* 6. form.formData - For easier testing of React JSON Schema Forms
|
|
477
|
+
* 7. (none) no data - initialize data from schema and layout defaults only
|
|
478
|
+
*/
|
|
479
|
+
initializeData() {
|
|
480
|
+
if (hasValue(this.data)) {
|
|
481
|
+
this.jsf.formValues = cloneDeep(this.data);
|
|
482
|
+
this.formValuesInput = 'data';
|
|
483
|
+
}
|
|
484
|
+
else if (hasValue(this.model)) {
|
|
485
|
+
this.jsf.AngularSchemaFormCompatibility = true;
|
|
486
|
+
this.jsf.formValues = cloneDeep(this.model);
|
|
487
|
+
this.formValuesInput = 'model';
|
|
488
|
+
}
|
|
489
|
+
else if (hasValue(this.ngModel)) {
|
|
490
|
+
this.jsf.AngularSchemaFormCompatibility = true;
|
|
491
|
+
this.jsf.formValues = cloneDeep(this.ngModel);
|
|
492
|
+
this.formValuesInput = 'ngModel';
|
|
493
|
+
}
|
|
494
|
+
else if (isObject(this.form) && hasValue(this.form.value)) {
|
|
495
|
+
this.jsf.JsonFormCompatibility = true;
|
|
496
|
+
this.jsf.formValues = cloneDeep(this.form.value);
|
|
497
|
+
this.formValuesInput = 'form.value';
|
|
498
|
+
}
|
|
499
|
+
else if (isObject(this.form) && hasValue(this.form.data)) {
|
|
500
|
+
this.jsf.formValues = cloneDeep(this.form.data);
|
|
501
|
+
this.formValuesInput = 'form.data';
|
|
502
|
+
}
|
|
503
|
+
else if (hasValue(this.formData)) {
|
|
504
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
505
|
+
this.formValuesInput = 'formData';
|
|
506
|
+
}
|
|
507
|
+
else if (hasOwn(this.form, 'formData') && hasValue(this.form.formData)) {
|
|
508
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
509
|
+
this.jsf.formValues = cloneDeep(this.form.formData);
|
|
510
|
+
this.formValuesInput = 'form.formData';
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
this.formValuesInput = "data"; //null;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* 'initializeLayout' function
|
|
518
|
+
*
|
|
519
|
+
* Initialize 'layout'
|
|
520
|
+
* Use first available array input:
|
|
521
|
+
* 1. layout - recommended
|
|
522
|
+
* 2. form - Angular Schema Form style
|
|
523
|
+
* 3. form.form - JSON Form style
|
|
524
|
+
* 4. form.layout - Single input style
|
|
525
|
+
* 5. (none) no layout - set default layout instead
|
|
526
|
+
* (full layout will be built later from the schema)
|
|
527
|
+
*
|
|
528
|
+
* Also, if alternate layout formats are available,
|
|
529
|
+
* import from 'UISchema' or 'customFormItems'
|
|
530
|
+
* used for React JSON Schema Form and JSON Form API compatibility
|
|
531
|
+
* Use first available input:
|
|
532
|
+
* 1. UISchema - React JSON Schema Form style
|
|
533
|
+
* 2. form.UISchema - For testing single input React JSON Schema Forms
|
|
534
|
+
* 2. form.customFormItems - JSON Form style
|
|
535
|
+
* 3. (none) no input - don't import
|
|
536
|
+
*/
|
|
537
|
+
initializeLayout() {
|
|
538
|
+
// Rename JSON Form-style 'options' lists to
|
|
539
|
+
// Angular Schema Form-style 'titleMap' lists.
|
|
540
|
+
const fixJsonFormOptions = (layout) => {
|
|
541
|
+
if (isObject(layout) || isArray(layout)) {
|
|
542
|
+
forEach(layout, (value, key) => {
|
|
543
|
+
if (hasOwn(value, 'options') && isObject(value.options)) {
|
|
544
|
+
value.titleMap = value.options;
|
|
545
|
+
delete value.options;
|
|
546
|
+
}
|
|
547
|
+
}, 'top-down');
|
|
548
|
+
}
|
|
549
|
+
return layout;
|
|
550
|
+
};
|
|
551
|
+
// Check for layout inputs and, if found, initialize form layout
|
|
552
|
+
if (isArray(this.layout)) {
|
|
553
|
+
this.jsf.layout = cloneDeep(this.layout);
|
|
554
|
+
}
|
|
555
|
+
else if (isArray(this.form)) {
|
|
556
|
+
this.jsf.AngularSchemaFormCompatibility = true;
|
|
557
|
+
this.jsf.layout = cloneDeep(this.form);
|
|
558
|
+
}
|
|
559
|
+
else if (this.form && isArray(this.form.form)) {
|
|
560
|
+
this.jsf.JsonFormCompatibility = true;
|
|
561
|
+
this.jsf.layout = fixJsonFormOptions(cloneDeep(this.form.form));
|
|
562
|
+
}
|
|
563
|
+
else if (this.form && isArray(this.form.layout)) {
|
|
564
|
+
this.jsf.layout = cloneDeep(this.form.layout);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
this.jsf.layout = ['*'];
|
|
568
|
+
}
|
|
569
|
+
// Check for alternate layout inputs
|
|
570
|
+
let alternateLayout = null;
|
|
571
|
+
if (isObject(this.UISchema)) {
|
|
572
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
573
|
+
alternateLayout = cloneDeep(this.UISchema);
|
|
574
|
+
}
|
|
575
|
+
else if (hasOwn(this.form, 'UISchema')) {
|
|
576
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
577
|
+
alternateLayout = cloneDeep(this.form.UISchema);
|
|
578
|
+
}
|
|
579
|
+
else if (hasOwn(this.form, 'uiSchema')) {
|
|
580
|
+
this.jsf.ReactJsonSchemaFormCompatibility = true;
|
|
581
|
+
alternateLayout = cloneDeep(this.form.uiSchema);
|
|
582
|
+
}
|
|
583
|
+
else if (hasOwn(this.form, 'customFormItems')) {
|
|
584
|
+
this.jsf.JsonFormCompatibility = true;
|
|
585
|
+
alternateLayout = fixJsonFormOptions(cloneDeep(this.form.customFormItems));
|
|
586
|
+
}
|
|
587
|
+
// if alternate layout found, copy alternate layout options into schema
|
|
588
|
+
if (alternateLayout) {
|
|
589
|
+
JsonPointer.forEachDeep(alternateLayout, (value, pointer) => {
|
|
590
|
+
const schemaPointer = pointer
|
|
591
|
+
.replace(/\//g, '/properties/')
|
|
592
|
+
.replace(/\/properties\/items\/properties\//g, '/items/properties/')
|
|
593
|
+
.replace(/\/properties\/titleMap\/properties\//g, '/titleMap/properties/');
|
|
594
|
+
if (hasValue(value) && hasValue(pointer)) {
|
|
595
|
+
let key = JsonPointer.toKey(pointer);
|
|
596
|
+
const groupPointer = (JsonPointer.parse(schemaPointer) || []).slice(0, -2);
|
|
597
|
+
let itemPointer;
|
|
598
|
+
// If 'ui:order' object found, copy into object schema root
|
|
599
|
+
if (key.toLowerCase() === 'ui:order') {
|
|
600
|
+
itemPointer = [...groupPointer, 'ui:order'];
|
|
601
|
+
// Copy other alternate layout options to schema 'x-schema-form',
|
|
602
|
+
// (like Angular Schema Form options) and remove any 'ui:' prefixes
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
if (key.slice(0, 3).toLowerCase() === 'ui:') {
|
|
606
|
+
key = key.slice(3);
|
|
607
|
+
}
|
|
608
|
+
itemPointer = [...groupPointer, 'x-schema-form', key];
|
|
609
|
+
}
|
|
610
|
+
if (JsonPointer.has(this.jsf.schema, groupPointer) &&
|
|
611
|
+
!JsonPointer.has(this.jsf.schema, itemPointer)) {
|
|
612
|
+
JsonPointer.set(this.jsf.schema, itemPointer, value);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* 'activateForm' function
|
|
620
|
+
*
|
|
621
|
+
* ...continued from 'initializeSchema' function, above
|
|
622
|
+
* If 'schema' has not been initialized (i.e. no schema input found)
|
|
623
|
+
* 6. If layout input - build schema from layout input
|
|
624
|
+
* 7. If data input - build schema from data input
|
|
625
|
+
*
|
|
626
|
+
* Create final layout,
|
|
627
|
+
* build the FormGroup template and the Angular FormGroup,
|
|
628
|
+
* subscribe to changes,
|
|
629
|
+
* and activate the form.
|
|
630
|
+
*/
|
|
631
|
+
activateForm() {
|
|
632
|
+
this.unsubscribeOnActivateForm$.next();
|
|
633
|
+
// If 'schema' not initialized
|
|
634
|
+
if (isEmpty(this.jsf.schema)) {
|
|
635
|
+
// TODO: If full layout input (with no '*'), build schema from layout
|
|
636
|
+
// if (!this.jsf.layout.includes('*')) {
|
|
637
|
+
// this.jsf.buildSchemaFromLayout();
|
|
638
|
+
// } else
|
|
639
|
+
// If data input, build schema from data
|
|
640
|
+
if (!isEmpty(this.jsf.formValues)) {
|
|
641
|
+
this.jsf.buildSchemaFromData();
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (!isEmpty(this.jsf.schema)) {
|
|
645
|
+
// If not already initialized, initialize ajv and compile schema
|
|
646
|
+
this.jsf.compileAjvSchema();
|
|
647
|
+
// Update all layout elements, add values, widgets, and validators,
|
|
648
|
+
// replace any '*' with a layout built from all schema elements,
|
|
649
|
+
// and update the FormGroup template with any new validators
|
|
650
|
+
this.jsf.buildLayout(this.widgetLibrary);
|
|
651
|
+
// Build the Angular FormGroup template from the schema
|
|
652
|
+
this.jsf.buildFormGroupTemplate(this.jsf.formValues);
|
|
653
|
+
// Build the real Angular FormGroup from the FormGroup template
|
|
654
|
+
this.jsf.buildFormGroup();
|
|
655
|
+
}
|
|
656
|
+
if (this.jsf.formGroup) {
|
|
657
|
+
// Reset initial form values
|
|
658
|
+
if (!isEmpty(this.jsf.formValues) &&
|
|
659
|
+
this.jsf.formOptions.setSchemaDefaults !== true &&
|
|
660
|
+
this.jsf.formOptions.setLayoutDefaults !== true) {
|
|
661
|
+
this.setFormValues(this.jsf.formValues);
|
|
662
|
+
}
|
|
663
|
+
// TODO: Figure out how to display calculated values without changing object data
|
|
664
|
+
// See http://ulion.github.io/jsonform/playground/?example=templating-values
|
|
665
|
+
// Calculate references to other fields
|
|
666
|
+
// if (!isEmpty(this.jsf.formGroup.value)) {
|
|
667
|
+
// forEach(this.jsf.formGroup.value, (value, key, object, rootObject) => {
|
|
668
|
+
// if (typeof value === 'string') {
|
|
669
|
+
// object[key] = this.jsf.parseText(value, value, rootObject, key);
|
|
670
|
+
// }
|
|
671
|
+
// }, 'top-down');
|
|
672
|
+
// }
|
|
673
|
+
// Subscribe to form changes to output live data, validation, and errors
|
|
674
|
+
this.dataChangesSubs = this.jsf.dataChanges.pipe(takeUntil(this.unsubscribeOnActivateForm$)).subscribe(data => {
|
|
675
|
+
this.onChanges.emit(this.objectWrap ? data['1'] : data);
|
|
676
|
+
if (this.formValuesInput && this.formValuesInput.indexOf('.') === -1) {
|
|
677
|
+
this[`${this.formValuesInput}Change`].emit(this.objectWrap ? data['1'] : data);
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
// Trigger change detection on statusChanges to show updated errors
|
|
681
|
+
this.statusChangesSubs = this.jsf.formGroup.statusChanges.pipe(takeUntil(this.unsubscribeOnActivateForm$)).subscribe(() => this.changeDetector.markForCheck());
|
|
682
|
+
this.isValidChangesSubs = this.jsf.isValidChanges.pipe(takeUntil(this.unsubscribeOnActivateForm$)).subscribe(isValid => this.isValid.emit(isValid));
|
|
683
|
+
this.validationErrorChangesSubs = this.jsf.validationErrorChanges.pipe(takeUntil(this.unsubscribeOnActivateForm$)).subscribe(err => this.validationErrors.emit(err));
|
|
684
|
+
// Output final schema, final layout, and initial data
|
|
685
|
+
this.formSchema.emit(this.jsf.schema);
|
|
686
|
+
this.formLayout.emit(this.jsf.layout);
|
|
687
|
+
this.onChanges.emit(this.objectWrap ? this.jsf.data['1'] : this.jsf.data);
|
|
688
|
+
// If validateOnRender, output initial validation and any errors
|
|
689
|
+
const validateOnRender = JsonPointer.get(this.jsf, '/formOptions/validateOnRender');
|
|
690
|
+
if (validateOnRender) { // validateOnRender === 'auto' || true
|
|
691
|
+
const touchAll = (control) => {
|
|
692
|
+
if (validateOnRender === true || hasValue(control.value)) {
|
|
693
|
+
control.markAsTouched();
|
|
694
|
+
}
|
|
695
|
+
Object.keys(control.controls || {})
|
|
696
|
+
.forEach(key => touchAll(control.controls[key]));
|
|
697
|
+
};
|
|
698
|
+
touchAll(this.jsf.formGroup);
|
|
699
|
+
this.isValid.emit(this.jsf.isValid);
|
|
700
|
+
this.validationErrors.emit(this.jsf.ajvErrors);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JsonSchemaFormComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.FrameworkLibraryService }, { token: i2.WidgetLibraryService }, { token: i3.JsonSchemaFormService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
705
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: JsonSchemaFormComponent, selector: "json-schema-form", inputs: { schema: "schema", layout: "layout", data: "data", options: "options", framework: "framework", widgets: "widgets", form: "form", model: "model", JSONSchema: "JSONSchema", UISchema: "UISchema", formData: "formData", ngModel: "ngModel", language: "language", loadExternalAssets: "loadExternalAssets", debug: "debug", theme: "theme", value: "value" }, outputs: { onChanges: "onChanges", onSubmit: "onSubmit", isValid: "isValid", validationErrors: "validationErrors", formSchema: "formSchema", formLayout: "formLayout", dataChange: "dataChange", modelChange: "modelChange", formDataChange: "formDataChange", ngModelChange: "ngModelChange" }, providers: [JsonSchemaFormService, JSON_SCHEMA_FORM_VALUE_ACCESSOR], usesOnChanges: true, ngImport: i0, template: "<form [autocomplete]=\"jsf?.formOptions?.autocomplete ? 'on' : 'off'\" class=\"json-schema-form\" (ngSubmit)=\"submitForm()\">\r\n <root-widget [layout]=\"jsf?.layout\"></root-widget>\r\n</form>\r\n<div *ngIf=\"debug || jsf?.formOptions?.debug\">\r\n Debug output:\r\n <pre>{{debugOutput}}</pre>\r\n</div>", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i6.RootComponent, selector: "root-widget", inputs: ["dataIndex", "layoutIndex", "layout", "isOrderable", "isFlexItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
706
|
+
}
|
|
707
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JsonSchemaFormComponent, decorators: [{
|
|
708
|
+
type: Component,
|
|
709
|
+
args: [{ selector: 'json-schema-form', changeDetection: ChangeDetectionStrategy.OnPush, providers: [JsonSchemaFormService, JSON_SCHEMA_FORM_VALUE_ACCESSOR], template: "<form [autocomplete]=\"jsf?.formOptions?.autocomplete ? 'on' : 'off'\" class=\"json-schema-form\" (ngSubmit)=\"submitForm()\">\r\n <root-widget [layout]=\"jsf?.layout\"></root-widget>\r\n</form>\r\n<div *ngIf=\"debug || jsf?.formOptions?.debug\">\r\n Debug output:\r\n <pre>{{debugOutput}}</pre>\r\n</div>" }]
|
|
710
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.FrameworkLibraryService }, { type: i2.WidgetLibraryService }, { type: i3.JsonSchemaFormService }], propDecorators: { schema: [{
|
|
711
|
+
type: Input
|
|
712
|
+
}], layout: [{
|
|
713
|
+
type: Input
|
|
714
|
+
}], data: [{
|
|
715
|
+
type: Input
|
|
716
|
+
}], options: [{
|
|
717
|
+
type: Input
|
|
718
|
+
}], framework: [{
|
|
719
|
+
type: Input
|
|
720
|
+
}], widgets: [{
|
|
721
|
+
type: Input
|
|
722
|
+
}], form: [{
|
|
723
|
+
type: Input
|
|
724
|
+
}], model: [{
|
|
725
|
+
type: Input
|
|
726
|
+
}], JSONSchema: [{
|
|
727
|
+
type: Input
|
|
728
|
+
}], UISchema: [{
|
|
729
|
+
type: Input
|
|
730
|
+
}], formData: [{
|
|
731
|
+
type: Input
|
|
732
|
+
}], ngModel: [{
|
|
733
|
+
type: Input
|
|
734
|
+
}], language: [{
|
|
735
|
+
type: Input
|
|
736
|
+
}], loadExternalAssets: [{
|
|
737
|
+
type: Input
|
|
738
|
+
}], debug: [{
|
|
739
|
+
type: Input
|
|
740
|
+
}], theme: [{
|
|
741
|
+
type: Input
|
|
742
|
+
}], value: [{
|
|
743
|
+
type: Input
|
|
744
|
+
}], onChanges: [{
|
|
745
|
+
type: Output
|
|
746
|
+
}], onSubmit: [{
|
|
747
|
+
type: Output
|
|
748
|
+
}], isValid: [{
|
|
749
|
+
type: Output
|
|
750
|
+
}], validationErrors: [{
|
|
751
|
+
type: Output
|
|
752
|
+
}], formSchema: [{
|
|
753
|
+
type: Output
|
|
754
|
+
}], formLayout: [{
|
|
755
|
+
type: Output
|
|
756
|
+
}], dataChange: [{
|
|
757
|
+
type: Output
|
|
758
|
+
}], modelChange: [{
|
|
759
|
+
type: Output
|
|
760
|
+
}], formDataChange: [{
|
|
761
|
+
type: Output
|
|
762
|
+
}], ngModelChange: [{
|
|
763
|
+
type: Output
|
|
764
|
+
}] } });
|
|
765
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi1zY2hlbWEtZm9ybS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1mb3Jtd29ya3MtY29yZS9zcmMvbGliL2pzb24tc2NoZW1hLWZvcm0uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZm9ybXdvcmtzLWNvcmUvc3JjL2xpYi9qc29uLXNjaGVtYS1mb3JtLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sU0FBUyxNQUFNLGtCQUFrQixDQUFDO0FBQ3pDLE9BQU8sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBRXJDLE9BQU8sRUFDTCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUlMLE1BQU0sR0FFUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQ25GLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFDTCxRQUFRLEVBQ1IsT0FBTyxFQUNQLE9BQU8sRUFDUCxPQUFPLEVBQ1AsUUFBUSxFQUNULE1BQU0sOEJBQThCLENBQUM7Ozs7Ozs7O0FBR3RDLE1BQU0sQ0FBQyxNQUFN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QUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0YsS0FBSztzQkFEUixLQUFLO2dCQVNJLFNBQVM7c0JBQWxCLE1BQU07Z0JBQ0csUUFBUTtzQkFBakIsTUFBTTtnQkFDRyxPQUFPO3NCQUFoQixNQUFNO2dCQUNHLGdCQUFnQjtzQkFBekIsTUFBTTtnQkFDRyxVQUFVO3NCQUFuQixNQUFNO2dCQUNHLFVBQVU7c0JBQW5CLE1BQU07Z0JBTUcsVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxXQUFXO3NCQUFwQixNQUFNO2dCQUNHLGNBQWM7c0JBQXZCLE1BQU07Z0JBQ0csYUFBYTtzQkFBdEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjbG9uZURlZXAgZnJvbSAnbG9kYXNoL2Nsb25lRGVlcCc7XHJcbmltcG9ydCBpc0VxdWFsIGZyb20gJ2xvZGFzaC9pc0VxdWFsJztcclxuXHJcbmltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBmb3J3YXJkUmVmLFxyXG4gIElucHV0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IEZyYW1ld29ya0xpYnJhcnlTZXJ2aWNlIH0gZnJvbSAnLi9mcmFtZXdvcmstbGlicmFyeS9mcmFtZXdvcmstbGlicmFyeS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSnNvblNjaGVtYUZvcm1TZXJ2aWNlIH0gZnJvbSAnLi9qc29uLXNjaGVtYS1mb3JtLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBjb252ZXJ0U2NoZW1hVG9EcmFmdDYgfSBmcm9tICcuL3NoYXJlZC9jb252ZXJ0LXNjaGVtYS10by1kcmFmdDYuZnVuY3Rpb24nO1xyXG5pbXBvcnQgeyByZXNvbHZlU2NoZW1hUmVmZXJlbmNlcyB9IGZyb20gJy4vc2hhcmVkL2pzb24tc2NoZW1hLmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7IEpzb25Qb2ludGVyIH0gZnJvbSAnLi9zaGFyZWQvanNvbnBvaW50ZXIuZnVuY3Rpb25zJztcclxuaW1wb3J0IHsgZm9yRWFjaCwgaGFzT3duIH0gZnJvbSAnLi9zaGFyZWQvdXRpbGl0eS5mdW5jdGlvbnMnO1xyXG5pbXBvcnQge1xyXG4gIGhhc1ZhbHVlLFxyXG4gIGluQXJyYXksXHJcbiAgaXNBcnJheSxcclxuICBpc0VtcHR5LFxyXG4gIGlzT2JqZWN0XHJcbn0gZnJvbSAnLi9zaGFyZWQvdmFsaWRhdG9yLmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7IFdpZGdldExpYnJhcnlTZXJ2aWNlIH0gZnJvbSAnLi93aWRnZXQtbGlicmFyeS93aWRnZXQtbGlicmFyeS5zZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBjb25zdCBKU09OX1NDSEVNQV9GT1JNX1ZBTFVFX0FDQ0VTU09SOiBhbnkgPSB7XHJcbiAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gSnNvblNjaGVtYUZvcm1Db21wb25lbnQpLFxyXG4gIG11bHRpOiB0cnVlLFxyXG59O1xyXG5cclxuLyoqXHJcbiAqIEBtb2R1bGUgJ0pzb25TY2hlbWFGb3JtQ29tcG9uZW50JyAtIEFuZ3VsYXIgSlNPTiBTY2hlbWEgRm9ybVxyXG4gKlxyXG4gKiBSb290IG1vZHVsZSBvZiB0aGUgQW5ndWxhciBKU09OIFNjaGVtYSBGb3JtIGNsaWVudC1zaWRlIGxpYnJhcnksXHJcbiAqIGFuIEFuZ3VsYXIgbGlicmFyeSB3aGljaCBnZW5lcmF0ZXMgYW4gSFRNTCBmb3JtIGZyb20gYSBKU09OIHNjaGVtYVxyXG4gKiBzdHJ1Y3R1cmVkIGRhdGEgbW9kZWwgYW5kL29yIGEgSlNPTiBTY2hlbWEgRm9ybSBsYXlvdXQgZGVzY3JpcHRpb24uXHJcbiAqXHJcbiAqIFRoaXMgbGlicmFyeSBhbHNvIHZhbGlkYXRlcyBpbnB1dCBkYXRhIGJ5IHRoZSB1c2VyLCB1c2luZyBib3RoIHZhbGlkYXRvcnMgb25cclxuICogaW5kaXZpZHVhbCBjb250cm9scyB0byBwcm92aWRlIHJlYWwtdGltZSBmZWVkYmFjayB3aGlsZSB0aGUgdXNlciBpcyBmaWxsaW5nXHJcbiAqIG91dCB0aGUgZm9ybSwgYW5kIHRoZW4gdmFsaWRhdGluZyB0aGUgZW50aXJlIGlucHV0IGFnYWluc3QgdGhlIHNjaGVtYSB3aGVuXHJcbiAqIHRoZSBmb3JtIGlzIHN1Ym1pdHRlZCB0byBtYWtlIHN1cmUgdGhlIHJldHVybmVkIEpTT04gZGF0YSBvYmplY3QgaXMgdmFsaWQuXHJcbiAqXHJcbiAqIFRoaXMgbGlicmFyeSBpcyBzaW1pbGFyIHRvLCBhbmQgbW9zdGx5IEFQSSBjb21wYXRpYmxlIHdpdGg6XHJcbiAqXHJcbiAqIC0gSlNPTiBTY2hlbWEgRm9ybSdzIEFuZ3VsYXIgU2NoZW1hIEZvcm0gbGlicmFyeSBmb3IgQW5ndWxhckpzXHJcbiAqICAgaHR0cDovL3NjaGVtYWZvcm0uaW9cclxuICogICBodHRwOi8vc2NoZW1hZm9ybS5pby9leGFtcGxlcy9ib290c3RyYXAtZXhhbXBsZS5odG1sIChleGFtcGxlcylcclxuICpcclxuICogLSBNb3ppbGxhJ3MgcmVhY3QtanNvbnNjaGVtYS1mb3JtIGxpYnJhcnkgZm9yIFJlYWN0XHJcbiAqICAgaHR0cHM6Ly9naXRodWIuY29tL21vemlsbGEtc2VydmljZXMvcmVhY3QtanNvbnNjaGVtYS1mb3JtXHJcbiAqICAgaHR0cHM6Ly9tb3ppbGxhLXNlcnZpY2VzLmdpdGh1Yi5pby9yZWFjdC1qc29uc2NoZW1hLWZvcm0gKGV4YW1wbGVzKVxyXG4gKlxyXG4gKiAtIEpvc2hmaXJlJ3MgSlNPTiBGb3JtIGxpYnJhcnkgZm9yIGpRdWVyeVxyXG4gKiAgIGh0dHBzOi8vZ2l0aHViLmNvbS9qb3NoZmlyZS9qc29uZm9ybVxyXG4gKiAgIGh0dHA6Ly91bGlvbi5naXRodWIuaW8vanNvbmZvcm0vcGxheWdyb3VuZCAoZXhhbXBsZXMpXHJcbiAqXHJcbiAqIFRoaXMgbGlicmFyeSBkZXBlbmRzIG9uOlxyXG4gKiAgLSBBbmd1bGFyIChvYnZpb3VzbHkpICAgICAgICAgICAgICAgICAgaHR0cHM6Ly9hbmd1bGFyLmlvXHJcbiAqICAtIGxvZGFzaCwgSmF2YVNjcmlwdCB1dGlsaXR5IGxpYnJhcnkgICBodHRwczovL2dpdGh1Yi5jb20vbG9kYXNoL2xvZGFzaFxyXG4gKiAgLSBhanYsIEFub3RoZXIgSlNPTiBTY2hlbWEgdmFsaWRhdG9yICAgaHR0cHM6Ly9naXRodWIuY29tL2Vwb2JlcmV6a2luL2FqdlxyXG4gKlxyXG4gKiBJbiBhZGRpdGlvbiwgdGhlIEV4YW1wbGUgUGxheWdyb3VuZCBhbHNvIGRlcGVuZHMgb246XHJcbiAqICAtIGJyYWNlLCBCcm93c2VyaWZpZWQgQWNlIGVkaXRvciAgICAgICBodHRwOi8vdGhsb3JlbnouZ2l0aHViLmlvL2JyYWNlXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Y29tcG9uZW50LXNlbGVjdG9yXHJcbiAgc2VsZWN0b3I6ICdqc29uLXNjaGVtYS1mb3JtJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vanNvbi1zY2hlbWEtZm9ybS5jb21wb25lbnQuaHRtbCcsXHJcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcbiAgLy8gQWRkaW5nICdKc29uU2NoZW1hRm9ybVNlcnZpY2UnIGhlcmUsIGluc3RlYWQgb2YgaW4gdGhlIG1vZHVsZSxcclxuICAvLyBjcmVhdGVzIGEgc2VwYXJhdGUgaW5zdGFuY2Ugb2YgdGhlIHNlcnZpY2UgZm9yIGVhY2ggY29tcG9uZW50XHJcbiAgcHJvdmlkZXJzOiAgWyBKc29uU2NoZW1hRm9ybVNlcnZpY2UsIEpTT05fU0NIRU1BX0ZPUk1fVkFMVUVfQUNDRVNTT1IgXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIEpzb25TY2hlbWFGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uQ2hhbmdlcywgT25Jbml0LE9uRGVzdHJveSB7XHJcbiAgLy8gVE9ETzogcXVpY2tmaXggdG8gYXZvaWQgc3Vic2NyaWJpbmcgdHdpY2UgdG8gdGhlIHNhbWUgZW1pdHRlcnNcclxuICBwcml2YXRlIHVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcclxuXHJcbiAgZGVidWdPdXRwdXQ6IGFueTsgLy8gRGVidWcgaW5mb3JtYXRpb24sIGlmIHJlcXVlc3RlZFxyXG4gIGZvcm1WYWx1ZVN1YnNjcmlwdGlvbjogYW55ID0gbnVsbDtcclxuICBmb3JtSW5pdGlhbGl6ZWQgPSBmYWxzZTtcclxuICBvYmplY3RXcmFwID0gZmFsc2U7IC8vIElzIG5vbi1vYmplY3QgaW5wdXQgc2NoZW1hIHdyYXBwZWQgaW4gYW4gb2JqZWN0P1xyXG5cclxuICBmb3JtVmFsdWVzSW5wdXQ6IHN0cmluZzsgLy8gTmFtZSBvZiB0aGUgaW5wdXQgcHJvdmlkaW5nIHRoZSBmb3JtIGRhdGFcclxuICBwcmV2aW91c0lucHV0czogeyAvLyBQcmV2aW91cyBpbnB1dCB2YWx1ZXMsIHRvIGRldGVjdCB3aGljaCBpbnB1dCB0cmlnZ2VycyBvbkNoYW5nZXNcclxuICAgIHNjaGVtYTogYW55LCBsYXlvdXQ6IGFueVtdLCBkYXRhOiBhbnksIG9wdGlvbnM6IGFueSwgZnJhbWV3b3JrOiBhbnkgfCBzdHJpbmcsXHJcbiAgICB3aWRnZXRzOiBhbnksIGZvcm06IGFueSwgbW9kZWw6IGFueSwgSlNPTlNjaGVtYTogYW55LCBVSVNjaGVtYTogYW55LFxyXG4gICAgZm9ybURhdGE6IGFueSwgbG9hZEV4dGVybmFsQXNzZXRzOiBib29sZWFuLCBkZWJ1ZzogYm9vbGVhbixcclxuICB9ID0ge1xyXG4gICAgICBzY2hlbWE6IG51bGwsIGxheW91dDogbnVsbCwgZGF0YTogbnVsbCwgb3B0aW9uczogbnVsbCwgZnJhbWV3b3JrOiBudWxsLFxyXG4gICAgICB3aWRnZXRzOiBudWxsLCBmb3JtOiBudWxsLCBtb2RlbDogbnVsbCwgSlNPTlNjaGVtYTogbnVsbCwgVUlTY2hlbWE6IG51bGwsXHJcbiAgICAgIGZvcm1EYXRhOiBudWxsLCBsb2FkRXh0ZXJuYWxBc3NldHM6IG51bGwsIGRlYnVnOiBudWxsLFxyXG4gICAgfTtcclxuXHJcbiAgLy8gUmVjb21tZW5kZWQgaW5wdXRzXHJcbiAgQElucHV0KCkgc2NoZW1hOiBhbnk7IC8vIFRoZSBKU09OIFNjaGVtYVxyXG4gIEBJbnB1dCgpIGxheW91dDogYW55W107IC8vIFRoZSBmb3JtIGxheW91dFxyXG4gIEBJbnB1dCgpIGRhdGE6IGFueTsgLy8gVGhlIGZvcm0gZGF0YVxyXG4gIEBJbnB1dCgpIG9wdGlvbnM6IGFueTsgLy8gVGhlIGdsb2JhbCBmb3JtIG9wdGlvbnNcclxuICBASW5wdXQoKSBmcmFtZXdvcms6IGFueSB8IHN0cmluZzsgLy8gVGhlIGZyYW1ld29yayB0byBsb2FkXHJcbiAgQElucHV0KCkgd2lkZ2V0czogYW55OyAvLyBBbnkgY3VzdG9tIHdpZGdldHMgdG8gbG9hZFxyXG5cclxuICAvLyBBbHRlcm5hdGUgY29tYmluZWQgc2luZ2xlIGlucHV0XHJcbiAgQElucHV0KCkgZm9ybTogYW55OyAvLyBGb3IgdGVzdGluZywgYW5kIEpTT04gU2NoZW1hIEZvcm0gQVBJIGNvbXBhdGliaWxpdHlcclxuXHJcbiAgLy8gQW5ndWxhciBTY2hlbWEgRm9ybSBBUEkgY29tcGF0aWJpbGl0eSBpbnB1dFxyXG4gIEBJbnB1dCgpIG1vZGVsOiBhbnk7IC8vIEFsdGVybmF0ZSBpbnB1dCBmb3IgZm9ybSBkYXRhXHJcblxyXG4gIC8vIFJlYWN0IEpTT04gU2NoZW1hIEZvcm0gQVBJIGNvbXBhdGliaWxpdHkgaW5wdXRzXHJcbiAgQElucHV0KCkgSlNPTlNjaGVtYTogYW55OyAvLyBBbHRlcm5hdGUgaW5wdXQgZm9yIEpTT04gU2NoZW1hXHJcbiAgQElucHV0KCkgVUlTY2hlbWE6IGFueTsgLy8gVUkgc2NoZW1hIC0gYWx0ZXJuYXRlIGZvcm0gbGF5b3V0IGZvcm1hdFxyXG4gIEBJbnB1dCgpIGZvcm1EYXRhOiBhbnk7IC8vIEFsdGVybmF0ZSBpbnB1dCBmb3IgZm9ybSBkYXRhXHJcblxyXG4gIEBJbnB1dCgpIG5nTW9kZWw6IGFueTsgLy8gQWx0ZXJuYXRlIGlucHV0IGZvciBBbmd1bGFyIGZvcm1zXHJcblxyXG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmc7IC8vIExhbmd1YWdlXHJcblxyXG4gIC8vIERldmVsb3BtZW50IGlucHV0cywgZm9yIHRlc3RpbmcgYW5kIGRlYnVnZ2luZ1xyXG4gIEBJbnB1dCgpIGxvYWRFeHRlcm5hbEFzc2V0czogYm9vbGVhbjsgLy8gTG9hZCBleHRlcm5hbCBmcmFtZXdvcmsgYXNzZXRzP1xyXG4gIEBJbnB1dCgpIGRlYnVnOiBib29sZWFuOyAvLyBTaG93IGRlYnVnIGluZm9ybWF0aW9uP1xyXG5cclxuICBASW5wdXQoKSB0aGVtZTogc3RyaW5nOyAvLyBUaGVtZVxyXG5cclxuICBASW5wdXQoKVxyXG4gIGdldCB2YWx1ZSgpOiBhbnkge1xyXG4gICAgcmV0dXJuIHRoaXMub2JqZWN0V3JhcCA/IHRoaXMuanNmLmRhdGFbJzEnXSA6IHRoaXMuanNmLmRhdGE7XHJcbiAgfVxyXG4gIHNldCB2YWx1ZSh2YWx1ZTogYW55KSB7XHJcbiAgICB0aGlzLnNldEZvcm1WYWx1ZXModmFsdWUsIGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8vIE91dHB1dHNcclxuICBAT3V0cHV0KCkgb25DaGFuZ2VzID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7IC8vIExpdmUgdW52YWxpZGF0ZWQgaW50ZXJuYWwgZm9ybSBkYXRhXHJcbiAgQE91dHB1dCgpIG9uU3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7IC8vIENvbXBsZXRlIHZhbGlkYXRlZCBmb3JtIGRhdGFcclxuICBAT3V0cHV0KCkgaXNWYWxpZCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTsgLy8gSXMgY3VycmVudCBkYXRhIHZhbGlkP1xyXG4gIEBPdXRwdXQoKSB2YWxpZGF0aW9uRXJyb3JzID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7IC8vIFZhbGlkYXRpb24gZXJyb3JzIChpZiBhbnkpXHJcbiAgQE91dHB1dCgpIGZvcm1TY2hlbWEgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTsgLy8gRmluYWwgc2NoZW1hIHVzZWQgdG8gY3JlYXRlIGZvcm1cclxuICBAT3V0cHV0KCkgZm9ybUxheW91dCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpOyAvLyBGaW5hbCBsYXlvdXQgdXNlZCB0byBjcmVhdGUgZm9ybVxyXG5cclxuICAvLyBPdXRwdXRzIGZvciBwb3NzaWJsZSAyLXdheSBkYXRhIGJpbmRpbmdcclxuICAvLyBPbmx5IHRoZSBvbmUgaW5wdXQgcHJvdmlkaW5nIHRoZSBpbml0aWFsIGZvcm0gZGF0YSB3aWxsIGJlIGJvdW5kLlxyXG4gIC8vIElmIHRoZXJlIGlzIG5vIGluaXRhbCBkYXRhLCBpbnB1dCAne30nIHRvIGFjdGl2YXRlIDItd2F5IGRhdGEgYmluZGluZy5cclxuICAvLyBUaGVyZSBpcyBubyAyLXdheSBiaW5kaW5nIGlmIGluaXRhbCBkYXRhIGlzIGNvbWJpbmVkIGluc2lkZSB0aGUgJ2Zvcm0nIGlucHV0LlxyXG4gIEBPdXRwdXQoKSBkYXRhQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIG1vZGVsQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIGZvcm1EYXRhQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIG5nTW9kZWxDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgb25DaGFuZ2U6IEZ1bmN0aW9uO1xyXG4gIG9uVG91Y2hlZDogRnVuY3Rpb247XHJcblxyXG4gIC8vVE9ETy1yZXZpZXcsbWF5YmUgdXNlIHRha2VVbnRpbERlc3Ryb3llZCByeGpzIG9wXHJcbiAgZGF0YUNoYW5nZXNTdWJzOlN1YnNjcmlwdGlvbjtcclxuICBzdGF0dXNDaGFuZ2VzU3ViczpTdWJzY3JpcHRpb247XHJcbiAgaXNWYWxpZENoYW5nZXNTdWJzOlN1YnNjcmlwdGlvbjtcclxuICB2YWxpZGF0aW9uRXJyb3JDaGFuZ2VzU3ViczpTdWJzY3JpcHRpb247XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgICBwcml2YXRlIGZyYW1ld29ya0xpYnJhcnk6IEZyYW1ld29ya0xpYnJhcnlTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB3aWRnZXRMaWJyYXJ5OiBXaWRnZXRMaWJyYXJ5U2VydmljZSxcclxuICAgIHB1YmxpYyBqc2Y6IEpzb25TY2hlbWFGb3JtU2VydmljZSxcclxuICApIHsgfVxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5kYXRhQ2hhbmdlc1N1YnM/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICB0aGlzLnN0YXR1c0NoYW5nZXNTdWJzPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5pc1ZhbGlkQ2hhbmdlc1N1YnM/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25FcnJvckNoYW5nZXNTdWJzPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5kYXRhQ2hhbmdlc1N1YnM9bnVsbDtcclxuICAgIHRoaXMuc3RhdHVzQ2hhbmdlc1N1YnM9bnVsbDtcclxuICAgIHRoaXMuaXNWYWxpZENoYW5nZXNTdWJzPW51bGw7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25FcnJvckNoYW5nZXNTdWJzPW51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2V0U2NyaXB0c0FuZFN0eWxlU2hlZXRzKCkge1xyXG4gICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmFqc2YnKS5mb3JFYWNoKGVsZW1lbnQgPT4gZWxlbWVudC5yZW1vdmUoKSk7XHJcbiAgfVxyXG4gIHByaXZhdGUgbG9hZFNjcmlwdHMoc2NyaXB0TGlzdD86c3RyaW5nW10pIHtcclxuICAgIGNvbnN0IHNjcmlwdHMgPSBzY3JpcHRMaXN0fHx0aGlzLmZyYW1ld29ya0xpYnJhcnkuZ2V0RnJhbWV3b3JrU2NyaXB0cygpO1xyXG4gICAgc2NyaXB0cy5tYXAoc2NyaXB0ID0+IHtcclxuICAgICAgY29uc3Qgc2NyaXB0VGFnOiBIVE1MU2NyaXB0RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xyXG4gICAgICBzY3JpcHRUYWcuc3JjID0gc2NyaXB0O1xyXG4gICAgICBzY3JpcHRUYWcudHlwZSA9ICd0ZXh0L2phdmFzY3JpcHQnO1xyXG4gICAgICBzY3JpcHRUYWcuYXN5bmMgPSB0cnVlO1xyXG4gICAgICBzY3JpcHRUYWcuc2V0QXR0cmlidXRlKCdjbGFzcycsICdhanNmJyk7XHJcbiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF0uYXBwZW5kQ2hpbGQoc2NyaXB0VGFnKTtcclxuICAgIH0pO1xyXG4gIH1cclxuICBwcml2YXRlIGxvYWRTdHlsZVNoZWV0cyhzdHlsZUxpc3Q/OnN0cmluZ1tdKSB7XHJcbiAgICBjb25zdCBzdHlsZXNoZWV0cyA9IHN0eWxlTGlzdHx8dGhpcy5mcmFtZXdvcmtMaWJyYXJ5LmdldEZyYW1ld29ya1N0eWxlc2hlZXRzKCk7XHJcbiAgICBzdHlsZXNoZWV0cy5tYXAoc3R5bGVzaGVldCA9PiB7XHJcbiAgICAgIGNvbnN0IGxpbmtUYWc6IEhUTUxMaW5rRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTtcclxuICAgICAgbGlua1RhZy5yZWwgPSAnc3R5bGVzaGVldCc7XHJcbiAgICAgIGxpbmtUYWcuaHJlZiA9IHN0eWxlc2hlZXQ7XHJcbiAgICAgIGxpbmtUYWcuc2V0QXR0cmlidXRlKCdjbGFzcycsICdhanNmJyk7XHJcbiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF0uYXBwZW5kQ2hpbGQobGlua1RhZyk7XHJcbiAgICB9KTtcclxuICB9XHJcbiAgcHJpdmF0ZSBsb2FkQXNzZXRzKCkge1xyXG4gICAgdGhpcy5mcmFtZXdvcmtMaWJyYXJ5LmdldEZyYW1ld29ya0Fzc2V0Q29uZmlnKCkudGhlbihhc3NldENmZz0+e1xyXG4gICAgICB0aGlzLnJlc2V0U2NyaXB0c0FuZFN0eWxlU2hlZXRzKCk7XHJcbiAgICAgIHRoaXMubG9hZFNjcmlwdHMoYXNzZXRDZmcuc2NyaXB0cyk7XHJcbiAgICAgIHRoaXMubG9hZFN0eWxlU2hlZXRzKGFzc2V0Q2ZnLnN0eWxlc2hlZXRzKTtcclxuICAgIH0pLmNhdGNoKGVycj0+e1xyXG4gICAgICBjb25zb2xlLmxvZyhlcnIpO1xyXG4gICAgICB0aGlzLnJlc2V0U2NyaXB0c0FuZFN0eWxlU2hlZXRzKCk7XHJcbiAgICAgIHRoaXMubG9hZFNjcmlwdHMoKTtcclxuICAgICAgdGhpcy5sb2FkU3R5bGVTaGVldHMoKTtcclxuICAgIH0pXHJcblxyXG4gIH1cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIHRoaXMudXBkYXRlRm9ybSgpO1xyXG4gICAgdGhpcy5sb2FkQXNzZXRzKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICB0aGlzLnVwZGF0ZUZvcm0oKTtcclxuICAgIC8vIENoZWNrIGlmIHRoZXJlJ3MgY2hhbmdlcyBpbiBGcmFtZXdvcmsgdGhlbiBsb2FkIGFzc2V0cyBpZiB0aGF0J3MgdGhlXHJcbiAgICBpZiAoY2hhbmdlcy5mcmFtZXdvcmspIHtcclxuICAgICAgaWYgKCFjaGFuZ2VzLmZyYW1ld29yay5pc0ZpcnN0Q2hhbmdlKCkgJiZcclxuICAgICAgICAoY2hhbmdlcy5mcmFtZXdvcmsucHJldmlvdXNWYWx1ZSAhPT0gY2hhbmdlcy5mcmFtZXdvcmsuY3VycmVudFZhbHVlKSkge1xyXG4gICAgICAgIHRoaXMubG9hZEFzc2V0cygpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpIHtcclxuICAgIHRoaXMuc2V0Rm9ybVZhbHVlcyh2YWx1ZSwgZmFsc2UpO1xyXG4gICAgaWYgKCF0aGlzLmZvcm1WYWx1ZXNJbnB1dCkgeyB0aGlzLmZvcm1WYWx1ZXNJbnB1dCA9ICduZ01vZGVsJzsgfVxyXG4gIH1cclxuXHJcbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogRnVuY3Rpb24pIHtcclxuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcclxuICB9XHJcblxyXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBGdW5jdGlvbikge1xyXG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcblxyXG4gIC8vc2VlIG5vdGVcclxuICAvL2h0dHBzOi8vYW5ndWxhci5pby9ndWlkZS91cGRhdGUtdG8tdmVyc2lvbi0xNSN2MTUtYmMtMDZcclxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcclxuICAgIGlmICh0aGlzLmpzZi5mb3JtT3B0aW9ucy5mb3JtRGlzYWJsZWQgIT09ICEhaXNEaXNhYmxlZCkge1xyXG4gICAgICB0aGlzLmpzZi5mb3JtT3B0aW9ucy5mb3JtRGlzYWJsZWQgPSAhIWlzRGlzYWJsZWQ7XHJcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUZvcm0oKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHVwZGF0ZUZvcm0oKSB7XHJcbiAgICAgIGxldCBjaGFuZ2VkRGF0YTtcclxuICAgIGlmICghdGhpcy5mb3JtSW5pdGlhbGl6ZWQgfHwgIXRoaXMuZm9ybVZhbHVlc0lucHV0IHx8XHJcbiAgICAgICh0aGlzLmxhbmd1YWdlICYmIHRoaXMubGFuZ3VhZ2UgIT09IHRoaXMuanNmLmxhbmd1YWdlKVxyXG4gICAgICBcclxuICAgICkge1xyXG4gICAgICB0aGlzLmluaXRpYWxpemVGb3JtKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5sYW5ndWFnZSAmJiB0aGlzLmxhbmd1YWdlICE9PSB0aGlzLmpzZi5sYW5ndWFnZSkge1xyXG4gICAgICAgIHRoaXMuanNmLnNldExhbmd1YWdlKHRoaXMubGFuZ3VhZ2UpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBHZXQgbmFtZXMgb2YgY2hhbmdlZCBpbnB1dHNcclxuICAgICAgbGV0IGNoYW5nZWRJbnB1dCA9IE9iamVjdC5rZXlzKHRoaXMucHJldmlvdXNJbnB1dHMpXHJcbiAgICAgICAgLmZpbHRlcihpbnB1dCA9PiB0aGlzLnByZXZpb3VzSW5wdXRzW2lucHV0XSAhPT0gdGhpc1tpbnB1dF0pO1xyXG4gICAgICBsZXQgcmVzZXRGaXJzdCA9IHRydWU7XHJcbiAgICAgIGlmIChjaGFuZ2VkSW5wdXQubGVuZ3RoID09PSAxICYmIGNoYW5nZWRJbnB1dFswXSA9PT0gJ2Zvcm0nICYmXHJcbiAgICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQuc3RhcnRzV2l0aCgnZm9ybS4nKVxyXG4gICAgICApIHtcclxuICAgICAgICAvLyBJZiBvbmx5ICdmb3JtJyBpbnB1dCBjaGFuZ2VkLCBnZXQgbmFtZXMgb2YgY2hhbmdlZCBrZXlzXHJcbiAgICAgICAgY2hhbmdlZElucHV0ID0gT2JqZWN0LmtleXModGhpcy5wcmV2aW91c0lucHV0cy5mb3JtIHx8IHt9KVxyXG4gICAgICAgICAgLmZpbHRlcihrZXkgPT4gIWlzRXF1YWwodGhpcy5wcmV2aW91c0lucHV0cy5mb3JtW2tleV0sIHRoaXMuZm9ybVtrZXldKSlcclxuICAgICAgICAgIC5tYXAoa2V5ID0+IGBmb3JtLiR7a2V5fWApO1xyXG4gICAgICAgIHJlc2V0Rmlyc3QgPSBmYWxzZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSWYgb25seSBpbnB1dCB2YWx1ZXMgaGF2ZSBjaGFuZ2VkLCB1cGRhdGUgdGhlIGZvcm0gdmFsdWVzXHJcbiAgICAgIGlmIChjaGFuZ2VkSW5wdXQubGVuZ3RoID09PSAxICYmIGNoYW5nZWRJbnB1dFswXSA9PT0gdGhpcy5mb3JtVmFsdWVzSW5wdXQpIHtcclxuICAgICAgICBpZiAodGhpcy5mb3JtVmFsdWVzSW5wdXQuaW5kZXhPZignLicpID09PSAtMSkge1xyXG4gICAgICAgICAgY2hhbmdlZERhdGE9dGhpc1t0aGlzLmZvcm1WYWx1ZXNJbnB1dF07XHJcbiAgICAgICAgICB0aGlzLnNldEZvcm1WYWx1ZXMoY2hhbmdlZERhdGEsIHJlc2V0Rmlyc3QpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBbaW5wdXQsIGtleV0gPSB0aGlzLmZvcm1WYWx1ZXNJbnB1dC5zcGxpdCgnLicpO1xyXG4gICAgICAgICAgY2hhbmdlZERhdGE9dGhpc1tpbnB1dF1ba2V5XTtcclxuICAgICAgICAgIHRoaXMuc2V0Rm9ybVZhbHVlcyhjaGFuZ2VkRGF0YSwgcmVzZXRGaXJzdCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBJZiBhbnl0aGluZyBlbHNlIGhhcyBjaGFuZ2VkLCByZS1yZW5kZXIgdGhlIGVudGlyZSBmb3JtXHJcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlZElucHV0Lmxlbmd0aCkge1xyXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZUZvcm0oY2hhbmdlZERhdGEpO1xyXG4gICAgICAgIGlmICh0aGlzLm9uQ2hhbmdlKSB7IHRoaXMub25DaGFuZ2UodGhpcy5qc2YuZm9ybVZhbHVlcyk7IH1cclxuICAgICAgICBpZiAodGhpcy5vblRvdWNoZWQpIHsgdGhpcy5vblRvdWNoZWQodGhpcy5qc2YuZm9ybVZhbHVlcyk7IH1cclxuICAgICAgfVxyXG4gICAgICBcclxuICAgICAgLy9zZXQgZnJhbWV3b3JrIHRoZW1lXHJcbiAgICAgIGlmICh0aGlzLnRoZW1lICYmIHRoaXMudGhlbWUgIT09IHRoaXMuZnJhbWV3b3JrTGlicmFyeS5nZXRBY3RpdmVUaGVtZSgpPy5uYW1lKSB7XHJcbiAgICAgICAgdGhpcy5mcmFtZXdvcmtMaWJyYXJ5LnJlcXVlc3RUaGVtZUNoYW5nZSh0aGlzLnRoZW1lKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gVXBkYXRlIHByZXZpb3VzIGlucHV0c1xyXG4gICAgICBPYmplY3Qua2V5cyh0aGlzLnByZXZpb3VzSW5wdXRzKVxyXG4gICAgICAgIC5maWx0ZXIoaW5wdXQgPT4gdGhpcy5wcmV2aW91c0lucHV0c1tpbnB1dF0gIT09IHRoaXNbaW5wdXRdKVxyXG4gICAgICAgIC5mb3JFYWNoKGlucHV0ID0+IHRoaXMucHJldmlvdXNJbnB1dHNbaW5wdXRdID0gdGhpc1tpbnB1dF0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2V0Rm9ybVZhbHVlcyhmb3JtVmFsdWVzOiBhbnksIHJlc2V0Rmlyc3QgPSB0cnVlKSB7XHJcbiAgICBpZiAoZm9ybVZhbHVlcykge1xyXG4gICAgICBjb25zdCBuZXdGb3JtVmFsdWVzID0gdGhpcy5vYmplY3RXcmFwID8gZm9ybVZhbHVlc1snMSddIDogZm9ybVZhbHVlcztcclxuICAgICAgaWYgKCF0aGlzLmpzZi5mb3JtR3JvdXApIHtcclxuICAgICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzID0gZm9ybVZhbHVlcztcclxuICAgICAgICB0aGlzLmFjdGl2YXRlRm9ybSgpO1xyXG4gICAgICB9IGVsc2UgaWYgKHJlc2V0Rmlyc3QpIHsvL2NoYW5nZWQgdG8gYXZvaWQgcmVzZXQgZXZlbnRzXHJcbiAgICAgICAgdGhpcy5qc2YuZm9ybUdyb3VwLnJlc2V0KHt9LHtlbWl0RXZlbnQ6ZmFsc2V9KTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5qc2YuZm9ybUdyb3VwKSB7Ly9jaGFuZ2VkIHRvIGF2b2lkIHJlc2V0IGV2ZW50c1xyXG4gICAgICAgIHRoaXMuanNmLmZvcm1Hcm91cC5wYXRjaFZhbHVlKG5ld0Zvcm1WYWx1ZXMse2VtaXRFdmVudDpmYWxzZX0pO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0aGlzLm9uQ2hhbmdlKSB7IHRoaXMub25DaGFuZ2UobmV3Rm9ybVZhbHVlcyk7IH1cclxuICAgICAgaWYgKHRoaXMub25Ub3VjaGVkKSB7IHRoaXMub25Ub3VjaGVkKG5ld0Zvcm1WYWx1ZXMpOyB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmpzZi5mb3JtR3JvdXAucmVzZXQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHN1Ym1pdEZvcm0oKSB7XHJcbiAgICBjb25zdCB2YWxpZERhdGEgPSB0aGlzLmpzZi52YWxpZERhdGE7XHJcbiAgICB0aGlzLm9uU3VibWl0LmVtaXQodGhpcy5vYmplY3RXcmFwID8gdmFsaWREYXRhWycxJ10gOiB2YWxpZERhdGEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2luaXRpYWxpemVGb3JtJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogLSBVcGRhdGUgJ3NjaGVtYScsICdsYXlvdXQnLCBhbmQgJ2Zvcm1WYWx1ZXMnLCBmcm9tIGlucHV0cy5cclxuICAgKlxyXG4gICAqIC0gQ3JlYXRlICdzY2hlbWFSZWZMaWJyYXJ5JyBhbmQgJ3NjaGVtYVJlY3Vyc2l2ZVJlZk1hcCdcclxuICAgKiAgIHRvIHJlc29sdmUgc2NoZW1hICRyZWYgbGlua3MsIGluY2x1ZGluZyByZWN1cnNpdmUgJHJlZiBsaW5rcy5cclxuICAgKlxyXG4gICAqIC0gQ3JlYXRlICdkYXRhUmVjdXJzaXZlUmVmTWFwJyB0byByZXNvbHZlIHJlY3Vyc2l2ZSBsaW5rcyBpbiBkYXRhXHJcbiAgICogICBhbmQgY29yZWN0bHkgc2V0IG91dHB1dCBmb3JtYXRzIGZvciByZWN1cnNpdmVseSBuZXN0ZWQgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLSBDcmVhdGUgJ2xheW91dFJlZkxpYnJhcnknIGFuZCAndGVtcGxhdGVSZWZMaWJyYXJ5JyB0byBzdG9yZVxyXG4gICAqICAgbmV3IGxheW91dCBub2RlcyBhbmQgZm9ybUdyb3VwIGVsZW1lbnRzIHRvIHVzZSB3aGVuIGR5bmFtaWNhbGx5XHJcbiAgICogICBhZGRpbmcgZm9ybSBjb21wb25lbnRzIHRvIGFycmF5cyBhbmQgcmVjdXJzaXZlICRyZWYgcG9pbnRzLlxyXG4gICAqXHJcbiAgICogLSBDcmVhdGUgJ2RhdGFNYXAnIHRvIG1hcCB0aGUgZGF0YSB0byB0aGUgc2NoZW1hIGFuZCB0ZW1wbGF0ZS5cclxuICAgKlxyXG4gICAqIC0gQ3JlYXRlIHRoZSBtYXN0ZXIgJ2Zvcm1Hcm91cFRlbXBsYXRlJyB0aGVuIGZyb20gaXQgJ2Zvcm1Hcm91cCdcclxuICAgKiAgIHRoZSBBbmd1bGFyIGZvcm1Hcm91cCB1c2VkIHRvIGNvbnRyb2wgdGhlIHJlYWN0aXZlIGZvcm0uXHJcbiAgICovXHJcbiAgaW5pdGlhbGl6ZUZvcm0oaW5pdGlhbERhdGE/OmFueSkge1xyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLnNjaGVtYSB8fCB0aGlzLmxheW91dCB8fCB0aGlzLmRhdGEgfHwgdGhpcy5mb3JtIHx8IHRoaXMubW9kZWwgfHxcclxuICAgICAgdGhpcy5KU09OU2NoZW1hIHx8IHRoaXMuVUlTY2hlbWEgfHwgdGhpcy5mb3JtRGF0YSB8fCB0aGlzLm5nTW9kZWwgfHxcclxuICAgICAgdGhpcy5qc2YuZGF0YVxyXG4gICAgKSB7XHJcbiAgICAgIC8vIFJlc2V0IGFsbCBmb3JtIHZhbHVlcyB0byBkZWZhdWx0c1xyXG4gICAgICB0aGlzLmpzZi5yZXNldEFsbFZhbHVlcygpO1xyXG4gICAgICB0aGlzLmluaXRpYWxpemVPcHRpb25zKCk7ICAgLy8gVXBkYXRlIG9wdGlvbnNcclxuICAgICAgdGhpcy5pbml0aWFsaXplU2NoZW1hKCk7ICAgIC8vIFVwZGF0ZSBzY2hlbWEsIHNjaGVtYVJlZkxpYnJhcnksXHJcbiAgICAgIC8vIHNjaGVtYVJlY3Vyc2l2ZVJlZk1hcCwgJiBkYXRhUmVjdXJzaXZlUmVmTWFwXHJcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUxheW91dCgpOyAgICAvLyBVcGRhdGUgbGF5b3V0LCBsYXlvdXRSZWZMaWJyYXJ5LFxyXG4gICAgICB0aGlzLmluaXRpYWxpemVEYXRhKCk7ICAgICAgLy8gVXBkYXRlIGZvcm1WYWx1ZXNcclxuICAgICAgaWYoaW5pdGlhbERhdGEpe1xyXG4gICAgICAgIHRoaXMuanNmLmZvcm1WYWx1ZXM9aW5pdGlhbERhdGE7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5hY3RpdmF0ZUZvcm0oKTsgICAgICAgIC8vIFVwZGF0ZSBkYXRhTWFwLCB0ZW1wbGF0ZVJlZkxpYnJhcnksXHJcbiAgICAgIC8vIGZvcm1Hcm91cFRlbXBsYXRlLCBmb3JtR3JvdXBcclxuXHJcbiAgICAgIC8vIFVuY29tbWVudCBpbmRpdmlkdWFsIGxpbmVzIHRvIG91dHB1dCBkZWJ1Z2dpbmcgaW5mb3JtYXRpb24gdG8gY29uc29sZTpcclxuICAgICAgLy8gKFRoZXNlIGFsd2F5cyB3b3JrLilcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2xvYWRpbmcgZm9ybS4uLicpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnc2NoZW1hJywgdGhpcy5qc2Yuc2NoZW1hKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2xheW91dCcsIHRoaXMuanNmLmxheW91dCk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdvcHRpb25zJywgdGhpcy5vcHRpb25zKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2Zvcm1WYWx1ZXMnLCB0aGlzLmpzZi5mb3JtVmFsdWVzKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2Zvcm1Hcm91cFRlbXBsYXRlJywgdGhpcy5qc2YuZm9ybUdyb3VwVGVtcGxhdGUpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnZm9ybUdyb3VwJywgdGhpcy5qc2YuZm9ybUdyb3VwKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2Zvcm1Hcm91cC52YWx1ZScsIHRoaXMuanNmLmZvcm1Hcm91cC52YWx1ZSk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdzY2hlbWFSZWZMaWJyYXJ5JywgdGhpcy5qc2Yuc2NoZW1hUmVmTGlicmFyeSk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdsYXlvdXRSZWZMaWJyYXJ5JywgdGhpcy5qc2YubGF5b3V0UmVmTGlicmFyeSk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCd0ZW1wbGF0ZVJlZkxpYnJhcnknLCB0aGlzLmpzZi50ZW1wbGF0ZVJlZkxpYnJhcnkpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnZGF0YU1hcCcsIHRoaXMuanNmLmRhdGFNYXApO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnYXJyYXlNYXAnLCB0aGlzLmpzZi5hcnJheU1hcCk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdzY2hlbWFSZWN1cnNpdmVSZWZNYXAnLCB0aGlzLmpzZi5zY2hlbWFSZWN1cnNpdmVSZWZNYXApO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnZGF0YVJlY3Vyc2l2ZVJlZk1hcCcsIHRoaXMuanNmLmRhdGFSZWN1cnNpdmVSZWZNYXApO1xyXG5cclxuICAgICAgLy8gVW5jb21tZW50IGluZGl2aWR1YWwgbGluZXMgdG8gb3V0cHV0IGRlYnVnZ2luZyBpbmZvcm1hdGlvbiB0byBicm93c2VyOlxyXG4gICAgICAvLyAoVGhlc2Ugb25seSB3b3JrIGlmIHRoZSAnZGVidWcnIG9wdGlvbiBoYXMgYWxzbyBiZWVuIHNldCB0byAndHJ1ZScuKVxyXG4gICAgICBpZiAodGhpcy5kZWJ1ZyB8fCB0aGlzLmpzZi5mb3JtT3B0aW9ucy5kZWJ1Zykge1xyXG4gICAgICAgIGNvbnN0IHZhcnM6IGFueVtdID0gW107XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLnNjaGVtYSk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmxheW91dCk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMub3B0aW9ucyk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmZvcm1WYWx1ZXMpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5mb3JtR3JvdXAudmFsdWUpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5mb3JtR3JvdXBUZW1wbGF0ZSk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmZvcm1Hcm91cCk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLnNjaGVtYVJlZkxpYnJhcnkpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5sYXlvdXRSZWZMaWJyYXJ5KTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YudGVtcGxhdGVSZWZMaWJyYXJ5KTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YuZGF0YU1hcCk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmFycmF5TWFwKTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2Yuc2NoZW1hUmVjdXJzaXZlUmVmTWFwKTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YuZGF0YVJlY3Vyc2l2ZVJlZk1hcCk7XHJcbiAgICAgICAgdGhpcy5kZWJ1Z091dHB1dCA9IHZhcnMubWFwKHYgPT4gSlNPTi5zdHJpbmdpZnkodiwgbnVsbCwgMikpLmpvaW4oJ1xcbicpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuZm9ybUluaXRpYWxpemVkID0gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdpbml0aWFsaXplT3B0aW9ucycgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEluaXRpYWxpemUgJ29wdGlvbnMnIChnbG9iYWwgZm9ybSBvcHRpb25zKSBhbmQgc2V0IGZyYW1ld29ya1xyXG4gICAqIENvbWJpbmUgYXZhaWxhYmxlIGlucHV0czpcclxuICAgKiAxLiBvcHRpb25zIC0gcmVjb21tZW5kZWRcclxuICAgKiAyLiBmb3JtLm9wdGlvbnMgLSBTaW5nbGUgaW5wdXQgc3R5bGVcclxuICAgKi9cclxuICBwcml2YXRlIGluaXRpYWxpemVPcHRpb25zKCkge1xyXG4gICAgaWYgKHRoaXMubGFuZ3VhZ2UgJiYgdGhpcy5sYW5ndWFnZSAhPT0gdGhpcy5qc2YubGFuZ3VhZ2UpIHtcclxuICAgICAgdGhpcy5qc2Yuc2V0TGFuZ3VhZ2UodGhpcy5sYW5ndWFnZSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmpzZi5zZXRPcHRpb25zKHsgZGVidWc6ICEhdGhpcy5kZWJ1ZyB9KTtcclxuICAgIGxldCBsb2FkRXh0ZXJuYWxBc3NldHM6IGJvb2xlYW4gPSB0aGlzLmxvYWRFeHRlcm5hbEFzc2V0cyB8fCBmYWxzZTtcclxuICAgIGxldCBmcmFtZXdvcms6IGFueSA9IHRoaXMuZnJhbWV3b3JrIHx8ICdkZWZhdWx0JztcclxuICAgIGlmIChpc09iamVjdCh0aGlzLm9wdGlvbnMpKSB7XHJcbiAgICAgIHRoaXMuanNmLnNldE9wdGlvbnModGhpcy5vcHRpb25zKTtcclxuICAgICAgbG9hZEV4dGVybmFsQXNzZXRzID0gdGhpcy5vcHRpb25zLmxvYWRFeHRlcm5hbEFzc2V0cyB8fCBsb2FkRXh0ZXJuYWxBc3NldHM7XHJcbiAgICAgIGZyYW1ld29yayA9IHRoaXMub3B0aW9ucy5mcmFtZXdvcmsgfHwgZnJhbWV3b3JrO1xyXG4gICAgfVxyXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMuZm9ybSkgJiYgaXNPYmplY3QodGhpcy5mb3JtLm9wdGlvbnMpKSB7XHJcbiAgICAgIHRoaXMuanNmLnNldE9wdGlvbnModGhpcy5mb3JtLm9wdGlvbnMpO1xyXG4gICAgICBsb2FkRXh0ZXJuYWxBc3NldHMgPSB0aGlzLmZvcm0ub3B0aW9ucy5sb2FkRXh0ZXJuYWxBc3NldHMgfHwgbG9hZEV4dGVybmFsQXNzZXRzO1xyXG4gICAgICBmcmFtZXdvcmsgPSB0aGlzLmZvcm0ub3B0aW9ucy5mcmFtZXdvcmsgfHwgZnJhbWV3b3JrO1xyXG4gICAgfVxyXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMud2lkZ2V0cykpIHtcclxuICAgICAgdGhpcy5qc2Yuc2V0T3B0aW9ucyh7IHdpZGdldHM6IHRoaXMud2lkZ2V0cyB9KTtcclxuICAgIH1cclxuICAgIHRoaXMuZnJhbWV3b3JrTGlicmFyeS5zZXRMb2FkRXh0ZXJuYWxBc3NldHMobG9hZEV4dGVybmFsQXNzZXRzKTtcclxuICAgIHRoaXMuZnJhbWV3b3JrTGlicmFyeS5zZXRGcmFtZXdvcmsoZnJhbWV3b3JrKTtcclxuICAgIHRoaXMuanNmLmZyYW1ld29yayA9IHRoaXMuZnJhbWV3b3JrTGlicmFyeS5nZXRGcmFtZXdvcmsoKTtcclxuICAgIGlmIChpc09iamVjdCh0aGlzLmpzZi5mb3JtT3B0aW9ucy53aWRnZXRzKSkge1xyXG4gICAgICBmb3IgKGNvbnN0IHdpZGdldCBvZiBPYmplY3Qua2V5cyh0aGlzLmpzZi5mb3JtT3B0aW9ucy53aWRnZXRzKSkge1xyXG4gICAgICAgIHRoaXMud2lkZ2V0TGlicmFyeS5yZWdpc3RlcldpZGdldCh3aWRnZXQsIHRoaXMuanNmLmZvcm1PcHRpb25zLndpZGdldHNbd2lkZ2V0XSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChpc09iamVjdCh0aGlzLmZvcm0pICYmIGlzT2JqZWN0KHRoaXMuZm9ybS50cGxkYXRhKSkge1xyXG4gICAgICB0aGlzLmpzZi5zZXRUcGxkYXRhKHRoaXMuZm9ybS50cGxkYXRhKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLnRoZW1lKSB7XHJcbiAgICAgIHRoaXMuZnJhbWV3b3JrTGlicmFyeS5yZXF1ZXN0VGhlbWVDaGFuZ2UodGhpcy50aGVtZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogJ2luaXRpYWxpemVTY2hlbWEnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBJbml0aWFsaXplICdzY2hlbWEnXHJcbiAgICogVXNlIGZpcnN0IGF2YWlsYWJsZSBpbnB1dDpcclxuICAgKiAxLiBzY2hlbWEgLSByZWNvbW1lbmRlZCAvIEFuZ3VsYXIgU2NoZW1hIEZvcm0gc3R5bGVcclxuICAgKiAyLiBmb3JtLnNjaGVtYSAtIFNpbmdsZSBpbnB1dCAvIEpTT04gRm9ybSBzdHlsZVxyXG4gICAqIDMuIEpTT05TY2hlbWEgLSBSZWFjdCBKU09OIFNjaGVtYSBGb3JtIHN0eWxlXHJcbiAgICogNC4gZm9ybS5KU09OU2NoZW1hIC0gRm9yIHRlc3Rpbmcgc2luZ2xlIGlucHV0IFJlYWN0IEpTT04gU2NoZW1hIEZvcm1zXHJcbiAgICogNS4gZm9ybSAtIEZvciB0ZXN0aW5nIHNpbmdsZSBzY2hlbWEtb25seSBpbnB1dHNcclxuICAgKlxyXG4gICAqIC4uLiBpZiBubyBzY2hlbWEgaW5wdXQgZm91bmQsIHRoZSAnYWN0aXZhdGVGb3JtJyBmdW5jdGlvbiwgYmVsb3csXHJcbiAgICogICAgIHdpbGwgbWFrZSB0d28gYWRkaXRpb25hbCBhdHRlbXB0cyB0byBidWlsZCBhIHNjaGVtYVxyXG4gICAqIDYuIElmIGxheW91dCBpbnB1dCAtIGJ1aWxkIHNjaGVtYSBmcm9tIGxheW91dFxyXG4gICAqIDcuIElmIGRhdGEgaW5wdXQgLSBidWlsZCBzY2hlbWEgZnJvbSBkYXRhXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpbml0aWFsaXplU2NoZW1hKCkge1xyXG5cclxuICAgIC8vIFRPRE86IHVwZGF0ZSB0byBhbGxvdyBub24tb2JqZWN0IHNjaGVtYXNcclxuXHJcbiAgICBpZiAoaXNPYmplY3QodGhpcy5zY2hlbWEpKSB7XHJcbiAgICAgIHRoaXMuanNmLkFuZ3VsYXJTY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIHRoaXMuanNmLnNjaGVtYSA9IGNsb25lRGVlcCh0aGlzLnNjaGVtYSk7XHJcbiAgICB9IGVsc2UgaWYgKGhhc093bih0aGlzLmZvcm0sICdzY2hlbWEnKSAmJiBpc09iamVjdCh0aGlzLmZvcm0uc2NoZW1hKSkge1xyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjbG9uZURlZXAodGhpcy5mb3JtLnNjaGVtYSk7XHJcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuSlNPTlNjaGVtYSkpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjbG9uZURlZXAodGhpcy5KU09OU2NoZW1hKTtcclxuICAgIH0gZWxzZSBpZiAoaGFzT3duKHRoaXMuZm9ybSwgJ0pTT05TY2hlbWEnKSAmJiBpc09iamVjdCh0aGlzLmZvcm0uSlNPTlNjaGVtYSkpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjbG9uZURlZXAodGhpcy5mb3JtLkpTT05TY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAncHJvcGVydGllcycpICYmIGlzT2JqZWN0KHRoaXMuZm9ybS5wcm9wZXJ0aWVzKSkge1xyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjbG9uZURlZXAodGhpcy5mb3JtKTtcclxuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QodGhpcy5mb3JtKSkge1xyXG4gICAgICAvLyBUT0RPOiBIYW5kbGUgb3RoZXIgdHlwZXMgb2YgZm9ybSBpbnB1dFxyXG4gICAgfVxyXG5cclxuICAgIGlmICghaXNFbXB0eSh0aGlzLmpzZi5zY2hlbWEpKSB7XHJcblxyXG4gICAgICAvLyBJZiBvdGhlciB0eXBlcyBhbHNvIGFsbG93ZWQsIHJlbmRlciBzY2hlbWEgYXMgYW4gb2JqZWN0XHJcbiAgICAgIGlmIChpbkFycmF5KCdvYmplY3QnLCB0aGlzLmpzZi5zY2hlbWEudHlwZSkpIHtcclxuICAgICAgICB0aGlzLmpzZi5zY2hlbWEudHlwZSA9ICdvYmplY3QnO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBXcmFwIG5vbi1vYmplY3Qgc2NoZW1hcyBpbiBvYmplY3QuXHJcbiAgICAgIGlmIChoYXNPd24odGhpcy5qc2Yuc2NoZW1hLCAndHlwZScpICYmIHRoaXMuanNmLnNjaGVtYS50eXBlICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIHRoaXMuanNmLnNjaGVtYSA9IHtcclxuICAgICAgICAgICd0eXBlJzogJ29iamVjdCcsXHJcbiAgICAgICAgICAncHJvcGVydGllcyc6IHsgMTogdGhpcy5qc2Yuc2NoZW1hIH1cclxuICAgICAgICB9O1xyXG4gICAgICAgIHRoaXMub2JqZWN0V3JhcCA9IHRydWU7XHJcbiAgICAgIH0gZWxzZSBpZiAoIWhhc093bih0aGlzLmpzZi5zY2hlbWEsICd0eXBlJykpIHtcclxuXHJcbiAgICAgICAgLy8gQWRkIHR5cGUgPSAnb2JqZWN0JyBpZiBtaXNzaW5nXHJcbiAgICAgICAgaWYgKGlzT2JqZWN0KHRoaXMuanNmLnNjaGVtYS5wcm9wZXJ0aWVzKSB8fFxyXG4gICAgICAgICAgaXNPYmplY3QodGhpcy5qc2Yuc2NoZW1hLnBhdHRlcm5Qcm9wZXJ0aWVzKSB8fFxyXG4gICAgICAgICAgaXNPYmplY3QodGhpcy5qc2Yuc2NoZW1hLmFkZGl0aW9uYWxQcm9wZXJ0aWVzKVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgdGhpcy5qc2Yuc2NoZW1hLnR5cGUgPSAnb2JqZWN0JztcclxuXHJcbiAgICAgICAgICAvLyBGaXggSlNPTiBzY2hlbWEgc2hvcnRoYW5kIChKU09OIEZvcm0gc3R5bGUpXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuanNmLkpzb25Gb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLmpzZi5zY2hlbWEgPSB7XHJcbiAgICAgICAgICAgICd0eXBlJzogJ29iamVjdCcsXHJcbiAgICAgICAgICAgICdwcm9wZXJ0aWVzJzogdGhpcy5qc2Yuc2NoZW1hXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSWYgbmVlZGVkLCB1cGRhdGUgSlNPTiBTY2hlbWEgdG8gZHJhZnQgNiBmb3JtYXQsIGluY2x1ZGluZ1xyXG4gICAgICAvLyBkcmFmdCAzIChKU09OIEZvcm0gc3R5bGUpIGFuZCBkcmFmdCA0IChBbmd1bGFyIFNjaGVtYSBGb3JtIHN0eWxlKVxyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjb252ZXJ0U2NoZW1hVG9EcmFmdDYodGhpcy5qc2Yuc2NoZW1hKTtcclxuXHJcbiAgICAgIC8vIEluaXRpYWxpemUgYWp2IGFuZCBjb21waWxlIHNjaGVtYVxyXG4gICAgICB0aGlzLmpzZi5jb21waWxlQWp2U2NoZW1hKCk7XHJcblxyXG4gICAgICAvLyBDcmVhdGUgc2NoZW1hUmVmTGlicmFyeSwgc2NoZW1hUmVjdXJzaXZlUmVmTWFwLCBkYXRhUmVjdXJzaXZlUmVmTWFwLCAmIGFycmF5TWFwXHJcbiAgICAgIHRoaXMuanNmLnNjaGVtYSA9IHJlc29sdmVTY2hlbWFSZWZlcmVuY2VzKFxyXG4gICAgICAgIHRoaXMuanNmLnNjaGVtYSwgdGhpcy5qc2Yuc2NoZW1hUmVmTGlicmFyeSwgdGhpcy5qc2Yuc2NoZW1hUmVjdXJzaXZlUmVmTWFwLFxyXG4gICAgICAgIHRoaXMuanNmLmRhdGFSZWN1cnNpdmVSZWZNYXAsIHRoaXMuanNmLmFycmF5TWFwXHJcbiAgICAgICk7XHJcbiAgICAgIGlmIChoYXNPd24odGhpcy5qc2Yuc2NoZW1hUmVmTGlicmFyeSwgJycpKSB7XHJcbiAgICAgICAgdGhpcy5qc2YuaGFzUm9vdFJlZmVyZW5jZSA9IHRydWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFRPRE86ICg/KSBSZXNvbHZlIGV4dGVybmFsICRyZWYgbGlua3NcclxuICAgICAgLy8gLy8gQ3JlYXRlIHNjaGVtYVJlZkxpYnJhcnkgJiBzY2hlbWFSZWN1cnNpdmVSZWZNYXBcclxuICAgICAgLy8gdGhpcy5wYXJzZXIuYnVuZGxlKHRoaXMuc2NoZW1hKVxyXG4gICAgICAvLyAgIC50aGVuKHNjaGVtYSA9PiB0aGlzLnNjaGVtYSA9IHJlc29sdmVTY2hlbWFSZWZlcmVuY2VzKFxyXG4gICAgICAvLyAgICAgc2NoZW1hLCB0aGlzLmpzZi5zY2hlbWFSZWZMaWJyYXJ5LFxyXG4gICAgICAvLyAgICAgdGhpcy5qc2Yuc2NoZW1hUmVjdXJzaXZlUmVmTWFwLCB0aGlzLmpzZi5kYXRhUmVjdXJzaXZlUmVmTWFwXHJcbiAgICAgIC8vICAgKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5pdGlhbGl6ZURhdGEnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBJbml0aWFsaXplICdmb3JtVmFsdWVzJ1xyXG4gICAqIGRlZnVsYXQgb3IgcHJldmlvdXNseSBzdWJtaXR0ZWQgdmFsdWVzIHVzZWQgdG8gcG9wdWxhdGUgZm9ybVxyXG4gICAqIFVzZSBmaXJzdCBhdmFpbGFibGUgaW5wdXQ6XHJcbiAgICogMS4gZGF0YSAtIHJlY29tbWVuZGVkXHJcbiAgICogMi4gbW9kZWwgLSBBbmd1bGFyIFNjaGVtYSBGb3JtIHN0eWxlXHJcbiAgICogMy4gZm9ybS52YWx1ZSAtIEpTT04gRm9ybSBzdHlsZVxyXG4gICAqIDQuIGZvcm0uZGF0YSAtIFNpbmdsZSBpbnB1dCBzdHlsZVxyXG4gICAqIDUuIGZvcm1EYXRhIC0gUmVhY3QgSlNPTiBTY2hlbWEgRm9ybSBzdHlsZVxyXG4gICAqIDYuIGZvcm0uZm9ybURhdGEgLSBGb3IgZWFzaWVyIHRlc3Rpbmcgb2YgUmVhY3QgSlNPTiBTY2hlbWEgRm9ybXNcclxuICAgKiA3LiAobm9uZSkgbm8gZGF0YSAtIGluaXRpYWxpemUgZGF0YSBmcm9tIHNjaGVtYSBhbmQgbGF5b3V0IGRlZmF1bHRzIG9ubHlcclxuICAgKi9cclxuICBwcml2YXRlIGluaXRpYWxpemVEYXRhKCkge1xyXG4gICAgaWYgKGhhc1ZhbHVlKHRoaXMuZGF0YSkpIHtcclxuICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGNsb25lRGVlcCh0aGlzLmRhdGEpO1xyXG4gICAgICB0aGlzLmZvcm1WYWx1ZXNJbnB1dCA9ICdkYXRhJztcclxuICAgIH0gZWxzZSBpZiAoaGFzVmFsdWUodGhpcy5tb2RlbCkpIHtcclxuICAgICAgdGhpcy5qc2YuQW5ndWxhclNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGNsb25lRGVlcCh0aGlzLm1vZGVsKTtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnbW9kZWwnO1xyXG4gICAgfSBlbHNlIGlmIChoYXNWYWx1ZSh0aGlzLm5nTW9kZWwpKSB7XHJcbiAgICAgIHRoaXMuanNmLkFuZ3VsYXJTY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIHRoaXMuanNmLmZvcm1WYWx1ZXMgPSBjbG9uZURlZXAodGhpcy5uZ01vZGVsKTtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnbmdNb2RlbCc7XHJcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuZm9ybSkgJiYgaGFzVmFsdWUodGhpcy5mb3JtLnZhbHVlKSkge1xyXG4gICAgICB0aGlzLmpzZi5Kc29uRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzID0gY2xvbmVEZWVwKHRoaXMuZm9ybS52YWx1ZSk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gJ2Zvcm0udmFsdWUnO1xyXG4gICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLmZvcm0pICYmIGhhc1ZhbHVlKHRoaXMuZm9ybS5kYXRhKSkge1xyXG4gICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzID0gY2xvbmVEZWVwKHRoaXMuZm9ybS5kYXRhKTtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnZm9ybS5kYXRhJztcclxuICAgIH0gZWxzZSBpZiAoaGFzVmFsdWUodGhpcy5mb3JtRGF0YSkpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmZvcm1WYWx1ZXNJbnB1dCA9ICdmb3JtRGF0YSc7XHJcbiAgICB9IGVsc2UgaWYgKGhhc093bih0aGlzLmZvcm0sICdmb3JtRGF0YScpICYmIGhhc1ZhbHVlKHRoaXMuZm9ybS5mb3JtRGF0YSkpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzID0gY2xvbmVEZWVwKHRoaXMuZm9ybS5mb3JtRGF0YSk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gJ2Zvcm0uZm9ybURhdGEnO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSBcImRhdGFcIjsvL251bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5pdGlhbGl6ZUxheW91dCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEluaXRpYWxpemUgJ2xheW91dCdcclxuICAgKiBVc2UgZmlyc3QgYXZhaWxhYmxlIGFycmF5IGlucHV0OlxyXG4gICAqIDEuIGxheW91dCAtIHJlY29tbWVuZGVkXHJcbiAgICogMi4gZm9ybSAtIEFuZ3VsYXIgU2NoZW1hIEZvcm0gc3R5bGVcclxuICAgKiAzLiBmb3JtLmZvcm0gLSBKU09OIEZvcm0gc3R5bGVcclxuICAgKiA0LiBmb3JtLmxheW91dCAtIFNpbmdsZSBpbnB1dCBzdHlsZVxyXG4gICAqIDUuIChub25lKSBubyBsYXlvdXQgLSBzZXQgZGVmYXVsdCBsYXlvdXQgaW5zdGVhZFxyXG4gICAqICAgIChmdWxsIGxheW91dCB3aWxsIGJlIGJ1aWx0IGxhdGVyIGZyb20gdGhlIHNjaGVtYSlcclxuICAgKlxyXG4gICAqIEFsc28sIGlmIGFsdGVybmF0ZSBsYXlvdXQgZm9ybWF0cyBhcmUgYXZhaWxhYmxlLFxyXG4gICAqIGltcG9ydCBmcm9tICdVSVNjaGVtYScgb3IgJ2N1c3RvbUZvcm1JdGVtcydcclxuICAgKiB1c2VkIGZvciBSZWFjdCBKU09OIFNjaGVtYSBGb3JtIGFuZCBKU09OIEZvcm0gQVBJIGNvbXBhdGliaWxpdHlcclxuICAgKiBVc2UgZmlyc3QgYXZhaWxhYmxlIGlucHV0OlxyXG4gICAqIDEuIFVJU2NoZW1hIC0gUmVhY3QgSlNPTiBTY2hlbWEgRm9ybSBzdHlsZVxyXG4gICAqIDIuIGZvcm0uVUlTY2hlbWEgLSBGb3IgdGVzdGluZyBzaW5nbGUgaW5wdXQgUmVhY3QgSlNPTiBTY2hlbWEgRm9ybXNcclxuICAgKiAyLiBmb3JtLmN1c3RvbUZvcm1JdGVtcyAtIEpTT04gRm9ybSBzdHlsZVxyXG4gICAqIDMuIChub25lKSBubyBpbnB1dCAtIGRvbid0IGltcG9ydFxyXG4gICAqL1xyXG4gIHByaXZhdGUgaW5pdGlhbGl6ZUxheW91dCgpIHtcclxuXHJcbiAgICAvLyBSZW5hbWUgSlNPTiBGb3JtLXN0eWxlICdvcHRpb25zJyBsaXN0cyB0b1xyXG4gICAgLy8gQW5ndWxhciBTY2hlbWEgRm9ybS1zdHlsZSAndGl0bGVNYXAnIGxpc3RzLlxyXG4gICAgY29uc3QgZml4SnNvbkZvcm1PcHRpb25zID0gKGxheW91dDogYW55KTogYW55ID0+IHtcclxuICAgICAgaWYgKGlzT2JqZWN0KGxheW91dCkgfHwgaXNBcnJheShsYXlvdXQpKSB7XHJcbiAgICAgICAgZm9yRWFjaChsYXlvdXQsICh2YWx1ZSwga2V5KSA9PiB7XHJcbiAgICAgICAgICBpZiAoaGFzT3duKHZhbHVlLCAnb3B0aW9ucycpICYmIGlzT2JqZWN0KHZhbHVlLm9wdGlvbnMpKSB7XHJcbiAgICAgICAgICAgIHZhbHVlLnRpdGxlTWFwID0gdmFsdWUub3B0aW9ucztcclxuICAgICAgICAgICAgZGVsZXRlIHZhbHVlLm9wdGlvbnM7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSwgJ3RvcC1kb3duJyk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGxheW91dDtcclxuICAgIH07XHJcblxyXG4gICAgLy8gQ2hlY2sgZm9yIGxheW91dCBpbnB1dHMgYW5kLCBpZiBmb3VuZCwgaW5pdGlhbGl6ZSBmb3JtIGxheW91dFxyXG4gICAgaWYgKGlzQXJyYXkodGhpcy5sYXlvdXQpKSB7XHJcbiAgICAgIHRoaXMuanNmLmxheW91dCA9IGNsb25lRGVlcCh0aGlzLmxheW91dCk7XHJcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkodGhpcy5mb3JtKSkge1xyXG4gICAgICB0aGlzLmpzZi5Bbmd1bGFyU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5sYXlvdXQgPSBjbG9uZURlZXAodGhpcy5mb3JtKTtcclxuICAgIH0gZWxzZSBpZiAodGhpcy5mb3JtICYmIGlzQXJyYXkodGhpcy5mb3JtLmZvcm0pKSB7XHJcbiAgICAgIHRoaXMuanNmLkpzb25Gb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIHRoaXMuanNmLmxheW91dCA9IGZpeEpzb25Gb3JtT3B0aW9ucyhjbG9uZURlZXAodGhpcy5mb3JtLmZvcm0pKTtcclxuICAgIH0gZWxzZSBpZiAodGhpcy5mb3JtICYmIGlzQXJyYXkodGhpcy5mb3JtLmxheW91dCkpIHtcclxuICAgICAgdGhpcy5qc2YubGF5b3V0ID0gY2xvbmVEZWVwKHRoaXMuZm9ybS5sYXlvdXQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5qc2YubGF5b3V0ID0gWycqJ107XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgZm9yIGFsdGVybmF0ZSBsYXlvdXQgaW5wdXRzXHJcbiAgICBsZXQgYWx0ZXJuYXRlTGF5b3V0OiBhbnkgPSBudWxsO1xyXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMuVUlTY2hlbWEpKSB7XHJcbiAgICAgIHRoaXMuanNmLlJlYWN0SnNvblNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgYWx0ZXJuYXRlTGF5b3V0ID0gY2xvbmVEZWVwKHRoaXMuVUlTY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAnVUlTY2hlbWEnKSkge1xyXG4gICAgICB0aGlzLmpzZi5SZWFjdEpzb25TY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIGFsdGVybmF0ZUxheW91dCA9IGNsb25lRGVlcCh0aGlzLmZvcm0uVUlTY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAndWlTY2hlbWEnKSkge1xyXG4gICAgICB0aGlzLmpzZi5SZWFjdEpzb25TY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIGFsdGVybmF0ZUxheW91dCA9IGNsb25lRGVlcCh0aGlzLmZvcm0udWlTY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAnY3VzdG9tRm9ybUl0ZW1zJykpIHtcclxuICAgICAgdGhpcy5qc2YuSnNvbkZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgYWx0ZXJuYXRlTGF5b3V0ID0gZml4SnNvbkZvcm1PcHRpb25zKGNsb25lRGVlcCh0aGlzLmZvcm0uY3VzdG9tRm9ybUl0ZW1zKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gaWYgYWx0ZXJuYXRlIGxheW91dCBmb3VuZCwgY29weSBhbHRlcm5hdGUgbGF5b3V0IG9wdGlvbnMgaW50byBzY2hlbWFcclxuICAgIGlmIChhbHRlcm5hdGVMYXlvdXQpIHtcclxuICAgICAgSnNvblBvaW50ZXIuZm9yRWFjaERlZXAoYWx0ZXJuYXRlTGF5b3V0LCAodmFsdWUsIHBvaW50ZXIpID0+IHtcclxuICAgICAgICBjb25zdCBzY2hlbWFQb2ludGVyID0gcG9pbnRlclxyXG4gICAgICAgICAgLnJlcGxhY2UoL1xcLy9nLCAnL3Byb3BlcnRpZXMvJylcclxuICAgICAgICAgIC5yZXBsYWNlKC9cXC9wcm9wZXJ0aWVzXFwvaXRlbXNcXC9wcm9wZXJ0aWVzXFwvL2csICcvaXRlbXMvcHJvcGVydGllcy8nKVxyXG4gICAgICAgICAgLnJlcGxhY2UoL1xcL3Byb3BlcnRpZXNcXC90aXRsZU1hcFxcL3Byb3BlcnRpZXNcXC8vZywgJy90aXRsZU1hcC9wcm9wZXJ0aWVzLycpO1xyXG4gICAgICAgIGlmIChoYXNWYWx1ZSh2YWx1ZSkgJiYgaGFzVmFsdWUocG9pbnRlcikpIHtcclxuICAgICAgICAgIGxldCBrZXkgPSBKc29uUG9pbnRlci50b0tleShwb2ludGVyKTtcclxuICAgICAgICAgIGNvbnN0IGdyb3VwUG9pbnRlciA9IChKc29uUG9pbnRlci5wYXJzZShzY2hlbWFQb2ludGVyKSB8fCBbXSkuc2xpY2UoMCwgLTIpO1xyXG4gICAgICAgICAgbGV0IGl0ZW1Qb2ludGVyOiBzdHJpbmcgfCBzdHJpbmdbXTtcclxuXHJcbiAgICAgICAgICAvLyBJZiAndWk6b3JkZXInIG9iamVjdCBmb3VuZCwgY29weSBpbnRvIG9iamVjdCBzY2hlbWEgcm9vdFxyXG4gICAgICAgICAgaWYgKGtleS50b0xvd2VyQ2FzZSgpID09PSAndWk6b3JkZXInKSB7XHJcbiAgICAgICAgICAgIGl0ZW1Qb2ludGVyID0gWy4uLmdyb3VwUG9pbnRlciwgJ3VpOm9yZGVyJ107XHJcblxyXG4gICAgICAgICAgICAvLyBDb3B5IG90aGVyIGFsdGVybmF0ZSBsYXlvdXQgb3B0aW9ucyB0byBzY2hlbWEgJ3gtc2NoZW1hLWZvcm0nLFxyXG4gICAgICAgICAgICAvLyAobGlrZSBBbmd1bGFyIFNjaGVtYSBGb3JtIG9wdGlvbnMpIGFuZCByZW1vdmUgYW55ICd1aTonIHByZWZpeGVzXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAoa2V5LnNsaWNlKDAsIDMpLnRvTG93ZXJDYXNlKCkgPT09ICd1aTonKSB7IGtleSA9IGtleS5zbGljZSgzKTsgfVxyXG4gICAgICAgICAgICBpdGVtUG9pbnRlciA9IFsuLi5ncm91cFBvaW50ZXIsICd4LXNjaGVtYS1mb3JtJywga2V5XTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChKc29uUG9pbnRlci5oYXModGhpcy5qc2Yuc2NoZW1hLCBncm91cFBvaW50ZXIpICYmXHJcbiAgICAgICAgICAgICFKc29uUG9pbnRlci5oYXModGhpcy5qc2Yuc2NoZW1hLCBpdGVtUG9pbnRlcilcclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICBKc29uUG9pbnRlci5zZXQodGhpcy5qc2Yuc2NoZW1hLCBpdGVtUG9pbnRlciwgdmFsdWUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnYWN0aXZhdGVGb3JtJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogLi4uY29udGludWVkIGZyb20gJ2luaXRpYWxpemVTY2hlbWEnIGZ1bmN0aW9uLCBhYm92ZVxyXG4gICAqIElmICdzY2hlbWEnIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCAoaS5lLiBubyBzY2hlbWEgaW5wdXQgZm91bmQpXHJcbiAgICogNi4gSWYgbGF5b3V0IGlucHV0IC0gYnVpbGQgc2NoZW1hIGZyb20gbGF5b3V0IGlucHV0XHJcbiAgICogNy4gSWYgZGF0YSBpbnB1dCAtIGJ1aWxkIHNjaGVtYSBmcm9tIGRhdGEgaW5wdXRcclxuICAgKlxyXG4gICAqIENyZWF0ZSBmaW5hbCBsYXlvdXQsXHJcbiAgICogYnVpbGQgdGhlIEZvcm1Hcm91cCB0ZW1wbGF0ZSBhbmQgdGhlIEFuZ3VsYXIgRm9ybUdyb3VwLFxyXG4gICAqIHN1YnNjcmliZSB0byBjaGFuZ2VzLFxyXG4gICAqIGFuZCBhY3RpdmF0ZSB0aGUgZm9ybS5cclxuICAgKi9cclxuICBwcml2YXRlIGFjdGl2YXRlRm9ybSgpIHtcclxuICAgIHRoaXMudW5zdWJzY3JpYmVPbkFjdGl2YXRlRm9ybSQubmV4dCgpO1xyXG4gICAgLy8gSWYgJ3NjaGVtYScgbm90IGluaXRpYWxpemVkXHJcbiAgICBpZiAoaXNFbXB0eSh0aGlzLmpzZi5zY2hlbWEpKSB7XHJcblxyXG4gICAgICAvLyBUT0RPOiBJZiBmdWxsIGxheW91dCBpbnB1dCAod2l0aCBubyAnKicpLCBidWlsZCBzY2hlbWEgZnJvbSBsYXlvdXRcclxuICAgICAgLy8gaWYgKCF0aGlzLmpzZi5sYXlvdXQuaW5jbHVkZXMoJyonKSkge1xyXG4gICAgICAvLyAgIHRoaXMuanNmLmJ1aWxkU2NoZW1hRnJvbUxheW91dCgpO1xyXG4gICAgICAvLyB9IGVsc2VcclxuXHJcbiAgICAgIC8vIElmIGRhdGEgaW5wdXQsIGJ1aWxkIHNjaGVtYSBmcm9tIGRhdGFcclxuICAgICAgaWYgKCFpc0VtcHR5KHRoaXMuanNmLmZvcm1WYWx1ZXMpKSB7XHJcbiAgICAgICAgdGhpcy5qc2YuYnVpbGRTY2hlbWFGcm9tRGF0YSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFpc0VtcHR5KHRoaXMuanNmLnNjaGVtYSkpIHtcclxuXHJcbiAgICAgIC8vIElmIG5vdCBhbHJlYWR5IGluaXRpYWxpemVkLCBpbml0aWFsaXplIGFqdiBhbmQgY29tcGlsZSBzY2hlbWFcclxuICAgICAgdGhpcy5qc2YuY29tcGlsZUFqdlNjaGVtYSgpO1xyXG5cclxuICAgICAgLy8gVXBkYXRlIGFsbCBsYXlvdXQgZWxlbWVudHMsIGFkZCB2YWx1ZXMsIHdpZGdldHMsIGFuZCB2YWxpZGF0b3JzLFxyXG4gICAgICAvLyByZXBsYWNlIGFueSAnKicgd2l0aCBhIGxheW91dCBidWlsdCBmcm9tIGFsbCBzY2hlbWEgZWxlbWVudHMsXHJcbiAgICAgIC8vIGFuZCB1cGRhdGUgdGhlIEZvcm1Hcm91cCB0ZW1wbGF0ZSB3aXRoIGFueSBuZXcgdmFsaWRhdG9yc1xyXG4gICAgICB0aGlzLmpzZi5idWlsZExheW91dCh0aGlzLndpZGdldExpYnJhcnkpO1xyXG5cclxuICAgICAgLy8gQnVpbGQgdGhlIEFuZ3VsYXIgRm9ybUdyb3VwIHRlbXBsYXRlIGZyb20gdGhlIHNjaGVtYVxyXG4gICAgICB0aGlzLmpzZi5idWlsZEZvcm1Hcm91cFRlbXBsYXRlKHRoaXMuanNmLmZvcm1WYWx1ZXMpO1xyXG5cclxuICAgICAgLy8gQnVpbGQgdGhlIHJlYWwgQW5ndWxhciBGb3JtR3JvdXAgZnJvbSB0aGUgRm9ybUdyb3VwIHRlbXBsYXRlXHJcbiAgICAgIHRoaXMuanNmLmJ1aWxkRm9ybUdyb3VwKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuanNmLmZvcm1Hcm91cCkge1xyXG5cclxuICAgICAgLy8gUmVzZXQgaW5pdGlhbCBmb3JtIHZhbHVlc1xyXG4gICAgICBpZiAoIWlzRW1wdHkodGhpcy5qc2YuZm9ybVZhbHVlcykgJiZcclxuICAgICAgICB0aGlzLmpzZi5mb3JtT3B0aW9ucy5zZXRTY2hlbWFEZWZhdWx0cyAhPT0gdHJ1ZSAmJlxyXG4gICAgICAgIHRoaXMuanNmLmZvcm1PcHRpb25zLnNldExheW91dERlZmF1bHRzICE9PSB0cnVlXHJcbiAgICAgICkge1xyXG4gICAgICAgIHRoaXMuc2V0Rm9ybVZhbHVlcyh0aGlzLmpzZi5mb3JtVmFsdWVzKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gVE9ETzogRmlndXJlIG91dCBob3cgdG8gZGlzcGxheSBjYWxjdWxhdGVkIHZhbHVlcyB3aXRob3V0IGNoYW5naW5nIG9iamVjdCBkYXRhXHJcbiAgICAgIC8vIFNlZSBodHRwOi8vdWxpb24uZ2l0aHViLmlvL2pzb25mb3JtL3BsYXlncm91bmQvP2V4YW1wbGU9dGVtcGxhdGluZy12YWx1ZXNcclxuICAgICAgLy8gQ2FsY3VsYXRlIHJlZmVyZW5jZXMgdG8gb3RoZXIgZmllbGRzXHJcbiAgICAgIC8vIGlmICghaXNFbXB0eSh0aGlzLmpzZi5mb3JtR3JvdXAudmFsdWUpKSB7XHJcbiAgICAgIC8vICAgZm9yRWFjaCh0aGlzLmpzZi5mb3JtR3JvdXAudmFsdWUsICh2YWx1ZSwga2V5LCBvYmplY3QsIHJvb3RPYmplY3QpID0+IHtcclxuICAgICAgLy8gICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIC8vICAgICAgIG9iamVjdFtrZXldID0gdGhpcy5qc2YucGFyc2VUZXh0KHZhbHVlLCB2YWx1ZSwgcm9vdE9iamVjdCwga2V5KTtcclxuICAgICAgLy8gICAgIH1cclxuICAgICAgLy8gICB9LCAndG9wLWRvd24nKTtcclxuICAgICAgLy8gfVxyXG5cclxuICAgICAgLy8gU3Vic2NyaWJlIHRvIGZvcm0gY2hhbmdlcyB0byBvdXRwdXQgbGl2ZSBkYXRhLCB2YWxpZGF0aW9uLCBhbmQgZXJyb3JzXHJcbiAgICAgIHRoaXMuZGF0YUNoYW5nZXNTdWJzPXRoaXMuanNmLmRhdGFDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmVPbkFjdGl2YXRlRm9ybSQpKS5zdWJzY3JpYmUoZGF0YSA9PiB7XHJcbiAgICAgICAgdGhpcy5vbkNoYW5nZXMuZW1pdCh0aGlzLm9iamVjdFdyYXAgPyBkYXRhWycxJ10gOiBkYXRhKTtcclxuICAgICAgICBpZiAodGhpcy5mb3JtVmFsdWVzSW5wdXQgJiYgdGhpcy5mb3JtVmFsdWVzSW5wdXQuaW5kZXhPZignLicpID09PSAtMSkge1xyXG4gICAgICAgICAgdGhpc1tgJHt0aGlzLmZvcm1WYWx1ZXNJbnB1dH1DaGFuZ2VgXS5lbWl0KHRoaXMub2JqZWN0V3JhcCA/IGRhdGFbJzEnXSA6IGRhdGEpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBUcmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb24gb24gc3RhdHVzQ2hhbmdlcyB0byBzaG93IHVwZGF0ZWQgZXJyb3JzXHJcbiAgICAgIHRoaXMuc3RhdHVzQ2hhbmdlc1N1YnM9IHRoaXMuanNmLmZvcm1Hcm91cC5zdGF0dXNDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmVPbkFjdGl2YXRlRm9ybSQpKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKSk7XHJcbiAgICAgIHRoaXMuaXNWYWxpZENoYW5nZXNTdWJzPXRoaXMuanNmLmlzVmFsaWRDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmVPbkFjdGl2YXRlRm9ybSQpKS5zdWJzY3JpYmUoaXNWYWxpZCA9PiB0aGlzLmlzVmFsaWQuZW1pdChpc1ZhbGlkKSk7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvbkVycm9yQ2hhbmdlc1N1YnM9dGhpcy5qc2YudmFsaWRhdGlvbkVycm9yQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kKSkuc3Vic2NyaWJlKGVyciA9PiB0aGlzLnZhbGlkYXRpb25FcnJvcnMuZW1pdChlcnIpKTtcclxuXHJcbiAgICAgIC8vIE91dHB1dCBmaW5hbCBzY2hlbWEsIGZpbmFsIGxheW91dCwgYW5kIGluaXRpYWwgZGF0YVxyXG4gICAgICB0aGlzLmZvcm1TY2hlbWEuZW1pdCh0aGlzLmpzZi5zY2hlbWEpO1xyXG4gICAgICB0aGlzLmZvcm1MYXlvdXQuZW1pdCh0aGlzLmpzZi5sYXlvdXQpO1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlcy5lbWl0KHRoaXMub2JqZWN0V3JhcCA/IHRoaXMuanNmLmRhdGFbJzEnXSA6IHRoaXMuanNmLmRhdGEpO1xyXG5cclxuICAgICAgLy8gSWYgdmFsaWRhdGVPblJlbmRlciwgb3V0cHV0IGluaXRpYWwgdmFsaWRhdGlvbiBhbmQgYW55IGVycm9yc1xyXG4gICAgICBjb25zdCB2YWxpZGF0ZU9uUmVuZGVyID1cclxuICAgICAgICBKc29uUG9pbnRlci5nZXQodGhpcy5qc2YsICcvZm9ybU9wdGlvbnMvdmFsaWRhdGVPblJlbmRlcicpO1xyXG4gICAgICBpZiAodmFsaWRhdGVPblJlbmRlcikgeyAvLyB2YWxpZGF0ZU9uUmVuZGVyID09PSAnYXV0bycgfHwgdHJ1ZVxyXG4gICAgICAgIGNvbnN0IHRvdWNoQWxsID0gKGNvbnRyb2wpID0+IHtcclxuICAgICAgICAgIGlmICh2YWxpZGF0ZU9uUmVuZGVyID09PSB0cnVlIHx8IGhhc1ZhbHVlKGNvbnRyb2wudmFsdWUpKSB7XHJcbiAgICAgICAgICAgIGNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgT2JqZWN0LmtleXMoY29udHJvbC5jb250cm9scyB8fCB7fSlcclxuICAgICAgICAgICAgLmZvckVhY2goa2V5ID0+IHRvdWNoQWxsKGNvbnRyb2wuY29udHJvbHNba2V5XSkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdG91Y2hBbGwodGhpcy5qc2YuZm9ybUdyb3VwKTtcclxuICAgICAgICB0aGlzLmlzVmFsaWQuZW1pdCh0aGlzLmpzZi5pc1ZhbGlkKTtcclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25FcnJvcnMuZW1pdCh0aGlzLmpzZi5hanZFcnJvcnMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG4iLCI8Zm9ybSBbYXV0b2NvbXBsZXRlXT1cImpzZj8uZm9ybU9wdGlvbnM/LmF1dG9jb21wbGV0ZSA/ICdvbicgOiAnb2ZmJ1wiIGNsYXNzPVwianNvbi1zY2hlbWEtZm9ybVwiIChuZ1N1Ym1pdCk9XCJzdWJtaXRGb3JtKClcIj5cclxuICA8cm9vdC13aWRnZXQgW2xheW91dF09XCJqc2Y/LmxheW91dFwiPjwvcm9vdC13aWRnZXQ+XHJcbjwvZm9ybT5cclxuPGRpdiAqbmdJZj1cImRlYnVnIHx8IGpzZj8uZm9ybU9wdGlvbnM/LmRlYnVnXCI+XHJcbiAgRGVidWcgb3V0cHV0OlxyXG4gIDxwcmU+e3tkZWJ1Z091dHB1dH19PC9wcmU+XHJcbjwvZGl2PiJdfQ==
|