@ng-formworks/core 17.2.7 → 18.0.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 +834 -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 +1158 -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 +10151 -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 +66 -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: "18.2.7", 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: "18.2.7", 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: "18.2.7", 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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SztnQkFTSSxTQUFTO3NCQUFsQixNQUFNO2dCQUNHLFFBQVE7c0JBQWpCLE1BQU07Z0JBQ0csT0FBTztzQkFBaEIsTUFBTTtnQkFDRyxnQkFBZ0I7c0JBQXpCLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxVQUFVO3NCQUFuQixNQUFNO2dCQU1HLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxjQUFjO3NCQUF2QixNQUFNO2dCQUNHLGFBQWE7c0JBQXRCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2xvbmVEZWVwIGZyb20gJ2xvZGFzaC9jbG9uZURlZXAnO1xyXG5pbXBvcnQgaXNFcXVhbCBmcm9tICdsb2Rhc2gvaXNFcXVhbCc7XHJcblxyXG5pbXBvcnQge1xyXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxyXG4gIENoYW5nZURldGVjdG9yUmVmLFxyXG4gIENvbXBvbmVudCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgZm9yd2FyZFJlZixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uSW5pdCxcclxuICBPdXRwdXQsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBGcmFtZXdvcmtMaWJyYXJ5U2VydmljZSB9IGZyb20gJy4vZnJhbWV3b3JrLWxpYnJhcnkvZnJhbWV3b3JrLWxpYnJhcnkuc2VydmljZSc7XHJcbmltcG9ydCB7IEpzb25TY2hlbWFGb3JtU2VydmljZSB9IGZyb20gJy4vanNvbi1zY2hlbWEtZm9ybS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgY29udmVydFNjaGVtYVRvRHJhZnQ2IH0gZnJvbSAnLi9zaGFyZWQvY29udmVydC1zY2hlbWEtdG8tZHJhZnQ2LmZ1bmN0aW9uJztcclxuaW1wb3J0IHsgcmVzb2x2ZVNjaGVtYVJlZmVyZW5jZXMgfSBmcm9tICcuL3NoYXJlZC9qc29uLXNjaGVtYS5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBKc29uUG9pbnRlciB9IGZyb20gJy4vc2hhcmVkL2pzb25wb2ludGVyLmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7IGZvckVhY2gsIGhhc093biB9IGZyb20gJy4vc2hhcmVkL3V0aWxpdHkuZnVuY3Rpb25zJztcclxuaW1wb3J0IHtcclxuICBoYXNWYWx1ZSxcclxuICBpbkFycmF5LFxyXG4gIGlzQXJyYXksXHJcbiAgaXNFbXB0eSxcclxuICBpc09iamVjdFxyXG59IGZyb20gJy4vc2hhcmVkL3ZhbGlkYXRvci5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBXaWRnZXRMaWJyYXJ5U2VydmljZSB9IGZyb20gJy4vd2lkZ2V0LWxpYnJhcnkvd2lkZ2V0LWxpYnJhcnkuc2VydmljZSc7XHJcblxyXG5leHBvcnQgY29uc3QgSlNPTl9TQ0hFTUFfRk9STV9WQUxVRV9BQ0NFU1NPUjogYW55ID0ge1xyXG4gIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IEpzb25TY2hlbWFGb3JtQ29tcG9uZW50KSxcclxuICBtdWx0aTogdHJ1ZSxcclxufTtcclxuXHJcbi8qKlxyXG4gKiBAbW9kdWxlICdKc29uU2NoZW1hRm9ybUNvbXBvbmVudCcgLSBBbmd1bGFyIEpTT04gU2NoZW1hIEZvcm1cclxuICpcclxuICogUm9vdCBtb2R1bGUgb2YgdGhlIEFuZ3VsYXIgSlNPTiBTY2hlbWEgRm9ybSBjbGllbnQtc2lkZSBsaWJyYXJ5LFxyXG4gKiBhbiBBbmd1bGFyIGxpYnJhcnkgd2hpY2ggZ2VuZXJhdGVzIGFuIEhUTUwgZm9ybSBmcm9tIGEgSlNPTiBzY2hlbWFcclxuICogc3RydWN0dXJlZCBkYXRhIG1vZGVsIGFuZC9vciBhIEpTT04gU2NoZW1hIEZvcm0gbGF5b3V0IGRlc2NyaXB0aW9uLlxyXG4gKlxyXG4gKiBUaGlzIGxpYnJhcnkgYWxzbyB2YWxpZGF0ZXMgaW5wdXQgZGF0YSBieSB0aGUgdXNlciwgdXNpbmcgYm90aCB2YWxpZGF0b3JzIG9uXHJcbiAqIGluZGl2aWR1YWwgY29udHJvbHMgdG8gcHJvdmlkZSByZWFsLXRpbWUgZmVlZGJhY2sgd2hpbGUgdGhlIHVzZXIgaXMgZmlsbGluZ1xyXG4gKiBvdXQgdGhlIGZvcm0sIGFuZCB0aGVuIHZhbGlkYXRpbmcgdGhlIGVudGlyZSBpbnB1dCBhZ2FpbnN0IHRoZSBzY2hlbWEgd2hlblxyXG4gKiB0aGUgZm9ybSBpcyBzdWJtaXR0ZWQgdG8gbWFrZSBzdXJlIHRoZSByZXR1cm5lZCBKU09OIGRhdGEgb2JqZWN0IGlzIHZhbGlkLlxyXG4gKlxyXG4gKiBUaGlzIGxpYnJhcnkgaXMgc2ltaWxhciB0bywgYW5kIG1vc3RseSBBUEkgY29tcGF0aWJsZSB3aXRoOlxyXG4gKlxyXG4gKiAtIEpTT04gU2NoZW1hIEZvcm0ncyBBbmd1bGFyIFNjaGVtYSBGb3JtIGxpYnJhcnkgZm9yIEFuZ3VsYXJKc1xyXG4gKiAgIGh0dHA6Ly9zY2hlbWFmb3JtLmlvXHJcbiAqICAgaHR0cDovL3NjaGVtYWZvcm0uaW8vZXhhbXBsZXMvYm9vdHN0cmFwLWV4YW1wbGUuaHRtbCAoZXhhbXBsZXMpXHJcbiAqXHJcbiAqIC0gTW96aWxsYSdzIHJlYWN0LWpzb25zY2hlbWEtZm9ybSBsaWJyYXJ5IGZvciBSZWFjdFxyXG4gKiAgIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3ppbGxhLXNlcnZpY2VzL3JlYWN0LWpzb25zY2hlbWEtZm9ybVxyXG4gKiAgIGh0dHBzOi8vbW96aWxsYS1zZXJ2aWNlcy5naXRodWIuaW8vcmVhY3QtanNvbnNjaGVtYS1mb3JtIChleGFtcGxlcylcclxuICpcclxuICogLSBKb3NoZmlyZSdzIEpTT04gRm9ybSBsaWJyYXJ5IGZvciBqUXVlcnlcclxuICogICBodHRwczovL2dpdGh1Yi5jb20vam9zaGZpcmUvanNvbmZvcm1cclxuICogICBodHRwOi8vdWxpb24uZ2l0aHViLmlvL2pzb25mb3JtL3BsYXlncm91bmQgKGV4YW1wbGVzKVxyXG4gKlxyXG4gKiBUaGlzIGxpYnJhcnkgZGVwZW5kcyBvbjpcclxuICogIC0gQW5ndWxhciAob2J2aW91c2x5KSAgICAgICAgICAgICAgICAgIGh0dHBzOi8vYW5ndWxhci5pb1xyXG4gKiAgLSBsb2Rhc2gsIEphdmFTY3JpcHQgdXRpbGl0eSBsaWJyYXJ5ICAgaHR0cHM6Ly9naXRodWIuY29tL2xvZGFzaC9sb2Rhc2hcclxuICogIC0gYWp2LCBBbm90aGVyIEpTT04gU2NoZW1hIHZhbGlkYXRvciAgIGh0dHBzOi8vZ2l0aHViLmNvbS9lcG9iZXJlemtpbi9hanZcclxuICpcclxuICogSW4gYWRkaXRpb24sIHRoZSBFeGFtcGxlIFBsYXlncm91bmQgYWxzbyBkZXBlbmRzIG9uOlxyXG4gKiAgLSBicmFjZSwgQnJvd3NlcmlmaWVkIEFjZSBlZGl0b3IgICAgICAgaHR0cDovL3RobG9yZW56LmdpdGh1Yi5pby9icmFjZVxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnanNvbi1zY2hlbWEtZm9ybScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2pzb24tc2NoZW1hLWZvcm0uY29tcG9uZW50Lmh0bWwnLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG4gIC8vIEFkZGluZyAnSnNvblNjaGVtYUZvcm1TZXJ2aWNlJyBoZXJlLCBpbnN0ZWFkIG9mIGluIHRoZSBtb2R1bGUsXHJcbiAgLy8gY3JlYXRlcyBhIHNlcGFyYXRlIGluc3RhbmNlIG9mIHRoZSBzZXJ2aWNlIGZvciBlYWNoIGNvbXBvbmVudFxyXG4gIHByb3ZpZGVyczogIFsgSnNvblNjaGVtYUZvcm1TZXJ2aWNlLCBKU09OX1NDSEVNQV9GT1JNX1ZBTFVFX0FDQ0VTU09SIF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBKc29uU2NoZW1hRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkNoYW5nZXMsIE9uSW5pdCxPbkRlc3Ryb3kge1xyXG4gIC8vIFRPRE86IHF1aWNrZml4IHRvIGF2b2lkIHN1YnNjcmliaW5nIHR3aWNlIHRvIHRoZSBzYW1lIGVtaXR0ZXJzXHJcbiAgcHJpdmF0ZSB1bnN1YnNjcmliZU9uQWN0aXZhdGVGb3JtJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGRlYnVnT3V0cHV0OiBhbnk7IC8vIERlYnVnIGluZm9ybWF0aW9uLCBpZiByZXF1ZXN0ZWRcclxuICBmb3JtVmFsdWVTdWJzY3JpcHRpb246IGFueSA9IG51bGw7XHJcbiAgZm9ybUluaXRpYWxpemVkID0gZmFsc2U7XHJcbiAgb2JqZWN0V3JhcCA9IGZhbHNlOyAvLyBJcyBub24tb2JqZWN0IGlucHV0IHNjaGVtYSB3cmFwcGVkIGluIGFuIG9iamVjdD9cclxuXHJcbiAgZm9ybVZhbHVlc0lucHV0OiBzdHJpbmc7IC8vIE5hbWUgb2YgdGhlIGlucHV0IHByb3ZpZGluZyB0aGUgZm9ybSBkYXRhXHJcbiAgcHJldmlvdXNJbnB1dHM6IHsgLy8gUHJldmlvdXMgaW5wdXQgdmFsdWVzLCB0byBkZXRlY3Qgd2hpY2ggaW5wdXQgdHJpZ2dlcnMgb25DaGFuZ2VzXHJcbiAgICBzY2hlbWE6IGFueSwgbGF5b3V0OiBhbnlbXSwgZGF0YTogYW55LCBvcHRpb25zOiBhbnksIGZyYW1ld29yazogYW55IHwgc3RyaW5nLFxyXG4gICAgd2lkZ2V0czogYW55LCBmb3JtOiBhbnksIG1vZGVsOiBhbnksIEpTT05TY2hlbWE6IGFueSwgVUlTY2hlbWE6IGFueSxcclxuICAgIGZvcm1EYXRhOiBhbnksIGxvYWRFeHRlcm5hbEFzc2V0czogYm9vbGVhbiwgZGVidWc6IGJvb2xlYW4sXHJcbiAgfSA9IHtcclxuICAgICAgc2NoZW1hOiBudWxsLCBsYXlvdXQ6IG51bGwsIGRhdGE6IG51bGwsIG9wdGlvbnM6IG51bGwsIGZyYW1ld29yazogbnVsbCxcclxuICAgICAgd2lkZ2V0czogbnVsbCwgZm9ybTogbnVsbCwgbW9kZWw6IG51bGwsIEpTT05TY2hlbWE6IG51bGwsIFVJU2NoZW1hOiBudWxsLFxyXG4gICAgICBmb3JtRGF0YTogbnVsbCwgbG9hZEV4dGVybmFsQXNzZXRzOiBudWxsLCBkZWJ1ZzogbnVsbCxcclxuICAgIH07XHJcblxyXG4gIC8vIFJlY29tbWVuZGVkIGlucHV0c1xyXG4gIEBJbnB1dCgpIHNjaGVtYTogYW55OyAvLyBUaGUgSlNPTiBTY2hlbWFcclxuICBASW5wdXQoKSBsYXlvdXQ6IGFueVtdOyAvLyBUaGUgZm9ybSBsYXlvdXRcclxuICBASW5wdXQoKSBkYXRhOiBhbnk7IC8vIFRoZSBmb3JtIGRhdGFcclxuICBASW5wdXQoKSBvcHRpb25zOiBhbnk7IC8vIFRoZSBnbG9iYWwgZm9ybSBvcHRpb25zXHJcbiAgQElucHV0KCkgZnJhbWV3b3JrOiBhbnkgfCBzdHJpbmc7IC8vIFRoZSBmcmFtZXdvcmsgdG8gbG9hZFxyXG4gIEBJbnB1dCgpIHdpZGdldHM6IGFueTsgLy8gQW55IGN1c3RvbSB3aWRnZXRzIHRvIGxvYWRcclxuXHJcbiAgLy8gQWx0ZXJuYXRlIGNvbWJpbmVkIHNpbmdsZSBpbnB1dFxyXG4gIEBJbnB1dCgpIGZvcm06IGFueTsgLy8gRm9yIHRlc3RpbmcsIGFuZCBKU09OIFNjaGVtYSBGb3JtIEFQSSBjb21wYXRpYmlsaXR5XHJcblxyXG4gIC8vIEFuZ3VsYXIgU2NoZW1hIEZvcm0gQVBJIGNvbXBhdGliaWxpdHkgaW5wdXRcclxuICBASW5wdXQoKSBtb2RlbDogYW55OyAvLyBBbHRlcm5hdGUgaW5wdXQgZm9yIGZvcm0gZGF0YVxyXG5cclxuICAvLyBSZWFjdCBKU09OIFNjaGVtYSBGb3JtIEFQSSBjb21wYXRpYmlsaXR5IGlucHV0c1xyXG4gIEBJbnB1dCgpIEpTT05TY2hlbWE6IGFueTsgLy8gQWx0ZXJuYXRlIGlucHV0IGZvciBKU09OIFNjaGVtYVxyXG4gIEBJbnB1dCgpIFVJU2NoZW1hOiBhbnk7IC8vIFVJIHNjaGVtYSAtIGFsdGVybmF0ZSBmb3JtIGxheW91dCBmb3JtYXRcclxuICBASW5wdXQoKSBmb3JtRGF0YTogYW55OyAvLyBBbHRlcm5hdGUgaW5wdXQgZm9yIGZvcm0gZGF0YVxyXG5cclxuICBASW5wdXQoKSBuZ01vZGVsOiBhbnk7IC8vIEFsdGVybmF0ZSBpbnB1dCBmb3IgQW5ndWxhciBmb3Jtc1xyXG5cclxuICBASW5wdXQoKSBsYW5ndWFnZTogc3RyaW5nOyAvLyBMYW5ndWFnZVxyXG5cclxuICAvLyBEZXZlbG9wbWVudCBpbnB1dHMsIGZvciB0ZXN0aW5nIGFuZCBkZWJ1Z2dpbmdcclxuICBASW5wdXQoKSBsb2FkRXh0ZXJuYWxBc3NldHM6IGJvb2xlYW47IC8vIExvYWQgZXh0ZXJuYWwgZnJhbWV3b3JrIGFzc2V0cz9cclxuICBASW5wdXQoKSBkZWJ1ZzogYm9vbGVhbjsgLy8gU2hvdyBkZWJ1ZyBpbmZvcm1hdGlvbj9cclxuXHJcbiAgQElucHV0KCkgdGhlbWU6IHN0cmluZzsgLy8gVGhlbWVcclxuXHJcbiAgQElucHV0KClcclxuICBnZXQgdmFsdWUoKTogYW55IHtcclxuICAgIHJldHVybiB0aGlzLm9iamVjdFdyYXAgPyB0aGlzLmpzZi5kYXRhWycxJ10gOiB0aGlzLmpzZi5kYXRhO1xyXG4gIH1cclxuICBzZXQgdmFsdWUodmFsdWU6IGFueSkge1xyXG4gICAgdGhpcy5zZXRGb3JtVmFsdWVzKHZhbHVlLCBmYWxzZSk7XHJcbiAgfVxyXG5cclxuICAvLyBPdXRwdXRzXHJcbiAgQE91dHB1dCgpIG9uQ2hhbmdlcyA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpOyAvLyBMaXZlIHVudmFsaWRhdGVkIGludGVybmFsIGZvcm0gZGF0YVxyXG4gIEBPdXRwdXQoKSBvblN1Ym1pdCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpOyAvLyBDb21wbGV0ZSB2YWxpZGF0ZWQgZm9ybSBkYXRhXHJcbiAgQE91dHB1dCgpIGlzVmFsaWQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7IC8vIElzIGN1cnJlbnQgZGF0YSB2YWxpZD9cclxuICBAT3V0cHV0KCkgdmFsaWRhdGlvbkVycm9ycyA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpOyAvLyBWYWxpZGF0aW9uIGVycm9ycyAoaWYgYW55KVxyXG4gIEBPdXRwdXQoKSBmb3JtU2NoZW1hID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7IC8vIEZpbmFsIHNjaGVtYSB1c2VkIHRvIGNyZWF0ZSBmb3JtXHJcbiAgQE91dHB1dCgpIGZvcm1MYXlvdXQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTsgLy8gRmluYWwgbGF5b3V0IHVzZWQgdG8gY3JlYXRlIGZvcm1cclxuXHJcbiAgLy8gT3V0cHV0cyBmb3IgcG9zc2libGUgMi13YXkgZGF0YSBiaW5kaW5nXHJcbiAgLy8gT25seSB0aGUgb25lIGlucHV0IHByb3ZpZGluZyB0aGUgaW5pdGlhbCBmb3JtIGRhdGEgd2lsbCBiZSBib3VuZC5cclxuICAvLyBJZiB0aGVyZSBpcyBubyBpbml0YWwgZGF0YSwgaW5wdXQgJ3t9JyB0byBhY3RpdmF0ZSAyLXdheSBkYXRhIGJpbmRpbmcuXHJcbiAgLy8gVGhlcmUgaXMgbm8gMi13YXkgYmluZGluZyBpZiBpbml0YWwgZGF0YSBpcyBjb21iaW5lZCBpbnNpZGUgdGhlICdmb3JtJyBpbnB1dC5cclxuICBAT3V0cHV0KCkgZGF0YUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIEBPdXRwdXQoKSBtb2RlbENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIEBPdXRwdXQoKSBmb3JtRGF0YUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIEBPdXRwdXQoKSBuZ01vZGVsQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIG9uQ2hhbmdlOiBGdW5jdGlvbjtcclxuICBvblRvdWNoZWQ6IEZ1bmN0aW9uO1xyXG5cclxuICAvL1RPRE8tcmV2aWV3LG1heWJlIHVzZSB0YWtlVW50aWxEZXN0cm95ZWQgcnhqcyBvcFxyXG4gIGRhdGFDaGFuZ2VzU3ViczpTdWJzY3JpcHRpb247XHJcbiAgc3RhdHVzQ2hhbmdlc1N1YnM6U3Vic2NyaXB0aW9uO1xyXG4gIGlzVmFsaWRDaGFuZ2VzU3ViczpTdWJzY3JpcHRpb247XHJcbiAgdmFsaWRhdGlvbkVycm9yQ2hhbmdlc1N1YnM6U3Vic2NyaXB0aW9uO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgcHJpdmF0ZSBmcmFtZXdvcmtMaWJyYXJ5OiBGcmFtZXdvcmtMaWJyYXJ5U2VydmljZSxcclxuICAgIHByaXZhdGUgd2lkZ2V0TGlicmFyeTogV2lkZ2V0TGlicmFyeVNlcnZpY2UsXHJcbiAgICBwdWJsaWMganNmOiBKc29uU2NoZW1hRm9ybVNlcnZpY2UsXHJcbiAgKSB7IH1cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZGF0YUNoYW5nZXNTdWJzPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5zdGF0dXNDaGFuZ2VzU3Vicz8udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMuaXNWYWxpZENoYW5nZXNTdWJzPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy52YWxpZGF0aW9uRXJyb3JDaGFuZ2VzU3Vicz8udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMuZGF0YUNoYW5nZXNTdWJzPW51bGw7XHJcbiAgICB0aGlzLnN0YXR1c0NoYW5nZXNTdWJzPW51bGw7XHJcbiAgICB0aGlzLmlzVmFsaWRDaGFuZ2VzU3Vicz1udWxsO1xyXG4gICAgdGhpcy52YWxpZGF0aW9uRXJyb3JDaGFuZ2VzU3Vicz1udWxsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXNldFNjcmlwdHNBbmRTdHlsZVNoZWV0cygpIHtcclxuICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5hanNmJykuZm9yRWFjaChlbGVtZW50ID0+IGVsZW1lbnQucmVtb3ZlKCkpO1xyXG4gIH1cclxuICBwcml2YXRlIGxvYWRTY3JpcHRzKHNjcmlwdExpc3Q/OnN0cmluZ1tdKSB7XHJcbiAgICBjb25zdCBzY3JpcHRzID0gc2NyaXB0TGlzdHx8dGhpcy5mcmFtZXdvcmtMaWJyYXJ5LmdldEZyYW1ld29ya1NjcmlwdHMoKTtcclxuICAgIHNjcmlwdHMubWFwKHNjcmlwdCA9PiB7XHJcbiAgICAgIGNvbnN0IHNjcmlwdFRhZzogSFRNTFNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcclxuICAgICAgc2NyaXB0VGFnLnNyYyA9IHNjcmlwdDtcclxuICAgICAgc2NyaXB0VGFnLnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0JztcclxuICAgICAgc2NyaXB0VGFnLmFzeW5jID0gdHJ1ZTtcclxuICAgICAgc2NyaXB0VGFnLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnYWpzZicpO1xyXG4gICAgICBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdLmFwcGVuZENoaWxkKHNjcmlwdFRhZyk7XHJcbiAgICB9KTtcclxuICB9XHJcbiAgcHJpdmF0ZSBsb2FkU3R5bGVTaGVldHMoc3R5bGVMaXN0PzpzdHJpbmdbXSkge1xyXG4gICAgY29uc3Qgc3R5bGVzaGVldHMgPSBzdHlsZUxpc3R8fHRoaXMuZnJhbWV3b3JrTGlicmFyeS5nZXRGcmFtZXdvcmtTdHlsZXNoZWV0cygpO1xyXG4gICAgc3R5bGVzaGVldHMubWFwKHN0eWxlc2hlZXQgPT4ge1xyXG4gICAgICBjb25zdCBsaW5rVGFnOiBIVE1MTGlua0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaW5rJyk7XHJcbiAgICAgIGxpbmtUYWcucmVsID0gJ3N0eWxlc2hlZXQnO1xyXG4gICAgICBsaW5rVGFnLmhyZWYgPSBzdHlsZXNoZWV0O1xyXG4gICAgICBsaW5rVGFnLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnYWpzZicpO1xyXG4gICAgICBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdLmFwcGVuZENoaWxkKGxpbmtUYWcpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG4gIHByaXZhdGUgbG9hZEFzc2V0cygpIHtcclxuICAgIHRoaXMuZnJhbWV3b3JrTGlicmFyeS5nZXRGcmFtZXdvcmtBc3NldENvbmZpZygpLnRoZW4oYXNzZXRDZmc9PntcclxuICAgICAgdGhpcy5yZXNldFNjcmlwdHNBbmRTdHlsZVNoZWV0cygpO1xyXG4gICAgICB0aGlzLmxvYWRTY3JpcHRzKGFzc2V0Q2ZnLnNjcmlwdHMpO1xyXG4gICAgICB0aGlzLmxvYWRTdHlsZVNoZWV0cyhhc3NldENmZy5zdHlsZXNoZWV0cyk7XHJcbiAgICB9KS5jYXRjaChlcnI9PntcclxuICAgICAgY29uc29sZS5sb2coZXJyKTtcclxuICAgICAgdGhpcy5yZXNldFNjcmlwdHNBbmRTdHlsZVNoZWV0cygpO1xyXG4gICAgICB0aGlzLmxvYWRTY3JpcHRzKCk7XHJcbiAgICAgIHRoaXMubG9hZFN0eWxlU2hlZXRzKCk7XHJcbiAgICB9KVxyXG5cclxuICB9XHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLnVwZGF0ZUZvcm0oKTtcclxuICAgIHRoaXMubG9hZEFzc2V0cygpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgdGhpcy51cGRhdGVGb3JtKCk7XHJcbiAgICAvLyBDaGVjayBpZiB0aGVyZSdzIGNoYW5nZXMgaW4gRnJhbWV3b3JrIHRoZW4gbG9hZCBhc3NldHMgaWYgdGhhdCdzIHRoZVxyXG4gICAgaWYgKGNoYW5nZXMuZnJhbWV3b3JrKSB7XHJcbiAgICAgIGlmICghY2hhbmdlcy5mcmFtZXdvcmsuaXNGaXJzdENoYW5nZSgpICYmXHJcbiAgICAgICAgKGNoYW5nZXMuZnJhbWV3b3JrLnByZXZpb3VzVmFsdWUgIT09IGNoYW5nZXMuZnJhbWV3b3JrLmN1cnJlbnRWYWx1ZSkpIHtcclxuICAgICAgICB0aGlzLmxvYWRBc3NldHMoKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KSB7XHJcbiAgICB0aGlzLnNldEZvcm1WYWx1ZXModmFsdWUsIGZhbHNlKTtcclxuICAgIGlmICghdGhpcy5mb3JtVmFsdWVzSW5wdXQpIHsgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnbmdNb2RlbCc7IH1cclxuICB9XHJcblxyXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IEZ1bmN0aW9uKSB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogRnVuY3Rpb24pIHtcclxuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XHJcbiAgfVxyXG5cclxuICAvL3NlZSBub3RlXHJcbiAgLy9odHRwczovL2FuZ3VsYXIuaW8vZ3VpZGUvdXBkYXRlLXRvLXZlcnNpb24tMTUjdjE1LWJjLTA2XHJcbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKSB7XHJcbiAgICBpZiAodGhpcy5qc2YuZm9ybU9wdGlvbnMuZm9ybURpc2FibGVkICE9PSAhIWlzRGlzYWJsZWQpIHtcclxuICAgICAgdGhpcy5qc2YuZm9ybU9wdGlvbnMuZm9ybURpc2FibGVkID0gISFpc0Rpc2FibGVkO1xyXG4gICAgICB0aGlzLmluaXRpYWxpemVGb3JtKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB1cGRhdGVGb3JtKCkge1xyXG4gICAgICBsZXQgY2hhbmdlZERhdGE7XHJcbiAgICBpZiAoIXRoaXMuZm9ybUluaXRpYWxpemVkIHx8ICF0aGlzLmZvcm1WYWx1ZXNJbnB1dCB8fFxyXG4gICAgICAodGhpcy5sYW5ndWFnZSAmJiB0aGlzLmxhbmd1YWdlICE9PSB0aGlzLmpzZi5sYW5ndWFnZSlcclxuICAgICAgXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5pbml0aWFsaXplRm9ybSgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHRoaXMubGFuZ3VhZ2UgJiYgdGhpcy5sYW5ndWFnZSAhPT0gdGhpcy5qc2YubGFuZ3VhZ2UpIHtcclxuICAgICAgICB0aGlzLmpzZi5zZXRMYW5ndWFnZSh0aGlzLmxhbmd1YWdlKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gR2V0IG5hbWVzIG9mIGNoYW5nZWQgaW5wdXRzXHJcbiAgICAgIGxldCBjaGFuZ2VkSW5wdXQgPSBPYmplY3Qua2V5cyh0aGlzLnByZXZpb3VzSW5wdXRzKVxyXG4gICAgICAgIC5maWx0ZXIoaW5wdXQgPT4gdGhpcy5wcmV2aW91c0lucHV0c1tpbnB1dF0gIT09IHRoaXNbaW5wdXRdKTtcclxuICAgICAgbGV0IHJlc2V0Rmlyc3QgPSB0cnVlO1xyXG4gICAgICBpZiAoY2hhbmdlZElucHV0Lmxlbmd0aCA9PT0gMSAmJiBjaGFuZ2VkSW5wdXRbMF0gPT09ICdmb3JtJyAmJlxyXG4gICAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0LnN0YXJ0c1dpdGgoJ2Zvcm0uJylcclxuICAgICAgKSB7XHJcbiAgICAgICAgLy8gSWYgb25seSAnZm9ybScgaW5wdXQgY2hhbmdlZCwgZ2V0IG5hbWVzIG9mIGNoYW5nZWQga2V5c1xyXG4gICAgICAgIGNoYW5nZWRJbnB1dCA9IE9iamVjdC5rZXlzKHRoaXMucHJldmlvdXNJbnB1dHMuZm9ybSB8fCB7fSlcclxuICAgICAgICAgIC5maWx0ZXIoa2V5ID0+ICFpc0VxdWFsKHRoaXMucHJldmlvdXNJbnB1dHMuZm9ybVtrZXldLCB0aGlzLmZvcm1ba2V5XSkpXHJcbiAgICAgICAgICAubWFwKGtleSA9PiBgZm9ybS4ke2tleX1gKTtcclxuICAgICAgICByZXNldEZpcnN0ID0gZmFsc2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIElmIG9ubHkgaW5wdXQgdmFsdWVzIGhhdmUgY2hhbmdlZCwgdXBkYXRlIHRoZSBmb3JtIHZhbHVlc1xyXG4gICAgICBpZiAoY2hhbmdlZElucHV0Lmxlbmd0aCA9PT0gMSAmJiBjaGFuZ2VkSW5wdXRbMF0gPT09IHRoaXMuZm9ybVZhbHVlc0lucHV0KSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZm9ybVZhbHVlc0lucHV0LmluZGV4T2YoJy4nKSA9PT0gLTEpIHtcclxuICAgICAgICAgIGNoYW5nZWREYXRhPXRoaXNbdGhpcy5mb3JtVmFsdWVzSW5wdXRdO1xyXG4gICAgICAgICAgdGhpcy5zZXRGb3JtVmFsdWVzKGNoYW5nZWREYXRhLCByZXNldEZpcnN0KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc3QgW2lucHV0LCBrZXldID0gdGhpcy5mb3JtVmFsdWVzSW5wdXQuc3BsaXQoJy4nKTtcclxuICAgICAgICAgIGNoYW5nZWREYXRhPXRoaXNbaW5wdXRdW2tleV07XHJcbiAgICAgICAgICB0aGlzLnNldEZvcm1WYWx1ZXMoY2hhbmdlZERhdGEsIHJlc2V0Rmlyc3QpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSWYgYW55dGhpbmcgZWxzZSBoYXMgY2hhbmdlZCwgcmUtcmVuZGVyIHRoZSBlbnRpcmUgZm9ybVxyXG4gICAgICB9IGVsc2UgaWYgKGNoYW5nZWRJbnB1dC5sZW5ndGgpIHtcclxuICAgICAgICB0aGlzLmluaXRpYWxpemVGb3JtKGNoYW5nZWREYXRhKTtcclxuICAgICAgICBpZiAodGhpcy5vbkNoYW5nZSkgeyB0aGlzLm9uQ2hhbmdlKHRoaXMuanNmLmZvcm1WYWx1ZXMpOyB9XHJcbiAgICAgICAgaWYgKHRoaXMub25Ub3VjaGVkKSB7IHRoaXMub25Ub3VjaGVkKHRoaXMuanNmLmZvcm1WYWx1ZXMpOyB9XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIC8vc2V0IGZyYW1ld29yayB0aGVtZVxyXG4gICAgICBpZiAodGhpcy50aGVtZSAmJiB0aGlzLnRoZW1lICE9PSB0aGlzLmZyYW1ld29ya0xpYnJhcnkuZ2V0QWN0aXZlVGhlbWUoKT8ubmFtZSkge1xyXG4gICAgICAgIHRoaXMuZnJhbWV3b3JrTGlicmFyeS5yZXF1ZXN0VGhlbWVDaGFuZ2UodGhpcy50aGVtZSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFVwZGF0ZSBwcmV2aW91cyBpbnB1dHNcclxuICAgICAgT2JqZWN0LmtleXModGhpcy5wcmV2aW91c0lucHV0cylcclxuICAgICAgICAuZmlsdGVyKGlucHV0ID0+IHRoaXMucHJldmlvdXNJbnB1dHNbaW5wdXRdICE9PSB0aGlzW2lucHV0XSlcclxuICAgICAgICAuZm9yRWFjaChpbnB1dCA9PiB0aGlzLnByZXZpb3VzSW5wdXRzW2lucHV0XSA9IHRoaXNbaW5wdXRdKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHNldEZvcm1WYWx1ZXMoZm9ybVZhbHVlczogYW55LCByZXNldEZpcnN0ID0gdHJ1ZSkge1xyXG4gICAgaWYgKGZvcm1WYWx1ZXMpIHtcclxuICAgICAgY29uc3QgbmV3Rm9ybVZhbHVlcyA9IHRoaXMub2JqZWN0V3JhcCA/IGZvcm1WYWx1ZXNbJzEnXSA6IGZvcm1WYWx1ZXM7XHJcbiAgICAgIGlmICghdGhpcy5qc2YuZm9ybUdyb3VwKSB7XHJcbiAgICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGZvcm1WYWx1ZXM7XHJcbiAgICAgICAgdGhpcy5hY3RpdmF0ZUZvcm0oKTtcclxuICAgICAgfSBlbHNlIGlmIChyZXNldEZpcnN0KSB7Ly9jaGFuZ2VkIHRvIGF2b2lkIHJlc2V0IGV2ZW50c1xyXG4gICAgICAgIHRoaXMuanNmLmZvcm1Hcm91cC5yZXNldCh7fSx7ZW1pdEV2ZW50OmZhbHNlfSk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMuanNmLmZvcm1Hcm91cCkgey8vY2hhbmdlZCB0byBhdm9pZCByZXNldCBldmVudHNcclxuICAgICAgICB0aGlzLmpzZi5mb3JtR3JvdXAucGF0Y2hWYWx1ZShuZXdGb3JtVmFsdWVzLHtlbWl0RXZlbnQ6ZmFsc2V9KTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5vbkNoYW5nZSkgeyB0aGlzLm9uQ2hhbmdlKG5ld0Zvcm1WYWx1ZXMpOyB9XHJcbiAgICAgIGlmICh0aGlzLm9uVG91Y2hlZCkgeyB0aGlzLm9uVG91Y2hlZChuZXdGb3JtVmFsdWVzKTsgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5qc2YuZm9ybUdyb3VwLnJlc2V0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzdWJtaXRGb3JtKCkge1xyXG4gICAgY29uc3QgdmFsaWREYXRhID0gdGhpcy5qc2YudmFsaWREYXRhO1xyXG4gICAgdGhpcy5vblN1Ym1pdC5lbWl0KHRoaXMub2JqZWN0V3JhcCA/IHZhbGlkRGF0YVsnMSddIDogdmFsaWREYXRhKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdpbml0aWFsaXplRm9ybScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIC0gVXBkYXRlICdzY2hlbWEnLCAnbGF5b3V0JywgYW5kICdmb3JtVmFsdWVzJywgZnJvbSBpbnB1dHMuXHJcbiAgICpcclxuICAgKiAtIENyZWF0ZSAnc2NoZW1hUmVmTGlicmFyeScgYW5kICdzY2hlbWFSZWN1cnNpdmVSZWZNYXAnXHJcbiAgICogICB0byByZXNvbHZlIHNjaGVtYSAkcmVmIGxpbmtzLCBpbmNsdWRpbmcgcmVjdXJzaXZlICRyZWYgbGlua3MuXHJcbiAgICpcclxuICAgKiAtIENyZWF0ZSAnZGF0YVJlY3Vyc2l2ZVJlZk1hcCcgdG8gcmVzb2x2ZSByZWN1cnNpdmUgbGlua3MgaW4gZGF0YVxyXG4gICAqICAgYW5kIGNvcmVjdGx5IHNldCBvdXRwdXQgZm9ybWF0cyBmb3IgcmVjdXJzaXZlbHkgbmVzdGVkIHZhbHVlcy5cclxuICAgKlxyXG4gICAqIC0gQ3JlYXRlICdsYXlvdXRSZWZMaWJyYXJ5JyBhbmQgJ3RlbXBsYXRlUmVmTGlicmFyeScgdG8gc3RvcmVcclxuICAgKiAgIG5ldyBsYXlvdXQgbm9kZXMgYW5kIGZvcm1Hcm91cCBlbGVtZW50cyB0byB1c2Ugd2hlbiBkeW5hbWljYWxseVxyXG4gICAqICAgYWRkaW5nIGZvcm0gY29tcG9uZW50cyB0byBhcnJheXMgYW5kIHJlY3Vyc2l2ZSAkcmVmIHBvaW50cy5cclxuICAgKlxyXG4gICAqIC0gQ3JlYXRlICdkYXRhTWFwJyB0byBtYXAgdGhlIGRhdGEgdG8gdGhlIHNjaGVtYSBhbmQgdGVtcGxhdGUuXHJcbiAgICpcclxuICAgKiAtIENyZWF0ZSB0aGUgbWFzdGVyICdmb3JtR3JvdXBUZW1wbGF0ZScgdGhlbiBmcm9tIGl0ICdmb3JtR3JvdXAnXHJcbiAgICogICB0aGUgQW5ndWxhciBmb3JtR3JvdXAgdXNlZCB0byBjb250cm9sIHRoZSByZWFjdGl2ZSBmb3JtLlxyXG4gICAqL1xyXG4gIGluaXRpYWxpemVGb3JtKGluaXRpYWxEYXRhPzphbnkpIHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5zY2hlbWEgfHwgdGhpcy5sYXlvdXQgfHwgdGhpcy5kYXRhIHx8IHRoaXMuZm9ybSB8fCB0aGlzLm1vZGVsIHx8XHJcbiAgICAgIHRoaXMuSlNPTlNjaGVtYSB8fCB0aGlzLlVJU2NoZW1hIHx8IHRoaXMuZm9ybURhdGEgfHwgdGhpcy5uZ01vZGVsIHx8XHJcbiAgICAgIHRoaXMuanNmLmRhdGFcclxuICAgICkge1xyXG4gICAgICAvLyBSZXNldCBhbGwgZm9ybSB2YWx1ZXMgdG8gZGVmYXVsdHNcclxuICAgICAgdGhpcy5qc2YucmVzZXRBbGxWYWx1ZXMoKTtcclxuICAgICAgdGhpcy5pbml0aWFsaXplT3B0aW9ucygpOyAgIC8vIFVwZGF0ZSBvcHRpb25zXHJcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZVNjaGVtYSgpOyAgICAvLyBVcGRhdGUgc2NoZW1hLCBzY2hlbWFSZWZMaWJyYXJ5LFxyXG4gICAgICAvLyBzY2hlbWFSZWN1cnNpdmVSZWZNYXAsICYgZGF0YVJlY3Vyc2l2ZVJlZk1hcFxyXG4gICAgICB0aGlzLmluaXRpYWxpemVMYXlvdXQoKTsgICAgLy8gVXBkYXRlIGxheW91dCwgbGF5b3V0UmVmTGlicmFyeSxcclxuICAgICAgdGhpcy5pbml0aWFsaXplRGF0YSgpOyAgICAgIC8vIFVwZGF0ZSBmb3JtVmFsdWVzXHJcbiAgICAgIGlmKGluaXRpYWxEYXRhKXtcclxuICAgICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzPWluaXRpYWxEYXRhO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuYWN0aXZhdGVGb3JtKCk7ICAgICAgICAvLyBVcGRhdGUgZGF0YU1hcCwgdGVtcGxhdGVSZWZMaWJyYXJ5LFxyXG4gICAgICAvLyBmb3JtR3JvdXBUZW1wbGF0ZSwgZm9ybUdyb3VwXHJcblxyXG4gICAgICAvLyBVbmNvbW1lbnQgaW5kaXZpZHVhbCBsaW5lcyB0byBvdXRwdXQgZGVidWdnaW5nIGluZm9ybWF0aW9uIHRvIGNvbnNvbGU6XHJcbiAgICAgIC8vIChUaGVzZSBhbHdheXMgd29yay4pXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdsb2FkaW5nIGZvcm0uLi4nKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ3NjaGVtYScsIHRoaXMuanNmLnNjaGVtYSk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdsYXlvdXQnLCB0aGlzLmpzZi5sYXlvdXQpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnb3B0aW9ucycsIHRoaXMub3B0aW9ucyk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdmb3JtVmFsdWVzJywgdGhpcy5qc2YuZm9ybVZhbHVlcyk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdmb3JtR3JvdXBUZW1wbGF0ZScsIHRoaXMuanNmLmZvcm1Hcm91cFRlbXBsYXRlKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2Zvcm1Hcm91cCcsIHRoaXMuanNmLmZvcm1Hcm91cCk7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdmb3JtR3JvdXAudmFsdWUnLCB0aGlzLmpzZi5mb3JtR3JvdXAudmFsdWUpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnc2NoZW1hUmVmTGlicmFyeScsIHRoaXMuanNmLnNjaGVtYVJlZkxpYnJhcnkpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnbGF5b3V0UmVmTGlicmFyeScsIHRoaXMuanNmLmxheW91dFJlZkxpYnJhcnkpO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygndGVtcGxhdGVSZWZMaWJyYXJ5JywgdGhpcy5qc2YudGVtcGxhdGVSZWZMaWJyYXJ5KTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2RhdGFNYXAnLCB0aGlzLmpzZi5kYXRhTWFwKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2FycmF5TWFwJywgdGhpcy5qc2YuYXJyYXlNYXApO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnc2NoZW1hUmVjdXJzaXZlUmVmTWFwJywgdGhpcy5qc2Yuc2NoZW1hUmVjdXJzaXZlUmVmTWFwKTtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2RhdGFSZWN1cnNpdmVSZWZNYXAnLCB0aGlzLmpzZi5kYXRhUmVjdXJzaXZlUmVmTWFwKTtcclxuXHJcbiAgICAgIC8vIFVuY29tbWVudCBpbmRpdmlkdWFsIGxpbmVzIHRvIG91dHB1dCBkZWJ1Z2dpbmcgaW5mb3JtYXRpb24gdG8gYnJvd3NlcjpcclxuICAgICAgLy8gKFRoZXNlIG9ubHkgd29yayBpZiB0aGUgJ2RlYnVnJyBvcHRpb24gaGFzIGFsc28gYmVlbiBzZXQgdG8gJ3RydWUnLilcclxuICAgICAgaWYgKHRoaXMuZGVidWcgfHwgdGhpcy5qc2YuZm9ybU9wdGlvbnMuZGVidWcpIHtcclxuICAgICAgICBjb25zdCB2YXJzOiBhbnlbXSA9IFtdO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5zY2hlbWEpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5sYXlvdXQpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLm9wdGlvbnMpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5mb3JtVmFsdWVzKTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YuZm9ybUdyb3VwLnZhbHVlKTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YuZm9ybUdyb3VwVGVtcGxhdGUpO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5mb3JtR3JvdXApO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5zY2hlbWFSZWZMaWJyYXJ5KTtcclxuICAgICAgICAvLyB2YXJzLnB1c2godGhpcy5qc2YubGF5b3V0UmVmTGlicmFyeSk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLnRlbXBsYXRlUmVmTGlicmFyeSk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmRhdGFNYXApO1xyXG4gICAgICAgIC8vIHZhcnMucHVzaCh0aGlzLmpzZi5hcnJheU1hcCk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLnNjaGVtYVJlY3Vyc2l2ZVJlZk1hcCk7XHJcbiAgICAgICAgLy8gdmFycy5wdXNoKHRoaXMuanNmLmRhdGFSZWN1cnNpdmVSZWZNYXApO1xyXG4gICAgICAgIHRoaXMuZGVidWdPdXRwdXQgPSB2YXJzLm1hcCh2ID0+IEpTT04uc3RyaW5naWZ5KHYsIG51bGwsIDIpKS5qb2luKCdcXG4nKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmZvcm1Jbml0aWFsaXplZCA9IHRydWU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5pdGlhbGl6ZU9wdGlvbnMnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBJbml0aWFsaXplICdvcHRpb25zJyAoZ2xvYmFsIGZvcm0gb3B0aW9ucykgYW5kIHNldCBmcmFtZXdvcmtcclxuICAgKiBDb21iaW5lIGF2YWlsYWJsZSBpbnB1dHM6XHJcbiAgICogMS4gb3B0aW9ucyAtIHJlY29tbWVuZGVkXHJcbiAgICogMi4gZm9ybS5vcHRpb25zIC0gU2luZ2xlIGlucHV0IHN0eWxlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpbml0aWFsaXplT3B0aW9ucygpIHtcclxuICAgIGlmICh0aGlzLmxhbmd1YWdlICYmIHRoaXMubGFuZ3VhZ2UgIT09IHRoaXMuanNmLmxhbmd1YWdlKSB7XHJcbiAgICAgIHRoaXMuanNmLnNldExhbmd1YWdlKHRoaXMubGFuZ3VhZ2UpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5qc2Yuc2V0T3B0aW9ucyh7IGRlYnVnOiAhIXRoaXMuZGVidWcgfSk7XHJcbiAgICBsZXQgbG9hZEV4dGVybmFsQXNzZXRzOiBib29sZWFuID0gdGhpcy5sb2FkRXh0ZXJuYWxBc3NldHMgfHwgZmFsc2U7XHJcbiAgICBsZXQgZnJhbWV3b3JrOiBhbnkgPSB0aGlzLmZyYW1ld29yayB8fCAnZGVmYXVsdCc7XHJcbiAgICBpZiAoaXNPYmplY3QodGhpcy5vcHRpb25zKSkge1xyXG4gICAgICB0aGlzLmpzZi5zZXRPcHRpb25zKHRoaXMub3B0aW9ucyk7XHJcbiAgICAgIGxvYWRFeHRlcm5hbEFzc2V0cyA9IHRoaXMub3B0aW9ucy5sb2FkRXh0ZXJuYWxBc3NldHMgfHwgbG9hZEV4dGVybmFsQXNzZXRzO1xyXG4gICAgICBmcmFtZXdvcmsgPSB0aGlzLm9wdGlvbnMuZnJhbWV3b3JrIHx8IGZyYW1ld29yaztcclxuICAgIH1cclxuICAgIGlmIChpc09iamVjdCh0aGlzLmZvcm0pICYmIGlzT2JqZWN0KHRoaXMuZm9ybS5vcHRpb25zKSkge1xyXG4gICAgICB0aGlzLmpzZi5zZXRPcHRpb25zKHRoaXMuZm9ybS5vcHRpb25zKTtcclxuICAgICAgbG9hZEV4dGVybmFsQXNzZXRzID0gdGhpcy5mb3JtLm9wdGlvbnMubG9hZEV4dGVybmFsQXNzZXRzIHx8IGxvYWRFeHRlcm5hbEFzc2V0cztcclxuICAgICAgZnJhbWV3b3JrID0gdGhpcy5mb3JtLm9wdGlvbnMuZnJhbWV3b3JrIHx8IGZyYW1ld29yaztcclxuICAgIH1cclxuICAgIGlmIChpc09iamVjdCh0aGlzLndpZGdldHMpKSB7XHJcbiAgICAgIHRoaXMuanNmLnNldE9wdGlvbnMoeyB3aWRnZXRzOiB0aGlzLndpZGdldHMgfSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmZyYW1ld29ya0xpYnJhcnkuc2V0TG9hZEV4dGVybmFsQXNzZXRzKGxvYWRFeHRlcm5hbEFzc2V0cyk7XHJcbiAgICB0aGlzLmZyYW1ld29ya0xpYnJhcnkuc2V0RnJhbWV3b3JrKGZyYW1ld29yayk7XHJcbiAgICB0aGlzLmpzZi5mcmFtZXdvcmsgPSB0aGlzLmZyYW1ld29ya0xpYnJhcnkuZ2V0RnJhbWV3b3JrKCk7XHJcbiAgICBpZiAoaXNPYmplY3QodGhpcy5qc2YuZm9ybU9wdGlvbnMud2lkZ2V0cykpIHtcclxuICAgICAgZm9yIChjb25zdCB3aWRnZXQgb2YgT2JqZWN0LmtleXModGhpcy5qc2YuZm9ybU9wdGlvbnMud2lkZ2V0cykpIHtcclxuICAgICAgICB0aGlzLndpZGdldExpYnJhcnkucmVnaXN0ZXJXaWRnZXQod2lkZ2V0LCB0aGlzLmpzZi5mb3JtT3B0aW9ucy53aWRnZXRzW3dpZGdldF0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAoaXNPYmplY3QodGhpcy5mb3JtKSAmJiBpc09iamVjdCh0aGlzLmZvcm0udHBsZGF0YSkpIHtcclxuICAgICAgdGhpcy5qc2Yuc2V0VHBsZGF0YSh0aGlzLmZvcm0udHBsZGF0YSk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy50aGVtZSkge1xyXG4gICAgICB0aGlzLmZyYW1ld29ya0xpYnJhcnkucmVxdWVzdFRoZW1lQ2hhbmdlKHRoaXMudGhlbWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gICAqICdpbml0aWFsaXplU2NoZW1hJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogSW5pdGlhbGl6ZSAnc2NoZW1hJ1xyXG4gICAqIFVzZSBmaXJzdCBhdmFpbGFibGUgaW5wdXQ6XHJcbiAgICogMS4gc2NoZW1hIC0gcmVjb21tZW5kZWQgLyBBbmd1bGFyIFNjaGVtYSBGb3JtIHN0eWxlXHJcbiAgICogMi4gZm9ybS5zY2hlbWEgLSBTaW5nbGUgaW5wdXQgLyBKU09OIEZvcm0gc3R5bGVcclxuICAgKiAzLiBKU09OU2NoZW1hIC0gUmVhY3QgSlNPTiBTY2hlbWEgRm9ybSBzdHlsZVxyXG4gICAqIDQuIGZvcm0uSlNPTlNjaGVtYSAtIEZvciB0ZXN0aW5nIHNpbmdsZSBpbnB1dCBSZWFjdCBKU09OIFNjaGVtYSBGb3Jtc1xyXG4gICAqIDUuIGZvcm0gLSBGb3IgdGVzdGluZyBzaW5nbGUgc2NoZW1hLW9ubHkgaW5wdXRzXHJcbiAgICpcclxuICAgKiAuLi4gaWYgbm8gc2NoZW1hIGlucHV0IGZvdW5kLCB0aGUgJ2FjdGl2YXRlRm9ybScgZnVuY3Rpb24sIGJlbG93LFxyXG4gICAqICAgICB3aWxsIG1ha2UgdHdvIGFkZGl0aW9uYWwgYXR0ZW1wdHMgdG8gYnVpbGQgYSBzY2hlbWFcclxuICAgKiA2LiBJZiBsYXlvdXQgaW5wdXQgLSBidWlsZCBzY2hlbWEgZnJvbSBsYXlvdXRcclxuICAgKiA3LiBJZiBkYXRhIGlucHV0IC0gYnVpbGQgc2NoZW1hIGZyb20gZGF0YVxyXG4gICAqL1xyXG4gIHByaXZhdGUgaW5pdGlhbGl6ZVNjaGVtYSgpIHtcclxuXHJcbiAgICAvLyBUT0RPOiB1cGRhdGUgdG8gYWxsb3cgbm9uLW9iamVjdCBzY2hlbWFzXHJcblxyXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMuc2NoZW1hKSkge1xyXG4gICAgICB0aGlzLmpzZi5Bbmd1bGFyU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSBjbG9uZURlZXAodGhpcy5zY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAnc2NoZW1hJykgJiYgaXNPYmplY3QodGhpcy5mb3JtLnNjaGVtYSkpIHtcclxuICAgICAgdGhpcy5qc2Yuc2NoZW1hID0gY2xvbmVEZWVwKHRoaXMuZm9ybS5zY2hlbWEpO1xyXG4gICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLkpTT05TY2hlbWEpKSB7XHJcbiAgICAgIHRoaXMuanNmLlJlYWN0SnNvblNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2Yuc2NoZW1hID0gY2xvbmVEZWVwKHRoaXMuSlNPTlNjaGVtYSk7XHJcbiAgICB9IGVsc2UgaWYgKGhhc093bih0aGlzLmZvcm0sICdKU09OU2NoZW1hJykgJiYgaXNPYmplY3QodGhpcy5mb3JtLkpTT05TY2hlbWEpKSB7XHJcbiAgICAgIHRoaXMuanNmLlJlYWN0SnNvblNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2Yuc2NoZW1hID0gY2xvbmVEZWVwKHRoaXMuZm9ybS5KU09OU2NoZW1hKTtcclxuICAgIH0gZWxzZSBpZiAoaGFzT3duKHRoaXMuZm9ybSwgJ3Byb3BlcnRpZXMnKSAmJiBpc09iamVjdCh0aGlzLmZvcm0ucHJvcGVydGllcykpIHtcclxuICAgICAgdGhpcy5qc2Yuc2NoZW1hID0gY2xvbmVEZWVwKHRoaXMuZm9ybSk7XHJcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuZm9ybSkpIHtcclxuICAgICAgLy8gVE9ETzogSGFuZGxlIG90aGVyIHR5cGVzIG9mIGZvcm0gaW5wdXRcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIWlzRW1wdHkodGhpcy5qc2Yuc2NoZW1hKSkge1xyXG5cclxuICAgICAgLy8gSWYgb3RoZXIgdHlwZXMgYWxzbyBhbGxvd2VkLCByZW5kZXIgc2NoZW1hIGFzIGFuIG9iamVjdFxyXG4gICAgICBpZiAoaW5BcnJheSgnb2JqZWN0JywgdGhpcy5qc2Yuc2NoZW1hLnR5cGUpKSB7XHJcbiAgICAgICAgdGhpcy5qc2Yuc2NoZW1hLnR5cGUgPSAnb2JqZWN0JztcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gV3JhcCBub24tb2JqZWN0IHNjaGVtYXMgaW4gb2JqZWN0LlxyXG4gICAgICBpZiAoaGFzT3duKHRoaXMuanNmLnNjaGVtYSwgJ3R5cGUnKSAmJiB0aGlzLmpzZi5zY2hlbWEudHlwZSAhPT0gJ29iamVjdCcpIHtcclxuICAgICAgICB0aGlzLmpzZi5zY2hlbWEgPSB7XHJcbiAgICAgICAgICAndHlwZSc6ICdvYmplY3QnLFxyXG4gICAgICAgICAgJ3Byb3BlcnRpZXMnOiB7IDE6IHRoaXMuanNmLnNjaGVtYSB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLm9iamVjdFdyYXAgPSB0cnVlO1xyXG4gICAgICB9IGVsc2UgaWYgKCFoYXNPd24odGhpcy5qc2Yuc2NoZW1hLCAndHlwZScpKSB7XHJcblxyXG4gICAgICAgIC8vIEFkZCB0eXBlID0gJ29iamVjdCcgaWYgbWlzc2luZ1xyXG4gICAgICAgIGlmIChpc09iamVjdCh0aGlzLmpzZi5zY2hlbWEucHJvcGVydGllcykgfHxcclxuICAgICAgICAgIGlzT2JqZWN0KHRoaXMuanNmLnNjaGVtYS5wYXR0ZXJuUHJvcGVydGllcykgfHxcclxuICAgICAgICAgIGlzT2JqZWN0KHRoaXMuanNmLnNjaGVtYS5hZGRpdGlvbmFsUHJvcGVydGllcylcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHRoaXMuanNmLnNjaGVtYS50eXBlID0gJ29iamVjdCc7XHJcblxyXG4gICAgICAgICAgLy8gRml4IEpTT04gc2NoZW1hIHNob3J0aGFuZCAoSlNPTiBGb3JtIHN0eWxlKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLmpzZi5Kc29uRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5qc2Yuc2NoZW1hID0ge1xyXG4gICAgICAgICAgICAndHlwZSc6ICdvYmplY3QnLFxyXG4gICAgICAgICAgICAncHJvcGVydGllcyc6IHRoaXMuanNmLnNjaGVtYVxyXG4gICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIElmIG5lZWRlZCwgdXBkYXRlIEpTT04gU2NoZW1hIHRvIGRyYWZ0IDYgZm9ybWF0LCBpbmNsdWRpbmdcclxuICAgICAgLy8gZHJhZnQgMyAoSlNPTiBGb3JtIHN0eWxlKSBhbmQgZHJhZnQgNCAoQW5ndWxhciBTY2hlbWEgRm9ybSBzdHlsZSlcclxuICAgICAgdGhpcy5qc2Yuc2NoZW1hID0gY29udmVydFNjaGVtYVRvRHJhZnQ2KHRoaXMuanNmLnNjaGVtYSk7XHJcblxyXG4gICAgICAvLyBJbml0aWFsaXplIGFqdiBhbmQgY29tcGlsZSBzY2hlbWFcclxuICAgICAgdGhpcy5qc2YuY29tcGlsZUFqdlNjaGVtYSgpO1xyXG5cclxuICAgICAgLy8gQ3JlYXRlIHNjaGVtYVJlZkxpYnJhcnksIHNjaGVtYVJlY3Vyc2l2ZVJlZk1hcCwgZGF0YVJlY3Vyc2l2ZVJlZk1hcCwgJiBhcnJheU1hcFxyXG4gICAgICB0aGlzLmpzZi5zY2hlbWEgPSByZXNvbHZlU2NoZW1hUmVmZXJlbmNlcyhcclxuICAgICAgICB0aGlzLmpzZi5zY2hlbWEsIHRoaXMuanNmLnNjaGVtYVJlZkxpYnJhcnksIHRoaXMuanNmLnNjaGVtYVJlY3Vyc2l2ZVJlZk1hcCxcclxuICAgICAgICB0aGlzLmpzZi5kYXRhUmVjdXJzaXZlUmVmTWFwLCB0aGlzLmpzZi5hcnJheU1hcFxyXG4gICAgICApO1xyXG4gICAgICBpZiAoaGFzT3duKHRoaXMuanNmLnNjaGVtYVJlZkxpYnJhcnksICcnKSkge1xyXG4gICAgICAgIHRoaXMuanNmLmhhc1Jvb3RSZWZlcmVuY2UgPSB0cnVlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBUT0RPOiAoPykgUmVzb2x2ZSBleHRlcm5hbCAkcmVmIGxpbmtzXHJcbiAgICAgIC8vIC8vIENyZWF0ZSBzY2hlbWFSZWZMaWJyYXJ5ICYgc2NoZW1hUmVjdXJzaXZlUmVmTWFwXHJcbiAgICAgIC8vIHRoaXMucGFyc2VyLmJ1bmRsZSh0aGlzLnNjaGVtYSlcclxuICAgICAgLy8gICAudGhlbihzY2hlbWEgPT4gdGhpcy5zY2hlbWEgPSByZXNvbHZlU2NoZW1hUmVmZXJlbmNlcyhcclxuICAgICAgLy8gICAgIHNjaGVtYSwgdGhpcy5qc2Yuc2NoZW1hUmVmTGlicmFyeSxcclxuICAgICAgLy8gICAgIHRoaXMuanNmLnNjaGVtYVJlY3Vyc2l2ZVJlZk1hcCwgdGhpcy5qc2YuZGF0YVJlY3Vyc2l2ZVJlZk1hcFxyXG4gICAgICAvLyAgICkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2luaXRpYWxpemVEYXRhJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogSW5pdGlhbGl6ZSAnZm9ybVZhbHVlcydcclxuICAgKiBkZWZ1bGF0IG9yIHByZXZpb3VzbHkgc3VibWl0dGVkIHZhbHVlcyB1c2VkIHRvIHBvcHVsYXRlIGZvcm1cclxuICAgKiBVc2UgZmlyc3QgYXZhaWxhYmxlIGlucHV0OlxyXG4gICAqIDEuIGRhdGEgLSByZWNvbW1lbmRlZFxyXG4gICAqIDIuIG1vZGVsIC0gQW5ndWxhciBTY2hlbWEgRm9ybSBzdHlsZVxyXG4gICAqIDMuIGZvcm0udmFsdWUgLSBKU09OIEZvcm0gc3R5bGVcclxuICAgKiA0LiBmb3JtLmRhdGEgLSBTaW5nbGUgaW5wdXQgc3R5bGVcclxuICAgKiA1LiBmb3JtRGF0YSAtIFJlYWN0IEpTT04gU2NoZW1hIEZvcm0gc3R5bGVcclxuICAgKiA2LiBmb3JtLmZvcm1EYXRhIC0gRm9yIGVhc2llciB0ZXN0aW5nIG9mIFJlYWN0IEpTT04gU2NoZW1hIEZvcm1zXHJcbiAgICogNy4gKG5vbmUpIG5vIGRhdGEgLSBpbml0aWFsaXplIGRhdGEgZnJvbSBzY2hlbWEgYW5kIGxheW91dCBkZWZhdWx0cyBvbmx5XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpbml0aWFsaXplRGF0YSgpIHtcclxuICAgIGlmIChoYXNWYWx1ZSh0aGlzLmRhdGEpKSB7XHJcbiAgICAgIHRoaXMuanNmLmZvcm1WYWx1ZXMgPSBjbG9uZURlZXAodGhpcy5kYXRhKTtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnZGF0YSc7XHJcbiAgICB9IGVsc2UgaWYgKGhhc1ZhbHVlKHRoaXMubW9kZWwpKSB7XHJcbiAgICAgIHRoaXMuanNmLkFuZ3VsYXJTY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIHRoaXMuanNmLmZvcm1WYWx1ZXMgPSBjbG9uZURlZXAodGhpcy5tb2RlbCk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gJ21vZGVsJztcclxuICAgIH0gZWxzZSBpZiAoaGFzVmFsdWUodGhpcy5uZ01vZGVsKSkge1xyXG4gICAgICB0aGlzLmpzZi5Bbmd1bGFyU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5mb3JtVmFsdWVzID0gY2xvbmVEZWVwKHRoaXMubmdNb2RlbCk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gJ25nTW9kZWwnO1xyXG4gICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLmZvcm0pICYmIGhhc1ZhbHVlKHRoaXMuZm9ybS52YWx1ZSkpIHtcclxuICAgICAgdGhpcy5qc2YuSnNvbkZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGNsb25lRGVlcCh0aGlzLmZvcm0udmFsdWUpO1xyXG4gICAgICB0aGlzLmZvcm1WYWx1ZXNJbnB1dCA9ICdmb3JtLnZhbHVlJztcclxuICAgIH0gZWxzZSBpZiAoaXNPYmplY3QodGhpcy5mb3JtKSAmJiBoYXNWYWx1ZSh0aGlzLmZvcm0uZGF0YSkpIHtcclxuICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGNsb25lRGVlcCh0aGlzLmZvcm0uZGF0YSk7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gJ2Zvcm0uZGF0YSc7XHJcbiAgICB9IGVsc2UgaWYgKGhhc1ZhbHVlKHRoaXMuZm9ybURhdGEpKSB7XHJcbiAgICAgIHRoaXMuanNmLlJlYWN0SnNvblNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5mb3JtVmFsdWVzSW5wdXQgPSAnZm9ybURhdGEnO1xyXG4gICAgfSBlbHNlIGlmIChoYXNPd24odGhpcy5mb3JtLCAnZm9ybURhdGEnKSAmJiBoYXNWYWx1ZSh0aGlzLmZvcm0uZm9ybURhdGEpKSB7XHJcbiAgICAgIHRoaXMuanNmLlJlYWN0SnNvblNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2YuZm9ybVZhbHVlcyA9IGNsb25lRGVlcCh0aGlzLmZvcm0uZm9ybURhdGEpO1xyXG4gICAgICB0aGlzLmZvcm1WYWx1ZXNJbnB1dCA9ICdmb3JtLmZvcm1EYXRhJztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZm9ybVZhbHVlc0lucHV0ID0gXCJkYXRhXCI7Ly9udWxsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2luaXRpYWxpemVMYXlvdXQnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBJbml0aWFsaXplICdsYXlvdXQnXHJcbiAgICogVXNlIGZpcnN0IGF2YWlsYWJsZSBhcnJheSBpbnB1dDpcclxuICAgKiAxLiBsYXlvdXQgLSByZWNvbW1lbmRlZFxyXG4gICAqIDIuIGZvcm0gLSBBbmd1bGFyIFNjaGVtYSBGb3JtIHN0eWxlXHJcbiAgICogMy4gZm9ybS5mb3JtIC0gSlNPTiBGb3JtIHN0eWxlXHJcbiAgICogNC4gZm9ybS5sYXlvdXQgLSBTaW5nbGUgaW5wdXQgc3R5bGVcclxuICAgKiA1LiAobm9uZSkgbm8gbGF5b3V0IC0gc2V0IGRlZmF1bHQgbGF5b3V0IGluc3RlYWRcclxuICAgKiAgICAoZnVsbCBsYXlvdXQgd2lsbCBiZSBidWlsdCBsYXRlciBmcm9tIHRoZSBzY2hlbWEpXHJcbiAgICpcclxuICAgKiBBbHNvLCBpZiBhbHRlcm5hdGUgbGF5b3V0IGZvcm1hdHMgYXJlIGF2YWlsYWJsZSxcclxuICAgKiBpbXBvcnQgZnJvbSAnVUlTY2hlbWEnIG9yICdjdXN0b21Gb3JtSXRlbXMnXHJcbiAgICogdXNlZCBmb3IgUmVhY3QgSlNPTiBTY2hlbWEgRm9ybSBhbmQgSlNPTiBGb3JtIEFQSSBjb21wYXRpYmlsaXR5XHJcbiAgICogVXNlIGZpcnN0IGF2YWlsYWJsZSBpbnB1dDpcclxuICAgKiAxLiBVSVNjaGVtYSAtIFJlYWN0IEpTT04gU2NoZW1hIEZvcm0gc3R5bGVcclxuICAgKiAyLiBmb3JtLlVJU2NoZW1hIC0gRm9yIHRlc3Rpbmcgc2luZ2xlIGlucHV0IFJlYWN0IEpTT04gU2NoZW1hIEZvcm1zXHJcbiAgICogMi4gZm9ybS5jdXN0b21Gb3JtSXRlbXMgLSBKU09OIEZvcm0gc3R5bGVcclxuICAgKiAzLiAobm9uZSkgbm8gaW5wdXQgLSBkb24ndCBpbXBvcnRcclxuICAgKi9cclxuICBwcml2YXRlIGluaXRpYWxpemVMYXlvdXQoKSB7XHJcblxyXG4gICAgLy8gUmVuYW1lIEpTT04gRm9ybS1zdHlsZSAnb3B0aW9ucycgbGlzdHMgdG9cclxuICAgIC8vIEFuZ3VsYXIgU2NoZW1hIEZvcm0tc3R5bGUgJ3RpdGxlTWFwJyBsaXN0cy5cclxuICAgIGNvbnN0IGZpeEpzb25Gb3JtT3B0aW9ucyA9IChsYXlvdXQ6IGFueSk6IGFueSA9PiB7XHJcbiAgICAgIGlmIChpc09iamVjdChsYXlvdXQpIHx8IGlzQXJyYXkobGF5b3V0KSkge1xyXG4gICAgICAgIGZvckVhY2gobGF5b3V0LCAodmFsdWUsIGtleSkgPT4ge1xyXG4gICAgICAgICAgaWYgKGhhc093bih2YWx1ZSwgJ29wdGlvbnMnKSAmJiBpc09iamVjdCh2YWx1ZS5vcHRpb25zKSkge1xyXG4gICAgICAgICAgICB2YWx1ZS50aXRsZU1hcCA9IHZhbHVlLm9wdGlvbnM7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB2YWx1ZS5vcHRpb25zO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0sICd0b3AtZG93bicpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBsYXlvdXQ7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIENoZWNrIGZvciBsYXlvdXQgaW5wdXRzIGFuZCwgaWYgZm91bmQsIGluaXRpYWxpemUgZm9ybSBsYXlvdXRcclxuICAgIGlmIChpc0FycmF5KHRoaXMubGF5b3V0KSkge1xyXG4gICAgICB0aGlzLmpzZi5sYXlvdXQgPSBjbG9uZURlZXAodGhpcy5sYXlvdXQpO1xyXG4gICAgfSBlbHNlIGlmIChpc0FycmF5KHRoaXMuZm9ybSkpIHtcclxuICAgICAgdGhpcy5qc2YuQW5ndWxhclNjaGVtYUZvcm1Db21wYXRpYmlsaXR5ID0gdHJ1ZTtcclxuICAgICAgdGhpcy5qc2YubGF5b3V0ID0gY2xvbmVEZWVwKHRoaXMuZm9ybSk7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuZm9ybSAmJiBpc0FycmF5KHRoaXMuZm9ybS5mb3JtKSkge1xyXG4gICAgICB0aGlzLmpzZi5Kc29uRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICB0aGlzLmpzZi5sYXlvdXQgPSBmaXhKc29uRm9ybU9wdGlvbnMoY2xvbmVEZWVwKHRoaXMuZm9ybS5mb3JtKSk7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuZm9ybSAmJiBpc0FycmF5KHRoaXMuZm9ybS5sYXlvdXQpKSB7XHJcbiAgICAgIHRoaXMuanNmLmxheW91dCA9IGNsb25lRGVlcCh0aGlzLmZvcm0ubGF5b3V0KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuanNmLmxheW91dCA9IFsnKiddO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrIGZvciBhbHRlcm5hdGUgbGF5b3V0IGlucHV0c1xyXG4gICAgbGV0IGFsdGVybmF0ZUxheW91dDogYW55ID0gbnVsbDtcclxuICAgIGlmIChpc09iamVjdCh0aGlzLlVJU2NoZW1hKSkge1xyXG4gICAgICB0aGlzLmpzZi5SZWFjdEpzb25TY2hlbWFGb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIGFsdGVybmF0ZUxheW91dCA9IGNsb25lRGVlcCh0aGlzLlVJU2NoZW1hKTtcclxuICAgIH0gZWxzZSBpZiAoaGFzT3duKHRoaXMuZm9ybSwgJ1VJU2NoZW1hJykpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICBhbHRlcm5hdGVMYXlvdXQgPSBjbG9uZURlZXAodGhpcy5mb3JtLlVJU2NoZW1hKTtcclxuICAgIH0gZWxzZSBpZiAoaGFzT3duKHRoaXMuZm9ybSwgJ3VpU2NoZW1hJykpIHtcclxuICAgICAgdGhpcy5qc2YuUmVhY3RKc29uU2NoZW1hRm9ybUNvbXBhdGliaWxpdHkgPSB0cnVlO1xyXG4gICAgICBhbHRlcm5hdGVMYXlvdXQgPSBjbG9uZURlZXAodGhpcy5mb3JtLnVpU2NoZW1hKTtcclxuICAgIH0gZWxzZSBpZiAoaGFzT3duKHRoaXMuZm9ybSwgJ2N1c3RvbUZvcm1JdGVtcycpKSB7XHJcbiAgICAgIHRoaXMuanNmLkpzb25Gb3JtQ29tcGF0aWJpbGl0eSA9IHRydWU7XHJcbiAgICAgIGFsdGVybmF0ZUxheW91dCA9IGZpeEpzb25Gb3JtT3B0aW9ucyhjbG9uZURlZXAodGhpcy5mb3JtLmN1c3RvbUZvcm1JdGVtcykpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGlmIGFsdGVybmF0ZSBsYXlvdXQgZm91bmQsIGNvcHkgYWx0ZXJuYXRlIGxheW91dCBvcHRpb25zIGludG8gc2NoZW1hXHJcbiAgICBpZiAoYWx0ZXJuYXRlTGF5b3V0KSB7XHJcbiAgICAgIEpzb25Qb2ludGVyLmZvckVhY2hEZWVwKGFsdGVybmF0ZUxheW91dCwgKHZhbHVlLCBwb2ludGVyKSA9PiB7XHJcbiAgICAgICAgY29uc3Qgc2NoZW1hUG9pbnRlciA9IHBvaW50ZXJcclxuICAgICAgICAgIC5yZXBsYWNlKC9cXC8vZywgJy9wcm9wZXJ0aWVzLycpXHJcbiAgICAgICAgICAucmVwbGFjZSgvXFwvcHJvcGVydGllc1xcL2l0ZW1zXFwvcHJvcGVydGllc1xcLy9nLCAnL2l0ZW1zL3Byb3BlcnRpZXMvJylcclxuICAgICAgICAgIC5yZXBsYWNlKC9cXC9wcm9wZXJ0aWVzXFwvdGl0bGVNYXBcXC9wcm9wZXJ0aWVzXFwvL2csICcvdGl0bGVNYXAvcHJvcGVydGllcy8nKTtcclxuICAgICAgICBpZiAoaGFzVmFsdWUodmFsdWUpICYmIGhhc1ZhbHVlKHBvaW50ZXIpKSB7XHJcbiAgICAgICAgICBsZXQga2V5ID0gSnNvblBvaW50ZXIudG9LZXkocG9pbnRlcik7XHJcbiAgICAgICAgICBjb25zdCBncm91cFBvaW50ZXIgPSAoSnNvblBvaW50ZXIucGFyc2Uoc2NoZW1hUG9pbnRlcikgfHwgW10pLnNsaWNlKDAsIC0yKTtcclxuICAgICAgICAgIGxldCBpdGVtUG9pbnRlcjogc3RyaW5nIHwgc3RyaW5nW107XHJcblxyXG4gICAgICAgICAgLy8gSWYgJ3VpOm9yZGVyJyBvYmplY3QgZm91bmQsIGNvcHkgaW50byBvYmplY3Qgc2NoZW1hIHJvb3RcclxuICAgICAgICAgIGlmIChrZXkudG9Mb3dlckNhc2UoKSA9PT0gJ3VpOm9yZGVyJykge1xyXG4gICAgICAgICAgICBpdGVtUG9pbnRlciA9IFsuLi5ncm91cFBvaW50ZXIsICd1aTpvcmRlciddO1xyXG5cclxuICAgICAgICAgICAgLy8gQ29weSBvdGhlciBhbHRlcm5hdGUgbGF5b3V0IG9wdGlvbnMgdG8gc2NoZW1hICd4LXNjaGVtYS1mb3JtJyxcclxuICAgICAgICAgICAgLy8gKGxpa2UgQW5ndWxhciBTY2hlbWEgRm9ybSBvcHRpb25zKSBhbmQgcmVtb3ZlIGFueSAndWk6JyBwcmVmaXhlc1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKGtleS5zbGljZSgwLCAzKS50b0xvd2VyQ2FzZSgpID09PSAndWk6JykgeyBrZXkgPSBrZXkuc2xpY2UoMyk7IH1cclxuICAgICAgICAgICAgaXRlbVBvaW50ZXIgPSBbLi4uZ3JvdXBQb2ludGVyLCAneC1zY2hlbWEtZm9ybScsIGtleV07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAoSnNvblBvaW50ZXIuaGFzKHRoaXMuanNmLnNjaGVtYSwgZ3JvdXBQb2ludGVyKSAmJlxyXG4gICAgICAgICAgICAhSnNvblBvaW50ZXIuaGFzKHRoaXMuanNmLnNjaGVtYSwgaXRlbVBvaW50ZXIpXHJcbiAgICAgICAgICApIHtcclxuICAgICAgICAgICAgSnNvblBvaW50ZXIuc2V0KHRoaXMuanNmLnNjaGVtYSwgaXRlbVBvaW50ZXIsIHZhbHVlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2FjdGl2YXRlRm9ybScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIC4uLmNvbnRpbnVlZCBmcm9tICdpbml0aWFsaXplU2NoZW1hJyBmdW5jdGlvbiwgYWJvdmVcclxuICAgKiBJZiAnc2NoZW1hJyBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQgKGkuZS4gbm8gc2NoZW1hIGlucHV0IGZvdW5kKVxyXG4gICAqIDYuIElmIGxheW91dCBpbnB1dCAtIGJ1aWxkIHNjaGVtYSBmcm9tIGxheW91dCBpbnB1dFxyXG4gICAqIDcuIElmIGRhdGEgaW5wdXQgLSBidWlsZCBzY2hlbWEgZnJvbSBkYXRhIGlucHV0XHJcbiAgICpcclxuICAgKiBDcmVhdGUgZmluYWwgbGF5b3V0LFxyXG4gICAqIGJ1aWxkIHRoZSBGb3JtR3JvdXAgdGVtcGxhdGUgYW5kIHRoZSBBbmd1bGFyIEZvcm1Hcm91cCxcclxuICAgKiBzdWJzY3JpYmUgdG8gY2hhbmdlcyxcclxuICAgKiBhbmQgYWN0aXZhdGUgdGhlIGZvcm0uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhY3RpdmF0ZUZvcm0oKSB7XHJcbiAgICB0aGlzLnVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kLm5leHQoKTtcclxuICAgIC8vIElmICdzY2hlbWEnIG5vdCBpbml0aWFsaXplZFxyXG4gICAgaWYgKGlzRW1wdHkodGhpcy5qc2Yuc2NoZW1hKSkge1xyXG5cclxuICAgICAgLy8gVE9ETzogSWYgZnVsbCBsYXlvdXQgaW5wdXQgKHdpdGggbm8gJyonKSwgYnVpbGQgc2NoZW1hIGZyb20gbGF5b3V0XHJcbiAgICAgIC8vIGlmICghdGhpcy5qc2YubGF5b3V0LmluY2x1ZGVzKCcqJykpIHtcclxuICAgICAgLy8gICB0aGlzLmpzZi5idWlsZFNjaGVtYUZyb21MYXlvdXQoKTtcclxuICAgICAgLy8gfSBlbHNlXHJcblxyXG4gICAgICAvLyBJZiBkYXRhIGlucHV0LCBidWlsZCBzY2hlbWEgZnJvbSBkYXRhXHJcbiAgICAgIGlmICghaXNFbXB0eSh0aGlzLmpzZi5mb3JtVmFsdWVzKSkge1xyXG4gICAgICAgIHRoaXMuanNmLmJ1aWxkU2NoZW1hRnJvbURhdGEoKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICghaXNFbXB0eSh0aGlzLmpzZi5zY2hlbWEpKSB7XHJcblxyXG4gICAgICAvLyBJZiBub3QgYWxyZWFkeSBpbml0aWFsaXplZCwgaW5pdGlhbGl6ZSBhanYgYW5kIGNvbXBpbGUgc2NoZW1hXHJcbiAgICAgIHRoaXMuanNmLmNvbXBpbGVBanZTY2hlbWEoKTtcclxuXHJcbiAgICAgIC8vIFVwZGF0ZSBhbGwgbGF5b3V0IGVsZW1lbnRzLCBhZGQgdmFsdWVzLCB3aWRnZXRzLCBhbmQgdmFsaWRhdG9ycyxcclxuICAgICAgLy8gcmVwbGFjZSBhbnkgJyonIHdpdGggYSBsYXlvdXQgYnVpbHQgZnJvbSBhbGwgc2NoZW1hIGVsZW1lbnRzLFxyXG4gICAgICAvLyBhbmQgdXBkYXRlIHRoZSBGb3JtR3JvdXAgdGVtcGxhdGUgd2l0aCBhbnkgbmV3IHZhbGlkYXRvcnNcclxuICAgICAgdGhpcy5qc2YuYnVpbGRMYXlvdXQodGhpcy53aWRnZXRMaWJyYXJ5KTtcclxuXHJcbiAgICAgIC8vIEJ1aWxkIHRoZSBBbmd1bGFyIEZvcm1Hcm91cCB0ZW1wbGF0ZSBmcm9tIHRoZSBzY2hlbWFcclxuICAgICAgdGhpcy5qc2YuYnVpbGRGb3JtR3JvdXBUZW1wbGF0ZSh0aGlzLmpzZi5mb3JtVmFsdWVzKTtcclxuXHJcbiAgICAgIC8vIEJ1aWxkIHRoZSByZWFsIEFuZ3VsYXIgRm9ybUdyb3VwIGZyb20gdGhlIEZvcm1Hcm91cCB0ZW1wbGF0ZVxyXG4gICAgICB0aGlzLmpzZi5idWlsZEZvcm1Hcm91cCgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmpzZi5mb3JtR3JvdXApIHtcclxuXHJcbiAgICAgIC8vIFJlc2V0IGluaXRpYWwgZm9ybSB2YWx1ZXNcclxuICAgICAgaWYgKCFpc0VtcHR5KHRoaXMuanNmLmZvcm1WYWx1ZXMpICYmXHJcbiAgICAgICAgdGhpcy5qc2YuZm9ybU9wdGlvbnMuc2V0U2NoZW1hRGVmYXVsdHMgIT09IHRydWUgJiZcclxuICAgICAgICB0aGlzLmpzZi5mb3JtT3B0aW9ucy5zZXRMYXlvdXREZWZhdWx0cyAhPT0gdHJ1ZVxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLnNldEZvcm1WYWx1ZXModGhpcy5qc2YuZm9ybVZhbHVlcyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFRPRE86IEZpZ3VyZSBvdXQgaG93IHRvIGRpc3BsYXkgY2FsY3VsYXRlZCB2YWx1ZXMgd2l0aG91dCBjaGFuZ2luZyBvYmplY3QgZGF0YVxyXG4gICAgICAvLyBTZWUgaHR0cDovL3VsaW9uLmdpdGh1Yi5pby9qc29uZm9ybS9wbGF5Z3JvdW5kLz9leGFtcGxlPXRlbXBsYXRpbmctdmFsdWVzXHJcbiAgICAgIC8vIENhbGN1bGF0ZSByZWZlcmVuY2VzIHRvIG90aGVyIGZpZWxkc1xyXG4gICAgICAvLyBpZiAoIWlzRW1wdHkodGhpcy5qc2YuZm9ybUdyb3VwLnZhbHVlKSkge1xyXG4gICAgICAvLyAgIGZvckVhY2godGhpcy5qc2YuZm9ybUdyb3VwLnZhbHVlLCAodmFsdWUsIGtleSwgb2JqZWN0LCByb290T2JqZWN0KSA9PiB7XHJcbiAgICAgIC8vICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAvLyAgICAgICBvYmplY3Rba2V5XSA9IHRoaXMuanNmLnBhcnNlVGV4dCh2YWx1ZSwgdmFsdWUsIHJvb3RPYmplY3QsIGtleSk7XHJcbiAgICAgIC8vICAgICB9XHJcbiAgICAgIC8vICAgfSwgJ3RvcC1kb3duJyk7XHJcbiAgICAgIC8vIH1cclxuXHJcbiAgICAgIC8vIFN1YnNjcmliZSB0byBmb3JtIGNoYW5nZXMgdG8gb3V0cHV0IGxpdmUgZGF0YSwgdmFsaWRhdGlvbiwgYW5kIGVycm9yc1xyXG4gICAgICB0aGlzLmRhdGFDaGFuZ2VzU3Vicz10aGlzLmpzZi5kYXRhQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kKSkuc3Vic2NyaWJlKGRhdGEgPT4ge1xyXG4gICAgICAgIHRoaXMub25DaGFuZ2VzLmVtaXQodGhpcy5vYmplY3RXcmFwID8gZGF0YVsnMSddIDogZGF0YSk7XHJcbiAgICAgICAgaWYgKHRoaXMuZm9ybVZhbHVlc0lucHV0ICYmIHRoaXMuZm9ybVZhbHVlc0lucHV0LmluZGV4T2YoJy4nKSA9PT0gLTEpIHtcclxuICAgICAgICAgIHRoaXNbYCR7dGhpcy5mb3JtVmFsdWVzSW5wdXR9Q2hhbmdlYF0uZW1pdCh0aGlzLm9iamVjdFdyYXAgPyBkYXRhWycxJ10gOiBkYXRhKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gVHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uIG9uIHN0YXR1c0NoYW5nZXMgdG8gc2hvdyB1cGRhdGVkIGVycm9yc1xyXG4gICAgICB0aGlzLnN0YXR1c0NoYW5nZXNTdWJzPSB0aGlzLmpzZi5mb3JtR3JvdXAuc3RhdHVzQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kKSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCkpO1xyXG4gICAgICB0aGlzLmlzVmFsaWRDaGFuZ2VzU3Vicz10aGlzLmpzZi5pc1ZhbGlkQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlT25BY3RpdmF0ZUZvcm0kKSkuc3Vic2NyaWJlKGlzVmFsaWQgPT4gdGhpcy5pc1ZhbGlkLmVtaXQoaXNWYWxpZCkpO1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25FcnJvckNoYW5nZXNTdWJzPXRoaXMuanNmLnZhbGlkYXRpb25FcnJvckNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZU9uQWN0aXZhdGVGb3JtJCkpLnN1YnNjcmliZShlcnIgPT4gdGhpcy52YWxpZGF0aW9uRXJyb3JzLmVtaXQoZXJyKSk7XHJcblxyXG4gICAgICAvLyBPdXRwdXQgZmluYWwgc2NoZW1hLCBmaW5hbCBsYXlvdXQsIGFuZCBpbml0aWFsIGRhdGFcclxuICAgICAgdGhpcy5mb3JtU2NoZW1hLmVtaXQodGhpcy5qc2Yuc2NoZW1hKTtcclxuICAgICAgdGhpcy5mb3JtTGF5b3V0LmVtaXQodGhpcy5qc2YubGF5b3V0KTtcclxuICAgICAgdGhpcy5vbkNoYW5nZXMuZW1pdCh0aGlzLm9iamVjdFdyYXAgPyB0aGlzLmpzZi5kYXRhWycxJ10gOiB0aGlzLmpzZi5kYXRhKTtcclxuXHJcbiAgICAgIC8vIElmIHZhbGlkYXRlT25SZW5kZXIsIG91dHB1dCBpbml0aWFsIHZhbGlkYXRpb24gYW5kIGFueSBlcnJvcnNcclxuICAgICAgY29uc3QgdmFsaWRhdGVPblJlbmRlciA9XHJcbiAgICAgICAgSnNvblBvaW50ZXIuZ2V0KHRoaXMuanNmLCAnL2Zvcm1PcHRpb25zL3ZhbGlkYXRlT25SZW5kZXInKTtcclxuICAgICAgaWYgKHZhbGlkYXRlT25SZW5kZXIpIHsgLy8gdmFsaWRhdGVPblJlbmRlciA9PT0gJ2F1dG8nIHx8IHRydWVcclxuICAgICAgICBjb25zdCB0b3VjaEFsbCA9IChjb250cm9sKSA9PiB7XHJcbiAgICAgICAgICBpZiAodmFsaWRhdGVPblJlbmRlciA9PT0gdHJ1ZSB8fCBoYXNWYWx1ZShjb250cm9sLnZhbHVlKSkge1xyXG4gICAgICAgICAgICBjb250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIE9iamVjdC5rZXlzKGNvbnRyb2wuY29udHJvbHMgfHwge30pXHJcbiAgICAgICAgICAgIC5mb3JFYWNoKGtleSA9PiB0b3VjaEFsbChjb250cm9sLmNvbnRyb2xzW2tleV0pKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIHRvdWNoQWxsKHRoaXMuanNmLmZvcm1Hcm91cCk7XHJcbiAgICAgICAgdGhpcy5pc1ZhbGlkLmVtaXQodGhpcy5qc2YuaXNWYWxpZCk7XHJcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uRXJyb3JzLmVtaXQodGhpcy5qc2YuYWp2RXJyb3JzKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbn1cclxuIiwiPGZvcm0gW2F1dG9jb21wbGV0ZV09XCJqc2Y/LmZvcm1PcHRpb25zPy5hdXRvY29tcGxldGUgPyAnb24nIDogJ29mZidcIiBjbGFzcz1cImpzb24tc2NoZW1hLWZvcm1cIiAobmdTdWJtaXQpPVwic3VibWl0Rm9ybSgpXCI+XHJcbiAgPHJvb3Qtd2lkZ2V0IFtsYXlvdXRdPVwianNmPy5sYXlvdXRcIj48L3Jvb3Qtd2lkZ2V0PlxyXG48L2Zvcm0+XHJcbjxkaXYgKm5nSWY9XCJkZWJ1ZyB8fCBqc2Y/LmZvcm1PcHRpb25zPy5kZWJ1Z1wiPlxyXG4gIERlYnVnIG91dHB1dDpcclxuICA8cHJlPnt7ZGVidWdPdXRwdXR9fTwvcHJlPlxyXG48L2Rpdj4iXX0=
|