@ngrx/data 12.4.0 → 13.0.0-rc.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.
Files changed (156) hide show
  1. package/{esm2015/index.js → esm2020/index.mjs} +0 -0
  2. package/esm2020/ngrx-data.mjs +5 -0
  3. package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
  4. package/esm2020/src/actions/entity-action-factory.mjs +50 -0
  5. package/{esm2015/src/actions/entity-action-guard.js → esm2020/src/actions/entity-action-guard.mjs} +0 -0
  6. package/{esm2015/src/actions/entity-action-operators.js → esm2020/src/actions/entity-action-operators.mjs} +0 -0
  7. package/{esm2015/src/actions/entity-action.js → esm2020/src/actions/entity-action.mjs} +0 -0
  8. package/esm2020/src/actions/entity-cache-action.mjs +116 -0
  9. package/esm2020/src/actions/entity-cache-change-set.mjs +50 -0
  10. package/{esm2015/src/actions/entity-op.js → esm2020/src/actions/entity-op.mjs} +0 -0
  11. package/{esm2015/src/actions/merge-strategy.js → esm2020/src/actions/merge-strategy.mjs} +0 -0
  12. package/{esm2015/src/actions/update-response-data.js → esm2020/src/actions/update-response-data.mjs} +0 -0
  13. package/{esm2015/src/dataservices/data-service-error.js → esm2020/src/dataservices/data-service-error.mjs} +0 -0
  14. package/{esm2015/src/dataservices/default-data-service-config.js → esm2020/src/dataservices/default-data-service-config.mjs} +0 -0
  15. package/{esm2015/src/dataservices/default-data.service.js → esm2020/src/dataservices/default-data.service.mjs} +13 -13
  16. package/esm2020/src/dataservices/entity-cache-data.service.mjs +146 -0
  17. package/esm2020/src/dataservices/entity-data.service.mjs +63 -0
  18. package/{esm2015/src/dataservices/http-url-generator.js → esm2020/src/dataservices/http-url-generator.mjs} +12 -10
  19. package/{esm2015/src/dataservices/interfaces.js → esm2020/src/dataservices/interfaces.mjs} +0 -0
  20. package/esm2020/src/dataservices/persistence-result-handler.service.mjs +49 -0
  21. package/esm2020/src/dispatchers/entity-cache-dispatcher.mjs +163 -0
  22. package/{esm2015/src/dispatchers/entity-commands.js → esm2020/src/dispatchers/entity-commands.mjs} +0 -0
  23. package/esm2020/src/dispatchers/entity-dispatcher-base.mjs +405 -0
  24. package/esm2020/src/dispatchers/entity-dispatcher-default-options.mjs +30 -0
  25. package/esm2020/src/dispatchers/entity-dispatcher-factory.mjs +65 -0
  26. package/{esm2015/src/dispatchers/entity-dispatcher.js → esm2020/src/dispatchers/entity-dispatcher.mjs} +0 -0
  27. package/esm2020/src/effects/entity-cache-effects.mjs +115 -0
  28. package/{esm2015/src/effects/entity-effects-scheduler.js → esm2020/src/effects/entity-effects-scheduler.mjs} +0 -0
  29. package/esm2020/src/effects/entity-effects.mjs +148 -0
  30. package/esm2020/src/entity-data-without-effects.module.mjs +160 -0
  31. package/esm2020/src/entity-data.module.mjs +121 -0
  32. package/esm2020/src/entity-metadata/entity-definition.mjs +33 -0
  33. package/esm2020/src/entity-metadata/entity-definition.service.mjs +93 -0
  34. package/{esm2015/src/entity-metadata/entity-filters.js → esm2020/src/entity-metadata/entity-filters.mjs} +0 -0
  35. package/{esm2015/src/entity-metadata/entity-metadata.js → esm2020/src/entity-metadata/entity-metadata.mjs} +0 -0
  36. package/{esm2015/src/entity-services/entity-collection-service-base.js → esm2020/src/entity-services/entity-collection-service-base.mjs} +0 -0
  37. package/esm2020/src/entity-services/entity-collection-service-elements-factory.mjs +38 -0
  38. package/esm2020/src/entity-services/entity-collection-service-factory.mjs +28 -0
  39. package/{esm2015/src/entity-services/entity-collection-service.js → esm2020/src/entity-services/entity-collection-service.mjs} +0 -0
  40. package/esm2020/src/entity-services/entity-services-base.mjs +119 -0
  41. package/esm2020/src/entity-services/entity-services-elements.mjs +33 -0
  42. package/{esm2015/src/entity-services/entity-services.js → esm2020/src/entity-services/entity-services.mjs} +0 -0
  43. package/{esm2015/src/index.js → esm2020/src/index.mjs} +0 -0
  44. package/{esm2015/src/reducers/constants.js → esm2020/src/reducers/constants.mjs} +0 -0
  45. package/esm2020/src/reducers/entity-cache-reducer.mjs +271 -0
  46. package/{esm2015/src/reducers/entity-cache.js → esm2020/src/reducers/entity-cache.mjs} +0 -0
  47. package/esm2020/src/reducers/entity-change-tracker-base.mjs +587 -0
  48. package/{esm2015/src/reducers/entity-change-tracker.js → esm2020/src/reducers/entity-change-tracker.mjs} +0 -0
  49. package/esm2020/src/reducers/entity-collection-creator.mjs +37 -0
  50. package/esm2020/src/reducers/entity-collection-reducer-methods.mjs +806 -0
  51. package/esm2020/src/reducers/entity-collection-reducer-registry.mjs +68 -0
  52. package/esm2020/src/reducers/entity-collection-reducer.mjs +24 -0
  53. package/{esm2015/src/reducers/entity-collection.js → esm2020/src/reducers/entity-collection.mjs} +0 -0
  54. package/{esm2015/src/selectors/entity-cache-selector.js → esm2020/src/selectors/entity-cache-selector.mjs} +0 -0
  55. package/esm2020/src/selectors/entity-selectors$.mjs +52 -0
  56. package/esm2020/src/selectors/entity-selectors.mjs +96 -0
  57. package/esm2020/src/utils/correlation-id-generator.mjs +30 -0
  58. package/esm2020/src/utils/default-logger.mjs +25 -0
  59. package/esm2020/src/utils/default-pluralizer.mjs +71 -0
  60. package/{esm2015/src/utils/guid-fns.js → esm2020/src/utils/guid-fns.mjs} +0 -0
  61. package/{esm2015/src/utils/interfaces.js → esm2020/src/utils/interfaces.mjs} +0 -0
  62. package/{esm2015/src/utils/utilities.js → esm2020/src/utils/utilities.mjs} +0 -0
  63. package/fesm2015/{ngrx-data.js → ngrx-data.mjs} +343 -286
  64. package/fesm2015/ngrx-data.mjs.map +1 -0
  65. package/fesm2020/ngrx-data.mjs +4936 -0
  66. package/fesm2020/ngrx-data.mjs.map +1 -0
  67. package/ngrx-data.d.ts +1 -1
  68. package/package.json +26 -14
  69. package/schematics/ng-add/index.js +29 -25
  70. package/schematics/ng-add/index.js.map +1 -1
  71. package/schematics-core/index.js +2 -1
  72. package/schematics-core/index.js.map +1 -1
  73. package/schematics-core/utility/angular-utils.js +6 -5
  74. package/schematics-core/utility/angular-utils.js.map +1 -1
  75. package/schematics-core/utility/ast-utils.js +12 -8
  76. package/schematics-core/utility/ast-utils.js.map +1 -1
  77. package/schematics-core/utility/find-component.js +12 -12
  78. package/schematics-core/utility/find-component.js.map +1 -1
  79. package/schematics-core/utility/find-module.js +12 -12
  80. package/schematics-core/utility/find-module.js.map +1 -1
  81. package/schematics-core/utility/json-utilts.js.map +1 -1
  82. package/schematics-core/utility/libs-version.js +1 -1
  83. package/schematics-core/utility/libs-version.js.map +1 -1
  84. package/schematics-core/utility/ngrx-utils.js +23 -13
  85. package/schematics-core/utility/ngrx-utils.js.map +1 -1
  86. package/schematics-core/utility/parse-name.js +3 -3
  87. package/schematics-core/utility/parse-name.js.map +1 -1
  88. package/schematics-core/utility/project.js +1 -1
  89. package/schematics-core/utility/project.js.map +1 -1
  90. package/schematics-core/utility/visitors.js +2 -2
  91. package/schematics-core/utility/visitors.js.map +1 -1
  92. package/src/actions/entity-action-factory.d.ts +3 -0
  93. package/src/dataservices/default-data.service.d.ts +3 -0
  94. package/src/dataservices/entity-cache-data.service.d.ts +3 -0
  95. package/src/dataservices/entity-data.service.d.ts +3 -0
  96. package/src/dataservices/http-url-generator.d.ts +3 -0
  97. package/src/dataservices/persistence-result-handler.service.d.ts +3 -0
  98. package/src/dispatchers/entity-cache-dispatcher.d.ts +3 -0
  99. package/src/dispatchers/entity-dispatcher-default-options.d.ts +3 -0
  100. package/src/dispatchers/entity-dispatcher-factory.d.ts +3 -0
  101. package/src/effects/entity-cache-effects.d.ts +3 -0
  102. package/src/effects/entity-effects.d.ts +3 -0
  103. package/src/entity-data-without-effects.module.d.ts +5 -0
  104. package/src/entity-data.module.d.ts +6 -0
  105. package/src/entity-metadata/entity-definition.service.d.ts +3 -0
  106. package/src/entity-services/entity-collection-service-base.d.ts +1 -1
  107. package/src/entity-services/entity-collection-service-elements-factory.d.ts +3 -0
  108. package/src/entity-services/entity-collection-service-factory.d.ts +3 -0
  109. package/src/entity-services/entity-services-base.d.ts +3 -0
  110. package/src/entity-services/entity-services-elements.d.ts +3 -0
  111. package/src/reducers/entity-cache-reducer.d.ts +3 -0
  112. package/src/reducers/entity-collection-creator.d.ts +3 -0
  113. package/src/reducers/entity-collection-reducer-methods.d.ts +3 -0
  114. package/src/reducers/entity-collection-reducer-registry.d.ts +3 -0
  115. package/src/reducers/entity-collection-reducer.d.ts +3 -0
  116. package/src/selectors/entity-selectors$.d.ts +3 -0
  117. package/src/selectors/entity-selectors.d.ts +3 -0
  118. package/src/utils/correlation-id-generator.d.ts +3 -0
  119. package/src/utils/default-logger.d.ts +3 -0
  120. package/src/utils/default-pluralizer.d.ts +3 -0
  121. package/bundles/ngrx-data.umd.js +0 -5418
  122. package/bundles/ngrx-data.umd.js.map +0 -1
  123. package/esm2015/ngrx-data.js +0 -6
  124. package/esm2015/src/actions/entity-action-factory.js +0 -43
  125. package/esm2015/src/actions/entity-cache-action.js +0 -116
  126. package/esm2015/src/actions/entity-cache-change-set.js +0 -50
  127. package/esm2015/src/dataservices/entity-cache-data.service.js +0 -141
  128. package/esm2015/src/dataservices/entity-data.service.js +0 -64
  129. package/esm2015/src/dataservices/persistence-result-handler.service.js +0 -51
  130. package/esm2015/src/dispatchers/entity-cache-dispatcher.js +0 -162
  131. package/esm2015/src/dispatchers/entity-dispatcher-base.js +0 -401
  132. package/esm2015/src/dispatchers/entity-dispatcher-default-options.js +0 -27
  133. package/esm2015/src/dispatchers/entity-dispatcher-factory.js +0 -61
  134. package/esm2015/src/effects/entity-cache-effects.js +0 -114
  135. package/esm2015/src/effects/entity-effects.js +0 -147
  136. package/esm2015/src/entity-data-without-effects.module.js +0 -126
  137. package/esm2015/src/entity-data.module.js +0 -103
  138. package/esm2015/src/entity-metadata/entity-definition.js +0 -26
  139. package/esm2015/src/entity-metadata/entity-definition.service.js +0 -89
  140. package/esm2015/src/entity-services/entity-collection-service-elements-factory.js +0 -42
  141. package/esm2015/src/entity-services/entity-collection-service-factory.js +0 -29
  142. package/esm2015/src/entity-services/entity-services-base.js +0 -120
  143. package/esm2015/src/entity-services/entity-services-elements.js +0 -37
  144. package/esm2015/src/reducers/entity-cache-reducer.js +0 -274
  145. package/esm2015/src/reducers/entity-change-tracker-base.js +0 -575
  146. package/esm2015/src/reducers/entity-collection-creator.js +0 -36
  147. package/esm2015/src/reducers/entity-collection-reducer-methods.js +0 -785
  148. package/esm2015/src/reducers/entity-collection-reducer-registry.js +0 -65
  149. package/esm2015/src/reducers/entity-collection-reducer.js +0 -25
  150. package/esm2015/src/selectors/entity-selectors$.js +0 -52
  151. package/esm2015/src/selectors/entity-selectors.js +0 -83
  152. package/esm2015/src/utils/correlation-id-generator.js +0 -27
  153. package/esm2015/src/utils/default-logger.js +0 -22
  154. package/esm2015/src/utils/default-pluralizer.js +0 -67
  155. package/fesm2015/ngrx-data.js.map +0 -1
  156. package/ngrx-data.metadata.json +0 -1
@@ -0,0 +1,806 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { ChangeType, } from './entity-collection';
3
+ import { EntityChangeTrackerBase } from './entity-change-tracker-base';
4
+ import { toUpdateFactory } from '../utils/utilities';
5
+ import { EntityActionGuard } from '../actions/entity-action-guard';
6
+ import { EntityOp } from '../actions/entity-op';
7
+ import { MergeStrategy } from '../actions/merge-strategy';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "../entity-metadata/entity-definition.service";
10
+ /**
11
+ * Base implementation of reducer methods for an entity collection.
12
+ */
13
+ export class EntityCollectionReducerMethods {
14
+ constructor(entityName, definition,
15
+ /*
16
+ * Track changes to entities since the last query or save
17
+ * Can revert some or all of those changes
18
+ */
19
+ entityChangeTracker) {
20
+ this.entityName = entityName;
21
+ this.definition = definition;
22
+ /**
23
+ * Dictionary of the {EntityCollectionReducerMethods} for this entity type,
24
+ * keyed by the {EntityOp}
25
+ */
26
+ this.methods = {
27
+ [EntityOp.CANCEL_PERSIST]: this.cancelPersist.bind(this),
28
+ [EntityOp.QUERY_ALL]: this.queryAll.bind(this),
29
+ [EntityOp.QUERY_ALL_ERROR]: this.queryAllError.bind(this),
30
+ [EntityOp.QUERY_ALL_SUCCESS]: this.queryAllSuccess.bind(this),
31
+ [EntityOp.QUERY_BY_KEY]: this.queryByKey.bind(this),
32
+ [EntityOp.QUERY_BY_KEY_ERROR]: this.queryByKeyError.bind(this),
33
+ [EntityOp.QUERY_BY_KEY_SUCCESS]: this.queryByKeySuccess.bind(this),
34
+ [EntityOp.QUERY_LOAD]: this.queryLoad.bind(this),
35
+ [EntityOp.QUERY_LOAD_ERROR]: this.queryLoadError.bind(this),
36
+ [EntityOp.QUERY_LOAD_SUCCESS]: this.queryLoadSuccess.bind(this),
37
+ [EntityOp.QUERY_MANY]: this.queryMany.bind(this),
38
+ [EntityOp.QUERY_MANY_ERROR]: this.queryManyError.bind(this),
39
+ [EntityOp.QUERY_MANY_SUCCESS]: this.queryManySuccess.bind(this),
40
+ [EntityOp.SAVE_ADD_MANY]: this.saveAddMany.bind(this),
41
+ [EntityOp.SAVE_ADD_MANY_ERROR]: this.saveAddManyError.bind(this),
42
+ [EntityOp.SAVE_ADD_MANY_SUCCESS]: this.saveAddManySuccess.bind(this),
43
+ [EntityOp.SAVE_ADD_ONE]: this.saveAddOne.bind(this),
44
+ [EntityOp.SAVE_ADD_ONE_ERROR]: this.saveAddOneError.bind(this),
45
+ [EntityOp.SAVE_ADD_ONE_SUCCESS]: this.saveAddOneSuccess.bind(this),
46
+ [EntityOp.SAVE_DELETE_MANY]: this.saveDeleteMany.bind(this),
47
+ [EntityOp.SAVE_DELETE_MANY_ERROR]: this.saveDeleteManyError.bind(this),
48
+ [EntityOp.SAVE_DELETE_MANY_SUCCESS]: this.saveDeleteManySuccess.bind(this),
49
+ [EntityOp.SAVE_DELETE_ONE]: this.saveDeleteOne.bind(this),
50
+ [EntityOp.SAVE_DELETE_ONE_ERROR]: this.saveDeleteOneError.bind(this),
51
+ [EntityOp.SAVE_DELETE_ONE_SUCCESS]: this.saveDeleteOneSuccess.bind(this),
52
+ [EntityOp.SAVE_UPDATE_MANY]: this.saveUpdateMany.bind(this),
53
+ [EntityOp.SAVE_UPDATE_MANY_ERROR]: this.saveUpdateManyError.bind(this),
54
+ [EntityOp.SAVE_UPDATE_MANY_SUCCESS]: this.saveUpdateManySuccess.bind(this),
55
+ [EntityOp.SAVE_UPDATE_ONE]: this.saveUpdateOne.bind(this),
56
+ [EntityOp.SAVE_UPDATE_ONE_ERROR]: this.saveUpdateOneError.bind(this),
57
+ [EntityOp.SAVE_UPDATE_ONE_SUCCESS]: this.saveUpdateOneSuccess.bind(this),
58
+ [EntityOp.SAVE_UPSERT_MANY]: this.saveUpsertMany.bind(this),
59
+ [EntityOp.SAVE_UPSERT_MANY_ERROR]: this.saveUpsertManyError.bind(this),
60
+ [EntityOp.SAVE_UPSERT_MANY_SUCCESS]: this.saveUpsertManySuccess.bind(this),
61
+ [EntityOp.SAVE_UPSERT_ONE]: this.saveUpsertOne.bind(this),
62
+ [EntityOp.SAVE_UPSERT_ONE_ERROR]: this.saveUpsertOneError.bind(this),
63
+ [EntityOp.SAVE_UPSERT_ONE_SUCCESS]: this.saveUpsertOneSuccess.bind(this),
64
+ // Do nothing on save errors except turn the loading flag off.
65
+ // See the ChangeTrackerMetaReducers
66
+ // Or the app could listen for those errors and do something
67
+ /// cache only operations ///
68
+ [EntityOp.ADD_ALL]: this.addAll.bind(this),
69
+ [EntityOp.ADD_MANY]: this.addMany.bind(this),
70
+ [EntityOp.ADD_ONE]: this.addOne.bind(this),
71
+ [EntityOp.REMOVE_ALL]: this.removeAll.bind(this),
72
+ [EntityOp.REMOVE_MANY]: this.removeMany.bind(this),
73
+ [EntityOp.REMOVE_ONE]: this.removeOne.bind(this),
74
+ [EntityOp.UPDATE_MANY]: this.updateMany.bind(this),
75
+ [EntityOp.UPDATE_ONE]: this.updateOne.bind(this),
76
+ [EntityOp.UPSERT_MANY]: this.upsertMany.bind(this),
77
+ [EntityOp.UPSERT_ONE]: this.upsertOne.bind(this),
78
+ [EntityOp.COMMIT_ALL]: this.commitAll.bind(this),
79
+ [EntityOp.COMMIT_MANY]: this.commitMany.bind(this),
80
+ [EntityOp.COMMIT_ONE]: this.commitOne.bind(this),
81
+ [EntityOp.UNDO_ALL]: this.undoAll.bind(this),
82
+ [EntityOp.UNDO_MANY]: this.undoMany.bind(this),
83
+ [EntityOp.UNDO_ONE]: this.undoOne.bind(this),
84
+ [EntityOp.SET_CHANGE_STATE]: this.setChangeState.bind(this),
85
+ [EntityOp.SET_COLLECTION]: this.setCollection.bind(this),
86
+ [EntityOp.SET_FILTER]: this.setFilter.bind(this),
87
+ [EntityOp.SET_LOADED]: this.setLoaded.bind(this),
88
+ [EntityOp.SET_LOADING]: this.setLoading.bind(this),
89
+ };
90
+ this.adapter = definition.entityAdapter;
91
+ this.isChangeTracking = definition.noChangeTracking !== true;
92
+ this.selectId = definition.selectId;
93
+ this.guard = new EntityActionGuard(entityName, this.selectId);
94
+ this.toUpdate = toUpdateFactory(this.selectId);
95
+ this.entityChangeTracker =
96
+ entityChangeTracker ||
97
+ new EntityChangeTrackerBase(this.adapter, this.selectId);
98
+ }
99
+ /** Cancel a persistence operation */
100
+ cancelPersist(collection) {
101
+ return this.setLoadingFalse(collection);
102
+ }
103
+ // #region query operations
104
+ queryAll(collection) {
105
+ return this.setLoadingTrue(collection);
106
+ }
107
+ queryAllError(collection, action) {
108
+ return this.setLoadingFalse(collection);
109
+ }
110
+ /**
111
+ * Merges query results per the MergeStrategy
112
+ * Sets loading flag to false and loaded flag to true.
113
+ */
114
+ queryAllSuccess(collection, action) {
115
+ const data = this.extractData(action);
116
+ const mergeStrategy = this.extractMergeStrategy(action);
117
+ return {
118
+ ...this.entityChangeTracker.mergeQueryResults(data, collection, mergeStrategy),
119
+ loaded: true,
120
+ loading: false,
121
+ };
122
+ }
123
+ queryByKey(collection, action) {
124
+ return this.setLoadingTrue(collection);
125
+ }
126
+ queryByKeyError(collection, action) {
127
+ return this.setLoadingFalse(collection);
128
+ }
129
+ queryByKeySuccess(collection, action) {
130
+ const data = this.extractData(action);
131
+ const mergeStrategy = this.extractMergeStrategy(action);
132
+ collection =
133
+ data == null
134
+ ? collection
135
+ : this.entityChangeTracker.mergeQueryResults([data], collection, mergeStrategy);
136
+ return this.setLoadingFalse(collection);
137
+ }
138
+ queryLoad(collection) {
139
+ return this.setLoadingTrue(collection);
140
+ }
141
+ queryLoadError(collection, action) {
142
+ return this.setLoadingFalse(collection);
143
+ }
144
+ /**
145
+ * Replaces all entities in the collection
146
+ * Sets loaded flag to true, loading flag to false,
147
+ * and clears changeState for the entire collection.
148
+ */
149
+ queryLoadSuccess(collection, action) {
150
+ const data = this.extractData(action);
151
+ return {
152
+ ...this.adapter.setAll(data, collection),
153
+ loading: false,
154
+ loaded: true,
155
+ changeState: {},
156
+ };
157
+ }
158
+ queryMany(collection, action) {
159
+ return this.setLoadingTrue(collection);
160
+ }
161
+ queryManyError(collection, action) {
162
+ return this.setLoadingFalse(collection);
163
+ }
164
+ queryManySuccess(collection, action) {
165
+ const data = this.extractData(action);
166
+ const mergeStrategy = this.extractMergeStrategy(action);
167
+ return {
168
+ ...this.entityChangeTracker.mergeQueryResults(data, collection, mergeStrategy),
169
+ loading: false,
170
+ };
171
+ }
172
+ // #endregion query operations
173
+ // #region save operations
174
+ // #region saveAddMany
175
+ /**
176
+ * Save multiple new entities.
177
+ * If saving pessimistically, delay adding to collection until server acknowledges success.
178
+ * If saving optimistically; add immediately.
179
+ * @param collection The collection to which the entities should be added.
180
+ * @param action The action payload holds options, including whether the save is optimistic,
181
+ * and the data, which must be an array of entities.
182
+ * If saving optimistically, the entities must have their keys.
183
+ */
184
+ saveAddMany(collection, action) {
185
+ if (this.isOptimistic(action)) {
186
+ const entities = this.guard.mustBeEntities(action); // ensure the entity has a PK
187
+ const mergeStrategy = this.extractMergeStrategy(action);
188
+ collection = this.entityChangeTracker.trackAddMany(entities, collection, mergeStrategy);
189
+ collection = this.adapter.addMany(entities, collection);
190
+ }
191
+ return this.setLoadingTrue(collection);
192
+ }
193
+ /**
194
+ * Attempt to save new entities failed or timed-out.
195
+ * Action holds the error.
196
+ * If saved pessimistically, new entities are not in the collection and
197
+ * you may not have to compensate for the error.
198
+ * If saved optimistically, the unsaved entities are in the collection and
199
+ * you may need to compensate for the error.
200
+ */
201
+ saveAddManyError(collection, action) {
202
+ return this.setLoadingFalse(collection);
203
+ }
204
+ // #endregion saveAddMany
205
+ // #region saveAddOne
206
+ /**
207
+ * Successfully saved new entities to the server.
208
+ * If saved pessimistically, add the entities from the server to the collection.
209
+ * If saved optimistically, the added entities are already in the collection.
210
+ * However, the server might have set or modified other fields (e.g, concurrency field),
211
+ * and may even return additional new entities.
212
+ * Therefore, upsert the entities in the collection with the returned values (if any)
213
+ * Caution: in a race, this update could overwrite unsaved user changes.
214
+ * Use pessimistic add to avoid this risk.
215
+ * Note: saveAddManySuccess differs from saveAddOneSuccess when optimistic.
216
+ * saveAddOneSuccess updates (not upserts) with the lone entity from the server.
217
+ * There is no effect if the entity is not already in cache.
218
+ * saveAddManySuccess will add an entity if it is not found in cache.
219
+ */
220
+ saveAddManySuccess(collection, action) {
221
+ // For pessimistic save, ensure the server generated the primary key if the client didn't send one.
222
+ const entities = this.guard.mustBeEntities(action);
223
+ const mergeStrategy = this.extractMergeStrategy(action);
224
+ if (this.isOptimistic(action)) {
225
+ collection = this.entityChangeTracker.mergeSaveUpserts(entities, collection, mergeStrategy);
226
+ }
227
+ else {
228
+ collection = this.entityChangeTracker.mergeSaveAdds(entities, collection, mergeStrategy);
229
+ }
230
+ return this.setLoadingFalse(collection);
231
+ }
232
+ // #endregion saveAddMany
233
+ // #region saveAddOne
234
+ /**
235
+ * Save a new entity.
236
+ * If saving pessimistically, delay adding to collection until server acknowledges success.
237
+ * If saving optimistically; add entity immediately.
238
+ * @param collection The collection to which the entity should be added.
239
+ * @param action The action payload holds options, including whether the save is optimistic,
240
+ * and the data, which must be an entity.
241
+ * If saving optimistically, the entity must have a key.
242
+ */
243
+ saveAddOne(collection, action) {
244
+ if (this.isOptimistic(action)) {
245
+ const entity = this.guard.mustBeEntity(action); // ensure the entity has a PK
246
+ const mergeStrategy = this.extractMergeStrategy(action);
247
+ collection = this.entityChangeTracker.trackAddOne(entity, collection, mergeStrategy);
248
+ collection = this.adapter.addOne(entity, collection);
249
+ }
250
+ return this.setLoadingTrue(collection);
251
+ }
252
+ /**
253
+ * Attempt to save a new entity failed or timed-out.
254
+ * Action holds the error.
255
+ * If saved pessimistically, the entity is not in the collection and
256
+ * you may not have to compensate for the error.
257
+ * If saved optimistically, the unsaved entity is in the collection and
258
+ * you may need to compensate for the error.
259
+ */
260
+ saveAddOneError(collection, action) {
261
+ return this.setLoadingFalse(collection);
262
+ }
263
+ /**
264
+ * Successfully saved a new entity to the server.
265
+ * If saved pessimistically, add the entity from the server to the collection.
266
+ * If saved optimistically, the added entity is already in the collection.
267
+ * However, the server might have set or modified other fields (e.g, concurrency field)
268
+ * Therefore, update the entity in the collection with the returned value (if any)
269
+ * Caution: in a race, this update could overwrite unsaved user changes.
270
+ * Use pessimistic add to avoid this risk.
271
+ */
272
+ saveAddOneSuccess(collection, action) {
273
+ // For pessimistic save, ensure the server generated the primary key if the client didn't send one.
274
+ const entity = this.guard.mustBeEntity(action);
275
+ const mergeStrategy = this.extractMergeStrategy(action);
276
+ if (this.isOptimistic(action)) {
277
+ const update = this.toUpdate(entity);
278
+ // Always update the cache with added entity returned from server
279
+ collection = this.entityChangeTracker.mergeSaveUpdates([update], collection, mergeStrategy, false /*never skip*/);
280
+ }
281
+ else {
282
+ collection = this.entityChangeTracker.mergeSaveAdds([entity], collection, mergeStrategy);
283
+ }
284
+ return this.setLoadingFalse(collection);
285
+ }
286
+ // #endregion saveAddOne
287
+ // #region saveAddMany
288
+ // TODO MANY
289
+ // #endregion saveAddMany
290
+ // #region saveDeleteOne
291
+ /**
292
+ * Delete an entity from the server by key and remove it from the collection (if present).
293
+ * If the entity is an unsaved new entity, remove it from the collection immediately
294
+ * and skip the server delete request.
295
+ * An optimistic save removes an existing entity from the collection immediately;
296
+ * a pessimistic save removes it after the server confirms successful delete.
297
+ * @param collection Will remove the entity with this key from the collection.
298
+ * @param action The action payload holds options, including whether the save is optimistic,
299
+ * and the data, which must be a primary key or an entity with a key;
300
+ * this reducer extracts the key from the entity.
301
+ */
302
+ saveDeleteOne(collection, action) {
303
+ const toDelete = this.extractData(action);
304
+ const deleteId = typeof toDelete === 'object'
305
+ ? this.selectId(toDelete)
306
+ : toDelete;
307
+ const change = collection.changeState[deleteId];
308
+ // If entity is already tracked ...
309
+ if (change) {
310
+ if (change.changeType === ChangeType.Added) {
311
+ // Remove the added entity immediately and forget about its changes (via commit).
312
+ collection = this.adapter.removeOne(deleteId, collection);
313
+ collection = this.entityChangeTracker.commitOne(deleteId, collection);
314
+ // Should not waste effort trying to delete on the server because it can't be there.
315
+ action.payload.skip = true;
316
+ }
317
+ else {
318
+ // Re-track it as a delete, even if tracking is turned off for this call.
319
+ collection = this.entityChangeTracker.trackDeleteOne(deleteId, collection);
320
+ }
321
+ }
322
+ // If optimistic delete, track current state and remove immediately.
323
+ if (this.isOptimistic(action)) {
324
+ const mergeStrategy = this.extractMergeStrategy(action);
325
+ collection = this.entityChangeTracker.trackDeleteOne(deleteId, collection, mergeStrategy);
326
+ collection = this.adapter.removeOne(deleteId, collection);
327
+ }
328
+ return this.setLoadingTrue(collection);
329
+ }
330
+ /**
331
+ * Attempt to delete the entity on the server failed or timed-out.
332
+ * Action holds the error.
333
+ * If saved pessimistically, the entity could still be in the collection and
334
+ * you may not have to compensate for the error.
335
+ * If saved optimistically, the entity is not in the collection and
336
+ * you may need to compensate for the error.
337
+ */
338
+ saveDeleteOneError(collection, action) {
339
+ return this.setLoadingFalse(collection);
340
+ }
341
+ /**
342
+ * Successfully deleted entity on the server. The key of the deleted entity is in the action payload data.
343
+ * If saved pessimistically, if the entity is still in the collection it will be removed.
344
+ * If saved optimistically, the entity has already been removed from the collection.
345
+ */
346
+ saveDeleteOneSuccess(collection, action) {
347
+ const deleteId = this.extractData(action);
348
+ if (this.isOptimistic(action)) {
349
+ const mergeStrategy = this.extractMergeStrategy(action);
350
+ collection = this.entityChangeTracker.mergeSaveDeletes([deleteId], collection, mergeStrategy);
351
+ }
352
+ else {
353
+ // Pessimistic: ignore mergeStrategy. Remove entity from the collection and from change tracking.
354
+ collection = this.adapter.removeOne(deleteId, collection);
355
+ collection = this.entityChangeTracker.commitOne(deleteId, collection);
356
+ }
357
+ return this.setLoadingFalse(collection);
358
+ }
359
+ // #endregion saveDeleteOne
360
+ // #region saveDeleteMany
361
+ /**
362
+ * Delete multiple entities from the server by key and remove them from the collection (if present).
363
+ * Removes unsaved new entities from the collection immediately
364
+ * but the id is still sent to the server for deletion even though the server will not find that entity.
365
+ * Therefore, the server must be willing to ignore a delete request for an entity it cannot find.
366
+ * An optimistic save removes existing entities from the collection immediately;
367
+ * a pessimistic save removes them after the server confirms successful delete.
368
+ * @param collection Removes entities from this collection.
369
+ * @param action The action payload holds options, including whether the save is optimistic,
370
+ * and the data, which must be an array of primary keys or entities with a key;
371
+ * this reducer extracts the key from the entity.
372
+ */
373
+ saveDeleteMany(collection, action) {
374
+ const deleteIds = this.extractData(action).map((d) => typeof d === 'object' ? this.selectId(d) : d);
375
+ deleteIds.forEach((deleteId) => {
376
+ const change = collection.changeState[deleteId];
377
+ // If entity is already tracked ...
378
+ if (change) {
379
+ if (change.changeType === ChangeType.Added) {
380
+ // Remove the added entity immediately and forget about its changes (via commit).
381
+ collection = this.adapter.removeOne(deleteId, collection);
382
+ collection = this.entityChangeTracker.commitOne(deleteId, collection);
383
+ // Should not waste effort trying to delete on the server because it can't be there.
384
+ action.payload.skip = true;
385
+ }
386
+ else {
387
+ // Re-track it as a delete, even if tracking is turned off for this call.
388
+ collection = this.entityChangeTracker.trackDeleteOne(deleteId, collection);
389
+ }
390
+ }
391
+ });
392
+ // If optimistic delete, track current state and remove immediately.
393
+ if (this.isOptimistic(action)) {
394
+ const mergeStrategy = this.extractMergeStrategy(action);
395
+ collection = this.entityChangeTracker.trackDeleteMany(deleteIds, collection, mergeStrategy);
396
+ collection = this.adapter.removeMany(deleteIds, collection);
397
+ }
398
+ return this.setLoadingTrue(collection);
399
+ }
400
+ /**
401
+ * Attempt to delete the entities on the server failed or timed-out.
402
+ * Action holds the error.
403
+ * If saved pessimistically, the entities could still be in the collection and
404
+ * you may not have to compensate for the error.
405
+ * If saved optimistically, the entities are not in the collection and
406
+ * you may need to compensate for the error.
407
+ */
408
+ saveDeleteManyError(collection, action) {
409
+ return this.setLoadingFalse(collection);
410
+ }
411
+ /**
412
+ * Successfully deleted entities on the server. The keys of the deleted entities are in the action payload data.
413
+ * If saved pessimistically, entities that are still in the collection will be removed.
414
+ * If saved optimistically, the entities have already been removed from the collection.
415
+ */
416
+ saveDeleteManySuccess(collection, action) {
417
+ const deleteIds = this.extractData(action);
418
+ if (this.isOptimistic(action)) {
419
+ const mergeStrategy = this.extractMergeStrategy(action);
420
+ collection = this.entityChangeTracker.mergeSaveDeletes(deleteIds, collection, mergeStrategy);
421
+ }
422
+ else {
423
+ // Pessimistic: ignore mergeStrategy. Remove entity from the collection and from change tracking.
424
+ collection = this.adapter.removeMany(deleteIds, collection);
425
+ collection = this.entityChangeTracker.commitMany(deleteIds, collection);
426
+ }
427
+ return this.setLoadingFalse(collection);
428
+ }
429
+ // #endregion saveDeleteMany
430
+ // #region saveUpdateOne
431
+ /**
432
+ * Save an update to an existing entity.
433
+ * If saving pessimistically, update the entity in the collection after the server confirms success.
434
+ * If saving optimistically, update the entity immediately, before the save request.
435
+ * @param collection The collection to update
436
+ * @param action The action payload holds options, including if the save is optimistic,
437
+ * and the data which, must be an {Update<T>}
438
+ */
439
+ saveUpdateOne(collection, action) {
440
+ const update = this.guard.mustBeUpdate(action);
441
+ if (this.isOptimistic(action)) {
442
+ const mergeStrategy = this.extractMergeStrategy(action);
443
+ collection = this.entityChangeTracker.trackUpdateOne(update, collection, mergeStrategy);
444
+ collection = this.adapter.updateOne(update, collection);
445
+ }
446
+ return this.setLoadingTrue(collection);
447
+ }
448
+ /**
449
+ * Attempt to update the entity on the server failed or timed-out.
450
+ * Action holds the error.
451
+ * If saved pessimistically, the entity in the collection is in the pre-save state
452
+ * you may not have to compensate for the error.
453
+ * If saved optimistically, the entity in the collection was updated
454
+ * and you may need to compensate for the error.
455
+ */
456
+ saveUpdateOneError(collection, action) {
457
+ return this.setLoadingFalse(collection);
458
+ }
459
+ /**
460
+ * Successfully saved the updated entity to the server.
461
+ * If saved pessimistically, update the entity in the collection with data from the server.
462
+ * If saved optimistically, the entity was already updated in the collection.
463
+ * However, the server might have set or modified other fields (e.g, concurrency field)
464
+ * Therefore, update the entity in the collection with the returned value (if any)
465
+ * Caution: in a race, this update could overwrite unsaved user changes.
466
+ * Use pessimistic update to avoid this risk.
467
+ * @param collection The collection to update
468
+ * @param action The action payload holds options, including if the save is optimistic, and
469
+ * the update data which, must be an UpdateResponse<T> that corresponds to the Update sent to the server.
470
+ * You must include an UpdateResponse even if the save was optimistic,
471
+ * to ensure that the change tracking is properly reset.
472
+ */
473
+ saveUpdateOneSuccess(collection, action) {
474
+ const update = this.guard.mustBeUpdateResponse(action);
475
+ const isOptimistic = this.isOptimistic(action);
476
+ const mergeStrategy = this.extractMergeStrategy(action);
477
+ collection = this.entityChangeTracker.mergeSaveUpdates([update], collection, mergeStrategy, isOptimistic /*skip unchanged if optimistic */);
478
+ return this.setLoadingFalse(collection);
479
+ }
480
+ // #endregion saveUpdateOne
481
+ // #region saveUpdateMany
482
+ /**
483
+ * Save updated entities.
484
+ * If saving pessimistically, update the entities in the collection after the server confirms success.
485
+ * If saving optimistically, update the entities immediately, before the save request.
486
+ * @param collection The collection to update
487
+ * @param action The action payload holds options, including if the save is optimistic,
488
+ * and the data which, must be an array of {Update<T>}.
489
+ */
490
+ saveUpdateMany(collection, action) {
491
+ const updates = this.guard.mustBeUpdates(action);
492
+ if (this.isOptimistic(action)) {
493
+ const mergeStrategy = this.extractMergeStrategy(action);
494
+ collection = this.entityChangeTracker.trackUpdateMany(updates, collection, mergeStrategy);
495
+ collection = this.adapter.updateMany(updates, collection);
496
+ }
497
+ return this.setLoadingTrue(collection);
498
+ }
499
+ /**
500
+ * Attempt to update entities on the server failed or timed-out.
501
+ * Action holds the error.
502
+ * If saved pessimistically, the entities in the collection are in the pre-save state
503
+ * you may not have to compensate for the error.
504
+ * If saved optimistically, the entities in the collection were updated
505
+ * and you may need to compensate for the error.
506
+ */
507
+ saveUpdateManyError(collection, action) {
508
+ return this.setLoadingFalse(collection);
509
+ }
510
+ /**
511
+ * Successfully saved the updated entities to the server.
512
+ * If saved pessimistically, the entities in the collection will be updated with data from the server.
513
+ * If saved optimistically, the entities in the collection were already updated.
514
+ * However, the server might have set or modified other fields (e.g, concurrency field)
515
+ * Therefore, update the entity in the collection with the returned values (if any)
516
+ * Caution: in a race, this update could overwrite unsaved user changes.
517
+ * Use pessimistic update to avoid this risk.
518
+ * @param collection The collection to update
519
+ * @param action The action payload holds options, including if the save is optimistic,
520
+ * and the data which, must be an array of UpdateResponse<T>.
521
+ * You must include an UpdateResponse for every Update sent to the server,
522
+ * even if the save was optimistic, to ensure that the change tracking is properly reset.
523
+ */
524
+ saveUpdateManySuccess(collection, action) {
525
+ const updates = this.guard.mustBeUpdateResponses(action);
526
+ const isOptimistic = this.isOptimistic(action);
527
+ const mergeStrategy = this.extractMergeStrategy(action);
528
+ collection = this.entityChangeTracker.mergeSaveUpdates(updates, collection, mergeStrategy, false /* never skip */);
529
+ return this.setLoadingFalse(collection);
530
+ }
531
+ // #endregion saveUpdateMany
532
+ // #region saveUpsertOne
533
+ /**
534
+ * Save a new or existing entity.
535
+ * If saving pessimistically, delay adding to collection until server acknowledges success.
536
+ * If saving optimistically; add immediately.
537
+ * @param collection The collection to which the entity should be upserted.
538
+ * @param action The action payload holds options, including whether the save is optimistic,
539
+ * and the data, which must be a whole entity.
540
+ * If saving optimistically, the entity must have its key.
541
+ */
542
+ saveUpsertOne(collection, action) {
543
+ if (this.isOptimistic(action)) {
544
+ const entity = this.guard.mustBeEntity(action); // ensure the entity has a PK
545
+ const mergeStrategy = this.extractMergeStrategy(action);
546
+ collection = this.entityChangeTracker.trackUpsertOne(entity, collection, mergeStrategy);
547
+ collection = this.adapter.upsertOne(entity, collection);
548
+ }
549
+ return this.setLoadingTrue(collection);
550
+ }
551
+ /**
552
+ * Attempt to save new or existing entity failed or timed-out.
553
+ * Action holds the error.
554
+ * If saved pessimistically, new or updated entity is not in the collection and
555
+ * you may not have to compensate for the error.
556
+ * If saved optimistically, the unsaved entities are in the collection and
557
+ * you may need to compensate for the error.
558
+ */
559
+ saveUpsertOneError(collection, action) {
560
+ return this.setLoadingFalse(collection);
561
+ }
562
+ /**
563
+ * Successfully saved new or existing entities to the server.
564
+ * If saved pessimistically, add the entities from the server to the collection.
565
+ * If saved optimistically, the added entities are already in the collection.
566
+ * However, the server might have set or modified other fields (e.g, concurrency field)
567
+ * Therefore, update the entities in the collection with the returned values (if any)
568
+ * Caution: in a race, this update could overwrite unsaved user changes.
569
+ * Use pessimistic add to avoid this risk.
570
+ */
571
+ saveUpsertOneSuccess(collection, action) {
572
+ // For pessimistic save, ensure the server generated the primary key if the client didn't send one.
573
+ const entity = this.guard.mustBeEntity(action);
574
+ const mergeStrategy = this.extractMergeStrategy(action);
575
+ // Always update the cache with upserted entities returned from server
576
+ collection = this.entityChangeTracker.mergeSaveUpserts([entity], collection, mergeStrategy);
577
+ return this.setLoadingFalse(collection);
578
+ }
579
+ // #endregion saveUpsertOne
580
+ // #region saveUpsertMany
581
+ /**
582
+ * Save multiple new or existing entities.
583
+ * If saving pessimistically, delay adding to collection until server acknowledges success.
584
+ * If saving optimistically; add immediately.
585
+ * @param collection The collection to which the entities should be upserted.
586
+ * @param action The action payload holds options, including whether the save is optimistic,
587
+ * and the data, which must be an array of whole entities.
588
+ * If saving optimistically, the entities must have their keys.
589
+ */
590
+ saveUpsertMany(collection, action) {
591
+ if (this.isOptimistic(action)) {
592
+ const entities = this.guard.mustBeEntities(action); // ensure the entity has a PK
593
+ const mergeStrategy = this.extractMergeStrategy(action);
594
+ collection = this.entityChangeTracker.trackUpsertMany(entities, collection, mergeStrategy);
595
+ collection = this.adapter.upsertMany(entities, collection);
596
+ }
597
+ return this.setLoadingTrue(collection);
598
+ }
599
+ /**
600
+ * Attempt to save new or existing entities failed or timed-out.
601
+ * Action holds the error.
602
+ * If saved pessimistically, new entities are not in the collection and
603
+ * you may not have to compensate for the error.
604
+ * If saved optimistically, the unsaved entities are in the collection and
605
+ * you may need to compensate for the error.
606
+ */
607
+ saveUpsertManyError(collection, action) {
608
+ return this.setLoadingFalse(collection);
609
+ }
610
+ /**
611
+ * Successfully saved new or existing entities to the server.
612
+ * If saved pessimistically, add the entities from the server to the collection.
613
+ * If saved optimistically, the added entities are already in the collection.
614
+ * However, the server might have set or modified other fields (e.g, concurrency field)
615
+ * Therefore, update the entities in the collection with the returned values (if any)
616
+ * Caution: in a race, this update could overwrite unsaved user changes.
617
+ * Use pessimistic add to avoid this risk.
618
+ */
619
+ saveUpsertManySuccess(collection, action) {
620
+ // For pessimistic save, ensure the server generated the primary key if the client didn't send one.
621
+ const entities = this.guard.mustBeEntities(action);
622
+ const mergeStrategy = this.extractMergeStrategy(action);
623
+ // Always update the cache with upserted entities returned from server
624
+ collection = this.entityChangeTracker.mergeSaveUpserts(entities, collection, mergeStrategy);
625
+ return this.setLoadingFalse(collection);
626
+ }
627
+ // #endregion saveUpsertMany
628
+ // #endregion save operations
629
+ // #region cache-only operations
630
+ /**
631
+ * Replaces all entities in the collection
632
+ * Sets loaded flag to true.
633
+ * Merges query results, preserving unsaved changes
634
+ */
635
+ addAll(collection, action) {
636
+ const entities = this.guard.mustBeEntities(action);
637
+ return {
638
+ ...this.adapter.setAll(entities, collection),
639
+ loading: false,
640
+ loaded: true,
641
+ changeState: {},
642
+ };
643
+ }
644
+ addMany(collection, action) {
645
+ const entities = this.guard.mustBeEntities(action);
646
+ const mergeStrategy = this.extractMergeStrategy(action);
647
+ collection = this.entityChangeTracker.trackAddMany(entities, collection, mergeStrategy);
648
+ return this.adapter.addMany(entities, collection);
649
+ }
650
+ addOne(collection, action) {
651
+ const entity = this.guard.mustBeEntity(action);
652
+ const mergeStrategy = this.extractMergeStrategy(action);
653
+ collection = this.entityChangeTracker.trackAddOne(entity, collection, mergeStrategy);
654
+ return this.adapter.addOne(entity, collection);
655
+ }
656
+ removeMany(collection, action) {
657
+ // payload must be entity keys
658
+ const keys = this.guard.mustBeKeys(action);
659
+ const mergeStrategy = this.extractMergeStrategy(action);
660
+ collection = this.entityChangeTracker.trackDeleteMany(keys, collection, mergeStrategy);
661
+ return this.adapter.removeMany(keys, collection);
662
+ }
663
+ removeOne(collection, action) {
664
+ // payload must be entity key
665
+ const key = this.guard.mustBeKey(action);
666
+ const mergeStrategy = this.extractMergeStrategy(action);
667
+ collection = this.entityChangeTracker.trackDeleteOne(key, collection, mergeStrategy);
668
+ return this.adapter.removeOne(key, collection);
669
+ }
670
+ removeAll(collection, action) {
671
+ return {
672
+ ...this.adapter.removeAll(collection),
673
+ loaded: false,
674
+ loading: false,
675
+ changeState: {}, // Assume clearing the collection and not trying to delete all entities
676
+ };
677
+ }
678
+ updateMany(collection, action) {
679
+ // payload must be an array of `Updates<T>`, not entities
680
+ const updates = this.guard.mustBeUpdates(action);
681
+ const mergeStrategy = this.extractMergeStrategy(action);
682
+ collection = this.entityChangeTracker.trackUpdateMany(updates, collection, mergeStrategy);
683
+ return this.adapter.updateMany(updates, collection);
684
+ }
685
+ updateOne(collection, action) {
686
+ // payload must be an `Update<T>`, not an entity
687
+ const update = this.guard.mustBeUpdate(action);
688
+ const mergeStrategy = this.extractMergeStrategy(action);
689
+ collection = this.entityChangeTracker.trackUpdateOne(update, collection, mergeStrategy);
690
+ return this.adapter.updateOne(update, collection);
691
+ }
692
+ upsertMany(collection, action) {
693
+ // <v6: payload must be an array of `Updates<T>`, not entities
694
+ // v6+: payload must be an array of T
695
+ const entities = this.guard.mustBeEntities(action);
696
+ const mergeStrategy = this.extractMergeStrategy(action);
697
+ collection = this.entityChangeTracker.trackUpsertMany(entities, collection, mergeStrategy);
698
+ return this.adapter.upsertMany(entities, collection);
699
+ }
700
+ upsertOne(collection, action) {
701
+ // <v6: payload must be an `Update<T>`, not an entity
702
+ // v6+: payload must be a T
703
+ const entity = this.guard.mustBeEntity(action);
704
+ const mergeStrategy = this.extractMergeStrategy(action);
705
+ collection = this.entityChangeTracker.trackUpsertOne(entity, collection, mergeStrategy);
706
+ return this.adapter.upsertOne(entity, collection);
707
+ }
708
+ commitAll(collection) {
709
+ return this.entityChangeTracker.commitAll(collection);
710
+ }
711
+ commitMany(collection, action) {
712
+ return this.entityChangeTracker.commitMany(this.extractData(action), collection);
713
+ }
714
+ commitOne(collection, action) {
715
+ return this.entityChangeTracker.commitOne(this.extractData(action), collection);
716
+ }
717
+ undoAll(collection) {
718
+ return this.entityChangeTracker.undoAll(collection);
719
+ }
720
+ undoMany(collection, action) {
721
+ return this.entityChangeTracker.undoMany(this.extractData(action), collection);
722
+ }
723
+ undoOne(collection, action) {
724
+ return this.entityChangeTracker.undoOne(this.extractData(action), collection);
725
+ }
726
+ /** Dangerous: Completely replace the collection's ChangeState. Use rarely and wisely. */
727
+ setChangeState(collection, action) {
728
+ const changeState = this.extractData(action);
729
+ return collection.changeState === changeState
730
+ ? collection
731
+ : { ...collection, changeState };
732
+ }
733
+ /**
734
+ * Dangerous: Completely replace the collection.
735
+ * Primarily for testing and rehydration from local storage.
736
+ * Use rarely and wisely.
737
+ */
738
+ setCollection(collection, action) {
739
+ const newCollection = this.extractData(action);
740
+ return collection === newCollection ? collection : newCollection;
741
+ }
742
+ setFilter(collection, action) {
743
+ const filter = this.extractData(action);
744
+ return collection.filter === filter
745
+ ? collection
746
+ : { ...collection, filter };
747
+ }
748
+ setLoaded(collection, action) {
749
+ const loaded = this.extractData(action) === true || false;
750
+ return collection.loaded === loaded
751
+ ? collection
752
+ : { ...collection, loaded };
753
+ }
754
+ setLoading(collection, action) {
755
+ return this.setLoadingFlag(collection, this.extractData(action));
756
+ }
757
+ setLoadingFalse(collection) {
758
+ return this.setLoadingFlag(collection, false);
759
+ }
760
+ setLoadingTrue(collection) {
761
+ return this.setLoadingFlag(collection, true);
762
+ }
763
+ /** Set the collection's loading flag */
764
+ setLoadingFlag(collection, loading) {
765
+ loading = loading === true ? true : false;
766
+ return collection.loading === loading
767
+ ? collection
768
+ : { ...collection, loading };
769
+ }
770
+ // #endregion Cache-only operations
771
+ // #region helpers
772
+ /** Safely extract data from the EntityAction payload */
773
+ extractData(action) {
774
+ return (action.payload && action.payload.data);
775
+ }
776
+ /** Safely extract MergeStrategy from EntityAction. Set to IgnoreChanges if collection itself is not tracked. */
777
+ extractMergeStrategy(action) {
778
+ // If not tracking this collection, always ignore changes
779
+ return this.isChangeTracking
780
+ ? action.payload && action.payload.mergeStrategy
781
+ : MergeStrategy.IgnoreChanges;
782
+ }
783
+ isOptimistic(action) {
784
+ return action.payload && action.payload.isOptimistic === true;
785
+ }
786
+ }
787
+ /**
788
+ * Creates {EntityCollectionReducerMethods} for a given entity type.
789
+ */
790
+ export class EntityCollectionReducerMethodsFactory {
791
+ constructor(entityDefinitionService) {
792
+ this.entityDefinitionService = entityDefinitionService;
793
+ }
794
+ /** Create the {EntityCollectionReducerMethods} for the named entity type */
795
+ create(entityName) {
796
+ const definition = this.entityDefinitionService.getDefinition(entityName);
797
+ const methodsClass = new EntityCollectionReducerMethods(entityName, definition);
798
+ return methodsClass.methods;
799
+ }
800
+ }
801
+ /** @nocollapse */ /** @nocollapse */ EntityCollectionReducerMethodsFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: EntityCollectionReducerMethodsFactory, deps: [{ token: i1.EntityDefinitionService }], target: i0.ɵɵFactoryTarget.Injectable });
802
+ /** @nocollapse */ /** @nocollapse */ EntityCollectionReducerMethodsFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: EntityCollectionReducerMethodsFactory });
803
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: EntityCollectionReducerMethodsFactory, decorators: [{
804
+ type: Injectable
805
+ }], ctorParameters: function () { return [{ type: i1.EntityDefinitionService }]; } });
806
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWNvbGxlY3Rpb24tcmVkdWNlci1tZXRob2RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy9kYXRhL3NyYy9yZWR1Y2Vycy9lbnRpdHktY29sbGVjdGlvbi1yZWR1Y2VyLW1ldGhvZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBRUwsVUFBVSxHQUVYLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3JELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBSW5FLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7OztBQWMxRDs7R0FFRztBQUNILE1BQU0sT0FBTyw4QkFBOEI7SUErR3pDLFlBQ1MsVUFBa0IsRUFDbEIsVUFBK0I7SUFDdEM7OztPQUdHO0lBQ0gsbUJBQTRDO1FBTnJDLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDbEIsZUFBVSxHQUFWLFVBQVUsQ0FBcUI7UUEzRnhDOzs7V0FHRztRQUNNLFlBQU8sR0FBd0M7WUFDdEQsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBRXhELENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM5QyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFD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LDREQUE0RDtZQUU1RCw2QkFBNkI7WUFFN0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQzFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM1QyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFFMUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2hELENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUNsRCxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFFaEQsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2xELENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUVoRCxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDbEQsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBRWhELENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUNoRCxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLENB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LENBQUM7SUFDRCxtQ0FBbUM7SUFFbkMsa0JBQWtCO0lBQ2xCLHdEQUF3RDtJQUM5QyxXQUFXLENBQVUsTUFBdUI7UUFDcEQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQU0sQ0FBQztJQUN0RCxDQUFDO0lBRUQsZ0hBQWdIO0lBQ3RHLG9CQUFvQixDQUFDLE1BQW9CO1FBQ2pELHlEQUF5RDtRQUN6RCxPQUFPLElBQUksQ0FBQyxnQkFBZ0I7WUFDMUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhO1lBQ2hELENBQUMsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDO0lBQ2xDLENBQUM7SUFFUyxZQUFZLENBQUMsTUFBb0I7UUFDekMsT0FBTyxNQUFNLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxLQUFLLElBQUksQ0FBQztJQUNoRSxDQUFDO0NBR0Y7QUFFRDs7R0FFRztBQUVILE1BQU0sT0FBTyxxQ0FBcUM7SUFDaEQsWUFBb0IsdUJBQWdEO1FBQWhELDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBeUI7SUFBRyxDQUFDO0lBRXhFLDZFQUE2RTtJQUM3RSxNQUFNLENBQUksVUFBa0I7UUFDMUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLGFBQWEsQ0FDM0QsVUFBVSxDQUNYLENBQUM7UUFDRixNQUFNLFlBQVksR0FBRyxJQUFJLDhCQUE4QixDQUNyRCxVQUFVLEVBQ1YsVUFBVSxDQUNYLENBQUM7UUFFRixPQUFPLFlBQVksQ0FBQyxPQUFPLENBQUM7SUFDOUIsQ0FBQzs7d0tBZFUscUNBQXFDOzRLQUFyQyxxQ0FBcUM7MkZBQXJDLHFDQUFxQztrQkFEakQsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEVudGl0eUFkYXB0ZXIsIElkU2VsZWN0b3IsIFVwZGF0ZSB9IGZyb20gJ0BuZ3J4L2VudGl0eSc7XG5pbXBvcnQge1xuICBDaGFuZ2VTdGF0ZU1hcCxcbiAgQ2hhbmdlVHlwZSxcbiAgRW50aXR5Q29sbGVjdGlvbixcbn0gZnJvbSAnLi9lbnRpdHktY29sbGVjdGlvbic7XG5pbXBvcnQgeyBFbnRpdHlDaGFuZ2VUcmFja2VyQmFzZSB9IGZyb20gJy4vZW50aXR5LWNoYW5nZS10cmFja2VyLWJhc2UnO1xuaW1wb3J0IHsgdG9VcGRhdGVGYWN0b3J5IH0gZnJvbSAnLi4vdXRpbHMvdXRpbGl0aWVzJztcbmltcG9ydCB7IEVudGl0eUFjdGlvbiB9IGZyb20gJy4uL2FjdGlvbnMvZW50aXR5LWFjdGlvbic7XG5pbXBvcnQgeyBFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yIH0gZnJvbSAnLi4vZGF0YXNlcnZpY2VzL2RhdGEtc2VydmljZS1lcnJvcic7XG5pbXBvcnQgeyBFbnRpdHlBY3Rpb25HdWFyZCB9IGZyb20gJy4uL2FjdGlvbnMvZW50aXR5LWFjdGlvbi1ndWFyZCc7XG5pbXBvcnQgeyBFbnRpdHlDaGFuZ2VUcmFja2VyIH0gZnJvbSAnLi9lbnRpdHktY2hhbmdlLXRyYWNrZXInO1xuaW1wb3J0IHsgRW50aXR5RGVmaW5pdGlvbiB9IGZyb20gJy4uL2VudGl0eS1tZXRhZGF0YS9lbnRpdHktZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBFbnRpdHlEZWZpbml0aW9uU2VydmljZSB9IGZyb20gJy4uL2VudGl0eS1tZXRhZGF0YS9lbnRpdHktZGVmaW5pdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEVudGl0eU9wIH0gZnJvbSAnLi4vYWN0aW9ucy9lbnRpdHktb3AnO1xuaW1wb3J0IHsgTWVyZ2VTdHJhdGVneSB9IGZyb20gJy4uL2FjdGlvbnMvbWVyZ2Utc3RyYXRlZ3knO1xuaW1wb3J0IHsgVXBkYXRlUmVzcG9uc2VEYXRhIH0gZnJvbSAnLi4vYWN0aW9ucy91cGRhdGUtcmVzcG9uc2UtZGF0YSc7XG5cbi8qKlxuICogTWFwIG9mIHtFbnRpdHlPcH0gdG8gcmVkdWNlciBtZXRob2QgZm9yIHRoZSBvcGVyYXRpb24uXG4gKiBJZiBhbiBvcGVyYXRpb24gaXMgbWlzc2luZywgY2FsbGVyIHNob3VsZCByZXR1cm4gdGhlIGNvbGxlY3Rpb24gZm9yIHRoYXQgcmVkdWNlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnRpdHlDb2xsZWN0aW9uUmVkdWNlck1ldGhvZE1hcDxUPiB7XG4gIFttZXRob2Q6IHN0cmluZ106IChcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uXG4gICkgPT4gRW50aXR5Q29sbGVjdGlvbjxUPjtcbn1cblxuLyoqXG4gKiBCYXNlIGltcGxlbWVudGF0aW9uIG9mIHJlZHVjZXIgbWV0aG9kcyBmb3IgYW4gZW50aXR5IGNvbGxlY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBFbnRpdHlDb2xsZWN0aW9uUmVkdWNlck1ldGhvZHM8VD4ge1xuICBwcm90ZWN0ZWQgYWRhcHRlcjogRW50aXR5QWRhcHRlcjxUPjtcbiAgcHJvdGVjdGVkIGd1YXJkOiBFbnRpdHlBY3Rpb25HdWFyZDxUPjtcbiAgLyoqIFRydWUgaWYgdGhpcyBjb2xsZWN0aW9uIHRyYWNrcyB1bnNhdmVkIGNoYW5nZXMgKi9cbiAgcHJvdGVjdGVkIGlzQ2hhbmdlVHJhY2tpbmc6IGJvb2xlYW47XG5cbiAgLyoqIEV4dHJhY3QgdGhlIHByaW1hcnkga2V5IChpZCk7IGRlZmF1bHQgdG8gYGlkYCAqL1xuICBzZWxlY3RJZDogSWRTZWxlY3RvcjxUPjtcblxuICAvKipcbiAgICogVHJhY2sgY2hhbmdlcyB0byBlbnRpdGllcyBzaW5jZSB0aGUgbGFzdCBxdWVyeSBvciBzYXZlXG4gICAqIENhbiByZXZlcnQgc29tZSBvciBhbGwgb2YgdGhvc2UgY2hhbmdlc1xuICAgKi9cbiAgZW50aXR5Q2hhbmdlVHJhY2tlcjogRW50aXR5Q2hhbmdlVHJhY2tlcjxUPjtcblxuICAvKipcbiAgICogQ29udmVydCBhbiBlbnRpdHkgKG9yIHBhcnRpYWwgZW50aXR5KSBpbnRvIHRoZSBgVXBkYXRlPFQ+YCBvYmplY3RcbiAgICogYGlkYDogdGhlIHByaW1hcnkga2V5IGFuZFxuICAgKiBgY2hhbmdlc2A6IHRoZSBlbnRpdHkgKG9yIHBhcnRpYWwgZW50aXR5IG9mIGNoYW5nZXMpLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRvVXBkYXRlOiAoZW50aXR5OiBQYXJ0aWFsPFQ+KSA9PiBVcGRhdGU8VD47XG5cbiAgLyoqXG4gICAqIERpY3Rpb25hcnkgb2YgdGhlIHtFbnRpdHlDb2xsZWN0aW9uUmVkdWNlck1ldGhvZHN9IGZvciB0aGlzIGVudGl0eSB0eXBlLFxuICAgKiBrZXllZCBieSB0aGUge0VudGl0eU9wfVxuICAgKi9cbiAgcmVhZG9ubHkgbWV0aG9kczogRW50aXR5Q29sbGVjdGlvblJlZHVjZXJNZXRob2RNYXA8VD4gPSB7XG4gICAgW0VudGl0eU9wLkNBTkNFTF9QRVJTSVNUXTogdGhpcy5jYW5jZWxQZXJzaXN0LmJpbmQodGhpcyksXG5cbiAgICBbRW50aXR5T3AuUVVFUllfQUxMXTogdGhpcy5xdWVyeUFsbC5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5RVUVSWV9BTExfRVJST1JdOiB0aGlzLnF1ZXJ5QWxsRXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuUVVFUllfQUxMX1NVQ0NFU1NdOiB0aGlzLnF1ZXJ5QWxsU3VjY2Vzcy5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlFVRVJZX0JZX0tFWV06IHRoaXMucXVlcnlCeUtleS5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5RVUVSWV9CWV9LRVlfRVJST1JdOiB0aGlzLnF1ZXJ5QnlLZXlFcnJvci5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5RVUVSWV9CWV9LRVlfU1VDQ0VTU106IHRoaXMucXVlcnlCeUtleVN1Y2Nlc3MuYmluZCh0aGlzKSxcblxuICAgIFtFbnRpdHlPcC5RVUVSWV9MT0FEXTogdGhpcy5xdWVyeUxvYWQuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuUVVFUllfTE9BRF9FUlJPUl06IHRoaXMucXVlcnlMb2FkRXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuUVVFUllfTE9BRF9TVUNDRVNTXTogdGhpcy5xdWVyeUxvYWRTdWNjZXNzLmJpbmQodGhpcyksXG5cbiAgICBbRW50aXR5T3AuUVVFUllfTUFOWV06IHRoaXMucXVlcnlNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlFVRVJZX01BTllfRVJST1JdOiB0aGlzLnF1ZXJ5TWFueUVycm9yLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlFVRVJZX01BTllfU1VDQ0VTU106IHRoaXMucXVlcnlNYW55U3VjY2Vzcy5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlNBVkVfQUREX01BTlldOiB0aGlzLnNhdmVBZGRNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNBVkVfQUREX01BTllfRVJST1JdOiB0aGlzLnNhdmVBZGRNYW55RXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9BRERfTUFOWV9TVUNDRVNTXTogdGhpcy5zYXZlQWRkTWFueVN1Y2Nlc3MuYmluZCh0aGlzKSxcblxuICAgIFtFbnRpdHlPcC5TQVZFX0FERF9PTkVdOiB0aGlzLnNhdmVBZGRPbmUuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9BRERfT05FX0VSUk9SXTogdGhpcy5zYXZlQWRkT25lRXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9BRERfT05FX1NVQ0NFU1NdOiB0aGlzLnNhdmVBZGRPbmVTdWNjZXNzLmJpbmQodGhpcyksXG5cbiAgICBbRW50aXR5T3AuU0FWRV9ERUxFVEVfTUFOWV06IHRoaXMuc2F2ZURlbGV0ZU1hbnkuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9ERUxFVEVfTUFOWV9FUlJPUl06IHRoaXMuc2F2ZURlbGV0ZU1hbnlFcnJvci5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5TQVZFX0RFTEVURV9NQU5ZX1NVQ0NFU1NdOiB0aGlzLnNhdmVEZWxldGVNYW55U3VjY2Vzcy5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlNBVkVfREVMRVRFX09ORV06IHRoaXMuc2F2ZURlbGV0ZU9uZS5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5TQVZFX0RFTEVURV9PTkVfRVJST1JdOiB0aGlzLnNhdmVEZWxldGVPbmVFcnJvci5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5TQVZFX0RFTEVURV9PTkVfU1VDQ0VTU106IHRoaXMuc2F2ZURlbGV0ZU9uZVN1Y2Nlc3MuYmluZCh0aGlzKSxcblxuICAgIFtFbnRpdHlPcC5TQVZFX1VQREFURV9NQU5ZXTogdGhpcy5zYXZlVXBkYXRlTWFueS5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5TQVZFX1VQREFURV9NQU5ZX0VSUk9SXTogdGhpcy5zYXZlVXBkYXRlTWFueUVycm9yLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNBVkVfVVBEQVRFX01BTllfU1VDQ0VTU106IHRoaXMuc2F2ZVVwZGF0ZU1hbnlTdWNjZXNzLmJpbmQodGhpcyksXG5cbiAgICBbRW50aXR5T3AuU0FWRV9VUERBVEVfT05FXTogdGhpcy5zYXZlVXBkYXRlT25lLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNBVkVfVVBEQVRFX09ORV9FUlJPUl06IHRoaXMuc2F2ZVVwZGF0ZU9uZUVycm9yLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNBVkVfVVBEQVRFX09ORV9TVUNDRVNTXTogdGhpcy5zYXZlVXBkYXRlT25lU3VjY2Vzcy5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlNBVkVfVVBTRVJUX01BTlldOiB0aGlzLnNhdmVVcHNlcnRNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNBVkVfVVBTRVJUX01BTllfRVJST1JdOiB0aGlzLnNhdmVVcHNlcnRNYW55RXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9VUFNFUlRfTUFOWV9TVUNDRVNTXTogdGhpcy5zYXZlVXBzZXJ0TWFueVN1Y2Nlc3MuYmluZCh0aGlzKSxcblxuICAgIFtFbnRpdHlPcC5TQVZFX1VQU0VSVF9PTkVdOiB0aGlzLnNhdmVVcHNlcnRPbmUuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9VUFNFUlRfT05FX0VSUk9SXTogdGhpcy5zYXZlVXBzZXJ0T25lRXJyb3IuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0FWRV9VUFNFUlRfT05FX1NVQ0NFU1NdOiB0aGlzLnNhdmVVcHNlcnRPbmVTdWNjZXNzLmJpbmQodGhpcyksXG5cbiAgICAvLyBEbyBub3RoaW5nIG9uIHNhdmUgZXJyb3JzIGV4Y2VwdCB0dXJuIHRoZSBsb2FkaW5nIGZsYWcgb2ZmLlxuICAgIC8vIFNlZSB0aGUgQ2hhbmdlVHJhY2tlck1ldGFSZWR1Y2Vyc1xuICAgIC8vIE9yIHRoZSBhcHAgY291bGQgbGlzdGVuIGZvciB0aG9zZSBlcnJvcnMgYW5kIGRvIHNvbWV0aGluZ1xuXG4gICAgLy8vIGNhY2hlIG9ubHkgb3BlcmF0aW9ucyAvLy9cblxuICAgIFtFbnRpdHlPcC5BRERfQUxMXTogdGhpcy5hZGRBbGwuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuQUREX01BTlldOiB0aGlzLmFkZE1hbnkuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuQUREX09ORV06IHRoaXMuYWRkT25lLmJpbmQodGhpcyksXG5cbiAgICBbRW50aXR5T3AuUkVNT1ZFX0FMTF06IHRoaXMucmVtb3ZlQWxsLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlJFTU9WRV9NQU5ZXTogdGhpcy5yZW1vdmVNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlJFTU9WRV9PTkVdOiB0aGlzLnJlbW92ZU9uZS5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlVQREFURV9NQU5ZXTogdGhpcy51cGRhdGVNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlVQREFURV9PTkVdOiB0aGlzLnVwZGF0ZU9uZS5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlVQU0VSVF9NQU5ZXTogdGhpcy51cHNlcnRNYW55LmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlVQU0VSVF9PTkVdOiB0aGlzLnVwc2VydE9uZS5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLkNPTU1JVF9BTExdOiB0aGlzLmNvbW1pdEFsbC5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5DT01NSVRfTUFOWV06IHRoaXMuY29tbWl0TWFueS5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5DT01NSVRfT05FXTogdGhpcy5jb21taXRPbmUuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuVU5ET19BTExdOiB0aGlzLnVuZG9BbGwuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuVU5ET19NQU5ZXTogdGhpcy51bmRvTWFueS5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5VTkRPX09ORV06IHRoaXMudW5kb09uZS5iaW5kKHRoaXMpLFxuXG4gICAgW0VudGl0eU9wLlNFVF9DSEFOR0VfU1RBVEVdOiB0aGlzLnNldENoYW5nZVN0YXRlLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNFVF9DT0xMRUNUSU9OXTogdGhpcy5zZXRDb2xsZWN0aW9uLmJpbmQodGhpcyksXG4gICAgW0VudGl0eU9wLlNFVF9GSUxURVJdOiB0aGlzLnNldEZpbHRlci5iaW5kKHRoaXMpLFxuICAgIFtFbnRpdHlPcC5TRVRfTE9BREVEXTogdGhpcy5zZXRMb2FkZWQuYmluZCh0aGlzKSxcbiAgICBbRW50aXR5T3AuU0VUX0xPQURJTkddOiB0aGlzLnNldExvYWRpbmcuYmluZCh0aGlzKSxcbiAgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgZW50aXR5TmFtZTogc3RyaW5nLFxuICAgIHB1YmxpYyBkZWZpbml0aW9uOiBFbnRpdHlEZWZpbml0aW9uPFQ+LFxuICAgIC8qXG4gICAgICogVHJhY2sgY2hhbmdlcyB0byBlbnRpdGllcyBzaW5jZSB0aGUgbGFzdCBxdWVyeSBvciBzYXZlXG4gICAgICogQ2FuIHJldmVydCBzb21lIG9yIGFsbCBvZiB0aG9zZSBjaGFuZ2VzXG4gICAgICovXG4gICAgZW50aXR5Q2hhbmdlVHJhY2tlcj86IEVudGl0eUNoYW5nZVRyYWNrZXI8VD5cbiAgKSB7XG4gICAgdGhpcy5hZGFwdGVyID0gZGVmaW5pdGlvbi5lbnRpdHlBZGFwdGVyO1xuICAgIHRoaXMuaXNDaGFuZ2VUcmFja2luZyA9IGRlZmluaXRpb24ubm9DaGFuZ2VUcmFja2luZyAhPT0gdHJ1ZTtcbiAgICB0aGlzLnNlbGVjdElkID0gZGVmaW5pdGlvbi5zZWxlY3RJZDtcblxuICAgIHRoaXMuZ3VhcmQgPSBuZXcgRW50aXR5QWN0aW9uR3VhcmQoZW50aXR5TmFtZSwgdGhpcy5zZWxlY3RJZCk7XG4gICAgdGhpcy50b1VwZGF0ZSA9IHRvVXBkYXRlRmFjdG9yeSh0aGlzLnNlbGVjdElkKTtcblxuICAgIHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlciA9XG4gICAgICBlbnRpdHlDaGFuZ2VUcmFja2VyIHx8XG4gICAgICBuZXcgRW50aXR5Q2hhbmdlVHJhY2tlckJhc2U8VD4odGhpcy5hZGFwdGVyLCB0aGlzLnNlbGVjdElkKTtcbiAgfVxuXG4gIC8qKiBDYW5jZWwgYSBwZXJzaXN0ZW5jZSBvcGVyYXRpb24gKi9cbiAgcHJvdGVjdGVkIGNhbmNlbFBlcnNpc3QoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvLyAjcmVnaW9uIHF1ZXJ5IG9wZXJhdGlvbnNcblxuICBwcm90ZWN0ZWQgcXVlcnlBbGwoY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPik6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHF1ZXJ5QWxsRXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2VzIHF1ZXJ5IHJlc3VsdHMgcGVyIHRoZSBNZXJnZVN0cmF0ZWd5XG4gICAqIFNldHMgbG9hZGluZyBmbGFnIHRvIGZhbHNlIGFuZCBsb2FkZWQgZmxhZyB0byB0cnVlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHF1ZXJ5QWxsU3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIubWVyZ2VRdWVyeVJlc3VsdHMoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICksXG4gICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIHF1ZXJ5QnlLZXkoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxudW1iZXIgfCBzdHJpbmc+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHF1ZXJ5QnlLZXlFcnJvcihcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPEVudGl0eUFjdGlvbkRhdGFTZXJ2aWNlRXJyb3I+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGYWxzZShjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBxdWVyeUJ5S2V5U3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLmV4dHJhY3REYXRhKGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICBjb2xsZWN0aW9uID1cbiAgICAgIGRhdGEgPT0gbnVsbFxuICAgICAgICA/IGNvbGxlY3Rpb25cbiAgICAgICAgOiB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIubWVyZ2VRdWVyeVJlc3VsdHMoXG4gICAgICAgICAgICBbZGF0YV0sXG4gICAgICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHF1ZXJ5TG9hZChjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+KTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ1RydWUoY29sbGVjdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgcXVlcnlMb2FkRXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgYWxsIGVudGl0aWVzIGluIHRoZSBjb2xsZWN0aW9uXG4gICAqIFNldHMgbG9hZGVkIGZsYWcgdG8gdHJ1ZSwgbG9hZGluZyBmbGFnIHRvIGZhbHNlLFxuICAgKiBhbmQgY2xlYXJzIGNoYW5nZVN0YXRlIGZvciB0aGUgZW50aXJlIGNvbGxlY3Rpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgcXVlcnlMb2FkU3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKTtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5hZGFwdGVyLnNldEFsbChkYXRhLCBjb2xsZWN0aW9uKSxcbiAgICAgIGxvYWRpbmc6IGZhbHNlLFxuICAgICAgbG9hZGVkOiB0cnVlLFxuICAgICAgY2hhbmdlU3RhdGU6IHt9LFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgcXVlcnlNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb25cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ1RydWUoY29sbGVjdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgcXVlcnlNYW55RXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgcXVlcnlNYW55U3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIubWVyZ2VRdWVyeVJlc3VsdHMoXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICksXG4gICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIC8vICNlbmRyZWdpb24gcXVlcnkgb3BlcmF0aW9uc1xuXG4gIC8vICNyZWdpb24gc2F2ZSBvcGVyYXRpb25zXG5cbiAgLy8gI3JlZ2lvbiBzYXZlQWRkTWFueVxuICAvKipcbiAgICogU2F2ZSBtdWx0aXBsZSBuZXcgZW50aXRpZXMuXG4gICAqIElmIHNhdmluZyBwZXNzaW1pc3RpY2FsbHksIGRlbGF5IGFkZGluZyB0byBjb2xsZWN0aW9uIHVudGlsIHNlcnZlciBhY2tub3dsZWRnZXMgc3VjY2Vzcy5cbiAgICogSWYgc2F2aW5nIG9wdGltaXN0aWNhbGx5OyBhZGQgaW1tZWRpYXRlbHkuXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHdoaWNoIHRoZSBlbnRpdGllcyBzaG91bGQgYmUgYWRkZWQuXG4gICAqIEBwYXJhbSBhY3Rpb24gVGhlIGFjdGlvbiBwYXlsb2FkIGhvbGRzIG9wdGlvbnMsIGluY2x1ZGluZyB3aGV0aGVyIHRoZSBzYXZlIGlzIG9wdGltaXN0aWMsXG4gICAqIGFuZCB0aGUgZGF0YSwgd2hpY2ggbXVzdCBiZSBhbiBhcnJheSBvZiBlbnRpdGllcy5cbiAgICogSWYgc2F2aW5nIG9wdGltaXN0aWNhbGx5LCB0aGUgZW50aXRpZXMgbXVzdCBoYXZlIHRoZWlyIGtleXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZUFkZE1hbnkoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUW10+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGlmICh0aGlzLmlzT3B0aW1pc3RpYyhhY3Rpb24pKSB7XG4gICAgICBjb25zdCBlbnRpdGllcyA9IHRoaXMuZ3VhcmQubXVzdEJlRW50aXRpZXMoYWN0aW9uKTsgLy8gZW5zdXJlIHRoZSBlbnRpdHkgaGFzIGEgUEtcbiAgICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrQWRkTWFueShcbiAgICAgICAgZW50aXRpZXMsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICk7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5hZGFwdGVyLmFkZE1hbnkoZW50aXRpZXMsIGNvbGxlY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nVHJ1ZShjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0IHRvIHNhdmUgbmV3IGVudGl0aWVzIGZhaWxlZCBvciB0aW1lZC1vdXQuXG4gICAqIEFjdGlvbiBob2xkcyB0aGUgZXJyb3IuXG4gICAqIElmIHNhdmVkIHBlc3NpbWlzdGljYWxseSwgbmV3IGVudGl0aWVzIGFyZSBub3QgaW4gdGhlIGNvbGxlY3Rpb24gYW5kXG4gICAqIHlvdSBtYXkgbm90IGhhdmUgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIHVuc2F2ZWQgZW50aXRpZXMgYXJlIGluIHRoZSBjb2xsZWN0aW9uIGFuZFxuICAgKiB5b3UgbWF5IG5lZWQgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVBZGRNYW55RXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvbiBzYXZlQWRkTWFueVxuXG4gIC8vICNyZWdpb24gc2F2ZUFkZE9uZVxuICAvKipcbiAgICogU3VjY2Vzc2Z1bGx5IHNhdmVkIG5ldyBlbnRpdGllcyB0byB0aGUgc2VydmVyLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIGFkZCB0aGUgZW50aXRpZXMgZnJvbSB0aGUgc2VydmVyIHRvIHRoZSBjb2xsZWN0aW9uLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIGFkZGVkIGVudGl0aWVzIGFyZSBhbHJlYWR5IGluIHRoZSBjb2xsZWN0aW9uLlxuICAgKiBIb3dldmVyLCB0aGUgc2VydmVyIG1pZ2h0IGhhdmUgc2V0IG9yIG1vZGlmaWVkIG90aGVyIGZpZWxkcyAoZS5nLCBjb25jdXJyZW5jeSBmaWVsZCksXG4gICAqIGFuZCBtYXkgZXZlbiByZXR1cm4gYWRkaXRpb25hbCBuZXcgZW50aXRpZXMuXG4gICAqIFRoZXJlZm9yZSwgdXBzZXJ0IHRoZSBlbnRpdGllcyBpbiB0aGUgY29sbGVjdGlvbiB3aXRoIHRoZSByZXR1cm5lZCB2YWx1ZXMgKGlmIGFueSlcbiAgICogQ2F1dGlvbjogaW4gYSByYWNlLCB0aGlzIHVwZGF0ZSBjb3VsZCBvdmVyd3JpdGUgdW5zYXZlZCB1c2VyIGNoYW5nZXMuXG4gICAqIFVzZSBwZXNzaW1pc3RpYyBhZGQgdG8gYXZvaWQgdGhpcyByaXNrLlxuICAgKiBOb3RlOiBzYXZlQWRkTWFueVN1Y2Nlc3MgZGlmZmVycyBmcm9tIHNhdmVBZGRPbmVTdWNjZXNzIHdoZW4gb3B0aW1pc3RpYy5cbiAgICogc2F2ZUFkZE9uZVN1Y2Nlc3MgdXBkYXRlcyAobm90IHVwc2VydHMpIHdpdGggdGhlIGxvbmUgZW50aXR5IGZyb20gdGhlIHNlcnZlci5cbiAgICogVGhlcmUgaXMgbm8gZWZmZWN0IGlmIHRoZSBlbnRpdHkgaXMgbm90IGFscmVhZHkgaW4gY2FjaGUuXG4gICAqIHNhdmVBZGRNYW55U3VjY2VzcyB3aWxsIGFkZCBhbiBlbnRpdHkgaWYgaXQgaXMgbm90IGZvdW5kIGluIGNhY2hlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVBZGRNYW55U3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKSB7XG4gICAgLy8gRm9yIHBlc3NpbWlzdGljIHNhdmUsIGVuc3VyZSB0aGUgc2VydmVyIGdlbmVyYXRlZCB0aGUgcHJpbWFyeSBrZXkgaWYgdGhlIGNsaWVudCBkaWRuJ3Qgc2VuZCBvbmUuXG4gICAgY29uc3QgZW50aXRpZXMgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0aWVzKGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVVcHNlcnRzKFxuICAgICAgICBlbnRpdGllcyxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVBZGRzKFxuICAgICAgICBlbnRpdGllcyxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG4gIC8vICNlbmRyZWdpb24gc2F2ZUFkZE1hbnlcblxuICAvLyAjcmVnaW9uIHNhdmVBZGRPbmVcbiAgLyoqXG4gICAqIFNhdmUgYSBuZXcgZW50aXR5LlxuICAgKiBJZiBzYXZpbmcgcGVzc2ltaXN0aWNhbGx5LCBkZWxheSBhZGRpbmcgdG8gY29sbGVjdGlvbiB1bnRpbCBzZXJ2ZXIgYWNrbm93bGVkZ2VzIHN1Y2Nlc3MuXG4gICAqIElmIHNhdmluZyBvcHRpbWlzdGljYWxseTsgYWRkIGVudGl0eSBpbW1lZGlhdGVseS5cbiAgICogQHBhcmFtIGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gd2hpY2ggdGhlIGVudGl0eSBzaG91bGQgYmUgYWRkZWQuXG4gICAqIEBwYXJhbSBhY3Rpb24gVGhlIGFjdGlvbiBwYXlsb2FkIGhvbGRzIG9wdGlvbnMsIGluY2x1ZGluZyB3aGV0aGVyIHRoZSBzYXZlIGlzIG9wdGltaXN0aWMsXG4gICAqIGFuZCB0aGUgZGF0YSwgd2hpY2ggbXVzdCBiZSBhbiBlbnRpdHkuXG4gICAqIElmIHNhdmluZyBvcHRpbWlzdGljYWxseSwgdGhlIGVudGl0eSBtdXN0IGhhdmUgYSBrZXkuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZUFkZE9uZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGlmICh0aGlzLmlzT3B0aW1pc3RpYyhhY3Rpb24pKSB7XG4gICAgICBjb25zdCBlbnRpdHkgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0eShhY3Rpb24pOyAvLyBlbnN1cmUgdGhlIGVudGl0eSBoYXMgYSBQS1xuICAgICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tBZGRPbmUoXG4gICAgICAgIGVudGl0eSxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICAgKTtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmFkYXB0ZXIuYWRkT25lKGVudGl0eSwgY29sbGVjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gc2F2ZSBhIG5ldyBlbnRpdHkgZmFpbGVkIG9yIHRpbWVkLW91dC5cbiAgICogQWN0aW9uIGhvbGRzIHRoZSBlcnJvci5cbiAgICogSWYgc2F2ZWQgcGVzc2ltaXN0aWNhbGx5LCB0aGUgZW50aXR5IGlzIG5vdCBpbiB0aGUgY29sbGVjdGlvbiBhbmRcbiAgICogeW91IG1heSBub3QgaGF2ZSB0byBjb21wZW5zYXRlIGZvciB0aGUgZXJyb3IuXG4gICAqIElmIHNhdmVkIG9wdGltaXN0aWNhbGx5LCB0aGUgdW5zYXZlZCBlbnRpdHkgaXMgaW4gdGhlIGNvbGxlY3Rpb24gYW5kXG4gICAqIHlvdSBtYXkgbmVlZCB0byBjb21wZW5zYXRlIGZvciB0aGUgZXJyb3IuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZUFkZE9uZUVycm9yKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248RW50aXR5QWN0aW9uRGF0YVNlcnZpY2VFcnJvcj5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1Y2Nlc3NmdWxseSBzYXZlZCBhIG5ldyBlbnRpdHkgdG8gdGhlIHNlcnZlci5cbiAgICogSWYgc2F2ZWQgcGVzc2ltaXN0aWNhbGx5LCBhZGQgdGhlIGVudGl0eSBmcm9tIHRoZSBzZXJ2ZXIgdG8gdGhlIGNvbGxlY3Rpb24uXG4gICAqIElmIHNhdmVkIG9wdGltaXN0aWNhbGx5LCB0aGUgYWRkZWQgZW50aXR5IGlzIGFscmVhZHkgaW4gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEhvd2V2ZXIsIHRoZSBzZXJ2ZXIgbWlnaHQgaGF2ZSBzZXQgb3IgbW9kaWZpZWQgb3RoZXIgZmllbGRzIChlLmcsIGNvbmN1cnJlbmN5IGZpZWxkKVxuICAgKiBUaGVyZWZvcmUsIHVwZGF0ZSB0aGUgZW50aXR5IGluIHRoZSBjb2xsZWN0aW9uIHdpdGggdGhlIHJldHVybmVkIHZhbHVlIChpZiBhbnkpXG4gICAqIENhdXRpb246IGluIGEgcmFjZSwgdGhpcyB1cGRhdGUgY291bGQgb3ZlcndyaXRlIHVuc2F2ZWQgdXNlciBjaGFuZ2VzLlxuICAgKiBVc2UgcGVzc2ltaXN0aWMgYWRkIHRvIGF2b2lkIHRoaXMgcmlzay5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlQWRkT25lU3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICkge1xuICAgIC8vIEZvciBwZXNzaW1pc3RpYyBzYXZlLCBlbnN1cmUgdGhlIHNlcnZlciBnZW5lcmF0ZWQgdGhlIHByaW1hcnkga2V5IGlmIHRoZSBjbGllbnQgZGlkbid0IHNlbmQgb25lLlxuICAgIGNvbnN0IGVudGl0eSA9IHRoaXMuZ3VhcmQubXVzdEJlRW50aXR5KGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29uc3QgdXBkYXRlOiBVcGRhdGVSZXNwb25zZURhdGE8VD4gPSB0aGlzLnRvVXBkYXRlKGVudGl0eSk7XG4gICAgICAvLyBBbHdheXMgdXBkYXRlIHRoZSBjYWNoZSB3aXRoIGFkZGVkIGVudGl0eSByZXR1cm5lZCBmcm9tIHNlcnZlclxuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVVcGRhdGVzKFxuICAgICAgICBbdXBkYXRlXSxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgbWVyZ2VTdHJhdGVneSxcbiAgICAgICAgZmFsc2UgLypuZXZlciBza2lwKi9cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIubWVyZ2VTYXZlQWRkcyhcbiAgICAgICAgW2VudGl0eV0sXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGYWxzZShjb2xsZWN0aW9uKTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uIHNhdmVBZGRPbmVcblxuICAvLyAjcmVnaW9uIHNhdmVBZGRNYW55XG4gIC8vIFRPRE8gTUFOWVxuICAvLyAjZW5kcmVnaW9uIHNhdmVBZGRNYW55XG5cbiAgLy8gI3JlZ2lvbiBzYXZlRGVsZXRlT25lXG4gIC8qKlxuICAgKiBEZWxldGUgYW4gZW50aXR5IGZyb20gdGhlIHNlcnZlciBieSBrZXkgYW5kIHJlbW92ZSBpdCBmcm9tIHRoZSBjb2xsZWN0aW9uIChpZiBwcmVzZW50KS5cbiAgICogSWYgdGhlIGVudGl0eSBpcyBhbiB1bnNhdmVkIG5ldyBlbnRpdHksIHJlbW92ZSBpdCBmcm9tIHRoZSBjb2xsZWN0aW9uIGltbWVkaWF0ZWx5XG4gICAqIGFuZCBza2lwIHRoZSBzZXJ2ZXIgZGVsZXRlIHJlcXVlc3QuXG4gICAqIEFuIG9wdGltaXN0aWMgc2F2ZSByZW1vdmVzIGFuIGV4aXN0aW5nIGVudGl0eSBmcm9tIHRoZSBjb2xsZWN0aW9uIGltbWVkaWF0ZWx5O1xuICAgKiBhIHBlc3NpbWlzdGljIHNhdmUgcmVtb3ZlcyBpdCBhZnRlciB0aGUgc2VydmVyIGNvbmZpcm1zIHN1Y2Nlc3NmdWwgZGVsZXRlLlxuICAgKiBAcGFyYW0gY29sbGVjdGlvbiBXaWxsIHJlbW92ZSB0aGUgZW50aXR5IHdpdGggdGhpcyBrZXkgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAgICogQHBhcmFtIGFjdGlvbiBUaGUgYWN0aW9uIHBheWxvYWQgaG9sZHMgb3B0aW9ucywgaW5jbHVkaW5nIHdoZXRoZXIgdGhlIHNhdmUgaXMgb3B0aW1pc3RpYyxcbiAgICogYW5kIHRoZSBkYXRhLCB3aGljaCBtdXN0IGJlIGEgcHJpbWFyeSBrZXkgb3IgYW4gZW50aXR5IHdpdGggYSBrZXk7XG4gICAqIHRoaXMgcmVkdWNlciBleHRyYWN0cyB0aGUga2V5IGZyb20gdGhlIGVudGl0eS5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlRGVsZXRlT25lKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248bnVtYmVyIHwgc3RyaW5nIHwgVD5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgdG9EZWxldGUgPSB0aGlzLmV4dHJhY3REYXRhKGFjdGlvbik7XG4gICAgY29uc3QgZGVsZXRlSWQgPVxuICAgICAgdHlwZW9mIHRvRGVsZXRlID09PSAnb2JqZWN0J1xuICAgICAgICA/IHRoaXMuc2VsZWN0SWQodG9EZWxldGUpXG4gICAgICAgIDogKHRvRGVsZXRlIGFzIHN0cmluZyB8IG51bWJlcik7XG4gICAgY29uc3QgY2hhbmdlID0gY29sbGVjdGlvbi5jaGFuZ2VTdGF0ZVtkZWxldGVJZF07XG4gICAgLy8gSWYgZW50aXR5IGlzIGFscmVhZHkgdHJhY2tlZCAuLi5cbiAgICBpZiAoY2hhbmdlKSB7XG4gICAgICBpZiAoY2hhbmdlLmNoYW5nZVR5cGUgPT09IENoYW5nZVR5cGUuQWRkZWQpIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBhZGRlZCBlbnRpdHkgaW1tZWRpYXRlbHkgYW5kIGZvcmdldCBhYm91dCBpdHMgY2hhbmdlcyAodmlhIGNvbW1pdCkuXG4gICAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmFkYXB0ZXIucmVtb3ZlT25lKGRlbGV0ZUlkIGFzIHN0cmluZywgY29sbGVjdGlvbik7XG4gICAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIuY29tbWl0T25lKGRlbGV0ZUlkLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgLy8gU2hvdWxkIG5vdCB3YXN0ZSBlZmZvcnQgdHJ5aW5nIHRvIGRlbGV0ZSBvbiB0aGUgc2VydmVyIGJlY2F1c2UgaXQgY2FuJ3QgYmUgdGhlcmUuXG4gICAgICAgIGFjdGlvbi5wYXlsb2FkLnNraXAgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmUtdHJhY2sgaXQgYXMgYSBkZWxldGUsIGV2ZW4gaWYgdHJhY2tpbmcgaXMgdHVybmVkIG9mZiBmb3IgdGhpcyBjYWxsLlxuICAgICAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrRGVsZXRlT25lKFxuICAgICAgICAgIGRlbGV0ZUlkLFxuICAgICAgICAgIGNvbGxlY3Rpb25cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiBvcHRpbWlzdGljIGRlbGV0ZSwgdHJhY2sgY3VycmVudCBzdGF0ZSBhbmQgcmVtb3ZlIGltbWVkaWF0ZWx5LlxuICAgIGlmICh0aGlzLmlzT3B0aW1pc3RpYyhhY3Rpb24pKSB7XG4gICAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci50cmFja0RlbGV0ZU9uZShcbiAgICAgICAgZGVsZXRlSWQsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICk7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5hZGFwdGVyLnJlbW92ZU9uZShkZWxldGVJZCBhcyBzdHJpbmcsIGNvbGxlY3Rpb24pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gZGVsZXRlIHRoZSBlbnRpdHkgb24gdGhlIHNlcnZlciBmYWlsZWQgb3IgdGltZWQtb3V0LlxuICAgKiBBY3Rpb24gaG9sZHMgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIHRoZSBlbnRpdHkgY291bGQgc3RpbGwgYmUgaW4gdGhlIGNvbGxlY3Rpb24gYW5kXG4gICAqIHlvdSBtYXkgbm90IGhhdmUgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIGVudGl0eSBpcyBub3QgaW4gdGhlIGNvbGxlY3Rpb24gYW5kXG4gICAqIHlvdSBtYXkgbmVlZCB0byBjb21wZW5zYXRlIGZvciB0aGUgZXJyb3IuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZURlbGV0ZU9uZUVycm9yKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248RW50aXR5QWN0aW9uRGF0YVNlcnZpY2VFcnJvcj5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1Y2Nlc3NmdWxseSBkZWxldGVkIGVudGl0eSBvbiB0aGUgc2VydmVyLiBUaGUga2V5IG9mIHRoZSBkZWxldGVkIGVudGl0eSBpcyBpbiB0aGUgYWN0aW9uIHBheWxvYWQgZGF0YS5cbiAgICogSWYgc2F2ZWQgcGVzc2ltaXN0aWNhbGx5LCBpZiB0aGUgZW50aXR5IGlzIHN0aWxsIGluIHRoZSBjb2xsZWN0aW9uIGl0IHdpbGwgYmUgcmVtb3ZlZC5cbiAgICogSWYgc2F2ZWQgb3B0aW1pc3RpY2FsbHksIHRoZSBlbnRpdHkgaGFzIGFscmVhZHkgYmVlbiByZW1vdmVkIGZyb20gdGhlIGNvbGxlY3Rpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZURlbGV0ZU9uZVN1Y2Nlc3MoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxudW1iZXIgfCBzdHJpbmc+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGNvbnN0IGRlbGV0ZUlkID0gdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pO1xuICAgIGlmICh0aGlzLmlzT3B0aW1pc3RpYyhhY3Rpb24pKSB7XG4gICAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVEZWxldGVzKFxuICAgICAgICBbZGVsZXRlSWRdLFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBQZXNzaW1pc3RpYzogaWdub3JlIG1lcmdlU3RyYXRlZ3kuIFJlbW92ZSBlbnRpdHkgZnJvbSB0aGUgY29sbGVjdGlvbiBhbmQgZnJvbSBjaGFuZ2UgdHJhY2tpbmcuXG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5hZGFwdGVyLnJlbW92ZU9uZShkZWxldGVJZCBhcyBzdHJpbmcsIGNvbGxlY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5jb21taXRPbmUoZGVsZXRlSWQsIGNvbGxlY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvbiBzYXZlRGVsZXRlT25lXG5cbiAgLy8gI3JlZ2lvbiBzYXZlRGVsZXRlTWFueVxuICAvKipcbiAgICogRGVsZXRlIG11bHRpcGxlIGVudGl0aWVzIGZyb20gdGhlIHNlcnZlciBieSBrZXkgYW5kIHJlbW92ZSB0aGVtIGZyb20gdGhlIGNvbGxlY3Rpb24gKGlmIHByZXNlbnQpLlxuICAgKiBSZW1vdmVzIHVuc2F2ZWQgbmV3IGVudGl0aWVzIGZyb20gdGhlIGNvbGxlY3Rpb24gaW1tZWRpYXRlbHlcbiAgICogYnV0IHRoZSBpZCBpcyBzdGlsbCBzZW50IHRvIHRoZSBzZXJ2ZXIgZm9yIGRlbGV0aW9uIGV2ZW4gdGhvdWdoIHRoZSBzZXJ2ZXIgd2lsbCBub3QgZmluZCB0aGF0IGVudGl0eS5cbiAgICogVGhlcmVmb3JlLCB0aGUgc2VydmVyIG11c3QgYmUgd2lsbGluZyB0byBpZ25vcmUgYSBkZWxldGUgcmVxdWVzdCBmb3IgYW4gZW50aXR5IGl0IGNhbm5vdCBmaW5kLlxuICAgKiBBbiBvcHRpbWlzdGljIHNhdmUgcmVtb3ZlcyBleGlzdGluZyBlbnRpdGllcyBmcm9tIHRoZSBjb2xsZWN0aW9uIGltbWVkaWF0ZWx5O1xuICAgKiBhIHBlc3NpbWlzdGljIHNhdmUgcmVtb3ZlcyB0aGVtIGFmdGVyIHRoZSBzZXJ2ZXIgY29uZmlybXMgc3VjY2Vzc2Z1bCBkZWxldGUuXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uIFJlbW92ZXMgZW50aXRpZXMgZnJvbSB0aGlzIGNvbGxlY3Rpb24uXG4gICAqIEBwYXJhbSBhY3Rpb24gVGhlIGFjdGlvbiBwYXlsb2FkIGhvbGRzIG9wdGlvbnMsIGluY2x1ZGluZyB3aGV0aGVyIHRoZSBzYXZlIGlzIG9wdGltaXN0aWMsXG4gICAqIGFuZCB0aGUgZGF0YSwgd2hpY2ggbXVzdCBiZSBhbiBhcnJheSBvZiBwcmltYXJ5IGtleXMgb3IgZW50aXRpZXMgd2l0aCBhIGtleTtcbiAgICogdGhpcyByZWR1Y2VyIGV4dHJhY3RzIHRoZSBrZXkgZnJvbSB0aGUgZW50aXR5LlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVEZWxldGVNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248KG51bWJlciB8IHN0cmluZyB8IFQpW10+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGNvbnN0IGRlbGV0ZUlkcyA9IHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKS5tYXAoKGQpID0+XG4gICAgICB0eXBlb2YgZCA9PT0gJ29iamVjdCcgPyB0aGlzLnNlbGVjdElkKGQpIDogKGQgYXMgc3RyaW5nIHwgbnVtYmVyKVxuICAgICk7XG4gICAgZGVsZXRlSWRzLmZvckVhY2goKGRlbGV0ZUlkKSA9PiB7XG4gICAgICBjb25zdCBjaGFuZ2UgPSBjb2xsZWN0aW9uLmNoYW5nZVN0YXRlW2RlbGV0ZUlkXTtcbiAgICAgIC8vIElmIGVudGl0eSBpcyBhbHJlYWR5IHRyYWNrZWQgLi4uXG4gICAgICBpZiAoY2hhbmdlKSB7XG4gICAgICAgIGlmIChjaGFuZ2UuY2hhbmdlVHlwZSA9PT0gQ2hhbmdlVHlwZS5BZGRlZCkge1xuICAgICAgICAgIC8vIFJlbW92ZSB0aGUgYWRkZWQgZW50aXR5IGltbWVkaWF0ZWx5IGFuZCBmb3JnZXQgYWJvdXQgaXRzIGNoYW5nZXMgKHZpYSBjb21taXQpLlxuICAgICAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmFkYXB0ZXIucmVtb3ZlT25lKGRlbGV0ZUlkIGFzIHN0cmluZywgY29sbGVjdGlvbik7XG4gICAgICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5jb21taXRPbmUoZGVsZXRlSWQsIGNvbGxlY3Rpb24pO1xuICAgICAgICAgIC8vIFNob3VsZCBub3Qgd2FzdGUgZWZmb3J0IHRyeWluZyB0byBkZWxldGUgb24gdGhlIHNlcnZlciBiZWNhdXNlIGl0IGNhbid0IGJlIHRoZXJlLlxuICAgICAgICAgIGFjdGlvbi5wYXlsb2FkLnNraXAgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFJlLXRyYWNrIGl0IGFzIGEgZGVsZXRlLCBldmVuIGlmIHRyYWNraW5nIGlzIHR1cm5lZCBvZmYgZm9yIHRoaXMgY2FsbC5cbiAgICAgICAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrRGVsZXRlT25lKFxuICAgICAgICAgICAgZGVsZXRlSWQsXG4gICAgICAgICAgICBjb2xsZWN0aW9uXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIC8vIElmIG9wdGltaXN0aWMgZGVsZXRlLCB0cmFjayBjdXJyZW50IHN0YXRlIGFuZCByZW1vdmUgaW1tZWRpYXRlbHkuXG4gICAgaWYgKHRoaXMuaXNPcHRpbWlzdGljKGFjdGlvbikpIHtcbiAgICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrRGVsZXRlTWFueShcbiAgICAgICAgZGVsZXRlSWRzLFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgICApO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuYWRhcHRlci5yZW1vdmVNYW55KGRlbGV0ZUlkcyBhcyBzdHJpbmdbXSwgY29sbGVjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gZGVsZXRlIHRoZSBlbnRpdGllcyBvbiB0aGUgc2VydmVyIGZhaWxlZCBvciB0aW1lZC1vdXQuXG4gICAqIEFjdGlvbiBob2xkcyB0aGUgZXJyb3IuXG4gICAqIElmIHNhdmVkIHBlc3NpbWlzdGljYWxseSwgdGhlIGVudGl0aWVzIGNvdWxkIHN0aWxsIGJlIGluIHRoZSBjb2xsZWN0aW9uIGFuZFxuICAgKiB5b3UgbWF5IG5vdCBoYXZlIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBlcnJvci5cbiAgICogSWYgc2F2ZWQgb3B0aW1pc3RpY2FsbHksIHRoZSBlbnRpdGllcyBhcmUgbm90IGluIHRoZSBjb2xsZWN0aW9uIGFuZFxuICAgKiB5b3UgbWF5IG5lZWQgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVEZWxldGVNYW55RXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogU3VjY2Vzc2Z1bGx5IGRlbGV0ZWQgZW50aXRpZXMgb24gdGhlIHNlcnZlci4gVGhlIGtleXMgb2YgdGhlIGRlbGV0ZWQgZW50aXRpZXMgYXJlIGluIHRoZSBhY3Rpb24gcGF5bG9hZCBkYXRhLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIGVudGl0aWVzIHRoYXQgYXJlIHN0aWxsIGluIHRoZSBjb2xsZWN0aW9uIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICogSWYgc2F2ZWQgb3B0aW1pc3RpY2FsbHksIHRoZSBlbnRpdGllcyBoYXZlIGFscmVhZHkgYmVlbiByZW1vdmVkIGZyb20gdGhlIGNvbGxlY3Rpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZURlbGV0ZU1hbnlTdWNjZXNzKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248KG51bWJlciB8IHN0cmluZylbXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZGVsZXRlSWRzID0gdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pO1xuICAgIGlmICh0aGlzLmlzT3B0aW1pc3RpYyhhY3Rpb24pKSB7XG4gICAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVEZWxldGVzKFxuICAgICAgICBkZWxldGVJZHMsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFBlc3NpbWlzdGljOiBpZ25vcmUgbWVyZ2VTdHJhdGVneS4gUmVtb3ZlIGVudGl0eSBmcm9tIHRoZSBjb2xsZWN0aW9uIGFuZCBmcm9tIGNoYW5nZSB0cmFja2luZy5cbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmFkYXB0ZXIucmVtb3ZlTWFueShkZWxldGVJZHMgYXMgc3RyaW5nW10sIGNvbGxlY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5jb21taXRNYW55KGRlbGV0ZUlkcywgY29sbGVjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGYWxzZShjb2xsZWN0aW9uKTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uIHNhdmVEZWxldGVNYW55XG5cbiAgLy8gI3JlZ2lvbiBzYXZlVXBkYXRlT25lXG4gIC8qKlxuICAgKiBTYXZlIGFuIHVwZGF0ZSB0byBhbiBleGlzdGluZyBlbnRpdHkuXG4gICAqIElmIHNhdmluZyBwZXNzaW1pc3RpY2FsbHksIHVwZGF0ZSB0aGUgZW50aXR5IGluIHRoZSBjb2xsZWN0aW9uIGFmdGVyIHRoZSBzZXJ2ZXIgY29uZmlybXMgc3VjY2Vzcy5cbiAgICogSWYgc2F2aW5nIG9wdGltaXN0aWNhbGx5LCB1cGRhdGUgdGhlIGVudGl0eSBpbW1lZGlhdGVseSwgYmVmb3JlIHRoZSBzYXZlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gYWN0aW9uIFRoZSBhY3Rpb24gcGF5bG9hZCBob2xkcyBvcHRpb25zLCBpbmNsdWRpbmcgaWYgdGhlIHNhdmUgaXMgb3B0aW1pc3RpYyxcbiAgICogYW5kIHRoZSBkYXRhIHdoaWNoLCBtdXN0IGJlIGFuIHtVcGRhdGU8VD59XG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZVVwZGF0ZU9uZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFVwZGF0ZTxUPj5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgdXBkYXRlID0gdGhpcy5ndWFyZC5tdXN0QmVVcGRhdGUoYWN0aW9uKTtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tVcGRhdGVPbmUoXG4gICAgICAgIHVwZGF0ZSxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICAgKTtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmFkYXB0ZXIudXBkYXRlT25lKHVwZGF0ZSwgY29sbGVjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdUcnVlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gdXBkYXRlIHRoZSBlbnRpdHkgb24gdGhlIHNlcnZlciBmYWlsZWQgb3IgdGltZWQtb3V0LlxuICAgKiBBY3Rpb24gaG9sZHMgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIHRoZSBlbnRpdHkgaW4gdGhlIGNvbGxlY3Rpb24gaXMgaW4gdGhlIHByZS1zYXZlIHN0YXRlXG4gICAqIHlvdSBtYXkgbm90IGhhdmUgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIGVudGl0eSBpbiB0aGUgY29sbGVjdGlvbiB3YXMgdXBkYXRlZFxuICAgKiBhbmQgeW91IG1heSBuZWVkIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBlcnJvci5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlVXBkYXRlT25lRXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogU3VjY2Vzc2Z1bGx5IHNhdmVkIHRoZSB1cGRhdGVkIGVudGl0eSB0byB0aGUgc2VydmVyLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIHVwZGF0ZSB0aGUgZW50aXR5IGluIHRoZSBjb2xsZWN0aW9uIHdpdGggZGF0YSBmcm9tIHRoZSBzZXJ2ZXIuXG4gICAqIElmIHNhdmVkIG9wdGltaXN0aWNhbGx5LCB0aGUgZW50aXR5IHdhcyBhbHJlYWR5IHVwZGF0ZWQgaW4gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEhvd2V2ZXIsIHRoZSBzZXJ2ZXIgbWlnaHQgaGF2ZSBzZXQgb3IgbW9kaWZpZWQgb3RoZXIgZmllbGRzIChlLmcsIGNvbmN1cnJlbmN5IGZpZWxkKVxuICAgKiBUaGVyZWZvcmUsIHVwZGF0ZSB0aGUgZW50aXR5IGluIHRoZSBjb2xsZWN0aW9uIHdpdGggdGhlIHJldHVybmVkIHZhbHVlIChpZiBhbnkpXG4gICAqIENhdXRpb246IGluIGEgcmFjZSwgdGhpcyB1cGRhdGUgY291bGQgb3ZlcndyaXRlIHVuc2F2ZWQgdXNlciBjaGFuZ2VzLlxuICAgKiBVc2UgcGVzc2ltaXN0aWMgdXBkYXRlIHRvIGF2b2lkIHRoaXMgcmlzay5cbiAgICogQHBhcmFtIGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gdXBkYXRlXG4gICAqIEBwYXJhbSBhY3Rpb24gVGhlIGFjdGlvbiBwYXlsb2FkIGhvbGRzIG9wdGlvbnMsIGluY2x1ZGluZyBpZiB0aGUgc2F2ZSBpcyBvcHRpbWlzdGljLCBhbmRcbiAgICogdGhlIHVwZGF0ZSBkYXRhIHdoaWNoLCBtdXN0IGJlIGFuIFVwZGF0ZVJlc3BvbnNlPFQ+IHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIFVwZGF0ZSBzZW50IHRvIHRoZSBzZXJ2ZXIuXG4gICAqIFlvdSBtdXN0IGluY2x1ZGUgYW4gVXBkYXRlUmVzcG9uc2UgZXZlbiBpZiB0aGUgc2F2ZSB3YXMgb3B0aW1pc3RpYyxcbiAgICogdG8gZW5zdXJlIHRoYXQgdGhlIGNoYW5nZSB0cmFja2luZyBpcyBwcm9wZXJseSByZXNldC5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlVXBkYXRlT25lU3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFVwZGF0ZVJlc3BvbnNlRGF0YTxUPj5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgdXBkYXRlID0gdGhpcy5ndWFyZC5tdXN0QmVVcGRhdGVSZXNwb25zZShhY3Rpb24pO1xuICAgIGNvbnN0IGlzT3B0aW1pc3RpYyA9IHRoaXMuaXNPcHRpbWlzdGljKGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLm1lcmdlU2F2ZVVwZGF0ZXMoXG4gICAgICBbdXBkYXRlXSxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBtZXJnZVN0cmF0ZWd5LFxuICAgICAgaXNPcHRpbWlzdGljIC8qc2tpcCB1bmNoYW5nZWQgaWYgb3B0aW1pc3RpYyAqL1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG4gIC8vICNlbmRyZWdpb24gc2F2ZVVwZGF0ZU9uZVxuXG4gIC8vICNyZWdpb24gc2F2ZVVwZGF0ZU1hbnlcbiAgLyoqXG4gICAqIFNhdmUgdXBkYXRlZCBlbnRpdGllcy5cbiAgICogSWYgc2F2aW5nIHBlc3NpbWlzdGljYWxseSwgdXBkYXRlIHRoZSBlbnRpdGllcyBpbiB0aGUgY29sbGVjdGlvbiBhZnRlciB0aGUgc2VydmVyIGNvbmZpcm1zIHN1Y2Nlc3MuXG4gICAqIElmIHNhdmluZyBvcHRpbWlzdGljYWxseSwgdXBkYXRlIHRoZSBlbnRpdGllcyBpbW1lZGlhdGVseSwgYmVmb3JlIHRoZSBzYXZlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gYWN0aW9uIFRoZSBhY3Rpb24gcGF5bG9hZCBob2xkcyBvcHRpb25zLCBpbmNsdWRpbmcgaWYgdGhlIHNhdmUgaXMgb3B0aW1pc3RpYyxcbiAgICogYW5kIHRoZSBkYXRhIHdoaWNoLCBtdXN0IGJlIGFuIGFycmF5IG9mIHtVcGRhdGU8VD59LlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcGRhdGVNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VXBkYXRlPFQ+W10+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIGNvbnN0IHVwZGF0ZXMgPSB0aGlzLmd1YXJkLm11c3RCZVVwZGF0ZXMoYWN0aW9uKTtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tVcGRhdGVNYW55KFxuICAgICAgICB1cGRhdGVzLFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgICApO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuYWRhcHRlci51cGRhdGVNYW55KHVwZGF0ZXMsIGNvbGxlY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nVHJ1ZShjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0IHRvIHVwZGF0ZSBlbnRpdGllcyBvbiB0aGUgc2VydmVyIGZhaWxlZCBvciB0aW1lZC1vdXQuXG4gICAqIEFjdGlvbiBob2xkcyB0aGUgZXJyb3IuXG4gICAqIElmIHNhdmVkIHBlc3NpbWlzdGljYWxseSwgdGhlIGVudGl0aWVzIGluIHRoZSBjb2xsZWN0aW9uIGFyZSBpbiB0aGUgcHJlLXNhdmUgc3RhdGVcbiAgICogeW91IG1heSBub3QgaGF2ZSB0byBjb21wZW5zYXRlIGZvciB0aGUgZXJyb3IuXG4gICAqIElmIHNhdmVkIG9wdGltaXN0aWNhbGx5LCB0aGUgZW50aXRpZXMgaW4gdGhlIGNvbGxlY3Rpb24gd2VyZSB1cGRhdGVkXG4gICAqIGFuZCB5b3UgbWF5IG5lZWQgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcGRhdGVNYW55RXJyb3IoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxFbnRpdHlBY3Rpb25EYXRhU2VydmljZUVycm9yPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmFsc2UoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogU3VjY2Vzc2Z1bGx5IHNhdmVkIHRoZSB1cGRhdGVkIGVudGl0aWVzIHRvIHRoZSBzZXJ2ZXIuXG4gICAqIElmIHNhdmVkIHBlc3NpbWlzdGljYWxseSwgdGhlIGVudGl0aWVzIGluIHRoZSBjb2xsZWN0aW9uIHdpbGwgYmUgdXBkYXRlZCB3aXRoIGRhdGEgZnJvbSB0aGUgc2VydmVyLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIGVudGl0aWVzIGluIHRoZSBjb2xsZWN0aW9uIHdlcmUgYWxyZWFkeSB1cGRhdGVkLlxuICAgKiBIb3dldmVyLCB0aGUgc2VydmVyIG1pZ2h0IGhhdmUgc2V0IG9yIG1vZGlmaWVkIG90aGVyIGZpZWxkcyAoZS5nLCBjb25jdXJyZW5jeSBmaWVsZClcbiAgICogVGhlcmVmb3JlLCB1cGRhdGUgdGhlIGVudGl0eSBpbiB0aGUgY29sbGVjdGlvbiB3aXRoIHRoZSByZXR1cm5lZCB2YWx1ZXMgKGlmIGFueSlcbiAgICogQ2F1dGlvbjogaW4gYSByYWNlLCB0aGlzIHVwZGF0ZSBjb3VsZCBvdmVyd3JpdGUgdW5zYXZlZCB1c2VyIGNoYW5nZXMuXG4gICAqIFVzZSBwZXNzaW1pc3RpYyB1cGRhdGUgdG8gYXZvaWQgdGhpcyByaXNrLlxuICAgKiBAcGFyYW0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byB1cGRhdGVcbiAgICogQHBhcmFtIGFjdGlvbiBUaGUgYWN0aW9uIHBheWxvYWQgaG9sZHMgb3B0aW9ucywgaW5jbHVkaW5nIGlmIHRoZSBzYXZlIGlzIG9wdGltaXN0aWMsXG4gICAqIGFuZCB0aGUgZGF0YSB3aGljaCwgbXVzdCBiZSBhbiBhcnJheSBvZiBVcGRhdGVSZXNwb25zZTxUPi5cbiAgICogWW91IG11c3QgaW5jbHVkZSBhbiBVcGRhdGVSZXNwb25zZSBmb3IgZXZlcnkgVXBkYXRlIHNlbnQgdG8gdGhlIHNlcnZlcixcbiAgICogZXZlbiBpZiB0aGUgc2F2ZSB3YXMgb3B0aW1pc3RpYywgdG8gZW5zdXJlIHRoYXQgdGhlIGNoYW5nZSB0cmFja2luZyBpcyBwcm9wZXJseSByZXNldC5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlVXBkYXRlTWFueVN1Y2Nlc3MoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxVcGRhdGVSZXNwb25zZURhdGE8VD5bXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgdXBkYXRlcyA9IHRoaXMuZ3VhcmQubXVzdEJlVXBkYXRlUmVzcG9uc2VzKGFjdGlvbik7XG4gICAgY29uc3QgaXNPcHRpbWlzdGljID0gdGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIubWVyZ2VTYXZlVXBkYXRlcyhcbiAgICAgIHVwZGF0ZXMsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneSxcbiAgICAgIGZhbHNlIC8qIG5ldmVyIHNraXAgKi9cbiAgICApO1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGYWxzZShjb2xsZWN0aW9uKTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uIHNhdmVVcGRhdGVNYW55XG5cbiAgLy8gI3JlZ2lvbiBzYXZlVXBzZXJ0T25lXG4gIC8qKlxuICAgKiBTYXZlIGEgbmV3IG9yIGV4aXN0aW5nIGVudGl0eS5cbiAgICogSWYgc2F2aW5nIHBlc3NpbWlzdGljYWxseSwgZGVsYXkgYWRkaW5nIHRvIGNvbGxlY3Rpb24gdW50aWwgc2VydmVyIGFja25vd2xlZGdlcyBzdWNjZXNzLlxuICAgKiBJZiBzYXZpbmcgb3B0aW1pc3RpY2FsbHk7IGFkZCBpbW1lZGlhdGVseS5cbiAgICogQHBhcmFtIGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gd2hpY2ggdGhlIGVudGl0eSBzaG91bGQgYmUgdXBzZXJ0ZWQuXG4gICAqIEBwYXJhbSBhY3Rpb24gVGhlIGFjdGlvbiBwYXlsb2FkIGhvbGRzIG9wdGlvbnMsIGluY2x1ZGluZyB3aGV0aGVyIHRoZSBzYXZlIGlzIG9wdGltaXN0aWMsXG4gICAqIGFuZCB0aGUgZGF0YSwgd2hpY2ggbXVzdCBiZSBhIHdob2xlIGVudGl0eS5cbiAgICogSWYgc2F2aW5nIG9wdGltaXN0aWNhbGx5LCB0aGUgZW50aXR5IG11c3QgaGF2ZSBpdHMga2V5LlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcHNlcnRPbmUoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29uc3QgZW50aXR5ID0gdGhpcy5ndWFyZC5tdXN0QmVFbnRpdHkoYWN0aW9uKTsgLy8gZW5zdXJlIHRoZSBlbnRpdHkgaGFzIGEgUEtcbiAgICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrVXBzZXJ0T25lKFxuICAgICAgICBlbnRpdHksXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIG1lcmdlU3RyYXRlZ3lcbiAgICAgICk7XG4gICAgICBjb2xsZWN0aW9uID0gdGhpcy5hZGFwdGVyLnVwc2VydE9uZShlbnRpdHksIGNvbGxlY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nVHJ1ZShjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0IHRvIHNhdmUgbmV3IG9yIGV4aXN0aW5nIGVudGl0eSBmYWlsZWQgb3IgdGltZWQtb3V0LlxuICAgKiBBY3Rpb24gaG9sZHMgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIG5ldyBvciB1cGRhdGVkIGVudGl0eSBpcyBub3QgaW4gdGhlIGNvbGxlY3Rpb24gYW5kXG4gICAqIHlvdSBtYXkgbm90IGhhdmUgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBvcHRpbWlzdGljYWxseSwgdGhlIHVuc2F2ZWQgZW50aXRpZXMgYXJlIGluIHRoZSBjb2xsZWN0aW9uIGFuZFxuICAgKiB5b3UgbWF5IG5lZWQgdG8gY29tcGVuc2F0ZSBmb3IgdGhlIGVycm9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcHNlcnRPbmVFcnJvcihcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPEVudGl0eUFjdGlvbkRhdGFTZXJ2aWNlRXJyb3I+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGYWxzZShjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWNjZXNzZnVsbHkgc2F2ZWQgbmV3IG9yIGV4aXN0aW5nIGVudGl0aWVzIHRvIHRoZSBzZXJ2ZXIuXG4gICAqIElmIHNhdmVkIHBlc3NpbWlzdGljYWxseSwgYWRkIHRoZSBlbnRpdGllcyBmcm9tIHRoZSBzZXJ2ZXIgdG8gdGhlIGNvbGxlY3Rpb24uXG4gICAqIElmIHNhdmVkIG9wdGltaXN0aWNhbGx5LCB0aGUgYWRkZWQgZW50aXRpZXMgYXJlIGFscmVhZHkgaW4gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEhvd2V2ZXIsIHRoZSBzZXJ2ZXIgbWlnaHQgaGF2ZSBzZXQgb3IgbW9kaWZpZWQgb3RoZXIgZmllbGRzIChlLmcsIGNvbmN1cnJlbmN5IGZpZWxkKVxuICAgKiBUaGVyZWZvcmUsIHVwZGF0ZSB0aGUgZW50aXRpZXMgaW4gdGhlIGNvbGxlY3Rpb24gd2l0aCB0aGUgcmV0dXJuZWQgdmFsdWVzIChpZiBhbnkpXG4gICAqIENhdXRpb246IGluIGEgcmFjZSwgdGhpcyB1cGRhdGUgY291bGQgb3ZlcndyaXRlIHVuc2F2ZWQgdXNlciBjaGFuZ2VzLlxuICAgKiBVc2UgcGVzc2ltaXN0aWMgYWRkIHRvIGF2b2lkIHRoaXMgcmlzay5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlVXBzZXJ0T25lU3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICkge1xuICAgIC8vIEZvciBwZXNzaW1pc3RpYyBzYXZlLCBlbnN1cmUgdGhlIHNlcnZlciBnZW5lcmF0ZWQgdGhlIHByaW1hcnkga2V5IGlmIHRoZSBjbGllbnQgZGlkbid0IHNlbmQgb25lLlxuICAgIGNvbnN0IGVudGl0eSA9IHRoaXMuZ3VhcmQubXVzdEJlRW50aXR5KGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICAvLyBBbHdheXMgdXBkYXRlIHRoZSBjYWNoZSB3aXRoIHVwc2VydGVkIGVudGl0aWVzIHJldHVybmVkIGZyb20gc2VydmVyXG4gICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVVcHNlcnRzKFxuICAgICAgW2VudGl0eV0sXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG4gIC8vICNlbmRyZWdpb24gc2F2ZVVwc2VydE9uZVxuXG4gIC8vICNyZWdpb24gc2F2ZVVwc2VydE1hbnlcbiAgLyoqXG4gICAqIFNhdmUgbXVsdGlwbGUgbmV3IG9yIGV4aXN0aW5nIGVudGl0aWVzLlxuICAgKiBJZiBzYXZpbmcgcGVzc2ltaXN0aWNhbGx5LCBkZWxheSBhZGRpbmcgdG8gY29sbGVjdGlvbiB1bnRpbCBzZXJ2ZXIgYWNrbm93bGVkZ2VzIHN1Y2Nlc3MuXG4gICAqIElmIHNhdmluZyBvcHRpbWlzdGljYWxseTsgYWRkIGltbWVkaWF0ZWx5LlxuICAgKiBAcGFyYW0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byB3aGljaCB0aGUgZW50aXRpZXMgc2hvdWxkIGJlIHVwc2VydGVkLlxuICAgKiBAcGFyYW0gYWN0aW9uIFRoZSBhY3Rpb24gcGF5bG9hZCBob2xkcyBvcHRpb25zLCBpbmNsdWRpbmcgd2hldGhlciB0aGUgc2F2ZSBpcyBvcHRpbWlzdGljLFxuICAgKiBhbmQgdGhlIGRhdGEsIHdoaWNoIG11c3QgYmUgYW4gYXJyYXkgb2Ygd2hvbGUgZW50aXRpZXMuXG4gICAqIElmIHNhdmluZyBvcHRpbWlzdGljYWxseSwgdGhlIGVudGl0aWVzIG11c3QgaGF2ZSB0aGVpciBrZXlzLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcHNlcnRNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VFtdPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICBpZiAodGhpcy5pc09wdGltaXN0aWMoYWN0aW9uKSkge1xuICAgICAgY29uc3QgZW50aXRpZXMgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0aWVzKGFjdGlvbik7IC8vIGVuc3VyZSB0aGUgZW50aXR5IGhhcyBhIFBLXG4gICAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci50cmFja1Vwc2VydE1hbnkoXG4gICAgICAgIGVudGl0aWVzLFxuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgICApO1xuICAgICAgY29sbGVjdGlvbiA9IHRoaXMuYWRhcHRlci51cHNlcnRNYW55KGVudGl0aWVzLCBjb2xsZWN0aW9uKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ1RydWUoY29sbGVjdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogQXR0ZW1wdCB0byBzYXZlIG5ldyBvciBleGlzdGluZyBlbnRpdGllcyBmYWlsZWQgb3IgdGltZWQtb3V0LlxuICAgKiBBY3Rpb24gaG9sZHMgdGhlIGVycm9yLlxuICAgKiBJZiBzYXZlZCBwZXNzaW1pc3RpY2FsbHksIG5ldyBlbnRpdGllcyBhcmUgbm90IGluIHRoZSBjb2xsZWN0aW9uIGFuZFxuICAgKiB5b3UgbWF5IG5vdCBoYXZlIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBlcnJvci5cbiAgICogSWYgc2F2ZWQgb3B0aW1pc3RpY2FsbHksIHRoZSB1bnNhdmVkIGVudGl0aWVzIGFyZSBpbiB0aGUgY29sbGVjdGlvbiBhbmRcbiAgICogeW91IG1heSBuZWVkIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBlcnJvci5cbiAgICovXG4gIHByb3RlY3RlZCBzYXZlVXBzZXJ0TWFueUVycm9yKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248RW50aXR5QWN0aW9uRGF0YVNlcnZpY2VFcnJvcj5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1Y2Nlc3NmdWxseSBzYXZlZCBuZXcgb3IgZXhpc3RpbmcgZW50aXRpZXMgdG8gdGhlIHNlcnZlci5cbiAgICogSWYgc2F2ZWQgcGVzc2ltaXN0aWNhbGx5LCBhZGQgdGhlIGVudGl0aWVzIGZyb20gdGhlIHNlcnZlciB0byB0aGUgY29sbGVjdGlvbi5cbiAgICogSWYgc2F2ZWQgb3B0aW1pc3RpY2FsbHksIHRoZSBhZGRlZCBlbnRpdGllcyBhcmUgYWxyZWFkeSBpbiB0aGUgY29sbGVjdGlvbi5cbiAgICogSG93ZXZlciwgdGhlIHNlcnZlciBtaWdodCBoYXZlIHNldCBvciBtb2RpZmllZCBvdGhlciBmaWVsZHMgKGUuZywgY29uY3VycmVuY3kgZmllbGQpXG4gICAqIFRoZXJlZm9yZSwgdXBkYXRlIHRoZSBlbnRpdGllcyBpbiB0aGUgY29sbGVjdGlvbiB3aXRoIHRoZSByZXR1cm5lZCB2YWx1ZXMgKGlmIGFueSlcbiAgICogQ2F1dGlvbjogaW4gYSByYWNlLCB0aGlzIHVwZGF0ZSBjb3VsZCBvdmVyd3JpdGUgdW5zYXZlZCB1c2VyIGNoYW5nZXMuXG4gICAqIFVzZSBwZXNzaW1pc3RpYyBhZGQgdG8gYXZvaWQgdGhpcyByaXNrLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVVcHNlcnRNYW55U3VjY2VzcyhcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKSB7XG4gICAgLy8gRm9yIHBlc3NpbWlzdGljIHNhdmUsIGVuc3VyZSB0aGUgc2VydmVyIGdlbmVyYXRlZCB0aGUgcHJpbWFyeSBrZXkgaWYgdGhlIGNsaWVudCBkaWRuJ3Qgc2VuZCBvbmUuXG4gICAgY29uc3QgZW50aXRpZXMgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0aWVzKGFjdGlvbik7XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICAvLyBBbHdheXMgdXBkYXRlIHRoZSBjYWNoZSB3aXRoIHVwc2VydGVkIGVudGl0aWVzIHJldHVybmVkIGZyb20gc2VydmVyXG4gICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci5tZXJnZVNhdmVVcHNlcnRzKFxuICAgICAgZW50aXRpZXMsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2V0TG9hZGluZ0ZhbHNlKGNvbGxlY3Rpb24pO1xuICB9XG4gIC8vICNlbmRyZWdpb24gc2F2ZVVwc2VydE1hbnlcblxuICAvLyAjZW5kcmVnaW9uIHNhdmUgb3BlcmF0aW9uc1xuXG4gIC8vICNyZWdpb24gY2FjaGUtb25seSBvcGVyYXRpb25zXG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIGFsbCBlbnRpdGllcyBpbiB0aGUgY29sbGVjdGlvblxuICAgKiBTZXRzIGxvYWRlZCBmbGFnIHRvIHRydWUuXG4gICAqIE1lcmdlcyBxdWVyeSByZXN1bHRzLCBwcmVzZXJ2aW5nIHVuc2F2ZWQgY2hhbmdlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFkZEFsbChcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFRbXT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZW50aXRpZXMgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0aWVzKGFjdGlvbik7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMuYWRhcHRlci5zZXRBbGwoZW50aXRpZXMsIGNvbGxlY3Rpb24pLFxuICAgICAgbG9hZGluZzogZmFsc2UsXG4gICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICBjaGFuZ2VTdGF0ZToge30sXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhZGRNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VFtdPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICBjb25zdCBlbnRpdGllcyA9IHRoaXMuZ3VhcmQubXVzdEJlRW50aXRpZXMoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tBZGRNYW55KFxuICAgICAgZW50aXRpZXMsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5hZGRNYW55KGVudGl0aWVzLCBjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhZGRPbmUoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICBjb25zdCBlbnRpdHkgPSB0aGlzLmd1YXJkLm11c3RCZUVudGl0eShhY3Rpb24pO1xuICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci50cmFja0FkZE9uZShcbiAgICAgIGVudGl0eSxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLmFkZE9uZShlbnRpdHksIGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlbW92ZU1hbnkoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxudW1iZXJbXSB8IHN0cmluZ1tdPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICAvLyBwYXlsb2FkIG11c3QgYmUgZW50aXR5IGtleXNcbiAgICBjb25zdCBrZXlzID0gdGhpcy5ndWFyZC5tdXN0QmVLZXlzKGFjdGlvbikgYXMgc3RyaW5nW107XG4gICAgY29uc3QgbWVyZ2VTdHJhdGVneSA9IHRoaXMuZXh0cmFjdE1lcmdlU3RyYXRlZ3koYWN0aW9uKTtcbiAgICBjb2xsZWN0aW9uID0gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnRyYWNrRGVsZXRlTWFueShcbiAgICAgIGtleXMsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZW1vdmVNYW55KGtleXMsIGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlbW92ZU9uZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPG51bWJlciB8IHN0cmluZz5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgLy8gcGF5bG9hZCBtdXN0IGJlIGVudGl0eSBrZXlcbiAgICBjb25zdCBrZXkgPSB0aGlzLmd1YXJkLm11c3RCZUtleShhY3Rpb24pIGFzIHN0cmluZztcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tEZWxldGVPbmUoXG4gICAgICBrZXksXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZW1vdmVPbmUoa2V5LCBjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZW1vdmVBbGwoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5hZGFwdGVyLnJlbW92ZUFsbChjb2xsZWN0aW9uKSxcbiAgICAgIGxvYWRlZDogZmFsc2UsIC8vIE9ubHkgUkVNT1ZFX0FMTCBzZXRzIGxvYWRlZCB0byBmYWxzZVxuICAgICAgbG9hZGluZzogZmFsc2UsXG4gICAgICBjaGFuZ2VTdGF0ZToge30sIC8vIEFzc3VtZSBjbGVhcmluZyB0aGUgY29sbGVjdGlvbiBhbmQgbm90IHRyeWluZyB0byBkZWxldGUgYWxsIGVudGl0aWVzXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCB1cGRhdGVNYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VXBkYXRlPFQ+W10+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIC8vIHBheWxvYWQgbXVzdCBiZSBhbiBhcnJheSBvZiBgVXBkYXRlczxUPmAsIG5vdCBlbnRpdGllc1xuICAgIGNvbnN0IHVwZGF0ZXMgPSB0aGlzLmd1YXJkLm11c3RCZVVwZGF0ZXMoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tVcGRhdGVNYW55KFxuICAgICAgdXBkYXRlcyxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwZGF0ZU1hbnkodXBkYXRlcywgY29sbGVjdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlT25lKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VXBkYXRlPFQ+PlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICAvLyBwYXlsb2FkIG11c3QgYmUgYW4gYFVwZGF0ZTxUPmAsIG5vdCBhbiBlbnRpdHlcbiAgICBjb25zdCB1cGRhdGUgPSB0aGlzLmd1YXJkLm11c3RCZVVwZGF0ZShhY3Rpb24pO1xuICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci50cmFja1VwZGF0ZU9uZShcbiAgICAgIHVwZGF0ZSxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwZGF0ZU9uZSh1cGRhdGUsIGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHVwc2VydE1hbnkoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUW10+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIC8vIDx2NjogcGF5bG9hZCBtdXN0IGJlIGFuIGFycmF5IG9mIGBVcGRhdGVzPFQ+YCwgbm90IGVudGl0aWVzXG4gICAgLy8gdjYrOiBwYXlsb2FkIG11c3QgYmUgYW4gYXJyYXkgb2YgVFxuICAgIGNvbnN0IGVudGl0aWVzID0gdGhpcy5ndWFyZC5tdXN0QmVFbnRpdGllcyhhY3Rpb24pO1xuICAgIGNvbnN0IG1lcmdlU3RyYXRlZ3kgPSB0aGlzLmV4dHJhY3RNZXJnZVN0cmF0ZWd5KGFjdGlvbik7XG4gICAgY29sbGVjdGlvbiA9IHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci50cmFja1Vwc2VydE1hbnkoXG4gICAgICBlbnRpdGllcyxcbiAgICAgIGNvbGxlY3Rpb24sXG4gICAgICBtZXJnZVN0cmF0ZWd5XG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnVwc2VydE1hbnkoZW50aXRpZXMsIGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHVwc2VydE9uZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIC8vIDx2NjogcGF5bG9hZCBtdXN0IGJlIGFuIGBVcGRhdGU8VD5gLCBub3QgYW4gZW50aXR5XG4gICAgLy8gdjYrOiBwYXlsb2FkIG11c3QgYmUgYSBUXG4gICAgY29uc3QgZW50aXR5ID0gdGhpcy5ndWFyZC5tdXN0QmVFbnRpdHkoYWN0aW9uKTtcbiAgICBjb25zdCBtZXJnZVN0cmF0ZWd5ID0gdGhpcy5leHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb24pO1xuICAgIGNvbGxlY3Rpb24gPSB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudHJhY2tVcHNlcnRPbmUoXG4gICAgICBlbnRpdHksXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgbWVyZ2VTdHJhdGVneVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci51cHNlcnRPbmUoZW50aXR5LCBjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb21taXRBbGwoY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPikge1xuICAgIHJldHVybiB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIuY29tbWl0QWxsKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbW1pdE1hbnkoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxUW10+XG4gICkge1xuICAgIHJldHVybiB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIuY29tbWl0TWFueShcbiAgICAgIHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKSxcbiAgICAgIGNvbGxlY3Rpb25cbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbW1pdE9uZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPFQ+XG4gICkge1xuICAgIHJldHVybiB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIuY29tbWl0T25lKFxuICAgICAgdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pLFxuICAgICAgY29sbGVjdGlvblxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdW5kb0FsbChjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+KSB7XG4gICAgcmV0dXJuIHRoaXMuZW50aXR5Q2hhbmdlVHJhY2tlci51bmRvQWxsKGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHVuZG9NYW55KFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248VFtdPlxuICApIHtcbiAgICByZXR1cm4gdGhpcy5lbnRpdHlDaGFuZ2VUcmFja2VyLnVuZG9NYW55KFxuICAgICAgdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pLFxuICAgICAgY29sbGVjdGlvblxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdW5kb09uZShjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LCBhY3Rpb246IEVudGl0eUFjdGlvbjxUPikge1xuICAgIHJldHVybiB0aGlzLmVudGl0eUNoYW5nZVRyYWNrZXIudW5kb09uZShcbiAgICAgIHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKSxcbiAgICAgIGNvbGxlY3Rpb25cbiAgICApO1xuICB9XG5cbiAgLyoqIERhbmdlcm91czogQ29tcGxldGVseSByZXBsYWNlIHRoZSBjb2xsZWN0aW9uJ3MgQ2hhbmdlU3RhdGUuIFVzZSByYXJlbHkgYW5kIHdpc2VseS4gKi9cbiAgcHJvdGVjdGVkIHNldENoYW5nZVN0YXRlKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248Q2hhbmdlU3RhdGVNYXA8VD4+XG4gICkge1xuICAgIGNvbnN0IGNoYW5nZVN0YXRlID0gdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pO1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmNoYW5nZVN0YXRlID09PSBjaGFuZ2VTdGF0ZVxuICAgICAgPyBjb2xsZWN0aW9uXG4gICAgICA6IHsgLi4uY29sbGVjdGlvbiwgY2hhbmdlU3RhdGUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEYW5nZXJvdXM6IENvbXBsZXRlbHkgcmVwbGFjZSB0aGUgY29sbGVjdGlvbi5cbiAgICogUHJpbWFyaWx5IGZvciB0ZXN0aW5nIGFuZCByZWh5ZHJhdGlvbiBmcm9tIGxvY2FsIHN0b3JhZ2UuXG4gICAqIFVzZSByYXJlbHkgYW5kIHdpc2VseS5cbiAgICovXG4gIHByb3RlY3RlZCBzZXRDb2xsZWN0aW9uKFxuICAgIGNvbGxlY3Rpb246IEVudGl0eUNvbGxlY3Rpb248VD4sXG4gICAgYWN0aW9uOiBFbnRpdHlBY3Rpb248RW50aXR5Q29sbGVjdGlvbjxUPj5cbiAgKSB7XG4gICAgY29uc3QgbmV3Q29sbGVjdGlvbiA9IHRoaXMuZXh0cmFjdERhdGEoYWN0aW9uKTtcbiAgICByZXR1cm4gY29sbGVjdGlvbiA9PT0gbmV3Q29sbGVjdGlvbiA/IGNvbGxlY3Rpb24gOiBuZXdDb2xsZWN0aW9uO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldEZpbHRlcihcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+LFxuICAgIGFjdGlvbjogRW50aXR5QWN0aW9uPGFueT5cbiAgKTogRW50aXR5Q29sbGVjdGlvbjxUPiB7XG4gICAgY29uc3QgZmlsdGVyID0gdGhpcy5leHRyYWN0RGF0YShhY3Rpb24pO1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlciA9PT0gZmlsdGVyXG4gICAgICA/IGNvbGxlY3Rpb25cbiAgICAgIDogeyAuLi5jb2xsZWN0aW9uLCBmaWx0ZXIgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRMb2FkZWQoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxib29sZWFuPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICBjb25zdCBsb2FkZWQgPSB0aGlzLmV4dHJhY3REYXRhKGFjdGlvbikgPT09IHRydWUgfHwgZmFsc2U7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubG9hZGVkID09PSBsb2FkZWRcbiAgICAgID8gY29sbGVjdGlvblxuICAgICAgOiB7IC4uLmNvbGxlY3Rpb24sIGxvYWRlZCB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldExvYWRpbmcoXG4gICAgY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPixcbiAgICBhY3Rpb246IEVudGl0eUFjdGlvbjxib29sZWFuPlxuICApOiBFbnRpdHlDb2xsZWN0aW9uPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRMb2FkaW5nRmxhZyhjb2xsZWN0aW9uLCB0aGlzLmV4dHJhY3REYXRhKGFjdGlvbikpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldExvYWRpbmdGYWxzZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGbGFnKGNvbGxlY3Rpb24sIGZhbHNlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRMb2FkaW5nVHJ1ZShcbiAgICBjb2xsZWN0aW9uOiBFbnRpdHlDb2xsZWN0aW9uPFQ+XG4gICk6IEVudGl0eUNvbGxlY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLnNldExvYWRpbmdGbGFnKGNvbGxlY3Rpb24sIHRydWUpO1xuICB9XG5cbiAgLyoqIFNldCB0aGUgY29sbGVjdGlvbidzIGxvYWRpbmcgZmxhZyAqL1xuICBwcm90ZWN0ZWQgc2V0TG9hZGluZ0ZsYWcoY29sbGVjdGlvbjogRW50aXR5Q29sbGVjdGlvbjxUPiwgbG9hZGluZzogYm9vbGVhbikge1xuICAgIGxvYWRpbmcgPSBsb2FkaW5nID09PSB0cnVlID8gdHJ1ZSA6IGZhbHNlO1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxvYWRpbmcgPT09IGxvYWRpbmdcbiAgICAgID8gY29sbGVjdGlvblxuICAgICAgOiB7IC4uLmNvbGxlY3Rpb24sIGxvYWRpbmcgfTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uIENhY2hlLW9ubHkgb3BlcmF0aW9uc1xuXG4gIC8vICNyZWdpb24gaGVscGVyc1xuICAvKiogU2FmZWx5IGV4dHJhY3QgZGF0YSBmcm9tIHRoZSBFbnRpdHlBY3Rpb24gcGF5bG9hZCAqL1xuICBwcm90ZWN0ZWQgZXh0cmFjdERhdGE8RCA9IGFueT4oYWN0aW9uOiBFbnRpdHlBY3Rpb248RD4pOiBEIHtcbiAgICByZXR1cm4gKGFjdGlvbi5wYXlsb2FkICYmIGFjdGlvbi5wYXlsb2FkLmRhdGEpIGFzIEQ7XG4gIH1cblxuICAvKiogU2FmZWx5IGV4dHJhY3QgTWVyZ2VTdHJhdGVneSBmcm9tIEVudGl0eUFjdGlvbi4gU2V0IHRvIElnbm9yZUNoYW5nZXMgaWYgY29sbGVjdGlvbiBpdHNlbGYgaXMgbm90IHRyYWNrZWQuICovXG4gIHByb3RlY3RlZCBleHRyYWN0TWVyZ2VTdHJhdGVneShhY3Rpb246IEVudGl0eUFjdGlvbikge1xuICAgIC8vIElmIG5vdCB0cmFja2luZyB0aGlzIGNvbGxlY3Rpb24sIGFsd2F5cyBpZ25vcmUgY2hhbmdlc1xuICAgIHJldHVybiB0aGlzLmlzQ2hhbmdlVHJhY2tpbmdcbiAgICAgID8gYWN0aW9uLnBheWxvYWQgJiYgYWN0aW9uLnBheWxvYWQubWVyZ2VTdHJhdGVneVxuICAgICAgOiBNZXJnZVN0cmF0ZWd5Lklnbm9yZUNoYW5nZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgaXNPcHRpbWlzdGljKGFjdGlvbjogRW50aXR5QWN0aW9uKSB7XG4gICAgcmV0dXJuIGFjdGlvbi5wYXlsb2FkICYmIGFjdGlvbi5wYXlsb2FkLmlzT3B0aW1pc3RpYyA9PT0gdHJ1ZTtcbiAgfVxuXG4gIC8vICNlbmRyZWdpb24gaGVscGVyc1xufVxuXG4vKipcbiAqIENyZWF0ZXMge0VudGl0eUNvbGxlY3Rpb25SZWR1Y2VyTWV0aG9kc30gZm9yIGEgZ2l2ZW4gZW50aXR5IHR5cGUuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBFbnRpdHlDb2xsZWN0aW9uUmVkdWNlck1ldGhvZHNGYWN0b3J5IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlbnRpdHlEZWZpbml0aW9uU2VydmljZTogRW50aXR5RGVmaW5pdGlvblNlcnZpY2UpIHt9XG5cbiAgLyoqIENyZWF0ZSB0aGUgIHtFbnRpdHlDb2xsZWN0aW9uUmVkdWNlck1ldGhvZHN9IGZvciB0aGUgbmFtZWQgZW50aXR5IHR5cGUgKi9cbiAgY3JlYXRlPFQ+KGVudGl0eU5hbWU6IHN0cmluZyk6IEVudGl0eUNvbGxlY3Rpb25SZWR1Y2VyTWV0aG9kTWFwPFQ+IHtcbiAgICBjb25zdCBkZWZpbml0aW9uID0gdGhpcy5lbnRpdHlEZWZpbml0aW9uU2VydmljZS5nZXREZWZpbml0aW9uPFQ+KFxuICAgICAgZW50aXR5TmFtZVxuICAgICk7XG4gICAgY29uc3QgbWV0aG9kc0NsYXNzID0gbmV3IEVudGl0eUNvbGxlY3Rpb25SZWR1Y2VyTWV0aG9kcyhcbiAgICAgIGVudGl0eU5hbWUsXG4gICAgICBkZWZpbml0aW9uXG4gICAgKTtcblxuICAgIHJldHVybiBtZXRob2RzQ2xhc3MubWV0aG9kcztcbiAgfVxufVxuIl19